[Gallery] Update desktop Rally for pages that did not have designs before (#314)

* Update desktop Rally for pages that did not have designs before
pull/320/head
Per Classon 6 years ago committed by GitHub
parent c1acfe799d
commit d04440c11f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

File diff suppressed because it is too large Load Diff

@ -171,6 +171,18 @@
"@rallyAccountDetailDataAccountOwner": { "@rallyAccountDetailDataAccountOwner": {
"description": "Title for an account detail. Below the name of the account owner will be displayed." "description": "Title for an account detail. Below the name of the account owner will be displayed."
}, },
"rallyBillDetailTotalAmount": "Total Amount",
"@rallyBillDetailTotalAmount": {
"description": "Title for column where it displays the total dollar amount that the user has in bills."
},
"rallyBillDetailAmountPaid": "Amount Paid",
"@rallyBillDetailAmountPaid": {
"description": "Title for column where it displays the amount that the user has paid."
},
"rallyBillDetailAmountDue": "Amount Due",
"@rallyBillDetailAmountDue": {
"description": "Title for column where it displays the amount that the user has due."
},
"rallyBudgetCategoryCoffeeShops": "Coffee Shops", "rallyBudgetCategoryCoffeeShops": "Coffee Shops",
"@rallyBudgetCategoryCoffeeShops": { "@rallyBudgetCategoryCoffeeShops": {
"description": "Category for budget, to sort expenses / bills in." "description": "Category for budget, to sort expenses / bills in."
@ -187,6 +199,18 @@
"@rallyBudgetCategoryClothing": { "@rallyBudgetCategoryClothing": {
"description": "Category for budget, to sort expenses / bills in." "description": "Category for budget, to sort expenses / bills in."
}, },
"rallyBudgetDetailTotalCap": "Total Cap",
"@rallyBudgetDetailTotalCap": {
"description": "Title for column where it displays the total dollar cap that the user has for its budget."
},
"rallyBudgetDetailAmountUsed": "Amount Used",
"@rallyBudgetDetailAmountUsed": {
"description": "Title for column where it displays the dollar amount that the user has used in its budget."
},
"rallyBudgetDetailAmountLeft": "Amount Left",
"@rallyBudgetDetailAmountLeft": {
"description": "Title for column where it displays the dollar amount that the user has left in its budget."
},
"rallySettingsManageAccounts": "Manage Accounts", "rallySettingsManageAccounts": "Manage Accounts",
"@rallySettingsManageAccounts": { "@rallySettingsManageAccounts": {
"description": "Link to go to the page 'Manage Accounts." "description": "Link to go to the page 'Manage Accounts."

@ -161,6 +161,18 @@
name="rallyAccountDetailDataAccountOwner" name="rallyAccountDetailDataAccountOwner"
description="Title for an account detail. Below the name of the account owner will be displayed." description="Title for an account detail. Below the name of the account owner will be displayed."
>Account Owner</string> >Account Owner</string>
<string
name="rallyBillDetailTotalAmount"
description="Title for column where it displays the total dollar amount that the user has in bills."
>Total Amount</string>
<string
name="rallyBillDetailAmountPaid"
description="Title for column where it displays the amount that the user has paid."
>Amount Paid</string>
<string
name="rallyBillDetailAmountDue"
description="Title for column where it displays the amount that the user has due."
>Amount Due</string>
<string <string
name="rallyBudgetCategoryCoffeeShops" name="rallyBudgetCategoryCoffeeShops"
description="Category for budget, to sort expenses / bills in." description="Category for budget, to sort expenses / bills in."
@ -177,6 +189,18 @@
name="rallyBudgetCategoryClothing" name="rallyBudgetCategoryClothing"
description="Category for budget, to sort expenses / bills in." description="Category for budget, to sort expenses / bills in."
>Clothing</string> >Clothing</string>
<string
name="rallyBudgetDetailTotalCap"
description="Title for column where it displays the total dollar cap that the user has for its budget."
>Total Cap</string>
<string
name="rallyBudgetDetailAmountUsed"
description="Title for column where it displays the dollar amount that the user has used in its budget."
>Amount Used</string>
<string
name="rallyBudgetDetailAmountLeft"
description="Title for column where it displays the dollar amount that the user has left in its budget."
>Amount Left</string>
<string <string
name="rallySettingsManageAccounts" name="rallySettingsManageAccounts"
description="Link to go to the page &apos;Manage Accounts." description="Link to go to the page &apos;Manage Accounts."

@ -995,6 +995,12 @@ class MessageLookup extends MessageLookupByLibrary {
"rallyAlertsMessageSpentOnRestaurants": m24, "rallyAlertsMessageSpentOnRestaurants": m24,
"rallyAlertsMessageUnassignedTransactions": m25, "rallyAlertsMessageUnassignedTransactions": m25,
"rallyBillAmount": m26, "rallyBillAmount": m26,
"rallyBillDetailAmountDue":
MessageLookupByLibrary.simpleMessage("Amount Due"),
"rallyBillDetailAmountPaid":
MessageLookupByLibrary.simpleMessage("Amount Paid"),
"rallyBillDetailTotalAmount":
MessageLookupByLibrary.simpleMessage("Total Amount"),
"rallyBills": MessageLookupByLibrary.simpleMessage("Bills"), "rallyBills": MessageLookupByLibrary.simpleMessage("Bills"),
"rallyBillsDue": MessageLookupByLibrary.simpleMessage("Due"), "rallyBillsDue": MessageLookupByLibrary.simpleMessage("Due"),
"rallyBudgetAmount": m27, "rallyBudgetAmount": m27,
@ -1006,6 +1012,12 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Groceries"), MessageLookupByLibrary.simpleMessage("Groceries"),
"rallyBudgetCategoryRestaurants": "rallyBudgetCategoryRestaurants":
MessageLookupByLibrary.simpleMessage("Restaurants"), MessageLookupByLibrary.simpleMessage("Restaurants"),
"rallyBudgetDetailAmountLeft":
MessageLookupByLibrary.simpleMessage("Amount Left"),
"rallyBudgetDetailAmountUsed":
MessageLookupByLibrary.simpleMessage("Amount Used"),
"rallyBudgetDetailTotalCap":
MessageLookupByLibrary.simpleMessage("Total Cap"),
"rallyBudgetLeft": MessageLookupByLibrary.simpleMessage("Left"), "rallyBudgetLeft": MessageLookupByLibrary.simpleMessage("Left"),
"rallyBudgets": MessageLookupByLibrary.simpleMessage("Budgets"), "rallyBudgets": MessageLookupByLibrary.simpleMessage("Budgets"),
"rallyDescription": "rallyDescription":

@ -8,6 +8,7 @@ import 'package:flutter/semantics.dart';
import 'package:gallery/data/gallery_options.dart'; import 'package:gallery/data/gallery_options.dart';
import 'package:gallery/layout/text_scale.dart'; import 'package:gallery/layout/text_scale.dart';
import 'package:gallery/layout/adaptive.dart';
import 'package:gallery/studies/rally/colors.dart'; import 'package:gallery/studies/rally/colors.dart';
import 'package:gallery/studies/rally/data.dart'; import 'package:gallery/studies/rally/data.dart';
import 'package:gallery/studies/rally/formatters.dart'; import 'package:gallery/studies/rally/formatters.dart';
@ -28,6 +29,9 @@ class RallyLineChart extends StatelessWidget {
labelStyle: Theme.of(context).textTheme.body1, labelStyle: Theme.of(context).textTheme.body1,
textDirection: GalleryOptions.of(context).textDirection(), textDirection: GalleryOptions.of(context).textDirection(),
textScaleFactor: reducedTextScale(context), textScaleFactor: reducedTextScale(context),
padding: isDisplayDesktop(context)
? EdgeInsets.symmetric(vertical: 22)
: EdgeInsets.zero,
), ),
); );
} }
@ -41,6 +45,7 @@ class RallyLineChartPainter extends CustomPainter {
@required this.labelStyle, @required this.labelStyle,
@required this.textDirection, @required this.textDirection,
@required this.textScaleFactor, @required this.textScaleFactor,
@required this.padding,
}); });
// The style for the labels. // The style for the labels.
@ -52,6 +57,9 @@ class RallyLineChartPainter extends CustomPainter {
// The text scale factor for the text. // The text scale factor for the text.
final double textScaleFactor; final double textScaleFactor;
// The padding around the text.
final EdgeInsets padding;
// The format for the dates. // The format for the dates.
final intl.DateFormat dateFormat; final intl.DateFormat dateFormat;
@ -253,7 +261,8 @@ class RallyLineChartPainter extends CustomPainter {
textDirection: textDirection, textDirection: textDirection,
); );
leftLabel.layout(); leftLabel.layout();
leftLabel.paint(canvas, Offset(rect.left + space / 2, rect.topCenter.dy)); leftLabel.paint(canvas,
Offset(rect.left + space / 2 + padding.vertical, rect.topCenter.dy));
final centerLabel = TextPainter( final centerLabel = TextPainter(
text: TextSpan( text: TextSpan(
@ -281,7 +290,8 @@ class RallyLineChartPainter extends CustomPainter {
rightLabel.layout(); rightLabel.layout();
rightLabel.paint( rightLabel.paint(
canvas, canvas,
Offset(rect.right - centerLabel.width - space / 2, rect.topCenter.dy), Offset(rect.right - centerLabel.width - space / 2 - padding.vertical,
rect.topCenter.dy),
); );
} }
} }

@ -38,6 +38,7 @@ class RallyColors {
static const Color cardBackground = Color(0x03FEFEFE); static const Color cardBackground = Color(0x03FEFEFE);
static const Color buttonColor = Color(0xFF09AF79); static const Color buttonColor = Color(0xFF09AF79);
static const Color focusColor = Color(0xCCFFFFFF); static const Color focusColor = Color(0xCCFFFFFF);
static const Color dividerColor = Color(0xAA282828);
/// Convenience method to get a single account color with position i. /// Convenience method to get a single account color with position i.
static Color accountColor(int i) { static Color accountColor(int i) {

@ -15,6 +15,12 @@ double sumAccountDataPrimaryAmount(List<AccountData> items) =>
double sumBillDataPrimaryAmount(List<BillData> items) => double sumBillDataPrimaryAmount(List<BillData> items) =>
sumOf<BillData>(items, (item) => item.primaryAmount); sumOf<BillData>(items, (item) => item.primaryAmount);
/// Calculates the sum of the primary amounts of a list of [BillData].
double sumBillDataPaidAmount(List<BillData> items) => sumOf<BillData>(
items.where((item) => item.isPaid).toList(),
(item) => item.primaryAmount,
);
/// Calculates the sum of the primary amounts of a list of [BudgetData]. /// Calculates the sum of the primary amounts of a list of [BudgetData].
double sumBudgetDataPrimaryAmount(List<BudgetData> items) => double sumBudgetDataPrimaryAmount(List<BudgetData> items) =>
sumOf<BudgetData>(items, (item) => item.primaryAmount); sumOf<BudgetData>(items, (item) => item.primaryAmount);
@ -52,7 +58,12 @@ class AccountData {
/// ///
/// The [primaryAmount] is the amount due in USD. /// The [primaryAmount] is the amount due in USD.
class BillData { class BillData {
const BillData({this.name, this.primaryAmount, this.dueDate}); const BillData({
this.name,
this.primaryAmount,
this.dueDate,
this.isPaid = false,
});
/// The display name of this entity. /// The display name of this entity.
final String name; final String name;
@ -62,6 +73,9 @@ class BillData {
/// The due date of this bill. /// The due date of this bill.
final String dueDate; final String dueDate;
/// If this bill has been paid.
final bool isPaid;
} }
/// A data model for a budget. /// A data model for a budget.
@ -103,9 +117,9 @@ class DetailedEventData {
final double amount; final double amount;
} }
/// A data model for account data. /// A data model for data displayed to the user.
class AccountDetailData { class UserDetailData {
AccountDetailData({this.title, this.value}); UserDetailData({this.title, this.value});
/// The display name of this entity. /// The display name of this entity.
final String title; final String title;
@ -143,34 +157,34 @@ class DummyDataService {
]; ];
} }
static List<AccountDetailData> getAccountDetailList(BuildContext context) { static List<UserDetailData> getAccountDetailList(BuildContext context) {
return <AccountDetailData>[ return <UserDetailData>[
AccountDetailData( UserDetailData(
title: GalleryLocalizations.of(context) title: GalleryLocalizations.of(context)
.rallyAccountDetailDataAnnualPercentageYield, .rallyAccountDetailDataAnnualPercentageYield,
value: percentFormat(context).format(0.001), value: percentFormat(context).format(0.001),
), ),
AccountDetailData( UserDetailData(
title: title:
GalleryLocalizations.of(context).rallyAccountDetailDataInterestRate, GalleryLocalizations.of(context).rallyAccountDetailDataInterestRate,
value: usdWithSignFormat(context).format(1676.14), value: usdWithSignFormat(context).format(1676.14),
), ),
AccountDetailData( UserDetailData(
title: title:
GalleryLocalizations.of(context).rallyAccountDetailDataInterestYtd, GalleryLocalizations.of(context).rallyAccountDetailDataInterestYtd,
value: usdWithSignFormat(context).format(81.45), value: usdWithSignFormat(context).format(81.45),
), ),
AccountDetailData( UserDetailData(
title: GalleryLocalizations.of(context) title: GalleryLocalizations.of(context)
.rallyAccountDetailDataInterestPaidLastYear, .rallyAccountDetailDataInterestPaidLastYear,
value: usdWithSignFormat(context).format(987.12), value: usdWithSignFormat(context).format(987.12),
), ),
AccountDetailData( UserDetailData(
title: GalleryLocalizations.of(context) title: GalleryLocalizations.of(context)
.rallyAccountDetailDataNextStatement, .rallyAccountDetailDataNextStatement,
value: shortDateFormat(context).format(DateTime.utc(2019, 12, 25)), value: shortDateFormat(context).format(DateTime.utc(2019, 12, 25)),
), ),
AccountDetailData( UserDetailData(
title: title:
GalleryLocalizations.of(context).rallyAccountDetailDataAccountOwner, GalleryLocalizations.of(context).rallyAccountDetailDataAccountOwner,
value: 'Philip Cao', value: 'Philip Cao',
@ -233,6 +247,7 @@ class DummyDataService {
primaryAmount: 1200, primaryAmount: 1200,
dueDate: dateFormatAbbreviatedMonthDay(context) dueDate: dateFormatAbbreviatedMonthDay(context)
.format(DateTime.utc(2019, 2, 9)), .format(DateTime.utc(2019, 2, 9)),
isPaid: true,
), ),
BillData( BillData(
name: 'TabFine Credit', name: 'TabFine Credit',
@ -249,6 +264,24 @@ class DummyDataService {
]; ];
} }
static List<UserDetailData> getBillDetailList(BuildContext context,
{double dueTotal, double paidTotal}) {
return <UserDetailData>[
UserDetailData(
title: GalleryLocalizations.of(context).rallyBillDetailTotalAmount,
value: usdWithSignFormat(context).format(paidTotal + dueTotal),
),
UserDetailData(
title: GalleryLocalizations.of(context).rallyBillDetailAmountPaid,
value: usdWithSignFormat(context).format(paidTotal),
),
UserDetailData(
title: GalleryLocalizations.of(context).rallyBillDetailAmountDue,
value: usdWithSignFormat(context).format(dueTotal),
),
];
}
static List<BudgetData> getBudgetDataList(BuildContext context) { static List<BudgetData> getBudgetDataList(BuildContext context) {
return <BudgetData>[ return <BudgetData>[
BudgetData( BudgetData(
@ -274,6 +307,24 @@ class DummyDataService {
]; ];
} }
static List<UserDetailData> getBudgetDetailList(BuildContext context,
{double capTotal, double usedTotal}) {
return <UserDetailData>[
UserDetailData(
title: GalleryLocalizations.of(context).rallyBudgetDetailTotalCap,
value: usdWithSignFormat(context).format(capTotal),
),
UserDetailData(
title: GalleryLocalizations.of(context).rallyBudgetDetailAmountUsed,
value: usdWithSignFormat(context).format(usedTotal),
),
UserDetailData(
title: GalleryLocalizations.of(context).rallyBudgetDetailAmountLeft,
value: usdWithSignFormat(context).format(capTotal - usedTotal),
),
];
}
static List<String> getSettingsTitles(BuildContext context) { static List<String> getSettingsTitles(BuildContext context) {
return <String>[ return <String>[
GalleryLocalizations.of(context).rallySettingsManageAccounts, GalleryLocalizations.of(context).rallySettingsManageAccounts,

@ -9,6 +9,7 @@ import 'package:flutter/rendering.dart';
import 'package:gallery/data/gallery_options.dart'; import 'package:gallery/data/gallery_options.dart';
import 'package:gallery/l10n/gallery_localizations.dart'; import 'package:gallery/l10n/gallery_localizations.dart';
import 'package:gallery/layout/adaptive.dart';
import 'package:gallery/layout/text_scale.dart'; import 'package:gallery/layout/text_scale.dart';
import 'package:gallery/studies/rally/charts/line_chart.dart'; import 'package:gallery/studies/rally/charts/line_chart.dart';
import 'package:gallery/studies/rally/charts/pie_chart.dart'; import 'package:gallery/studies/rally/charts/pie_chart.dart';
@ -170,7 +171,7 @@ class FinancialEntityCategoryView extends StatelessWidget {
height: 1, height: 1,
indent: 16, indent: 16,
endIndent: 16, endIndent: 16,
color: Color(0xAA282828), color: RallyColors.dividerColor,
), ),
], ],
), ),
@ -309,13 +310,7 @@ class FinancialEntityCategoryDetailsPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final List<_DetailedEventCard> cards = items.map((detailedEventData) { final isDesktop = isDisplayDesktop(context);
return _DetailedEventCard(
title: detailedEventData.title,
date: detailedEventData.date,
amount: detailedEventData.amount,
);
}).toList();
return ApplyTextOptions( return ApplyTextOptions(
child: Scaffold( child: Scaffold(
@ -335,7 +330,20 @@ class FinancialEntityCategoryDetailsPage extends StatelessWidget {
child: RallyLineChart(events: items), child: RallyLineChart(events: items),
), ),
Expanded( Expanded(
child: ListView(shrinkWrap: true, children: cards), child: Padding(
padding: isDesktop ? EdgeInsets.all(40) : EdgeInsets.zero,
child: ListView(
shrinkWrap: true,
children: [
for (DetailedEventData detailedEventData in items)
_DetailedEventCard(
title: detailedEventData.title,
date: detailedEventData.date,
amount: detailedEventData.amount,
),
],
),
),
), ),
], ],
), ),
@ -357,7 +365,7 @@ class _DetailedEventCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme; final isDesktop = isDisplayDesktop(context);
return FlatButton( return FlatButton(
onPressed: () {}, onPressed: () {},
padding: EdgeInsets.symmetric(horizontal: 16), padding: EdgeInsets.symmetric(horizontal: 16),
@ -366,37 +374,42 @@ class _DetailedEventCard extends StatelessWidget {
Container( Container(
padding: EdgeInsets.symmetric(vertical: 16), padding: EdgeInsets.symmetric(vertical: 16),
width: double.infinity, width: double.infinity,
child: Wrap( child: isDesktop
? Row(
children: [
Expanded(
flex: 1,
child: _EventTitle(title: title),
),
_EventDate(date: date),
Expanded(
flex: 1,
child: Align(
alignment: AlignmentDirectional.centerEnd,
child: _EventAmount(amount: amount),
),
),
],
)
: Wrap(
alignment: WrapAlignment.spaceBetween, alignment: WrapAlignment.spaceBetween,
children: [ children: [
Column( Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( _EventTitle(title: title),
title, _EventDate(date: date),
style: textTheme.body1.copyWith(fontSize: 16),
),
Text(
shortDateFormat(context).format(date),
semanticsLabel: longDateFormat(context).format(date),
style:
textTheme.body1.copyWith(color: RallyColors.gray60),
),
], ],
), ),
Text( _EventAmount(amount: amount),
usdWithSignFormat(context).format(amount),
style: textTheme.body2
.copyWith(fontSize: 20, color: RallyColors.gray),
),
], ],
), ),
), ),
SizedBox( SizedBox(
height: 1, height: 1,
child: Container( child: Container(
color: const Color(0xAA282828), color: RallyColors.dividerColor,
), ),
), ),
], ],
@ -404,3 +417,49 @@ class _DetailedEventCard extends StatelessWidget {
); );
} }
} }
class _EventAmount extends StatelessWidget {
const _EventAmount({Key key, @required this.amount}) : super(key: key);
final double amount;
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return Text(
usdWithSignFormat(context).format(amount),
style: textTheme.body2.copyWith(fontSize: 20, color: RallyColors.gray),
);
}
}
class _EventDate extends StatelessWidget {
const _EventDate({Key key, @required this.date}) : super(key: key);
final DateTime date;
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return Text(
shortDateFormat(context).format(date),
semanticsLabel: longDateFormat(context).format(date),
style: textTheme.body1.copyWith(color: RallyColors.gray60),
);
}
}
class _EventTitle extends StatelessWidget {
const _EventTitle({Key key, @required this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return Text(
title,
style: textTheme.body1.copyWith(fontSize: 16),
);
}
}

@ -5,11 +5,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gallery/l10n/gallery_localizations.dart'; import 'package:gallery/l10n/gallery_localizations.dart';
import 'package:gallery/layout/adaptive.dart';
import 'package:gallery/studies/rally/charts/pie_chart.dart'; import 'package:gallery/studies/rally/charts/pie_chart.dart';
import 'package:gallery/studies/rally/colors.dart';
import 'package:gallery/studies/rally/data.dart'; import 'package:gallery/studies/rally/data.dart';
import 'package:gallery/studies/rally/finance.dart'; import 'package:gallery/studies/rally/finance.dart';
import 'package:gallery/studies/rally/tabs/sidebar.dart';
/// A page that shows a summary of accounts. /// A page that shows a summary of accounts.
class AccountsView extends StatelessWidget { class AccountsView extends StatelessWidget {
@ -18,74 +17,18 @@ class AccountsView extends StatelessWidget {
final items = DummyDataService.getAccountDataList(context); final items = DummyDataService.getAccountDataList(context);
final detailItems = DummyDataService.getAccountDetailList(context); final detailItems = DummyDataService.getAccountDetailList(context);
final balanceTotal = sumAccountDataPrimaryAmount(items); final balanceTotal = sumAccountDataPrimaryAmount(items);
final view = FinancialEntityView(
return TabWithSidebar(
mainView: FinancialEntityView(
heroLabel: GalleryLocalizations.of(context).rallyAccountTotal, heroLabel: GalleryLocalizations.of(context).rallyAccountTotal,
heroAmount: balanceTotal, heroAmount: balanceTotal,
segments: buildSegmentsFromAccountItems(items), segments: buildSegmentsFromAccountItems(items),
wholeAmount: balanceTotal, wholeAmount: balanceTotal,
financialEntityCards: buildAccountDataListViews(items, context), financialEntityCards: buildAccountDataListViews(items, context),
);
if (isDisplayDesktop(context)) {
return Row(
children: [
Flexible(
flex: 2,
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 24),
child: view,
),
),
),
Expanded(
flex: 1,
child: Container(
color: RallyColors.inputBackground,
padding: EdgeInsetsDirectional.only(start: 24),
height: double.infinity,
alignment: AlignmentDirectional.centerStart,
child: ListView(
shrinkWrap: true,
children: [
for (AccountDetailData item in detailItems)
_AccountDetail(title: item.title, value: item.value),
],
),
),
),
],
);
} else {
return SingleChildScrollView(child: view);
}
}
}
class _AccountDetail extends StatelessWidget {
const _AccountDetail({Key key, this.value, this.title}) : super(key: key);
final String value;
final String title;
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 8),
Text(
title,
style:
textTheme.body1.copyWith(fontSize: 16, color: RallyColors.gray60),
),
SizedBox(height: 8),
Text(
value,
style: textTheme.body2.copyWith(fontSize: 20),
), ),
SizedBox(height: 8), sidebarItems: [
Container(color: RallyColors.primaryBackground, height: 1), for (UserDetailData item in detailItems)
SidebarItem(title: item.title, value: item.value)
], ],
); );
} }

