From e514373c33e1ccd1a69e90183922354e0b88085b Mon Sep 17 00:00:00 2001 From: freenorm Date: Thu, 24 Oct 2024 12:56:09 +0200 Subject: [PATCH 1/2] first commit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9b418011..dccf4abe 100644 --- a/README.md +++ b/README.md @@ -25,3 +25,4 @@ This flutter dashboard library is versatile; it's tailored to work seamlessly on ![Preview](/gif.gif) ![App UI](/ui.png) +# mbooke_web_source_code From c4b049a3d77b27655201803406fa49d6551053bd Mon Sep 17 00:00:00 2001 From: freenorm Date: Thu, 24 Oct 2024 12:56:56 +0200 Subject: [PATCH 2/2] first site --- assets/images/app.jpeg | Bin 0 -> 48802 bytes .../home_navigation_controller.dart | 16 + lib/controllers/menu_app_controller.dart | 24 +- lib/main.dart | 29 +- lib/models/my_files.dart | 24 +- lib/models/recent_file.dart | 55 +- lib/screens/authentication/bottom_text.dart | 20 + lib/screens/authentication/button.dart | 22 + lib/screens/authentication/content.dart | 2 + lib/screens/authentication/desktop.dart | 143 +++++ lib/screens/authentication/login.dart | 39 ++ lib/screens/authentication/mobile.dart | 99 ++++ lib/screens/authentication/mobile_menu.dart | 54 ++ .../authentication/mobile_top_bar.dart | 18 + lib/screens/authentication/nav_bar.dart | 503 ++++++++++++++++++ .../authentication/responsive_widget.dart | 43 ++ lib/screens/authentication/style.dart | 5 + lib/screens/dashboard/bookings_screen.dart | 32 ++ .../dashboard/components/bookings.dart | 229 ++++++++ lib/screens/dashboard/components/chart.dart | 6 +- .../dashboard/components/closed_bookings.dart | 0 .../dashboard/components/file_info_card.dart | 2 +- lib/screens/dashboard/components/header.dart | 12 +- .../dashboard/components/my_fields.dart | 2 +- .../dashboard/components/my_files.dart | 2 +- .../components/processed_bookings.dart | 198 +++++++ .../dashboard/components/recent_files.dart | 15 +- .../dashboard/components/storage_details.dart | 13 +- lib/screens/main/components/side_menu.dart | 78 ++- lib/screens/main/main_screen.dart | 16 +- pubspec.lock | 26 +- pubspec.yaml | 2 +- 32 files changed, 1611 insertions(+), 118 deletions(-) create mode 100644 assets/images/app.jpeg create mode 100644 lib/controllers/home_navigation_controller.dart create mode 100644 lib/screens/authentication/bottom_text.dart create mode 100644 lib/screens/authentication/button.dart create mode 100644 lib/screens/authentication/content.dart create mode 100644 lib/screens/authentication/desktop.dart create mode 100644 lib/screens/authentication/login.dart create mode 100644 lib/screens/authentication/mobile.dart create mode 100644 lib/screens/authentication/mobile_menu.dart create mode 100644 lib/screens/authentication/mobile_top_bar.dart create mode 100644 lib/screens/authentication/nav_bar.dart create mode 100644 lib/screens/authentication/responsive_widget.dart create mode 100644 lib/screens/authentication/style.dart create mode 100644 lib/screens/dashboard/bookings_screen.dart create mode 100644 lib/screens/dashboard/components/bookings.dart create mode 100644 lib/screens/dashboard/components/closed_bookings.dart create mode 100644 lib/screens/dashboard/components/processed_bookings.dart diff --git a/assets/images/app.jpeg b/assets/images/app.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..e5ca46735cc211a77290e65c8e12827ade219ad2 GIT binary patch literal 48802 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Ðvpj5a&BN%h5BTHF@y9QnU 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 literal 0 HcmV?d00001 diff --git a/lib/controllers/home_navigation_controller.dart b/lib/controllers/home_navigation_controller.dart new file mode 100644 index 00000000..e9c52b1f --- /dev/null +++ b/lib/controllers/home_navigation_controller.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; + +class HomeNavigationController extends ChangeNotifier { + int _screenNumber = 0; // Initialize to zero by default + + // Getter for screenNumber + int get screenNumber => _screenNumber; + + // Setter for screenNumber + set screenNumber(int value) { + if (_screenNumber != value) { + _screenNumber = value; + notifyListeners(); // Notify listeners when the value changes + } + } +} diff --git a/lib/controllers/menu_app_controller.dart b/lib/controllers/menu_app_controller.dart index 7e966279..4ace7784 100644 --- a/lib/controllers/menu_app_controller.dart +++ b/lib/controllers/menu_app_controller.dart @@ -1,13 +1,27 @@ +// menu_app_controller.dart + +import 'package:admin/screens/dashboard/bookings_screen.dart'; import 'package:flutter/material.dart'; +import 'package:admin/screens/dashboard/dashboard_screen.dart'; + +class MenuAppController with ChangeNotifier { + final GlobalKey scaffoldKey = GlobalKey(); -class MenuAppController extends ChangeNotifier { - final GlobalKey _scaffoldKey = GlobalKey(); + // Initialize currentScreen to your default screen + Widget currentScreen = BookingsScreen(); - GlobalKey get scaffoldKey => _scaffoldKey; + //DashboardScreen(); + + // Method to change the screen + void changeScreen(Widget screen) { + currentScreen = screen; + notifyListeners(); // Notify listeners to rebuild widgets + } + // Existing method to control the menu void controlMenu() { - if (!_scaffoldKey.currentState!.isDrawerOpen) { - _scaffoldKey.currentState!.openDrawer(); + if (!scaffoldKey.currentState!.isDrawerOpen) { + scaffoldKey.currentState!.openDrawer(); } } } diff --git a/lib/main.dart b/lib/main.dart index ad6dead9..d33513d1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,12 +1,25 @@ import 'package:admin/constants.dart'; +import 'package:admin/controllers/home_navigation_controller.dart'; import 'package:admin/controllers/menu_app_controller.dart'; +import 'package:admin/screens/authentication/login.dart'; import 'package:admin/screens/main/main_screen.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; void main() { - runApp(MyApp()); + runApp(MultiProvider(providers: [ + + + + + ChangeNotifierProvider( + create: (_) => HomeNavigationController(),), + + ChangeNotifierProvider( + create: (context) => MenuAppController(), + ), + ], child: MyApp())); } class MyApp extends StatelessWidget { @@ -22,14 +35,12 @@ class MyApp extends StatelessWidget { .apply(bodyColor: Colors.white), canvasColor: secondaryColor, ), - home: MultiProvider( - providers: [ - ChangeNotifierProvider( - create: (context) => MenuAppController(), - ), - ], - child: MainScreen(), - ), + initialRoute: '/', + routes: { + '/': (context) => HomePage(), + '/home': (context) => MainScreen() + }, + ); } } diff --git a/lib/models/my_files.dart b/lib/models/my_files.dart index b3df1aed..789ee713 100644 --- a/lib/models/my_files.dart +++ b/lib/models/my_files.dart @@ -18,34 +18,34 @@ class CloudStorageInfo { List demoMyFiles = [ CloudStorageInfo( - title: "Documents", - numOfFiles: 1328, + title: "Visits", + numOfFiles: 20, svgSrc: "assets/icons/Documents.svg", - totalStorage: "1.9GB", + totalStorage: "12/07/2024", color: primaryColor, percentage: 35, ), CloudStorageInfo( - title: "Google Drive", - numOfFiles: 1328, + title: "Booked", + numOfFiles: 15, svgSrc: "assets/icons/google_drive.svg", - totalStorage: "2.9GB", + totalStorage: "12/07/24", color: Color(0xFFFFA113), percentage: 35, ), CloudStorageInfo( - title: "One Drive", - numOfFiles: 1328, + title: "Pending bookings", + numOfFiles: 5, svgSrc: "assets/icons/one_drive.svg", - totalStorage: "1GB", + totalStorage: "12/07/24", color: Color(0xFFA4CDFF), percentage: 10, ), CloudStorageInfo( - title: "Documents", - numOfFiles: 5328, + title: "Closed bookings", + numOfFiles: 10, svgSrc: "assets/icons/drop_box.svg", - totalStorage: "7.3GB", + totalStorage: "12/07/24", color: Color(0xFF007EE5), percentage: 78, ), diff --git a/lib/models/recent_file.dart b/lib/models/recent_file.dart index b7b9c799..f113c44e 100644 --- a/lib/models/recent_file.dart +++ b/lib/models/recent_file.dart @@ -1,50 +1,47 @@ +import 'package:flutter/material.dart'; + class RecentFile { - final String? icon, title, date, size; + final String? title, date, size; + final IconData? icon; RecentFile({this.icon, this.title, this.date, this.size}); } List demoRecentFiles = [ RecentFile( - icon: "assets/icons/xd_file.svg", - title: "XD File", - date: "01-03-2021", - size: "3.5mb", + title: "Brian Molwantwa", + date: "brian@gmail.com", + size: "plaiting", ), RecentFile( - icon: "assets/icons/Figma_file.svg", - title: "Figma File", - date: "27-02-2021", - size: "19.0mb", + title: "Fitzgerald Kebadire", + date: "fitzkebadire@tuta.io", + size: "plaiting", ), RecentFile( - icon: "assets/icons/doc_file.svg", - title: "Document", - date: "23-02-2021", - size: "32.5mb", + title: "Tombo Fisiwe", + date: "tombofisiwe@yahoo.com", + size: "hair cut", ), RecentFile( - icon: "assets/icons/sound_file.svg", - title: "Sound File", - date: "21-02-2021", - size: "3.5mb", + title: "Huma Babylon", + date: "humababylon@gmail.com", + size: "plaitinghair", ), RecentFile( - icon: "assets/icons/media_file.svg", - title: "Media File", - date: "23-02-2021", - size: "2.5gb", + title: "Benoni Ishmael", + date: "benoniishmail@borankana.com", + size: "haircut", ), RecentFile( - icon: "assets/icons/pdf_file.svg", - title: "Sales PDF", - date: "25-02-2021", - size: "3.5mb", + title: "Peter Piano", + date: "peterpian@killmonger.com", + size: "dreadlocks", ), RecentFile( - icon: "assets/icons/excel_file.svg", - title: "Excel File", - date: "25-02-2021", - size: "34.5mb", + + title: "Simon Bro", + date: "simonbro@yahoo.com", + size: "haircut", ), ]; diff --git a/lib/screens/authentication/bottom_text.dart b/lib/screens/authentication/bottom_text.dart new file mode 100644 index 00000000..7ae5ea95 --- /dev/null +++ b/lib/screens/authentication/bottom_text.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +class BottomText extends StatelessWidget { + final String mainText; + final String secondaryText; + + const BottomText({Key? key, required this.mainText, required this.secondaryText}) + : super(key: key); + @override + Widget build(BuildContext context) { + return RichText( + text: TextSpan(children: [ + TextSpan(text: "$mainText \n"), + TextSpan( + text: secondaryText, + style: GoogleFonts.roboto(fontSize: 16, fontWeight: FontWeight.w300)), + ], style: GoogleFonts.roboto(fontSize: 58, fontWeight: FontWeight.bold))); + } +} diff --git a/lib/screens/authentication/button.dart b/lib/screens/authentication/button.dart new file mode 100644 index 00000000..4f621c8d --- /dev/null +++ b/lib/screens/authentication/button.dart @@ -0,0 +1,22 @@ +import 'package:admin/screens/authentication/style.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +class CustomButton extends StatelessWidget { + final String text; + + const CustomButton({ Key? key, required this.text}) : super(key: key); + @override + Widget build(BuildContext context) { + return Container( + decoration: + BoxDecoration(color: active, borderRadius: BorderRadius.circular(30)), + padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 12), + child: Text( + text, + style: GoogleFonts.roboto( + fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white), + ), + ); + } +} diff --git a/lib/screens/authentication/content.dart b/lib/screens/authentication/content.dart new file mode 100644 index 00000000..cb4f7b84 --- /dev/null +++ b/lib/screens/authentication/content.dart @@ -0,0 +1,2 @@ +const mainParagraph = + "You’re more than just a photo. You have stories to tell, and passions to share, and things to talk about that are more interesting than the weather. Because you deserve what dating deserves: better."; diff --git a/lib/screens/authentication/desktop.dart b/lib/screens/authentication/desktop.dart new file mode 100644 index 00000000..48ccaa9a --- /dev/null +++ b/lib/screens/authentication/desktop.dart @@ -0,0 +1,143 @@ +import 'package:admin/screens/authentication/bottom_text.dart'; +import 'package:admin/screens/authentication/button.dart'; +import 'package:admin/screens/authentication/content.dart'; +import 'package:admin/screens/authentication/responsive_widget.dart'; +import 'package:admin/screens/authentication/style.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +class DesktopScreen extends StatelessWidget { + const DesktopScreen({ Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + var screenSize = MediaQuery.of(context).size; + return Container( + constraints: BoxConstraints(maxWidth: 1440), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: EdgeInsets.symmetric(horizontal: 40), + width: screenSize.width / 2, + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(bottom: 15), + child: Text( + "Because you deserve convinience", + style: GoogleFonts.roboto( + color: active, + fontSize: 14, + fontWeight: FontWeight.bold), + ), + ), + RichText( + text: TextSpan( + children: [ + TextSpan(text: "Get noticed for "), + TextSpan( + text: "value", + style: GoogleFonts.roboto(color: active)), + TextSpan(text: " you offer "), + TextSpan( + text: "not what", + style: GoogleFonts.roboto(color: active)), + TextSpan(text: " something."), + ], + style: GoogleFonts.roboto( + fontSize: ResponsiveWidget.isMediumScreen(context) + ? 38 + : 58, + fontWeight: FontWeight.bold))), + Visibility( + child: Text( + mainParagraph, + style: GoogleFonts.roboto( + fontSize: 20, letterSpacing: 1.5, height: 1.5), + ), + ), + SizedBox( + height: 20, + ), + Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(40), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(.1), + offset: Offset(0, 40), + blurRadius: 80) + ]), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: screenSize.width / 4, + padding: EdgeInsets.only(left: 8), + child: TextField( + decoration: InputDecoration( + icon: Icon(Icons.email_outlined), + hintText: "Enter your email", + border: InputBorder.none), + ), + ), + CustomButton( + text: "Get started", + ) + ], + ), + ), + SizedBox(height: screenSize.height / 14), + Visibility( + visible: screenSize.height > 700, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + BottomText( + mainText: "15k+", + secondaryText: "Bookings and\nhappy clients", + ), + BottomText( + mainText: "1,456", + secondaryText: "New members\nsignup every day", + ), + BottomText( + mainText: "1M+", + secondaryText: "Members from\naround the world", + ), + ], + ), + ) + ], + ), + ), + ), + Container( + decoration: BoxDecoration(borderRadius: BorderRadius.circular(10)), + width: screenSize.width / 2, + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + height: screenSize.width / 50, + ), + Image.asset( + "assets/images/app.jpeg", + width: screenSize.width / 5, + ), + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/authentication/login.dart b/lib/screens/authentication/login.dart new file mode 100644 index 00000000..b87e21bd --- /dev/null +++ b/lib/screens/authentication/login.dart @@ -0,0 +1,39 @@ +import 'package:admin/screens/authentication/desktop.dart'; +import 'package:admin/screens/authentication/mobile.dart'; +import 'package:admin/screens/authentication/mobile_menu.dart'; +import 'package:admin/screens/authentication/nav_bar.dart'; +import 'package:admin/screens/authentication/responsive_widget.dart'; +import 'package:admin/screens/authentication/style.dart'; +import 'package:flutter/material.dart'; + + + +class HomePage extends StatefulWidget { + @override + _HomePageState createState() => _HomePageState(); +} + +class _HomePageState extends State { + GlobalKey scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + var screenSize = MediaQuery.of(context).size; + return Scaffold( + key: scaffoldKey, + appBar: ResponsiveWidget.isSmallScreen(context) + ? mobileTopBar(scaffoldKey) + : PreferredSize( + preferredSize: Size(screenSize.width, 1000), + child: NavBar(), + ), + drawer: MobileMenu(), + backgroundColor: bgColor, + body: ResponsiveWidget( + largeScreen: DesktopScreen(), + smallScreen: MobileScreen(), + )); + } + + mobileTopBar(GlobalKey scaffoldKey) {} +} diff --git a/lib/screens/authentication/mobile.dart b/lib/screens/authentication/mobile.dart new file mode 100644 index 00000000..8134462d --- /dev/null +++ b/lib/screens/authentication/mobile.dart @@ -0,0 +1,99 @@ +import 'package:admin/screens/authentication/button.dart'; +import 'package:admin/screens/authentication/content.dart'; +import 'package:admin/screens/authentication/style.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +class MobileScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + var screenSize = MediaQuery.of(context).size; + + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 450, + constraints: BoxConstraints(maxWidth: 450), + margin: EdgeInsets.symmetric(horizontal: 20), + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + children: [ + TextSpan( + text: "Get noticed for ", + ), + TextSpan( + text: "who", + style: GoogleFonts.roboto(color: active)), + TextSpan( + text: " you are, ", + ), + TextSpan( + text: "not what", + style: GoogleFonts.roboto(color: active)), + TextSpan( + text: " you look like.", + ), + ], + style: GoogleFonts.roboto( + fontSize: 28, fontWeight: FontWeight.bold)), + ), + ), + ], + ), + SizedBox( + height: 20, + ), + Container( + width: 550, + constraints: BoxConstraints(maxWidth: 550), + child: Text( + mainParagraph, + textAlign: TextAlign.center, + style: GoogleFonts.roboto(letterSpacing: 1.5, height: 1.5), + ), + ), + SizedBox( + height: 20, + ), + Container( + constraints: BoxConstraints(maxWidth: 550), + padding: EdgeInsets.all(4), + margin: EdgeInsets.symmetric(horizontal: 20), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(40), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(.1), + offset: Offset(0, 40), + blurRadius: 80) + ]), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: screenSize.width / 4, + padding: EdgeInsets.only(left: 4), + child: TextField( + decoration: InputDecoration( + icon: Icon(Icons.email_outlined), + hintText: "Email", + border: InputBorder.none), + ), + ), + CustomButton( + text: "Get started", + ) + ], + ), + ), + ], + ); + } +} diff --git a/lib/screens/authentication/mobile_menu.dart b/lib/screens/authentication/mobile_menu.dart new file mode 100644 index 00000000..cf484f4c --- /dev/null +++ b/lib/screens/authentication/mobile_menu.dart @@ -0,0 +1,54 @@ +import 'package:admin/screens/authentication/style.dart'; +import 'package:flutter/material.dart'; + +class MobileMenu extends StatelessWidget { + const MobileMenu({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Drawer( + child: Container( + color: active, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + InkWell( + onTap: () {}, + child: Text( + 'Pricing', + style: TextStyle(color: Colors.white, fontSize: 22), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 5.0, bottom: 5.0), + child: Divider(), + ), + InkWell( + onTap: () {}, + child: Text( + 'Login', + style: TextStyle(color: Colors.white, fontSize: 22), + ), + ), + Expanded( + child: Align( + alignment: Alignment.bottomCenter, + child: Text( + 'Copyright © 2020 | Santos Enoque', + style: TextStyle( + color: Colors.white, + fontSize: 14, + ), + ), + ), + ) + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/authentication/mobile_top_bar.dart b/lib/screens/authentication/mobile_top_bar.dart new file mode 100644 index 00000000..6db9d5fa --- /dev/null +++ b/lib/screens/authentication/mobile_top_bar.dart @@ -0,0 +1,18 @@ +import 'package:admin/screens/authentication/style.dart'; +import 'package:flutter/material.dart'; + +Widget mobileTopBar(GlobalKey key) => AppBar( + leading: IconButton( + icon: Icon( + Icons.menu, + color: active, + ), + onPressed: () { + key.currentState?.openDrawer(); + }, + ), + title: Image.asset("assets/images/logo.png"), + centerTitle: true, + elevation: 0, + backgroundColor: bgColor, + ); diff --git a/lib/screens/authentication/nav_bar.dart b/lib/screens/authentication/nav_bar.dart new file mode 100644 index 00000000..a4285845 --- /dev/null +++ b/lib/screens/authentication/nav_bar.dart @@ -0,0 +1,503 @@ +import 'package:admin/screens/authentication/button.dart'; +import 'package:admin/screens/authentication/style.dart'; +import 'package:admin/screens/main/main_screen.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +class NavBar extends StatefulWidget { + @override + _NavBarState createState() => _NavBarState(); +} + +class _NavBarState extends State { + final List _isHovering = [false, false]; + + // Controllers for email and password fields + final TextEditingController emailController = TextEditingController(); + final TextEditingController passwordController = TextEditingController(); + + // Remember to dispose of the controllers + @override + void dispose() { + emailController.dispose(); + passwordController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var screenSize = MediaQuery.of(context).size; + + // Define 'active' and 'disable' colors if not already defined + // Replace with your desired color + final Color disable = Colors.grey; // Replace with your desired color + + return PreferredSize( + preferredSize: Size(screenSize.width, 1000), + child: Container( + // color: Colors.transparent, + child: Padding( + padding: EdgeInsets.all(20), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + width: 20, + ), + Text( + 'Mbooke', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 30, + color: active, + ), + ), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox(width: screenSize.width / 8), + // Email TextField + InkWell( + onHover: (value) { + setState(() { + value + ? _isHovering[0] = true + : _isHovering[0] = false; + }); + }, + hoverColor: Colors.transparent, + onTap: () {}, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 12, + ), + Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(7), + ), + width: screenSize.width / 5, + child: SizedBox( + height: 33, + child: TextField( + controller: emailController, + style: TextStyle(color: active, fontSize: 17), + clipBehavior: Clip.none, + decoration: InputDecoration( + contentPadding: EdgeInsets.all(0), + hintStyle: + TextStyle(color: active, fontSize: 13), + prefixIconColor: active, + prefixIcon: Icon( + Icons.email_outlined, + size: 20, + ), + counterStyle: + TextStyle(color: active, fontSize: 13), + hintText: "Email", + border: InputBorder.none, + ), + ), + ), + ), + SizedBox(height: 5), + Visibility( + maintainAnimation: true, + maintainState: true, + maintainSize: true, + visible: _isHovering[0], + child: Container( + decoration: BoxDecoration( + color: active, + borderRadius: BorderRadius.circular(20), + ), + height: 7, + width: 7, + ), + ), + ], + ), + ), + SizedBox(width: screenSize.width / 100), + // Password TextField + InkWell( + onHover: (value) { + setState(() { + value + ? _isHovering[0] = true + : _isHovering[0] = false; + }); + }, + hoverColor: Colors.transparent, + onTap: () {}, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 12, + ), + Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(7), + ), + height: 33, + width: screenSize.width / 6, + padding: EdgeInsets.only(left: 8), + child: TextField( + controller: passwordController, + style: TextStyle(color: active, fontSize: 17), + obscureText: true, + decoration: InputDecoration( + contentPadding: EdgeInsets.all(0), + hintStyle: + TextStyle(color: active, fontSize: 13), + prefixIconColor: active, + prefixIcon: Icon( + Icons.lock, + size: 20, + ), + hintText: "Password", + border: InputBorder.none, + ), + ), + ), + SizedBox(height: 5), + Visibility( + maintainAnimation: true, + maintainState: true, + maintainSize: true, + visible: _isHovering[0], + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(20), + ), + height: 7, + width: 7, + ), + ), + ], + ), + ), + SizedBox(width: screenSize.width / 50), + // Log In Button (No pop-up) + InkWell( + onHover: (value) { + setState(() { + value + ? _isHovering[1] = true + : _isHovering[1] = false; + }); + }, + hoverColor: Colors.transparent, + onTap: () { + // Perform login action or navigate to MainScreen + Navigator.pushNamed(context, '/home'); + }, + child: CustomButton(text: 'Log in'), + ), + SizedBox(width: screenSize.width / 20), + ], + ), + ), + // Register Button with Pop-up + InkWell( + onTap: () { + + + +showDialog( + context: context, + builder: (BuildContext context) { + // Use a StatefulBuilder to manage state within the dialog + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + // Controllers for the input fields + TextEditingController nameController = + TextEditingController(); + TextEditingController surnameController = + TextEditingController(); + TextEditingController companyController = + TextEditingController(); + TextEditingController registrationController = + TextEditingController(); + TextEditingController yearController = + TextEditingController(); + TextEditingController ownerNameController = + TextEditingController(); + TextEditingController ownerIdController = + TextEditingController(); + TextEditingController locationController = + TextEditingController(); + TextEditingController emailController = + TextEditingController(); + TextEditingController phoneController = + TextEditingController(); + TextEditingController sectorController = + TextEditingController(); + + return + + + Dialog( + child: Container( + width: 600, // Increase the width of the dialog + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all( + 16.0), // Increase padding for better spacing + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Title + Text( + 'Register', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold), + ), + SizedBox(height: 20), + // Row 1: Name and Surname + Row( + children: [ + Expanded( + child: TextField( + controller: nameController, + decoration: InputDecoration( + labelText: 'Name', + ), + ), + ), + SizedBox( + width: + 20), // Increase space between columns + Expanded( + child: TextField( + controller: surnameController, + decoration: InputDecoration( + labelText: 'Surname', + ), + ), + ), + ], + ), + SizedBox(height: 20), + // Row 2: Company Name and Registration Number + Row( + children: [ + Expanded( + child: TextField( + controller: companyController, + decoration: InputDecoration( + labelText: 'Company Name', + ), + ), + ), + SizedBox(width: 20), + Expanded( + child: TextField( + controller: + registrationController, + decoration: InputDecoration( + labelText: + 'Registration Number', + ), + ), + ), + ], + ), + SizedBox(height: 20), + // Row 3: Year Started and Sector + Row( + children: [ + Expanded( + child: TextField( + controller: yearController, + decoration: InputDecoration( + labelText: 'Year Started', + ), + keyboardType: + TextInputType.number, + ), + ), + SizedBox(width: 20), + Expanded( + child: TextField( + controller: sectorController, + decoration: InputDecoration( + labelText: 'Sector', + ), + ), + ), + ], + ), + SizedBox(height: 20), + // Row 4: Owner's Name and ID Card + Row( + children: [ + Expanded( + child: TextField( + controller: ownerNameController, + decoration: InputDecoration( + labelText: "Owner's Name", + ), + ), + ), + SizedBox(width: 20), + Expanded( + child: TextField( + controller: ownerIdController, + decoration: InputDecoration( + labelText: "Owner's ID Card", + ), + ), + ), + ], + ), + SizedBox(height: 20), + // Row 5: Location and Email + Row( + children: [ + Expanded( + child: TextField( + controller: locationController, + decoration: InputDecoration( + labelText: 'Location', + ), + ), + ), + SizedBox(width: 20), + Expanded( + child: TextField( + controller: emailController, + decoration: InputDecoration( + labelText: 'Email', + ), + keyboardType: + TextInputType.emailAddress, + ), + ), + ], + ), + SizedBox(height: 20), + // Row 6: Phone Number + Row( + children: [ + Expanded( + child: TextField( + controller: phoneController, + decoration: InputDecoration( + labelText: 'Phone Number', + ), + keyboardType: TextInputType.phone, + ), + ), + SizedBox(width: 20), + Expanded( + child: SizedBox + .shrink(), // Empty space to align layout + ), + ], + ), + SizedBox(height: 30), + // Actions + Row( + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + Navigator.of(context) + .pop(); // Close the dialog + }, + child: Text('Cancel'), + ), + SizedBox(width: 20), + ElevatedButton( + onPressed: () { + // Retrieve the input values + String name = + nameController.text.trim(); + String surname = + surnameController.text.trim(); + String company = + companyController.text.trim(); + String registrationNumber = + registrationController.text + .trim(); + String yearStarted = + yearController.text.trim(); + String ownerName = + ownerNameController.text + .trim(); + String ownerId = + ownerIdController.text.trim(); + String location = + locationController.text + .trim(); + String email = + emailController.text.trim(); + String phone = + phoneController.text.trim(); + String sector = + sectorController.text.trim(); + + // Perform registration logic here + // For example, validate inputs and send data to the server + + Navigator.of(context) + .pop(); // Close the dialog + // Navigate to another screen or show a success message + }, + child: Text('Proceed'), + ), + ], + ), + ], + ), + ), + ), + ), + ); + }, + ); + }, + ); + + + + + + + + + + + + + + + + + + + + + + }, + child: CustomButton( + text: "Register", + ), + ), + SizedBox(width: screenSize.width / 40), + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/authentication/responsive_widget.dart b/lib/screens/authentication/responsive_widget.dart new file mode 100644 index 00000000..c2c9b80a --- /dev/null +++ b/lib/screens/authentication/responsive_widget.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; + +class ResponsiveWidget extends StatelessWidget { + final Widget largeScreen; + // final Widget mediumScreen; + final Widget smallScreen; + + const ResponsiveWidget({ + Key? key, + required this.largeScreen, + // this.mediumScreen, + required this.smallScreen, + }) : super(key: key); + + static bool isSmallScreen(BuildContext context) { + return MediaQuery.of(context).size.width < 852; + } + + static bool isLargeScreen(BuildContext context) { + return MediaQuery.of(context).size.width > 1200; + } + + static bool isMediumScreen(BuildContext context) { + return MediaQuery.of(context).size.width >= 852 && + MediaQuery.of(context).size.width <= 1200; + } + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + if (constraints.maxWidth > 1200) { + return largeScreen; + } else if (constraints.maxWidth <= 1200 && + constraints.maxWidth >= 852) { + return largeScreen; + } else { + return smallScreen; + } + }, + ); + } +} diff --git a/lib/screens/authentication/style.dart b/lib/screens/authentication/style.dart new file mode 100644 index 00000000..3a0197b6 --- /dev/null +++ b/lib/screens/authentication/style.dart @@ -0,0 +1,5 @@ +import 'package:flutter/material.dart'; + +Color active = Color(0xff003E65); +Color disable = Color(0xFF7D8790); +Color bgColor = Colors.grey; diff --git a/lib/screens/dashboard/bookings_screen.dart b/lib/screens/dashboard/bookings_screen.dart new file mode 100644 index 00000000..a819b411 --- /dev/null +++ b/lib/screens/dashboard/bookings_screen.dart @@ -0,0 +1,32 @@ +import 'package:admin/screens/dashboard/components/bookings.dart'; +import 'package:admin/screens/dashboard/components/processed_bookings.dart'; +import 'package:admin/screens/dashboard/components/storage_details.dart'; +import 'package:flutter/material.dart'; + +class BookingsScreen extends StatelessWidget { + const BookingsScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + flex: 2, + child: Column( + children: [ + Expanded( + child: Bookings(), + ), + Divider(), + Expanded( + child: ProcessedBookings(), + ) + ], + ), + ), + + Expanded(child: StorageDetails()) + ], + ); + } +} diff --git a/lib/screens/dashboard/components/bookings.dart b/lib/screens/dashboard/components/bookings.dart new file mode 100644 index 00000000..7ae560c1 --- /dev/null +++ b/lib/screens/dashboard/components/bookings.dart @@ -0,0 +1,229 @@ +import 'package:admin/models/recent_file.dart'; + +import 'package:flutter/material.dart'; + +import '../../../constants.dart'; + +class Bookings extends StatelessWidget { + const Bookings({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.all(10), + color: Colors.white, + child: Text( + "Pending Bookings", + style: + TextStyle(color: Colors.black, fontWeight: FontWeight.bold), + //style: Theme.of(context).textTheme.titleMedium, + ), + ), + SizedBox( + width: double.infinity, + child: InkWell( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + // Use a StatefulBuilder to manage state within the dialog + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + // Controllers for the input fields + + + return Dialog( + child: Container( + width: 600, // Increase the width of the dialog + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all( + 16.0), // Increase padding for better spacing + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Title + Text( + 'Booking details', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold), + ), + SizedBox(height: 20), + // Row 1: Name and Surname + Row( + children: [ + Expanded( + child: Text('Full Name') + ), + SizedBox( + width: + 20), // Increase space between columns + Expanded( + child: Text('Thabang Dompreho') + ), + ], + ), + SizedBox(height: 20), + // Row 2: Company Name and Registration Number + Row( + children: [ + Expanded( + child: Text('Location: ') + ), + SizedBox(width: 20), + Expanded( + child: Text('Gaborone') + ), + ], + ), + SizedBox(height: 20), + // Row 3: Year Started and Sector + Row( + children: [ + Expanded( + child: Text('Service: ') + ), + SizedBox(width: 20), + Expanded( + child: Text('Hair cut') + ), + ], + ), + SizedBox(height: 20), + // Row 4: Owner's Name and ID Card + Row( + children: [ + Expanded( + child: Text('Price: ') + ), + SizedBox(width: 20), + Expanded( + child: Text('P250.00') + ), + ], + ), + SizedBox(height: 20), + // Row 5: Location and Email + Row( + children: [ + Expanded( + child: Text('Booking time:') + ), + SizedBox(width: 20), + Expanded( + child: Text('1500hrs') + ), + ], + ), + SizedBox(height: 20), + // Row 6: Phone Number + Row( + children: [ + Expanded( + child: Text('Phone number: ') + ), + SizedBox(width: 20), + Expanded(child: Text('+267 75470516')), + ], + ), + SizedBox(height: 30), + // Actions + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + Navigator.of(context) + .pop(); // Close the dialog + }, + child: Text('Cancel'), + ), + SizedBox(width: 20), + ElevatedButton( + onPressed: () { + // Retrieve the input values + + + // Perform registration logic here + // For example, validate inputs and send data to the server + + Navigator.of(context) + .pop(); // Close the dialog + // Navigate to another screen or show a success message + }, + child: Text('Process booking'), + ), + ], + ), + ], + ), + ), + ), + ), + ); + }, + ); + }, + ); + + + }, + child: DataTable( + columnSpacing: defaultPadding, + // minWidth: 600, + columns: [ + DataColumn( + label: Text("Client Name"), + ), + DataColumn( + label: Text("Email Address"), + ), + DataColumn( + label: Text("Service type"), + ), + ], + rows: List.generate( + demoRecentFiles.length, + (index) => recentFileDataRow(demoRecentFiles[index]), + ), + ), + ), + ), + ], + ), + ), + ); + } +} + +DataRow recentFileDataRow(RecentFile fileInfo) { + return DataRow( + cells: [ + DataCell( + Row( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: defaultPadding), + child: Text(fileInfo.title!), + ), + ], + ), + ), + DataCell(Text(fileInfo.date!)), + DataCell(Text(fileInfo.size!)), + ], + ); +} diff --git a/lib/screens/dashboard/components/chart.dart b/lib/screens/dashboard/components/chart.dart index 725f2224..8a41081c 100644 --- a/lib/screens/dashboard/components/chart.dart +++ b/lib/screens/dashboard/components/chart.dart @@ -28,14 +28,14 @@ class Chart extends StatelessWidget { children: [ SizedBox(height: defaultPadding), Text( - "29.1", + "40", style: Theme.of(context).textTheme.headlineMedium!.copyWith( color: Colors.white, fontWeight: FontWeight.w600, height: 0.5, ), ), - Text("of 128GB") + Text("complete") ], ), ), @@ -53,7 +53,7 @@ List paiChartSelectionData = [ radius: 25, ), PieChartSectionData( - color: Color(0xFF26E5FF), + color: Colors.yellow, value: 20, showTitle: false, radius: 22, diff --git a/lib/screens/dashboard/components/closed_bookings.dart b/lib/screens/dashboard/components/closed_bookings.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/screens/dashboard/components/file_info_card.dart b/lib/screens/dashboard/components/file_info_card.dart index 87fe6cfa..eef45232 100644 --- a/lib/screens/dashboard/components/file_info_card.dart +++ b/lib/screens/dashboard/components/file_info_card.dart @@ -57,7 +57,7 @@ class FileInfoCard extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "${info.numOfFiles} Files", + "${info.numOfFiles} People", style: Theme.of(context) .textTheme .bodySmall! diff --git a/lib/screens/dashboard/components/header.dart b/lib/screens/dashboard/components/header.dart index dad40fcb..6464b033 100644 --- a/lib/screens/dashboard/components/header.dart +++ b/lib/screens/dashboard/components/header.dart @@ -54,15 +54,17 @@ class ProfileCard extends StatelessWidget { ), child: Row( children: [ - Image.asset( - "assets/images/profile_pic.png", - height: 38, - ), + + CircleAvatar(child: Icon(Icons.person),), + // Image.asset( + // "assets/images/profile_pic.png", + // height: 38, + // ), if (!Responsive.isMobile(context)) Padding( padding: const EdgeInsets.symmetric(horizontal: defaultPadding / 2), - child: Text("Angelina Jolie"), + child: Text("Gontlefela Norman"), ), Icon(Icons.keyboard_arrow_down), ], diff --git a/lib/screens/dashboard/components/my_fields.dart b/lib/screens/dashboard/components/my_fields.dart index 25234c74..2057a1ff 100644 --- a/lib/screens/dashboard/components/my_fields.dart +++ b/lib/screens/dashboard/components/my_fields.dart @@ -19,7 +19,7 @@ class MyFiles extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "My Files", + "My menu", style: Theme.of(context).textTheme.titleMedium, ), ElevatedButton.icon( diff --git a/lib/screens/dashboard/components/my_files.dart b/lib/screens/dashboard/components/my_files.dart index 146e8504..4d503f85 100644 --- a/lib/screens/dashboard/components/my_files.dart +++ b/lib/screens/dashboard/components/my_files.dart @@ -19,7 +19,7 @@ class MyFiles extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "My Files", + "My menu", style: Theme.of(context).textTheme.titleMedium, ), ElevatedButton.icon( diff --git a/lib/screens/dashboard/components/processed_bookings.dart b/lib/screens/dashboard/components/processed_bookings.dart new file mode 100644 index 00000000..67debea5 --- /dev/null +++ b/lib/screens/dashboard/components/processed_bookings.dart @@ -0,0 +1,198 @@ +import 'package:admin/models/recent_file.dart'; + +import 'package:flutter/material.dart'; + +import '../../../constants.dart'; + +class ProcessedBookings extends StatelessWidget { + const ProcessedBookings({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(defaultPadding), + decoration: BoxDecoration( + color: secondaryColor, + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.all(10), + color: Colors.white, + child: Text( + "Processed Bookings", + style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold), + //style: Theme.of(context).textTheme.titleMedium, + ), + ), + SizedBox( + width: double.infinity, + child: InkWell( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + // Use a StatefulBuilder to manage state within the dialog + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + // Controllers for the input fields + + return Dialog( + child: Container( + width: 600, // Increase the width of the dialog + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all( + 16.0), // Increase padding for better spacing + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Title + + SizedBox(height: 20), + // Row 1: Name and Surname + Row( + children: [ + Expanded(child: Text('Full Name')), + SizedBox( + width: + 20), // Increase space between columns + Expanded( + child: Text('Thabang Dompreho')), + ], + ), + SizedBox(height: 20), + // Row 2: Company Name and Registration Number + Row( + children: [ + Expanded(child: Text('Location: ')), + SizedBox(width: 20), + Expanded(child: Text('Gaborone')), + ], + ), + SizedBox(height: 20), + // Row 3: Year Started and Sector + Row( + children: [ + Expanded(child: Text('Service: ')), + SizedBox(width: 20), + Expanded(child: Text('Hair cut')), + ], + ), + SizedBox(height: 20), + // Row 4: Owner's Name and ID Card + Row( + children: [ + Expanded(child: Text('Price: ')), + SizedBox(width: 20), + Expanded(child: Text('P250.00')), + ], + ), + SizedBox(height: 20), + // Row 5: Location and Email + Row( + children: [ + Expanded(child: Text('Booking time:')), + SizedBox(width: 20), + Expanded(child: Text('1500hrs')), + ], + ), + SizedBox(height: 20), + // Row 6: Phone Number + Row( + children: [ + Expanded(child: Text('Phone number: ')), + SizedBox(width: 20), + Expanded(child: Text('+267 75470516')), + ], + ), + SizedBox(height: 30), + // Actions + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + Navigator.of(context) + .pop(); // Close the dialog + }, + child: Text('Cancel'), + ), + SizedBox(width: 20), + ElevatedButton( + onPressed: () { + // Retrieve the input values + + // Perform registration logic here + // For example, validate inputs and send data to the server + + Navigator.of(context) + .pop(); // Close the dialog + // Navigate to another screen or show a success message + }, + child: Text('Process booking'), + ), + ], + ), + ], + ), + ), + ), + ), + ); + }, + ); + }, + ); + }, + child: DataTable( + columnSpacing: defaultPadding, + // minWidth: 600, + columns: [ + DataColumn( + label: Text("Client Name"), + ), + DataColumn( + label: Text("Email Address"), + ), + DataColumn( + label: Text("Date/Time"), + ), + ], + rows: List.generate( + demoRecentFiles.length, + (index) => recentFileDataRow(demoRecentFiles[index]), + ), + ), + ), + ), + ], + ), + ), + ); + } +} + +DataRow recentFileDataRow(RecentFile fileInfo) { + return DataRow( + cells: [ + DataCell( + Row( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: defaultPadding), + child: Text(fileInfo.title!), + ), + ], + ), + ), + DataCell(Text(fileInfo.date!)), + DataCell(Text(fileInfo.size!)), + ], + ); +} diff --git a/lib/screens/dashboard/components/recent_files.dart b/lib/screens/dashboard/components/recent_files.dart index f371bcda..b46a46b2 100644 --- a/lib/screens/dashboard/components/recent_files.dart +++ b/lib/screens/dashboard/components/recent_files.dart @@ -1,7 +1,6 @@ import 'package:admin/models/recent_file.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; import '../../../constants.dart'; @@ -22,7 +21,7 @@ class RecentFiles extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Recent Files", + "Recent Bookings", style: Theme.of(context).textTheme.titleMedium, ), SizedBox( @@ -32,13 +31,13 @@ class RecentFiles extends StatelessWidget { // minWidth: 600, columns: [ DataColumn( - label: Text("File Name"), + label: Text("Client Name"), ), DataColumn( - label: Text("Date"), + label: Text("Email Address"), ), DataColumn( - label: Text("Size"), + label: Text("Service type"), ), ], rows: List.generate( @@ -59,11 +58,7 @@ DataRow recentFileDataRow(RecentFile fileInfo) { DataCell( Row( children: [ - SvgPicture.asset( - fileInfo.icon!, - height: 30, - width: 30, - ), + Padding( padding: const EdgeInsets.symmetric(horizontal: defaultPadding), child: Text(fileInfo.title!), diff --git a/lib/screens/dashboard/components/storage_details.dart b/lib/screens/dashboard/components/storage_details.dart index 47fb8d3a..ecd60e83 100644 --- a/lib/screens/dashboard/components/storage_details.dart +++ b/lib/screens/dashboard/components/storage_details.dart @@ -20,11 +20,14 @@ class StorageDetails extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Storage Details", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, + Container( + padding: EdgeInsets.all(10), + color: Colors.white, + child: Text( + "Processed Bookings", + style: + TextStyle(color: Colors.black, fontWeight: FontWeight.bold), + //style: Theme.of(context).textTheme.titleMedium, ), ), SizedBox(height: defaultPadding), diff --git a/lib/screens/main/components/side_menu.dart b/lib/screens/main/components/side_menu.dart index 20999627..7f6090e4 100644 --- a/lib/screens/main/components/side_menu.dart +++ b/lib/screens/main/components/side_menu.dart @@ -1,5 +1,7 @@ +import 'package:admin/controllers/home_navigation_controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:provider/provider.dart'; // Import Provider class SideMenu extends StatelessWidget { const SideMenu({ @@ -8,51 +10,92 @@ class SideMenu extends StatelessWidget { @override Widget build(BuildContext context) { + // Access the HomeNavigationController + final navigationController = Provider.of(context); + return Drawer( child: ListView( children: [ DrawerHeader( - child: Image.asset("assets/images/logo.png"), + // Add a background color + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Center( + child: Icon( + Icons.book, + color: Colors.white, + size: 30, + ), + ), + Center( + child: Text( + 'Mbooke', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 30, + color: Colors.white), + ), + ), + ], + ), ), DrawerListTile( title: "Dashboard", svgSrc: "assets/icons/menu_dashboard.svg", - press: () {}, + press: () { + navigationController.screenNumber = 0; + Navigator.pop(context); + }, ), DrawerListTile( - title: "Transaction", + title: "Bookings", svgSrc: "assets/icons/menu_tran.svg", - press: () {}, + press: () { + navigationController.screenNumber = 1; + Navigator.pop(context); + }, ), DrawerListTile( - title: "Task", + title: "Services", svgSrc: "assets/icons/menu_task.svg", - press: () {}, + press: () { + navigationController.screenNumber = 2; + Navigator.pop(context); + }, ), DrawerListTile( - title: "Documents", + title: "Statistics", svgSrc: "assets/icons/menu_doc.svg", - press: () {}, + press: () { + navigationController.screenNumber = 3; + Navigator.pop(context); + }, ), DrawerListTile( title: "Store", svgSrc: "assets/icons/menu_store.svg", - press: () {}, + press: () { + navigationController.screenNumber = 4; + Navigator.pop(context); + }, ), DrawerListTile( - title: "Notification", + title: "Feedback", svgSrc: "assets/icons/menu_notification.svg", - press: () {}, + press: () { + navigationController.screenNumber = 5; + Navigator.pop(context); + }, ), DrawerListTile( title: "Profile", svgSrc: "assets/icons/menu_profile.svg", - press: () {}, - ), - DrawerListTile( - title: "Settings", - svgSrc: "assets/icons/menu_setting.svg", - press: () {}, + press: () { + navigationController.screenNumber = 6; + Navigator.pop(context); + }, ), ], ), @@ -63,7 +106,6 @@ class SideMenu extends StatelessWidget { class DrawerListTile extends StatelessWidget { const DrawerListTile({ Key? key, - // For selecting those three line once press "Command+D" required this.title, required this.svgSrc, required this.press, diff --git a/lib/screens/main/main_screen.dart b/lib/screens/main/main_screen.dart index d67d40c3..7ee7bd69 100644 --- a/lib/screens/main/main_screen.dart +++ b/lib/screens/main/main_screen.dart @@ -1,6 +1,5 @@ import 'package:admin/controllers/menu_app_controller.dart'; import 'package:admin/responsive.dart'; -import 'package:admin/screens/dashboard/dashboard_screen.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -9,8 +8,10 @@ import 'components/side_menu.dart'; class MainScreen extends StatelessWidget { @override Widget build(BuildContext context) { + final menuController = Provider.of(context); + return Scaffold( - key: context.read().scaffoldKey, + key: menuController.scaffoldKey, drawer: SideMenu(), body: SafeArea( child: Row( @@ -19,14 +20,19 @@ class MainScreen extends StatelessWidget { // We want this side menu only for large screen if (Responsive.isDesktop(context)) Expanded( - // default flex = 1 - // and it takes 1/6 part of the screen + // Default flex = 1 + // It takes 1/6 part of the screen child: SideMenu(), ), Expanded( // It takes 5/6 part of the screen flex: 5, - child: DashboardScreen(), + // Display the current screen based on navigation state + child: Consumer( + builder: (context, controller, child) { + return controller.currentScreen; + }, + ), ), ], ), diff --git a/pubspec.lock b/pubspec.lock index 6e2508f4..194ed366 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -143,18 +143,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" url: "https://pub.dev" source: hosted - version: "10.0.5" + version: "10.0.4" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.3" leak_tracker_testing: dependency: transitive description: @@ -175,18 +175,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.12.0" nested: dependency: transitive description: @@ -340,10 +340,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.0" typed_data: dependency: transitive description: @@ -388,10 +388,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" url: "https://pub.dev" source: hosted - version: "14.2.4" + version: "14.2.1" web: dependency: transitive description: @@ -417,5 +417,5 @@ packages: source: hosted version: "6.5.0" sdks: - dart: ">=3.5.0 <4.0.0" + dart: ">=3.4.3 <4.0.0" flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index db7edcc8..7b48c777 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,7 +18,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=3.5.0 <4.0.0" + sdk: ">=3.4.3 <4.0.0" dependencies: flutter: