mirror of
https://github.com/flutter/samples.git
synced 2025-11-10 14:58:34 +00:00
[Gallery] Update desktop Rally for pages that did not have designs before (#314)
* Update desktop Rally for pages that did not have designs before
This commit is contained in:
BIN
gallery/fonts/google_fonts/Eczar-Regular.ttf
Normal file
BIN
gallery/fonts/google_fonts/Eczar-Regular.ttf
Normal file
Binary file not shown.
BIN
gallery/fonts/google_fonts/Eczar-SemiBold.ttf
Normal file
BIN
gallery/fonts/google_fonts/Eczar-SemiBold.ttf
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -171,6 +171,18 @@
|
||||
"@rallyAccountDetailDataAccountOwner": {
|
||||
"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": {
|
||||
"description": "Category for budget, to sort expenses / bills in."
|
||||
@@ -187,6 +199,18 @@
|
||||
"@rallyBudgetCategoryClothing": {
|
||||
"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": {
|
||||
"description": "Link to go to the page 'Manage Accounts."
|
||||
|
||||
@@ -161,6 +161,18 @@
|
||||
name="rallyAccountDetailDataAccountOwner"
|
||||
description="Title for an account detail. Below the name of the account owner will be displayed."
|
||||
>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
|
||||
name="rallyBudgetCategoryCoffeeShops"
|
||||
description="Category for budget, to sort expenses / bills in."
|
||||
@@ -177,6 +189,18 @@
|
||||
name="rallyBudgetCategoryClothing"
|
||||
description="Category for budget, to sort expenses / bills in."
|
||||
>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
|
||||
name="rallySettingsManageAccounts"
|
||||
description="Link to go to the page 'Manage Accounts."
|
||||
|
||||
@@ -995,6 +995,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"rallyAlertsMessageSpentOnRestaurants": m24,
|
||||
"rallyAlertsMessageUnassignedTransactions": m25,
|
||||
"rallyBillAmount": m26,
|
||||
"rallyBillDetailAmountDue":
|
||||
MessageLookupByLibrary.simpleMessage("Amount Due"),
|
||||
"rallyBillDetailAmountPaid":
|
||||
MessageLookupByLibrary.simpleMessage("Amount Paid"),
|
||||
"rallyBillDetailTotalAmount":
|
||||
MessageLookupByLibrary.simpleMessage("Total Amount"),
|
||||
"rallyBills": MessageLookupByLibrary.simpleMessage("Bills"),
|
||||
"rallyBillsDue": MessageLookupByLibrary.simpleMessage("Due"),
|
||||
"rallyBudgetAmount": m27,
|
||||
@@ -1006,6 +1012,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
MessageLookupByLibrary.simpleMessage("Groceries"),
|
||||
"rallyBudgetCategoryRestaurants":
|
||||
MessageLookupByLibrary.simpleMessage("Restaurants"),
|
||||
"rallyBudgetDetailAmountLeft":
|
||||
MessageLookupByLibrary.simpleMessage("Amount Left"),
|
||||
"rallyBudgetDetailAmountUsed":
|
||||
MessageLookupByLibrary.simpleMessage("Amount Used"),
|
||||
"rallyBudgetDetailTotalCap":
|
||||
MessageLookupByLibrary.simpleMessage("Total Cap"),
|
||||
"rallyBudgetLeft": MessageLookupByLibrary.simpleMessage("Left"),
|
||||
"rallyBudgets": MessageLookupByLibrary.simpleMessage("Budgets"),
|
||||
"rallyDescription":
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:flutter/semantics.dart';
|
||||
|
||||
import 'package:gallery/data/gallery_options.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/data.dart';
|
||||
import 'package:gallery/studies/rally/formatters.dart';
|
||||
@@ -28,6 +29,9 @@ class RallyLineChart extends StatelessWidget {
|
||||
labelStyle: Theme.of(context).textTheme.body1,
|
||||
textDirection: GalleryOptions.of(context).textDirection(),
|
||||
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.textDirection,
|
||||
@required this.textScaleFactor,
|
||||
@required this.padding,
|
||||
});
|
||||
|
||||
// The style for the labels.
|
||||
@@ -52,6 +57,9 @@ class RallyLineChartPainter extends CustomPainter {
|
||||
// The text scale factor for the text.
|
||||
final double textScaleFactor;
|
||||
|
||||
// The padding around the text.
|
||||
final EdgeInsets padding;
|
||||
|
||||
// The format for the dates.
|
||||
final intl.DateFormat dateFormat;
|
||||
|
||||
@@ -253,7 +261,8 @@ class RallyLineChartPainter extends CustomPainter {
|
||||
textDirection: textDirection,
|
||||
);
|
||||
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(
|
||||
text: TextSpan(
|
||||
@@ -281,7 +290,8 @@ class RallyLineChartPainter extends CustomPainter {
|
||||
rightLabel.layout();
|
||||
rightLabel.paint(
|
||||
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 buttonColor = Color(0xFF09AF79);
|
||||
static const Color focusColor = Color(0xCCFFFFFF);
|
||||
static const Color dividerColor = Color(0xAA282828);
|
||||
|
||||
/// Convenience method to get a single account color with position i.
|
||||
static Color accountColor(int i) {
|
||||
|
||||
@@ -15,6 +15,12 @@ double sumAccountDataPrimaryAmount(List<AccountData> items) =>
|
||||
double sumBillDataPrimaryAmount(List<BillData> items) =>
|
||||
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].
|
||||
double sumBudgetDataPrimaryAmount(List<BudgetData> items) =>
|
||||
sumOf<BudgetData>(items, (item) => item.primaryAmount);
|
||||
@@ -52,7 +58,12 @@ class AccountData {
|
||||
///
|
||||
/// The [primaryAmount] is the amount due in USD.
|
||||
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.
|
||||
final String name;
|
||||
@@ -62,6 +73,9 @@ class BillData {
|
||||
|
||||
/// The due date of this bill.
|
||||
final String dueDate;
|
||||
|
||||
/// If this bill has been paid.
|
||||
final bool isPaid;
|
||||
}
|
||||
|
||||
/// A data model for a budget.
|
||||
@@ -103,9 +117,9 @@ class DetailedEventData {
|
||||
final double amount;
|
||||
}
|
||||
|
||||
/// A data model for account data.
|
||||
class AccountDetailData {
|
||||
AccountDetailData({this.title, this.value});
|
||||
/// A data model for data displayed to the user.
|
||||
class UserDetailData {
|
||||
UserDetailData({this.title, this.value});
|
||||
|
||||
/// The display name of this entity.
|
||||
final String title;
|
||||
@@ -143,34 +157,34 @@ class DummyDataService {
|
||||
];
|
||||
}
|
||||
|
||||
static List<AccountDetailData> getAccountDetailList(BuildContext context) {
|
||||
return <AccountDetailData>[
|
||||
AccountDetailData(
|
||||
static List<UserDetailData> getAccountDetailList(BuildContext context) {
|
||||
return <UserDetailData>[
|
||||
UserDetailData(
|
||||
title: GalleryLocalizations.of(context)
|
||||
.rallyAccountDetailDataAnnualPercentageYield,
|
||||
value: percentFormat(context).format(0.001),
|
||||
),
|
||||
AccountDetailData(
|
||||
UserDetailData(
|
||||
title:
|
||||
GalleryLocalizations.of(context).rallyAccountDetailDataInterestRate,
|
||||
value: usdWithSignFormat(context).format(1676.14),
|
||||
),
|
||||
AccountDetailData(
|
||||
UserDetailData(
|
||||
title:
|
||||
GalleryLocalizations.of(context).rallyAccountDetailDataInterestYtd,
|
||||
value: usdWithSignFormat(context).format(81.45),
|
||||
),
|
||||
AccountDetailData(
|
||||
UserDetailData(
|
||||
title: GalleryLocalizations.of(context)
|
||||
.rallyAccountDetailDataInterestPaidLastYear,
|
||||
value: usdWithSignFormat(context).format(987.12),
|
||||
),
|
||||
AccountDetailData(
|
||||
UserDetailData(
|
||||
title: GalleryLocalizations.of(context)
|
||||
.rallyAccountDetailDataNextStatement,
|
||||
value: shortDateFormat(context).format(DateTime.utc(2019, 12, 25)),
|
||||
),
|
||||
AccountDetailData(
|
||||
UserDetailData(
|
||||
title:
|
||||
GalleryLocalizations.of(context).rallyAccountDetailDataAccountOwner,
|
||||
value: 'Philip Cao',
|
||||
@@ -233,6 +247,7 @@ class DummyDataService {
|
||||
primaryAmount: 1200,
|
||||
dueDate: dateFormatAbbreviatedMonthDay(context)
|
||||
.format(DateTime.utc(2019, 2, 9)),
|
||||
isPaid: true,
|
||||
),
|
||||
BillData(
|
||||
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) {
|
||||
return <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) {
|
||||
return <String>[
|
||||
GalleryLocalizations.of(context).rallySettingsManageAccounts,
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:flutter/rendering.dart';
|
||||
|
||||
import 'package:gallery/data/gallery_options.dart';
|
||||
import 'package:gallery/l10n/gallery_localizations.dart';
|
||||
import 'package:gallery/layout/adaptive.dart';
|
||||
import 'package:gallery/layout/text_scale.dart';
|
||||
import 'package:gallery/studies/rally/charts/line_chart.dart';
|
||||
import 'package:gallery/studies/rally/charts/pie_chart.dart';
|
||||
@@ -170,7 +171,7 @@ class FinancialEntityCategoryView extends StatelessWidget {
|
||||
height: 1,
|
||||
indent: 16,
|
||||
endIndent: 16,
|
||||
color: Color(0xAA282828),
|
||||
color: RallyColors.dividerColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -309,13 +310,7 @@ class FinancialEntityCategoryDetailsPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<_DetailedEventCard> cards = items.map((detailedEventData) {
|
||||
return _DetailedEventCard(
|
||||
title: detailedEventData.title,
|
||||
date: detailedEventData.date,
|
||||
amount: detailedEventData.amount,
|
||||
);
|
||||
}).toList();
|
||||
final isDesktop = isDisplayDesktop(context);
|
||||
|
||||
return ApplyTextOptions(
|
||||
child: Scaffold(
|
||||
@@ -335,7 +330,20 @@ class FinancialEntityCategoryDetailsPage extends StatelessWidget {
|
||||
child: RallyLineChart(events: items),
|
||||
),
|
||||
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
|
||||
Widget build(BuildContext context) {
|
||||
final textTheme = Theme.of(context).textTheme;
|
||||
final isDesktop = isDisplayDesktop(context);
|
||||
return FlatButton(
|
||||
onPressed: () {},
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
@@ -366,37 +374,42 @@ class _DetailedEventCard extends StatelessWidget {
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 16),
|
||||
width: double.infinity,
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: textTheme.body1.copyWith(fontSize: 16),
|
||||
),
|
||||
Text(
|
||||
shortDateFormat(context).format(date),
|
||||
semanticsLabel: longDateFormat(context).format(date),
|
||||
style:
|
||||
textTheme.body1.copyWith(color: RallyColors.gray60),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
usdWithSignFormat(context).format(amount),
|
||||
style: textTheme.body2
|
||||
.copyWith(fontSize: 20, color: RallyColors.gray),
|
||||
),
|
||||
],
|
||||
),
|
||||
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,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_EventTitle(title: title),
|
||||
_EventDate(date: date),
|
||||
],
|
||||
),
|
||||
_EventAmount(amount: amount),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 1,
|
||||
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: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/colors.dart';
|
||||
import 'package:gallery/studies/rally/data.dart';
|
||||
import 'package:gallery/studies/rally/finance.dart';
|
||||
import 'package:gallery/studies/rally/tabs/sidebar.dart';
|
||||
|
||||
/// A page that shows a summary of accounts.
|
||||
class AccountsView extends StatelessWidget {
|
||||
@@ -18,74 +17,18 @@ class AccountsView extends StatelessWidget {
|
||||
final items = DummyDataService.getAccountDataList(context);
|
||||
final detailItems = DummyDataService.getAccountDetailList(context);
|
||||
final balanceTotal = sumAccountDataPrimaryAmount(items);
|
||||
final view = FinancialEntityView(
|
||||
heroLabel: GalleryLocalizations.of(context).rallyAccountTotal,
|
||||
heroAmount: balanceTotal,
|
||||
segments: buildSegmentsFromAccountItems(items),
|
||||
wholeAmount: balanceTotal,
|
||||
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),
|
||||
Container(color: RallyColors.primaryBackground, height: 1),
|
||||
return TabWithSidebar(
|
||||
mainView: FinancialEntityView(
|
||||
heroLabel: GalleryLocalizations.of(context).rallyAccountTotal,
|
||||
heroAmount: balanceTotal,
|
||||
segments: buildSegmentsFromAccountItems(items),
|
||||
wholeAmount: balanceTotal,
|
||||
financialEntityCards: buildAccountDataListViews(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: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/data.dart';
|
||||
import 'package:gallery/studies/rally/finance.dart';
|
||||
import 'package:gallery/studies/rally/tabs/sidebar.dart';
|
||||
|
||||
/// A page that shows a summary of bills.
|
||||
class BillsView extends StatefulWidget {
|
||||
@@ -22,17 +22,25 @@ class _BillsViewState extends State<BillsView>
|
||||
Widget build(BuildContext context) {
|
||||
List<BillData> items = DummyDataService.getBillDataList(context);
|
||||
final dueTotal = sumBillDataPrimaryAmount(items);
|
||||
return SingleChildScrollView(
|
||||
child: Container(
|
||||
padding: isDisplayDesktop(context) ? EdgeInsets.only(top: 24) : null,
|
||||
child: FinancialEntityView(
|
||||
heroLabel: GalleryLocalizations.of(context).rallyBillsDue,
|
||||
heroAmount: dueTotal,
|
||||
segments: buildSegmentsFromBillItems(items),
|
||||
wholeAmount: dueTotal,
|
||||
financialEntityCards: buildBillDataListViews(items, context),
|
||||
),
|
||||
final paidTotal = sumBillDataPaidAmount(items);
|
||||
final detailItems = DummyDataService.getBillDetailList(
|
||||
context,
|
||||
dueTotal: dueTotal,
|
||||
paidTotal: paidTotal,
|
||||
);
|
||||
|
||||
return TabWithSidebar(
|
||||
mainView: FinancialEntityView(
|
||||
heroLabel: GalleryLocalizations.of(context).rallyBillsDue,
|
||||
heroAmount: dueTotal,
|
||||
segments: buildSegmentsFromBillItems(items),
|
||||
wholeAmount: dueTotal,
|
||||
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: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/data.dart';
|
||||
import 'package:gallery/studies/rally/finance.dart';
|
||||
import 'package:gallery/studies/rally/tabs/sidebar.dart';
|
||||
|
||||
class BudgetsView extends StatefulWidget {
|
||||
@override
|
||||
@@ -22,17 +22,24 @@ class _BudgetsViewState extends State<BudgetsView>
|
||||
final items = DummyDataService.getBudgetDataList(context);
|
||||
final capTotal = sumBudgetDataPrimaryAmount(items);
|
||||
final usedTotal = sumBudgetDataAmountUsed(items);
|
||||
return SingleChildScrollView(
|
||||
child: Container(
|
||||
padding: isDisplayDesktop(context) ? EdgeInsets.only(top: 24) : null,
|
||||
child: FinancialEntityView(
|
||||
heroLabel: GalleryLocalizations.of(context).rallyBudgetLeft,
|
||||
heroAmount: capTotal - usedTotal,
|
||||
segments: buildSegmentsFromBudgetItems(items),
|
||||
wholeAmount: capTotal,
|
||||
financialEntityCards: buildBudgetDataListViews(items, context),
|
||||
),
|
||||
final detailItems = DummyDataService.getBudgetDetailList(
|
||||
context,
|
||||
capTotal: capTotal,
|
||||
usedTotal: usedTotal,
|
||||
);
|
||||
|
||||
return TabWithSidebar(
|
||||
mainView: FinancialEntityView(
|
||||
heroLabel: GalleryLocalizations.of(context).rallyBudgetLeft,
|
||||
heroAmount: capTotal - usedTotal,
|
||||
segments: buildSegmentsFromBudgetItems(items),
|
||||
wholeAmount: capTotal,
|
||||
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:gallery/layout/adaptive.dart';
|
||||
import 'package:gallery/studies/rally/colors.dart';
|
||||
import 'package:gallery/studies/rally/data.dart';
|
||||
import 'package:gallery/studies/rally/login.dart';
|
||||
|
||||
@@ -16,14 +17,19 @@ class SettingsView extends StatefulWidget {
|
||||
class _SettingsViewState extends State<SettingsView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final items = DummyDataService.getSettingsTitles(context)
|
||||
.map((title) => _SettingsItem(title))
|
||||
.toList();
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: isDisplayDesktop(context) ? 24 : 0),
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
children: items,
|
||||
children: [
|
||||
for (String title in DummyDataService.getSettingsTitles(context)) ...[
|
||||
_SettingsItem(title),
|
||||
Divider(
|
||||
color: RallyColors.dividerColor,
|
||||
height: 1,
|
||||
)
|
||||
]
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
87
gallery/lib/studies/rally/tabs/sidebar.dart
Normal file
87
gallery/lib/studies/rally/tabs/sidebar.dart
Normal file
@@ -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,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user