Merge branch 'moe-sikander' into 'master'

improvements

See merge request Cloud_Solution/mohemm-flutter-moe!3
merge-requests/4/merge
Sikander Saleem 3 years ago
commit 6e381cbe16

@ -0,0 +1,57 @@
{
"agcgw_all":{
"CN":"connect-drcn.dbankcloud.cn",
"CN_back":"connect-drcn.hispace.hicloud.com",
"DE":"connect-dre.dbankcloud.cn",
"DE_back":"connect-dre.hispace.hicloud.com",
"RU":"connect-drru.hispace.dbankcloud.ru",
"RU_back":"connect-drru.hispace.dbankcloud.cn",
"SG":"connect-dra.dbankcloud.cn",
"SG_back":"connect-dra.hispace.hicloud.com"
},
"websocketgw_all":{
"CN":"connect-ws-drcn.hispace.dbankcloud.cn",
"CN_back":"connect-ws-drcn.hispace.dbankcloud.com",
"DE":"connect-ws-dre.hispace.dbankcloud.cn",
"DE_back":"connect-ws-dre.hispace.dbankcloud.com",
"RU":"connect-ws-drru.hispace.dbankcloud.ru",
"RU_back":"connect-ws-drru.hispace.dbankcloud.cn",
"SG":"connect-ws-dra.hispace.dbankcloud.cn",
"SG_back":"connect-ws-dra.hispace.dbankcloud.com"
},
"client":{
"cp_id":"2640966000002322881",
"product_id":"737518067793559971",
"client_id":"715996003571874624",
"client_secret":"B5B89A56A53847C6BB9D216A8747E75952760DF9A8232239D8744CD847A8FFDA",
"project_id":"737518067793559971",
"app_id":"104737117",
"api_key":"DAEDACKDrYgyco9mjPV9ZUjCSh1kCr/GBV0nseHH0z2mnxlZ41RksOKmyTi+PUTwmGEPK+VxCup4F9oUf4VbDnCsjB7aNBShYcjR+g==",
"package_name":"hmg.cloudSolutions.mohem"
},
"oauth_client":{
"client_id":"104737117",
"client_type":1
},
"app_info":{
"app_id":"104737117",
"package_name":"hmg.cloudSolutions.mohem"
},
"configuration_version":"3.0",
"appInfos":[
{
"package_name":"hmg.cloudSolutions.mohem",
"client":{
"app_id":"104737117"
},
"app_info":{
"package_name":"hmg.cloudSolutions.mohem",
"app_id":"104737117"
},
"oauth_client":{
"client_type":1,
"client_id":"104737117"
}
}
]
}

