// Copyright 2019-present the Flutter authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import 'package:flutter/material.dart'; import 'package:flutter_gallery/demo/rally/charts/pie_chart.dart'; import 'package:flutter_gallery/demo/rally/charts/line_chart.dart'; import 'package:flutter_gallery/demo/rally/charts/vertical_fraction_bar.dart'; import 'package:flutter_gallery/demo/rally/colors.dart'; import 'package:flutter_gallery/demo/rally/data.dart'; import 'package:flutter_gallery/demo/rally/formatters.dart'; class FinancialEntityView extends StatelessWidget { const FinancialEntityView({ this.heroLabel, this.heroAmount, this.wholeAmount, this.segments, this.financialEntityCards, }) : assert(segments.length == financialEntityCards.length); /// The amounts to assign each item. final List<RallyPieChartSegment> segments; final String heroLabel; final double heroAmount; final double wholeAmount; final List<FinancialEntityCategoryView> financialEntityCards; @override Widget build(BuildContext context) { return Column( children: <Widget>[ RallyPieChart( heroLabel: heroLabel, heroAmount: heroAmount, wholeAmount: wholeAmount, segments: segments, ), SizedBox( height: 1, child: Container( color: const Color(0xA026282F), ), ), ListView(shrinkWrap: true, children: financialEntityCards), ], ); } } /// A reusable widget to show balance information of a single entity as a card. class FinancialEntityCategoryView extends StatelessWidget { const FinancialEntityCategoryView({ @required this.indicatorColor, @required this.indicatorFraction, @required this.title, @required this.subtitle, @required this.amount, @required this.suffix, }); final Color indicatorColor; final double indicatorFraction; final String title; final String subtitle; final double amount; final Widget suffix; @override Widget build(BuildContext context) { return FlatButton( onPressed: () { Navigator.push( context, MaterialPageRoute<FinancialEntityCategoryDetailsPage>( builder: (BuildContext context) => FinancialEntityCategoryDetailsPage(), ), ); }, child: SizedBox( height: 68, child: Column( children: <Widget>[ Expanded( child: Row( children: <Widget>[ Padding( padding: const EdgeInsets.only(left: 12, right: 12), child: VerticalFractionBar( color: indicatorColor, fraction: indicatorFraction, ), ), Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( title, style: Theme.of(context).textTheme.body1.copyWith(fontSize: 16), ), Text( subtitle, style: Theme.of(context).textTheme.body1.copyWith(color: RallyColors.gray60), ), ], ), const Spacer(), Text( '\$ ' + usdFormat.format(amount), style: Theme.of(context).textTheme.body2.copyWith(fontSize: 20, color: RallyColors.gray), ), SizedBox(width: 32, child: suffix), ], ), ), const Divider( height: 1, indent: 16, endIndent: 16, color: Color(0xAA282828), ), ], ), ), ); } } /// Data model for [FinancialEntityCategoryView]. class FinancialEntityCategoryModel { const FinancialEntityCategoryModel( this.indicatorColor, this.indicatorFraction, this.title, this.subtitle, this.usdAmount, this.suffix, ); final Color indicatorColor; final double indicatorFraction; final String title; final String subtitle; final double usdAmount; final Widget suffix; } FinancialEntityCategoryView buildFinancialEntityFromAccountData( AccountData model, int accountDataIndex, ) { return FinancialEntityCategoryView( suffix: const Icon(Icons.chevron_right, color: Colors.grey), title: model.name, subtitle: '• • • • • • ${model.accountNumber.substring(6)}', indicatorColor: RallyColors.accountColor(accountDataIndex), indicatorFraction: 1, amount: model.primaryAmount, ); } FinancialEntityCategoryView buildFinancialEntityFromBillData( BillData model, int billDataInex, ) { return FinancialEntityCategoryView( suffix: const Icon(Icons.chevron_right, color: Colors.grey), title: model.name, subtitle: model.dueDate, indicatorColor: RallyColors.billColor(billDataInex), indicatorFraction: 1, amount: model.primaryAmount, ); } FinancialEntityCategoryView buildFinancialEntityFromBudgetData( BudgetData item, int budgetDataIndex, BuildContext context, ) { final String amountUsed = usdWithSignFormat.format(item.amountUsed); final String primaryAmount = usdWithSignFormat.format(item.primaryAmount); return FinancialEntityCategoryView( suffix: Text( ' LEFT', style: Theme.of(context).textTheme.body1.copyWith(color: RallyColors.gray60, fontSize: 10), ), title: item.name, subtitle: amountUsed + ' / ' + primaryAmount, indicatorColor: RallyColors.budgetColor(budgetDataIndex), indicatorFraction: item.amountUsed / item.primaryAmount, amount: item.primaryAmount - item.amountUsed, ); } List<FinancialEntityCategoryView> buildAccountDataListViews( List<AccountData> items) { return List<FinancialEntityCategoryView>.generate( items.length, (int i) => buildFinancialEntityFromAccountData(items[i], i), ); } List<FinancialEntityCategoryView> buildBillDataListViews(List<BillData> items) { return List<FinancialEntityCategoryView>.generate( items.length, (int i) => buildFinancialEntityFromBillData(items[i], i), ); } List<FinancialEntityCategoryView> buildBudgetDataListViews( List<BudgetData> items, BuildContext context) { return <FinancialEntityCategoryView>[ for (int i = 0; i < items.length; i++) buildFinancialEntityFromBudgetData(items[i], i, context) ]; } class FinancialEntityCategoryDetailsPage extends StatelessWidget { final List<DetailedEventData> items = DummyDataService.getDetailedEventItems(); @override Widget build(BuildContext context) { final List<_DetailedEventCard> cards = items.map((DetailedEventData detailedEventData) { return _DetailedEventCard( title: detailedEventData.title, subtitle: dateFormat.format(detailedEventData.date), amount: detailedEventData.amount, ); }).toList(); return Scaffold( appBar: AppBar( elevation: 0, centerTitle: true, title: Text( 'Checking', style: Theme.of(context).textTheme.body1.copyWith(fontSize: 18), ), ), body: Column( children: <Widget>[ SizedBox( height: 200, width: double.infinity, child: RallyLineChart(events: items), ), Flexible( child: ListView(shrinkWrap: true, children: cards), ), ], ), ); } } class _DetailedEventCard extends StatelessWidget { const _DetailedEventCard({ @required this.title, @required this.subtitle, @required this.amount, }); final String title; final String subtitle; final double amount; @override Widget build(BuildContext context) { final TextTheme textTheme = Theme.of(context).textTheme; return FlatButton( onPressed: () {}, child: SizedBox( height: 68, child: Column( children: <Widget>[ SizedBox( height: 67, child: Row( children: <Widget>[ Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( title, style: textTheme.body1.copyWith(fontSize: 16), ), Text( subtitle, style: textTheme.body1.copyWith(color: RallyColors.gray60), ) ], ), const Spacer(), Text( '\$${usdFormat.format(amount)}', style: textTheme.body2.copyWith(fontSize: 20, color: RallyColors.gray), ), ], ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: SizedBox( height: 1, child: Container( color: const Color(0xAA282828), ), ), ), ], ), ), ); } }