diff --git a/assets/school_logos/UNC-Charlotte (1).png b/assets/school_logos/UNC-Charlotte (1).png new file mode 100644 index 0000000..bd01193 Binary files /dev/null and b/assets/school_logos/UNC-Charlotte (1).png differ diff --git a/lib/models/game_cards.dart b/lib/models/game_cards.dart new file mode 100644 index 0000000..f36156d --- /dev/null +++ b/lib/models/game_cards.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; + +import '../screens/sport_schedule.dart'; +import 'dart:convert'; + +class GameCardFeed{ + + static final sportUrl = + 'https://charlotte49ers.com/services/adaptive_components.ashx?type=scoreboard&start=0&count=80'; + Future> getEvents(int sportID) async { + var url = '$sportUrl&sport_id=$sportID&name=&extra=%7B%7D'; + http.Response response = await http.get(url); + Iterable games = json.decode(response.body); + return games + .map((json) => sport_schedule.fromJson(json)) + .toList(); + //return games.map((e) => sport_schedule.fromJson(e)).toList(); + } + Future> getGames(int sportID) async { + Map> mapGrab = {}; + + List eventInfo = await getEvents(sportID); + + for (int i = 0; i < eventInfo.length; i++) { + var sportEvent = DateTime(eventInfo[i].date.year, eventInfo[i].date.month, + eventInfo[i].date.day); + var original = mapGrab[sportEvent]; + + if (original == null) { + //print("null"); + mapGrab[sportEvent] = [eventInfo[i]]; + } else { + //print(eventInfo[i].date); + mapGrab[sportEvent] = List.from(original) + ..addAll([eventInfo[i]]); + } + } + List list = []; + mapGrab.forEach((k, v) => list.add(ScheduleObject(k, v))); + return list; + } +} + +class HorizontalGameCards extends StatelessWidget { + final GameCardFeed gameCard; + final double numCards; + final int sportID; + + const HorizontalGameCards({ + Key key, + @required this.gameCard, + this.numCards = 8, + this.sportID, + }) : super(key: key); + + double heightIn(BuildContext context) { + return MediaQuery.of(context).size.height / numCards; + } + + @override + Widget build(BuildContext context) { + var card = gameCard.getGames(sportID); + var events = []; + return SizedBox( + height: heightIn(context), + child: FutureBuilder( + future: card, + // ignore: missing_return + builder: (ctx, snapshot) { + //print(snapshot); + if (!snapshot.hasData) { + return Center(child: CircularProgressIndicator()); + } else { + events = snapshot.data; + + return ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: events.length, + itemBuilder: (context, index) { + return GameCard( + gameCard: events[index].sportSched[0], + ); + }, + ); + } + }, + ), + ); + } + } + +class ScheduleObject { + DateTime d; + List sportSched; + ScheduleObject(this.d, this.sportSched); +} \ No newline at end of file diff --git a/lib/news/article.dart b/lib/news/article.dart index 033f85b..9019538 100644 --- a/lib/news/article.dart +++ b/lib/news/article.dart @@ -90,3 +90,59 @@ class ArticleCard extends StatelessWidget { ); } } + +class ArticleCardVert extends StatelessWidget { + const ArticleCardVert({ + Key key, + @required this.article, + this.numCards = 2.1, + }) : super(key: key); + + final Article article; + final double numCards; + + double heightIn(BuildContext context) { + return (MediaQuery.of(context).size.height * 7/8) / numCards; + } + + @override + Widget build(BuildContext context) { + var decoration = BoxDecoration( + image: DecorationImage( + image: NetworkImage( + article.thumbUrl, + ), + fit: BoxFit.cover, + ), + ); + + var body = Column( + verticalDirection: VerticalDirection.up, + children: [ + Container( + color: Colors.white, + child: ListTile( + title: Text( + article.mediumHeadline, + overflow: TextOverflow.ellipsis, + maxLines: 2, + ), + ), + ), + ], + ); + + + return SizedBox( + height: heightIn(context), + child: Card( + semanticContainer: true, + clipBehavior: Clip.antiAliasWithSaveLayer, + child: Container( + decoration: decoration, + child: body, + ), + ), + ); + } +} diff --git a/lib/news/feed.dart b/lib/news/feed.dart index 62aaea5..d4a27db 100644 --- a/lib/news/feed.dart +++ b/lib/news/feed.dart @@ -82,3 +82,43 @@ class HorizontalNewsFeed extends StatelessWidget { ); } } + + +class VerticalNewsFeed extends StatelessWidget { + final Feed newsFeed; + final String sportFilter; + + const VerticalNewsFeed({ + Key key, + @required this.newsFeed, + @required this.sportFilter, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + var page = newsFeed.getPage(1, size: 100).then((page) => page.where((article) => article.sport.toLowerCase().contains(sportFilter.toLowerCase())).toList()); + var size = MediaQuery.of(context).size; + return SizedBox( + height: size.height * (7/8), + child: FutureBuilder( + future: page, + builder: (ctx, snapshot) { + if (!snapshot.hasData) { + return Center(child: CircularProgressIndicator()); + } else { + List
articles = snapshot.data; + return ListView.builder( + //shrinkWrap: true, + scrollDirection: Axis.vertical, + itemCount: articles.length, + itemBuilder: (ctx, idx) { + return ArticleCardVert( + article: articles[idx], + ); + }, + ); + } + }, + )); + } +} diff --git a/lib/screens/sport.dart b/lib/screens/sport.dart index 25a15e3..cc28258 100644 --- a/lib/screens/sport.dart +++ b/lib/screens/sport.dart @@ -1,18 +1,20 @@ import 'package:flutter/material.dart'; import '../news/feed.dart'; +import '../models/game_cards.dart'; class Sport extends StatelessWidget { static final List colorList = [ - const Item('Football', Colors.green,[3]), - const Item("Basketball", Colors.red,[5,13]), - const Item("Soccer", Colors.pinkAccent,[9,17]), - const Item('Baseball', Colors.orange,[1]), - const Item('Softball', Colors.yellow,[12]), - const Item('Volleyball', Colors.blue,[20]), - const Item('Tennis', Colors.yellowAccent,[10,18]), + const Item('Football',[3]), + const Item("Basketball",[5,13]), + const Item("Soccer",[9,17]), + const Item('Baseball',[1]), + const Item('Softball',[12]), + const Item('Volleyball',[20]), + const Item('Tennis',[10,18]), ]; final feed = Feed(); // was var not final + final gameCard = GameCardFeed(); final String imageMale = 'images/male.png'; final String imageFemale = 'images/female.png'; @@ -43,9 +45,9 @@ class Sport extends StatelessWidget { return StatefulBuilder( builder: (context, StateSetter setState) => Scaffold( appBar: AppBar( - centerTitle: false, - title: buildDropdownButton(selectedSport, setState), - backgroundColor: _curSport.color, + centerTitle: false, + title: buildDropdownButton(selectedSport, setState), + backgroundColor: Colors.green, //--Gender Switch-- Need to make condition to determine gender actions: [ @@ -54,8 +56,8 @@ class Sport extends StatelessWidget { value: genderSport, onChanged: (value) { setState(() { - genderSport = value; - _genderSwitcherCheck(); + genderSport = value; + _genderSwitcherCheck(); }); }, inactiveThumbColor: Colors.lightBlue, @@ -67,8 +69,10 @@ class Sport extends StatelessWidget { ] ), body: ListView( + physics: const NeverScrollableScrollPhysics(), children: [ - HorizontalNewsFeed(newsFeed: feed, title: Text(_curSport.name), sportFilter: _curSport.name,), + HorizontalGameCards(gameCard: gameCard, sportID: sport_ID,), + VerticalNewsFeed(newsFeed: feed, sportFilter: _curSport.name), ], ), drawer: Drawer( @@ -128,7 +132,7 @@ class Sport extends StatelessWidget { setState(() { _curSport = value; _genderSwitcherCheck(); - print(sport_ID); + //print(sport_ID); }); }, items: colorList.map>((Item item) { @@ -152,14 +156,12 @@ class Sport extends StatelessWidget { genderSportSwitch = false; sport_ID = _curSport.sportID[0]; } - print(sport_ID); + //print(sport_ID); } } class Item { - const Item(this.name, this.color, this.sportID); - + const Item(this.name, this.sportID); final String name; - final Color color; final List sportID; } \ No newline at end of file diff --git a/lib/screens/sport_schedule.dart b/lib/screens/sport_schedule.dart index 5dcb470..71a93a5 100644 --- a/lib/screens/sport_schedule.dart +++ b/lib/screens/sport_schedule.dart @@ -62,3 +62,141 @@ class sport_schedule { ); } } + +class GameCard extends StatelessWidget { + const GameCard({ + Key key, + @required this.gameCard, + this.numCards = 2.25, + }) : super(key: key); + + final sport_schedule gameCard; + final double numCards; + + double widthIn(BuildContext context) { + return MediaQuery.of(context).size.width / numCards; + } + + Text _pastGameScore( + String homeAway, String winLoss, String uncc, String opponent) { + if (homeAway == "H" || homeAway == "T") { + return (Text('$uncc - $opponent')); + } else { + return (Text('$opponent - $uncc')); + } + } + + Image _homeAwayImageOrder(String h, String opposingTeam, bool l, BuildContext ctx) { + if ((h == "H") == l) { + return (Image.network( + 'https://fiusports.com/images/logos/UNC-Charlotte.png?width=80&height=80&mode=max', + )); + } else { + return (Image.network( + 'https://charlotte49ers.com' + opposingTeam, + )); + } + } + + Color winLoss(String wl){ + if (wl == "W") { + return Colors.green; + } else if (wl == "L") { + return Colors.red; + } else { + return Colors.grey; + } + } + + @override + Widget build(BuildContext ctx) { + var _months = { + 1: 'JAN', + 2: 'FEB', + 3: 'MAR', + 4: 'APR', + 5: 'MAY', + 6: 'JUN', + 7: 'JUL', + 8: 'AUG', + 9: 'SEP', + 10: 'OCT', + 11: 'NOV', + 12: 'DEC' + }; + var decoration = BoxDecoration( + border: Border.all( + color: winLoss(gameCard.status), //UNCC Green + width: 1.2, + ), + borderRadius: BorderRadius.circular(2), + ); + var logoWidth = 4.5; + var body = Column( + verticalDirection: VerticalDirection.up, + children: [ + Container( + color: Colors.white, + child: ListTile( + leading: SizedBox( + width: widthIn(ctx)/logoWidth, + child: _homeAwayImageOrder( + gameCard.location_indicator, + gameCard.image, + true, ctx)), + title: FittedBox( + fit: BoxFit.contain, + child: Wrap( + children: [ + if (gameCard.status == null) // no game yet + Text( + '${_months[gameCard.date.month]} ${gameCard.date.day}' + ) + else + _pastGameScore( + gameCard.location_indicator, + gameCard.status, + gameCard.team_score, + gameCard.opponent_score,), + ], + ) + ), + subtitle: FittedBox( + fit: BoxFit.contain, + child: Wrap( + children: [ + if (gameCard.status != null) // no game yet + Text( + '${_months[gameCard.date.month]} ${gameCard.date.day}', textAlign: TextAlign.center, + ) + else + Text('${gameCard.date.hour}:${gameCard.date.minute} PM'), + ], + ) + ), + trailing: SizedBox( + width: widthIn(ctx)/logoWidth, + child: _homeAwayImageOrder( + gameCard.location_indicator, + gameCard.image, + false, ctx)), + onTap: () => print('${gameCard.date} ${gameCard.status}'), + ), + ), + ], + ); + + + return SizedBox( + width: widthIn(ctx), + child: Card( + semanticContainer: true, + clipBehavior: Clip.antiAliasWithSaveLayer, + child: Container( + decoration: decoration, + child: body, + ), + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index b39c496..76f0d96 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,21 +7,21 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.0.13" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "1.5.2" + version: "1.6.0" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.0" + version: "2.4.1" bloc: dependency: transitive description: @@ -35,21 +35,21 @@ packages: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "2.0.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" + version: "1.1.3" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.11" + version: "1.14.12" convert: dependency: transitive description: @@ -63,7 +63,7 @@ packages: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "2.1.4" cupertino_icons: dependency: "direct main" description: @@ -113,7 +113,7 @@ packages: name: image url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.12" intl: dependency: transitive description: @@ -176,7 +176,7 @@ packages: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.1.3" rxdart: dependency: transitive description: @@ -230,7 +230,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.5.5" + version: "1.7.0" stack_trace: dependency: transitive description: @@ -279,7 +279,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.11" + version: "0.2.15" typed_data: dependency: transitive description: @@ -300,7 +300,7 @@ packages: name: xml url: "https://pub.dartlang.org" source: hosted - version: "3.5.0" + version: "3.6.1" sdks: dart: ">=2.6.0 <3.0.0" flutter: ">=1.12.13+hotfix.4 <2.0.0"