From f99ea0dacd8d99261a268cff73f9bfdae7520a3f Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 25 Mar 2025 12:32:54 +0300 Subject: [PATCH] remove camel case text, confirmation dialog added, on back press. --- lib/extensions/text_extensions.dart | 15 ++-- lib/extensions/widget_extensions.dart | 46 ++++++++--- .../common_widgets/app_filled_button.dart | 4 +- .../common_widgets/default_app_bar.dart | 16 +++- .../dialoge/acknowledge_work_dialog.dart | 67 ++++++++++++++++ .../swipe_module/dialoge/confirm_dialog.dart | 14 ++-- .../maintenance_request_main.dart | 76 ++++++++++--------- 7 files changed, 175 insertions(+), 63 deletions(-) create mode 100644 lib/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart diff --git a/lib/extensions/text_extensions.dart b/lib/extensions/text_extensions.dart index 5a81bc5c..ea5496e3 100644 --- a/lib/extensions/text_extensions.dart +++ b/lib/extensions/text_extensions.dart @@ -164,13 +164,14 @@ extension CapExtension on String { String get allInCaps => toUpperCase(); - String get cleanupWhitespace => replaceAll(RegExp(r"\s+"), " "); - - String get capitalizeFirstOfEach => trim().isNotEmpty - ? trim().toLowerCase().split(" ").map((str) { - return str.trim()?.inCaps ?? ""; - }).join(" ") - : ""; + String get cleanupWhitespace => this;//replaceAll(RegExp(r"\s+"), " "); + + String get capitalizeFirstOfEach => this; + //trim().isNotEmpty + // ? trim().toLowerCase().split(" ").map((str) { + // return str.trim()?.inCaps ?? ""; + // }).join(" ") + // : ""; } extension FilesExtension on String { diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index 0586f01a..23a5a6a1 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -4,6 +4,7 @@ import 'package:shimmer/shimmer.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart'; import '../new_views/app_style/app_color.dart'; @@ -54,6 +55,26 @@ extension WidgetExtensions on Widget { Widget toExpanded({int flex = 1}) => Expanded(flex: flex, child: this); + Widget handlePopScope(BuildContext _cxt, VoidCallback onSave) { + return PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, result) { + if (didPop) { + return; + } + showDialog( + context: _cxt, + builder: (BuildContext cxt) => AcknowledgeWorkDialog( + onSave: () => onSave(), + onDiscard: () { + Navigator.of(cxt).pop(); + }, + ), + ); + }, + child: this); + } + Widget toShimmer({bool isShow = true, double radius = 20}) => isShow ? Shimmer.fromColors( baseColor: const Color(0xffe8eff0), @@ -81,18 +102,19 @@ extension WidgetExtensions on Widget { ).toShadowContainer(context) : this; - Widget toShadowContainer(BuildContext context, {bool showShadow = true,double borderRadius = 14, bool withShadow = true, Color? backgroundColor, double padding = 16, EdgeInsets? paddingObject}) => withShadow - ? Container( - padding: paddingObject ?? EdgeInsets.all(padding), - width: double.infinity, - decoration: ShapeDecoration( - color: backgroundColor ?? AppColor.background(context), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(borderRadius)), - shadows: showShadow ? [boxShadowR14] : null, - ), - child: this, - ) - : this; + Widget toShadowContainer(BuildContext context, {bool showShadow = true, double borderRadius = 14, bool withShadow = true, Color? backgroundColor, double padding = 16, EdgeInsets? paddingObject}) => + withShadow + ? Container( + padding: paddingObject ?? EdgeInsets.all(padding), + width: double.infinity, + decoration: ShapeDecoration( + color: backgroundColor ?? AppColor.background(context), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(borderRadius)), + shadows: showShadow ? [boxShadowR14] : null, + ), + child: this, + ) + : this; Widget bottomSheetContainer(BuildContext context, {EdgeInsets? padding}) => Container( clipBehavior: Clip.antiAlias, diff --git a/lib/new_views/common_widgets/app_filled_button.dart b/lib/new_views/common_widgets/app_filled_button.dart index 153f7431..87376c27 100644 --- a/lib/new_views/common_widgets/app_filled_button.dart +++ b/lib/new_views/common_widgets/app_filled_button.dart @@ -15,6 +15,7 @@ class AppFilledButton extends StatelessWidget { final Color? textColor; final bool showBorder; final double radius; + final int height; final bool disableButton; const AppFilledButton( @@ -25,6 +26,7 @@ class AppFilledButton extends StatelessWidget { this.icon, this.fontSize, this.loading = false, + this.height = 56, this.showBorder = false, this.disableButton = false, this.buttonColor, @@ -36,7 +38,7 @@ class AppFilledButton extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - height: 56.toScreenHeight, + height: height.toScreenHeight, width: maxWidth ? double.infinity : null, alignment: Alignment.center, decoration: BoxDecoration( diff --git a/lib/new_views/common_widgets/default_app_bar.dart b/lib/new_views/common_widgets/default_app_bar.dart index 6cc8bd5a..7d28abaa 100644 --- a/lib/new_views/common_widgets/default_app_bar.dart +++ b/lib/new_views/common_widgets/default_app_bar.dart @@ -4,6 +4,7 @@ import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/new_views/pages/land_page/land_page.dart'; +import 'package:test_sa/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart'; import '../app_style/app_color.dart'; @@ -12,8 +13,9 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { final List? actions; final Function? onBackPress; final bool showHomeActionButton; + final VoidCallback? onWillPopScope; - const DefaultAppBar({this.title, this.onBackPress, this.actions, this.showHomeActionButton = false, Key? key}) : super(key: key); + const DefaultAppBar({this.title, this.onBackPress, this.onWillPopScope, this.actions, this.showHomeActionButton = false, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -40,6 +42,18 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { title: Row( children: [ const Icon(Icons.arrow_back_ios).onPress(() { + if (onWillPopScope != null) { + showDialog( + context: context, + builder: (BuildContext cxt) => AcknowledgeWorkDialog( + onSave: onWillPopScope!, + onDiscard: () { + Navigator.of(cxt).pop(); + }, + ), + ); + return; + } if (onBackPress != null) { onBackPress!(); } else { diff --git a/lib/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart b/lib/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart new file mode 100644 index 00000000..81ee9a1d --- /dev/null +++ b/lib/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart @@ -0,0 +1,67 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; + +class AcknowledgeWorkDialog extends StatelessWidget { + final String? title; + final String? message; + final String? okTitle; + final VoidCallback onSave; + final VoidCallback onDiscard; + + const AcknowledgeWorkDialog( + {Key? key, this.title, this.message = "To prevent the risk of losing your changes, Please confirm Save or Discard", this.okTitle, required this.onSave, required this.onDiscard}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.white, + shape: const RoundedRectangleBorder(), + insetPadding: const EdgeInsets.only(left: 21, right: 21), + child: Padding( + padding: const EdgeInsets.only(left: 20, right: 20, top: 18, bottom: 28), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + const Text( + "Confirm", + style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: Colors.black87, height: 35 / 24, letterSpacing: -0.96), + ).paddingOnly(top: 16, bottom: 8), + message != null ? message!.heading5(context).custom(color: AppColor.neutral50) : const SizedBox(), + 28.height, + Row( + children: [ + AppFilledButton( + label: "Discard", + buttonColor: Colors.white54, + textColor: AppColor.red30, + height: 40, + showBorder: true, + onPressed: () { + Navigator.of(context).pop(); + onDiscard(); + }, + ).expanded, + 16.width, + AppFilledButton( + label: "Save", + onPressed: () { + Navigator.of(context).pop(); + onSave(); + }, + height: 40, + buttonColor: AppColor.green70, + ).expanded, + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/new_views/swipe_module/dialoge/confirm_dialog.dart b/lib/new_views/swipe_module/dialoge/confirm_dialog.dart index 3e07310f..f8cfacfb 100644 --- a/lib/new_views/swipe_module/dialoge/confirm_dialog.dart +++ b/lib/new_views/swipe_module/dialoge/confirm_dialog.dart @@ -6,13 +6,13 @@ import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; class ConfirmDialog extends StatelessWidget { - final String ?title; - final String ?message; - final String ?okTitle; - final VoidCallback ?onTap; - final VoidCallback ?onCloseTap; + final String? title; + final String? message; + final String? okTitle; + final VoidCallback? onTap; + final VoidCallback? onCloseTap; - const ConfirmDialog({Key ?key, this.title, this.message, this.okTitle, this.onTap, this.onCloseTap}) : super(key: key); + const ConfirmDialog({Key? key, this.title, this.message, this.okTitle, this.onTap, this.onCloseTap}) : super(key: key); @override Widget build(BuildContext context) { @@ -45,7 +45,7 @@ class ConfirmDialog extends StatelessWidget { ) ], ), - message!=null?message!.heading5(context).custom(color: AppColor.neutral70):const SizedBox(), + message != null ? message!.heading5(context).custom(color: AppColor.neutral70) : const SizedBox(), 28.height, AppFilledButton( label: okTitle ?? "OK", diff --git a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart index e60383bb..a9dded6f 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart @@ -49,7 +49,12 @@ class _MaintenanceRequestFormState extends State with Si bool isUpdate = requestDetailProvider.activityMaintenanceHelperModel?.id != 0; return Scaffold( backgroundColor: AppColor.neutral110, - appBar: const DefaultAppBar(title: "CM Activity"), + appBar: DefaultAppBar( + title: "CM Activity", + onWillPopScope: () { + save(requestDetailProvider); + }, + ), body: Stack( children: [ DefaultTabController( @@ -97,48 +102,49 @@ class _MaintenanceRequestFormState extends State with Si label: requestDetailProvider.activityMaintenanceHelperModel?.id != 0 ? context.translation.update : context.translation.addActivity, // Use the dynamic label buttonColor: AppColor.primary10, onPressed: () async { - //TODO add this as dropdown not added in design yet Bhaa need to confirm with hussain then. - // requestDetailProvider.activityMaintenanceHelperModel?.lastSituationId = 282; - - if (validate(model: requestDetailProvider.activityMaintenanceHelperModel!)) { - requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers = requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers ?? []; - requestDetailProvider.activityMaintenanceHelperModel?.timerModelList?.forEach((timer) { - int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; - requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers?.add( - ActivityMaintenanceTimers( - id: 0, - startTime: timer.startAt!.toIso8601String(), // Handle potential null - endTime: timer.endAt?.toIso8601String(), // Handle potential null - workingHours: ((durationInSecond) / 60 / 60), - ), - ); - }); - showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - int status = -1; - if (requestDetailProvider.activityMaintenanceHelperModel?.id == 0) { - status = await requestDetailProvider.createActivityMaintenanceRequest(); - } else { - status = await requestDetailProvider.updateActivityMaintenance(); - } - if (status == 200) { - requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!); - Navigator.pop(context); - Navigator.pop(context); - } else { - Navigator.pop(context); - } - } - - // Handle button press + save(requestDetailProvider); }, ), ), ], ), - ); + ).handlePopScope(context, () { + save(requestDetailProvider); + }); }); } + void save(ServiceRequestDetailProvider requestDetailProvider) async { + if (validate(model: requestDetailProvider.activityMaintenanceHelperModel!)) { + requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers = requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers ?? []; + requestDetailProvider.activityMaintenanceHelperModel?.timerModelList?.forEach((timer) { + int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; + requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers?.add( + ActivityMaintenanceTimers( + id: 0, + startTime: timer.startAt!.toIso8601String(), // Handle potential null + endTime: timer.endAt?.toIso8601String(), // Handle potential null + workingHours: ((durationInSecond) / 60 / 60), + ), + ); + }); + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + int status = -1; + if (requestDetailProvider.activityMaintenanceHelperModel?.id == 0) { + status = await requestDetailProvider.createActivityMaintenanceRequest(); + } else { + status = await requestDetailProvider.updateActivityMaintenance(); + } + if (status == 200) { + requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!); + Navigator.pop(context); + Navigator.pop(context); + } else { + Navigator.pop(context); + } + } + } + bool validate({required ActivityMaintenanceHelperModel model}) { if (model.activityStatus == null) { Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.activityStatus}");