basic structure
							parent
							
								
									1b6ebc67c3
								
							
						
					
					
						commit
						89f6df8c77
					
				
											
												Binary file not shown.
											
										
									
								| After Width: | Height: | Size: 6.1 KiB | 
											
												Binary file not shown.
											
										
									
								| After Width: | Height: | Size: 12 KiB | 
											
												Binary file not shown.
											
										
									
								| After Width: | Height: | Size: 6.3 KiB | 
											
												Binary file not shown.
											
										
									
								| After Width: | Height: | Size: 7.1 KiB | 
											
												Binary file not shown.
											
										
									
								| After Width: | Height: | Size: 43 KiB | 
| @ -1 +1,2 @@ | |||||||
|  | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" | ||||||
| #include "Generated.xcconfig" | #include "Generated.xcconfig" | ||||||
|  | |||||||
| @ -1 +1,2 @@ | |||||||
|  | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" | ||||||
| #include "Generated.xcconfig" | #include "Generated.xcconfig" | ||||||
|  | |||||||
| @ -0,0 +1,19 @@ | |||||||
|  | import 'package:mohem_flutter_app/provider/counter.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  | 
 | ||||||
|  | class AppProvider extends StatelessWidget { | ||||||
|  |   final Widget child; | ||||||
|  | 
 | ||||||
|  |   AppProvider({required this.child}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return MultiProvider( | ||||||
|  |       providers: [ | ||||||
|  |         ChangeNotifierProvider(create: (_) => Counter()), | ||||||
|  |       ], | ||||||
|  |       child: child, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,34 @@ | |||||||
|  | //class which loads components "in the background", i.e. ui does not depend on it | ||||||
|  | 
 | ||||||
|  | import 'package:mohem_flutter_app/services/shared_preferences.dart'; | ||||||
|  | import 'package:injector/injector.dart'; | ||||||
|  | //import 'package:revocheckapp/services/firebase_service.dart'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class BackgroundLoader { | ||||||
|  |   Future loadBackgroundData() async { | ||||||
|  |     //init notification setting | ||||||
|  |     try { | ||||||
|  |       /* | ||||||
|  |       final isPromotionNotificationEnabled = await Injector.appInstance | ||||||
|  |           .getDependency<ISharedPreferences>() | ||||||
|  |           .promotionNotificationsEnabled; | ||||||
|  |       if (isPromotionNotificationEnabled == null) { | ||||||
|  |         await Injector.appInstance | ||||||
|  |             .getDependency<ISharedPreferences>() | ||||||
|  |             .setPromotionNotificationEnabled(true); | ||||||
|  |         Injector.appInstance | ||||||
|  |             .getDependency<IFirebaseService>() | ||||||
|  |             .subscribeForPromotions(); | ||||||
|  |       } */ | ||||||
|  |     } catch (_) { | ||||||
|  |       //something wend wrong, set it to true | ||||||
|  |       await Injector.appInstance | ||||||
|  |           .getDependency<ISharedPreferences>() | ||||||
|  |           .setPromotionNotificationEnabled(true); | ||||||
|  |       /*Injector.appInstance | ||||||
|  |           .getDependency<IFirebaseService>() | ||||||
|  |           .subscribeForPromotions();*/ | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,8 @@ | |||||||
|  | enum YesOrNo { | ||||||
|  |   no, | ||||||
|  |   yes, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const String icons = "assets/icons/"; | ||||||
|  | const String categorySvgIcons = "assets/category/svg/"; | ||||||
|  | const String svgIcons = "assets/svg/"; | ||||||
| @ -0,0 +1,38 @@ | |||||||
|  | // import 'package:firebase_crashlytics/firebase_crashlytics.dart'; | ||||||
|  | // import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | import 'package:mohem_flutter_app/repo/account_repository.dart'; | ||||||
|  | import 'package:injector/injector.dart'; | ||||||
|  | 
 | ||||||
|  | import 'background_loader.dart'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class AppDependencies { | ||||||
|  |   static void addDependencies() { | ||||||
|  |     Injector injector = Injector.appInstance; | ||||||
|  | 
 | ||||||
|  |     //add dependencies as needed | ||||||
|  |     injector.registerSingleton<IAcRepository>(() => AcRepository()); | ||||||
|  | 
 | ||||||
|  |     // injector.registerSingleton<IAcRepository>((injector) => AcRepository()); | ||||||
|  | 
 | ||||||
|  |     _addCrashlytics(); | ||||||
|  |     _loadBackgroundTasksNonBlocking(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   static void _addCrashlytics() { | ||||||
|  |     // Set `enableInDevMode` to true to see reports while in debug mode | ||||||
|  |     // This is only to be used for confirming that reports are being | ||||||
|  |     // submitted as expected. It is not intended to be used for everyday | ||||||
|  |     // development. | ||||||
|  |     //Crashlytics.instance.enableInDevMode = true; | ||||||
|  | 
 | ||||||
|  |     // Pass all uncaught errors from the framework to Crashlytics. | ||||||
|  |     // FlutterError.onError = Crashlytics.instance.recordFlutterError; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   static void _loadBackgroundTasksNonBlocking() { | ||||||
|  |     final backgroundLoader = BackgroundLoader(); | ||||||
|  |     backgroundLoader.loadBackgroundData(); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,18 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | import 'package:flutter_localizations/flutter_localizations.dart'; | ||||||
|  | 
 | ||||||
|  | class AppLocalizations { | ||||||
|  |   static const Iterable<LocalizationsDelegate<dynamic>> localizationsDelegates = | ||||||
|  |       [ | ||||||
|  |     // ... app-specific localization delegate[s] here | ||||||
|  |     // S.delegate, | ||||||
|  |     GlobalMaterialLocalizations.delegate, | ||||||
|  |     GlobalWidgetsLocalizations.delegate, | ||||||
|  |     GlobalCupertinoLocalizations.delegate | ||||||
|  |   ]; | ||||||
|  | 
 | ||||||
|  |   static const List<Locale> supportedLocales = [ | ||||||
|  |     const Locale("en", "US") | ||||||
|  |   ]; | ||||||
|  | } | ||||||
| @ -0,0 +1,46 @@ | |||||||
|  | import 'package:mohem_flutter_app/pages/dashboard/dashboard_page.dart'; | ||||||
|  | import 'package:mohem_flutter_app/pages/user/complete_profile_page.dart'; | ||||||
|  | import 'package:mohem_flutter_app/pages/user/forget_password_page.dart'; | ||||||
|  | import 'package:mohem_flutter_app/pages/user/login_verification_page.dart'; | ||||||
|  | import 'package:mohem_flutter_app/pages/user/login_verify_account_page.dart'; | ||||||
|  | import 'package:mohem_flutter_app/pages/user/profile/profile_1_page.dart'; | ||||||
|  | import 'package:mohem_flutter_app/pages/user/profile/profile_2_page.dart'; | ||||||
|  | import 'package:mohem_flutter_app/pages/user/profile/profile_3_page.dart'; | ||||||
|  | import 'package:mohem_flutter_app/pages/user/register_page.dart'; | ||||||
|  | import 'package:mohem_flutter_app/pages/user/register_selection_page.dart'; | ||||||
|  | import 'package:mohem_flutter_app/pages/user/splash_page.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | class AppRoutes { | ||||||
|  |   //User | ||||||
|  |   static final String splash = "/splash"; | ||||||
|  |   static final String registerSelection = "/registerSelection"; | ||||||
|  |   static final String loginVerifyAccount = "/loginVerifyAccount"; | ||||||
|  |   static final String register = "/register"; | ||||||
|  |   static final String forgetPassword = "/forgetPassword"; | ||||||
|  |   static final String loginVerification = "/loginVerification"; | ||||||
|  |   static final String dashboard = "/dashboard"; | ||||||
|  |   static final String completeProfile = "/completeProfile"; | ||||||
|  |   static final String profile1 = "/profile1"; | ||||||
|  |   static final String profile2 = "/profile2"; | ||||||
|  |   static final String profile3 = "/profile3"; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   static final String initialRoute = splash; | ||||||
|  | 
 | ||||||
|  |   static final Map<String, WidgetBuilder> routes = { | ||||||
|  |     //User | ||||||
|  |     splash: (context) => SplashPage(), | ||||||
|  |     registerSelection: (context) => RegisterSelectionPage(), | ||||||
|  |     loginVerifyAccount: (context) => LoginVerifyAccountPage(), | ||||||
|  |     register: (context) => RegisterPage(), | ||||||
|  |     forgetPassword: (context) => ForgetPasswordPage(), | ||||||
|  |     loginVerification: (context) => LoginVerificationPage(), | ||||||
|  |     dashboard: (context) => DashboardPage(), | ||||||
|  |     completeProfile: (context) => CompleteProfilePage(), | ||||||
|  |     profile1: (context) => Profile1Page(), | ||||||
|  |     profile2: (context) => Profile2Page(), | ||||||
|  |     profile3: (context) => Profile3Page(), | ||||||
|  |   }; | ||||||
|  | } | ||||||
| @ -0,0 +1,94 @@ | |||||||
|  | // DO NOT EDIT. This is code generated via package:easy_localization/generate.dart | ||||||
|  | 
 | ||||||
|  | // ignore_for_file: prefer_single_quotes | ||||||
|  | 
 | ||||||
|  | import 'dart:ui'; | ||||||
|  | 
 | ||||||
|  | import 'package:easy_localization/easy_localization.dart' show AssetLoader; | ||||||
|  | 
 | ||||||
|  | class CodegenLoader extends AssetLoader{ | ||||||
|  |   const CodegenLoader(); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<Map<String, dynamic>> load(String fullPath, Locale locale ) { | ||||||
|  |     return Future.value(mapLocales[locale.toString()]); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   static const Map<String,dynamic> en = { | ||||||
|  |   "title": "Hello", | ||||||
|  |   "msg": "Hello {} in the {} world ", | ||||||
|  |   "msg_named": "{} are written in the {lang} language", | ||||||
|  |   "clickMe": "Click me", | ||||||
|  |   "profile": { | ||||||
|  |     "reset_password": { | ||||||
|  |       "label": "Reset Password", | ||||||
|  |       "username": "Username", | ||||||
|  |       "password": "password" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "clicked": { | ||||||
|  |     "zero": "You clicked {} times!", | ||||||
|  |     "one": "You clicked {} time!", | ||||||
|  |     "two": "You clicked {} times!", | ||||||
|  |     "few": "You clicked {} times!", | ||||||
|  |     "many": "You clicked {} times!", | ||||||
|  |     "other": "You clicked {} times!" | ||||||
|  |   }, | ||||||
|  |   "amount": { | ||||||
|  |     "zero": "Your amount : {} ", | ||||||
|  |     "one": "Your amount : {} ", | ||||||
|  |     "two": "Your amount : {} ", | ||||||
|  |     "few": "Your amount : {} ", | ||||||
|  |     "many": "Your amount : {} ", | ||||||
|  |     "other": "Your amount : {} " | ||||||
|  |   }, | ||||||
|  |   "gender": { | ||||||
|  |     "male": "Hi man ;) ", | ||||||
|  |     "female": "Hello girl :)", | ||||||
|  |     "with_arg": { | ||||||
|  |       "male": "Hi man ;) {}", | ||||||
|  |       "female": "Hello girl :) {}" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "reset_locale": "Reset Language" | ||||||
|  | }; | ||||||
|  | static const Map<String,dynamic> en_US = { | ||||||
|  |   "title": "Hello", | ||||||
|  |   "msg": "Hello {} in the {} world ", | ||||||
|  |   "msg_named": "{} are written in the {lang} language", | ||||||
|  |   "clickMe": "Click me", | ||||||
|  |   "profile": { | ||||||
|  |     "reset_password": { | ||||||
|  |       "label": "Reset Password", | ||||||
|  |       "username": "Username", | ||||||
|  |       "password": "password" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "clicked": { | ||||||
|  |     "zero": "You clicked {} times!", | ||||||
|  |     "one": "You clicked {} time!", | ||||||
|  |     "two": "You clicked {} times!", | ||||||
|  |     "few": "You clicked {} times!", | ||||||
|  |     "many": "You clicked {} times!", | ||||||
|  |     "other": "You clicked {} times!" | ||||||
|  |   }, | ||||||
|  |   "amount": { | ||||||
|  |     "zero": "Your amount : {} ", | ||||||
|  |     "one": "Your amount : {} ", | ||||||
|  |     "two": "Your amount : {} ", | ||||||
|  |     "few": "Your amount : {} ", | ||||||
|  |     "many": "Your amount : {} ", | ||||||
|  |     "other": "Your amount : {} " | ||||||
|  |   }, | ||||||
|  |   "gender": { | ||||||
|  |     "male": "Hi man ;) ", | ||||||
|  |     "female": "Hello girl :)", | ||||||
|  |     "with_arg": { | ||||||
|  |       "male": "Hi man ;) {}", | ||||||
|  |       "female": "Hello girl :) {}" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "reset_locale": "Reset Language" | ||||||
|  | }; | ||||||
|  | static const Map<String, Map<String,dynamic>> mapLocales = {"en": en, "en_US": en_US}; | ||||||
|  | } | ||||||
| @ -1,115 +1,50 @@ | |||||||
|  | import 'package:mohem_flutter_app/config/app_provider.dart'; | ||||||
|  | import 'package:mohem_flutter_app/config/dependencies.dart'; | ||||||
|  | import 'package:mohem_flutter_app/theme/app_theme.dart'; | ||||||
|  | import 'package:easy_localization/easy_localization.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| 
 | import 'package:sizer/sizer.dart'; | ||||||
| void main() { | 
 | ||||||
|   runApp(const MyApp()); | import 'config/localization.dart'; | ||||||
|  | import 'config/routes.dart'; | ||||||
|  | 
 | ||||||
|  | Future<void> main() async { | ||||||
|  |   WidgetsFlutterBinding.ensureInitialized(); | ||||||
|  | 
 | ||||||
|  |   await EasyLocalization.ensureInitialized(); | ||||||
|  |   runApp( | ||||||
|  |     EasyLocalization( | ||||||
|  |       supportedLocales: [ | ||||||
|  |         Locale('en', 'US'), | ||||||
|  |       ], | ||||||
|  |       path: 'resources/langs', | ||||||
|  |       child: MyApp(), | ||||||
|  |     ), | ||||||
|  |   ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class MyApp extends StatelessWidget { | class MyApp extends StatelessWidget { | ||||||
|   const MyApp({Key? key}) : super(key: key); |  | ||||||
| 
 |  | ||||||
|   // This widget is the root of your application. |   // This widget is the root of your application. | ||||||
|   @override |   MyApp() { | ||||||
|   Widget build(BuildContext context) { |     AppDependencies.addDependencies(); | ||||||
|     return MaterialApp( |  | ||||||
|       title: 'Flutter Demo', |  | ||||||
|       theme: ThemeData( |  | ||||||
|         // This is the theme of your application. |  | ||||||
|         // |  | ||||||
|         // Try running your application with "flutter run". You'll see the |  | ||||||
|         // application has a blue toolbar. Then, without quitting the app, try |  | ||||||
|         // changing the primarySwatch below to Colors.green and then invoke |  | ||||||
|         // "hot reload" (press "r" in the console where you ran "flutter run", |  | ||||||
|         // or simply save your changes to "hot reload" in a Flutter IDE). |  | ||||||
|         // Notice that the counter didn't reset back to zero; the application |  | ||||||
|         // is not restarted. |  | ||||||
|         primarySwatch: Colors.blue, |  | ||||||
|       ), |  | ||||||
|       home: const MyHomePage(title: 'Flutter Demo Home Page'), |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| class MyHomePage extends StatefulWidget { |  | ||||||
|   const MyHomePage({Key? key, required this.title}) : super(key: key); |  | ||||||
| 
 |  | ||||||
|   // This widget is the home page of your application. It is stateful, meaning |  | ||||||
|   // that it has a State object (defined below) that contains fields that affect |  | ||||||
|   // how it looks. |  | ||||||
| 
 |  | ||||||
|   // This class is the configuration for the state. It holds the values (in this |  | ||||||
|   // case the title) provided by the parent (in this case the App widget) and |  | ||||||
|   // used by the build method of the State. Fields in a Widget subclass are |  | ||||||
|   // always marked "final". |  | ||||||
| 
 |  | ||||||
|   final String title; |  | ||||||
| 
 |  | ||||||
|   @override |  | ||||||
|   State<MyHomePage> createState() => _MyHomePageState(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| class _MyHomePageState extends State<MyHomePage> { |  | ||||||
|   int _counter = 0; |  | ||||||
| 
 |  | ||||||
|   void _incrementCounter() { |  | ||||||
|     setState(() { |  | ||||||
|       // This call to setState tells the Flutter framework that something has |  | ||||||
|       // changed in this State, which causes it to rerun the build method below |  | ||||||
|       // so that the display can reflect the updated values. If we changed |  | ||||||
|       // _counter without calling setState(), then the build method would not be |  | ||||||
|       // called again, and so nothing would appear to happen. |  | ||||||
|       _counter++; |  | ||||||
|     }); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     // This method is rerun every time setState is called, for instance as done |     return AppProvider( | ||||||
|     // by the _incrementCounter method above. |       child: Sizer( | ||||||
|     // |         builder: (context, orientation, deviceType) { | ||||||
|     // The Flutter framework has been optimized to make rerunning build methods |           return MaterialApp( | ||||||
|     // fast, so that you can just rebuild anything that needs updating rather |             theme: AppTheme.getTheme(), | ||||||
|     // than having to individually change instances of widgets. |             debugShowCheckedModeBanner: false, | ||||||
|     return Scaffold( |             localizationsDelegates: context.localizationDelegates, | ||||||
|       appBar: AppBar( |             supportedLocales: context.supportedLocales, | ||||||
|         // Here we take the value from the MyHomePage object that was created by |             locale: context.locale, | ||||||
|         // the App.build method, and use it to set our appbar title. |             initialRoute: AppRoutes.initialRoute, | ||||||
|         title: Text(widget.title), |             routes: AppRoutes.routes, | ||||||
|       ), |           ); | ||||||
|       body: Center( |         }, | ||||||
|         // Center is a layout widget. It takes a single child and positions it |  | ||||||
|         // in the middle of the parent. |  | ||||||
|         child: Column( |  | ||||||
|           // Column is also a layout widget. It takes a list of children and |  | ||||||
|           // arranges them vertically. By default, it sizes itself to fit its |  | ||||||
|           // children horizontally, and tries to be as tall as its parent. |  | ||||||
|           // |  | ||||||
|           // Invoke "debug painting" (press "p" in the console, choose the |  | ||||||
|           // "Toggle Debug Paint" action from the Flutter Inspector in Android |  | ||||||
|           // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) |  | ||||||
|           // to see the wireframe for each widget. |  | ||||||
|           // |  | ||||||
|           // Column has various properties to control how it sizes itself and |  | ||||||
|           // how it positions its children. Here we use mainAxisAlignment to |  | ||||||
|           // center the children vertically; the main axis here is the vertical |  | ||||||
|           // axis because Columns are vertical (the cross axis would be |  | ||||||
|           // horizontal). |  | ||||||
|           mainAxisAlignment: MainAxisAlignment.center, |  | ||||||
|           children: <Widget>[ |  | ||||||
|             const Text( |  | ||||||
|               'You have pushed the button this many times:', |  | ||||||
|             ), |  | ||||||
|             Text( |  | ||||||
|               '$_counter', |  | ||||||
|               style: Theme.of(context).textTheme.headline4, |  | ||||||
|             ), |  | ||||||
|           ], |  | ||||||
|         ), |  | ||||||
|       ), |       ), | ||||||
|       floatingActionButton: FloatingActionButton( |  | ||||||
|         onPressed: _incrementCounter, |  | ||||||
|         tooltip: 'Increment', |  | ||||||
|         child: const Icon(Icons.add), |  | ||||||
|       ), // This trailing comma makes auto-formatting nicer for build methods. |  | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,43 @@ | |||||||
|  | // To parse this JSON data, do | ||||||
|  | // | ||||||
|  | //     final account = accountFromJson(jsonString); | ||||||
|  | 
 | ||||||
|  | import 'dart:convert'; | ||||||
|  | 
 | ||||||
|  | import 'package:mohem_flutter_app/models/parent_list.dart'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Account accountFromJson(String str) => Account.fromJson(json.decode(str)); | ||||||
|  | 
 | ||||||
|  | String accountToJson(Account data) => json.encode(data.toJson()); | ||||||
|  | 
 | ||||||
|  | class Account { | ||||||
|  |   Account({ | ||||||
|  |     required this.parentList, | ||||||
|  |     required this.selectedItem, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   List<ParentList>? parentList; | ||||||
|  |   int selectedItem; | ||||||
|  | 
 | ||||||
|  |   factory Account.fromJson(Map<String, dynamic> json) => Account( | ||||||
|  |         parentList: json["parentList"] == null | ||||||
|  |             ? null | ||||||
|  |             : List<ParentList>.from( | ||||||
|  |                 json["parentList"].map((x) => ParentList.fromJson(x))), | ||||||
|  |         selectedItem: | ||||||
|  |             json["selectedItem"] == null ? null : json["selectedItem"], | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |   Map<String, dynamic> toJson() => { | ||||||
|  |         "parentList": parentList == null | ||||||
|  |             ? null | ||||||
|  |             : List<dynamic>.from(parentList!.map((x) => x.toJson())), | ||||||
|  |         "selectedItem": selectedItem == null ? null : selectedItem, | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |   Map<String, dynamic> toJsonData() => { | ||||||
|  |         "selectedItem": selectedItem == null ? null : selectedItem, | ||||||
|  |       }; | ||||||
|  | } | ||||||
| @ -0,0 +1,12 @@ | |||||||
|  | class ConfigModel { | ||||||
|  |   ConfigModel(this.endpoint, this.organizationName); | ||||||
|  | 
 | ||||||
|  |   String endpoint; | ||||||
|  | 
 | ||||||
|  |   String organizationName; | ||||||
|  | 
 | ||||||
|  |   factory ConfigModel.fromJson(Map<String, dynamic> json) => | ||||||
|  |       ConfigModel("", ""); | ||||||
|  | 
 | ||||||
|  | // Map<String, dynamic> toJson() => _$ConfigModelToJson(this); | ||||||
|  | } | ||||||
| @ -0,0 +1,26 @@ | |||||||
|  | class ParentList { | ||||||
|  |   ParentList({ | ||||||
|  |     required this.dbId, | ||||||
|  |     required this.text, | ||||||
|  |     required this.path, | ||||||
|  |     required this.isSelected, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   int dbId; | ||||||
|  |   String text; | ||||||
|  |   String path; | ||||||
|  |   bool isSelected; | ||||||
|  | 
 | ||||||
|  |   factory ParentList.fromJson(Map<String, dynamic> json) => ParentList( | ||||||
|  |         dbId: json["dbId"] == null ? null : json["dbId"], | ||||||
|  |         text: json["text"] == null ? null : json["text"], | ||||||
|  |         path: json["path"] == null ? null : json["path"], | ||||||
|  |         isSelected: false, | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |   Map<String, dynamic> toJson() => { | ||||||
|  |         "dbId": dbId == null ? null : dbId, | ||||||
|  |         "text": text == null ? null : text, | ||||||
|  |         "path": path == null ? null : path, | ||||||
|  |       }; | ||||||
|  | } | ||||||
| @ -0,0 +1,34 @@ | |||||||
|  | /// | ||||||
|  | /// This example was taken from | ||||||
|  | /// https://flutter.dev/docs/development/data-and-backend/json | ||||||
|  | /// | ||||||
|  | 
 | ||||||
|  | /// This allows the `User` class to access private members in | ||||||
|  | /// the generated file. The value for this is *.g.dart, where | ||||||
|  | /// the star denotes the source file name. | ||||||
|  | 
 | ||||||
|  | /// An annotation for the code generator to know that this class needs the | ||||||
|  | /// JSON serialization logic to be generated. | ||||||
|  | 
 | ||||||
|  | class BackendResponse { | ||||||
|  |   BackendResponse({required this.id, required this.isOk, required this.result}); | ||||||
|  | 
 | ||||||
|  |   int id; | ||||||
|  |   bool isOk; | ||||||
|  |   dynamic result; | ||||||
|  | 
 | ||||||
|  |   /// A necessary factory constructor for creating a new User instance | ||||||
|  |   /// from a map. Pass the map to the generated `_$UserFromJson()` constructor. | ||||||
|  |   /// The constructor is named after the source class, in this case, User. | ||||||
|  |   factory BackendResponse.fromJson(Map<String, dynamic> json) => | ||||||
|  |       BackendResponse( | ||||||
|  |         id: 1, | ||||||
|  |         isOk: false, | ||||||
|  |         result: null, | ||||||
|  |       ); | ||||||
|  | // | ||||||
|  | // /// `toJson` is the convention for a class to declare support for serialization | ||||||
|  | // /// to JSON. The implementation simply calls the private, generated | ||||||
|  | // /// helper method `_$UserToJson`. | ||||||
|  | // Map<String, dynamic> toJson() => _$BackendResponseToJson(this); | ||||||
|  | } | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | class User { | ||||||
|  |   int id; | ||||||
|  | 
 | ||||||
|  |   User(this.id, this.userName, this.userImage, this.createdDate); | ||||||
|  | 
 | ||||||
|  |   String userName; | ||||||
|  |   String userImage; | ||||||
|  |   String createdDate; | ||||||
|  | } | ||||||
| @ -0,0 +1,48 @@ | |||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
|  | import 'package:mohem_flutter_app/config/routes.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/navigator.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/utils.dart'; | ||||||
|  | import 'package:mohem_flutter_app/widgets/txt.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | class SplashPage extends StatelessWidget { | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Scaffold( | ||||||
|  |       body: Container( | ||||||
|  |         width: double.infinity, | ||||||
|  |         height: double.infinity, | ||||||
|  |         child: Column( | ||||||
|  |           children: [ | ||||||
|  |             mFlex(5), | ||||||
|  |             Txt( | ||||||
|  |               "Logo", | ||||||
|  |               fontSize: 45, | ||||||
|  |               bold: true, | ||||||
|  |             ), | ||||||
|  |             mFlex(3), | ||||||
|  |             Txt( | ||||||
|  |               "First Time Log In", | ||||||
|  |               txtType: TxtType.heading1, | ||||||
|  |               isFlatButton: true, | ||||||
|  |               onTap: () { | ||||||
|  |                 navigateWithName(context, AppRoutes.registerSelection); | ||||||
|  |               }, | ||||||
|  |             ), | ||||||
|  |             mFlex(1), | ||||||
|  |             Txt( | ||||||
|  |               "Already Signed Up and Logged In", | ||||||
|  |               txtType: TxtType.heading1, | ||||||
|  |               isFlatButton: true, | ||||||
|  |               onTap: () { | ||||||
|  |                 navigateWithName(context, AppRoutes.loginVerification); | ||||||
|  |               }, | ||||||
|  |             ), | ||||||
|  |             mFlex(5), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,20 @@ | |||||||
|  | import 'package:flutter/foundation.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | class Counter with ChangeNotifier, DiagnosticableTreeMixin { | ||||||
|  |   int _count = 0; | ||||||
|  | 
 | ||||||
|  |   int get count => _count; | ||||||
|  | 
 | ||||||
|  |   void increment() { | ||||||
|  |     _count++; | ||||||
|  |     notifyListeners(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /// Makes `Counter` readable inside the devtools by listing all of its properties | ||||||
|  |   @override | ||||||
|  |   void debugFillProperties(DiagnosticPropertiesBuilder properties) { | ||||||
|  |     super.debugFillProperties(properties); | ||||||
|  |     properties.add(IntProperty('count', count)); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,49 @@ | |||||||
|  | import 'dart:convert'; | ||||||
|  | import 'dart:io'; | ||||||
|  | 
 | ||||||
|  | import 'package:mohem_flutter_app/models/account.dart'; | ||||||
|  | import 'package:mohem_flutter_app/models/response_models.dart'; | ||||||
|  | import 'package:mohem_flutter_app/services/backend_service.dart'; | ||||||
|  | import 'package:injector/injector.dart'; | ||||||
|  | 
 | ||||||
|  | abstract class IAcRepository { | ||||||
|  |   Future<Account> getAccountList(); | ||||||
|  | 
 | ||||||
|  |   Future<BackendResponse> updateAccount(String dataAsJson); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class AcRepository implements IAcRepository { | ||||||
|  |   static const String ACCOUNT_API_CONTROLLER_MOBILE = | ||||||
|  |       "AccountApiControllerMobile/"; | ||||||
|  | 
 | ||||||
|  |   static const String ACCOUNT_LIST = ACCOUNT_API_CONTROLLER_MOBILE + "list"; | ||||||
|  |   static const String UPDATE_LIST = | ||||||
|  |       ACCOUNT_API_CONTROLLER_MOBILE + "saveaccountselected"; | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<Account> getAccountList() async { | ||||||
|  |     BackendResponse response = await Injector.appInstance | ||||||
|  |         .getDependency<IBackendApiService>() | ||||||
|  |         .getAuthenticatedAPI(ACCOUNT_LIST); | ||||||
|  | 
 | ||||||
|  |     if (response != null && response.isOk) { | ||||||
|  |       return Account.fromJson(response.result); | ||||||
|  |     } else { | ||||||
|  |       throw Exception(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<BackendResponse> updateAccount(String dataAsJson) async { | ||||||
|  |     BackendResponse response = await Injector.appInstance | ||||||
|  |         .getDependency<IBackendApiService>() | ||||||
|  |         .postAuthenticatedAPI(UPDATE_LIST, dataAsJson); | ||||||
|  | 
 | ||||||
|  |     if (response != null && response.isOk) { | ||||||
|  |       //if parsing failed, throw exception | ||||||
|  |       return response; | ||||||
|  |     } else { | ||||||
|  |       throw Exception(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,127 @@ | |||||||
|  | import 'dart:convert'; | ||||||
|  | import 'dart:io'; | ||||||
|  | import 'package:mohem_flutter_app/models/response_models.dart'; | ||||||
|  | import 'package:mohem_flutter_app/services/secure_storage.dart'; | ||||||
|  | import 'package:http/http.dart'; | ||||||
|  | import 'package:injector/injector.dart'; | ||||||
|  | 
 | ||||||
|  | import 'http_service.dart'; | ||||||
|  | import 'network_service.dart'; | ||||||
|  | 
 | ||||||
|  | abstract class IBackendApiService { | ||||||
|  |   Future<BackendResponse> getUnauthenticatedAPI(String route); | ||||||
|  | 
 | ||||||
|  |   Future<BackendResponse> getAuthenticatedAPI(String route); | ||||||
|  | 
 | ||||||
|  |   Future<BackendResponse> postUnauthenticatedAPI( | ||||||
|  |       String route, String dataAsJson); | ||||||
|  | 
 | ||||||
|  |   Future<BackendResponse> postAuthenticatedAPI(String route, String dataAsJson); | ||||||
|  | 
 | ||||||
|  |   Future<BackendResponse> deleteAuthenticatedAPI(String route, String id); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class BackendApiService implements IBackendApiService { | ||||||
|  |   static String _homeUrl = "https://check.revotec.eu/check2/"; | ||||||
|  |   static String _serverApiBaseUrl = _homeUrl + "mapi/v1/"; | ||||||
|  | 
 | ||||||
|  |   static String get homeUrl => _homeUrl; | ||||||
|  | 
 | ||||||
|  |   final ISecureStorage _secureStorage = | ||||||
|  |       Injector.appInstance.getDependency<ISecureStorage>(); | ||||||
|  |   final IHttpService _httpService = | ||||||
|  |       Injector.appInstance.getDependency<IHttpService>(); | ||||||
|  | 
 | ||||||
|  |   ///internal helper functions which executes the given api call | ||||||
|  |   ///and wraps the response | ||||||
|  |   Future<BackendResponse> _callApi(Future<dynamic> callback) async { | ||||||
|  |     Response response; | ||||||
|  |     try { | ||||||
|  |       //execute future | ||||||
|  |       response = await callback; | ||||||
|  |       //check response code, and if not ok return isOk = false | ||||||
|  |       //200 for Get | ||||||
|  |       //201 for Post | ||||||
|  | 
 | ||||||
|  |       // print("res121: " + | ||||||
|  |       //     response.statusCode.toString() + | ||||||
|  |       //     " Body:" + | ||||||
|  |       //     response.body.toString()); | ||||||
|  |       //if delete request sent so server is returning 204 in case of success. | ||||||
|  |       if (response.statusCode == 204) | ||||||
|  |         return BackendResponse(id: 1, isOk: true, result: null); | ||||||
|  | 
 | ||||||
|  |       if (response.statusCode != 200 && response.statusCode != 201) | ||||||
|  |         return BackendResponse(id: -1, isOk: false, result: null); | ||||||
|  |       //if response code is good then parse message and return parsed response | ||||||
|  |       return BackendResponse.fromJson(json.decode(response.body)); | ||||||
|  |       //return BackendResponse.fromJson(dioResponse.body); | ||||||
|  |     } catch (e) { | ||||||
|  |       return BackendResponse(id: -1, isOk: false, result: null); | ||||||
|  |       // try { | ||||||
|  |       //   return BackendResponse.fromJson(json.decode(response.body)); | ||||||
|  |       // } catch (e) { | ||||||
|  |       //   return BackendResponse(id:-1, isOk:false,result: null); | ||||||
|  |       // } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<BackendResponse> getAuthenticatedAPI(String route) async { | ||||||
|  |     await checkConnection(); | ||||||
|  |     final token = await _secureStorage.readBearerToken(); | ||||||
|  |     return _callApi(_httpService.get(_serverApiBaseUrl + route, headers: { | ||||||
|  |       'Content-Type': 'application/json', | ||||||
|  |       'Accept': '*/*', | ||||||
|  |       HttpHeaders.authorizationHeader: "Bearer $token" | ||||||
|  |     })); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<BackendResponse> getUnauthenticatedAPI(String route) async { | ||||||
|  |     await checkConnection(); | ||||||
|  |     return _callApi(_httpService.get(_serverApiBaseUrl + route, | ||||||
|  |         headers: {'Content-Type': 'application/json', 'Accept': '*/*'})); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<BackendResponse> postAuthenticatedAPI( | ||||||
|  |       String route, String dataAsJson) async { | ||||||
|  |     await checkConnection(); | ||||||
|  |     final token = await _secureStorage.readBearerToken(); | ||||||
|  |     // print("res121: " + _serverApiBaseUrl + route); | ||||||
|  |     return _callApi(_httpService | ||||||
|  |         .post(_serverApiBaseUrl + route, body: dataAsJson, headers: { | ||||||
|  |       'Content-Type': 'application/json', | ||||||
|  |       'Accept': '*/*', | ||||||
|  |       HttpHeaders.authorizationHeader: "Bearer $token" | ||||||
|  |     })); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<BackendResponse> postUnauthenticatedAPI( | ||||||
|  |       String route, String dataAsJson) async { | ||||||
|  |     await checkConnection(); | ||||||
|  |     return _callApi(_httpService.post(_serverApiBaseUrl + route, | ||||||
|  |         body: dataAsJson, headers: {'Content-Type': 'application/json'})); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Future<void> checkConnection() async { | ||||||
|  |     if (!(await Injector.appInstance | ||||||
|  |         .getDependency<INetworkService>() | ||||||
|  |         .isHostAvailable(_homeUrl))) throw NetworkException(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<BackendResponse> deleteAuthenticatedAPI( | ||||||
|  |       String route, String id) async { | ||||||
|  |     await checkConnection(); | ||||||
|  |     final token = await _secureStorage.readBearerToken(); | ||||||
|  |     return _callApi( | ||||||
|  |         _httpService.delete(_serverApiBaseUrl + route + "/" + id, headers: { | ||||||
|  |       'Content-Type': 'application/json', | ||||||
|  |       'Accept': '*/*', | ||||||
|  |       HttpHeaders.authorizationHeader: "Bearer $token" | ||||||
|  |     })); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,180 @@ | |||||||
|  | /* | ||||||
|  | import 'dart:io' show Platform; | ||||||
|  | import 'package:firebase_messaging/firebase_messaging.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:flutter_local_notifications/flutter_local_notifications.dart'; | ||||||
|  | 
 | ||||||
|  | abstract class IFirebaseService { | ||||||
|  |   Future<String> get token; | ||||||
|  | 
 | ||||||
|  |   Future<dynamic> backgroundMessageHandler(Map<String, dynamic> message); | ||||||
|  | 
 | ||||||
|  |   Future<dynamic> messageHandler(Map<String, dynamic> message); | ||||||
|  | 
 | ||||||
|  |   Future<dynamic> onLaunch(Map<String, dynamic> message); | ||||||
|  | 
 | ||||||
|  |   Future<dynamic> onResume(Map<String, dynamic> message); | ||||||
|  | 
 | ||||||
|  |   void subscribeForPromotions(); | ||||||
|  | 
 | ||||||
|  |   void unsubscribeFromPromotions(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //https://medium.com/@SebastianEngel/easy-push-notifications-with-flutter-and-firebase-cloud-messaging-d96084f5954f | ||||||
|  | class FirebaseService implements IFirebaseService { | ||||||
|  |   FirebaseMessaging _firebaseMessaging; | ||||||
|  | 
 | ||||||
|  |   FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin; | ||||||
|  | 
 | ||||||
|  |   FirebaseService() {. | ||||||
|  |     _firebaseMessaging = FirebaseMessaging(); | ||||||
|  | 
 | ||||||
|  |     //https://github.com/FirebaseExtended/flutterfire/issues/1695 | ||||||
|  |     _firebaseMessaging.configure( | ||||||
|  |       onMessage: messageHandler, | ||||||
|  |       onBackgroundMessage: | ||||||
|  |       Platform.isAndroid ? myBackgroundMessageHandler : null, | ||||||
|  |       onLaunch: onLaunch, | ||||||
|  |       onResume: onResume, | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     //monitor firebase token changes | ||||||
|  |     //https://firebase.google.com/docs/cloud-messaging/android/client#sample-register | ||||||
|  |     ///The registration token may change when: | ||||||
|  |     // | ||||||
|  |     //The app deletes Instance ID | ||||||
|  |     //The app is restored on a new device | ||||||
|  |     //The user uninstalls/reinstall the app | ||||||
|  |     //The user clears app data. | ||||||
|  |     /// | ||||||
|  | 
 | ||||||
|  |     //for the first release we don't care about token refreshes | ||||||
|  |     /*Stream<String> fcmStream = _firebaseMessaging.onTokenRefresh; | ||||||
|  |     fcmStream.listen((token) { | ||||||
|  | 
 | ||||||
|  |     });*/ | ||||||
|  | 
 | ||||||
|  |     //ios specific settings | ||||||
|  |     //taken from https://github.com/FirebaseExtended/flutterfire/blob/master/packages/firebase_messaging/example/lib/main.dart | ||||||
|  |     _firebaseMessaging.requestNotificationPermissions( | ||||||
|  |         const IosNotificationSettings( | ||||||
|  |             sound: true, badge: true, alert: true, provisional: true)); | ||||||
|  |     _firebaseMessaging.onIosSettingsRegistered | ||||||
|  |         .listen((IosNotificationSettings settings) { | ||||||
|  |       print("Settings registered: $settings"); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     var initializationSettingsAndroid = | ||||||
|  |     AndroidInitializationSettings('app_icon'); | ||||||
|  |     var initializationSettingsIOS = | ||||||
|  |     IOSInitializationSettings(onDidReceiveLocalNotification: onDidReceiveLocalNotification); | ||||||
|  |     var initializationSettings = InitializationSettings( | ||||||
|  |         initializationSettingsAndroid, initializationSettingsIOS); | ||||||
|  |     flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); | ||||||
|  |     flutterLocalNotificationsPlugin.initialize(initializationSettings, | ||||||
|  |         onSelectNotification: selectNotification); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Future<dynamic> onDidReceiveLocalNotification(int id, String title, String body, String payload)  async{ | ||||||
|  |     var androidPlatformChannelSpecifics = AndroidNotificationDetails( | ||||||
|  |         'new_message_channel_id', | ||||||
|  |         'Neue Nachricht', | ||||||
|  |         'Channel für neue Nachrichten', | ||||||
|  |         importance: Importance.Max, | ||||||
|  |         priority: Priority.High, | ||||||
|  |         ticker: 'ticker'); | ||||||
|  |     var iOSPlatformChannelSpecifics = IOSNotificationDetails(); | ||||||
|  |     var platformChannelSpecifics = NotificationDetails( | ||||||
|  |         androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics); | ||||||
|  |     await flutterLocalNotificationsPlugin.show( | ||||||
|  |         0, | ||||||
|  |         title, | ||||||
|  |         body, | ||||||
|  |         platformChannelSpecifics); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future backgroundMessageHandler(Map<String, dynamic> message) async { | ||||||
|  |     await myBackgroundMessageHandler(message); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future messageHandler(Map<String, dynamic> message) async { | ||||||
|  |     print("onMessage: $message"); | ||||||
|  | 
 | ||||||
|  | // initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project | ||||||
|  | 
 | ||||||
|  |     var androidPlatformChannelSpecifics = AndroidNotificationDetails( | ||||||
|  |         'new_message_channel_id', | ||||||
|  |         'Neue Nachricht', | ||||||
|  |         'Channel für neue Nachrichten', | ||||||
|  |         importance: Importance.Max, | ||||||
|  |         priority: Priority.High, | ||||||
|  |         ticker: 'ticker'); | ||||||
|  |     var iOSPlatformChannelSpecifics = IOSNotificationDetails(); | ||||||
|  |     var platformChannelSpecifics = NotificationDetails( | ||||||
|  |         androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics); | ||||||
|  | 
 | ||||||
|  |     if(Platform.isAndroid) { | ||||||
|  |       await flutterLocalNotificationsPlugin.show( | ||||||
|  |           0, | ||||||
|  |           message["notification"]["title"], | ||||||
|  |           message["notification"]["body"], | ||||||
|  |           platformChannelSpecifics); | ||||||
|  |     }else if(Platform.isIOS){ | ||||||
|  |       await flutterLocalNotificationsPlugin.show( | ||||||
|  |           0, | ||||||
|  |           message["aps"]["alert"]["title"], | ||||||
|  |           message["aps"]["alert"]["body"], | ||||||
|  |           platformChannelSpecifics); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Future selectNotification(String payload) async { | ||||||
|  |     if (payload != null) { | ||||||
|  |       debugPrint('notification payload: ' + payload); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future onLaunch(Map<String, dynamic> message) async { | ||||||
|  |     print("onLaunch: $message"); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future onResume(Map<String, dynamic> message) async { | ||||||
|  |     print("onResume: $message"); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<String> get token => _firebaseMessaging.getToken(); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   void subscribeForPromotions() { | ||||||
|  |     _firebaseMessaging.subscribeToTopic("promotions"); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   void unsubscribeFromPromotions() { | ||||||
|  |     _firebaseMessaging.unsubscribeFromTopic("promotions"); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) { | ||||||
|  |   debugPrint("BACKGROUND MESSAGE RECEIVED"); | ||||||
|  |   print("BACKGROUND MESSAGE RECEIVED"); | ||||||
|  |   return Future.value(() => true); | ||||||
|  | 
 | ||||||
|  |   /*if (message.containsKey('data')) { | ||||||
|  |     // Handle data message | ||||||
|  |     final dynamic data = message['data']; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (message.containsKey('notification')) { | ||||||
|  |     // Handle notification message | ||||||
|  |     final dynamic notification = message['notification']; | ||||||
|  |   }*/ | ||||||
|  | 
 | ||||||
|  |   // Or do other work. | ||||||
|  | } | ||||||
|  | */ | ||||||
| @ -0,0 +1,36 @@ | |||||||
|  | import 'dart:convert'; | ||||||
|  | import 'dart:io'; | ||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | import 'package:http/http.dart' as http; | ||||||
|  | import 'package:http/http.dart'; | ||||||
|  | import 'package:path/path.dart'; | ||||||
|  | import 'package:injector/injector.dart'; | ||||||
|  | 
 | ||||||
|  | abstract class IHttpService { | ||||||
|  |   Future<Response> post(url, | ||||||
|  |       {Map<String, String> headers, body, Encoding encoding}); | ||||||
|  | 
 | ||||||
|  |   Future<Response> get(url, {Map<String, String> headers}); | ||||||
|  | 
 | ||||||
|  |   Future<Response> delete(url, {Map<String, String> headers}); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class HttpService implements IHttpService { | ||||||
|  |   @override | ||||||
|  |   Future<Response> delete(url, {Map<String, String>? headers}) { | ||||||
|  |     return http.delete(url, headers: headers); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<Response> get(url, {Map<String, String>? headers}) { | ||||||
|  |     return http.get(url, headers: headers); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<Response> post(url, | ||||||
|  |       {Map<String, String>? headers, body, Encoding? encoding}) { | ||||||
|  |     return http.post(url, headers: headers, body: body, encoding: encoding); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,26 @@ | |||||||
|  | // import 'dart:io'; | ||||||
|  | // | ||||||
|  | // import 'package:image_picker/image_picker.dart'; | ||||||
|  | // | ||||||
|  | // abstract class IMediaService { | ||||||
|  | //   Future<File?> takePicture(); | ||||||
|  | // | ||||||
|  | //   Future<File?> openImageFromGallery(); | ||||||
|  | // } | ||||||
|  | // | ||||||
|  | // class MediaService implements IMediaService { | ||||||
|  | //   @override | ||||||
|  | //   Future<File?> openImageFromGallery() async { | ||||||
|  | //     final pickedFile = | ||||||
|  | //     await ImagePicker().getImage(source: ImageSource.gallery); | ||||||
|  | //     if (pickedFile == null) return null; | ||||||
|  | //     return File(pickedFile.path); | ||||||
|  | //   } | ||||||
|  | // | ||||||
|  | //   @override | ||||||
|  | //   Future<File?> takePicture() async { | ||||||
|  | //     final pickedFile = await ImagePicker().getImage(source: ImageSource.camera); | ||||||
|  | //     if (pickedFile == null) return null; | ||||||
|  | //     return File(pickedFile.path); | ||||||
|  | //   } | ||||||
|  | // } | ||||||
| @ -0,0 +1,25 @@ | |||||||
|  | 
 | ||||||
|  | import 'dart:io'; | ||||||
|  | 
 | ||||||
|  | abstract class INetworkService { | ||||||
|  |   Future<bool> isHostAvailable(String endpoint); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class NetworkService implements INetworkService{ | ||||||
|  |   @override | ||||||
|  |   Future<bool> isHostAvailable(String endpoint) async { | ||||||
|  |     try { | ||||||
|  |       final result = await InternetAddress.lookup(endpoint.substring(endpoint.indexOf('//')+2).substring(0,endpoint.substring(endpoint.indexOf('//')+2).indexOf('/'))); | ||||||
|  |       if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) { | ||||||
|  |         return true; | ||||||
|  |       } else{ | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  |     } on SocketException catch (_) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class NetworkException implements  Exception { | ||||||
|  | } | ||||||
| @ -0,0 +1,33 @@ | |||||||
|  | abstract class ISecureStorage { | ||||||
|  |   Future<String> readBearerToken(); | ||||||
|  | 
 | ||||||
|  |   Future<void> clearUserCredentials(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class SecureStorage implements ISecureStorage { | ||||||
|  |   ///return bearer token if present, or null if not | ||||||
|  |   @override | ||||||
|  |   Future<String> readBearerToken() async { | ||||||
|  |     try { | ||||||
|  |       return ""; | ||||||
|  |     } catch (_) { | ||||||
|  |       //an error occured returning null | ||||||
|  |       return ""; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   ///returns true if write was successful, false otherwise | ||||||
|  |   @override | ||||||
|  |   Future<bool> writeBearerToken(String token) async { | ||||||
|  |     try { | ||||||
|  |       await ""; | ||||||
|  |       return true; | ||||||
|  |     } catch (_) { | ||||||
|  |       //an error occured returning false | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> clearUserCredentials() async {} | ||||||
|  | } | ||||||
| @ -0,0 +1,119 @@ | |||||||
|  | import 'dart:convert'; | ||||||
|  | 
 | ||||||
|  | import 'package:mohem_flutter_app/models/config_model.dart'; | ||||||
|  | 
 | ||||||
|  | import 'package:shared_preferences/shared_preferences.dart' | ||||||
|  | as SharedPrefsPlugin; | ||||||
|  | 
 | ||||||
|  | /// | ||||||
|  | /// Taken from AlarmGuide Project | ||||||
|  | /// | ||||||
|  | 
 | ||||||
|  | abstract class ISharedPreferences { | ||||||
|  |   Future<int?> get authState; | ||||||
|  | 
 | ||||||
|  |   Future<void> setAuthState(int authState); | ||||||
|  | 
 | ||||||
|  |   Future<int?> get configState; | ||||||
|  | 
 | ||||||
|  |   Future<void> setConfigState(int confState); | ||||||
|  | 
 | ||||||
|  |   Future<ConfigModel?> get config; | ||||||
|  | 
 | ||||||
|  |   Future<void> setConfig(ConfigModel config); | ||||||
|  | 
 | ||||||
|  |   Future<bool?> get promotionNotificationsEnabled; | ||||||
|  | 
 | ||||||
|  |   Future<void> setPromotionNotificationEnabled(bool newSetting); | ||||||
|  | 
 | ||||||
|  |   Future<bool?> get helpAlreadyShown; | ||||||
|  | 
 | ||||||
|  |   Future<void> setHelpAlreadyShown(); | ||||||
|  | 
 | ||||||
|  |   Future<int?> get useS3; | ||||||
|  | 
 | ||||||
|  |   Future<void> setUseS3(int value); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class SharedPreferences implements ISharedPreferences { | ||||||
|  |   static const String _AUTH_STATE_KEY = "auth_key"; | ||||||
|  |   static const String _CONFIG_KEY = "config"; | ||||||
|  |   static const String _CONFIG_STATE_KEY = "config_key"; | ||||||
|  |   static const String _PROMOTION_NOTIFICATION_KEY = "promotion"; | ||||||
|  |   static const String _HELP_ALREADY_SHOWN = "help_shown"; | ||||||
|  |   static const String _USE_S3 = "s3"; | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<int?> get authState async { | ||||||
|  |     final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); | ||||||
|  |     return sharedPrefs.getInt(_AUTH_STATE_KEY); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> setAuthState(int authState) async { | ||||||
|  |     final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); | ||||||
|  |     sharedPrefs.setInt(_AUTH_STATE_KEY, authState); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<ConfigModel?> get config async { | ||||||
|  |     final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); | ||||||
|  |     final configAsJson = sharedPrefs.getString(_CONFIG_KEY); | ||||||
|  |     return ConfigModel.fromJson(jsonDecode(configAsJson!)); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> setConfig(ConfigModel config) async { | ||||||
|  |     final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); | ||||||
|  |     sharedPrefs.setString(_CONFIG_KEY, jsonEncode(config)); | ||||||
|  |     setConfigState(1); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<bool?> get promotionNotificationsEnabled async { | ||||||
|  |     final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); | ||||||
|  |     return sharedPrefs.getBool(_PROMOTION_NOTIFICATION_KEY); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> setPromotionNotificationEnabled(bool newSetting) async { | ||||||
|  |     final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); | ||||||
|  |     sharedPrefs.setBool(_PROMOTION_NOTIFICATION_KEY, newSetting); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<bool?> get helpAlreadyShown async { | ||||||
|  |     final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); | ||||||
|  |     return sharedPrefs.getBool(_HELP_ALREADY_SHOWN); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> setHelpAlreadyShown() async { | ||||||
|  |     final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); | ||||||
|  |     sharedPrefs.setBool(_HELP_ALREADY_SHOWN, true); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<int?> get configState async { | ||||||
|  |     final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); | ||||||
|  |     return sharedPrefs.getInt(_CONFIG_STATE_KEY); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> setConfigState(int confState) async { | ||||||
|  |     final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); | ||||||
|  |     sharedPrefs.setInt(_CONFIG_STATE_KEY, confState); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> setUseS3(int value) async { | ||||||
|  |     final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); | ||||||
|  |     sharedPrefs.setInt(_USE_S3, value); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<int?> get useS3 async { | ||||||
|  |     final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance(); | ||||||
|  |     return sharedPrefs.getInt(_USE_S3); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,29 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | import 'colors.dart'; | ||||||
|  | 
 | ||||||
|  | class AppTheme { | ||||||
|  |   static getTheme() => ThemeData( | ||||||
|  |         // This is the theme of your application. | ||||||
|  |         // | ||||||
|  |         // Try running your application with "flutter run". You'll see the | ||||||
|  |         // application has a blue toolbar. Then, without quitting the app, try | ||||||
|  |         // changing the primarySwatch below to Colors.green and then invoke | ||||||
|  |         // "hot reload" (press "r" in the console where you ran "flutter run", | ||||||
|  |         // or simply save your changes to "hot reload" in a Flutter IDE). | ||||||
|  |         // Notice that the counter didn't reset back to zero; the application | ||||||
|  |         // is not restarted. | ||||||
|  |         primaryColor: primaryColor, | ||||||
|  |         primarySwatch: Colors.blue, | ||||||
|  |         backgroundColor: Colors.white, | ||||||
|  |         primaryTextTheme: TextTheme( | ||||||
|  |           headline6: TextStyle(color: Colors.white), | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | extension ExtendedRevoCheckTheme on TextTheme { | ||||||
|  |   //add custom styles and colors here | ||||||
|  |   //taken from https://medium.com/@crizantlai/flutter-how-to-extend-themedata-b5b987a95bb5 | ||||||
|  |   TextStyle get price => const TextStyle(color: Colors.redAccent); | ||||||
|  | } | ||||||
| @ -0,0 +1,13 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | const Color primaryColor = Colors.white; | ||||||
|  | const Color accentColor = Colors.blue; | ||||||
|  | const Color appBackgroundColor = Colors.white; | ||||||
|  | Color? accentColorDark = Colors.green[800]; | ||||||
|  | const Color borderColor = Colors.blueGrey; | ||||||
|  | Color? borderLightColor = Colors.blueGrey[50]; | ||||||
|  | Color backgroudColor = | ||||||
|  |     Colors.blueGrey[50]!.withOpacity(0.5) ?? Colors.transparent; | ||||||
|  | const Color iconColor = Colors.blueGrey; | ||||||
|  | Color? headingColor = Colors.blueGrey[800]; | ||||||
|  | Color? txtColor = Colors.blueGrey[500]; | ||||||
| @ -0,0 +1,36 @@ | |||||||
|  | import 'package:permission_handler/permission_handler.dart'; | ||||||
|  | 
 | ||||||
|  | import 'dialogs.dart'; | ||||||
|  | 
 | ||||||
|  | enum ConfirmAction { CANCEL, ACCEPT } | ||||||
|  | 
 | ||||||
|  | Future<bool> requestPermissionGranted( | ||||||
|  |     context, Permission requestPermissions) async { | ||||||
|  |   var result = await requestPermissions.request(); | ||||||
|  | 
 | ||||||
|  |   switch (result) { | ||||||
|  |     case PermissionStatus.granted: | ||||||
|  |       // Application has been given permission to use the feature. | ||||||
|  |       return true; | ||||||
|  |     case PermissionStatus.denied: | ||||||
|  |       // Application has been denied permission to use the feature. | ||||||
|  |       return false; | ||||||
|  |     case PermissionStatus.permanentlyDenied: | ||||||
|  |       ConfirmAction? res = await showConfirmDialogs( | ||||||
|  |           context, | ||||||
|  |           'You was denied Permission. You have give manual permission from app setting. ', | ||||||
|  |           'Open App Setting', | ||||||
|  |           'Cancel'); | ||||||
|  |       if (res == ConfirmAction.ACCEPT) { | ||||||
|  |         return false; | ||||||
|  |       } else if (res == ConfirmAction.CANCEL) { | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  |       return false; | ||||||
|  |     case PermissionStatus.restricted: | ||||||
|  |       // iOS has restricted access to a specific feature. | ||||||
|  |       return false; | ||||||
|  |     default: | ||||||
|  |       return false; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,35 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | import 'AppPermissionHandler.dart'; | ||||||
|  | 
 | ||||||
|  | Future<ConfirmAction?> showConfirmDialogs( | ||||||
|  |     context, msg, positiveText, negativeText) async { | ||||||
|  |   return showDialog<ConfirmAction>( | ||||||
|  |     context: context, | ||||||
|  |     barrierDismissible: false, | ||||||
|  |     builder: (context) { | ||||||
|  |       return AlertDialog( | ||||||
|  |         backgroundColor: Colors.white, | ||||||
|  |         title: Text(msg, style: TextStyle(fontSize: 16)), | ||||||
|  |         actions: <Widget>[ | ||||||
|  |           TextButton( | ||||||
|  |             child: Text( | ||||||
|  |               negativeText, | ||||||
|  |             ), | ||||||
|  |             onPressed: () { | ||||||
|  |               Navigator.of(context).pop(ConfirmAction.CANCEL); | ||||||
|  |             }, | ||||||
|  |           ), | ||||||
|  |           TextButton( | ||||||
|  |             child: Text( | ||||||
|  |               positiveText, | ||||||
|  |             ), | ||||||
|  |             onPressed: () { | ||||||
|  |               Navigator.of(context).pop(ConfirmAction.ACCEPT); | ||||||
|  |             }, | ||||||
|  |           ) | ||||||
|  |         ], | ||||||
|  |       ); | ||||||
|  |     }, | ||||||
|  |   ); | ||||||
|  | } | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | navigateWithName(BuildContext context, String routeName, {Object? arguments}) { | ||||||
|  |   Navigator.pushNamed(context, routeName, arguments: arguments); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pop(BuildContext context) { | ||||||
|  |   Navigator.of(context).pop(); | ||||||
|  | } | ||||||
| @ -0,0 +1,311 @@ | |||||||
|  | import 'dart:convert'; | ||||||
|  | import 'dart:io'; | ||||||
|  | import 'dart:typed_data'; | ||||||
|  | import 'dart:ui'; | ||||||
|  | 
 | ||||||
|  | import 'package:mohem_flutter_app/config/constants.dart'; | ||||||
|  | import 'package:mohem_flutter_app/theme/colors.dart'; | ||||||
|  | import 'package:mohem_flutter_app/widgets/txt.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:flutter_svg/svg.dart'; | ||||||
|  | 
 | ||||||
|  | import 'package:sizer/sizer.dart'; | ||||||
|  | 
 | ||||||
|  | Color getColorFromHex(String hexColor) { | ||||||
|  |   hexColor = hexColor.toUpperCase().replaceAll('#', ''); | ||||||
|  | 
 | ||||||
|  |   if (hexColor.length == 6) { | ||||||
|  |     hexColor = 'FF' + hexColor; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return Color(int.parse(hexColor, radix: 16)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Widget spacerVertical(double v) { | ||||||
|  |   return Container( | ||||||
|  |     height: v, | ||||||
|  |     width: double.infinity, | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | Future delay(int millis) async { | ||||||
|  |   return await Future.delayed(Duration(milliseconds: millis)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | inkWellCorner({double? r}) { | ||||||
|  |   return RoundedRectangleBorder( | ||||||
|  |     borderRadius: BorderRadius.circular(r ?? 4), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Widget spacerHorizontal(double v) { | ||||||
|  |   return Container( | ||||||
|  |     height: v, | ||||||
|  |     width: v, | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Widget mHeight(double f) { | ||||||
|  |   return Container( | ||||||
|  |     width: f, | ||||||
|  |     height: f, | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Widget mDivider(Color color, {double? h}) { | ||||||
|  |   return Container( | ||||||
|  |     width: double.infinity, | ||||||
|  |     height: h ?? 1, | ||||||
|  |     color: color, | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Widget mDivider3({double? h}) { | ||||||
|  |   return Container( | ||||||
|  |     width: double.infinity, | ||||||
|  |     height: h ?? 1, | ||||||
|  |     color: borderLightColor!.withOpacity(0.7) ?? Colors.transparent, | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Widget mDivider2(Color color, double w) { | ||||||
|  |   return Container( | ||||||
|  |     width: w, | ||||||
|  |     height: 1, | ||||||
|  |     color: color, | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | InputDecoration txtField(String label) { | ||||||
|  |   return new InputDecoration( | ||||||
|  |     border: InputBorder.none, | ||||||
|  |     focusedBorder: InputBorder.none, | ||||||
|  |     enabledBorder: InputBorder.none, | ||||||
|  |     errorBorder: InputBorder.none, | ||||||
|  |     hintText: label, | ||||||
|  |     hintStyle: TextStyle(color: Colors.grey), | ||||||
|  |     disabledBorder: InputBorder.none, | ||||||
|  |     isDense: false, | ||||||
|  |     contentPadding: EdgeInsets.only(left: 15, right: 15), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Widget mWidth(double f) { | ||||||
|  |   return Container( | ||||||
|  |     width: f, | ||||||
|  |     height: f, | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Widget mFlex(int f) { | ||||||
|  |   return Flexible( | ||||||
|  |     flex: f, | ||||||
|  |     child: Container( | ||||||
|  |       width: double.infinity, | ||||||
|  |       height: double.infinity, | ||||||
|  |     ), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | Widget mExp(int f) { | ||||||
|  |   return Expanded( | ||||||
|  |     flex: f, | ||||||
|  |     child: Container( | ||||||
|  |       width: double.infinity, | ||||||
|  |     ), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | spacer() { | ||||||
|  |   return SizedBox( | ||||||
|  |     height: 8, | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Widget floatButton(String icon, {Color? color, required Function onClick, String? title}) { | ||||||
|  |   return Padding( | ||||||
|  |     padding: const EdgeInsets.only(top: 12, bottom: 12), | ||||||
|  |     child: Column( | ||||||
|  |       crossAxisAlignment: CrossAxisAlignment.center, | ||||||
|  |       mainAxisAlignment: MainAxisAlignment.center, | ||||||
|  |       children: [ | ||||||
|  |         FloatingActionButton( | ||||||
|  |           onPressed: () { | ||||||
|  |             onClick(); | ||||||
|  |           }, | ||||||
|  |           heroTag: icon, | ||||||
|  |           backgroundColor: accentColor, | ||||||
|  |           elevation: 4, | ||||||
|  |           child: Container( | ||||||
|  |             child: SvgPicture.asset( | ||||||
|  |               categorySvgIcons + icon, | ||||||
|  |               color: color, | ||||||
|  |             ), | ||||||
|  |             width: double.infinity, | ||||||
|  |             height: double.infinity, | ||||||
|  |             decoration: containerRadius(Colors.white, 200), | ||||||
|  |             clipBehavior: Clip.antiAlias, | ||||||
|  |             padding: EdgeInsets.all(15), | ||||||
|  |             margin: EdgeInsets.all(1), | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |         if (title != null) mHeight(2.w), | ||||||
|  |         if (title != null) | ||||||
|  |           Txt( | ||||||
|  |             title, | ||||||
|  |             fontSize: 12.sp, | ||||||
|  |             bold: true, | ||||||
|  |             color: headingColor, | ||||||
|  |           ) | ||||||
|  |       ], | ||||||
|  |     ), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | navigateTo(context, page) { | ||||||
|  |   Navigator.push(context, MaterialPageRoute(builder: (context) => page)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | circularImage(String im, double width, double height) { | ||||||
|  |   return new Container(width: 190.0, height: 190.0, decoration: new BoxDecoration(shape: BoxShape.circle, image: new DecorationImage(fit: BoxFit.fill, image: new AssetImage(im)))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | circularImage2(String im, double width, double height) { | ||||||
|  |   return new Container(width: width, height: height, decoration: new BoxDecoration(shape: BoxShape.circle, image: new DecorationImage(fit: BoxFit.fill, image: new AssetImage(im)))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | cardRadius(double radius) { | ||||||
|  |   return RoundedRectangleBorder( | ||||||
|  |     side: BorderSide(color: Colors.transparent, width: 1), | ||||||
|  |     borderRadius: BorderRadius.circular(radius), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | cardRadiusWithoutBorder(double radius) { | ||||||
|  |   return RoundedRectangleBorder( | ||||||
|  |     side: BorderSide(color: Colors.transparent, width: 1), | ||||||
|  |     borderRadius: BorderRadius.circular(radius), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Image imageFromBase64String(String base64String) { | ||||||
|  |   return Image.memory(base64Decode(base64String)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Uint8List dataFromBase64String(String base64String) { | ||||||
|  |   return base64Decode(base64String); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | String base64String(Uint8List data) { | ||||||
|  |   return base64Encode(data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Widget overLayWidget({double? width, double? height,List<Color>? color}) { | ||||||
|  |   return Container( | ||||||
|  |     width: width ?? double.infinity, | ||||||
|  |     height: height ?? 60, | ||||||
|  |     decoration: BoxDecoration( | ||||||
|  |       gradient: LinearGradient( | ||||||
|  |         colors: color!=null?color:[ | ||||||
|  |           Colors.black.withOpacity(0.2), | ||||||
|  |           Colors.black.withOpacity(0.1), | ||||||
|  |           Colors.black.withOpacity(0.004), | ||||||
|  |         ], | ||||||
|  |         begin: Alignment.topCenter, | ||||||
|  |         end: Alignment.bottomCenter, | ||||||
|  |         tileMode: TileMode.clamp, | ||||||
|  |       ), | ||||||
|  |     ), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Decoration containerRadius(Color color, double r) { | ||||||
|  |   return BoxDecoration( | ||||||
|  |     color: color, | ||||||
|  |     borderRadius: BorderRadius.all(Radius.circular(r)), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Decoration containerRadiusTop({Color? color, double? r}) { | ||||||
|  |   return BoxDecoration( | ||||||
|  |     color: color ?? Colors.white, | ||||||
|  |     borderRadius: BorderRadius.only(topRight: Radius.circular(r ?? 12), topLeft: Radius.circular(r ?? 12)), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Decoration containerRadiusBorder(Color color, double r) { | ||||||
|  |   return BoxDecoration( | ||||||
|  |     color: Colors.transparent, | ||||||
|  |     border: Border.all(color: color, width: 1), | ||||||
|  |     borderRadius: BorderRadius.all(Radius.circular(r)), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Decoration containerRadiusBottom(Color color, double r) { | ||||||
|  |   return BoxDecoration( | ||||||
|  |     color: color, | ||||||
|  |     borderRadius: BorderRadius.only(bottomLeft: Radius.circular(r), bottomRight: Radius.circular(r)), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ShapeBorder cardRadiusTop(double radius) { | ||||||
|  |   return RoundedRectangleBorder( | ||||||
|  |     side: BorderSide(color: Colors.transparent, width: 0), | ||||||
|  |     borderRadius: BorderRadius.only(topLeft: Radius.circular(radius), topRight: Radius.circular(radius)), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Decoration containerColorRadiusBorderWidth(Color background, double radius, Color color, double w) { | ||||||
|  |   return BoxDecoration( | ||||||
|  |     color: background, | ||||||
|  |     border: Border.all( | ||||||
|  |         width: w, // | ||||||
|  |         color: color //                  <--- border width here | ||||||
|  |         ), | ||||||
|  |     borderRadius: BorderRadius.circular(radius), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ShapeBorder cardRadiusTop2(double radius) { | ||||||
|  |   return RoundedRectangleBorder( | ||||||
|  |     borderRadius: BorderRadius.only(topLeft: Radius.circular(radius), topRight: Radius.circular(radius)), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ShapeBorder cardRadiusBottom(double radius) { | ||||||
|  |   return RoundedRectangleBorder( | ||||||
|  |     borderRadius: BorderRadius.only(bottomLeft: Radius.circular(radius), bottomRight: Radius.circular(radius)), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Decoration containerColorRadiusBorder(Color background, double radius, Color color) { | ||||||
|  |   return BoxDecoration( | ||||||
|  |     color: background, | ||||||
|  |     border: Border.all( | ||||||
|  |         width: 1, // | ||||||
|  |         color: color //                  <--- border width here | ||||||
|  |         ), | ||||||
|  |     borderRadius: BorderRadius.circular(radius), | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //Decoration appGradient = BoxDecoration( | ||||||
|  | //  gradient: LinearGradient( | ||||||
|  | //    colors: [ | ||||||
|  | //      Colors.green[200], | ||||||
|  | //      Colors.green, | ||||||
|  | //    ], | ||||||
|  | //    begin: Alignment.topCenter, | ||||||
|  | //    end: Alignment.bottomCenter, | ||||||
|  | //  ), | ||||||
|  | //); | ||||||
|  | // launchURL(String url) async { | ||||||
|  | //   if (await canLaunch(url)) { | ||||||
|  | //     await launch(url); | ||||||
|  | //   } else { | ||||||
|  | //     throw 'Could not launch $url'; | ||||||
|  | //   } | ||||||
|  | // } | ||||||
| @ -0,0 +1,28 @@ | |||||||
|  | import 'package:mohem_flutter_app/theme/colors.dart'; | ||||||
|  | import 'package:mohem_flutter_app/widgets/txt.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:sizer/sizer.dart'; | ||||||
|  | 
 | ||||||
|  | AppBar appBar({ | ||||||
|  |   Color? backgroundColor, | ||||||
|  |   double? elevation, | ||||||
|  |   String? title, | ||||||
|  |   Color? titleColor, | ||||||
|  |   bool? isTitleCenter, | ||||||
|  |   Color? backIconColor, | ||||||
|  |   List<Widget>? actions, | ||||||
|  | }) { | ||||||
|  |   return AppBar( | ||||||
|  |     backgroundColor: backgroundColor ?? appBackgroundColor, | ||||||
|  |     elevation: elevation ?? 0, | ||||||
|  |     centerTitle: isTitleCenter ?? true, | ||||||
|  |     iconTheme: IconThemeData( | ||||||
|  |       color: backIconColor ?? Colors.black, //change your color here | ||||||
|  |     ), | ||||||
|  |     actions: actions, | ||||||
|  |     title: Txt( | ||||||
|  |       title ?? "", | ||||||
|  |       txtType: TxtType.appBar, | ||||||
|  |     ), | ||||||
|  |   ); | ||||||
|  | } | ||||||
| @ -0,0 +1,62 @@ | |||||||
|  | import 'dart:ui'; | ||||||
|  | 
 | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | const kDemoText = Center( | ||||||
|  |   child: Text( | ||||||
|  |     '', | ||||||
|  |     style: TextStyle( | ||||||
|  |       fontSize: 25, | ||||||
|  |       color: Colors.white, | ||||||
|  |       letterSpacing: 2, | ||||||
|  |     ), | ||||||
|  |     textAlign: TextAlign.center, | ||||||
|  |   ), | ||||||
|  | ); | ||||||
|  | const double kBlur = 1.0; | ||||||
|  | const EdgeInsetsGeometry kDefaultPadding = EdgeInsets.all(16); | ||||||
|  | const Color kDefaultColor = Colors.transparent; | ||||||
|  | const BorderRadius kBorderRadius = BorderRadius.all(Radius.circular(20)); | ||||||
|  | const double kColorOpacity = 0.0; | ||||||
|  | 
 | ||||||
|  | class BlurryContainer extends StatelessWidget { | ||||||
|  |   final Widget child; | ||||||
|  |   final double blur; | ||||||
|  |   final double? height, width; | ||||||
|  |   final EdgeInsetsGeometry padding; | ||||||
|  |   final Color bgColor; | ||||||
|  | 
 | ||||||
|  |   final BorderRadius borderRadius; | ||||||
|  | 
 | ||||||
|  |   //final double colorOpacity; | ||||||
|  | 
 | ||||||
|  |   BlurryContainer({ | ||||||
|  |     this.child = kDemoText, | ||||||
|  |     this.blur = 5, | ||||||
|  |     required this.height, | ||||||
|  |     required this.width, | ||||||
|  |     this.padding = kDefaultPadding, | ||||||
|  |     this.bgColor = kDefaultColor, | ||||||
|  |     this.borderRadius = kBorderRadius, | ||||||
|  |     //this.colorOpacity = kColorOpacity, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return ClipRRect( | ||||||
|  |       borderRadius: borderRadius, | ||||||
|  |       child: BackdropFilter( | ||||||
|  |         filter: ImageFilter.blur(sigmaX: blur, sigmaY: blur), | ||||||
|  |         child: Container( | ||||||
|  |           height: height!, | ||||||
|  |           width: width!, | ||||||
|  |           padding: padding, | ||||||
|  |           color: bgColor == Colors.transparent | ||||||
|  |               ? bgColor | ||||||
|  |               : bgColor.withOpacity(0.5), | ||||||
|  |           child: child, | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | import 'package:mohem_flutter_app/utils/utils.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | class ShowCircularButton extends StatelessWidget { | ||||||
|  |   VoidCallback onPressed; | ||||||
|  |   IconData? iconData; | ||||||
|  |   ShowCircularButton({this.iconData,required this.onPressed}); | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Card( | ||||||
|  |       shape: cardRadius(1000), | ||||||
|  |       color: Colors.black.withOpacity(0.2), | ||||||
|  |       margin: EdgeInsets.all(12), | ||||||
|  |       child: IconButton( | ||||||
|  |         onPressed: onPressed, | ||||||
|  |         icon: Icon( | ||||||
|  |           iconData?? Icons.amp_stories_outlined, | ||||||
|  |           color: Colors.white, | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | import 'package:mohem_flutter_app/theme/colors.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/utils.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | import '../txt.dart'; | ||||||
|  | 
 | ||||||
|  | class ShowImageButton extends StatelessWidget { | ||||||
|  |   String icon, title; | ||||||
|  |   VoidCallback onClick; | ||||||
|  | 
 | ||||||
|  |   ShowImageButton( | ||||||
|  |       {required this.icon, required this.title, required this.onClick}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return InkWell( | ||||||
|  |       onTap: onClick, | ||||||
|  |       child: Container( | ||||||
|  |         width: double.infinity, | ||||||
|  |         child: Column( | ||||||
|  |           children: [ | ||||||
|  |             Container( | ||||||
|  |               width: double.infinity, | ||||||
|  |               height: 120, | ||||||
|  |               color: accentColor, | ||||||
|  |               padding: EdgeInsets.all(30), | ||||||
|  |               child: Image.asset( | ||||||
|  |                 icon, | ||||||
|  |                 color: Colors.white, | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |             mHeight(12), | ||||||
|  |             Txt( | ||||||
|  |               title, | ||||||
|  |               txtType: TxtType.heading2, | ||||||
|  |               color: Colors.blue, | ||||||
|  |             ) | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,16 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | void showMDialog( | ||||||
|  |   context, { | ||||||
|  |   Widget? child, | ||||||
|  | }) async { | ||||||
|  |   return showDialog( | ||||||
|  |     context: context, | ||||||
|  |     barrierDismissible: true, | ||||||
|  |     builder: (context) { | ||||||
|  |       return Dialog( | ||||||
|  |         child: child, | ||||||
|  |       ); | ||||||
|  |     }, | ||||||
|  |   ); | ||||||
|  | } | ||||||
| @ -0,0 +1,38 @@ | |||||||
|  | import 'package:mohem_flutter_app/theme/colors.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/navigator.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/utils.dart'; | ||||||
|  | import 'package:mohem_flutter_app/widgets/show_fill_button.dart'; | ||||||
|  | import 'package:mohem_flutter_app/widgets/txt.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | class MessageDialog extends StatelessWidget { | ||||||
|  |   String? title, buttonTitle; | ||||||
|  |   VoidCallback? onClick; | ||||||
|  |   MessageDialog({this.title, this.buttonTitle,this.onClick}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Container( | ||||||
|  |       color: Colors.white, | ||||||
|  |       padding: EdgeInsets.all(30), | ||||||
|  |       child: Column( | ||||||
|  |         mainAxisSize: MainAxisSize.min, | ||||||
|  |         crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |         children: [ | ||||||
|  |           Txt( | ||||||
|  |             title ?? "message", | ||||||
|  |             txtType: TxtType.heading3, | ||||||
|  |           ), | ||||||
|  |           mHeight(40), | ||||||
|  |           ShowFillButton( | ||||||
|  |             title: buttonTitle ?? "Continue", | ||||||
|  |             width: double.infinity, | ||||||
|  |             onPressed: () { | ||||||
|  |               onClick!(); | ||||||
|  |             }, | ||||||
|  |           ) | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,74 @@ | |||||||
|  | import 'package:mohem_flutter_app/theme/colors.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/navigator.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/utils.dart'; | ||||||
|  | import 'package:mohem_flutter_app/widgets/show_fill_button.dart'; | ||||||
|  | import 'package:mohem_flutter_app/widgets/txt.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | class OtpDialog extends StatelessWidget { | ||||||
|  |   VoidCallback onClick; | ||||||
|  | 
 | ||||||
|  |   OtpDialog({required this.onClick}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Container( | ||||||
|  |       color: Colors.white, | ||||||
|  |       padding: EdgeInsets.all(30), | ||||||
|  |       child: Column( | ||||||
|  |         mainAxisSize: MainAxisSize.min, | ||||||
|  |         crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|  |         children: [ | ||||||
|  |           Txt( | ||||||
|  |             "Please insert OTP Code", | ||||||
|  |             txtType: TxtType.heading3, | ||||||
|  |           ), | ||||||
|  |           mHeight(20), | ||||||
|  |           Row( | ||||||
|  |             children: [ | ||||||
|  |               Expanded( | ||||||
|  |                 child: Container( | ||||||
|  |                   width: double.infinity, | ||||||
|  |                   height: 60, | ||||||
|  |                   color: accentColor.withOpacity(0.3), | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |               mWidth(12), | ||||||
|  |               Expanded( | ||||||
|  |                 child: Container( | ||||||
|  |                   width: double.infinity, | ||||||
|  |                   height: 60, | ||||||
|  |                   color: accentColor.withOpacity(0.3), | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |               mWidth(12), | ||||||
|  |               Expanded( | ||||||
|  |                 child: Container( | ||||||
|  |                   width: double.infinity, | ||||||
|  |                   height: 60, | ||||||
|  |                   color: accentColor.withOpacity(0.3), | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |               mWidth(12), | ||||||
|  |               Expanded( | ||||||
|  |                 child: Container( | ||||||
|  |                   width: double.infinity, | ||||||
|  |                   height: 60, | ||||||
|  |                   color: accentColor.withOpacity(0.3), | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ], | ||||||
|  |           ), | ||||||
|  |           mHeight(40), | ||||||
|  |           ShowFillButton( | ||||||
|  |             title: "Check Code", | ||||||
|  |             width: double.infinity, | ||||||
|  |             onPressed: () { | ||||||
|  |               onClick(); | ||||||
|  |             }, | ||||||
|  |           ) | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,26 @@ | |||||||
|  | import 'package:flutter/cupertino.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | showDraggableDialog(BuildContext context, Widget child) { | ||||||
|  |   showGeneralDialog( | ||||||
|  |     barrierLabel: "Label", | ||||||
|  |     barrierDismissible: false, | ||||||
|  |     barrierColor: Colors.black.withOpacity(0.2), | ||||||
|  |     transitionDuration: Duration(milliseconds: 200), | ||||||
|  |     context: context, | ||||||
|  |     pageBuilder: (context, anim1, anim2) { | ||||||
|  |       return Dismissible( | ||||||
|  |         direction: DismissDirection.vertical, | ||||||
|  |         key: const Key('key'), | ||||||
|  |         onDismissed: (_) => Navigator.of(context).pop(), | ||||||
|  |         child: child, | ||||||
|  |       ); | ||||||
|  |     }, | ||||||
|  |     transitionBuilder: (context, anim1, anim2, child) { | ||||||
|  |       return SlideTransition( | ||||||
|  |         position: Tween(begin: Offset(0, 1), end: Offset(0, 0)).animate(anim1), | ||||||
|  |         child: child, | ||||||
|  |       ); | ||||||
|  |     }, | ||||||
|  |   ); | ||||||
|  | } | ||||||
| @ -0,0 +1,78 @@ | |||||||
|  | import 'package:mohem_flutter_app/theme/colors.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/utils.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:mohem_flutter_app/theme/colors.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/utils.dart'; | ||||||
|  | 
 | ||||||
|  | import '../txt.dart'; | ||||||
|  | 
 | ||||||
|  | class DropdownField extends StatefulWidget { | ||||||
|  |   String? hint; | ||||||
|  |   List<String>? list; | ||||||
|  | 
 | ||||||
|  |   DropdownField({this.hint, this.list}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   State<DropdownField> createState() => _DropdownFieldState(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class _DropdownFieldState extends State<DropdownField> { | ||||||
|  |   String? dropdownValue; | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Container( | ||||||
|  |       decoration: containerColorRadiusBorderWidth( | ||||||
|  |         Colors.transparent, | ||||||
|  |         4, | ||||||
|  |         borderColor, | ||||||
|  |         0.5, | ||||||
|  |       ), | ||||||
|  |       margin: EdgeInsets.all(2), | ||||||
|  |       padding: EdgeInsets.only(left: 8, right: 8), | ||||||
|  |       child: DropdownButton<String>( | ||||||
|  |         value: dropdownValue, | ||||||
|  |         icon: const Icon(Icons.keyboard_arrow_down_sharp), | ||||||
|  |         elevation: 16, | ||||||
|  |         iconSize: 16, | ||||||
|  |         iconEnabledColor: borderColor, | ||||||
|  |         iconDisabledColor: borderColor, | ||||||
|  |         isExpanded: true, | ||||||
|  |         style: const TextStyle(color: Colors.black), | ||||||
|  |         hint: Txt( | ||||||
|  |           widget.hint ?? "", | ||||||
|  |           txtType: TxtType.heading1, | ||||||
|  |           bold: false, | ||||||
|  |           color: borderColor, | ||||||
|  |         ), | ||||||
|  |         underline: Container( | ||||||
|  |           height: 0, | ||||||
|  |         ), | ||||||
|  |         onChanged: (String? newValue) { | ||||||
|  |           setState(() { | ||||||
|  |             dropdownValue = newValue!; | ||||||
|  |           }); | ||||||
|  |         }, | ||||||
|  |         items: (widget.list ?? | ||||||
|  |                 <String>[ | ||||||
|  |                   'One', | ||||||
|  |                   'Two', | ||||||
|  |                   'Free', | ||||||
|  |                   'Four', | ||||||
|  |                 ]) | ||||||
|  |             .map<DropdownMenuItem<String>>( | ||||||
|  |           (String value) { | ||||||
|  |             return DropdownMenuItem<String>( | ||||||
|  |               value: value, | ||||||
|  |               child: Txt( | ||||||
|  |                 value, | ||||||
|  |                 txtType: TxtType.heading1, | ||||||
|  |                 bold: false, | ||||||
|  |               ), | ||||||
|  |             ); | ||||||
|  |           }, | ||||||
|  |         ).toList(), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,33 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:flutter_svg/flutter_svg.dart'; | ||||||
|  | import 'package:mohem_flutter_app/config/constants.dart'; | ||||||
|  | import 'package:mohem_flutter_app/theme/colors.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/utils.dart'; | ||||||
|  | import 'package:mohem_flutter_app/widgets/txt.dart'; | ||||||
|  | 
 | ||||||
|  | class DropDownText extends StatelessWidget { | ||||||
|  |   String title; | ||||||
|  | 
 | ||||||
|  |   DropDownText(this.title); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Row( | ||||||
|  |       crossAxisAlignment: CrossAxisAlignment.center, | ||||||
|  |       mainAxisAlignment: MainAxisAlignment.center, | ||||||
|  |       children: [ | ||||||
|  |         Txt( | ||||||
|  |           title, | ||||||
|  |           txtType: TxtType.heading3, | ||||||
|  |           color: accentColor, | ||||||
|  |         ), | ||||||
|  |         mWidth(16), | ||||||
|  |         SvgPicture.asset( | ||||||
|  |           svgIcons + "ic_arrow_down.svg", | ||||||
|  |           width: 10, | ||||||
|  |           height: 10, | ||||||
|  |         ), | ||||||
|  |       ], | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,235 @@ | |||||||
|  | import 'dart:math'; | ||||||
|  | 
 | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | extension ExtendedText on Widget { | ||||||
|  |   showOverlay({double? width, double? height}){ | ||||||
|  |     return Container( | ||||||
|  |       width: width ?? double.infinity, | ||||||
|  |       height: height ?? 60, | ||||||
|  |       decoration: BoxDecoration( | ||||||
|  |         gradient: LinearGradient(colors: [ | ||||||
|  |           Colors.black.withOpacity(0.2), | ||||||
|  |           Colors.black.withOpacity(0.1), | ||||||
|  |           Colors.black.withOpacity(0.004), | ||||||
|  |         ], begin: Alignment.topCenter, end: Alignment.bottomCenter, tileMode: TileMode.clamp), | ||||||
|  |       ), | ||||||
|  |       child: this, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | extension ImageExt on Image { | ||||||
|  |   Widget circular() { | ||||||
|  |     return ClipRRect( | ||||||
|  |       clipBehavior: Clip.hardEdge, | ||||||
|  |       borderRadius: BorderRadius.circular(100), | ||||||
|  |       child: this, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | extension WidgetExt on Widget { | ||||||
|  |   Widget toWidget() { | ||||||
|  |     return this as Widget; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Widget sized({double? width, double? height}) { | ||||||
|  |     return SizedBox( | ||||||
|  |       width: width, | ||||||
|  |       height: height, | ||||||
|  |       child: this, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |   Widget inkWell({required VoidCallback onTap,double radius=0}){ | ||||||
|  |     return InkWell( | ||||||
|  |       child: Material(child: this,color: Colors.transparent,), | ||||||
|  |       onTap: onTap, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |   Widget sizeSq(double size) { | ||||||
|  |     return SizedBox( | ||||||
|  |       width: size, | ||||||
|  |       height: size, | ||||||
|  |       child: this, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Widget fillParent({double hFactor = 1, double? vFactor}) { | ||||||
|  |     return FractionallySizedBox( | ||||||
|  |       heightFactor: null, | ||||||
|  |       widthFactor: hFactor, | ||||||
|  |       child: this, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Widget margin( | ||||||
|  |       {double top = 0, double bottom = 0, double left = 0, double right = 0}) { | ||||||
|  |     var pad = | ||||||
|  |     EdgeInsets.only(top: top, left: left, bottom: bottom, right: right); | ||||||
|  |     try { | ||||||
|  |       (this as dynamic).margin = pad; | ||||||
|  |     } catch (err) { | ||||||
|  |       return Padding( | ||||||
|  |         padding: pad, | ||||||
|  |         child: this, | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |     return this; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Widget toClip({double r = 40}) { | ||||||
|  |     return ClipRRect( | ||||||
|  |       borderRadius: BorderRadius.all( | ||||||
|  |         Radius.circular(r), | ||||||
|  |       ), | ||||||
|  |       clipBehavior: Clip.antiAlias, | ||||||
|  |       child: this, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Widget scrollable({Axis? direction, bool fadingEdge = true}) { | ||||||
|  |   //   var scrollview = SingleChildScrollView( | ||||||
|  |   //     child: this, | ||||||
|  |   //     controller: ScrollController(), | ||||||
|  |   //     scrollDirection: direction ?? Axis.vertical, | ||||||
|  |   //   ); | ||||||
|  |   //   return fadingEdge ? scrollview.fadingEdge() : scrollview; | ||||||
|  |   // } | ||||||
|  | 
 | ||||||
|  |   Widget expand() { | ||||||
|  |     return Expanded( | ||||||
|  |       child: this, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Widget align(Alignment alignment) { | ||||||
|  |     return Align( | ||||||
|  |       alignment: alignment, | ||||||
|  |       child: this, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Widget center() { | ||||||
|  |     return Center( | ||||||
|  |       child: this, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Widget padding(EdgeInsets padding) { | ||||||
|  |     return Padding( | ||||||
|  |       padding: padding, | ||||||
|  |       child: this, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Widget paddingAll(double padding) { | ||||||
|  |     return Padding( | ||||||
|  |       padding: EdgeInsets.all(padding), | ||||||
|  |       child: this, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Widget onTap(VoidCallback onTap, {double corners = 0}) { | ||||||
|  |   //   return Clickable.widget(child: this, corners: corners, onTap: onTap); | ||||||
|  |   // } | ||||||
|  | 
 | ||||||
|  |   Widget ignoreInteraction() { | ||||||
|  |     return IgnorePointer( | ||||||
|  |       child: this, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // extension xScrollView on ScrollView { | ||||||
|  | //   Widget fadingEdge() => FadingEdgeScrollView.fromScrollView( | ||||||
|  | //     child: this, | ||||||
|  | //     gradientFractionOnEnd: 0.08, | ||||||
|  | //     gradientFractionOnStart: 0.08, | ||||||
|  | //     shouldDisposeScrollController: true, | ||||||
|  | //   ); | ||||||
|  | // } | ||||||
|  | // | ||||||
|  | // extension x2ScrollView on SingleChildScrollView { | ||||||
|  | //   Widget fadingEdge() => FadingEdgeScrollView.fromSingleChildScrollView( | ||||||
|  | //     child: this, | ||||||
|  | //     gradientFractionOnEnd: 0.08, | ||||||
|  | //     gradientFractionOnStart: 0.08, | ||||||
|  | //     shouldDisposeScrollController: true, | ||||||
|  | //   ); | ||||||
|  | // } | ||||||
|  | 
 | ||||||
|  | class Position { | ||||||
|  |   final double x, y, w, h; | ||||||
|  | 
 | ||||||
|  |   Position(this.x, this.y, this.w, this.h); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | extension KeyExt on GlobalKey { | ||||||
|  |   Position globalPosition() { | ||||||
|  |     RenderBox box = currentContext!.findRenderObject() as RenderBox; | ||||||
|  |     Offset xy = box.localToGlobal(Offset.zero); | ||||||
|  |     Size wh = box.size; | ||||||
|  |     return Position(xy.dx, xy.dy, wh.width, wh.height); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | extension StateExt on State { | ||||||
|  |   reload({VoidCallback? b}) { | ||||||
|  |     setState(b ?? () {}); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // extension LocatiionExt on Location { | ||||||
|  | //   LatLng toLatLng() { | ||||||
|  | //     return LatLng(lat!, lng!); | ||||||
|  | //   } | ||||||
|  | // } | ||||||
|  | 
 | ||||||
|  | // extension xList<T> on List<T> { | ||||||
|  | //   T randomItem() { | ||||||
|  | //     final random = new Random(); | ||||||
|  | //     var i = random.nextInt(this.length); | ||||||
|  | //     return this[i]; | ||||||
|  | //   } | ||||||
|  | // | ||||||
|  | //   List<T> append(List<T> items) { | ||||||
|  | //     this.addAll(items); | ||||||
|  | //     return this; | ||||||
|  | //   } | ||||||
|  | // | ||||||
|  | //   bool isFirst(T item) => first == item; | ||||||
|  | // | ||||||
|  | //   bool isLast(T item) => last == item; | ||||||
|  | // | ||||||
|  | //   getOneByOne( | ||||||
|  | //       {required int delayMillis, | ||||||
|  | //       required Function(T) callback, VoidCallback? complete}) async { | ||||||
|  | //     for (var i in this) { | ||||||
|  | //       await delay(delayMillis); | ||||||
|  | //       callback(i); | ||||||
|  | //     } | ||||||
|  | //     complete!(); | ||||||
|  | //   } | ||||||
|  | // } | ||||||
|  | 
 | ||||||
|  | extension xFuture<T> on Future<T?> { | ||||||
|  |   thenWithDelay(int millis, Function(T) thenBlock) { | ||||||
|  |     then((value) { | ||||||
|  |       Future.delayed(Duration(milliseconds: millis)) | ||||||
|  |           .then((value) => thenBlock(value)); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | extension xDouble on int { | ||||||
|  |   Duration durationMillis() => Duration(milliseconds: this); | ||||||
|  | 
 | ||||||
|  |   Duration durationSec() => Duration(seconds: this); | ||||||
|  | 
 | ||||||
|  |   Duration durationHour() => Duration(hours: this); | ||||||
|  | } | ||||||
| @ -0,0 +1,63 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | class GradientAppBar extends StatelessWidget { | ||||||
|  |   final String title; | ||||||
|  |   final double barHeight = 50.0; | ||||||
|  |   IconData? iconData; | ||||||
|  | 
 | ||||||
|  |   GradientAppBar(this.title, {this.iconData}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     final double statusbarHeight = MediaQuery.of(context).padding.top; | ||||||
|  | 
 | ||||||
|  |     return new Container( | ||||||
|  |       padding: EdgeInsets.only(top: statusbarHeight), | ||||||
|  |       height: statusbarHeight + barHeight, | ||||||
|  |       child: Row( | ||||||
|  |         children: [ | ||||||
|  |           IconButton( | ||||||
|  |             onPressed: () { | ||||||
|  |               Navigator.pop(context); | ||||||
|  |             }, | ||||||
|  |             icon: Icon( | ||||||
|  |               Icons.arrow_back_ios, | ||||||
|  |               color: Colors.white, | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           Expanded( | ||||||
|  |             child: Center( | ||||||
|  |               child: Text( | ||||||
|  |                 title, | ||||||
|  |                 style: TextStyle( | ||||||
|  |                     fontSize: 20.0, | ||||||
|  |                     color: Colors.white, | ||||||
|  |                     fontWeight: FontWeight.bold), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           if (iconData != null) | ||||||
|  |             IconButton( | ||||||
|  |               onPressed: () {}, | ||||||
|  |               icon: Icon( | ||||||
|  |                 iconData, | ||||||
|  |                 color: Colors.white, | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |       decoration: BoxDecoration( | ||||||
|  |         gradient: LinearGradient( | ||||||
|  |           colors: [ | ||||||
|  |             Colors.black.withOpacity(0.4), | ||||||
|  |             Colors.black.withOpacity(0.2), | ||||||
|  |             Colors.black.withOpacity(0.0001), | ||||||
|  |           ], | ||||||
|  |           begin: Alignment.topCenter, | ||||||
|  |           end: Alignment.bottomCenter, | ||||||
|  |           tileMode: TileMode.clamp, | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,30 @@ | |||||||
|  | import 'package:mohem_flutter_app/config/constants.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/utils.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | class CircularImage extends StatelessWidget { | ||||||
|  |   double? w, h, padding; | ||||||
|  |   String? image; | ||||||
|  | 
 | ||||||
|  |   CircularImage({this.w, this.h, this.image, this.padding}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Container( | ||||||
|  |       width: w ?? 120, | ||||||
|  |       height: h ?? 120, | ||||||
|  |       child: Card( | ||||||
|  |         shape: cardRadius(2000), | ||||||
|  |         clipBehavior: Clip.antiAlias, | ||||||
|  |         elevation: 4, | ||||||
|  |         child: Card( | ||||||
|  |           shape: cardRadius(2000), | ||||||
|  |           clipBehavior: Clip.antiAlias, | ||||||
|  |           elevation: 0, | ||||||
|  |           margin: EdgeInsets.all(padding ?? 0), | ||||||
|  |           child: Image.asset(image ?? icons + "green.jpg"), | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,32 @@ | |||||||
|  | import 'package:mohem_flutter_app/theme/colors.dart'; | ||||||
|  | import 'package:mohem_flutter_app/widgets/show_fill_button.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | class ShowCardButton extends StatelessWidget { | ||||||
|  |   String title; | ||||||
|  |   VoidCallback onPressed; | ||||||
|  |   Color txtColor; | ||||||
|  | 
 | ||||||
|  |   ShowCardButton({ | ||||||
|  |     required this.title, | ||||||
|  |     required this.onPressed, | ||||||
|  |     this.txtColor = Colors.white, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Card( | ||||||
|  |       margin: EdgeInsets.zero, | ||||||
|  |       elevation: 20, | ||||||
|  |       child: Container( | ||||||
|  |         width: double.infinity, | ||||||
|  |         padding: EdgeInsets.all(12), | ||||||
|  |         child: ShowFillButton( | ||||||
|  |           title: title, | ||||||
|  |           onPressed: onPressed, | ||||||
|  |           txtColor: txtColor, | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,41 @@ | |||||||
|  | import 'package:mohem_flutter_app/theme/colors.dart'; | ||||||
|  | import 'package:mohem_flutter_app/widgets/txt.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | class ShowFillButton extends StatelessWidget { | ||||||
|  |   String title; | ||||||
|  |   VoidCallback onPressed; | ||||||
|  |   Color txtColor; | ||||||
|  |   double elevation, radius,width; | ||||||
|  | 
 | ||||||
|  |   ShowFillButton({ | ||||||
|  |     required this.title, | ||||||
|  |     required this.onPressed, | ||||||
|  |     this.txtColor = Colors.white, | ||||||
|  |     this.elevation = 4, | ||||||
|  |     this.radius = 6, | ||||||
|  |     this.width=88, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return ElevatedButton( | ||||||
|  |       style: ElevatedButton.styleFrom( | ||||||
|  |         onPrimary: Colors.black87, | ||||||
|  |         primary: accentColor, | ||||||
|  |         minimumSize: Size(width, 45), | ||||||
|  |         padding: EdgeInsets.symmetric(horizontal: 16), | ||||||
|  |         elevation: elevation, | ||||||
|  |         shape: RoundedRectangleBorder( | ||||||
|  |           borderRadius: BorderRadius.all(Radius.circular(radius)), | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |       onPressed: onPressed, | ||||||
|  |       child: Txt( | ||||||
|  |         title.toUpperCase(), | ||||||
|  |         color: txtColor, | ||||||
|  |         txtType: TxtType.heading1, | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,170 @@ | |||||||
|  | // import 'package:auto_size_text/auto_size_text.dart'; | ||||||
|  | import 'package:mohem_flutter_app/theme/colors.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/utils.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:sizer/sizer.dart'; | ||||||
|  | 
 | ||||||
|  | enum TxtType { | ||||||
|  |   small, | ||||||
|  |   normal, | ||||||
|  |   heading1, | ||||||
|  |   heading2, | ||||||
|  |   heading3, | ||||||
|  |   appBar, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class Txt extends StatelessWidget { | ||||||
|  |   String text; | ||||||
|  |   int? maxLines; | ||||||
|  |   double? fontSize; | ||||||
|  |   Color? color; | ||||||
|  |   bool? bold; | ||||||
|  |   bool? isUnderline; | ||||||
|  |   bool? isFlatButton; | ||||||
|  |   double? pedding; | ||||||
|  |   TextAlign? textAlign; | ||||||
|  |   FontWeight? fontWeight; | ||||||
|  |   Function? onTap; | ||||||
|  |   TxtType txtType; | ||||||
|  | 
 | ||||||
|  |   Txt(this.text, {this.maxLines, this.color, this.bold, this.fontSize, this.isUnderline, this.isFlatButton, this.pedding, this.textAlign, this.fontWeight, this.onTap, this.txtType = TxtType.normal}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     if (isFlatButton != null) | ||||||
|  |       return Padding( | ||||||
|  |         padding: EdgeInsets.only(right: pedding ?? 0, left: pedding ?? 0), | ||||||
|  |         child: InkWell( | ||||||
|  |           onTap: () { | ||||||
|  |             onTap!(); | ||||||
|  |           }, | ||||||
|  |           customBorder: inkWellCorner(r: 4), | ||||||
|  |           child: Padding( | ||||||
|  |             padding: const EdgeInsets.only( | ||||||
|  |               left: 14, | ||||||
|  |               right: 14, | ||||||
|  |               top: 6, | ||||||
|  |               bottom: 6, | ||||||
|  |             ), | ||||||
|  |             child: getText(), | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  |     else | ||||||
|  |       return getText(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Widget getText() { | ||||||
|  |     return Material( | ||||||
|  |       type: MaterialType.transparency, | ||||||
|  |       child: Text( | ||||||
|  |         text, | ||||||
|  |         maxLines: maxLines, | ||||||
|  |         textAlign: textAlign, | ||||||
|  |         overflow: maxLines != null ? TextOverflow.ellipsis : null, | ||||||
|  |         style: TextStyle( | ||||||
|  |           fontSize: fontSize ?? | ||||||
|  |               (txtType == TxtType.small | ||||||
|  |                   ? 8.sp | ||||||
|  |                   : txtType == TxtType.normal | ||||||
|  |                       ? 10.sp | ||||||
|  |                       : txtType == TxtType.heading1 | ||||||
|  |                           ? 11.sp | ||||||
|  |                           : txtType == TxtType.heading2 | ||||||
|  |                               ? 12.sp | ||||||
|  |                               : txtType == TxtType.heading3 | ||||||
|  |                                   ? 13.sp | ||||||
|  |                                   : txtType == TxtType.appBar | ||||||
|  |                                       ? 14.sp | ||||||
|  |                                       : 8.sp), | ||||||
|  |           color: color ?? | ||||||
|  |               (txtType == TxtType.appBar | ||||||
|  |                   ? Colors.black | ||||||
|  |                   : txtType == TxtType.heading1 | ||||||
|  |                       ? headingColor | ||||||
|  |                       : txtType == TxtType.heading2 | ||||||
|  |                           ? headingColor | ||||||
|  |                           : txtType == TxtType.heading3 | ||||||
|  |                               ? headingColor | ||||||
|  |                               : null), | ||||||
|  |           fontWeight: (fontWeight != null) | ||||||
|  |               ? fontWeight | ||||||
|  |               : ((bold != null) | ||||||
|  |                   ? FontWeight.bold | ||||||
|  |                   : (txtType == TxtType.appBar | ||||||
|  |                       ? FontWeight.bold | ||||||
|  |                       : txtType == TxtType.heading1 | ||||||
|  |                           ? FontWeight.bold | ||||||
|  |                           : txtType == TxtType.heading2 | ||||||
|  |                               ? FontWeight.bold | ||||||
|  |                               : txtType == TxtType.heading3 | ||||||
|  |                                   ? FontWeight.bold | ||||||
|  |                                   : null)), | ||||||
|  |           decoration: (isUnderline != null) ? TextDecoration.underline : null, | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // class TxtAuto extends StatelessWidget { | ||||||
|  | //   String text; | ||||||
|  | //   int? maxLines; | ||||||
|  | //   double? fontSize; | ||||||
|  | //   Color? color; | ||||||
|  | //   bool? bold; | ||||||
|  | //   bool? isUnderline; | ||||||
|  | //   bool? isFlatButton; | ||||||
|  | //   double? pedding; | ||||||
|  | //   TextAlign? textAlign; | ||||||
|  | // | ||||||
|  | //   TxtAuto( | ||||||
|  | //       this.text, { | ||||||
|  | //         this.maxLines, | ||||||
|  | //         this.color, | ||||||
|  | //         this.bold, | ||||||
|  | //         this.fontSize, | ||||||
|  | //         this.isUnderline, | ||||||
|  | //         this.isFlatButton, | ||||||
|  | //         this.pedding, | ||||||
|  | //         this.textAlign, | ||||||
|  | //       }); | ||||||
|  | // | ||||||
|  | //   @override | ||||||
|  | //   Widget build(BuildContext context) { | ||||||
|  | //     if (isFlatButton != null) | ||||||
|  | //       return Padding( | ||||||
|  | //         padding: EdgeInsets.only(right: pedding ?? 0, left: pedding ?? 0), | ||||||
|  | //         child: InkWell( | ||||||
|  | //           onTap: () {}, | ||||||
|  | //           customBorder: inkWellCorner(r: 4), | ||||||
|  | //           child: Padding( | ||||||
|  | //             padding: const EdgeInsets.only( | ||||||
|  | //               left: 14, | ||||||
|  | //               right: 14, | ||||||
|  | //               top: 6, | ||||||
|  | //               bottom: 6, | ||||||
|  | //             ), | ||||||
|  | //             child: getText(), | ||||||
|  | //           ), | ||||||
|  | //         ), | ||||||
|  | //       ); | ||||||
|  | //     else | ||||||
|  | //       return getText(); | ||||||
|  | //   } | ||||||
|  | // | ||||||
|  | //   Widget getText() { | ||||||
|  | //     return AutoSizeText( | ||||||
|  | //       text, | ||||||
|  | //       maxLines: maxLines, | ||||||
|  | //       textAlign: textAlign, | ||||||
|  | //       overflow: maxLines != null ? TextOverflow.ellipsis : null, | ||||||
|  | //       style: TextStyle( | ||||||
|  | //         fontSize: fontSize, | ||||||
|  | //         color: color, | ||||||
|  | //         fontWeight: (bold != null) ? FontWeight.bold : null, | ||||||
|  | //         decoration: (isUnderline != null) ? TextDecoration.underline : null, | ||||||
|  | //       ), | ||||||
|  | //     ); | ||||||
|  | //   } | ||||||
|  | // } | ||||||
| @ -0,0 +1,155 @@ | |||||||
|  | import 'package:mohem_flutter_app/theme/colors.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/utils.dart'; | ||||||
|  | import 'package:mohem_flutter_app/widgets/txt.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:sizer/sizer.dart'; | ||||||
|  | 
 | ||||||
|  | class TxtField extends StatelessWidget { | ||||||
|  |   TextEditingController controller = new TextEditingController(); | ||||||
|  |   String? title; | ||||||
|  |   String? hint; | ||||||
|  |   String? lable; | ||||||
|  |   IconData? prefixData; | ||||||
|  |   IconData? postfixData; | ||||||
|  |   bool isNeedFilterButton; | ||||||
|  |   bool isNeedClickAll; | ||||||
|  |   bool isButtonEnable; | ||||||
|  |   double? elevation; | ||||||
|  |   Function? onTap; | ||||||
|  |   String? buttonTitle; | ||||||
|  |   int? maxLines; | ||||||
|  |   bool isSidePaddingZero; | ||||||
|  |   bool isNeedBorder; | ||||||
|  | 
 | ||||||
|  |   TxtField({ | ||||||
|  |     this.title, | ||||||
|  |     this.lable, | ||||||
|  |     this.hint, | ||||||
|  |     this.prefixData, | ||||||
|  |     this.postfixData, | ||||||
|  |     this.isNeedClickAll = false, | ||||||
|  |     this.isNeedFilterButton = false, | ||||||
|  |     this.elevation, | ||||||
|  |     this.onTap, | ||||||
|  |     this.isButtonEnable = false, | ||||||
|  |     this.buttonTitle, | ||||||
|  |     this.maxLines, | ||||||
|  |     this.isSidePaddingZero = false, | ||||||
|  |     this.isNeedBorder = true, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     controller.text = title ?? ""; | ||||||
|  |     return InkWell( | ||||||
|  |       onTap: isNeedClickAll == false | ||||||
|  |           ? null | ||||||
|  |           : () { | ||||||
|  |               onTap!(); | ||||||
|  |             }, | ||||||
|  |       customBorder: inkWellCorner(), | ||||||
|  |       child: Row( | ||||||
|  |         children: [ | ||||||
|  |           Expanded( | ||||||
|  |             child: Card( | ||||||
|  |               elevation: elevation, | ||||||
|  |               margin: isSidePaddingZero ? EdgeInsets.zero : null, | ||||||
|  |               child: TextField( | ||||||
|  |                 autofocus: false, | ||||||
|  |                 controller: controller, | ||||||
|  |                 enabled: isNeedClickAll == true ? false : true, | ||||||
|  |                 maxLines: maxLines, | ||||||
|  |                 onTap: () {}, | ||||||
|  |                 decoration: InputDecoration( | ||||||
|  |                   labelText: lable, | ||||||
|  |                   alignLabelWithHint: true, | ||||||
|  |                   fillColor: Colors.white, | ||||||
|  |                   focusedBorder: OutlineInputBorder( | ||||||
|  |                     borderSide: BorderSide( | ||||||
|  |                         color: accentColor, width: isNeedBorder ? 1.0 : 0), | ||||||
|  |                     borderRadius: BorderRadius.circular(4.0), | ||||||
|  |                   ), | ||||||
|  |                   enabledBorder: OutlineInputBorder( | ||||||
|  |                     borderSide: BorderSide( | ||||||
|  |                         color: borderColor, width: isNeedBorder ? 1.0 : 0), | ||||||
|  |                     borderRadius: BorderRadius.circular(4.0), | ||||||
|  |                   ), | ||||||
|  |                   disabledBorder: OutlineInputBorder( | ||||||
|  |                     borderSide: BorderSide( | ||||||
|  |                         color: borderColor, width: isNeedBorder ? 1.0 : 0), | ||||||
|  |                     borderRadius: BorderRadius.circular(4.0), | ||||||
|  |                   ), | ||||||
|  |                   prefixIcon: prefixData != null | ||||||
|  |                       ? Icon( | ||||||
|  |                           Icons.search, | ||||||
|  |                           color: borderColor, | ||||||
|  |                         ) | ||||||
|  |                       : null, | ||||||
|  |                   labelStyle: TextStyle(color: borderColor, fontSize: 13.sp), | ||||||
|  |                   hintStyle: TextStyle(color: borderColor, fontSize: 9.sp), | ||||||
|  |                   hintText: hint ?? "", | ||||||
|  |                   contentPadding: prefixData == null | ||||||
|  |                       ? EdgeInsets.only( | ||||||
|  |                           left: 12, | ||||||
|  |                           right: 12, | ||||||
|  |                           top: maxLines != null ? 12 : 0, | ||||||
|  |                           bottom: maxLines != null ? 12 : 0, | ||||||
|  |                         ) | ||||||
|  |                       : EdgeInsets.zero, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           if (isNeedFilterButton) mWidth(8), | ||||||
|  |           if (isNeedFilterButton) | ||||||
|  |             InkWell( | ||||||
|  |               onTap: isNeedClickAll | ||||||
|  |                   ? null | ||||||
|  |                   : () { | ||||||
|  |                       controller.clear(); | ||||||
|  |                     }, | ||||||
|  |               child: Container( | ||||||
|  |                 width: 55, | ||||||
|  |                 height: 55, | ||||||
|  |                 child: Card( | ||||||
|  |                   color: accentColor, | ||||||
|  |                   // margin: EdgeInsets.all(4), | ||||||
|  |                   // shape: cardRadius(0), | ||||||
|  |                   child: Icon( | ||||||
|  |                     postfixData ?? Icons.filter_alt, | ||||||
|  |                     color: Colors.white, | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           if (isButtonEnable) | ||||||
|  |             Material( | ||||||
|  |               child: InkWell( | ||||||
|  |                 onTap: () {}, | ||||||
|  |                 customBorder: inkWellCorner(), | ||||||
|  |                 child: Container( | ||||||
|  |                   height: 55, | ||||||
|  |                   child: Card( | ||||||
|  |                     color: accentColor, | ||||||
|  |                     // margin: EdgeInsets.all(4), | ||||||
|  |                     // shape: cardRadius(0), | ||||||
|  |                     child: Center( | ||||||
|  |                       child: Padding( | ||||||
|  |                         padding: const EdgeInsets.only(left: 12, right: 12), | ||||||
|  |                         child: Txt( | ||||||
|  |                           buttonTitle ?? "Search", | ||||||
|  |                           color: Colors.white, | ||||||
|  |                           fontSize: 18, | ||||||
|  |                           bold: true, | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|  |                     ), | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,26 @@ | |||||||
|  | import 'package:mohem_flutter_app/config/constants.dart'; | ||||||
|  | import 'package:mohem_flutter_app/utils/utils.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | 
 | ||||||
|  | class UserImage extends StatelessWidget { | ||||||
|  |   double? size; | ||||||
|  |   String? url; | ||||||
|  | 
 | ||||||
|  |   UserImage({this.size, this.url}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Container( | ||||||
|  |       height: size ?? 60, | ||||||
|  |       width: size ?? 60, | ||||||
|  |       decoration: containerRadius(Colors.transparent, 1000), | ||||||
|  |       clipBehavior: Clip.antiAlias, | ||||||
|  |       child: Image.asset( | ||||||
|  |         url ?? icons + "Blue Masked.jpg", | ||||||
|  |         width: double.infinity, | ||||||
|  |         height: double.infinity, | ||||||
|  |         fit: BoxFit.cover, | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,38 @@ | |||||||
|  | { | ||||||
|  |   "title": "Hello", | ||||||
|  |   "msg": "Hello {} in the {} world ", | ||||||
|  |   "msg_named": "{} are written in the {lang} language", | ||||||
|  |   "clickMe": "Click me", | ||||||
|  |   "profile": { | ||||||
|  |     "reset_password": { | ||||||
|  |       "label": "Reset Password", | ||||||
|  |       "username": "Username", | ||||||
|  |       "password": "password" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "clicked": { | ||||||
|  |     "zero": "You clicked {} times!", | ||||||
|  |     "one": "You clicked {} time!", | ||||||
|  |     "two": "You clicked {} times!", | ||||||
|  |     "few": "You clicked {} times!", | ||||||
|  |     "many": "You clicked {} times!", | ||||||
|  |     "other": "You clicked {} times!" | ||||||
|  |   }, | ||||||
|  |   "amount": { | ||||||
|  |     "zero": "Your amount : {} ", | ||||||
|  |     "one": "Your amount : {} ", | ||||||
|  |     "two": "Your amount : {} ", | ||||||
|  |     "few": "Your amount : {} ", | ||||||
|  |     "many": "Your amount : {} ", | ||||||
|  |     "other": "Your amount : {} " | ||||||
|  |   }, | ||||||
|  |   "gender": { | ||||||
|  |     "male": "Hi man ;) ", | ||||||
|  |     "female": "Hello girl :)", | ||||||
|  |     "with_arg": { | ||||||
|  |       "male": "Hi man ;) {}", | ||||||
|  |       "female": "Hello girl :) {}" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "reset_locale": "Reset Language" | ||||||
|  | } | ||||||
| @ -0,0 +1,38 @@ | |||||||
|  | { | ||||||
|  |   "title": "Hello", | ||||||
|  |   "msg": "Hello {} in the {} world ", | ||||||
|  |   "msg_named": "{} are written in the {lang} language", | ||||||
|  |   "clickMe": "Click me", | ||||||
|  |   "profile": { | ||||||
|  |     "reset_password": { | ||||||
|  |       "label": "Reset Password", | ||||||
|  |       "username": "Username", | ||||||
|  |       "password": "password" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "clicked": { | ||||||
|  |     "zero": "You clicked {} times!", | ||||||
|  |     "one": "You clicked {} time!", | ||||||
|  |     "two": "You clicked {} times!", | ||||||
|  |     "few": "You clicked {} times!", | ||||||
|  |     "many": "You clicked {} times!", | ||||||
|  |     "other": "You clicked {} times!" | ||||||
|  |   }, | ||||||
|  |   "amount": { | ||||||
|  |     "zero": "Your amount : {} ", | ||||||
|  |     "one": "Your amount : {} ", | ||||||
|  |     "two": "Your amount : {} ", | ||||||
|  |     "few": "Your amount : {} ", | ||||||
|  |     "many": "Your amount : {} ", | ||||||
|  |     "other": "Your amount : {} " | ||||||
|  |   }, | ||||||
|  |   "gender": { | ||||||
|  |     "male": "Hi man ;) ", | ||||||
|  |     "female": "Hello girl :)", | ||||||
|  |     "with_arg": { | ||||||
|  |       "male": "Hi man ;) {}", | ||||||
|  |       "female": "Hello girl :) {}" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "reset_locale": "Reset Language" | ||||||
|  | } | ||||||
					Loading…
					
					
				
		Reference in New Issue