Skip to content

Commit

Permalink
Merge pull request #10 from robert-northmind/feature/update-ux-on-det…
Browse files Browse the repository at this point in the history
…ails-page

Feature/update ux on details page
  • Loading branch information
robert-northmind authored Apr 13, 2020
2 parents 36eb4da + 07a3142 commit b0b1db2
Show file tree
Hide file tree
Showing 7 changed files with 369 additions and 134 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## 1.1.0

- Added possability to change type of graph data in details view
- Entry point to details page now reachable directly from all countries list
- Added all reposrt history to details page, not only last 7 days

Expand Down
74 changes: 74 additions & 0 deletions lib/blocs/graph_history/graph_history_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import 'package:equatable/equatable.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';

enum GraphHistoryTimeType { lastSevenDays, allTime }

class GraphHistoryEvent {
final GraphHistoryTimeType graphHistoryTimeType;
GraphHistoryEvent({this.graphHistoryTimeType});
}

class GraphHistoryState extends Equatable {
final GraphHistoryTimeType graphHistoryTimeType;
GraphHistoryState({this.graphHistoryTimeType});

Map<String, dynamic> toJson() {
int enumValue = 0;
switch (graphHistoryTimeType) {
case GraphHistoryTimeType.allTime:
enumValue = 0;
break;
case GraphHistoryTimeType.lastSevenDays:
enumValue = 1;
break;
}
return {'GraphHistoryTimeType': enumValue};
}

factory GraphHistoryState.fromJson({Map<String, dynamic> json}) {
final enumValue = json['GraphHistoryTimeType'] as int;
GraphHistoryTimeType graphHistoryTimeType;
if (enumValue == 0) {
graphHistoryTimeType = GraphHistoryTimeType.allTime;
} else {
graphHistoryTimeType = GraphHistoryTimeType.lastSevenDays;
}
return GraphHistoryState(graphHistoryTimeType: graphHistoryTimeType);
}

@override
List<Object> get props => [graphHistoryTimeType];
}