@ -5,10 +5,10 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:gallery/l10n/gallery_localizations.dart'; import 'package:gallery/l10n/gallery_localizations.dart';
import 'package:gallery/layout/adaptive.dart';
import 'package:gallery/studies/rally/charts/pie_chart.dart'; import 'package:gallery/studies/rally/charts/pie_chart.dart';
import 'package:gallery/studies/rally/data.dart'; import 'package:gallery/studies/rally/data.dart';
import 'package:gallery/studies/rally/finance.dart'; import 'package:gallery/studies/rally/finance.dart';
import 'package:gallery/studies/rally/tabs/sidebar.dart';
/// A page that shows a summary of bills. /// A page that shows a summary of bills.
class BillsView extends StatefulWidget { class BillsView extends StatefulWidget {
@ -22,17 +22,25 @@ class _BillsViewState extends State<BillsView>
Widget build(BuildContext context) { Widget build(BuildContext context) {
List<BillData> items = DummyDataService.getBillDataList(context); List<BillData> items = DummyDataService.getBillDataList(context);
final dueTotal = sumBillDataPrimaryAmount(items); final dueTotal = sumBillDataPrimaryAmount(items);
return SingleChildScrollView( final paidTotal = sumBillDataPaidAmount(items);
child: Container( final detailItems = DummyDataService.getBillDetailList(
padding: isDisplayDesktop(context) ? EdgeInsets.only(top: 24) : null, context,
child: FinancialEntityView( dueTotal: dueTotal,
paidTotal: paidTotal,
);
return TabWithSidebar(
mainView: FinancialEntityView(
heroLabel: GalleryLocalizations.of(context).rallyBillsDue, heroLabel: GalleryLocalizations.of(context).rallyBillsDue,
heroAmount: dueTotal, heroAmount: dueTotal,
segments: buildSegmentsFromBillItems(items), segments: buildSegmentsFromBillItems(items),
wholeAmount: dueTotal, wholeAmount: dueTotal,
financialEntityCards: buildBillDataListViews(items, context), financialEntityCards: buildBillDataListViews(items, context),
), ),
), sidebarItems: [
for (UserDetailData item in detailItems)
SidebarItem(title: item.title, value: item.value)
],
); );
} }
} }

