1
0
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:
Per Classon
2020-02-06 12:02:30 +01:00
committed by GitHub
parent c1acfe799d
commit d04440c11f
15 changed files with 1118 additions and 807 deletions

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -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 &apos;Manage Accounts."

View File

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

View File

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

View File

@@ -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) {

View File

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

View File

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

View File

@@ -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)
],
);
}

View File

@@ -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)
],
);
}
}

View File

@@ -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)
],
);
}
}

View File

@@ -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,
)
]
],
),
);
}

View 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,
),
],
);
}
}