This commit is contained in:
efrilm
2025-11-10 17:23:26 +07:00
parent 0a8f8d93bb
commit b2b2e2b111
12 changed files with 625 additions and 98 deletions
+2
View File
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../application/auth/auth_bloc.dart';
import '../application/auth/logout/logout_bloc.dart';
import '../application/category/category_loader/category_loader_bloc.dart';
import '../application/checkout/checkout_form/checkout_form_bloc.dart';
import '../application/customer/customer_loader/customer_loader_bloc.dart';
@@ -57,6 +58,7 @@ class _AppWidgetState extends State<AppWidget> {
BlocProvider(create: (context) => getIt<PrinterLoaderBloc>()),
BlocProvider(create: (context) => getIt<PrintStruckBloc>()),
BlocProvider(create: (context) => getIt<SyncSettingBloc>()),
BlocProvider(create: (context) => getIt<LogoutBloc>()),
],
child: MaterialApp.router(
debugShowCheckedModeBanner: false,
@@ -0,0 +1,57 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../application/auth/logout/logout_bloc.dart';
import '../../../common/theme/theme.dart';
import '../button/button.dart';
import '../spaces/space.dart';
import 'dialog.dart';
class LogoutModalDialog extends StatelessWidget {
const LogoutModalDialog({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<LogoutBloc, LogoutState>(
builder: (context, state) {
return CustomModalDialog(
title: 'Konfirmasi',
contentPadding: EdgeInsets.all(16),
bottom: Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: AppElevatedButton.outlined(
onPressed: () => context.maybePop(),
label: 'Batal',
),
),
SpaceWidth(12),
Expanded(
child: AppElevatedButton.filled(
onPressed: state.isLoggingOut
? null
: () {
context.read<LogoutBloc>().add(
const LogoutEvent.logout(),
);
context.maybePop();
},
label: 'Ya',
isLoading: state.isLoggingOut,
),
),
],
),
),
child: Text(
'Apakah anda yakin ingin keluar?',
style: AppStyle.lg.copyWith(fontWeight: FontWeight.w600),
),
);
},
);
}
}
+135 -98
View File
@@ -1,8 +1,12 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../application/auth/logout/logout_bloc.dart';
import '../../../common/theme/theme.dart';
import '../../components/assets/assets.gen.dart';
import '../../components/dialog/logout_modal_dialog.dart';
import '../../components/toast/flushbar.dart';
import '../../router/app_router.gr.dart';
@RoutePage()
@@ -11,107 +15,140 @@ class MainPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return AutoTabsRouter(
routes: [
HomeRoute(),
TableRoute(),
ReportRoute(),
CustomerRoute(),
SettingRoute(),
],
builder: (context, child) {
final tabsRouter = AutoTabsRouter.of(context);
return Scaffold(
body: Row(
children: [
NavigationRail(
selectedIndex: tabsRouter.activeIndex,
onDestinationSelected: tabsRouter.setActiveIndex,
labelType: NavigationRailLabelType.none,
backgroundColor: AppColor.primary,
selectedIconTheme: const IconThemeData(color: Colors.white),
indicatorColor: AppColor.disabled.withOpacity(0.25),
indicatorShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
minExtendedWidth: 56,
leading: Padding(
padding: EdgeInsets.all(8.0),
child: Assets.images.logoWhite.image(
width: 40,
height: 40,
fit: BoxFit.contain,
),
),
trailing: Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.only(bottom: 16.0),
child: IconButton(
icon: const Icon(
Icons.logout,
color: AppColor.disabled,
),
onPressed: () {},
tooltip: 'Logout',
),
),
),
),
destinations: const [
NavigationRailDestination(
icon: Icon(Icons.home_outlined, color: AppColor.disabled),
selectedIcon: Icon(Icons.home, color: AppColor.white),
label: Text('POS'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
icon: Icon(
Icons.table_bar_outlined,
color: AppColor.disabled,
),
selectedIcon: Icon(Icons.table_bar, color: AppColor.white),
label: Text('Meja'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
icon: Icon(
Icons.pie_chart_outline_outlined,
color: AppColor.disabled,
),
selectedIcon: Icon(Icons.pie_chart, color: AppColor.white),
label: Text('Laporan'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
icon: Icon(
Icons.person_2_outlined,
color: AppColor.disabled,
),
selectedIcon: Icon(Icons.person_2, color: AppColor.white),
label: Text('Pelanggan'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
icon: Icon(
Icons.settings_outlined,
color: AppColor.disabled,
),
selectedIcon: Icon(Icons.settings, color: AppColor.white),
label: Text('Pengaturan'),
padding: EdgeInsets.symmetric(vertical: 8),
),
],
),
const VerticalDivider(thickness: 1, width: 1),
// Main content area
Expanded(child: child),
],
return BlocListener<LogoutBloc, LogoutState>(
listenWhen: (p, c) =>
p.logoutFailureOrSuccess != c.logoutFailureOrSuccess,
listener: (context, state) {
state.logoutFailureOrSuccess.fold(
() => null,
(either) => either.fold(
(f) {
AppFlushbar.showAuthFailureToast(context, f);
if (context.mounted) {
context.router.replaceAll([const LoginRoute()]);
}
},
(_) {
if (context.mounted) {
context.router.replaceAll([const LoginRoute()]);
}
},
),
);
},
child: AutoTabsRouter(
routes: [
HomeRoute(),
TableRoute(),
ReportRoute(),
CustomerRoute(),
SettingRoute(),
],
builder: (context, child) {
final tabsRouter = AutoTabsRouter.of(context);
return Scaffold(
body: Row(
children: [
NavigationRail(
selectedIndex: tabsRouter.activeIndex,
onDestinationSelected: tabsRouter.setActiveIndex,
labelType: NavigationRailLabelType.none,
backgroundColor: AppColor.primary,
selectedIconTheme: const IconThemeData(color: Colors.white),
indicatorColor: AppColor.disabled.withOpacity(0.25),
indicatorShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
minExtendedWidth: 56,
leading: Padding(
padding: EdgeInsets.all(8.0),
child: Assets.images.logoWhite.image(
width: 40,
height: 40,
fit: BoxFit.contain,
),
),
trailing: Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.only(bottom: 16.0),
child: IconButton(
icon: const Icon(
Icons.logout,
color: AppColor.disabled,
),
onPressed: () {
showDialog(
context: context,
builder: (context) => LogoutModalDialog(),
);
},
tooltip: 'Logout',
),
),
),
),
destinations: const [
NavigationRailDestination(
icon: Icon(Icons.home_outlined, color: AppColor.disabled),
selectedIcon: Icon(Icons.home, color: AppColor.white),
label: Text('POS'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
icon: Icon(
Icons.table_bar_outlined,
color: AppColor.disabled,
),
selectedIcon: Icon(
Icons.table_bar,
color: AppColor.white,
),
label: Text('Meja'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
icon: Icon(
Icons.pie_chart_outline_outlined,
color: AppColor.disabled,
),
selectedIcon: Icon(
Icons.pie_chart,
color: AppColor.white,
),
label: Text('Laporan'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
icon: Icon(
Icons.person_2_outlined,
color: AppColor.disabled,
),
selectedIcon: Icon(Icons.person_2, color: AppColor.white),
label: Text('Pelanggan'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
icon: Icon(
Icons.settings_outlined,
color: AppColor.disabled,
),
selectedIcon: Icon(Icons.settings, color: AppColor.white),
label: Text('Pengaturan'),
padding: EdgeInsets.symmetric(vertical: 8),
),
],
),
const VerticalDivider(thickness: 1, width: 1),
// Main content area
Expanded(child: child),
],
),
);
},
),
);
}
}