@ -5,10 +5,10 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:gallery/l10n/gallery_localizations.dart'; import 'package:gallery/l10n/gallery_localizations.dart';
import 'package:gallery/layout/adaptive.dart';
import 'package:gallery/studies/rally/charts/pie_chart.dart'; import 'package:gallery/studies/rally/charts/pie_chart.dart';
import 'package:gallery/studies/rally/data.dart'; import 'package:gallery/studies/rally/data.dart';
import 'package:gallery/studies/rally/finance.dart'; import 'package:gallery/studies/rally/finance.dart';
import 'package:gallery/studies/rally/tabs/sidebar.dart';
class BudgetsView extends StatefulWidget { class BudgetsView extends StatefulWidget {
@override @override
@ -22,17 +22,24 @@ class _BudgetsViewState extends State<BudgetsView>
final items = DummyDataService.getBudgetDataList(context); final items = DummyDataService.getBudgetDataList(context);
final capTotal = sumBudgetDataPrimaryAmount(items); final capTotal = sumBudgetDataPrimaryAmount(items);
final usedTotal = sumBudgetDataAmountUsed(items); final usedTotal = sumBudgetDataAmountUsed(items);
return SingleChildScrollView( final detailItems = DummyDataService.getBudgetDetailList(
child: Container( context,
padding: isDisplayDesktop(context) ? EdgeInsets.only(top: 24) : null, capTotal: capTotal,
child: FinancialEntityView( usedTotal: usedTotal,
);
return TabWithSidebar(
mainView: FinancialEntityView(
heroLabel: GalleryLocalizations.of(context).rallyBudgetLeft, heroLabel: GalleryLocalizations.of(context).rallyBudgetLeft,
heroAmount: capTotal - usedTotal, heroAmount: capTotal - usedTotal,
segments: buildSegmentsFromBudgetItems(items), segments: buildSegmentsFromBudgetItems(items),
wholeAmount: capTotal, wholeAmount: capTotal,
financialEntityCards: buildBudgetDataListViews(items, context), financialEntityCards: buildBudgetDataListViews(items, context),
), ),
), sidebarItems: [
for (UserDetailData item in detailItems)
SidebarItem(title: item.title, value: item.value)
],
); );
} }
} }

@ -5,6 +5,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gallery/layout/adaptive.dart'; import 'package:gallery/layout/adaptive.dart';
import 'package:gallery/studies/rally/colors.dart';
import 'package:gallery/studies/rally/data.dart'; import 'package:gallery/studies/rally/data.dart';
import 'package:gallery/studies/rally/login.dart'; import 'package:gallery/studies/rally/login.dart';
@ -16,14 +17,19 @@ class SettingsView extends StatefulWidget {
class _SettingsViewState extends State<SettingsView> { class _SettingsViewState extends State<SettingsView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final items = DummyDataService.getSettingsTitles(context)
.map((title) => _SettingsItem(title))
.toList();
return Container( return Container(
padding: EdgeInsets.only(top: isDisplayDesktop(context) ? 24 : 0), padding: EdgeInsets.only(top: isDisplayDesktop(context) ? 24 : 0),
child: ListView( child: ListView(
shrinkWrap: true, shrinkWrap: true,
children: items, children: [
for (String title in DummyDataService.getSettingsTitles(context)) ...[
_SettingsItem(title),
Divider(
color: RallyColors.dividerColor,
height: 1,
)
]
],
), ),
); );
} }

@ -0,0 +1,87 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:gallery/layout/adaptive.dart';
import 'package:gallery/studies/rally/colors.dart';
class TabWithSidebar extends StatelessWidget {
const TabWithSidebar({
Key key,
@required this.mainView,
@required this.sidebarItems,
}) : super(key: key);
final Widget mainView;
final List<Widget> sidebarItems;
@override
Widget build(BuildContext context) {
if (isDisplayDesktop(context)) {
return Row(
children: [
Flexible(
flex: 2,
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 24),
child: mainView,
),
),
),
Expanded(
flex: 1,
child: Container(
color: RallyColors.inputBackground,
padding: EdgeInsetsDirectional.only(start: 24),
height: double.infinity,
alignment: AlignmentDirectional.centerStart,
child: ListView(
shrinkWrap: true,
children: sidebarItems,
),
),
),
],
);
} else {
return SingleChildScrollView(child: mainView);
}
}
}
class SidebarItem extends StatelessWidget {
const SidebarItem({Key key, this.value, this.title}) : super(key: key);
final String value;
final String title;
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 8),
Text(
title,
style: textTheme.body1.copyWith(
fontSize: 16,
color: RallyColors.gray60,
),
),
SizedBox(height: 8),
Text(
value,
style: textTheme.body2.copyWith(fontSize: 20),
),
SizedBox(height: 8),
Container(
color: RallyColors.primaryBackground,
height: 1,
),
],
);
}
}
Loading…
Cancel
Save