You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
684 lines
22 KiB
Dart
684 lines
22 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:mohem_flutter_app/app_state/app_state.dart';
|
|
import 'package:mohem_flutter_app/classes/utils.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:share_plus/share_plus.dart';
|
|
|
|
class MazayaAccessResultParams {
|
|
final bool isGranted;
|
|
final String dependentName;
|
|
final String? dependentInitials;
|
|
final String? downloadUrl;
|
|
|
|
const MazayaAccessResultParams({
|
|
required this.isGranted,
|
|
required this.dependentName,
|
|
this.dependentInitials,
|
|
this.downloadUrl,
|
|
});
|
|
}
|
|
|
|
class _ShieldPainter extends CustomPainter {
|
|
final Color color;
|
|
final bool isGranted;
|
|
|
|
_ShieldPainter({required this.color, required this.isGranted});
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
Paint paint = Paint()
|
|
..color = color
|
|
..style = PaintingStyle.stroke
|
|
..strokeWidth = 2.4
|
|
..strokeCap = StrokeCap.round
|
|
..strokeJoin = StrokeJoin.round;
|
|
|
|
double w = size.width;
|
|
double h = size.height;
|
|
|
|
// Shield path
|
|
Path path = Path();
|
|
path.moveTo(w * 0.5, h * 0.1);
|
|
path.cubicTo(w * 0.72, h * 0.1, w * 0.88, h * 0.18, w * 0.88, h * 0.38);
|
|
path.cubicTo(w * 0.88, h * 0.65, w * 0.68, h * 0.84, w * 0.5, h * 0.92);
|
|
path.cubicTo(w * 0.32, h * 0.84, w * 0.12, h * 0.65, w * 0.12, h * 0.38);
|
|
path.cubicTo(w * 0.12, h * 0.18, w * 0.28, h * 0.1, w * 0.5, h * 0.1);
|
|
path.close();
|
|
|
|
canvas.drawPath(path, paint);
|
|
|
|
if (isGranted) {
|
|
// Checkmark path
|
|
Path checkPath = Path();
|
|
checkPath.moveTo(w * 0.34, h * 0.49);
|
|
checkPath.lineTo(w * 0.46, h * 0.61);
|
|
checkPath.lineTo(w * 0.66, h * 0.39);
|
|
canvas.drawPath(checkPath, paint);
|
|
} else {
|
|
// Cross path
|
|
canvas.drawLine(
|
|
Offset(w * 0.38, h * 0.38),
|
|
Offset(w * 0.62, h * 0.62),
|
|
paint,
|
|
);
|
|
canvas.drawLine(
|
|
Offset(w * 0.62, h * 0.38),
|
|
Offset(w * 0.38, h * 0.62),
|
|
paint,
|
|
);
|
|
}
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(covariant _ShieldPainter oldDelegate) =>
|
|
color != oldDelegate.color || isGranted != oldDelegate.isGranted;
|
|
}
|
|
|
|
class MazayaAccessResultScreen extends StatelessWidget {
|
|
final bool isGranted;
|
|
final String dependentName;
|
|
final String? dependentInitials;
|
|
final String? downloadUrl;
|
|
|
|
const MazayaAccessResultScreen({
|
|
Key? key,
|
|
this.isGranted = true,
|
|
this.dependentName = "",
|
|
this.dependentInitials,
|
|
this.downloadUrl,
|
|
}) : super(key: key);
|
|
|
|
static String getDownloadLink() {
|
|
int channel = AppState().postParamsObject?.channel ?? 31;
|
|
bool isIos = Platform.isIOS;
|
|
if (channel == 33) {
|
|
return isIos
|
|
? "https://apps.apple.com/sa/app/al-habib-mohem/id1480157255"
|
|
: "https://play.google.com/store/apps/details?id=com.cloudsolutions.alhabibmohemm&hl=en";
|
|
} else {
|
|
return isIos
|
|
? "https://apps.apple.com/sa/app/mohemm/id1468856602"
|
|
: "https://play.google.com/store/apps/details?id=hmg.cloudSolutions.mohem&hl=en";
|
|
}
|
|
}
|
|
|
|
String _getInitials(String? name) {
|
|
if (name == null || name.trim().isEmpty) return "D";
|
|
List<String> parts = name.trim().split(RegExp(r'\s+')).where((String p) => p.isNotEmpty).toList();
|
|
if (parts.isEmpty) return "D";
|
|
if (parts.length == 1) {
|
|
return parts.first.length >= 2 ? parts.first.substring(0, 2).toUpperCase() : parts.first.toUpperCase();
|
|
}
|
|
return "${parts.first[0]}${parts.last[0]}".toUpperCase();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
bool isAr = AppState().isArabic(context);
|
|
String fontFamily = isAr ? 'Cairo' : 'Poppins';
|
|
|
|
// Resolve arguments if passed via ModalRoute
|
|
Object? routeArgs = ModalRoute.of(context)?.settings.arguments;
|
|
bool effectiveGranted = isGranted;
|
|
String effectiveName = dependentName;
|
|
String? effectiveInitials = dependentInitials;
|
|
String? effectiveUrl = downloadUrl;
|
|
|
|
if (routeArgs is MazayaAccessResultParams) {
|
|
effectiveGranted = routeArgs.isGranted;
|
|
effectiveName = routeArgs.dependentName;
|
|
effectiveInitials = routeArgs.dependentInitials;
|
|
effectiveUrl = routeArgs.downloadUrl;
|
|
} else if (routeArgs is Map<String, dynamic>) {
|
|
effectiveGranted = routeArgs['isGranted'] ?? isGranted;
|
|
effectiveName = routeArgs['dependentName'] ?? dependentName;
|
|
effectiveInitials = routeArgs['dependentInitials'] ?? dependentInitials;
|
|
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);
|
|
|
|
return Scaffold(
|
|
backgroundColor: Colors.white,
|
|
appBar: PreferredSize(
|
|
preferredSize: const Size.fromHeight(56),
|
|
child: SafeArea(
|
|
child: Container(
|
|
height: 56,
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Row(
|
|
children: <Widget>[
|
|
InkWell(
|
|
borderRadius: BorderRadius.circular(20),
|
|
onTap: () => Navigator.pop(context),
|
|
child: const Padding(
|
|
padding: EdgeInsets.all(8.0),
|
|
child: Icon(
|
|
Icons.arrow_back_ios_new_rounded,
|
|
size: 20,
|
|
color: Color(0xFF1E293B),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(width: 4),
|
|
LocaleKeys.mazayaTitle.tr().toText20(
|
|
isBold: true,
|
|
color: const Color(0xFF1E293B),
|
|
),
|
|
const Spacer(),
|
|
InkWell(
|
|
borderRadius: BorderRadius.circular(20),
|
|
onTap: () => Navigator.pop(context),
|
|
child: const Padding(
|
|
padding: EdgeInsets.all(8.0),
|
|
child: Icon(
|
|
Icons.close_rounded,
|
|
size: 24,
|
|
color: Color(0xFF1E293B),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
body: SafeArea(
|
|
child: Column(
|
|
children: <Widget>[
|
|
Expanded(
|
|
child: SingleChildScrollView(
|
|
padding: const EdgeInsets.fromLTRB(20, 16, 20, 20),
|
|
child: effectiveGranted
|
|
? _buildGrantedContent(context, isAr, fontFamily, effectiveName, initials, linkToShare)
|
|
: _buildRevokedContent(context, isAr, fontFamily, effectiveName, initials),
|
|
),
|
|
),
|
|
_buildBottomButtons(context, isAr, fontFamily, effectiveGranted, linkToShare),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildGrantedContent(
|
|
BuildContext context,
|
|
bool isAr,
|
|
String fontFamily,
|
|
String name,
|
|
String initials,
|
|
String linkToShare,
|
|
) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: <Widget>[
|
|
const SizedBox(height: 8),
|
|
|
|
// Shield checkmark badge
|
|
Container(
|
|
width: 80,
|
|
height: 80,
|
|
decoration: const BoxDecoration(
|
|
color: Color(0xFFE6F7F2),
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Center(
|
|
child: CustomPaint(
|
|
size: const Size(40, 40),
|
|
painter: _ShieldPainter(
|
|
color: const Color(0xFF168A89),
|
|
isGranted: true,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 18),
|
|
|
|
// Title
|
|
LocaleKeys.mazayaAccessGranted.tr().toText22(
|
|
isBold: true,
|
|
isCentered: true,
|
|
color: const Color(0xFF1E293B),
|
|
),
|
|
|
|
const SizedBox(height: 8),
|
|
|
|
// Description
|
|
LocaleKeys.mazayaAccessGrantedDesc.tr(args: <String>[name]).toText14(
|
|
isCenter: true,
|
|
color: const Color(0xFF64748B),
|
|
),
|
|
|
|
const SizedBox(height: 22),
|
|
|
|
// Access is now active banner
|
|
Container(
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFFE8F8F0),
|
|
borderRadius: BorderRadius.circular(14),
|
|
border: Border.all(color: const Color(0xFFCEEFE7), width: 1),
|
|
),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
const Padding(
|
|
padding: EdgeInsets.only(top: 2),
|
|
child: Icon(
|
|
Icons.check_circle_outline_rounded,
|
|
color: Color(0xFF168A89),
|
|
size: 20,
|
|
),
|
|
),
|
|
const SizedBox(width: 10),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
LocaleKeys.accessIsNowActive.tr().toText14(
|
|
isBold: true,
|
|
color: const Color(0xFF168A89),
|
|
),
|
|
const SizedBox(height: 3),
|
|
LocaleKeys.accessIsNowActiveDesc.tr(args: <String>[name]).toText12(
|
|
color: const Color(0xFF64748B),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 14),
|
|
|
|
// Dependent Card
|
|
Container(
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.all(14),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(14),
|
|
border: Border.all(color: const Color(0xFFF1F5F9)),
|
|
boxShadow: const <BoxShadow>[
|
|
BoxShadow(
|
|
color: Color(0x08000000),
|
|
blurRadius: 10,
|
|
offset: Offset(0, 3),
|
|
),
|
|
],
|
|
),
|
|
child: Row(
|
|
children: <Widget>[
|
|
Container(
|
|
width: 42,
|
|
height: 42,
|
|
decoration: const BoxDecoration(
|
|
color: Color(0xFFE6F7F2),
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Center(
|
|
child: initials.toText14(
|
|
isBold: true,
|
|
color: const Color(0xFF168A89),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
name.toText14(
|
|
isBold: true,
|
|
maxlines: 1,
|
|
color: const Color(0xFF1E293B),
|
|
),
|
|
const SizedBox(height: 2),
|
|
LocaleKeys.dependentAccessActive.tr().toText12(
|
|
isBold: true,
|
|
color: const Color(0xFF168A89),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const Icon(
|
|
Icons.lock_open_rounded,
|
|
color: Color(0xFF168A89),
|
|
size: 20,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 14),
|
|
|
|
// Shareable App-Download Link Card
|
|
Container(
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.all(14),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(14),
|
|
border: Border.all(color: const Color(0xFFE2E8F0)),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
Container(
|
|
width: 36,
|
|
height: 36,
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFFE8F8F0),
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
child: const Center(
|
|
child: Icon(
|
|
Icons.smartphone_rounded,
|
|
color: Color(0xFF168A89),
|
|
size: 20,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(width: 10),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
LocaleKeys.shareableAppDownloadLink.tr().toText14(
|
|
isBold: true,
|
|
color: const Color(0xFF1E293B),
|
|
),
|
|
const SizedBox(height: 2),
|
|
LocaleKeys.shareableAppDownloadLinkDesc.tr(args: <String>[name]).toText12(
|
|
color: const Color(0xFF64748B),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 12),
|
|
Container(
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 9),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFFF8FAFC),
|
|
borderRadius: BorderRadius.circular(10),
|
|
border: Border.all(color: const Color(0xFFE2E8F0)),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
LocaleKeys.downloadLink.tr().toText11(
|
|
isBold: true,
|
|
color: const Color(0xFF168A89),
|
|
),
|
|
const SizedBox(height: 3),
|
|
linkToShare.toText12(
|
|
maxLine: 1,
|
|
color: const Color(0xFF334155),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildRevokedContent(
|
|
BuildContext context,
|
|
bool isAr,
|
|
String fontFamily,
|
|
String name,
|
|
String initials,
|
|
) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: <Widget>[
|
|
const SizedBox(height: 8),
|
|
|
|
// Shield bad badge
|
|
Container(
|
|
width: 80,
|
|
height: 80,
|
|
decoration: const BoxDecoration(
|
|
color: Color(0xFFFEECEB),
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Center(
|
|
child: CustomPaint(
|
|
size: const Size(40, 40),
|
|
painter: _ShieldPainter(
|
|
color: const Color(0xFFED1C24),
|
|
isGranted: false,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 18),
|
|
|
|
// Title
|
|
LocaleKeys.mazayaAccessRevoked.tr().toText22(
|
|
isBold: true,
|
|
isCentered: true,
|
|
color: const Color(0xFF1E293B),
|
|
),
|
|
|
|
const SizedBox(height: 8),
|
|
|
|
// Description
|
|
LocaleKeys.mazayaAccessRevokedDesc.tr().toText14(
|
|
isCenter: true,
|
|
color: const Color(0xFF64748B),
|
|
),
|
|
|
|
const SizedBox(height: 22),
|
|
|
|
// Contact your sponsor banner
|
|
Container(
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFFFFF5F5),
|
|
borderRadius: BorderRadius.circular(14),
|
|
border: Border.all(color: const Color(0xFFFFCDD2), width: 1),
|
|
),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
const Padding(
|
|
padding: EdgeInsets.only(top: 2),
|
|
child: Icon(
|
|
Icons.phone_outlined,
|
|
color: Color(0xFFED1C24),
|
|
size: 20,
|
|
),
|
|
),
|
|
const SizedBox(width: 10),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
LocaleKeys.contactYourSponsor.tr().toText14(
|
|
isBold: true,
|
|
color: const Color(0xFFED1C24),
|
|
),
|
|
const SizedBox(height: 3),
|
|
LocaleKeys.contactYourSponsorDesc.tr().toText12(
|
|
color: const Color(0xFF64748B),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 14),
|
|
|
|
// Dependent Card
|
|
Container(
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.all(14),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(14),
|
|
border: Border.all(color: const Color(0xFFF1F5F9)),
|
|
boxShadow: const <BoxShadow>[
|
|
BoxShadow(
|
|
color: Color(0x08000000),
|
|
blurRadius: 10,
|
|
offset: Offset(0, 3),
|
|
),
|
|
],
|
|
),
|
|
child: Row(
|
|
children: <Widget>[
|
|
Container(
|
|
width: 42,
|
|
height: 42,
|
|
decoration: const BoxDecoration(
|
|
color: Color(0xFFFFF1F0),
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Center(
|
|
child: initials.toText14(
|
|
isBold: true,
|
|
color: const Color(0xFFED1C24),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
name.toText14(
|
|
isBold: true,
|
|
maxlines: 1,
|
|
color: const Color(0xFF1E293B),
|
|
),
|
|
const SizedBox(height: 2),
|
|
LocaleKeys.dependentAccessBlocked.tr().toText12(
|
|
isBold: true,
|
|
color: const Color(0xFFED1C24),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const Icon(
|
|
Icons.lock_outline_rounded,
|
|
color: Color(0xFFED1C24),
|
|
size: 20,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildBottomButtons(
|
|
BuildContext context,
|
|
bool isAr,
|
|
String fontFamily,
|
|
bool granted,
|
|
String linkToShare,
|
|
) {
|
|
if (granted) {
|
|
return Container(
|
|
color: Colors.white,
|
|
padding: const EdgeInsets.fromLTRB(20, 10, 20, 20),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
DefaultButton(
|
|
LocaleKeys.shareDownloadLink.tr(),
|
|
() async {
|
|
try {
|
|
await SharePlus.instance.share(ShareParams(text: linkToShare));
|
|
} catch (_) {}
|
|
},
|
|
trailingIconData: isAr ? Icons.arrow_back_rounded : Icons.arrow_forward_rounded,
|
|
fontSize: 14,
|
|
isTextExpanded: false,
|
|
height: 48,
|
|
borderRadius: 12,
|
|
),
|
|
const SizedBox(height: 10),
|
|
DefaultButton(
|
|
LocaleKeys.copyLink.tr(),
|
|
() {
|
|
Clipboard.setData(ClipboardData(text: linkToShare));
|
|
Utils.showToast(LocaleKeys.linkCopied.tr());
|
|
},
|
|
colors: const <Color>[Colors.white, Colors.white],
|
|
border: Border.all(color: const Color(0xFFCBD5E1)),
|
|
textColor: const Color(0xFF168A89),
|
|
fontSize: 14,
|
|
isTextExpanded: false,
|
|
height: 48,
|
|
borderRadius: 12,
|
|
),
|
|
const SizedBox(height: 10),
|
|
DefaultButton(
|
|
LocaleKeys.done.tr(),
|
|
() => Navigator.pop(context),
|
|
colors: const <Color>[Colors.white, Colors.white],
|
|
border: Border.all(color: const Color(0xFFCBD5E1)),
|
|
textColor: const Color(0xFF334155),
|
|
fontSize: 14,
|
|
isTextExpanded: false,
|
|
height: 48,
|
|
borderRadius: 12,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
} else {
|
|
return Container(
|
|
color: Colors.white,
|
|
padding: const EdgeInsets.fromLTRB(20, 10, 20, 20),
|
|
child: DefaultButton(
|
|
LocaleKeys.returnToSignIn.tr(),
|
|
() => Navigator.pop(context),
|
|
colors: const <Color>[Colors.white, Colors.white],
|
|
border: Border.all(color: const Color(0xFFCEEFE7), width: 1.2),
|
|
textColor: const Color(0xFF168A89),
|
|
iconData: isAr ? Icons.arrow_forward_rounded : Icons.arrow_back_rounded,
|
|
fontSize: 14,
|
|
isTextExpanded: false,
|
|
height: 48,
|
|
borderRadius: 12,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
}
|