diff --git a/images/female.png b/images/female.png new file mode 100644 index 0000000..5ad63c1 Binary files /dev/null and b/images/female.png differ diff --git a/images/male.png b/images/male.png new file mode 100644 index 0000000..f39cd83 Binary files /dev/null and b/images/male.png differ diff --git a/lib/monthly_calendar.dart b/lib/monthly_calendar.dart new file mode 100644 index 0000000..8730ac6 --- /dev/null +++ b/lib/monthly_calendar.dart @@ -0,0 +1,384 @@ +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:table_calendar/table_calendar.dart'; + +import 'screens/sport_schedule.dart'; +import 'screens/sport.dart' as globals; +import 'dart:convert'; + +class Calendar extends StatefulWidget { + @override + _Calendar createState() => _Calendar(); +} + +//List _selectedEvents; //original that makes events work +List _selectedEvents; //Removing the allows it to still work. Proceed with caution +DateTime selectedDay; +Map> _events; + +class _Calendar extends State with TickerProviderStateMixin { + AnimationController _animationController; + CalendarController _calController; + + int sportID = globals.Sport.sport_ID; + static final sportUrl = 'https://charlotte49ers.com/services/adaptive_components.ashx?type=scoreboard&start=0&count=80'; + + Future> getEvents() 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() async { + Map> mapGrab = {}; + + List eventInfo = await getEvents(); + + 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]]); + } + } + return mapGrab; + } + + @override + void initState() { + final _selectedDay = DateTime.now(); + + //_selectedEvents = _events[_selectedDay] ?? []; + _selectedEvents = []; + _calController = CalendarController(); + + _animationController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 400), + ); + + _animationController.forward(); + + WidgetsBinding.instance.addPostFrameCallback((_) { + getGames().then((val) => setState(() { + _events = val; + })); + }); + + super.initState(); + } + + @override + void dispose() { + _animationController.dispose(); + _calController.dispose(); + super.dispose(); + } + + //void _DaySelected(DateTime day, List events) { //original that makes events work + void _DaySelected(DateTime day, List events) { //Removing the allows it to still work. Proceed with caution + setState(() { + _selectedEvents = events; + selectedDay = DateTime(day.year, day.month, day.day); + }); + } + + /*void _onVisibleDaysChanged(DateTime first, DateTime last, CalendarFormat format) { + print('CALLBACK: _onVisibleDaysChanged'); + } + void _onCalendarCreated(DateTime first, DateTime last, CalendarFormat format) { + print('CALLBACK: _onCalendarCreated'); + }*/ + + //----- Builds calendar and event Lister ----- + @override + Widget build(BuildContext context) { + return Center( + child: Column( + children: [ + _buildCalendar(), + const SizedBox(height: 8.0), + Expanded(child: _eventLister()), + ], + ), + ); + } + + //----- Builds calendar ----- + @override + Widget _buildCalendar() { + return TableCalendar( + calendarController: _calController, + initialCalendarFormat: CalendarFormat.month, + startingDayOfWeek: StartingDayOfWeek.sunday, + //availableGestures: AvailableGestures.all, + events: _events, + + availableCalendarFormats: const { + CalendarFormat.month: '', + }, + + calendarStyle: CalendarStyle( + outsideWeekendStyle: TextStyle( + color: Colors.grey, + ), + + weekendStyle: TextStyle( + color: Colors.black, + ), + ), + + daysOfWeekStyle: DaysOfWeekStyle( + weekendStyle: TextStyle( + color: Colors.black, + ), + weekdayStyle: TextStyle( + color: Colors.black, + ), + ), + + headerStyle: HeaderStyle( + centerHeaderTitle: true, + formatButtonVisible: false, //hides button that formats between 1 week, 2 week, month + //formatButtonShowsNext: false, + ), + + builders: CalendarBuilders( + selectedDayBuilder: (context, date, _) { + return Container( + margin: const EdgeInsets.all(4.0), + alignment: Alignment.center, + + decoration: BoxDecoration( + border: Border.all( + color: Color.fromRGBO(0, 112, 60, 1), //UNCC Green + ), + color: Color.fromRGBO(179, 163, 105, 1), //UNCC Gold + borderRadius: BorderRadius.circular(10.0) + ), + + child: Text( + '${date.day}', + style: TextStyle(color: Colors.white), + ), + ); + }, + + todayDayBuilder: (context, date, _) { + + return Container( + margin: const EdgeInsets.all(4.0), + alignment: Alignment.center, + + decoration: BoxDecoration( + border: Border.all( + color: Color.fromRGBO(0, 112, 60, 1), //UNCC Green + ), + borderRadius: BorderRadius.circular(10.0) + ), + + child: Text( + '${date.day}', + style: TextStyle( + color: Colors.black, + ), + ), + ); + }, + + markersBuilder: (context, date, events, holidays) { + final miniBox = []; + + if (events.isNotEmpty) { + miniBox.add( + Positioned( + right: 1, + bottom: 1, + child: _buildEventsMarker(date, events), + ), + ); + } + + return miniBox; + }, + ), + + onDaySelected: (date, events) { + _DaySelected(date, events); + _animationController.forward(from: 0.0); + }, + + //onVisibleDaysChanged: _onVisibleDaysChanged, + //onCalendarCreated: _onCalendarCreated, + + ); + } + + //----- Creates event box display (mini box) ----- + Widget _buildEventsMarker(DateTime date, List events) { + return AnimatedContainer( + duration: const Duration(milliseconds: 300), + + decoration: BoxDecoration( + shape: BoxShape.rectangle, + + /*border: _calController.isSelected(date) //if selected date + ? Border.all(color: Colors.black, width: 1.5,) + : _calController.isToday(date) //if today's date + ? Border.all(color: Colors.black, width: 1.5,) + : Border.all(color: Colors.black, width: 0,),*/ + + //color: Color.fromRGBO(0, 112, 60, 1), //UNCC Green + //color: Colors.grey, + + //if selected date && home game / else away game + color: _calController.isSelected(date) + ? Colors.blue[400] + : Color.fromRGBO(0, 112, 60, 1), //UNCC Green + //: Colors.grey, + ), + + width: 16.0, + height: 16.0, + + child: Center( + child: Text( + '${events.length}', + style: TextStyle().copyWith( + color: Colors.white, + fontSize: 12.0, + ), + ), + ), + ); + } + + //----- Creates event display ----- + Widget _eventLister() { + return ListView( + children: _selectedEvents.map((event) => Container( + decoration: BoxDecoration( + border: Border.all( + color: Color.fromRGBO(0, 112, 60, 1), //UNCC Green + width: 0.8, + ), + + borderRadius: BorderRadius.circular(12.0), + ), + + height: 70.0, + margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), + + child: ListTile( + leading: Icon(Icons.image), //opponent logo - Not done (Placeholder) + title: Wrap( + + + children: [ + if (event.location_indicator.toString() == "H") + Text( + 'vs. ', + style: TextStyle( //home game + fontSize: 11.6, + ), + ) + else + Text( + 'at ', + style: TextStyle( //away game + fontSize: 11.6, + ), + ), + + Text( + event.opponentTitle.toString(), + style: TextStyle( + fontSize: 11.6, + ), + ) //opponent name + ], + ), + + //Type of sport - Location + subtitle: Text( + event.sportTitle.toString() + " - " + event.location.toString(), + style: TextStyle( + fontSize: 10.3, + ), + ), + + trailing: Wrap( + //mainAxisSize: MainAxisSize.min, + + children: [ + //---Score--- + //Game hasn't occured + if (event.status.toString() == "null") + Text("TBD"), + + //---Scores--- + if (event.status.toString() == "W" || event.status.toString() == "L" || event.status.toString() == "T") //Finished games + Text(event.team_score.toString() + " - " + event.opponent_score.toString() + " ") + + else if (event.status.toString() == "N" && event.team_score.toString() != "null" && event.opponent_score.toString() != "null") //Games that don't count + Text(event.team_score.toString() + " - " + event.opponent_score.toString() + " "), + + //---Game Status--- + if (event.status.toString() == "W") //Win + Text( + (" " + event.status.toString() + " "), + style: TextStyle( + color: Colors.white, + backgroundColor: Color.fromRGBO(0, 112, 60, 1), + ) + ), + + if (event.status.toString() == "L" || event.status.toString() == "T") //Lose-Tie + Text( + (" " + event.status.toString() + " "), + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.black, + backgroundColor: Colors.grey, + ) + ), + + if (event.status.toString() == "N" && event.postscore.toString() != "Canceled") //N + Text( + (" " + event.status.toString() + " "), + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.black, + backgroundColor: Colors.grey, + ) + ) + else if (event.team_score.toString() == "null" && event.opponent_score.toString() == "null" + && event.status.toString() == "N") //Game was canceled + Text( + "Canceled", + style: TextStyle( + color: Colors.red, + ) + ), + + ], + ), + onTap: () => print('$event tapped!'), //When event display is clicked + ), + )).toList(), + ); + } +} \ No newline at end of file diff --git a/lib/news/article.dart b/lib/news/article.dart index 4acc3a5..033f85b 100644 --- a/lib/news/article.dart +++ b/lib/news/article.dart @@ -76,6 +76,7 @@ class ArticleCard extends StatelessWidget { ], ); + return SizedBox( width: widthIn(context), child: Card( diff --git a/lib/news/feed.dart b/lib/news/feed.dart index f9da8d6..c5662ce 100644 --- a/lib/news/feed.dart +++ b/lib/news/feed.dart @@ -43,7 +43,14 @@ class HorizontalNewsFeed extends StatelessWidget { title: title, trailing: IconButton( icon: Icon(Icons.navigate_next), + onPressed: () => Navigator.of(context).pushNamed('/Sport'), + + /*onPressed: () { //changed + Navigator.of(context).pushNamed('/Sport'); + print(Navigator.of(context).pushNamed('/Sport')); + }*/ + ), ), Expanded( diff --git a/lib/screens/schedule.dart b/lib/screens/schedule.dart index c827f1f..0a3f716 100644 --- a/lib/screens/schedule.dart +++ b/lib/screens/schedule.dart @@ -1,6 +1,10 @@ import 'package:flutter/material.dart'; +import '../monthly_calendar.dart'; class Schedule extends StatelessWidget{ + + final calendar = Calendar(); + @override Widget build(BuildContext context) { return StatefulBuilder( @@ -10,7 +14,9 @@ class Schedule extends StatelessWidget{ title: Text("49ers"), backgroundColor: Colors.green, ), - body: Text("Schedule Goes Here"), + body: Container ( + child: calendar, + ), drawer: Drawer( child: ListView( children: [ diff --git a/lib/screens/sport.dart b/lib/screens/sport.dart index ac34014..b141d4d 100644 --- a/lib/screens/sport.dart +++ b/lib/screens/sport.dart @@ -12,9 +12,15 @@ class Sport extends StatelessWidget { Item _curSport = colorList[0]; - final feed = Feed(); // was var not final + bool genderSportSwitch = false; //determines if sport needs the gender switch + final String imageMale = 'images/male.png'; + final String imageFemale = 'images/female.png'; + static bool genderSport = false; //determines which gender switch is set M - false / F - True + + static int sport_ID; + @override Widget build(BuildContext context) { Item selectedSport; @@ -25,6 +31,32 @@ class Sport extends StatelessWidget { centerTitle: false, title: buildDropdownButton(selectedSport, setState), backgroundColor: _curSport.color, + + //--Gender Switch-- Need to make condition to determine gender + actions: [ + if (genderSportSwitch == true) + Switch( + value: genderSport, + onChanged: (value) { + setState(() { + if (value == false) { + genderSport = false; + } + else { + genderSport = true; + } + + print("value: " + value.toString()); + print("gender: " + genderSport.toString()); + }); + }, + inactiveThumbColor: Colors.lightBlue, + inactiveThumbImage: Image.asset(imageMale).image, + + activeColor: Colors.pinkAccent, + activeThumbImage: Image.asset(imageFemale).image, + ), + ] ), body: ListView( children: [ @@ -91,6 +123,45 @@ class Sport extends StatelessWidget { onChanged: (Item value) { setState(() { _curSport = value; + + print("genderSport: " + genderSport.toString()); + + //Will set the sport id / Display gender switch + switch (_curSport.name) { //prints are temp + case 'FootBall': + genderSportSwitch = false; + sport_ID = 3; + break; + + case 'BasketBall': + genderSportSwitch = true; + + if (genderSport == false) { + sport_ID = 5; //Male + } + else { + sport_ID = 13; //Female + } + break; + + case 'Soccer': + genderSportSwitch = true; + + if (genderSport == false) { + sport_ID = 9; //Male + } + else { + sport_ID = 17; //Female + } + break; + + case 'Baseball': + genderSportSwitch = false; + + sport_ID = 1; + break; + } + print(sport_ID); }); }, items: colorList.map>((Item item) { diff --git a/lib/screens/sport_schedule.dart b/lib/screens/sport_schedule.dart new file mode 100644 index 0000000..e13775a --- /dev/null +++ b/lib/screens/sport_schedule.dart @@ -0,0 +1,64 @@ +import 'package:flutter/material.dart'; + +class sport_schedule { + final int id; //id for each game + final DateTime date; //date: 2020-09-05T00:00:00 + final String location_indicator; //location_indicator: H-Home / A-Away + final String location; //location: Knoxville, Tenn., Charlotte, NC + + // -- sport json -- + final int idSport; //id: Each sport different number + final String sportTitle; //title: Football, Men's Soccer + final String gender; //gender: M - F + + // -- opponent json -- + final String opponentTitle; //title: Tennessee, Norfolk State + //final image - image: (do later) + + // -- result json -- + final String status; //status: W - T - L + final String team_score; //team_score: + final String opponent_score; //opponent_score: + final String postscore; + + sport_schedule( + this.id, { + this.date, + this.location_indicator, + this.location, + + this.idSport, + this.sportTitle, + this.gender, + + this.opponentTitle, + //this.image, + + this.status, + this.team_score, + this.opponent_score, + this.postscore, + }); + + factory sport_schedule.fromJson(Map json) { + return sport_schedule( + json['id'], + date: DateTime.parse(json['date']), + location_indicator: json['location_indicator'], + location: json['location'], + + idSport: json['sport']['id'], + sportTitle: json['sport']['title'], + gender: json['sport']['gender'], + + opponentTitle: json['opponent']['title'], + //image: json['opponent']['image'], + + status: json['result']['status'], + + team_score: json['result']['team_score'], + opponent_score: json['result']['opponent_score'], + postscore: json['result']['postscore'], + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 3e6efa1..e01b47c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -114,6 +114,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.12" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.1" matcher: dependency: transitive description: @@ -148,7 +155,7 @@ packages: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.8.0+1" + version: "1.9.0" petitparser: dependency: transitive description: @@ -205,6 +212,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.2+4" + simple_gesture_detector: + dependency: transitive + description: + name: simple_gesture_detector + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" sky_engine: dependency: transitive description: flutter @@ -238,6 +252,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.5" + table_calendar: + dependency: "direct main" + description: + name: table_calendar + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.3" term_glyph: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 43653d7..cb97cbf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,7 +14,8 @@ description: A sports app for UNC-Charlotte 49ers version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + #sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.6.0 <3.0.0" dependencies: flutter: @@ -27,12 +28,12 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 + table_calendar: dev_dependencies: flutter_test: sdk: flutter - # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec @@ -48,6 +49,9 @@ flutter: # assets: # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg + assets: + - images/male.png + - images/female.png # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware.