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" | ||||
|  | ||||
| @ -1 +1,2 @@ | ||||
| #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.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:sizer/sizer.dart'; | ||||
| 
 | ||||
| void main() { | ||||
|   runApp(const MyApp()); | ||||
| } | ||||
| import 'config/localization.dart'; | ||||
| import 'config/routes.dart'; | ||||
| 
 | ||||
| class MyApp extends StatelessWidget { | ||||
|   const MyApp({Key? key}) : super(key: key); | ||||
| Future<void> main() async { | ||||
|   WidgetsFlutterBinding.ensureInitialized(); | ||||
| 
 | ||||
|   // This widget is the root of your application. | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     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, | ||||
|   await EasyLocalization.ensureInitialized(); | ||||
|   runApp( | ||||
|     EasyLocalization( | ||||
|       supportedLocales: [ | ||||
|         Locale('en', 'US'), | ||||
|       ], | ||||
|       path: 'resources/langs', | ||||
|       child: MyApp(), | ||||
|     ), | ||||
|       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++; | ||||
|     }); | ||||
| class MyApp extends StatelessWidget { | ||||
|   // This widget is the root of your application. | ||||
|   MyApp() { | ||||
|     AppDependencies.addDependencies(); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     // This method is rerun every time setState is called, for instance as done | ||||
|     // by the _incrementCounter method above. | ||||
|     // | ||||
|     // The Flutter framework has been optimized to make rerunning build methods | ||||
|     // fast, so that you can just rebuild anything that needs updating rather | ||||
|     // than having to individually change instances of widgets. | ||||
|     return Scaffold( | ||||
|       appBar: AppBar( | ||||
|         // Here we take the value from the MyHomePage object that was created by | ||||
|         // the App.build method, and use it to set our appbar title. | ||||
|         title: Text(widget.title), | ||||
|       ), | ||||
|       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, | ||||
|             ), | ||||
|           ], | ||||
|         ), | ||||
|     return AppProvider( | ||||
|       child: Sizer( | ||||
|         builder: (context, orientation, deviceType) { | ||||
|           return MaterialApp( | ||||
|             theme: AppTheme.getTheme(), | ||||
|             debugShowCheckedModeBanner: false, | ||||
|             localizationsDelegates: context.localizationDelegates, | ||||
|             supportedLocales: context.supportedLocales, | ||||
|             locale: context.locale, | ||||
|             initialRoute: AppRoutes.initialRoute, | ||||
|             routes: AppRoutes.routes, | ||||
|           ); | ||||
|         }, | ||||
|       ), | ||||
|       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