@ -31,6 +31,7 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'com.google.gms.google-services'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
apply plugin: 'com.huawei.agconnect'
android {
compileSdkVersion 33
@ -58,6 +59,12 @@ android {
}
signingConfigs {
// debug {
// keyAlias keystoreProperties['keyAlias']
// keyPassword keystoreProperties['keyPassword']
// storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
// storePassword keystoreProperties['storePassword']
// }
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
@ -68,6 +75,9 @@ android {
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

@ -7,7 +7,15 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- Chat Web RTC Calling -->
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<application
android:allowBackup="false"

@ -3,12 +3,14 @@ buildscript {
repositories {
google()
mavenCentral()
maven { url 'https://developer.huawei.com/repo/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.8'
classpath 'com.huawei.agconnect:agcp:1.8.0.300'
}
}
@ -16,6 +18,7 @@ allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://developer.huawei.com/repo/' }
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

@ -2,6 +2,15 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsForMedia</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
@ -33,7 +42,7 @@
<key>NFCReaderUsageDescription</key>
<string>This App requires access to NFC to mark your attendance.</string>
<key>NSCameraUsageDescription</key>
<string>This app requires camera access to capture &amp; upload pictures.</string>
<string>This app requires camera access to capture &amp; upload picture as profile image.</string>
<key>NSFaceIDUsageDescription</key>
<string>This app requires Face ID to allow biometric authentication for app login.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
@ -46,15 +55,13 @@
<string>This app requires photo library access to select image as document &amp; upload it.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app requires microphone access to for call.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app requires photo library access to select image as document &amp; upload it.</string>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>FirebaseAppDelegateProxyEnabled</key>
<false/>
<false/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
@ -80,14 +87,9 @@
</array>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
<string>TAG</string>
</array>
<key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
<array>
<string>0000</string>
</array>
</dict>
</plist>

@ -1,7 +1,6 @@
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart';
import 'package:mohem_flutter_app/models/itg_forms_models/request_detail_model.dart';
import 'package:mohem_flutter_app/models/member_information_list_model.dart';
@ -77,7 +76,19 @@ class AppState {
bool get getIsDemoMarathon => _isDemoMarathon;
final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 4.0, mobileType: Platform.isAndroid ? "android" : "ios");
bool _isHuawei = false;
set setIsHuawei(bool value) => _isHuawei = value;
bool get getIsHuawei => _isHuawei;
String _huaweiPushToken = "";
set setHuaweiPushToken(String value) => _huaweiPushToken = value;
String get getHuaweiPushToken => _huaweiPushToken;
final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 4.1, mobileType: Platform.isAndroid ? "android" : "ios");
void setPostParamsInitConfig() {
isAuthenticated = false;
@ -180,5 +191,4 @@ class AppState {
}
bool cancelRequestTrancsection = true;
}

@ -1,12 +1,10 @@
import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart';
class ApiConsts {
//static String baseUrl = "http://10.200.204.20:2801/"; // Local server
// static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server
// static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server
static String baseUrl = "https://hmgwebservices.com"; // Live server
static String baseUrl = "https://uathrmsys.moenergy.gov.sa"; //MOE UAT
// static String baseUrl = "https://hrmsys.moenergy.gov.sa"; // MOE ;LIVE
static String baseUrlServices = baseUrl + "/Services/"; // server
// static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server
static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/";
static String erpRest = baseUrlServices + "ERP.svc/REST/";
static String swpRest = baseUrlServices + "SWP.svc/REST/";

@ -60,13 +60,13 @@ class DateUtil {
}
}
date = date + " $hours:$mins:$secs";
DateTime returnDate = DateFormat("MM/dd/yyyy HH:mm:ss").parse(date);
DateTime returnDate = DateFormat("MM/dd/yyyy HH:mm:ss", "en_US").parse(date);
return returnDate;
}
static DateTime convertSimpleStringDateToDateddMMyyyy(String date) {
return DateFormat("MM/dd/yyyy hh:mm:ss").parse(date);
return DateFormat("MM/dd/yyyy hh:mm:ss", "en_US").parse(date);
}
static DateTime convertStringToDateNoTimeZone(String date) {
@ -123,7 +123,7 @@ class DateUtil {
}
static String formatDateToTime(DateTime date) {
return DateFormat('hh:mm a').format(date);
return DateFormat('hh:mm a', "en_US").format(date);
}
static String yearMonthDay(DateTime dateTime) {
@ -419,7 +419,7 @@ class DateUtil {
/// [dateTime] convert DateTime to data formatted
static String getDayMonthDateFormatted(DateTime dateTime) {
if (dateTime != null)
return DateFormat('dd/MM').format(dateTime);
return DateFormat('dd/MM', "en_US").format(dateTime);
else
return "";
}
@ -466,7 +466,7 @@ class DateUtil {
/// [dateTime] convert DateTime to data formatted
static String getDayMonthYearHourMinuteDateFormatted(DateTime dateTime) {
if (dateTime != null)
return dateTime.day.toString() + "/" + dateTime.month.toString() + "/" + dateTime.year.toString() + " " + DateFormat('HH:mm').format(dateTime);
return dateTime.day.toString() + "/" + dateTime.month.toString() + "/" + dateTime.year.toString() + " " + DateFormat('HH:mm', "en_US").format(dateTime);
else
return "";
}
@ -491,11 +491,11 @@ class DateUtil {
}
static String getFormattedDate(DateTime dateTime, String formattedString) {
return DateFormat(formattedString).format(dateTime);
return DateFormat(formattedString, "en_US").format(dateTime);
}
static String convertISODateToJsonDate(String isoDate) {
return "/Date(" + DateFormat('mm-dd-yyy').parse(isoDate).millisecondsSinceEpoch.toString() + ")/";
return "/Date(" + DateFormat('mm-dd-yyy', "en_US").parse(isoDate).millisecondsSinceEpoch.toString() + ")/";
}
// static String getDay(DayOfWeek dayOfWeek) {

@ -1,13 +1,14 @@
import 'dart:convert';
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:huawei_hmsavailability/huawei_hmsavailability.dart';
import 'package:huawei_push/huawei_push.dart' as huawei_push;
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:firebase_core/firebase_core.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
@ -18,6 +19,10 @@ class AppNotifications {
factory AppNotifications() => _instance;
late HmsApiAvailability hmsApiAvailability;
String _huaweiToken = '';
Future<void> requestPermissions() async {
if (Platform.isIOS) {
await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()?.requestPermissions(alert: true, badge: true, sound: true);
@ -35,6 +40,7 @@ class AppNotifications {
}
void init(String? firebaseToken) async {
hmsApiAvailability = HmsApiAvailability();
await requestPermissions();
AppState().setDeviceToken = firebaseToken;
await Permission.notification.isDenied.then((bool value) {
@ -57,6 +63,48 @@ class AppNotifications {
FirebaseMessaging.instance.onTokenRefresh.listen((String token) {
AppState().setDeviceToken = token;
});
if (Platform.isAndroid) {
await hmsApiAvailability.isHMSAvailable().then((value) async {
if (value == 0) {
huawei_push.Push.enableLogger();
var result = await huawei_push.Push.setAutoInitEnabled(true);
huawei_push.Push.onNotificationOpenedApp.listen((message) {
// newMessage(toFirebaseRemoteMessage(message));
}, onError: (e) => print(e.toString()));
huawei_push.Push.onMessageReceivedStream.listen((message) {
// newMessage(toFirebaseRemoteMessage(message));
}, onError: (e) => print(e.toString()));
}
}).catchError((err) {
print(err);
});
}
}
void initHuaweiPush(Function loginCallback) {
AppState().setIsHuawei = true;
initTokenStream(loginCallback);
huawei_push.Push.getToken("");
}
// HUAWEI PUSH TOKEN IMPLEMENTATION
void _onTokenEvent(String event) {
_huaweiToken = event;
AppState().setHuaweiPushToken = _huaweiToken;
debugPrint("HUAWEI PUSH TOKEN: $_huaweiToken");
}
void _onTokenError(Object error) {}
Future<void> initTokenStream(Function loginCallback) async {
huawei_push.Push.getTokenStream.listen(_onTokenEvent, onError: _onTokenError).onData((data) {
AppState().setHuaweiPushToken = data;
debugPrint("HUAWEI PUSH TOKEN: $data");
loginCallback();
});
}
void _handleMessage(RemoteMessage message) {

@ -98,7 +98,8 @@ class Utils {
static void handleException(dynamic exception, cxt, Function(String)? onErrorMessage) {
String errorMessage;
if (exception.error.errorType != null && exception.error.errorType == 4) {
print("exception:$exception");
if (exception?.error?.errorType != null && exception.error.errorType == 4) {
Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.appUpdateScreen, (_) => false, arguments: exception.error?.errorMessage);
} else {
if (exception is APIException) {
@ -266,7 +267,7 @@ class Utils {
static String getMonthNamedFormat(DateTime date) {
/// it will return like "29-Sep-2022"
return DateFormat('dd-MMM-yyyy').format(date);
return DateFormat('dd-MMM-yyyy', "en_US").format(date);
}
static String reverseFormatDate(String date) {
@ -336,9 +337,9 @@ class Utils {
return date;
} else {
if (date.toLowerCase().split("-")[1].length == 3) {
return DateFormat('dd-MM-yyyy').format(DateFormat('dd-MMM-yyyy').parseLoose(date));
return DateFormat('dd-MM-yyyy', "en_US").format(DateFormat('dd-MMM-yyyy', "en_US").parseLoose(date));
} else {
return DateFormat('dd-MM-yyyy').format(DateFormat('yyyy-MM-dd').parseLoose(date));
return DateFormat('dd-MM-yyyy', "en_US").format(DateFormat('yyyy-MM-dd', "en_US").parseLoose(date));
}
// return DateFormat('yyyy-MM-dd').format(DateFormat('dd-MM-yyyy').parseLoose(date));
}

@ -1,9 +1,8 @@
// ignore_for_file: prefer_single_quotes, lines_longer_than_80_chars final
Map<String, dynamic> env = {
"appConfig": "lib/config/config_en.json",
// Worklist (Dynamic ListView, Dynamic Forms, Dynamic Submission)
// link to generate dart class https://www.webinovers.com/web-tools/json-to-dart-convertor
Map<String, dynamic> _env = {
"appConfig": "lib/config/config_en.json",
"login": {
"verification": true,
"verificationMethod": {
@ -21,6 +20,7 @@ Map<String, dynamic> env = {
"monthlyAttendance": false,
"vocationRules": false,
},
"itg": false,
"marathon": false,
"offersDiscount": false,
"myTeams": false,
@ -32,4 +32,175 @@ Map<String, dynamic> env = {
"chat": false,
"monthlyAttendance": false,
"vocationRules": false,
"canEdit": false,
};
Env env = Env.fromJson(_env);
class Env {
Env({
required this.appConfig,
required this.login,
required this.bottomBar,
required this.dashboard,
required this.itg,
required this.marathon,
required this.offersDiscount,
required this.myTeams,
required this.modifiy,
required this.myRequest,
required this.pendingTransactions,
required this.myProfile,
required this.itemsForSale,
required this.chat,
required this.monthlyAttendance,
required this.vocationRules,
required this.canEdit,
});
late final String appConfig;
late final Login login;
late final bool bottomBar;
late final Dashboard dashboard;
late final bool itg;
late final bool marathon;
late final bool offersDiscount;
late final bool myTeams;
late final bool modifiy;
late final bool myRequest;
late final bool pendingTransactions;
late final bool myProfile;
late final bool itemsForSale;
late final bool chat;
late final bool monthlyAttendance;
late final bool vocationRules;
late final bool canEdit;
Env.fromJson(Map<String, dynamic> json) {
appConfig = json['appConfig'];
login = Login.fromJson(json['login']);
bottomBar = json['bottomBar'];
dashboard = Dashboard.fromJson(json['dashboard']);
marathon = json['marathon'];
itg = json['itg'];
offersDiscount = json['offersDiscount'];
myTeams = json['myTeams'];
modifiy = json['modifiy'];
myRequest = json['myRequest'];
pendingTransactions = json['pendingTransactions'];
myProfile = json['myProfile'];
itemsForSale = json['itemsForSale'];
chat = json['chat'];
monthlyAttendance = json['monthlyAttendance'];
vocationRules = json['vocationRules'];
canEdit = json['canEdit'];
}
Map<String, dynamic> toJson() {
var _data = <String, dynamic>{};
_data['appConfig'] = appConfig;
_data['login'] = login.toJson();
_data['bottomBar'] = bottomBar;
_data['dashboard'] = dashboard.toJson();
_data['marathon'] = marathon;
_data['itg'] = itg;
_data['offersDiscount'] = offersDiscount;
_data['myTeams'] = myTeams;
_data['modifiy'] = modifiy;
_data['myRequest'] = myRequest;
_data['pendingTransactions'] = pendingTransactions;
_data['myProfile'] = myProfile;
_data['itemsForSale'] = itemsForSale;
_data['chat'] = chat;
_data['monthlyAttendance'] = monthlyAttendance;
_data['vocationRules'] = vocationRules;
_data['canEdit'] = canEdit;
return _data;
}
}
class Login {
Login({
required this.verification,
required this.verificationMethod,
required this.forgetPassword,
});
late final bool verification;
late final VerificationMethod verificationMethod;
late final bool forgetPassword;
Login.fromJson(Map<String, dynamic> json) {
verification = json['verification'];
verificationMethod = VerificationMethod.fromJson(json['verificationMethod']);
forgetPassword = json['forgetPassword'];
}
Map<String, dynamic> toJson() {
var _data = <String, dynamic>{};
_data['verification'] = verification;
_data['verificationMethod'] = verificationMethod.toJson();
_data['forgetPassword'] = forgetPassword;
return _data;
}
}
class VerificationMethod {
VerificationMethod({
required this.whatsapp,
});
late final bool whatsapp;
VerificationMethod.fromJson(Map<String, dynamic> json) {
whatsapp = json['whatsapp'];
}
Map<String, dynamic> toJson() {
var _data = <String, dynamic>{};
_data['whatsapp'] = whatsapp;
return _data;
}
}
class Dashboard {
Dashboard({
required this.attendance,
required this.worklist,
required this.ticketBalance,
required this.leaveBalance,
required this.missingSwipe,
required this.monthlyAttendance,
required this.vocationRules,
});
late final bool attendance;
late final bool worklist;
late final bool ticketBalance;
late final bool leaveBalance;
late final bool missingSwipe;
late final bool monthlyAttendance;
late final bool vocationRules;
Dashboard.fromJson(Map<String, dynamic> json) {
attendance = json['attendance'];
worklist = json['worklist'];
ticketBalance = json['ticketBalance'];
leaveBalance = json['leaveBalance'];
missingSwipe = json['missingSwipe'];
monthlyAttendance = json['monthlyAttendance'];
vocationRules = json['vocationRules'];
}
Map<String, dynamic> toJson() {
var _data = <String, dynamic>{};
_data['attendance'] = attendance;
_data['worklist'] = worklist;
_data['ticketBalance'] = ticketBalance;
_data['leaveBalance'] = leaveBalance;
_data['missingSwipe'] = missingSwipe;
_data['monthlyAttendance'] = monthlyAttendance;
_data['vocationRules'] = vocationRules;
return _data;
}
}

@ -9,7 +9,6 @@ import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/otp_widget.dart';
import 'package:sizer/sizer.dart';
final ValueNotifier<String> otpFieldClear = ValueNotifier<String>("");

@ -221,7 +221,7 @@ extension EmailValidator on String {
String date = this.split("T")[0];
String time = this.split("T")[1];
var dates = date.split("-");
return "${dates[2]} ${getMonth(int.parse(dates[1]))} ${dates[0]} ${DateFormat('hh:mm a').format(DateFormat('hh:mm:ss').parse(time))}";
return "${dates[2]} ${getMonth(int.parse(dates[1]))} ${dates[0]} ${DateFormat('hh:mm a', "en_US").format(DateFormat('hh:mm:ss', "en_US").parse(time))}";
}
String getMonth(int month) {

@ -6,9 +6,11 @@ import 'package:flutter/services.dart';
import 'package:logger/logger.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/consts.dart';
import 'package:mohem_flutter_app/config/env.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/generated/codegen_loader.g.dart';
import 'package:mohem_flutter_app/models/post_params_model.dart';
import 'package:mohem_flutter_app/provider/chat_call_provider.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart';
import 'package:mohem_flutter_app/provider/eit_provider_model.dart';
@ -25,7 +27,6 @@ Logger logger = Logger(
),
);
class MyHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
@ -62,12 +63,17 @@ Future<void> main() async {
ChangeNotifierProvider<EITProviderModel>(
create: (_) => EITProviderModel(),
),
ChangeNotifierProvider<ChatProviderModel>(
create: (_) => ChatProviderModel(),
),
ChangeNotifierProvider<MarathonProvider>(
create: (_) => MarathonProvider(),
)
if (env.chat)
ChangeNotifierProvider<ChatProviderModel>(
create: (_) => ChatProviderModel(),
),
if (env.marathon)
ChangeNotifierProvider<MarathonProvider>(
create: (_) => MarathonProvider(),
),
// ChangeNotifierProvider<ChatCallProvider>(
// create: (_) => ChatCallProvider(),
// ),
],
child: const MyApp(),
),
@ -259,5 +265,3 @@ class MyApp extends StatelessWidget {
// });
// }
// }

@ -7,127 +7,191 @@ import 'dart:convert';
class CallDataModel {
CallDataModel({
this.callerId,
this.callReceiverID,
this.notificationForeground,
this.message,
this.callerDetails,
this.receiverId,
this.receiverDetails,
this.title,
this.type,
this.identity,
this.name,
this.isCall,
this.isWebrtc,
this.contant,
this.contantNo,
this.chatEventId,
this.fileTypeId,
this.currentUserId,
this.chatSource,
this.userChatHistoryLineRequestList,
this.server,
this.calltype,
});
String? callerId;
String? callReceiverID;
String? notificationForeground;
String? message;
String? title;
String? type;
String? identity;
String? name;
String? isCall;
String? isWebrtc;
String? contant;
String? contantNo;
String? chatEventId;
dynamic? fileTypeId;
String? currentUserId;
String? chatSource;
List<UserChatHistoryLineRequestList>? userChatHistoryLineRequestList;
String? server;
CallerDetails? callerDetails;
String? receiverId;
ReceiverDetails? receiverDetails;
dynamic title;
String? calltype;
factory CallDataModel.fromRawJson(String str) => CallDataModel.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory CallDataModel.fromJson(Map<String, dynamic> json) => CallDataModel(
callerId: json["callerID"] == null ? null : json["callerID"],
callReceiverID: json["callReceiverID"] == null ? null : json["callReceiverID"],
notificationForeground: json["notification_foreground"] == null ? null : json["notification_foreground"],
message: json["message"] == null ? null : json["message"],
title: json["title"] == null ? null : json["title"],
type: json["type"] == null ? null : json["type"],
identity: json["identity"] == null ? null : json["identity"],
name: json["name"] == null ? null : json["name"],
isCall: json["is_call"] == null ? null : json["is_call"],
isWebrtc: json["is_webrtc"] == null ? null : json["is_webrtc"],
contant: json["contant"] == null ? null : json["contant"],
contantNo: json["contantNo"] == null ? null : json["contantNo"],
chatEventId: json["chatEventId"] == null ? null : json["chatEventId"],
fileTypeId: json["fileTypeId"],
currentUserId: json["currentUserId"] == null ? null : json["currentUserId"],
chatSource: json["chatSource"] == null ? null : json["chatSource"],
userChatHistoryLineRequestList: json["userChatHistoryLineRequestList"] == null
? null
: List<UserChatHistoryLineRequestList>.from(
json["userChatHistoryLineRequestList"].map(
(x) => UserChatHistoryLineRequestList.fromJson(x),
),
),
server: json["server"] == null ? null : json["server"],
);
callerId: json["callerID"],
callerDetails: json["callerDetails"] == null ? null : CallerDetails.fromJson(json["callerDetails"]),
receiverId: json["receiverID"],
receiverDetails: json["receiverDetails"] == null ? null : ReceiverDetails.fromJson(json["receiverDetails"]),
title: json["title"],
calltype: json["calltype"],
);
Map<String, dynamic> toJson() => {
"callerID": callerId,
"callerDetails": callerDetails?.toJson(),
"receiverID": receiverId,
"receiverDetails": receiverDetails?.toJson(),
"title": title,
"calltype": calltype,
};
}
class CallerDetails {
CallerDetails({
this.response,
this.errorResponses,
});
Response? response;
dynamic errorResponses;
factory CallerDetails.fromRawJson(String str) => CallerDetails.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory CallerDetails.fromJson(Map<String, dynamic> json) => CallerDetails(
response: json["response"] == null ? null : Response.fromJson(json["response"]),
errorResponses: json["errorResponses"],
);
Map<String, dynamic> toJson() => {
"callerID": callerId == null ? null : callerId,
"callReceiverID": callReceiverID == null ? null : callReceiverID,
"notification_foreground": notificationForeground == null ? null : notificationForeground,
"message": message == null ? null : message,
"title": title == null ? null : title,
"type": type == null ? null : type,
"identity": identity == null ? null : identity,
"name": name == null ? null : name,
"is_call": isCall == null ? null : isCall,
"is_webrtc": isWebrtc == null ? null : isWebrtc,
"contant": contant == null ? null : contant,
"contantNo": contantNo == null ? null : contantNo,
"chatEventId": chatEventId == null ? null : chatEventId,
"fileTypeId": fileTypeId,
"currentUserId": currentUserId == null ? null : currentUserId,
"chatSource": chatSource == null ? null : chatSource,
"userChatHistoryLineRequestList": userChatHistoryLineRequestList == null
? null
: List<dynamic>.from(
userChatHistoryLineRequestList!.map(
(x) => x.toJson(),
),
),
"server": server == null ? null : server,
};
"response": response?.toJson(),
"errorResponses": errorResponses,
};
}
class UserChatHistoryLineRequestList {
UserChatHistoryLineRequestList({
this.isSeen,
this.isDelivered,
this.targetUserId,
this.targetUserStatus,
class Response {
Response({
this.id,
this.userName,
this.email,
this.phone,
this.title,
this.token,
this.isDomainUser,
this.isActiveCode,
this.encryptedUserId,
this.encryptedUserName,
});
bool? isSeen;
bool? isDelivered;
int? targetUserId;
int? targetUserStatus;
int? id;
String? userName;
String? email;
dynamic phone;
String? title;
String? token;
bool? isDomainUser;
bool? isActiveCode;
String? encryptedUserId;
String? encryptedUserName;
factory Response.fromRawJson(String str) => Response.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Response.fromJson(Map<String, dynamic> json) => Response(
id: json["id"],
userName: json["userName"],
email: json["email"],
phone: json["phone"],
title: json["title"],
token: json["token"],
isDomainUser: json["isDomainUser"],
isActiveCode: json["isActiveCode"],
encryptedUserId: json["encryptedUserId"],
encryptedUserName: json["encryptedUserName"],
);
Map<String, dynamic> toJson() => {
"id": id,
"userName": userName,
"email": email,
"phone": phone,
"title": title,
"token": token,
"isDomainUser": isDomainUser,
"isActiveCode": isActiveCode,
"encryptedUserId": encryptedUserId,
"encryptedUserName": encryptedUserName,
};
}
class ReceiverDetails {
ReceiverDetails({
this.id,
this.userName,
this.email,
this.phone,
this.title,
this.userStatus,
this.image,
this.unreadMessageCount,
this.userAction,
this.isPin,
this.isFav,
this.isAdmin,
this.rKey,
this.totalCount,
});
int? id;
String? userName;
String? email;
dynamic phone;
dynamic title;
int? userStatus;
String? image;
int? unreadMessageCount;
dynamic userAction;
bool? isPin;
bool? isFav;
bool? isAdmin;
String? rKey;
int? totalCount;
factory ReceiverDetails.fromRawJson(String str) => ReceiverDetails.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory UserChatHistoryLineRequestList.fromJson(Map<String, dynamic> json) => UserChatHistoryLineRequestList(
isSeen: json["isSeen"] == null ? null : json["isSeen"],
isDelivered: json["isDelivered"] == null ? null : json["isDelivered"],
targetUserId: json["targetUserId"] == null ? null : json["targetUserId"],
targetUserStatus: json["targetUserStatus"] == null ? null : json["targetUserStatus"],
);
factory ReceiverDetails.fromJson(Map<String, dynamic> json) => ReceiverDetails(
id: json["id"],
userName: json["userName"],
email: json["email"],
phone: json["phone"],
title: json["title"],
userStatus: json["userStatus"],
image: json["image"],
unreadMessageCount: json["unreadMessageCount"],
userAction: json["userAction"],
isPin: json["isPin"],
isFav: json["isFav"],
isAdmin: json["isAdmin"],
rKey: json["rKey"],
totalCount: json["totalCount"],
);
Map<String, dynamic> toJson() => {
"isSeen": isSeen == null ? null : isSeen,
"isDelivered": isDelivered == null ? null : isDelivered,
"targetUserId": targetUserId == null ? null : targetUserId,
"targetUserStatus": targetUserStatus == null ? null : targetUserStatus,
};
"id": id,
"userName": userName,
"email": email,
"phone": phone,
"title": title,
"userStatus": userStatus,
"image": image,
"unreadMessageCount": unreadMessageCount,
"userAction": userAction,
"isPin": isPin,
"isFav": isFav,
"isAdmin": isAdmin,
"rKey": rKey,
"totalCount": totalCount,
};
}

@ -31,6 +31,7 @@ class GetEITDFFStructureList {
List<PARENTSEGMENTSVSSplitedVS>? pARENTSEGMENTSVSSplitedVS;
String? rEADONLY;
String? rEQUIREDFLAG;
String? rEQCOLTIP;
String? sEGMENTNAME;
String? sEGMENTPROMPT;
int? sEGMENTSEQNUM;
@ -73,6 +74,7 @@ class GetEITDFFStructureList {
this.pARENTSEGMENTSVSSplitedVS,
this.rEADONLY,
this.rEQUIREDFLAG,
this.rEQCOLTIP,
this.sEGMENTNAME,
this.sEGMENTPROMPT,
this.sEGMENTSEQNUM,
@ -132,7 +134,6 @@ class GetEITDFFStructureList {
});
}
pARENTSEGMENTSVS = json['PARENT_SEGMENTS_VS'];
if (json['PARENT_SEGMENTS_VS_SplitedVS'] != null) {
pARENTSEGMENTSVSSplitedVS = <PARENTSEGMENTSVSSplitedVS>[];
json['PARENT_SEGMENTS_VS_SplitedVS'].forEach((v) {
@ -141,6 +142,7 @@ class GetEITDFFStructureList {
}
rEADONLY = json['READ_ONLY'];
rEQUIREDFLAG = json['REQUIRED_FLAG'];
rEQCOLTIP = json['REQ_COL_TIP'];
sEGMENTNAME = json['SEGMENT_NAME'];
sEGMENTPROMPT = json['SEGMENT_PROMPT'];
sEGMENTSEQNUM = json['SEGMENT_SEQ_NUM'];
@ -171,9 +173,6 @@ class GetEITDFFStructureList {
if (this.eSERVICESVS != null) {
data['E_SERVICES_VS'] = this.eSERVICESVS!.map((v) => v.toJson()).toList();
}
// if (this.eSERVICESVS != null) {
// data['E_SERVICES_VS'] = this.eSERVICESVS!.toList();
// }
data['FLEX_VALUE_SET_NAME'] = this.fLEXVALUESETNAME;
data['FORMAT_TYPE'] = this.fORMATTYPE;
data['FORMAT_TYPE_DSP'] = this.fORMATTYPEDSP;
@ -193,9 +192,9 @@ class GetEITDFFStructureList {
if (this.pARENTSEGMENTSVSSplitedVS != null) {
data['PARENT_SEGMENTS_VS_SplitedVS'] = this.pARENTSEGMENTSVSSplitedVS!.map((v) => v.toJson()).toList();
}
data['READ_ONLY'] = this.rEADONLY;
data['REQUIRED_FLAG'] = this.rEQUIREDFLAG;
data['REQ_COL_TIP'] = this.rEQCOLTIP;
data['SEGMENT_NAME'] = this.sEGMENTNAME;
data['SEGMENT_PROMPT'] = this.sEGMENTPROMPT;
data['SEGMENT_SEQ_NUM'] = this.sEGMENTSEQNUM;

@ -1,6 +1,6 @@
class GetMobileLoginInfoListModel {
int? iD;
int? employeeID;
String? employeeID;
int? channelID;
int? companyID;
String? deviceType;

@ -0,0 +1,187 @@
import 'dart:convert';
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart';
class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
///////////////////// Web RTC Video Calling //////////////////////
// Video Call
late RTCPeerConnection _peerConnection;
RTCVideoRenderer _localVideoRenderer = RTCVideoRenderer();
final RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();
MediaStream? _localStream;
MediaStream? _remoteStream;
void initCallListeners() {
chatHubConnection.on("OnCallAcceptedAsync", onCallAcceptedAsync);
chatHubConnection.on("OnIceCandidateAsync", onIceCandidateAsync);
chatHubConnection.on("OnOfferAsync", onOfferAsync);
chatHubConnection.on("OnAnswerOffer", onAnswerOffer);
chatHubConnection.on("OnHangUpAsync", onHangUpAsync);
chatHubConnection.on("OnCallDeclinedAsync", onCallDeclinedAsync);
}
//Video Constraints
var videoConstraints = {
"video": {
"mandatory": {
"width": {"min": 320},
"height": {"min": 180}
},
"optional": [
{
"width": {"max": 1280}
},
{"frameRate": 25},
{"facingMode": "user"}
]
},
"frameRate": 25,
"width": 420, //420,//640,//1280,
"height": 240 //240//480//720
};
// Audio Constraints
var audioConstraints = {
"sampleRate": 8000,
"sampleSize": 16,
"channelCount": 2,
"echoCancellation": true,
"audio": true,
};
Future<RTCPeerConnection> _createPeerConnection() async {
// {"url": "stun:stun.l.google.com:19302"},
Map<String, dynamic> configuration = {
"iceServers": [
{"urls": 'stun:15.185.116.59:3478'},
{"urls": "turn:15.185.116.59:3479", "username": "admin", "credential": "admin"}
]
};
Map<String, dynamic> offerSdpConstraints = {
"mandatory": {
"OfferToReceiveAudio": true,
"OfferToReceiveVideo": true,
},
"optional": [],
};
RTCPeerConnection pc = await createPeerConnection(configuration, offerSdpConstraints);
// if (pc != null) print(pc);
//pc.addStream(widget.localStream);
pc.onIceCandidate = (e) {
if (e.candidate != null) {
print(json.encode({
'candidate': e.candidate.toString(),
'sdpMid': e.sdpMid.toString(),
'sdpMlineIndex': e.sdpMLineIndex,
}));
}
};
pc.onIceConnectionState = (e) {
print(e);
};
pc.onAddStream = (stream) {
print('addStream: ' + stream.id);
_remoteRenderer.srcObject = stream;
};
return pc;
}
void init() {
initRenderers();
_createPeerConnection().then((pc) {
_peerConnection = pc;
// _setRemoteDescription(widget.info);
});
}
void initRenderers() {
_localVideoRenderer.initialize();
_remoteRenderer.initialize();
initLocalCamera();
}
void initLocalCamera() async {
_localStream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': true});
_localVideoRenderer.srcObject = _localStream;
// _localVideoRenderer.srcObject = await navigator.mediaDevices
// .getUserMedia({'video': true, 'audio': true});
print('this source Object');
print('this suarce ${_localVideoRenderer.srcObject != null}');
notifyListeners();
}
void startCall({required String callType}) {}
void endCall() {}
void checkCall(Map<String, dynamic> message) {
switch (message["callStatus"]) {
case 'connected':
{}
break;
case 'offer':
{}
break;
case 'accept':
{}
break;
case 'candidate':
{}
break;
case 'bye':
{}
break;
case 'leave':
{}
break;
}
}
//// Listeners Methods ////
void onCallAcceptedAsync(List<Object?>? params) {}
void onIceCandidateAsync(List<Object?>? params) {}
void onOfferAsync(List<Object?>? params) {}
void onAnswerOffer(List<Object?>? params) {}
void onHangUpAsync(List<Object?>? params) {}
void onCallDeclinedAsync(List<Object?>? params) {}
//// Invoke Methods
Future<void> invoke({required String invokeMethod, required String currentUserID, required String targetUserID, bool isVideoCall = false, var data}) async {
List<Object> args = [];
if (invokeMethod == "answerCallAsync") {
args = [currentUserID, targetUserID];
} else if (invokeMethod == "CallUserAsync") {
args = [currentUserID, targetUserID, isVideoCall];
} else if (invokeMethod == "IceCandidateAsync") {
args = [targetUserID, data];
} else if (invokeMethod == "OfferAsync") {
args = [targetUserID, data];
} else if (invokeMethod == "AnswerOfferAsync") {
args = [targetUserID, data];
//json In Data
}
await chatHubConnection.invoke(invokeMethod, args: args);
}
void stopListeners() async {
chatHubConnection.off('OnCallDeclinedAsync');
chatHubConnection.off('OnCallAcceptedAsync');
chatHubConnection.off('OnIceCandidateAsync');
chatHubConnection.off('OnAnswerOffer');
}
}

@ -69,6 +69,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
List<ChatUser> teamMembersList = [];
Material.TextDirection textDirection = Material.TextDirection.ltr;
bool isRTL = false;
String msgText = "";
//Chat Home Page Counter
int chatUConvCounter = 0;
@ -77,6 +79,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
List<ChatUser>? chatUsersList = [];
int pageNo = 1;
bool disbaleChatForThisUser = false;
Future<void> getUserAutoLoginToken() async {
userLoginToken.UserAutoLoginModel userLoginResponse = await ChatApiClient().getUserLoginToken();
if (userLoginResponse.response != null) {
@ -86,6 +90,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
Utils.showToast(
userLoginResponse.errorResponses!.first.fieldName.toString() + " Erorr",
);
disbaleChatForThisUser = true;
notifyListeners();
}
}
@ -117,6 +123,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
// chatHubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
chatHubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
chatHubConnection.on("OnUpdateUserChatHistoryStatusAsync", updateUserChatStatus);
if (kDebugMode) {
logger.i("All listeners registered");
}
@ -912,7 +919,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
String dateFormte(DateTime data) {
DateFormat f = DateFormat('hh:mm a dd MMM yyyy');
DateFormat f = DateFormat('hh:mm a dd MMM yyyy', "en_US");
f.format(data);
return f.format(data);
}
@ -1007,23 +1014,25 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
void disposeData() {
search.clear();
isChatScreenActive = false;
receiverID = 0;
paginationVal = 0;
message.text = '';
isTextMsg = false;
isAttachmentMsg = false;
isVoiceMsg = false;
isReplyMsg = false;
repliedMsg = [];
sFileType = "";
deleteData();
favUsersList.clear();
searchedChats?.clear();
pChatHistory?.clear();
chatHubConnection.stop();
AppState().chatDetails = null;
if (!disbaleChatForThisUser) {
search.clear();
isChatScreenActive = false;
receiverID = 0;
paginationVal = 0;
message.text = '';
isTextMsg = false;
isAttachmentMsg = false;
isVoiceMsg = false;
isReplyMsg = false;
repliedMsg = [];
sFileType = "";
deleteData();
favUsersList.clear();
searchedChats?.clear();
pChatHistory?.clear();
chatHubConnection.stop();
AppState().chatDetails = null;
}
}
void deleteData() {
@ -1407,17 +1416,16 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
void inputBoxDirection(String val) {
if (val.isNotEmpty) {
isTextMsg = true;
RegExp exp = RegExp("[a-zA-Z]");
if (exp.hasMatch(val.substring(val.length - 1)) && val.substring(val.length - 1) != " ") {
textDirection = Material.TextDirection.ltr;
notifyListeners();
} else if (val.substring(val.length - 1) != " " && !exp.hasMatch(val.substring(val.length - 1))) {
textDirection = Material.TextDirection.rtl;
notifyListeners();
}
} else {
isTextMsg = false;
}
msgText = val;
notifyListeners();
}
void onDirectionChange(bool val) {
isRTL = val;
notifyListeners();
}
Material.TextDirection getTextDirection(String v) {
@ -1451,18 +1459,19 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
void openChatByNoti(BuildContext context) async {
SingleUserChatModel nUser = SingleUserChatModel();
Utils.saveStringFromPrefs("isAppOpendByChat", "false");
SingleUserChatModel nUser = SingleUserChatModel.fromJson(jsonDecode(await Utils.getStringFromPrefs("notificationData")));
Utils.saveStringFromPrefs("notificationData", "null");
logger.w(jsonEncode(nUser));
Future.delayed(const Duration(seconds: 2));
for (ChatUser user in searchedChats!) {
if (user.id == nUser.targetUserId) {
Navigator.pushNamed(context, AppRoutes.chatDetailed, arguments: ChatDetailedScreenParams(user, false));
return;
} else {
openChatByNoti(context);
if (await Utils.getStringFromPrefs("notificationData") != "null") {
nUser = SingleUserChatModel.fromJson(jsonDecode(await Utils.getStringFromPrefs("notificationData")));
Utils.saveStringFromPrefs("notificationData", "null");
Future.delayed(const Duration(seconds: 2));
for (ChatUser user in searchedChats!) {
if (user.id == nUser.targetUserId) {
Navigator.pushNamed(context, AppRoutes.chatDetailed, arguments: ChatDetailedScreenParams(user, false));
return;
}
}
}
Utils.saveStringFromPrefs("notificationData", "null");
}
}

@ -103,11 +103,12 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
drawerMenuItemList = [
DrawerMenuItem("assets/images/drawer/my_profile.svg", LocaleKeys.myProfile.tr(), AppRoutes.profile),
DrawerMenuItem("assets/images/drawer/performance_evaluation.svg", LocaleKeys.performanceEvaluation.tr(), AppRoutes.performanceEvaluation),
DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.mowadhafhi.tr(), AppRoutes.mowadhafhi),
DrawerMenuItem("assets/images/drawer/pending_trasactions.svg", LocaleKeys.pendingTransactions.tr(), AppRoutes.pendingTransactions),
// DrawerMenuItem("assets/images/drawer/drawer_marathon.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen),
DrawerMenuItem("assets/images/drawer/change_password.svg", LocaleKeys.changePassword.tr(), AppRoutes.changePassword),
// DrawerMenuItem("assets/images/drawer/performance_evaluation.svg", LocaleKeys.performanceEvaluation.tr(), AppRoutes.performanceEvaluation),
// DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.mowadhafhi.tr(), AppRoutes.mowadhafhi),
// DrawerMenuItem("assets/images/drawer/pending_trasactions.svg", LocaleKeys.pendingTransactions.tr(), AppRoutes.pendingTransactions),
// // DrawerMenuItem("assets/images/drawer/drawer_marathon.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen),
// DrawerMenuItem("assets/images/drawer/change_password.svg", LocaleKeys.changePassword.tr(), AppRoutes.changePassword),
//
];
notifyListeners();
@ -139,15 +140,17 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
getOpenNotificationsList = genericResponseModel?.getOpenNotificationsList;
workListCounter = genericResponseModel?.pOPENNTFNUMBER ?? 0;
itgFormsModel = await DashboardApiClient().getItgFormsPendingTask();
if (env.itg) itgFormsModel = await DashboardApiClient().getItgFormsPendingTask();
workListCounter = workListCounter + (itgFormsModel?.totalCount ?? 0);
GenericResponseModel? cocGenericResponseModel = await DashboardApiClient().getCOCNotifications();
cocCount = cocGenericResponseModel?.mohemmITGPendingTaskResponseItem;
if (cocCount != null) {
cocFinalCount = (cocCount?.escalation ?? 0) + (cocCount?.waitingToClose ?? 0) + (cocCount?.waitingForAcceptance ?? 0) + (cocCount?.extendTATRequest ?? 0);
workListCounter += cocFinalCount;
if (env.itg) {
GenericResponseModel? cocGenericResponseModel = await DashboardApiClient().getCOCNotifications();
cocCount = cocGenericResponseModel?.mohemmITGPendingTaskResponseItem;
if (cocCount != null) {
cocFinalCount = (cocCount?.escalation ?? 0) + (cocCount?.waitingToClose ?? 0) + (cocCount?.waitingForAcceptance ?? 0) + (cocCount?.extendTATRequest ?? 0);
workListCounter += cocFinalCount;
}
}
if (showLoading) Utils.hideLoading(context);
notifyListeners();
} catch (ex) {
@ -188,7 +191,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
//Leave and Ticket Balance API's & Methods
Future fetchLeaveTicketBalance(context, DateTime date) async {
try {
accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(date));
accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy", "en_US").format(date));
isLeaveTicketBalanceLoading = false;
leaveBalanceAccrual = accrualList![0];
ticketBalance = (accrualList![1].accrualNetEntitlement ?? 0.0) + (accrualList![2].accrualNetEntitlement ?? 0.0) + (accrualList![3].accrualNetEntitlement ?? 0.0);
@ -210,12 +213,12 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
List<ListMenu> menuList = await DashboardApiClient().getListMenu();
List findMyRequest = menuList.where((element) => element.menuType == "E").toList();
if (findMyRequest.isNotEmpty) {
drawerMenuItemList.insert(3, DrawerMenuItem("assets/images/drawer/my_requests.svg", LocaleKeys.myRequest.tr(), AppRoutes.myRequests));
drawerMenuItemList.add(DrawerMenuItem("assets/images/drawer/my_requests.svg", LocaleKeys.myRequest.tr(), AppRoutes.myRequests));
}
List findMyTeam = menuList.where((element) => element.menuType == "M").toList();
if (findMyTeam.isNotEmpty) {
AppState().setempStatusIsManager = true;
drawerMenuItemList.insert(2, DrawerMenuItem("assets/images/drawer/my_team.svg", LocaleKeys.myTeamMembers.tr(), AppRoutes.myTeam));
drawerMenuItemList.add(DrawerMenuItem("assets/images/drawer/my_team.svg", LocaleKeys.myTeamMembers.tr(), AppRoutes.myTeam));
}
} catch (ex) {
logger.wtf(ex);
@ -231,10 +234,10 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
homeMenus = parseMenus(getMenuEntriesList ?? []);
if (homeMenus!.isNotEmpty) {
if(env["dashboard"]["monthlyAttendance"]) {
if (env.dashboard.monthlyAttendance) {
homeMenus!.first.menuEntiesList.insert(0, GetMenuEntriesList(requestType: "MONTHLY_ATTENDANCE", prompt: LocaleKeys.monthlyAttendance.tr()));
}
if(env["dashboard"]["vocationRules"]) {
if (env.dashboard.vocationRules) {
homeMenus!.first.menuEntiesList.add(GetMenuEntriesList(requestType: "VACATION_RULE", prompt: LocaleKeys.vacationRule.tr()));
}
}
@ -247,7 +250,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
}
void getCategoryOffersListAPI(BuildContext context) async {
void getCategoryOffersListAPI(BuildContext context) async {
try {
// Utils.showLoading(context);
getOffersList = await OffersAndDiscountsApiClient().getOffersList(0, 10);
@ -274,6 +277,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
MohemmItgResponseItem? res = await DashboardApiClient().getITGPageNotification();
return res;
}
void notify() {
notifyListeners();
}

@ -432,7 +432,7 @@ class _MonthlyAttendanceScreenState extends State<MonthlyAttendanceScreen> {
expand: false,
builder: (_, controller) {
dynamic dmyString = getScheduleShiftsDetailsList!.sCHEDULEDATE;
DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss").parse(dmyString);
DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss", "en_US").parse(dmyString);
return Column(
children: [
Container(

@ -140,7 +140,7 @@ class _VacationRuleScreenState extends State<VacationRuleScreen> {
}
String getParsedTime(String time) {
DateTime date = DateFormat("MM/dd/yyyy").parse(time);
return DateFormat("d MMM yyyy").format(date);
DateTime date = DateFormat("MM/dd/yyyy", "en_US").parse(time);
return DateFormat("d MMM yyyy", "en_US").format(date);
}
}

@ -10,12 +10,14 @@ import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/chat/call.dart';
import 'package:mohem_flutter_app/provider/chat_call_provider.dart';
import 'package:provider/provider.dart';
class OutGoingCall extends StatefulWidget {
CallDataModel OutGoingCallData;
bool? isVideoCall;
CallDataModel outGoingCallData;
bool isVideoCall;
OutGoingCall({Key? key, required this.OutGoingCallData, this.isVideoCall}) : super(key: key);
OutGoingCall({Key? key, required this.outGoingCallData, required this.isVideoCall}) : super(key: key);
@override
_OutGoingCallState createState() => _OutGoingCallState();
@ -23,23 +25,25 @@ class OutGoingCall extends StatefulWidget {
class _OutGoingCallState extends State<OutGoingCall> with SingleTickerProviderStateMixin {
AnimationController? _animationController;
CameraController? _controller;
late CameraController controller;
late List<CameraDescription> _cameras;
Future<void>? _initializeControllerFuture;
bool isCameraReady = false;
bool isMicOff = false;
bool isLoudSpeaker = false;
bool isCamOff = false;
late ChatCallProvider callProviderd;
@override
void initState() {
callProviderd = Provider.of<ChatCallProvider>(context, listen: false);
_animationController = AnimationController(
vsync: this,
duration: const Duration(
milliseconds: 500,
),
);
logger.d(jsonEncode(widget.OutGoingCallData));
//_runAnimation();
// _runAnimation();
// connectSignaling();
WidgetsBinding.instance.addPostFrameCallback(
(_) => _runAnimation(),
@ -58,13 +62,10 @@ class _OutGoingCallState extends State<OutGoingCall> with SingleTickerProviderSt
return Stack(
alignment: FractionalOffset.center,
children: <Widget>[
if (widget.isVideoCall!)
if (widget.isVideoCall)
Positioned.fill(
child: AspectRatio(
aspectRatio: _controller!.value.aspectRatio,
child: CameraPreview(
_controller!,
),
child: CameraPreview(
controller,
),
),
Positioned.fill(
@ -74,7 +75,7 @@ class _OutGoingCallState extends State<OutGoingCall> with SingleTickerProviderSt
child: Container(
decoration: BoxDecoration(
color: MyColors.grey57Color.withOpacity(
0.7,
0.3,
),
),
child: Column(
@ -105,9 +106,9 @@ class _OutGoingCallState extends State<OutGoingCall> with SingleTickerProviderSt
fit: BoxFit.cover,
),
10.height,
const Text(
"Aamir Saleem Ahmad",
style: TextStyle(
Text(
widget.outGoingCallData.title,
style: const TextStyle(
fontSize: 21,
fontWeight: FontWeight.bold,
color: MyColors.white,
@ -179,7 +180,7 @@ class _OutGoingCallState extends State<OutGoingCall> with SingleTickerProviderSt
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
if (widget.isVideoCall!)
if (widget.isVideoCall)
RawMaterialButton(
onPressed: () {
_camOff();
@ -267,13 +268,10 @@ class _OutGoingCallState extends State<OutGoingCall> with SingleTickerProviderSt
}
void _runAnimation() async {
List<CameraDescription> cameras = await availableCameras();
CameraDescription firstCamera = cameras[1];
_controller = CameraController(
firstCamera,
ResolutionPreset.medium,
);
_initializeControllerFuture = _controller!.initialize();
_cameras = await availableCameras();
CameraDescription firstCamera = _cameras[1];
controller = CameraController(firstCamera, ResolutionPreset.medium);
_initializeControllerFuture = controller.initialize();
setState(() {});
// setAudioFile();
for (int i = 0; i < 100; i++) {
@ -304,7 +302,7 @@ class _OutGoingCallState extends State<OutGoingCall> with SingleTickerProviderSt
try {
// backToHome();
// final roomModel = RoomModel(name: widget.OutGoingCallData.name, token: widget.OutGoingCallData.sessionId, identity: widget.OutGoingCallData.identity);
await _controller?.dispose();
await controller?.dispose();
// changeCallStatusAPI(4);

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
@ -13,7 +14,10 @@ import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/chat/call.dart';
import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart';
import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart';
import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart';
import 'package:mohem_flutter_app/provider/chat_call_provider.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/ui/chat/custom_auto_direction.dart';
import 'package:mohem_flutter_app/ui/chat/call/chat_outgoing_call_screen.dart';
import 'package:mohem_flutter_app/ui/chat/chat_bubble.dart';
import 'package:mohem_flutter_app/ui/chat/common.dart';
@ -41,8 +45,10 @@ class ChatDetailScreen extends StatefulWidget {
class _ChatDetailScreenState extends State<ChatDetailScreen> {
final RefreshController _rc = RefreshController(initialRefresh: false);
late ChatProviderModel data;
late ChatCallProvider callPro;
ChatDetailedScreenParams? params;
var textDirection = TextDirection.RTL;
// var textDirection = TextDirection.RTL;
void getMoreChat() async {
if (params != null) {
@ -72,6 +78,7 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
Widget build(BuildContext context) {
params = ModalRoute.of(context)!.settings.arguments as ChatDetailedScreenParams;
data = Provider.of<ChatProviderModel>(context, listen: false);
// callPro = Provider.of<ChatCallProvider>(context, listen: false);
if (params != null) {
data.getSingleUserChatHistory(
senderUID: AppState().chatDetails!.response!.id!.toInt(),
@ -92,11 +99,11 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
chatUser: params!.chatUser,
actions: [
// SvgPicture.asset("assets/icons/chat/call.svg", width: 21, height: 23).onPress(() {
// // makeCall(callType: "AUDIO", con: hubConnection);
// makeCall(callType: "AUDIO");
// }),
// 24.width,
// SvgPicture.asset("assets/icons/chat/video_call.svg", width: 21, height: 18).onPress(() {
// // makeCall(callType: "VIDEO", con: hubConnection);
// makeCall(callType: "VIDEO");
// }),
// 21.width,
],
@ -252,37 +259,39 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
if (!m.isRecoding)
Row(
children: [
TextField(
textDirection: m.textDirection,
controller: m.message,
decoration: InputDecoration(
hintTextDirection: m.textDirection,
hintText: m.isAttachmentMsg
? m.selectedFile.path.split("/").last
: m.textDirection.name == "rtl" ? "اكتب هنا للرد" :LocaleKeys.typeheretoreply.tr(),
hintStyle: TextStyle(color: m.isAttachmentMsg ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14),
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
filled: true,
fillColor: MyColors.white,
contentPadding: const EdgeInsets.only(
left: 21,
top: 20,
bottom: 20,
CustomAutoDirection(
onDirectionChange: (bool isRTL) => m.onDirectionChange(isRTL),
text: m.msgText,
child: TextField(
// textDirection: m.textDirection,
controller: m.message,
decoration: InputDecoration(
hintTextDirection: m.textDirection,
hintText: m.isAttachmentMsg ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(),
hintStyle: TextStyle(color: m.isAttachmentMsg ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14),
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
filled: true,
fillColor: MyColors.white,
contentPadding: const EdgeInsets.only(
left: 21,
top: 20,
bottom: 20,
),
prefixIconConstraints: const BoxConstraints(),
prefixIcon: m.sFileType.isNotEmpty
? SvgPicture.asset(m.getType(m.sFileType), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 21, right: 15)
: null,
),
prefixIconConstraints: const BoxConstraints(),
prefixIcon: m.sFileType.isNotEmpty
? SvgPicture.asset(m.getType(m.sFileType), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 21, right: 15)
: null,
),
onChanged: (String val) {
m.inputBoxDirection(val);
m.userTypingInvoke(currentUser: AppState().chatDetails!.response!.id!, reciptUser: params!.chatUser!.id!);
},
).expanded,
onChanged: (String val) {
m.inputBoxDirection(val);
m.userTypingInvoke(currentUser: AppState().chatDetails!.response!.id!, reciptUser: params!.chatUser!.id!);
},
).expanded,
),
if (m.sFileType.isNotEmpty)
Row(
children: <Widget>[
@ -342,45 +351,30 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
}
}
void makeCall({required String callType, required HubConnection con}) async {
void makeCall({required String callType}) async {
callPro.initCallListeners();
print("================== Make call Triggered ============================");
Map<String, dynamic> json = {
"callerID": AppState().chatDetails!.response!.id!.toString(),
"callReceiverID": params!.chatUser!.id.toString(),
"notification_foreground": "true",
"message": "Aamir is calling",
"title": "Video Call",
"type": callType == "VIDEO" ? "Video" : "Audio",
"identity": AppState().chatDetails!.response!.userName,
"name": AppState().chatDetails!.response!.title,
"is_call": "true",
"is_webrtc": "true",
"contant": "Start video Call ${AppState().chatDetails!.response!.userName}",
"contantNo": "775d1f11-62d9-6fcc-91f6-21f8c14559fb",
"chatEventId": "3",
"fileTypeId": null,
"currentUserId": AppState().chatDetails!.response!.id!.toString(),
"chatSource": "1",
"userChatHistoryLineRequestList": [
{
"isSeen": false,
"isDelivered": false,
"targetUserId": params!.chatUser!.id!,
"targetUserStatus": 4,
}
],
// "server": "https://192.168.8.163:8086",
"server": "https://livecareturn.hmg.com:8086",
"callerDetails": AppState().chatDetails!.toJson(),
"receiverID": params!.chatUser!.id.toString(),
"receiverDetails": params!.chatUser!.toJson(),
"title": params!.chatUser!.userName!.replaceAll(".", " "),
"calltype": callType == "VIDEO" ? "Video" : "Audio",
};
logger.w(json);
CallDataModel callData = CallDataModel.fromJson(json);
await Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => OutGoingCall(
isVideoCall: callType == "VIDEO" ? true : false,
OutGoingCallData: callData,
outGoingCallData: callData,
),
),
);
).then((value) {
print("then");
callPro.stopListeners();
});
}
}

@ -52,11 +52,11 @@ class _ChatHomeState extends State<ChatHome> {
if (data.searchedChats == null || data.searchedChats!.isEmpty) {
data.isLoading = true;
data.getUserRecentChats().whenComplete(() async {
String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat");
String notificationData = await Utils.getStringFromPrefs("notificationData");
if (isAppOpendByChat != "null" || isAppOpendByChat == "true" && notificationData != "null") {
data.openChatByNoti(context);
}
// String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat");
// String notificationData = await Utils.getStringFromPrefs("notificationData");
// if (isAppOpendByChat != "null" || isAppOpendByChat == "true" && notificationData != "null") {
// data.openChatByNoti(context);
// }
});
}
}

@ -0,0 +1,38 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart' as intl;
class CustomAutoDirection extends StatefulWidget {
final String text;
final Widget child;
final void Function(bool isRTL)? onDirectionChange;
const CustomAutoDirection({Key? key, required this.text, required this.child, this.onDirectionChange}) : super(key: key);
@override
_CustomAutoDirectionState createState() => _CustomAutoDirectionState();
}
class _CustomAutoDirectionState extends State<CustomAutoDirection> {
late String text;
late Widget childWidget;
@override
Widget build(BuildContext context) {
text = widget.text;
childWidget = widget.child;
return Directionality(textDirection: isRTL(text) ? TextDirection.rtl : TextDirection.ltr, child: childWidget);
}
@override
void didUpdateWidget(CustomAutoDirection oldWidget) {
if (isRTL(oldWidget.text) != isRTL(widget.text)) {
WidgetsBinding.instance.addPostFrameCallback((_) => widget.onDirectionChange?.call(isRTL(widget.text)));
}
super.didUpdateWidget(oldWidget);
}
bool isRTL(String text) {
if (text.isEmpty) return Directionality.of(context) == TextDirection.rtl;
return intl.Bidi.detectRtlDirectionality(text);
}
}

@ -6,10 +6,8 @@ import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/main.dart';
class EmployeeDigitialIdDialog extends StatelessWidget {
@override

@ -61,13 +61,13 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
super.initState();
scheduleMicrotask(() {
data = Provider.of<DashboardProviderModel>(context, listen: false);
if (env["marathon"]) {
if (env.marathon) {
marathonProvider = Provider.of<MarathonProvider>(context, listen: false);
}
if (env["chat"]) {
if (env.chat) {
cProvider = Provider.of<ChatProviderModel>(context, listen: false);
_bHubCon();
}
_bHubCon();
_onRefresh(true);
});
}
@ -91,24 +91,28 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
chatHubConnection.stop();
if (!cProvider.disbaleChatForThisUser) {
chatHubConnection.stop();
}
}
void _bHubCon() {
cProvider.getUserAutoLoginToken().whenComplete(() async {
String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat");
if (isAppOpendByChat != null && isAppOpendByChat == "true") {
Utils.showLoading(context);
cProvider.buildHubConnection();
Future.delayed(const Duration(seconds: 2), () async {
cProvider.invokeChatCounter(userId: AppState().chatDetails!.response!.id!);
gotoChat(context);
});
} else {
cProvider.buildHubConnection();
Future.delayed(const Duration(seconds: 2), () {
cProvider.invokeChatCounter(userId: AppState().chatDetails!.response!.id!);
});
if (!cProvider.disbaleChatForThisUser) {
String isAppOpendByChat = await Utils.getStringFromPrefs("isAppOpendByChat");
if (isAppOpendByChat != null && isAppOpendByChat == "true") {
Utils.showLoading(context);
cProvider.buildHubConnection();
Future.delayed(const Duration(seconds: 2), () async {
cProvider.invokeChatCounter(userId: AppState().chatDetails!.response!.id!);
gotoChat(context);
});
} else {
cProvider.buildHubConnection();
Future.delayed(const Duration(seconds: 2), () {
cProvider.invokeChatCounter(userId: AppState().chatDetails!.response!.id!);
});
}
}
});
}
@ -137,21 +141,25 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
// print(value.result!.data!.notificationTitle);
// });
data.fetchListMenu();
if (env["dashboard"]["attendance"]) {
if (env.dashboard.attendance) {
data.fetchAttendanceTracking(context);
}
data.fetchWorkListCounter(context);
if (env["dashboard"]["missingSwipe"]) {
if (env.dashboard.missingSwipe) {
data.fetchMissingSwipe(context);
}
data.fetchLeaveTicketBalance(context, DateTime.now());
data.fetchMenuEntries();
data.getCategoryOffersListAPI(context);
if (env["marathon"]) {
if (env.offersDiscount) {
data.getCategoryOffersListAPI(context);
}
if (env.marathon) {
marathonProvider.getMarathonDetailsFromApi();
}
if (!isFromInit) checkHubCon();
if (env.chat) {
marathonProvider.getMarathonDetailsFromApi();
if (!cProvider.disbaleChatForThisUser && !isFromInit) checkHubCon();
}
_refreshController.refreshCompleted();
}
@ -235,12 +243,12 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
});
}),
Image.asset("assets/images/logos/main_mohemm_logo.png", width: 134, height: 28).expanded,
SvgPicture.asset(
"assets/images/announcements.svg",
matchTextDirection: true,
).onPress(() async {
await Navigator.pushNamed(context, AppRoutes.announcements);
})
// SvgPicture.asset(
// "assets/images/announcements.svg",
// matchTextDirection: true,
// ).onPress(() async {
// await Navigator.pushNamed(context, AppRoutes.announcements);
// })
],
).paddingOnly(left: 21, right: 21, top: 48, bottom: 7),
Expanded(
@ -265,119 +273,119 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
16.height,
Row(
children: [
if (env["dashboard"]["attendance"])
Expanded(
child: AspectRatio(
aspectRatio: 159 / 159,
child: Consumer<DashboardProviderModel>(
builder: (BuildContext context, DashboardProviderModel model, Widget? child) {
return (model.isAttendanceTrackingLoading
? GetAttendanceTrackingShimmer()
: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
gradient: const LinearGradient(transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [
MyColors.gradiantEndColor,
MyColors.gradiantStartColor,
]),
),
child: Stack(
alignment: Alignment.center,
children: [
if (model.isTimeRemainingInSeconds == 0) SvgPicture.asset("assets/images/thumb.svg"),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
if (env.dashboard.attendance)
Expanded(
child: AspectRatio(
aspectRatio: 159 / 159,
child: Consumer<DashboardProviderModel>(
builder: (BuildContext context, DashboardProviderModel model, Widget? child) {
return (model.isAttendanceTrackingLoading
? GetAttendanceTrackingShimmer()
: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
gradient: const LinearGradient(transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [
MyColors.gradiantEndColor,
MyColors.gradiantStartColor,
]),
),
child: Stack(
alignment: Alignment.center,
children: [
if (model.isTimeRemainingInSeconds == 0) SvgPicture.asset("assets/images/thumb.svg"),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.markAttendance.tr().toText14(color: Colors.white, isBold: true),
if (model.isTimeRemainingInSeconds == 0) DateTime.now().toString().split(" ")[0].toText12(color: Colors.white),
if (model.isTimeRemainingInSeconds != 0)
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
9.height,
Directionality(
textDirection: ui.TextDirection.ltr,
child: CountdownTimer(
endTime: model.endTime,
onEnd: null,
endWidget: "00:00:00".toText14(color: Colors.white, isBold: true),
textStyle: const TextStyle(color: Colors.white, fontSize: 14, letterSpacing: -0.48, fontWeight: FontWeight.bold),
),
),
LocaleKeys.timeLeftToday.tr().toText12(color: Colors.white),
9.height,
ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(20)),
child: LinearProgressIndicator(
value: model.progress,
minHeight: 8,
valueColor: const AlwaysStoppedAnimation<Color>(Colors.white),
backgroundColor: const Color(0xff196D73),
),
),
],
),
],
).paddingOnly(top: 12, right: 15, left: 12),
),
Row(
children: [
LocaleKeys.markAttendance.tr().toText14(color: Colors.white, isBold: true),
if (model.isTimeRemainingInSeconds == 0) DateTime.now().toString().split(" ")[0].toText12(color: Colors.white),
if (model.isTimeRemainingInSeconds != 0)
Column(
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
9.height,
Directionality(
textDirection: ui.TextDirection.ltr,
child: CountdownTimer(
endTime: model.endTime,
onEnd: null,
endWidget: "00:00:00".toText14(color: Colors.white, isBold: true),
textStyle: const TextStyle(color: Colors.white, fontSize: 14, letterSpacing: -0.48, fontWeight: FontWeight.bold),
),
),
LocaleKeys.timeLeftToday.tr().toText12(color: Colors.white),
9.height,
ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(20)),
child: LinearProgressIndicator(
value: model.progress,
minHeight: 8,
valueColor: const AlwaysStoppedAnimation<Color>(Colors.white),
backgroundColor: const Color(0xff196D73),
),
),
LocaleKeys.checkIn.tr().toText12(color: Colors.white),
(model.attendanceTracking!.pSwipeIn == null ? "--:--" : model.attendanceTracking!.pSwipeIn)
.toString()
.toText14(color: Colors.white, isBold: true),
4.height,
],
).paddingOnly(left: 12, right: 12),
),
Container(
margin: EdgeInsets.only(top: AppState().isArabic(context) ? 6 : 0),
width: 45,
height: 45,
padding: const EdgeInsets.only(left: 10, right: 10),
decoration: BoxDecoration(
color: Color(0xff259EA4),
borderRadius: BorderRadius.only(
bottomRight: AppState().isArabic(context) ? Radius.circular(0) : Radius.circular(15),
bottomLeft: AppState().isArabic(context) ? Radius.circular(15) : Radius.circular(0),
),
),
child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/attendance.svg" : "assets/images/attendance.svg"),
).onPress(() {
showMyBottomSheet(
context,
callBackFunc: () {},
child: MarkAttendanceWidget(model, isFromDashboard: true),
);
}),
],
).paddingOnly(top: 12, right: 15, left: 12),
),
Row(
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.checkIn.tr().toText12(color: Colors.white),
(model.attendanceTracking!.pSwipeIn == null ? "--:--" : model.attendanceTracking!.pSwipeIn)
.toString()
.toText14(color: Colors.white, isBold: true),
4.height,
],
).paddingOnly(left: 12, right: 12),
),
Container(
margin: EdgeInsets.only(top: AppState().isArabic(context) ? 6 : 0),
width: 45,
height: 45,
padding: const EdgeInsets.only(left: 10, right: 10),
decoration: BoxDecoration(
color: Color(0xff259EA4),
borderRadius: BorderRadius.only(
bottomRight: AppState().isArabic(context) ? Radius.circular(0) : Radius.circular(15),
bottomLeft: AppState().isArabic(context) ? Radius.circular(15) : Radius.circular(0),
),
),
child: SvgPicture.asset(model.isTimeRemainingInSeconds == 0 ? "assets/images/attendance.svg" : "assets/images/attendance.svg"),
).onPress(() {
showMyBottomSheet(
context,
callBackFunc: () {},
child: MarkAttendanceWidget(model, isFromDashboard: true),
);
}),
],
),
],
),
],
),
).onPress(
() {
Navigator.pushNamed(context, AppRoutes.todayAttendance);
},
))
.animatedSwither();
},
),
],
),
],
),
).onPress(
() {
Navigator.pushNamed(context, AppRoutes.todayAttendance);
},
))
.animatedSwither();
},
),
),
),
),
if (env["dashboard"]["attendance"]) 9.width,
if (env.dashboard.attendance) 9.width,
Expanded(
child: MenusWidget(),
),
@ -385,102 +393,105 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
),
],
).paddingOnly(left: 21, right: 21, top: 7, bottom: 21),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
LocaleKeys.offers.tr().toText12(),
Row(
children: [
LocaleKeys.discounts.tr().toText24(isBold: true),
6.width,
Container(
padding: const EdgeInsets.only(left: 8, right: 8),
decoration: BoxDecoration(
color: MyColors.yellowColor,
borderRadius: BorderRadius.circular(10),
),
child: LocaleKeys.newString.tr().toText10(isBold: true)),
],
),
],
Visibility(
visible: env.offersDiscount,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
LocaleKeys.offers.tr().toText12(),
Row(
children: [
LocaleKeys.discounts.tr().toText24(isBold: true),
6.width,
Container(
padding: const EdgeInsets.only(left: 8, right: 8),
decoration: BoxDecoration(
color: MyColors.yellowColor,
borderRadius: BorderRadius.circular(10),
),
child: LocaleKeys.newString.tr().toText10(isBold: true)),
],
),
],
),
),
),
LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() {
Navigator.pushNamed(context, AppRoutes.offersAndDiscounts);
})
],
).paddingOnly(left: 21, right: 21),
Consumer<DashboardProviderModel>(
builder: (BuildContext context, DashboardProviderModel model, Widget? child) {
return SizedBox(
height: 103 + 33,
child: ListView.separated(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.only(left: 21, right: 21, top: 13),
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext cxt, int index) {
return model.isOffersLoading
? const OffersShimmerWidget()
: InkWell(
onTap: () {
navigateToDetails(data.getOffersList[index]);
},
child: SizedBox(
width: 73,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 73,
height: 73,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(
Radius.circular(100),
),
border: Border.all(color: MyColors.lightGreyE3Color, width: 1),
),
child: ClipRRect(
borderRadius: const BorderRadius.all(
Radius.circular(50),
LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() {
Navigator.pushNamed(context, AppRoutes.offersAndDiscounts);
})
],
).paddingOnly(left: 21, right: 21),
Consumer<DashboardProviderModel>(
builder: (BuildContext context, DashboardProviderModel model, Widget? child) {
return SizedBox(
height: 103 + 33,
child: ListView.separated(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.only(left: 21, right: 21, top: 13),
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext cxt, int index) {
return model.isOffersLoading
? const OffersShimmerWidget()
: InkWell(
onTap: () {
navigateToDetails(data.getOffersList[index]);
},
child: SizedBox(
width: 73,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 73,
height: 73,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(
Radius.circular(100),
),
border: Border.all(color: MyColors.lightGreyE3Color, width: 1),
),
child: Hero(
tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!,
transitionOnUserGestures: true,
child: Image.network(
data.getOffersList[index].bannerImage!,
fit: BoxFit.contain,
child: ClipRRect(
borderRadius: const BorderRadius.all(
Radius.circular(50),
),
child: Hero(
tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!,
transitionOnUserGestures: true,
child: Image.network(
data.getOffersList[index].logo!,
fit: BoxFit.contain,
),
),
),
),
),
4.height,
Expanded(
child: AppState().isArabic(context)
? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1)
: data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1),
),
],
4.height,
Expanded(
child: AppState().isArabic(context)
? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1)
: data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1),
),
],
),
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => 8.width,
itemCount: 9),
);
},
),
],
);
},
separatorBuilder: (BuildContext cxt, int index) => 8.width,
itemCount: 9),
);
},
),
],
),
),
Container(
width: double.infinity,
@ -493,9 +504,8 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (env["marathon"])
context.watch<MarathonProvider>().isLoading ? const MarathonBannerShimmer().paddingAll(20) : const MarathonBanner().paddingOnly(left: 21, right: 21, bottom: 21, top: 8),
if (env.marathon)
context.watch<MarathonProvider>().isLoading ? const MarathonBannerShimmer().paddingAll(20) : const MarathonBanner().paddingOnly(left: 21, right: 21, bottom: 21, top: 8),
ServicesWidget(),
],
),
@ -510,110 +520,116 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
drawer: SafeArea(
child: AppDrawer(onLanguageChange: _onRefresh),
),
bottomNavigationBar:!env["bottomBar"]
bottomNavigationBar: !env.bottomBar
? null
: SizedBox(
height: Platform.isAndroid ? 70 : 100,
child: BottomNavigationBar(
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: SvgPicture.asset(
"assets/icons/home.svg",
color: currentIndex == 0 ? MyColors.grey3AColor : MyColors.grey98Color,
).paddingAll(4),
label: LocaleKeys.home.tr(),
),
BottomNavigationBarItem(
icon: SvgPicture.asset(
"assets/icons/create_req.svg",
color: currentIndex == 1 ? MyColors.grey3AColor : MyColors.grey98Color,
).paddingAll(4),
label: LocaleKeys.mowadhafhiRequest.tr(),
),
BottomNavigationBarItem(
icon: Stack(
alignment: Alignment.centerLeft,
children: [
SvgPicture.asset(
"assets/icons/work_list.svg",
color: currentIndex == 2 ? MyColors.grey3AColor : MyColors.grey98Color,
).paddingAll(4),
Consumer<DashboardProviderModel>(
builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) {
if (data.workListCounter == 0) {
return const SizedBox();
}
return Positioned(
right: 0,
top: 0,
child: Container(
padding: const EdgeInsets.only(left: 4, right: 4),
alignment: Alignment.center,
decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)),
child: data.workListCounter.toString().toText10(color: Colors.white),
height: Platform.isAndroid ? 70 : 100,
child: BottomNavigationBar(
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: SvgPicture.asset(
"assets/icons/home.svg",
color: currentIndex == 0 ? MyColors.grey3AColor : MyColors.grey98Color,
).paddingAll(4),
label: LocaleKeys.home.tr(),
),
BottomNavigationBarItem(
icon: SvgPicture.asset(
"assets/icons/create_req.svg",
color: currentIndex == 1 ? MyColors.grey3AColor : MyColors.grey98Color,
).paddingAll(4),
label: LocaleKeys.mowadhafhiRequest.tr(),
),
BottomNavigationBarItem(
icon: Stack(
alignment: Alignment.centerLeft,
children: [
SvgPicture.asset(
"assets/icons/work_list.svg",
color: currentIndex == 2 ? MyColors.grey3AColor : MyColors.grey98Color,
).paddingAll(4),
Consumer<DashboardProviderModel>(
builder: (BuildContext cxt, DashboardProviderModel data, Widget? child) {
if (data.workListCounter == 0) {
return const SizedBox();
}
return Positioned(
right: 0,
top: 0,
child: Container(
padding: const EdgeInsets.only(left: 4, right: 4),
alignment: Alignment.center,
decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)),
child: data.workListCounter.toString().toText10(color: Colors.white),
),
);
},
),
);
},
],
),
label: LocaleKeys.workList.tr(),
),
],
),
label: LocaleKeys.workList.tr(),
),
BottomNavigationBarItem(
icon: SvgPicture.asset(
"assets/icons/item_for_sale.svg",
color: currentIndex == 3 ? MyColors.grey3AColor : MyColors.grey98Color,
).paddingAll(4),
label: LocaleKeys.itemsForSale.tr(),
),
BottomNavigationBarItem(
icon: Stack(
alignment: Alignment.centerLeft,
children: [
SvgPicture.asset(
"assets/icons/chat/chat.svg",
color: currentIndex == 4 ? MyColors.grey3AColor : MyColors.grey98Color,
).paddingAll(4),
Consumer<ChatProviderModel>(
builder: (BuildContext cxt, ChatProviderModel data, Widget? child) {
return Positioned(
right: 0,
top: 0,
child: Container(
padding: const EdgeInsets.only(left: 4, right: 4),
alignment: Alignment.center,
decoration: BoxDecoration(color: MyColors.redColor, borderRadius: BorderRadius.circular(17)),
child: data.chatUConvCounter.toString().toText10(color: Colors.white),
BottomNavigationBarItem(
icon: SvgPicture.asset(
"assets/icons/item_for_sale.svg",
color: currentIndex == 3 ? MyColors.grey3AColor : MyColors.grey98Color,
).paddingAll(4),
label: LocaleKeys.itemsForSale.tr(),
),
BottomNavigationBarItem(
icon: Stack(
alignment: Alignment.centerLeft,
children: [
SvgPicture.asset(
"assets/icons/chat/chat.svg",
color: currentIndex == 4
? MyColors.grey3AColor
: cProvider.disbaleChatForThisUser
? MyColors.lightGreyE3Color
: MyColors.grey98Color,
).paddingAll(4),
Consumer<ChatProviderModel>(
builder: (BuildContext cxt, ChatProviderModel data, Widget? child) {
return Positioned(
right: 0,
top: 0,
child: Container(
padding: const EdgeInsets.only(left: 4, right: 4),
alignment: Alignment.center,
decoration: BoxDecoration(color: cProvider.disbaleChatForThisUser ? MyColors.pinkDarkColor : MyColors.redColor, borderRadius: BorderRadius.circular(17)),
child: data.chatUConvCounter.toString().toText10(color: Colors.white),
),
);
},
),
);
},
],
),
label: LocaleKeys.chat.tr(),
),
],
currentIndex: currentIndex,
selectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey3AColor, fontWeight: FontWeight.w600),
unselectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey98Color, fontWeight: FontWeight.w600),
type: BottomNavigationBarType.fixed,
selectedItemColor: MyColors.grey3AColor,
backgroundColor: MyColors.backgroundColor,
selectedIconTheme: const IconThemeData(color: MyColors.grey3AColor, size: 28),
unselectedIconTheme: const IconThemeData(color: MyColors.grey98Color, size: 28),
onTap: (int index) {
if (index == 1) {
Navigator.pushNamed(context, AppRoutes.mowadhafhi);
} else if (index == 2) {
Navigator.pushNamed(context, AppRoutes.workList);
} else if (index == 3) {
Navigator.pushNamed(context, AppRoutes.itemsForSale);
} else if (index == 4) {
if (!cProvider.disbaleChatForThisUser) {
Navigator.pushNamed(context, AppRoutes.chat);
}
}
},
),
label: LocaleKeys.chat.tr(),
),
],
currentIndex: currentIndex,
selectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey3AColor, fontWeight: FontWeight.w600),
unselectedLabelStyle: const TextStyle(fontSize: 10, color: MyColors.grey98Color, fontWeight: FontWeight.w600),
type: BottomNavigationBarType.fixed,
selectedItemColor: MyColors.grey3AColor,
backgroundColor: MyColors.backgroundColor,
selectedIconTheme: const IconThemeData(color: MyColors.grey3AColor, size: 28),
unselectedIconTheme: const IconThemeData(color: MyColors.grey98Color, size: 28),
onTap: (int index) {
if (index == 1) {
Navigator.pushNamed(context, AppRoutes.mowadhafhi);
} else if (index == 2) {
Navigator.pushNamed(context, AppRoutes.workList);
} else if (index == 3) {
Navigator.pushNamed(context, AppRoutes.itemsForSale);
} else if (index == 4) {
Navigator.pushNamed(context, AppRoutes.chat);
}
},
),
),
);
}

@ -5,6 +5,7 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/env.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
@ -29,12 +30,14 @@ class AppDrawer extends StatefulWidget {
class _AppDrawerState extends State<AppDrawer> {
List<DrawerMenuItem> drawerMenuItemList = [];
late ChatProviderModel chatData;
ChatProviderModel? chatData;
@override
void initState() {
super.initState();
chatData = Provider.of<ChatProviderModel>(context, listen: false);
if (env.chat) {
chatData = Provider.of<ChatProviderModel>(context, listen: false);
}
}
@override
@ -117,9 +120,10 @@ class _AppDrawerState extends State<AppDrawer> {
Navigator.pushNamed(context, drawerMenuItemList[index].routeName);
});
}),
menuItem("assets/images/drawer/employee_id.svg", LocaleKeys.employeeDigitalID.tr(), "", closeDrawer: false, onPress: () => showMDialog(context, child: EmployeeDigitialIdDialog())),
if (AppState().businessCardPrivilege)
menuItem("assets/images/drawer/view_business_card.svg", LocaleKeys.viewBusinessCard.tr(), "", closeDrawer: false, onPress: () => showMDialog(context, child: BusinessCardDialog())),
// menuItem("assets/images/drawer/employee_id.svg", LocaleKeys.employeeDigitalID.tr(), "", closeDrawer: false, onPress: () => showMDialog(context, child: EmployeeDigitialIdDialog())),
// if (AppState().businessCardPrivilege)
// menuItem("assets/images/drawer/view_business_card.svg", LocaleKeys.viewBusinessCard.tr(), "", closeDrawer: false, onPress: () => showMDialog(context, child: BusinessCardDialog())),
//
menuItem("assets/images/drawer/logout.svg", LocaleKeys.logout.tr(), "", color: MyColors.redA3Color, closeDrawer: false, onPress: performLogout),
// menuItem("assets/images/drawer/logout.svg", LocaleKeys.logout.tr(), "", color: MyColors.redA3Color, closeDrawer: false, onPress: () {Navigator.pushNamed(context, AppRoutes.survey,);
],
@ -175,7 +179,7 @@ class _AppDrawerState extends State<AppDrawer> {
AppState().isAuthenticated = false;
AppState().isLogged = false;
AppState().setPostParamsInitConfig();
chatData.disposeData();
chatData?.disposeData();
// SharedPreferences prefs = await SharedPreferences.getInstance();
// await prefs.clear();
Navigator.pushNamedAndRemoveUntil(context, AppRoutes.login, (Route<dynamic> route) => false, arguments: null);

@ -53,7 +53,7 @@ class MenusWidget extends StatelessWidget {
).onPress(() {
Navigator.pushNamed(context, AppRoutes.workList);
}),
if(env["dashboard"]["missingSwipe"])
if(env.dashboard.missingSwipe)
data.isMissingSwipeLoading
? MenuShimmer().onPress(() {
data.fetchWorkListCounter(context);
@ -108,7 +108,7 @@ class MenusWidget extends StatelessWidget {
).onPress(() {
Navigator.pushNamed(context, AppRoutes.leaveBalance);
}),
if(env["dashboard"]["ticketBalance"])
if(env.dashboard.ticketBalance)
data.isLeaveTicketBalanceLoading
? MenuShimmer().onPress(() {
data.fetchWorkListCounter(context);

@ -1,3 +1,5 @@
import 'dart:convert';
import 'package:easy_localization/src/public_ext.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
@ -69,7 +71,10 @@ class ServicesWidget extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SvgPicture.asset(AppState().isArabic(context) ? getMenuIconAr(data.homeMenus![parentIndex].menuEntiesList[index].prompt!) : getMenuIconEn(data.homeMenus![parentIndex].menuEntiesList[index].prompt!)),
Image.memory(
Base64Decoder().convert(data.homeMenus![parentIndex].menuEntiesList[index].icon ?? ""),
scale: 1.25,
),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [

@ -313,6 +313,7 @@ class _AddLeaveBalanceScreenState extends State<AddLeaveBalanceScreen> {
model.eSERVICESDV?.pIDCOLUMNNAME ?? "",
isReadOnly: model.rEADONLY == "Y",
isInputTypeNum: true,
length: model.mAXIMUMSIZE,
onChange: (text) {
model.eSERVICESDV ??= ESERVICESDV();
model.eSERVICESDV!.pIDCOLUMNNAME = text;
@ -501,6 +502,7 @@ class _AddLeaveBalanceScreenState extends State<AddLeaveBalanceScreen> {
(model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""),
model.eSERVICESDV?.pIDCOLUMNNAME ?? "",
isReadOnly: model.rEADONLY == "Y",
length: model.mAXIMUMSIZE,
onChange: (text) {
//model.fieldAnswer = text;
},

@ -8,6 +8,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:huawei_hmsavailability/huawei_hmsavailability.dart';
import 'package:mohem_flutter_app/api/login_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
@ -20,7 +21,6 @@ import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/check_mobile_app_version_model.dart';
import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart';
import 'package:mohem_flutter_app/models/member_information_list_model.dart';
@ -28,7 +28,6 @@ import 'package:mohem_flutter_app/models/member_login_list_model.dart';
import 'package:mohem_flutter_app/models/privilege_list_model.dart';
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
import 'package:mohem_flutter_app/widgets/input_widget.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:safe_device/safe_device.dart';
import 'package:wifi_iot/wifi_iot.dart';
@ -59,9 +58,12 @@ class _LoginScreenState extends State<LoginScreen> {
bool isOnExternalStorage = false;
bool isDevelopmentModeEnable = false;
late HmsApiAvailability hmsApiAvailability;
@override
void initState() {
super.initState();
hmsApiAvailability = HmsApiAvailability();
// checkFirebaseToken();
// if (kReleaseMode) {
// checkDeviceSafety();
@ -95,27 +97,27 @@ class _LoginScreenState extends State<LoginScreen> {
Future<void> checkFirebaseToken() async {
try {
Utils.showLoading(context);
await Firebase.initializeApp();
// await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
// alert: true,
// badge: true,
// sound: true,
// );
// await FirebaseMessaging.instance.requestPermission();
_firebaseMessaging = FirebaseMessaging.instance;
firebaseToken = await _firebaseMessaging.getToken();
AppNotifications().init(firebaseToken);
loginInfo = await LoginApiClient().getMobileLoginInfoNEW(firebaseToken ?? "", Platform.isAndroid ? "android" : "ios");
if (loginInfo == null) {
await checkPrefs();
_autoLogin = false;
Utils.hideLoading(context);
return;
if (Platform.isAndroid) {
try {
await hmsApiAvailability.isHMSAvailable().then((value) async {
if (value == 0) {
AppState().setIsHuawei = true;
AppNotifications().initHuaweiPush(checkLoginInfo);
} else {
await Firebase.initializeApp();
_firebaseMessaging = FirebaseMessaging.instance;
firebaseToken = await _firebaseMessaging.getToken();
AppNotifications().init(firebaseToken);
checkLoginInfo();
}
});
} catch (ex) {}
} else {
loginInfo!.deviceToken = firebaseToken;
await checkPrefs();
Utils.hideLoading(context);
performLogin();
await Firebase.initializeApp();
_firebaseMessaging = FirebaseMessaging.instance;
firebaseToken = await _firebaseMessaging.getToken();
AppNotifications().init(firebaseToken);
checkLoginInfo();
}
} catch (ex) {
Utils.hideLoading(context);
@ -123,9 +125,24 @@ class _LoginScreenState extends State<LoginScreen> {
}
}
void checkLoginInfo() async {
loginInfo = await LoginApiClient().getMobileLoginInfoNEW(AppState().getIsHuawei ? AppState().getHuaweiPushToken : firebaseToken ?? "", Platform.isAndroid ? "android" : "ios");
if (loginInfo == null) {
await checkPrefs();
_autoLogin = false;
Utils.hideLoading(context);
return;
} else {
loginInfo!.deviceToken = firebaseToken;
await checkPrefs();
Utils.hideLoading(context);
performLogin();
}
}
Future<void> checkPrefs() async {
String username = await Utils.getStringFromPrefs(SharedPrefsConsts.username);
if (username.isNotEmpty) {
if (!username.isNotEmpty) { // for test purpose i added !
String password = await Utils.getStringFromPrefs(SharedPrefsConsts.password);
// String firebaseToken = await Utils.getStringFromPrefs(SharedPrefsConsts.firebaseToken);
// print("firebaseToken:$firebaseToken");
@ -166,22 +183,29 @@ class _LoginScreenState extends State<LoginScreen> {
}
}
@override
Widget build(BuildContext context) {
if (isAppOpenBySystem == null) {
isAppOpenBySystem = (ModalRoute.of(context)!.settings.arguments ?? true) as bool;
if (!kReleaseMode) {
// username.text = "15444"; // Maha User
// username.text = "15153"; // Tamer User
// password.text = "Abcd@1234";
username.text = "SRCA4779T"; // Hashim User
password.text = "a12345";
username.text = "1100313582";
password.text = "moe123456";
username.text = "SRCA04101"; // Hashim User
password.text = "a123456";
// 1) Normal user :
// Username: 1100313582
// Employee # and Name: 210624 - شهد خالد ابراهيم الشامخ
// Password: moe123456
//
// 2) Normal user :
// Username: 1002528733
// Employee # and Name: 221142 - فؤاد محمدامين بكر موسى
// moe123456
//
//
// 3) HR User Account
// Username: 1087779144
// Employee # and Name: 190089 - عبدالله عبدالرحمن محمد الشهري
// Password: moe123456
}
if (isAppOpenBySystem!) checkFirebaseToken();
}
@ -232,7 +256,7 @@ class _LoginScreenState extends State<LoginScreen> {
12.height,
InputWidget(LocaleKeys.password.tr(), "xxxxxx", password, isTextIsPassword: true),
9.height,
if (env["login"]["forgetPassword"])
if (env.login.forgetPassword)
Align(
alignment: Alignment.centerRight,
child: LocaleKeys.forgotPassword.tr().toText12(isUnderLine: true, color: MyColors.textMixColor).onPress(() {

@ -11,6 +11,7 @@ import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/date_uitl.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/env.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/dialogs/otp_dialog.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
@ -141,7 +142,7 @@ class _VerifyLastLoginScreenState extends State<VerifyLastLoginScreen> {
children: [
if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(3),
if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(4),
getButton(2),
if (env.login.verificationMethod.whatsapp) getButton(2),
getButton(1),
],
)
@ -364,7 +365,7 @@ class _VerifyLastLoginScreenState extends State<VerifyLastLoginScreen> {
Future<void> performDirectApiCall(String _title, String _icon, int _flag, String value, TextEditingController? _pinPutController, {bool isDirectLogin = false}) async {
try {
GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(false, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName);
GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(true, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName);
GenericResponseModel? genericResponseModel1 = await LoginApiClient().insertMobileLoginInfoNEW(
AppState().memberLoginList?.pEMAILADDRESS ?? "",
genericResponseModel?.pSESSIONID ?? 0,
@ -372,7 +373,7 @@ class _VerifyLastLoginScreenState extends State<VerifyLastLoginScreen> {
_flag,
AppState().memberLoginList?.pMOBILENUMBER ?? "",
AppState().getUserName!,
mobileLoginInfoListModel!.deviceToken!,
AppState().getIsHuawei ? AppState().getHuaweiPushToken : mobileLoginInfoListModel!.deviceToken!,
Platform.isAndroid ? "android" : "ios");
AppState().setMemberInformationListModel = genericResponseModel!.memberInformationList?.first;
AppState().setPrivilegeListModel = genericResponseModel!.privilegeList ?? [];

@ -79,7 +79,7 @@ class _VerifyLoginScreenState extends State<VerifyLoginScreen> {
children: [
if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(3),
if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(4),
if (env["login"]["verificationMethod"]["whatsapp"]) getButton(2),
if (env.login.verificationMethod.whatsapp) getButton(2),
getButton(1),
],
)
@ -620,7 +620,7 @@ class _VerifyLoginScreenState extends State<VerifyLoginScreen> {
int.tryParse(AppState().memberLoginList?.pMOBILENUMBER ?? ""),
(value, TextEditingController _pinPutController) async {
Utils.showLoading(context);
try {
try {
GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(true, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName);
GenericResponseModel? genericResponseModel1 = await LoginApiClient().insertMobileLoginInfoNEW(
AppState().memberLoginList?.pEMAILADDRESS ?? "",
@ -629,7 +629,7 @@ class _VerifyLoginScreenState extends State<VerifyLoginScreen> {
_flag,
AppState().memberLoginList?.pMOBILENUMBER ?? "",
AppState().getUserName!,
firebaseToken!,
AppState().getIsHuawei ? AppState().getHuaweiPushToken : firebaseToken!,
Platform.isAndroid ? "android" : "ios");
if (genericResponseModel?.errorMessage != null) {
Utils.showToast(genericResponseModel?.errorMessage ?? "");
@ -638,13 +638,13 @@ class _VerifyLoginScreenState extends State<VerifyLoginScreen> {
AppState().setMemberInformationListModel = genericResponseModel.memberInformationList?.first;
MemberInformationListModel.saveToPrefs(genericResponseModel.memberInformationList ?? []);
PrivilegeListModel.saveToPrefs(genericResponseModel.privilegeList ?? []);
AppState().setMohemmWifiSSID = genericResponseModel.mohemmWifiSSID;
AppState().setMohemmWifiPassword = genericResponseModel.mohemmWifiPassword;
AppState().setMohemmWifiPassword = genericResponseModel.mohemmWifiPassword;
// AppState().setMohemmWifiSSID = genericResponseModel.mohemmWifiSSID;
// AppState().setMohemmWifiPassword = genericResponseModel.mohemmWifiPassword;
// AppState().setMohemmWifiPassword = genericResponseModel.mohemmWifiPassword;
Utils.saveStringFromPrefs(SharedPrefsConsts.username, AppState().getUserName!);
Utils.saveStringFromPrefs(SharedPrefsConsts.password, AppState().password!);
Utils.saveStringFromPrefs(SharedPrefsConsts.mohemmWifiSSID, genericResponseModel.mohemmWifiSSID!);
Utils.saveStringFromPrefs(SharedPrefsConsts.mohemmWifiPassword, genericResponseModel.mohemmWifiPassword!);
// Utils.saveStringFromPrefs(SharedPrefsConsts.mohemmWifiSSID, genericResponseModel.mohemmWifiSSID ?? "");
// Utils.saveStringFromPrefs(SharedPrefsConsts.mohemmWifiPassword, genericResponseModel.mohemmWifiPassword!);
}
Utils.hideLoading(context);
Navigator.pop(context);

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:developer';
import 'package:appinio_swiper/appinio_swiper.dart';
import 'package:flutter/cupertino.dart';
@ -134,6 +135,7 @@ class MarathonProvider extends ChangeNotifier {
late VideoPlayerController videoController;
Future<void> initializeVideoPlayer() async {
log("VIDEO PLAYER INITIALIZED!!!");
videoController = VideoPlayerController.network(ApiConsts.marathonBaseUrlServices + marathonDetailModel.sponsors!.first.video!);
await videoController.initialize();
await videoController.play();

@ -169,7 +169,6 @@ class MarathonScreen extends StatelessWidget {
],
)
: const SizedBox(),
34.height,
if (provider.selectedWinners != null) ...<Widget>[
provider.selectedWinners!.length == 1
? Column(
@ -179,7 +178,7 @@ class MarathonScreen extends StatelessWidget {
isCentered: true,
),
8.height,
AppState().memberInformationList!.eMPLOYEENUMBER!.toText22(color: MyColors.grey57Color),
provider.selectedWinners![0].employeeId!.toText22(color: MyColors.grey57Color),
],
)
: ListView.separated(
@ -310,7 +309,7 @@ class MarathonScreen extends StatelessWidget {
else ...<Widget>[
MarathonProgressContainer(provider: provider).paddingOnly(left: 21, right: 21),
],
if (provider.questionCardStatus == QuestionCardStatus.findingWinner) ...<Widget>[
if (provider.questionCardStatus == QuestionCardStatus.findingWinner && !provider.isUserOutOfGame) ...<Widget>[
getNameContainer(context),
],
QuestionCardBuilder(
@ -337,7 +336,7 @@ class MarathonScreen extends StatelessWidget {
subTitle: LocaleKeys.youMissedTheQuestion.tr().toText18(color: MyColors.darkTextColor, isCentered: true),
),
onFindingWinner: (BuildContext context) => CustomStatusWidget(
asset: Lottie.asset(MyLottieConsts.winnerLottie, height: 168, reverse: false),
asset: Lottie.asset(MyLottieConsts.winnerLottie, height: 168, reverse: false, repeat: true),
title: LocaleKeys.fingersCrossed.tr().toText22(color: MyColors.greenColor),
subTitle: LocaleKeys.winnerSelectedRandomly.tr().toText18(color: MyColors.darkTextColor, isCentered: true),
),

@ -123,10 +123,13 @@ class CountdownTimerForDetailScreen extends StatelessWidget {
Widget buildCountdownTimer(CurrentRemainingTime? time) {
if (provider.marathonDetailModel.startTime != null) {
int remainingTimeInMinutes = DateTime.parse(provider.marathonDetailModel.startTime!).difference(DateTime.now()).inMinutes;
if (remainingTimeInMinutes <= 30) {
scheduleMicrotask(() {
if (remainingTimeInMinutes <= 30 && provider.canPlayDemo == true) {
// scheduleMicrotask(() {
// print("Timer TRUE!!!: ${time?.min.toString()}");
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
provider.canPlayDemo = false;
});
// });
}
}

@ -347,7 +347,10 @@ class MarathonBanner extends StatelessWidget {
@override
Widget build(BuildContext context) {
MarathonProvider provider = context.read<MarathonProvider>();
// if(provider.isUserWaiting) {
// provider.isUserWaiting = false;
// provider.getMarathonDetailsFromApi();
// }
return !provider.isPrivilegedWithMarathon
? getUnPrivilegedMarathon(context)
: provider.isUpComingMarathon
@ -524,6 +527,8 @@ class MarathonBanner extends StatelessWidget {
int remainingTimeInMinutes = DateTime.parse(provider.marathonDetailModel.startTime!).difference(DateTime.now()).inMinutes;
if (remainingTimeInMinutes > 5 && provider.marathonDetailModel.sponsors != null && provider.marathonDetailModel.sponsors!.isNotEmpty) {
log("IF CALLED!!!");
log("Remaining Time: $remainingTimeInMinutes");
Utils.showLoading(context);
try {
await provider.initializeVideoPlayer().then((_) {
@ -532,14 +537,19 @@ class MarathonBanner extends StatelessWidget {
Navigator.pushNamed(context, AppRoutes.marathonSponsorVideoScreen);
});
} catch (e) {
if (kDebugMode) {
// if (kDebugMode) {
log("Error in VideoPlayer: ${e.toString()}");
}
// }
Utils.hideLoading(context);
Navigator.pushNamed(context, AppRoutes.marathonIntroScreen);
Navigator.pushNamed(context, AppRoutes.marathonIntroScreen).then((value) {
print("Back to home!!!");
});
}
} else {
Navigator.pushNamed(context, AppRoutes.marathonIntroScreen);
log("ELSE CALLED!!!");
Navigator.pushNamed(context, AppRoutes.marathonIntroScreen).then((value) {
print("Back to home!!!");
});
}
}),
)

@ -66,7 +66,11 @@ class MarathonProgressContainer extends StatelessWidget {
stepper(
provider.currentQuestionNumber,
provider.answerStatusesList,
AppState().getIsDemoMarathon ? provider.demoMarathonDetailModel.totalQuestions! : provider.marathonDetailModel.totalQuestions!,
(provider.demoMarathonDetailModel.totalQuestions != null || provider.marathonDetailModel.totalQuestions != null)
? AppState().getIsDemoMarathon
? provider.demoMarathonDetailModel.totalQuestions!
: provider.marathonDetailModel.totalQuestions!
: 10,
provider.isUserOutOfGame,
),
8.height,

@ -67,8 +67,8 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? "";
if (tempVar.isNotEmpty) {
if (!tempVar.contains("/")) {
DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar);
tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date);
DateTime date = DateFormat('yyyy-MM-dd', "en_US").parse(tempVar);
tempVar = DateFormat('yyyy/MM/dd HH:mm:ss', "en_US").format(date);
}
}
}
@ -492,6 +492,8 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
model.eSERVICESDV?.pIDCOLUMNNAME ?? "",
isReadOnly: model.rEADONLY == "Y",
isInputTypeNum: true,
length: model.mAXIMUMSIZE,
toolTip: model.rEQCOLTIP,
onChange: (text) {
model.fieldAnswer = text;
model.eSERVICESDV ??= ESERVICESDV();
@ -506,7 +508,7 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
displayText = displayText.replaceAll(" 00:00:00", "");
}
if (displayText.contains("/")) {
displayText = DateFormat('yyyy-MM-dd').format(DateFormat("yyyy/MM/dd").parse(displayText));
displayText = DateFormat('yyyy-MM-dd', "en_US").format(DateFormat("yyyy/MM/dd", "en_US").parse(displayText));
}
}
return DynamicTextFieldWidget(
@ -514,10 +516,11 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
displayText,
suffixIconData: Icons.calendar_today,
isEnable: false,
toolTip: model.rEQCOLTIP,
onTap: () async {
if ((getEitDffStructureList![index].eSERVICESDV?.pVALUECOLUMNNAME != null)) {
if (getEitDffStructureList![index].isDefaultTypeIsCDPS) {
selectedDate = DateFormat("yyyy/MM/dd").parse(getEitDffStructureList![index].eSERVICESDV!.pVALUECOLUMNNAME!.replaceAll('/"', '').replaceAll(" 00:00:00", ""));
selectedDate = DateFormat("yyyy/MM/dd", "en_US").parse(getEitDffStructureList![index].eSERVICESDV!.pVALUECOLUMNNAME!.replaceAll('/"', '').replaceAll(" 00:00:00", ""));
} else {
selectedDate = DateTime.parse(getEitDffStructureList![index].eSERVICESDV!.pVALUECOLUMNNAME!);
}
@ -576,9 +579,9 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
tempDate = tempDate.replaceAll("00:00:00", '').trim();
}
if (tempDate.contains("/")) {
selectedDate = DateFormat("yyyy/MM/dd").parse(tempDate);
selectedDate = DateFormat("yyyy/MM/dd", "en_US").parse(tempDate);
} else {
selectedDate = DateFormat("yyyy-MM-dd").parse(tempDate);
selectedDate = DateFormat("yyyy-MM-dd", "en_US").parse(tempDate);
}
} else {
selectedDate = DateTime.parse(getEitDffStructureList![index].eSERVICESDV!.pVALUECOLUMNNAME!);
@ -689,6 +692,7 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
(model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""),
model.eSERVICESDV?.pIDCOLUMNNAME ?? "",
isReadOnly: model.rEADONLY == "Y",
length: model.mAXIMUMSIZE,
onChange: (text) {
model.fieldAnswer = text;
},
@ -700,7 +704,7 @@ class _DynamicInputScreenState extends State<DynamicInputScreen> {
displayText = displayText.replaceAll(" 00:00:00", "");
}
if (!displayText.contains("-")) {
displayText = DateFormat('yyyy-MM-dd').format(DateFormat("yyyy/MM/dd").parse(displayText));
displayText = DateFormat('yyyy-MM-dd', "en_US").format(DateFormat("yyyy/MM/dd", "en_US").parse(displayText));
}
}
return DynamicTextFieldWidget(

@ -159,7 +159,7 @@ class _ViewAttendanceState extends State<ViewAttendance> {
children: [
Row(
children: [
"${DateFormat("MMMM-yyyy").format(formattedDate)}".toText16(color: MyColors.grey3AColor),
"${DateFormat("MMMM-yyyy", "en_US").format(formattedDate)}".toText16(color: MyColors.grey3AColor),
const Icon(Icons.keyboard_arrow_down_rounded, color: MyColors.grey3AColor),
],
).onPress(
@ -439,7 +439,7 @@ class _ViewAttendanceState extends State<ViewAttendance> {
expand: false,
builder: (_, controller) {
dynamic dmyString = getScheduleShiftsDetailsList!.sCHEDULEDATE;
DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss").parse(dmyString);
DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss", "en_US").parse(dmyString);
return Column(
children: [
Container(
@ -468,7 +468,7 @@ class _ViewAttendanceState extends State<ViewAttendance> {
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${DateFormat("MMMM-dd-yyyy").format(dateTime1).replaceAll('-', " ")}".toText24(isBold: true, color: Colors.white),
"${DateFormat("MMMM-dd-yyyy", "en_US").format(dateTime1).replaceAll('-', " ")}".toText24(isBold: true, color: Colors.white),
LocaleKeys.attendanceDetails.tr().toText16(color: MyColors.greyACColor),
12.height,
CircularStepProgressBar(

@ -105,7 +105,7 @@ class _MonthlyPaySlipScreenState extends State<MonthlyPaySlipScreen> {
Container(alignment: Alignment.centerLeft, child: LocaleKeys.month.tr().toText17(isBold: true, color: MyColors.darkIconColor)),
Row(
children: [
DateFormat("MMMM-yyyy").format(DateFormat("MM/dd/yyyy").parse(paySlipList[selectedMonthIndex!].pAYMENTDATE!)).toText16(color: MyColors.greyACColor),
DateFormat("MMMM-yyyy", "en_US").format(DateFormat("MM/dd/yyyy", "en_US").parse(paySlipList[selectedMonthIndex!].pAYMENTDATE!)).toText16(color: MyColors.greyACColor),
const Icon(Icons.keyboard_arrow_down_rounded, color: MyColors.greyACColor),
],
).onPress(() async {

@ -238,7 +238,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
isEnable: false,
onTap: () async {
DateTime dateValue = await _selectDate(context);
date = (DateFormat('yyyy-MM-dd').format(dateValue));
date = (DateFormat('yyyy-MM-dd', "en_US").format(dateValue));
model!.getContactDetailsList!.sEGMENTVALUEDSP = date;
setState(() {});
},
@ -286,6 +286,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
(model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""),
model.getContactDetailsList!.sEGMENTVALUEDSP ?? "",
isInputTypeNum: true,
length: model.mAXIMUMSIZE,
onChange: (String text) {
model.getContactDetailsList!.sEGMENTVALUEDSP = text;
},
@ -298,7 +299,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
isEnable: false,
onTap: () async {
DateTime dateValue = await _selectDate(context);
date = (DateFormat('yyyy-MM-dd').format(dateValue));
date = (DateFormat('yyyy-MM-dd', "en_US").format(dateValue));
model!.getContactDetailsList!.sEGMENTVALUEDSP = date;
setState(() {});
},
@ -345,6 +346,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
(model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""),
model.getContactDetailsList!.sEGMENTVALUEDSP ?? "",
isInputTypeNum: true,
length: model.mAXIMUMSIZE,
onChange: (String text) {
model.getContactDetailsList!.sEGMENTVALUEDSP = text;
},
@ -357,7 +359,7 @@ class _AddUpdateFamilyMemberState extends State<AddUpdateFamilyMember> {
isEnable: false,
onTap: () async {
DateTime dateValue = await _selectDate(context);
date = (DateFormat('yyyy-MM-dd').format(dateValue));
date = (DateFormat('yyyy-MM-dd', "en_US").format(dateValue));
model!.getContactDetailsList!.sEGMENTVALUEDSP = date;
setState(() {});
},

@ -5,6 +5,7 @@ import 'package:mohem_flutter_app/api/profile_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/env.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
@ -100,6 +101,7 @@ class _ContactDetailsState extends State<ContactDetails> {
),
separatorBuilder: (cxt, index) => 12.height,
itemCount: getEmployeePhonesList.length),
if(env.canEdit)
if (menuEntriesPhone.updateButton == 'Y')
AppState().isArabic(context)
? Positioned(
@ -131,6 +133,7 @@ class _ContactDetailsState extends State<ContactDetails> {
),
separatorBuilder: (cxt, index) => 12.height,
itemCount: getEmployeeAddressList.length),
if(env.canEdit)
if (menuEntriesAddress.updateButton == 'Y')
AppState().isArabic(context)
? Positioned(
@ -148,6 +151,7 @@ class _ContactDetailsState extends State<ContactDetails> {
else
Stack(
children: [
if(env.canEdit)
if (menuEntriesAddress.addButton == 'Y')
AppState().isArabic(context)
? Positioned(

@ -88,8 +88,8 @@ class _DeleteFamilyMemberState extends State<DeleteFamilyMember> {
isEnable: false,
onTap: () async {
DateTime dateValue = await _selectDate(context);
date = DateFormat('yyyy/MM/dd').format(dateValue);
datePar = DateFormat('yyyy/MM/dd hh:mm:ss').format(dateValue);
date = DateFormat('yyyy/MM/dd', "en_US").format(dateValue);
datePar = DateFormat('yyyy/MM/dd hh:mm:ss', "en_US").format(dateValue);
setState(() {});
},
).paddingOnly(bottom: 12),

@ -227,6 +227,7 @@ class _DynamicInputScreenState extends State<DynamicInputScreenAddress> {
(model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""),
model.getEmployeeAddressList?.sEGMENTVALUEDSP ?? "",
isReadOnly: model.rEADONLY == "Y",
length: model.mAXIMUMSIZE,
onChange: (text) {
model.getEmployeeAddressList?.sEGMENTVALUEDSP = text;
},
@ -242,10 +243,10 @@ class _DynamicInputScreenState extends State<DynamicInputScreenAddress> {
DateTime date1 = DateTime(date.year, date.month, date.day);
getAddressDffStructureList![index].dESCFLEXCONTEXTNAME = date.toString();
ESERVICESDV eservicesdv = ESERVICESDV(
pIDCOLUMNNAME: DateFormat('yyyy-MM-dd').format(date1),
pIDCOLUMNNAME: DateFormat('yyyy-MM-dd', "en_US").format(date1),
pRETURNMSG: "null",
pRETURNSTATUS: getAddressDffStructureList![index].dEFAULTVALUE,
pVALUECOLUMNNAME: DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date));
pVALUECOLUMNNAME: DateFormat('yyyy-MM-ddThh:mm:ss.s', "en_US").format(date));
getAddressDffStructureList![index].eSERVICESDV = eservicesdv;
setState(() {});
if (model.cHILDSEGMENTSVSSplited?.isNotEmpty ?? false) {
@ -270,8 +271,8 @@ class _DynamicInputScreenState extends State<DynamicInputScreenAddress> {
// for date format type, date format is changed
tempVar = e.eSERVICESDV?.pVALUECOLUMNNAME ?? "";
if (tempVar.isNotEmpty) {
DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar);
tempVar = DateFormat('dd-MMM-yyy').format(date);
DateTime date = DateFormat('yyyy-MM-dd', "en_US").parse(tempVar);
tempVar = DateFormat('dd-MMM-yyy', "en_US").format(date);
if (e.aPPLICATIONCOLUMNNAME == null) {
effectiveDate = tempVar;
}
@ -294,7 +295,7 @@ class _DynamicInputScreenState extends State<DynamicInputScreenAddress> {
values,
dynamicParams!.correctOrNew,
countryCode,
effectiveDate.isEmpty ? DateFormat('dd-MMM-yyy').format(DateTime.now()) : effectiveDate,
effectiveDate.isEmpty ? DateFormat('dd-MMM-yyy', "en_US").format(DateTime.now()) : effectiveDate,
);
Utils.hideLoading(context);

@ -233,10 +233,10 @@ class _DynamicInputScreenState extends State<DynamicInputScreenProfile> {
DateTime date1 = DateTime(date.year, date.month, date.day);
getBasicDetDffStructureList![index].userBasicDetail!.sEGMENTVALUEDSP = date.toString();
ESERVICESDV eservicesdv = ESERVICESDV(
pIDCOLUMNNAME: DateFormat('yyyy-MM-dd').format(date1),
pIDCOLUMNNAME: DateFormat('yyyy-MM-dd', "en_US").format(date1),
pRETURNMSG: "null",
pRETURNSTATUS: getBasicDetDffStructureList![index].dEFAULTVALUE,
pVALUECOLUMNNAME: DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date));
pVALUECOLUMNNAME: DateFormat('yyyy-MM-ddThh:mm:ss.s', "en_US").format(date));
getBasicDetDffStructureList![index].eSERVICESDV = eservicesdv;
setState(() {});
if (model.cHILDSEGMENTSVSSplited?.isNotEmpty ?? false) {
@ -371,8 +371,8 @@ class _DynamicInputScreenState extends State<DynamicInputScreenProfile> {
// for date format type, date format is changed
tempVar = e.eSERVICESDV?.pVALUECOLUMNNAME ?? "";
if (tempVar.isNotEmpty) {
DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar);
tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date);
DateTime date = DateFormat('yyyy-MM-dd', "en_US").parse(tempVar);
tempVar = DateFormat('yyyy/MM/dd HH:mm:ss', "en_US").format(date);
}
}
return ValidateEitTransactionModel(dATEVALUE: null, nAME: e.aPPLICATIONCOLUMNNAME, nUMBERVALUE: null, tRANSACTIONNUMBER: 1, vARCHAR2VALUE: tempVar.toString()).toJson();

@ -29,7 +29,7 @@ class ProfileInFo extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
16.height,
memberInfo.eMPLOYEENAME!.toText22(),
memberInfo.eMPLOYEENAME!.toText22(isCentered: true),
("${memberInfo.eMPLOYEENUMBER!} | ${memberInfo.getPositionName()}").toText13(color: MyColors.grey80Color),
memberInfo.eMPLOYEEEMAILADDRESS!.toText13(),
12.height,

@ -176,6 +176,7 @@ class _NewRequestState extends State<NewRequest> {
model.eSERVICESDV?.pIDCOLUMNNAME ?? "",
isReadOnly: model.rEADONLY == "Y",
isInputTypeNum: true,
length: model.mAXIMUMSIZE,
onChange: (text) {
model.fieldAnswer = text;
model.eSERVICESDV ??= ESERVICESDV();
@ -189,7 +190,7 @@ class _NewRequestState extends State<NewRequest> {
displayText = displayText.replaceAll(" 00:00:00", "");
}
if (!displayText.contains("-")) {
displayText = DateFormat('yyyy-MM-dd').format(DateFormat("yyyy/MM/dd").parse(displayText));
displayText = DateFormat('yyyy-MM-dd', "en_US").format(DateFormat("yyyy/MM/dd", "en_US").parse(displayText));
}
}
return DynamicTextFieldWidget(
@ -200,7 +201,7 @@ class _NewRequestState extends State<NewRequest> {
onTap: () async {
if ((getCCPDFFStructureModelList![index].eSERVICESDV?.pVALUECOLUMNNAME != null)) {
if (getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS) {
selectedDate = DateFormat("yyyy/MM/dd").parse(getCCPDFFStructureModelList![index].eSERVICESDV!.pVALUECOLUMNNAME!.replaceAll('/"', '').replaceAll(" 00:00:00", ""));
selectedDate = DateFormat("yyyy/MM/dd", "en_US").parse(getCCPDFFStructureModelList![index].eSERVICESDV!.pVALUECOLUMNNAME!.replaceAll('/"', '').replaceAll(" 00:00:00", ""));
} else {
selectedDate = DateTime.parse(getCCPDFFStructureModelList![index].eSERVICESDV!.pVALUECOLUMNNAME!);
}
@ -211,16 +212,16 @@ class _NewRequestState extends State<NewRequest> {
ESERVICESDV eservicesdv;
if (getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS) {
eservicesdv = ESERVICESDV(
pIDCOLUMNNAME: DateFormat('yyyy/MM/dd HH:MM:SS').format(date1),
pIDCOLUMNNAME: DateFormat('yyyy/MM/dd HH:MM:SS', "en_US").format(date1),
pRETURNMSG: "null",
pRETURNSTATUS: getCCPDFFStructureModelList![index].dEFAULTVALUE,
pVALUECOLUMNNAME: getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS ? DateFormat('yyyy/MM/dd HH:MM:SS').format(date) : DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date));
pVALUECOLUMNNAME: getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS ? DateFormat('yyyy/MM/dd HH:MM:SS', "en_US").format(date) : DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date));
} else {
eservicesdv = ESERVICESDV(
pIDCOLUMNNAME: DateFormat('yyyy-MM-dd').format(date1),
pIDCOLUMNNAME: DateFormat('yyyy-MM-dd', "en_US").format(date1),
pRETURNMSG: "null",
pRETURNSTATUS: getCCPDFFStructureModelList![index].dEFAULTVALUE,
pVALUECOLUMNNAME: getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS ? DateFormat('yyyy-MM-dd hh:mm:ss').format(date) : DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date));
pVALUECOLUMNNAME: getCCPDFFStructureModelList![index].isDefaultTypeIsCDPS ? DateFormat('yyyy-MM-dd hh:mm:ss', "en_US").format(date) : DateFormat('yyyy-MM-ddThh:mm:ss.s').format(date));
}
getCCPDFFStructureModelList![index].eSERVICESDV = eservicesdv;
setState(() {});
@ -323,6 +324,7 @@ class _NewRequestState extends State<NewRequest> {
isPopup: true,
isInputTypeNum: true,
isReadOnly: model.rEADONLY == "Y",
length: model.mAXIMUMSIZE,
).paddingOnly(bottom: 12),
itemBuilder: (_) => <PopupMenuItem<int>>[
for (int i = 0; i < model.eSERVICESVS!.length; i++) PopupMenuItem<int>(child: Text(model.eSERVICESVS![i].vALUECOLUMNNAME!), value: i),

@ -85,7 +85,7 @@ class _OffersAndDiscountsDetailsState extends State<OffersAndDiscountsDetails> {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
getOffersList[0].discount!.toText16(isBold: true),
getOffersList[0].discountDescription!.toText16(isBold: true),
InkWell(
onTap: () {
_shareOfferAsImage();

@ -107,8 +107,8 @@ class _EndEmploymentScreenState extends State<EndEmploymentScreen> {
tempVar = e.eSERVICESDV?.pIDCOLUMNNAME ?? "";
if (tempVar.isNotEmpty) {
if (!tempVar.contains("/")) {
DateTime date = DateFormat('yyyy-MM-dd').parse(tempVar);
tempVar = DateFormat('yyyy/MM/dd HH:mm:ss').format(date);
DateTime date = DateFormat('yyyy-MM-dd', "en_US").parse(tempVar);
tempVar = DateFormat('yyyy/MM/dd HH:mm:ss', "en_US").format(date);
}
}
}
@ -303,6 +303,7 @@ class _EndEmploymentScreenState extends State<EndEmploymentScreen> {
model.eSERVICESDV?.pIDCOLUMNNAME ?? "",
isReadOnly: model.rEADONLY == "Y",
isInputTypeNum: true,
length: model.mAXIMUMSIZE,
onChange: (text) {
model.eSERVICESDV ??= ESERVICESDV();
model.eSERVICESDV!.pIDCOLUMNNAME = text;
@ -475,6 +476,7 @@ class _EndEmploymentScreenState extends State<EndEmploymentScreen> {
(model.sEGMENTPROMPT ?? "") + (model.rEQUIREDFLAG == "Y" ? "*" : ""),
model.eSERVICESDV?.pIDCOLUMNNAME ?? "",
isReadOnly: model.rEADONLY == "Y",
length: model.mAXIMUMSIZE,
onChange: (text) {
//model.fieldAnswer = text;
},

@ -13,7 +13,7 @@ class AppLogo extends StatelessWidget {
return Row(
children: [
SvgPicture.asset(
"assets/mohemm_logo.svg",
"assets/moe_logo.svg",
height: 48,
width: 48,
alignment: Alignment.centerRight,

@ -63,7 +63,7 @@ class _BalancesDashboardWidgetState extends State<BalancesDashboardWidget> {
void changeAccrualDate(bool showLoading) async {
try {
if (showLoading) Utils.showLoading(context);
List<GetAccrualBalancesList> accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime), empID: widget.selectedEmp);
List<GetAccrualBalancesList> accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy", "en_US").format(accrualDateTime), empID: widget.selectedEmp);
if (accrualList.isNotEmpty) {
if (widget.isLeaveBalance) {
leaveBalanceAccrual = accrualList[0];

@ -1,5 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
class DynamicTextFieldWidget extends StatelessWidget {
final String labelText;
@ -17,11 +20,14 @@ class DynamicTextFieldWidget extends StatelessWidget {
final bool isInputTypeNumSigned;
final bool isObscureText;
final bool isBackgroundEnable;
final int? length;
final String? toolTip;
final void Function(String)? onChange;
DynamicTextFieldWidget(this.labelText, this.hintText, //this.controller,
{this.isObscureText = false,
this.onTap,
this.onToolTipTap,
this.suffixIconData,
this.isEnable = true,
this.isReadOnly = false,
@ -31,6 +37,8 @@ class DynamicTextFieldWidget extends StatelessWidget {
this.onChange,
this.isInputTypeNum = false,
this.isInputTypeNumSigned = true,
this.length,
this.toolTip = "",
this.isBackgroundEnable = false});
@override
@ -68,13 +76,18 @@ class DynamicTextFieldWidget extends StatelessWidget {
enabled: isEnable,
scrollPadding: EdgeInsets.zero,
readOnly: isReadOnly,
keyboardType: (isInputTypeNum) ? (isInputTypeNumSigned ? const TextInputType.numberWithOptions(signed: true, decimal: true) : TextInputType.numberWithOptions(signed: true, decimal: true)) : TextInputType.text,
keyboardType: (isInputTypeNum)
? (isInputTypeNumSigned ? const TextInputType.numberWithOptions(signed: true, decimal: true) : TextInputType.numberWithOptions(signed: true, decimal: true))
: TextInputType.text,
textInputAction: TextInputAction.done,
//controller: controller,
maxLines: lines,
obscuringCharacter: "*",
obscureText: isObscureText,
onChanged: onChange,
inputFormatters: [
LengthLimitingTextInputFormatter(length),
],
style: const TextStyle(
fontSize: 14,
height: 21 / 14,
@ -107,6 +120,10 @@ class DynamicTextFieldWidget extends StatelessWidget {
),
if (isPopup) const Icon(Icons.keyboard_arrow_down_outlined, color: MyColors.darkIconColor),
if (onTap != null) Icon(suffixIconData ?? Icons.keyboard_arrow_down_outlined, color: MyColors.darkIconColor),
if (toolTip!.isNotEmpty)
Icon(Icons.help_outline_rounded, color: MyColors.darkIconColor).onPress(() {
Utils.showToast(toolTip!);
}).paddingOnly(left: 6),
],
),
),

@ -36,7 +36,7 @@ class _LoadingDialogState extends State<LoadingDialog> {
textDirection: TextDirection.rtl,
child: Center(
child: Image.asset(
"assets/images/logos/loading_mohemm_logo.gif",
"assets/images/logos/loading_moe.gif",
height: 96.0,
width: 96.0,
),

@ -1,22 +1,11 @@
import 'dart:async';
import 'dart:math';
import 'dart:ui';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_directions_api/google_directions_api.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:mohem_flutter_app/classes/app_permissions.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/theme/colors.dart';
// import 'package:geodesy/geodesy.dart' as geodesy;
//Created By Mr.Zohaib
class Location {
static _Map map = _Map();
static void havePermission(Function(bool) callback) {
Geolocator.checkPermission().then((value) async {
if (value == LocationPermission.denied) {
@ -46,12 +35,11 @@ class Location {
});
}
static void getCurrentLocation(Function(LatLng?, bool isMocked) callback, BuildContext context) {
static void getCurrentLocation(Function(Position position, bool isMocked) callback, BuildContext context) {
void done(Position position) {
//AppStorage.sp.saveLocation(position);
bool isMocked = position.isMocked;
LatLng? myCurrentLocation = LatLng(position.latitude, position.longitude);
callback(myCurrentLocation, isMocked);
callback(position, isMocked);
}
AppPermissions.location((granted) {
@ -70,182 +58,4 @@ class Location {
}
}, context);
}
// static LatLng locationAwayFrom(
// {required LatLng loc1, num distanceMeters = 200.0, num bearing = 270.0}) {
// geodesy.LatLng l1 = geodesy.LatLng(loc1.latitude, loc1.longitude);
// geodesy.LatLng destinationPoint = geodesy.Geodesy()
// .destinationPointByDistanceAndBearing(l1, distanceMeters, bearing);
// return LatLng(destinationPoint.latitude, destinationPoint.longitude);
// }
static Future<double> distanceTo(LatLng destination) async {
var myLoc = await Geolocator.getLastKnownPosition();
var distance = 0.0;
if (myLoc != null) {
distance = Geolocator.distanceBetween(destination.latitude, destination.longitude, myLoc.latitude, myLoc.longitude);
}
return distance;
}
}
class _Map {
Marker createMarker(
String id, {
required LatLng coordinates,
BitmapDescriptor? icon,
VoidCallback? onTap,
}) {
MarkerId markerId = MarkerId(id);
return Marker(
icon: icon ?? BitmapDescriptor.defaultMarker,
markerId: markerId,
position: coordinates,
flat: false,
// infoWindow: InfoWindow(title: id, snippet: '*'),
onTap: onTap,
);
}
CameraPosition initialCamera({required Completer<GoogleMapController> mapController, LatLng? position, double zoom = 12}) {
position = position ?? LatLng(24.7249303, 46.5416656);
CameraPosition riyadhEye = CameraPosition(
target: position,
zoom: zoom,
);
mapController.future.then((controller) {
controller.animateCamera(CameraUpdate.newCameraPosition(riyadhEye));
});
return riyadhEye;
}
CameraPosition moveTo(LatLng location, {double zoom = 12, double direction = 0.0, required Completer<GoogleMapController> mapController, bool? animation}) {
var camera = CameraPosition(target: location, zoom: zoom, bearing: direction);
mapController.future.then((controller) {
animation ?? false ? controller.animateCamera(CameraUpdate.newCameraPosition(camera)) : controller.moveCamera(CameraUpdate.newCameraPosition(camera));
});
return camera;
}
void moveCamera(CameraPosition camera, @required Completer<GoogleMapController> mapController, bool animation) {
mapController.future.then((controller) {
animation ? controller.animateCamera(CameraUpdate.newCameraPosition(camera)) : controller.moveCamera(CameraUpdate.newCameraPosition(camera));
});
}
void scrollBy({double x = 0, double y = 0, required Completer<GoogleMapController> mapController, bool animation = true}) {
var camera = CameraUpdate.scrollBy(x, y);
mapController.future.then((controller) {
animation ? controller.animateCamera(camera) : controller.moveCamera(camera);
});
}
// void goToCurrentLocation({Completer<GoogleMapController>? mapController, double? direction = 0.0, bool? animation}) {
// Location.getCurrentLocation((location) {
// moveTo(location!, zoom: 17, mapController: mapController!, animation: animation, direction: direction!);
// });
// }
var routes = Map<String, DirectionsRoute>();
void setRoutePolylines(LatLng? source, LatLng? destination, Set<Polyline> polylines, Completer<GoogleMapController> mapController, Function(DirectionsRoute?) completion) {
if (source == null || destination == null) {
completion(null);
return;
}
var origin = '${source.latitude},${source.longitude}';
var destin = '${destination.latitude},${destination.longitude}';
var routeId = '$origin->$destination';
void createPolyline(DirectionsRoute results) {
List<LatLng> polylineCoordinates = results.overviewPath!.map((e) => LatLng(e.latitude, e.longitude)).toList();
PolylineId id = PolylineId("route");
Polyline polyline = Polyline(
polylineId: id,
color: accentColor,
width: 5,
jointType: JointType.round,
startCap: Cap.roundCap,
endCap: Cap.roundCap,
points: polylineCoordinates,
);
polylines.removeWhere((element) => true);
polylines.add(polyline);
LatLngBounds bound = getBounds(coordinates: polylineCoordinates);
focusCameraToLatLngBounds(bound: bound, mapController: mapController, padding: 100);
completion(routes[routeId]);
}
var availableRoute = routes[routeId];
if (availableRoute == null) {
var request = DirectionsRequest(origin: origin, destination: destin);
DirectionsService().route(request, (response, status) {
if (status == DirectionsStatus.ok && response.routes!.isNotEmpty) {
routes[routeId] = response.routes!.first;
createPolyline(response.routes!.first);
}
});
} else {
createPolyline(availableRoute);
}
}
LatLngBounds getBounds({required List<LatLng> coordinates}) {
var lngs = coordinates.map<double>((c) => c.longitude).toList();
var lats = coordinates.map<double>((c) => c.latitude).toList();
double bottomMost = lngs.reduce(min);
double topMost = lngs.reduce(max);
double leftMost = lats.reduce(min);
double rightMost = lats.reduce(max);
LatLngBounds bounds = LatLngBounds(
northeast: LatLng(rightMost, topMost),
southwest: LatLng(leftMost, bottomMost),
);
return bounds;
double? x0, x1, y0, y1;
for (LatLng latLng in coordinates) {
if (x0 == null) {
x0 = x1 = latLng.latitude;
y0 = y1 = latLng.longitude;
} else {
if (latLng.latitude > x1!) x1 = latLng.latitude;
if (latLng.latitude < x0) x0 = latLng.latitude;
if (latLng.longitude > y1!) y1 = latLng.longitude;
if (latLng.longitude < y0!) y0 = latLng.longitude;
}
}
return LatLngBounds(northeast: LatLng(x1!, y1!), southwest: LatLng(x0!, y0!));
}
void focusCameraToLatLngBounds({LatLngBounds? bound, Completer<GoogleMapController>? mapController, double? padding}) async {
if (bound == null) return;
CameraUpdate camera = CameraUpdate.newLatLngBounds(bound, padding!);
GoogleMapController controller = await mapController!.future;
controller.animateCamera(camera);
}
void focusCameraTo2Points({LatLng? point1, LatLng? point2, Completer<GoogleMapController>? mapController, double? padding}) async {
var source = point1;
var destination = point2;
if (source != null && destination != null) {
// 'package:google_maps_flutter_platform_interface/src/types/location.dart': Failed assertion: line 72 pos 16: 'southwest.latitude <= northeast.latitude': is not true.
LatLngBounds bound;
if (source.latitude <= destination.latitude) {
bound = LatLngBounds(southwest: source, northeast: destination);
} else {
bound = LatLngBounds(southwest: destination, northeast: source);
}
if (bound == null) return;
focusCameraToLatLngBounds(bound: bound, mapController: mapController, padding: padding);
}
}
}

@ -3,7 +3,7 @@ import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:mohem_flutter_app/api/dashboard_api_client.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
@ -95,11 +95,11 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
// if (isNfcEnabled)
attendanceMethod("NFC", "assets/images/nfc.svg", isNfcEnabled, () {
if (isNfcLocationEnabled) {
Location.getCurrentLocation((LatLng? latlng, bool isMocked) {
Location.getCurrentLocation((Position position, bool isMocked) {
if (isMocked) {
markFakeAttendance("NFC", latlng?.latitude.toString() ?? "", latlng?.longitude.toString() ?? "");
markFakeAttendance("NFC", position.latitude.toString() ?? "", position.longitude.toString() ?? "");
} else {
performNfcAttendance(widget.model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? "");
performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
}
}, context);
} else {
@ -109,11 +109,11 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
if (isWifiEnabled)
attendanceMethod("Wifi", "assets/images/wufu.svg", isWifiEnabled, () {
if (isWifiLocationEnabled) {
Location.getCurrentLocation((LatLng? latlng, bool isMocked) {
Location.getCurrentLocation((Position position, bool isMocked) {
if (isMocked) {
markFakeAttendance("WIFI", latlng?.latitude.toString() ?? "", latlng?.longitude.toString() ?? "");
markFakeAttendance("WIFI", position.latitude.toString() ?? "", position.longitude.toString() ?? "");
} else {
performWifiAttendance(widget.model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? "");
performWifiAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
}
}, context);
} else {
@ -124,11 +124,11 @@ class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
if (isQrEnabled)
attendanceMethod("QR", "assets/images/ic_qr.svg", isQrEnabled, () async {
if (isQrLocationEnabled) {
Location.getCurrentLocation((LatLng? latlng, bool isMocked) {
Location.getCurrentLocation((Position position, bool isMocked) {
if (isMocked) {
markFakeAttendance("QR", latlng?.latitude.toString() ?? "", latlng?.longitude.toString() ?? "");
markFakeAttendance("QR", position.latitude.toString() ?? "", position.longitude.toString() ?? "");
} else {
performQrCodeAttendance(widget.model, lat: latlng?.latitude.toString() ?? "", lng: latlng?.longitude.toString() ?? "");
performQrCodeAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
}
}, context);
} else {

@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 3.2.0+300020
version: 3.6.4+2
environment:
sdk: ">=2.16.0 <3.0.0"
@ -46,7 +46,7 @@ dependencies:
local_auth: ^1.1.9
fluttertoast: ^8.0.8
syncfusion_flutter_calendar: ^19.4.48
flutter_calendar_carousel: ^2.1.0
# flutter_calendar_carousel: ^2.1.0
pie_chart: ^5.1.0
shared_preferences: ^2.0.12
firebase_messaging: ^13.0.4
@ -57,13 +57,7 @@ dependencies:
uuid: ^3.0.6
image_picker: ^0.8.5+3
file_picker: ^4.6.1
# maps
google_maps_flutter: ^2.0.2
google_maps_utils: ^1.4.0+1
google_directions_api: ^0.9.0
geolocator: ^9.0.2
# flutter_compass: ^0.6.1
google_maps_flutter_web: ^0.3.2
month_year_picker: ^0.2.0+1
month_picker_dialog_2: 0.5.5
open_file: ^3.2.1
@ -71,7 +65,7 @@ dependencies:
flutter_html: ^3.0.0-alpha.6
# flutter_barcode_scanner: ^2.0.0
qr_code_scanner: ^1.0.0
qr_flutter: ^4.0.0
# qr_flutter: ^4.0.0
url_launcher: ^6.0.15
share: 2.0.4
flutter_rating_bar: ^4.0.1
@ -91,7 +85,7 @@ dependencies:
logging: ^1.0.1
swipe_to: ^1.0.2
flutter_webrtc: ^0.9.16
camera: ^0.10.0+4
camera: ^0.10.3
flutter_local_notifications: any
#firebase_analytics: any
@ -102,11 +96,16 @@ dependencies:
#Encryption
flutter_des: ^2.1.0
video_player: ^2.4.7
video_player: ^2.5.1
just_audio: ^0.9.30
safe_device: ^1.1.2
flutter_layout_grid: ^2.0.1
#Huawei Dependencies
huawei_hmsavailability: ^6.6.0+300
huawei_location: 6.0.0+302
huawei_push: ^6.7.0+300
dependency_overrides:
firebase_core_platform_interface: 4.5.1

Loading…
Cancel
Save