class GraphHistoryBloc
extends HydratedBloc<GraphHistoryEvent, GraphHistoryState> {
@override
GraphHistoryState get initialState {
return super.initialState ??
GraphHistoryState(graphHistoryTimeType: GraphHistoryTimeType.allTime);
}

@override
GraphHistoryState fromJson(Map<String, dynamic> source) {
try {
return GraphHistoryState.fromJson(json: source);
} catch (_) {
return GraphHistoryState(
graphHistoryTimeType: GraphHistoryTimeType.allTime);
}
}

@override
Stream<GraphHistoryState> mapEventToState(GraphHistoryEvent event) async* {
yield GraphHistoryState(graphHistoryTimeType: event.graphHistoryTimeType);
}

@override
Map<String, dynamic> toJson(GraphHistoryState state) {
try {
return state.toJson();
} catch (_) {
return {};
}
}
}
193 changes: 139 additions & 54 deletions lib/widgets/details_page/details_page_route.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import 'package:corona_stats/blocs/graph_history/graph_history_bloc.dart';
import 'package:corona_stats/models/covid19_country_report.dart';
import 'package:corona_stats/main.dart';
import 'package:corona_stats/widgets/details_page/weekly_day_to_day_summary_widget.dart';
import 'package:corona_stats/widgets/details_page/summary_list_tile.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class DetailsPageRoute extends StatelessWidget {
final Covid19CountryReport countryReport;
Expand All @@ -11,63 +13,146 @@ class DetailsPageRoute extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: AppTitleWidget(
title: countryReport.country,
return MultiBlocProvider(
providers: [
BlocProvider<GraphHistoryBloc>(
create: ((BuildContext context) {
return GraphHistoryBloc();
}),
),
],
child: Scaffold(
appBar: AppBar(
title: AppTitleWidget(
title: countryReport.country,
),
),
body: Container(
child: BlocBuilder<GraphHistoryBloc, GraphHistoryState>(
builder: (context, state) {
final isAllTime =
state.graphHistoryTimeType == GraphHistoryTimeType.allTime;
final reports = isAllTime
? countryReport.allReports
: countryReport.lastWeekReports.reversed.toList();
return ListView(
padding: EdgeInsets.fromLTRB(5, 10, 5, 0),
children: <Widget>[
_GraphTimeframeSelectionWidget(
graphHistoryTimeType: state.graphHistoryTimeType,
),
SummaryListTileWidget(
title: 'Total cases',
values: reports
.map(
(item) => item.confirmed,
)
.toList(),
),
SummaryListTileWidget(
title: 'Deaths',
values: reports
.map(
(item) => item.deaths,
)
.toList(),
),
SummaryListTileWidget(
title: 'Recovered',
values: reports
.map(
(item) => item.recovered,
)
.toList(),
),
SummaryListTileWidget(
title: 'Active cases',
values: reports
.map(
(item) => item.confirmed - item.recovered,
)
.toList(),
),
SummaryListTileWidget(
title: "Death rate",
isPercent: true,
values: reports.map((item) {
if (item.confirmed <= 0) {
return 0;
} else {
return item.deaths / item.confirmed.toDouble() * 100;
}
}).toList(),
),
SizedBox(height: 20),
WeeklyDayToDaySummaryWidget(
key: Key('DayToDayListWidget'),
countryReport: countryReport,
),
SizedBox(height: 40),
],
);
},
),
),
),
body: Container(
child: ListView(
children: <Widget>[
SummaryListTileWidget(
title: 'Total cases',
values: countryReport.allReports
.map(
(item) => item.confirmed,
)
.toList(),
),
SummaryListTileWidget(
title: 'Deaths',
values: countryReport.allReports
.map(
(item) => item.deaths,
)
.toList(),
),
SummaryListTileWidget(
title: 'Recovered',
values: countryReport.allReports
.map(
(item) => item.recovered,
)
.toList(),
),
SummaryListTileWidget(
title: 'Active cases',
values: countryReport.allReports
.map(
(item) => item.confirmed - item.recovered,
)
.toList(),
),
SummaryListTileWidget(
title: "Death rate in %",
values: countryReport.allReports.map((item) {
if (item.confirmed <= 0) {
return 0;
} else {
return item.deaths / item.confirmed.toDouble() * 100;
}
}).toList(),
);
}
}

class _GraphTimeframeSelectionWidget extends StatelessWidget {
final GraphHistoryTimeType graphHistoryTimeType;

const _GraphTimeframeSelectionWidget({Key key, this.graphHistoryTimeType})
: super(key: key);

String _getStringValueForHistoryTimeType(GraphHistoryTimeType type) {
switch (type) {
case GraphHistoryTimeType.allTime:
return 'all time';
case GraphHistoryTimeType.lastSevenDays:
return 'the last 7 days';
}
return '';
}

@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: <Widget>[
Text('Show graph data from: '),
DropdownButton<GraphHistoryTimeType>(
value: graphHistoryTimeType,
icon: Icon(Icons.show_chart),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.red[600]),
underline: Container(
height: 2,
color: Colors.red[600],
),
WeeklyDayToDaySummaryWidget(
key: Key('DayToDayListWidget'),
countryReport: countryReport,
)
],
),
onChanged: (GraphHistoryTimeType newValue) {
print("changed to new Value: $newValue");
BlocProvider.of<GraphHistoryBloc>(context)
.add(GraphHistoryEvent(graphHistoryTimeType: newValue));
// setState(() {
// dropdownValue = newValue;
// });
},
items: <GraphHistoryTimeType>[
GraphHistoryTimeType.allTime,
GraphHistoryTimeType.lastSevenDays
].map<DropdownMenuItem<GraphHistoryTimeType>>(
(GraphHistoryTimeType value) {
return DropdownMenuItem<GraphHistoryTimeType>(
value: value,
child: Text(' ${_getStringValueForHistoryTimeType(value)} '),
);
}).toList(),
),
],
),
);
}
Expand Down
31 changes: 19 additions & 12 deletions lib/widgets/details_page/summary_list_tile.dart
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import 'package:corona_stats/utils/theme.dart';
import 'package:fcharts/fcharts.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class SummaryListTileWidget extends StatelessWidget {
final String title;
final List<num> values;
final bool isPercent;

const SummaryListTileWidget({
Key key,
this.title,
this.values,
}) : super(key: key);
const SummaryListTileWidget(
{Key key, this.title, this.values, this.isPercent = false})
: super(key: key);

@override
Widget build(BuildContext context) {
final numberFormatter = NumberFormat();
return Card(
color: Covid19Theme.appBackgroundColor,
elevation: 4.0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: IntrinsicHeight(
Expand All @@ -28,16 +31,16 @@ class SummaryListTileWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
numberFormatter.format(
values[values.length - 1],
),
style: TextStyle(
fontSize: 25,
),
(isPercent
? '${values[values.length - 1].toStringAsFixed(1)} %'
: numberFormatter.format(
values[values.length - 1],
)),
style: TextStyle(fontSize: 25, color: Colors.white),
),
Text(
title,
style: TextStyle(fontSize: 16, color: Colors.black38),
style: TextStyle(fontSize: 16, color: Colors.white),
)
]),
),
Expand All @@ -48,6 +51,10 @@ class SummaryListTileWidget extends StatelessWidget {
lines: [
Sparkline(
data: values.map((data) => data.toDouble()).toList(),
stroke: PaintOptions.stroke(
color: Colors.red[500],
strokeWidth: 2.0,
),
)
],
)),
Expand Down
Loading

0 comments on commit b0b1db2

Please sign in to comment.