Merge pull request #20 from allemangD/SportPageCards

Sport page cards
This commit is contained in:
clopezr1
2020-05-01 15:51:09 -04:00
committed by GitHub
7 changed files with 363 additions and 30 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@@ -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<List<sport_schedule>> 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<sport_schedule>((json) => sport_schedule.fromJson(json))
.toList();
//return games.map((e) => sport_schedule.fromJson(e)).toList();
}
Future<List<ScheduleObject>> getGames(int sportID) async {
Map<DateTime, List<sport_schedule>> mapGrab = {};
List<sport_schedule> 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<ScheduleObject> 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<sport_schedule> sportSched;
ScheduleObject(this.d, this.sportSched);
}

View File

@@ -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: <Widget>[
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,
),
),
);
}
}

View File

@@ -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<Article> articles = snapshot.data;
return ListView.builder(
//shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: articles.length,
itemBuilder: (ctx, idx) {
return ArticleCardVert(
article: articles[idx],
);
},
);
}
},
));
}
}

View File

@@ -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<Item> colorList = <Item>[
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: <Widget>[
@@ -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: <Widget>[
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<DropdownMenuItem<Item>>((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<int> sportID;
}

View File

@@ -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: <Widget>[
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: <Widget>[
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: <Widget>[
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,
),
),
);
}
}

View File

@@ -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"