no message

wala_plus
Sultan khan 3 weeks ago
parent 4541bfb1db
commit 330b317164

Binary file not shown.

Before

Width:  |  Height:  |  Size: 778 KiB

After

Width:  |  Height:  |  Size: 168 KiB

@ -22,6 +22,7 @@ import 'package:mohem_flutter_app/widgets/loading_dialog.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:nfc_manager/platform_tags.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:mohem_flutter_app/ui/profile/mazaya_access_result_screen.dart';
// ignore_for_file: avoid_annotating_with_dynamic
@ -94,7 +95,59 @@ class Utils {
return await prefs.setString(key, value);
}
static bool isMazayaAccessRevoked(dynamic error) {
if (error == null) return false;
String str = "";
if (error is APIException && error.error != null) {
String errCode = error.error?.errorCode?.toString() ?? "";
String errMsg = error.error?.errorMessage?.toString() ?? "";
str = "$errCode $errMsg ${error.message}";
if (errCode.trim().toUpperCase() == "E4") {
return true;
}
} else {
str = error.toString();
}
String lower = str.toLowerCase();
if (lower.contains("no active grant") ||
lower.contains("grant request") ||
lower.contains("grant was found") ||
lower.contains("grant_request") ||
lower.contains("e4:") ||
lower.contains("e4 -") ||
lower.contains("e4 :")) {
return true;
}
if (str.contains("طلب منح") ||
str.contains("منح نشط") ||
str.contains("لا يوجد طلب منح") ||
str.contains("تم إلغاء وصول مزايا") ||
str.contains("إلغاء مزايا")) {
return true;
}
return false;
}
static void handleException(dynamic exception, cxt, Function(String)? onErrorMessage) {
if (isMazayaAccessRevoked(exception)) {
String depName = AppState().dependentName ?? "";
if (depName.isEmpty) {
depName = AppState().walaplusDepInfoModel?.pDependentName ?? "";
}
if (cxt != null) {
Navigator.push(
cxt,
MaterialPageRoute(
builder: (context) => MazayaAccessResultScreen(
isGranted: false,
dependentName: depName,
),
),
);
return;
}
}
String errorMessage;
if (exception.error.errorType != null && exception.error.errorType == 4) {
Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.appUpdateScreen, (_) => false, arguments: exception.error?.errorMessage);

@ -10,6 +10,7 @@ class GetEmployeeContactsList {
String? rELATIONSHIP;
String? mAZAYAACCESSFLG;
dynamic mazayaAccess;
String? nATIONALIDENTIFIER;
GetEmployeeContactsList(
{this.cONTACTNAME,
@ -21,7 +22,8 @@ class GetEmployeeContactsList {
this.pRIMARYCONTACTFLAG,
this.rELATIONSHIP,
this.mAZAYAACCESSFLG,
this.mazayaAccess});
this.mazayaAccess,
this.nATIONALIDENTIFIER});
GetEmployeeContactsList.fromJson(Map<String, dynamic> json) {
cONTACTNAME = json['CONTACT_NAME'];
@ -34,6 +36,10 @@ class GetEmployeeContactsList {
rELATIONSHIP = json['RELATIONSHIP'];
mAZAYAACCESSFLG = json['MAZAYA_ACCESS_FLG']?.toString() ?? json['MAZAYA_ACCESS']?.toString();
mazayaAccess = mAZAYAACCESSFLG;
nATIONALIDENTIFIER = json['NATIONAL_IDENTIFIER']?.toString() ??
json['NATIONAL_ID']?.toString() ??
json['CIVIL_ID']?.toString() ??
json['IQAMA_NUMBER']?.toString();
}
Map<String, dynamic> toJson() {
@ -48,6 +54,7 @@ class GetEmployeeContactsList {
data['RELATIONSHIP'] = rELATIONSHIP;
data['MAZAYA_ACCESS_FLG'] = mAZAYAACCESSFLG;
data['MAZAYA_ACCESS'] = mazayaAccess;
data['NATIONAL_IDENTIFIER'] = nATIONALIDENTIFIER;
return data;
}
}

@ -22,6 +22,7 @@ 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/ui/profile/mazaya_access_result_screen.dart';
import 'package:mohem_flutter_app/models/basic_member_information_model.dart';
import 'package:mohem_flutter_app/models/check_mobile_app_version_model.dart';
import 'package:mohem_flutter_app/models/generic_response_model.dart';
@ -125,11 +126,6 @@ class _LoginScreenState extends State<LoginScreen> {
GetMobileLoginInfoListModel? loginInfo;
GetMobileLoginInfoDependentModel? dependentLoginInfo;
bool get _hasDeviceDependentData {
if (dependentLoginInfo == null) return false;
String id = dependentLoginInfo?.nationalId ?? dependentLoginInfo?.dependentID ?? "";
return id.trim().isNotEmpty;
}
Future<void> checkFirebaseToken() async {
try {
@ -598,6 +594,23 @@ class _LoginScreenState extends State<LoginScreen> {
return "";
}
void _navigateToMazayaAccessRevoked([String? depName]) async {
String name = depName ?? AppState().dependentName ?? "";
if (name.isEmpty) {
name = await Utils.getStringFromPrefs("P_DEPENDENT_NAME");
}
if (!mounted) return;
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => MazayaAccessResultScreen(
isGranted: false,
dependentName: name,
),
),
);
}
void performDependentLogin() async {
if (nationalId.text.trim().isEmpty) {
Utils.showToast(LocaleKeys.pleaseEnterNationalId.tr());
@ -634,6 +647,10 @@ class _LoginScreenState extends State<LoginScreen> {
if (depLoginResponse?.errorMessage != null && depLoginResponse!.errorMessage!.isNotEmpty) {
Utils.hideLoading(context);
if (Utils.isMazayaAccessRevoked(depLoginResponse.errorMessage)) {
_navigateToMazayaAccessRevoked();
return;
}
Utils.showToast(depLoginResponse.errorMessage!);
return;
}
@ -694,6 +711,10 @@ class _LoginScreenState extends State<LoginScreen> {
} catch (ex) {
if (kDebugMode) print(ex);
Utils.hideLoading(context);
if (Utils.isMazayaAccessRevoked(ex)) {
_navigateToMazayaAccessRevoked();
return;
}
Utils.handleException(ex, context, null);
}
}
@ -716,6 +737,11 @@ class _LoginScreenState extends State<LoginScreen> {
Utils.hideLoading(context);
if (checkOtpResponse?.errorMessage != null && checkOtpResponse!.errorMessage!.isNotEmpty) {
if (Utils.isMazayaAccessRevoked(checkOtpResponse.errorMessage)) {
Navigator.pop(context);
_navigateToMazayaAccessRevoked();
return;
}
Utils.showToast(checkOtpResponse.errorMessage!);
_pinPutController.clear();
otpFieldClear.value = "";
@ -736,6 +762,11 @@ class _LoginScreenState extends State<LoginScreen> {
_pinPutController.clear();
otpFieldClear.value = "";
Utils.hideLoading(context);
if (Utils.isMazayaAccessRevoked(ex)) {
Navigator.pop(context);
_navigateToMazayaAccessRevoked();
return;
}
Utils.handleException(ex, context, null);
}
},
@ -755,6 +786,11 @@ class _LoginScreenState extends State<LoginScreen> {
Utils.showToast(LocaleKeys.verificationCodeResent.tr());
} catch (ex) {
Utils.hideLoading(context);
if (Utils.isMazayaAccessRevoked(ex)) {
Navigator.pop(context);
_navigateToMazayaAccessRevoked();
return;
}
Utils.handleException(ex, context, null);
}
},

File diff suppressed because it is too large Load Diff

@ -110,33 +110,17 @@ class _FamilyMembersState extends State<FamilyMembers> {
return "${parts.first[0]}${parts.last[0]}".toUpperCase();
}
String _getIdEnding(GetEmployeeContactsList contact) {
String raw = contact.pERSONID?.toString() ??
contact.cONTACTPERSONID?.toString() ??
contact.cONTACTRELATIONSHIPID?.toString() ??
"";
if (raw.length > 4) {
return raw.substring(raw.length - 4);
}
if (raw.isNotEmpty) {
return raw.padLeft(4, '0');
}
return "";
}
List<GetEmployeeContactsList> get _filteredList {
if (_searchQuery.trim().isEmpty) return getEmployeeContactsList;
String q = _searchQuery.trim().toLowerCase();
return getEmployeeContactsList.where((GetEmployeeContactsList item) {
String name = (item.cONTACTNAME ?? "").toLowerCase();
String rel = (item.rELATIONSHIP ?? "").toLowerCase();
String id = _getIdEnding(item);
String personId = (item.pERSONID?.toString() ?? "").toLowerCase();
String contactPersonId = (item.cONTACTPERSONID?.toString() ?? "").toLowerCase();
String contactType = (item.cONTACTTYPE ?? "").toLowerCase();
return name.contains(q) ||
rel.contains(q) ||
id.contains(q) ||
personId.contains(q) ||
contactPersonId.contains(q) ||
contactType.contains(q);
@ -178,12 +162,13 @@ class _FamilyMembersState extends State<FamilyMembers> {
List<GetEmployeeContactsList> displayList = _filteredList;
return Scaffold(
backgroundColor: Colors.white,
backgroundColor: const Color(0xFFF8FAFC),
appBar: PreferredSize(
preferredSize: const Size.fromHeight(56),
child: SafeArea(
child: Container(
height: 56,
color: const Color(0xFFF8FAFC),
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: <Widget>[
@ -342,7 +327,7 @@ class _FamilyMembersState extends State<FamilyMembers> {
bool isAllowed = _isAccessAllowed(item);
return Container(
padding: const EdgeInsets.all(16),
padding: const EdgeInsets.fromLTRB(16, 16, 16, 14),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
@ -364,16 +349,20 @@ class _FamilyMembersState extends State<FamilyMembers> {
children: <Widget>[
// Initials Circle
Container(
width: 44,
height: 44,
width: 48,
height: 48,
decoration: const BoxDecoration(
color: Color(0xFFE6F7F2),
color: Color(0xFFE6F5F3),
shape: BoxShape.circle,
),
child: Center(
child: _getInitials(item.cONTACTNAME).toText16(
isBold: true,
color: const Color(0xFF168A89),
child: Text(
_getInitials(item.cONTACTNAME),
style: const TextStyle(
color: Color(0xFF168A89),
fontWeight: FontWeight.w700,
fontSize: 15,
),
),
),
),
@ -384,10 +373,15 @@ class _FamilyMembersState extends State<FamilyMembers> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
(item.cONTACTNAME ?? "").toText16(
isBold: true,
maxlines: 1,
color: const Color(0xFF1E293B),
Text(
item.cONTACTNAME ?? "",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,
color: Color(0xFF1E293B),
),
),
const SizedBox(height: 3),
Row(
@ -398,7 +392,6 @@ class _FamilyMembersState extends State<FamilyMembers> {
color: const Color(0xFF168A89),
),
),
],
),
],
@ -411,11 +404,16 @@ class _FamilyMembersState extends State<FamilyMembers> {
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: isAllowed ? const Color(0xFFE8F8F0) : const Color(0xFFFEECEB),
color: isAllowed ? const Color(0xFFE8F8F0) : const Color(0xFFFDE8E8),
borderRadius: BorderRadius.circular(20),
),
child: (isAllowed ? LocaleKeys.active.tr() : LocaleKeys.noAccess.tr()).toText11(
color: isAllowed ? const Color(0xFF2DBD72) : const Color(0xFFED1C24),
child: Text(
isAllowed ? LocaleKeys.active.tr() : LocaleKeys.noAccess.tr(),
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w500,
color: isAllowed ? const Color(0xFF168A89) : const Color(0xFFDC2626),
),
),
),
],
@ -423,32 +421,41 @@ class _FamilyMembersState extends State<FamilyMembers> {
),
const SizedBox(height: 14),
const Divider(height: 1, thickness: 1, color: Color(0xFFF1F5F9)),
const SizedBox(height: 12),
// Bottom Action Row
if (fromMazaya) ...<Widget>[
// Mazaya Access Buttons: Revoke or Allow
InkWell(
borderRadius: BorderRadius.circular(10),
onTap: () => _toggleMazayaAccess(item),
child: Container(
width: double.infinity,
height: 40,
decoration: BoxDecoration(
color: isAllowed ? const Color(0xFFFFF1F0) : const Color(0xFFE6F7F2),
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: isAllowed ? const Color(0xFFFFD9D7) : const Color(0xFFCEEFE7),
width: 0.8,
),
),
child: Center(
child: (isAllowed
? LocaleKeys.revokeMazayaAccess.tr()
: LocaleKeys.allowMazayaAccess.tr())
.toText14(
isBold: true,
isCenter: true,
color: isAllowed ? const Color(0xFFED1C24) : const Color(0xFF168A89),
Center(
child: InkWell(
borderRadius: BorderRadius.circular(8),
onTap: () => _toggleMazayaAccess(item),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
isAllowed ? Icons.close : Icons.check,
size: isAllowed ? 16 : 18,
color: isAllowed ? const Color(0xFFDC2626) : const Color(0xFF168A89),
),
const SizedBox(width: 6),
Text(
isAllowed
? LocaleKeys.revokeMazayaAccess.tr()
: LocaleKeys.allowMazayaAccess.tr(),
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w700,
color: isAllowed ? const Color(0xFFDC2626) : const Color(0xFF168A89),
decoration: TextDecoration.underline,
decorationColor: isAllowed ? const Color(0xFFDC2626) : const Color(0xFF168A89),
),
),
],
),
),
),

@ -142,6 +142,15 @@ class MazayaAccessResultScreen extends StatelessWidget {
effectiveUrl = routeArgs['downloadUrl'] ?? downloadUrl;
}
if (effectiveName.trim().isEmpty) {
String fallback = AppState().dependentName ?? "";
if (fallback.isNotEmpty) {
effectiveName = fallback;
} else {
effectiveName = isAr ? "التابع" : "Dependent";
}
}
String linkToShare = effectiveUrl ?? getDownloadLink();
String initials = effectiveInitials ?? _getInitials(effectiveName);

@ -21,6 +21,15 @@ class DynamicTextFieldWidget extends StatelessWidget {
final int? maxLength;
final List<TextInputFormatter>? inputFormatters;
final Color? backgroundColor;
final Color? borderColor;
final double? borderWidth;
final Color? labelColor;
final Color? textColor;
final Color? suffixIconColor;
final BorderRadius? borderRadius;
final List<BoxShadow>? boxShadow;
final BoxConstraints? constraints;
final EdgeInsetsGeometry? padding;
DynamicTextFieldWidget(this.labelText, this.hintText,
{this.controller,
@ -38,20 +47,37 @@ class DynamicTextFieldWidget extends StatelessWidget {
this.isBackgroundEnable = false,
this.maxLength,
this.inputFormatters,
this.backgroundColor});
this.backgroundColor,
this.borderColor,
this.borderWidth,
this.labelColor,
this.textColor,
this.suffixIconColor,
this.borderRadius,
this.boxShadow,
this.constraints,
this.padding});
@override
Widget build(BuildContext context) {
Color effectiveBorderColor = borderColor ?? MyColors.lightGreyEFColor;
double effectiveBorderWidth = borderWidth ?? 1.0;
Color effectiveLabelColor = labelColor ?? const Color(0xff2B353E);
Color effectiveTextColor = textColor ?? const Color(0xff2B353E);
Color effectiveSuffixColor = suffixIconColor ?? MyColors.darkIconColor;
return Container(
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 15, top: 15),
constraints: constraints,
padding: padding ?? const EdgeInsets.only(left: 16, right: 16, bottom: 15, top: 15),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
borderRadius: borderRadius ?? BorderRadius.circular(15),
color: backgroundColor ?? (isReadOnly ? MyColors.lightGreyEFColor : Colors.white),
border: Border.all(
color: MyColors.lightGreyEFColor,
width: 1,
color: effectiveBorderColor,
width: effectiveBorderWidth,
),
boxShadow: boxShadow,
),
child: InkWell(
onTap: onTap,
@ -65,10 +91,10 @@ class DynamicTextFieldWidget extends StatelessWidget {
if (labelText.isNotEmpty)
Text(
labelText,
style: const TextStyle(
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w600,
color: Color(0xff2B353E),
color: effectiveLabelColor,
letterSpacing: -0.44,
),
),
@ -87,11 +113,11 @@ class DynamicTextFieldWidget extends StatelessWidget {
obscuringCharacter: "*",
obscureText: isObscureText,
onChanged: onChange,
style: const TextStyle(
style: TextStyle(
fontSize: 14,
height: 21 / 14,
fontWeight: FontWeight.w400,
color: Color(0xff2B353E),
color: effectiveTextColor,
letterSpacing: -0.44,
),
decoration: InputDecoration(
@ -106,9 +132,6 @@ class DynamicTextFieldWidget extends StatelessWidget {
color: Color(0xff575757),
letterSpacing: -0.56,
),
// suffixIconConstraints: const BoxConstraints(minWidth: 50),
// suffixIcon: suffixIconData == null ? null : Icon(suffixIconData, color: MyColors.darkTextColor),
// suffixIcon: suffixTap == null ? null : IconButton(icon: Icon(suffixIconData, color: MyColors.darkTextColor), onPressed: suffixTap),
contentPadding: EdgeInsets.zero,
border: InputBorder.none,
focusedBorder: InputBorder.none,
@ -118,8 +141,12 @@ 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 (isPopup)
Icon(Icons.keyboard_arrow_down_outlined, color: effectiveSuffixColor)
else if (onTap != null)
Icon(suffixIconData ?? Icons.keyboard_arrow_down_outlined, color: effectiveSuffixColor)
else if (suffixIconData != null)
Icon(suffixIconData, color: effectiveSuffixColor),
],
),
),

Loading…
Cancel
Save