okane/lib/ui/navigation.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(),
),
);
}
}