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