184 lines
5.4 KiB
Dart
184 lines
5.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:okane/screen.dart';
|
|
import 'package:okane/ui/pages/account/account.dart';
|
|
import 'package:okane/ui/pages/budgets/budget_details.dart';
|
|
import 'package:okane/ui/pages/budgets/budgets.dart';
|
|
import 'package:okane/ui/pages/template_list.dart';
|
|
import 'package:okane/ui/pages/transaction_details.dart';
|
|
import 'package:okane/ui/pages/transaction_list.dart';
|
|
import 'package:okane/ui/state/core.dart';
|
|
|
|
enum OkanePage { accounts, transactions, beneficiaries, templates, budgets }
|
|
|
|
typedef OkanePageBuilder = Widget Function(bool);
|
|
|
|
class OkanePageItem {
|
|
final OkanePage page;
|
|
final IconData icon;
|
|
final String label;
|
|
final Widget child;
|
|
final OkanePageBuilder? details;
|
|
|
|
const OkanePageItem(
|
|
this.page,
|
|
this.icon,
|
|
this.label,
|
|
this.child,
|
|
this.details,
|
|
);
|
|
|
|
NavigationDestination toDestination() =>
|
|
NavigationDestination(icon: Icon(icon), label: label);
|
|
|
|
NavigationRailDestination toRailDestination() =>
|
|
NavigationRailDestination(icon: Icon(icon), label: Text(label));
|
|
}
|
|
|
|
final _pages = <OkanePageItem>[
|
|
OkanePageItem(
|
|
OkanePage.accounts,
|
|
Icons.account_box,
|
|
"Accounts",
|
|
AccountListPage(isPage: false),
|
|
null,
|
|
),
|
|
OkanePageItem(
|
|
OkanePage.transactions,
|
|
Icons.monetization_on_rounded,
|
|
"Transactions",
|
|
TransactionListPage(),
|
|
(_) => TransactionDetailsPage(),
|
|
),
|
|
OkanePageItem(
|
|
OkanePage.beneficiaries,
|
|
Icons.person,
|
|
"Beneficiaries",
|
|
Container(),
|
|
null,
|
|
),
|
|
OkanePageItem(
|
|
OkanePage.templates,
|
|
Icons.list,
|
|
"Templates",
|
|
TemplateListPage(),
|
|
null,
|
|
),
|
|
OkanePageItem(
|
|
OkanePage.budgets,
|
|
Icons.pie_chart,
|
|
"Budgets",
|
|
BudgetListPage(),
|
|
(_) => BudgetDetailsPage(),
|
|
),
|
|
];
|
|
|
|
class OkaneNavigationRail extends StatelessWidget {
|
|
const OkaneNavigationRail({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return BlocBuilder<CoreCubit, CoreState>(
|
|
builder:
|
|
(context, state) => NavigationRail(
|
|
onDestinationSelected:
|
|
(i) => context.read<CoreCubit>().setPage(_pages[i].page),
|
|
destinations: _pages.map((p) => p.toRailDestination()).toList(),
|
|
selectedIndex: _pages.indexWhere((p) => p.page == state.activePage),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class OkaneNavigationBar extends StatelessWidget {
|
|
const OkaneNavigationBar({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return BlocBuilder<CoreCubit, CoreState>(
|
|
builder:
|
|
(context, state) => NavigationBar(
|
|
onDestinationSelected:
|
|
(i) => context.read<CoreCubit>().setPage(_pages[i].page),
|
|
destinations: _pages.map((p) => p.toDestination()).toList(),
|
|
selectedIndex: _pages.indexWhere((p) => p.page == state.activePage),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class OkaneNavigationDrawer extends StatelessWidget {
|
|
const OkaneNavigationDrawer({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return BlocBuilder<CoreCubit, CoreState>(
|
|
builder: (context, state) => Drawer(
|
|
child: ListView(
|
|
children: _pages.map((p) => ListTile(
|
|
title: Text(p.label),
|
|
leading: Icon(p.icon),
|
|
selected: p.page == state.activePage,
|
|
onTap: () {
|
|
context.read<CoreCubit>().setPage(p.page);
|
|
Navigator.of(context).pop();
|
|
},
|
|
)).toList(),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class OkaneNavigationLayout extends StatelessWidget {
|
|
const OkaneNavigationLayout({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final screenSize = getScreenSize(context);
|
|
return BlocBuilder<CoreCubit, CoreState>(
|
|
builder:
|
|
(_, state) => IndexedStack(
|
|
index: _pages.indexWhere((p) => p.page == state.activePage),
|
|
children:
|
|
_pages
|
|
.map(
|
|
(p) => switch (screenSize) {
|
|
ScreenSize.small => Column(
|
|
children: [
|
|
SizedBox(
|
|
height: 50,
|
|
child: Padding(
|
|
padding: EdgeInsets.all(8),
|
|
child: Row(
|
|
children: [
|
|
IconButton(
|
|
icon: Icon(Icons.menu),
|
|
onPressed: () {
|
|
Scaffold.of(context).openDrawer();
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
Expanded(child: p.child),
|
|
],
|
|
),
|
|
ScreenSize.normal =>
|
|
p.details != null
|
|
? Row(
|
|
children: [
|
|
Expanded(child: p.child),
|
|
Expanded(child: p.details!(false)),
|
|
],
|
|
)
|
|
: p.child,
|
|
},
|
|
)
|
|
.toList(),
|
|
),
|
|
);
|
|
}
|
|
}
|