import 'package:flutter_lucide/flutter_lucide.dart'; import 'package:marco/controller/layout/layout_controller.dart'; import 'package:marco/helpers/theme/admin_theme.dart'; import 'package:marco/helpers/theme/app_theme.dart'; import 'package:marco/helpers/theme/theme_customizer.dart'; import 'package:marco/helpers/widgets/my_button.dart'; import 'package:marco/helpers/widgets/my_container.dart'; import 'package:marco/helpers/widgets/my_dashed_divider.dart'; import 'package:marco/helpers/widgets/my_responsive.dart'; import 'package:marco/helpers/widgets/my_spacing.dart'; import 'package:marco/helpers/widgets/my_text.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:marco/view/layouts/left_bar.dart'; import 'package:marco/view/layouts/right_bar.dart'; import 'package:marco/view/layouts/top_bar.dart'; import 'package:marco/widgets/custom_pop_menu.dart'; import 'package:marco/helpers/services/storage/local_storage.dart'; import 'package:marco/model/employee_info.dart'; import 'package:marco/helpers/widgets/avatar.dart'; import 'package:marco/helpers/services/api_endpoints.dart'; class Layout extends StatelessWidget { final Widget? child; final Widget? floatingActionButton; final LayoutController controller = LayoutController(); final topBarTheme = AdminTheme.theme.topBarTheme; final contentTheme = AdminTheme.theme.contentTheme; final EmployeeInfo? employeeInfo = LocalStorage.getEmployeeInfo(); Layout({super.key, this.child, this.floatingActionButton}); bool get isBetaEnvironment => ApiEndpoints.baseUrl.contains("stage"); @override Widget build(BuildContext context) { return MyResponsive(builder: (BuildContext context, _, screenMT) { return GetBuilder( init: controller, builder: (controller) { if (screenMT.isMobile || screenMT.isTablet) { return mobileScreen(); } else { return largeScreen(); } }); }); } Widget mobileScreen() { return Scaffold( key: controller.scaffoldKey, appBar: AppBar( elevation: 0, actions: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MySpacing.width(6), if (isBetaEnvironment) Padding( padding: const EdgeInsets.symmetric( vertical: 17.0, horizontal: 8.0), child: Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.blueAccent, borderRadius: BorderRadius.circular(4), ), child: Text( 'BETA', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 12, ), ), ), ), ], ), MySpacing.width(6), InkWell( onTap: () { Get.toNamed('/dashboard'); }, borderRadius: BorderRadius.circular(6), splashColor: contentTheme.primary.withAlpha(20), child: Padding( padding: MySpacing.xy(8, 8), child: Icon( LucideIcons.layout_dashboard, size: 18, color: Colors.blueAccent, ), ), ), MySpacing.width(8), CustomPopupMenu( backdrop: true, onChange: (_) {}, offsetX: -180, menu: Padding( padding: MySpacing.xy(8, 8), child: Center( child: Icon( LucideIcons.bell, size: 18, ), ), ), menuBuilder: (_) => buildNotifications(), ), MySpacing.width(8), CustomPopupMenu( backdrop: true, onChange: (_) {}, offsetX: -90, offsetY: 0, menu: Padding( padding: MySpacing.xy(0, 8), child: MyContainer.rounded( paddingAll: 0, child: Avatar( firstName: employeeInfo?.firstName ?? 'First', lastName: employeeInfo?.lastName ?? 'Name', ), ), ), menuBuilder: (_) => buildAccountMenu(), ), MySpacing.width(20) ], ), drawer: LeftBar(), floatingActionButton: floatingActionButton, body: SingleChildScrollView( key: controller.scrollKey, child: child, ), ); } Widget largeScreen() { return Scaffold( key: controller.scaffoldKey, endDrawer: RightBar(), floatingActionButton: floatingActionButton, body: Row( children: [ LeftBar(isCondensed: ThemeCustomizer.instance.leftBarCondensed), Expanded( child: Stack( children: [ Positioned( top: 0, right: 0, left: 0, bottom: 0, child: SingleChildScrollView( padding: MySpacing.fromLTRB(0, 58 + flexSpacing, 0, flexSpacing), key: controller.scrollKey, child: child, ), ), Positioned(top: 0, left: 0, right: 0, child: TopBar()), ], ), ), ], ), ); } Widget buildNotifications() { Widget buildNotification(String title, String description) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.labelLarge(title), MySpacing.height(4), MyText.bodySmall(description) ], ); } return MyContainer.bordered( paddingAll: 0, width: 250, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: MySpacing.xy(16, 12), child: MyText.titleMedium("Notification", fontWeight: 600), ), MyDashedDivider( height: 1, color: theme.dividerColor, dashSpace: 4, dashWidth: 6), Padding( padding: MySpacing.xy(16, 12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ buildNotification("Welcome to Marco", "Welcome to Marco, we are glad to have you here"), MySpacing.height(12), buildNotification("New update available", "There is a new update available for your app"), ], ), ), MyDashedDivider( height: 1, color: theme.dividerColor, dashSpace: 4, dashWidth: 6), Padding( padding: MySpacing.xy(16, 0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ MyButton.text( onPressed: () {}, splashColor: contentTheme.primary.withAlpha(28), child: MyText.labelSmall( "View All", color: contentTheme.primary, ), ), MyButton.text( onPressed: () {}, splashColor: contentTheme.danger.withAlpha(28), child: MyText.labelSmall( "Clear", color: contentTheme.danger, ), ), ], ), ) ], ), ); } Widget buildAccountMenu() { return MyContainer.bordered( paddingAll: 0, width: 150, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: MySpacing.xy(8, 8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyButton( onPressed:null, tapTargetSize: MaterialTapTargetSize.shrinkWrap, borderRadiusAll: AppStyle.buttonRadius.medium, padding: MySpacing.xy(8, 4), splashColor: contentTheme.onBackground.withAlpha(20), backgroundColor: const Color.fromARGB(0, 220, 218, 218), child: Row( children: [ Icon( LucideIcons.user, size: 14, color: contentTheme.onBackground, ), MySpacing.width(8), MyText.labelMedium( "My Account", fontWeight: 600, ) ], ), ), MySpacing.height(4), MyButton( tapTargetSize: MaterialTapTargetSize.shrinkWrap, onPressed:null, borderRadiusAll: AppStyle.buttonRadius.medium, padding: MySpacing.xy(8, 4), splashColor: contentTheme.onBackground.withAlpha(20), backgroundColor: const Color.fromARGB(0, 220, 218, 218), child: Row( children: [ Icon( LucideIcons.settings, size: 14, color: contentTheme.onBackground, ), MySpacing.width(8), MyText.labelMedium( "Settings", fontWeight: 600, ) ], ), ), MyButton( tapTargetSize: MaterialTapTargetSize.shrinkWrap, onPressed: () async { await LocalStorage.logout(); }, borderRadiusAll: AppStyle.buttonRadius.medium, padding: MySpacing.xy(8, 4), splashColor: contentTheme.onBackground.withAlpha(20), backgroundColor: Colors.transparent, child: Row( children: [ Icon( LucideIcons.log_out, size: 14, color: contentTheme.onBackground, ), MySpacing.width(8), MyText.labelMedium( "Logout", fontWeight: 600, ) ], ), ), ], ), ), Divider( height: 1, thickness: 1, ), ], ), ); } }