From ae1293d28d0b7c3f97b389822b3065c11d3c4b8a Mon Sep 17 00:00:00 2001 From: efrilm Date: Tue, 12 Aug 2025 17:36:41 +0700 Subject: [PATCH] feat: main page --- lib/common/theme/theme.dart | 13 ++ .../pages/auth/login/login_page.dart | 3 + lib/presentation/pages/home/home_page.dart | 12 ++ lib/presentation/pages/main/main_page.dart | 27 ++++ .../pages/main/widgets/bottom_navbar.dart | 50 ++++++++ .../pages/profile/profile_page.dart | 12 ++ .../pages/report/report_page.dart | 12 ++ .../pages/transaction/transaction_page.dart | 12 ++ lib/presentation/router/app_router.dart | 11 ++ lib/presentation/router/app_router.gr.dart | 116 ++++++++++++++++-- 10 files changed, 255 insertions(+), 13 deletions(-) create mode 100644 lib/presentation/pages/home/home_page.dart create mode 100644 lib/presentation/pages/main/main_page.dart create mode 100644 lib/presentation/pages/main/widgets/bottom_navbar.dart create mode 100644 lib/presentation/pages/profile/profile_page.dart create mode 100644 lib/presentation/pages/report/report_page.dart create mode 100644 lib/presentation/pages/transaction/transaction_page.dart diff --git a/lib/common/theme/theme.dart b/lib/common/theme/theme.dart index 0eb846f..f8c9585 100644 --- a/lib/common/theme/theme.dart +++ b/lib/common/theme/theme.dart @@ -42,5 +42,18 @@ class ThemeApp { ), ), ), + bottomNavigationBarTheme: BottomNavigationBarThemeData( + backgroundColor: AppColor.background, + selectedItemColor: AppColor.primary, + unselectedItemColor: AppColor.textSecondary, + selectedLabelStyle: AppStyle.md.copyWith( + color: AppColor.primary, + fontWeight: FontWeight.w600, + ), + unselectedLabelStyle: AppStyle.md.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), ); } diff --git a/lib/presentation/pages/auth/login/login_page.dart b/lib/presentation/pages/auth/login/login_page.dart index 7495a14..4d487fa 100644 --- a/lib/presentation/pages/auth/login/login_page.dart +++ b/lib/presentation/pages/auth/login/login_page.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import '../../../../common/theme/theme.dart'; import '../../../components/button/button.dart'; import '../../../components/spacer/spacer.dart'; +import '../../../router/app_router.gr.dart'; import 'widgets/email_field.dart'; import 'widgets/password_field.dart'; @@ -76,6 +77,8 @@ class _LoginPageState extends State with TickerProviderStateMixin { setState(() { _isLoading = false; }); + + context.router.replace(const MainRoute()); } } diff --git a/lib/presentation/pages/home/home_page.dart b/lib/presentation/pages/home/home_page.dart new file mode 100644 index 0000000..7e4b3ad --- /dev/null +++ b/lib/presentation/pages/home/home_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class HomePage extends StatelessWidget { + const HomePage({super.key}); + + @override + Widget build(BuildContext context) { + return Center(child: Text('HomePage')); + } +} diff --git a/lib/presentation/pages/main/main_page.dart b/lib/presentation/pages/main/main_page.dart new file mode 100644 index 0000000..6232fc7 --- /dev/null +++ b/lib/presentation/pages/main/main_page.dart @@ -0,0 +1,27 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +import '../../router/app_router.gr.dart'; +import 'widgets/bottom_navbar.dart'; + +@RoutePage() +class MainPage extends StatelessWidget { + const MainPage({super.key}); + + @override + Widget build(BuildContext context) { + return AutoTabsRouter.pageView( + routes: [HomeRoute(), TransactionRoute(), ReportRoute(), ProfileRoute()], + physics: const NeverScrollableScrollPhysics(), + builder: (context, child, pageController) { + final tabsRouter = AutoTabsRouter.of(context); + + return Scaffold( + resizeToAvoidBottomInset: false, + body: child, + bottomNavigationBar: MainBottomNavbar(tabsRouter: tabsRouter), + ); + }, + ); + } +} diff --git a/lib/presentation/pages/main/widgets/bottom_navbar.dart b/lib/presentation/pages/main/widgets/bottom_navbar.dart new file mode 100644 index 0000000..0749a45 --- /dev/null +++ b/lib/presentation/pages/main/widgets/bottom_navbar.dart @@ -0,0 +1,50 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:line_icons/line_icon.dart'; +import 'package:line_icons/line_icons.dart'; + +class MainBottomNavbar extends StatefulWidget { + final TabsRouter tabsRouter; + + const MainBottomNavbar({super.key, required this.tabsRouter}); + + @override + State createState() => _MainBottomNavbarState(); +} + +class _MainBottomNavbarState extends State { + @override + Widget build(BuildContext context) { + return BottomNavigationBar( + currentIndex: widget.tabsRouter.activeIndex, + onTap: (index) { + setState(() { + widget.tabsRouter.setActiveIndex(index); + }); + }, + type: BottomNavigationBarType.fixed, + items: [ + BottomNavigationBarItem( + icon: LineIcon(LineIcons.home), + label: 'Home', + tooltip: 'Home', + ), + BottomNavigationBarItem( + icon: LineIcon(LineIcons.moneyBill), + label: 'Transaction', + tooltip: 'Transaction', + ), + BottomNavigationBarItem( + icon: LineIcon(LineIcons.barChart), + label: 'Report', + tooltip: 'Report', + ), + BottomNavigationBarItem( + icon: LineIcon(LineIcons.user), + label: 'Profile', + tooltip: 'Profile', + ), + ], + ); + } +} diff --git a/lib/presentation/pages/profile/profile_page.dart b/lib/presentation/pages/profile/profile_page.dart new file mode 100644 index 0000000..0b5054b --- /dev/null +++ b/lib/presentation/pages/profile/profile_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class ProfilePage extends StatelessWidget { + const ProfilePage({super.key}); + + @override + Widget build(BuildContext context) { + return Center(child: Text('ProfilePage')); + } +} diff --git a/lib/presentation/pages/report/report_page.dart b/lib/presentation/pages/report/report_page.dart new file mode 100644 index 0000000..da379df --- /dev/null +++ b/lib/presentation/pages/report/report_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class ReportPage extends StatelessWidget { + const ReportPage({super.key}); + + @override + Widget build(BuildContext context) { + return Center(child: Text('ReportPage')); + } +} diff --git a/lib/presentation/pages/transaction/transaction_page.dart b/lib/presentation/pages/transaction/transaction_page.dart new file mode 100644 index 0000000..dd46d95 --- /dev/null +++ b/lib/presentation/pages/transaction/transaction_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class TransactionPage extends StatelessWidget { + const TransactionPage({super.key}); + + @override + Widget build(BuildContext context) { + return Center(child: Text('TransactionPage')); + } +} diff --git a/lib/presentation/router/app_router.dart b/lib/presentation/router/app_router.dart index 7affb17..57f4892 100644 --- a/lib/presentation/router/app_router.dart +++ b/lib/presentation/router/app_router.dart @@ -10,5 +10,16 @@ class AppRouter extends RootStackRouter { // Auth AutoRoute(page: LoginRoute.page), + + // Main + AutoRoute( + page: MainRoute.page, + children: [ + AutoRoute(page: HomeRoute.page), + AutoRoute(page: TransactionRoute.page), + AutoRoute(page: ReportRoute.page), + AutoRoute(page: ProfileRoute.page), + ], + ), ]; } diff --git a/lib/presentation/router/app_router.gr.dart b/lib/presentation/router/app_router.gr.dart index f55f644..2972cc6 100644 --- a/lib/presentation/router/app_router.gr.dart +++ b/lib/presentation/router/app_router.gr.dart @@ -10,39 +10,129 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:apskel_owner_flutter/presentation/pages/auth/login/login_page.dart' - as _i1; -import 'package:apskel_owner_flutter/presentation/pages/splash/splash_page.dart' as _i2; -import 'package:auto_route/auto_route.dart' as _i3; +import 'package:apskel_owner_flutter/presentation/pages/home/home_page.dart' + as _i1; +import 'package:apskel_owner_flutter/presentation/pages/main/main_page.dart' + as _i3; +import 'package:apskel_owner_flutter/presentation/pages/profile/profile_page.dart' + as _i4; +import 'package:apskel_owner_flutter/presentation/pages/report/report_page.dart' + as _i5; +import 'package:apskel_owner_flutter/presentation/pages/splash/splash_page.dart' + as _i6; +import 'package:apskel_owner_flutter/presentation/pages/transaction/transaction_page.dart' + as _i7; +import 'package:auto_route/auto_route.dart' as _i8; /// generated route for -/// [_i1.LoginPage] -class LoginRoute extends _i3.PageRouteInfo { - const LoginRoute({List<_i3.PageRouteInfo>? children}) +/// [_i1.HomePage] +class HomeRoute extends _i8.PageRouteInfo { + const HomeRoute({List<_i8.PageRouteInfo>? children}) + : super(HomeRoute.name, initialChildren: children); + + static const String name = 'HomeRoute'; + + static _i8.PageInfo page = _i8.PageInfo( + name, + builder: (data) { + return const _i1.HomePage(); + }, + ); +} + +/// generated route for +/// [_i2.LoginPage] +class LoginRoute extends _i8.PageRouteInfo { + const LoginRoute({List<_i8.PageRouteInfo>? children}) : super(LoginRoute.name, initialChildren: children); static const String name = 'LoginRoute'; - static _i3.PageInfo page = _i3.PageInfo( + static _i8.PageInfo page = _i8.PageInfo( name, builder: (data) { - return const _i1.LoginPage(); + return const _i2.LoginPage(); }, ); } /// generated route for -/// [_i2.SplashPage] -class SplashRoute extends _i3.PageRouteInfo { - const SplashRoute({List<_i3.PageRouteInfo>? children}) +/// [_i3.MainPage] +class MainRoute extends _i8.PageRouteInfo { + const MainRoute({List<_i8.PageRouteInfo>? children}) + : super(MainRoute.name, initialChildren: children); + + static const String name = 'MainRoute'; + + static _i8.PageInfo page = _i8.PageInfo( + name, + builder: (data) { + return const _i3.MainPage(); + }, + ); +} + +/// generated route for +/// [_i4.ProfilePage] +class ProfileRoute extends _i8.PageRouteInfo { + const ProfileRoute({List<_i8.PageRouteInfo>? children}) + : super(ProfileRoute.name, initialChildren: children); + + static const String name = 'ProfileRoute'; + + static _i8.PageInfo page = _i8.PageInfo( + name, + builder: (data) { + return const _i4.ProfilePage(); + }, + ); +} + +/// generated route for +/// [_i5.ReportPage] +class ReportRoute extends _i8.PageRouteInfo { + const ReportRoute({List<_i8.PageRouteInfo>? children}) + : super(ReportRoute.name, initialChildren: children); + + static const String name = 'ReportRoute'; + + static _i8.PageInfo page = _i8.PageInfo( + name, + builder: (data) { + return const _i5.ReportPage(); + }, + ); +} + +/// generated route for +/// [_i6.SplashPage] +class SplashRoute extends _i8.PageRouteInfo { + const SplashRoute({List<_i8.PageRouteInfo>? children}) : super(SplashRoute.name, initialChildren: children); static const String name = 'SplashRoute'; - static _i3.PageInfo page = _i3.PageInfo( + static _i8.PageInfo page = _i8.PageInfo( name, builder: (data) { - return const _i2.SplashPage(); + return const _i6.SplashPage(); + }, + ); +} + +/// generated route for +/// [_i7.TransactionPage] +class TransactionRoute extends _i8.PageRouteInfo { + const TransactionRoute({List<_i8.PageRouteInfo>? children}) + : super(TransactionRoute.name, initialChildren: children); + + static const String name = 'TransactionRoute'; + + static _i8.PageInfo page = _i8.PageInfo( + name, + builder: (data) { + return const _i7.TransactionPage(); }, ); }