From aa11d93409d7302e74a0919ed9ec2dd37125e292 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Mon, 23 Jun 2025 13:08:13 +0300 Subject: [PATCH] update user contact info bottomsheet design and statedate time initial value added --- lib/controllers/api_routes/urls.dart | 10 +- .../providers/api/user_provider.dart | 40 ++++++++ .../workorder/work_order_helper_models.dart | 4 +- lib/models/user.dart | 17 ++++ .../service_request_detail_view.dart | 7 ++ .../components/assistant_employee_card.dart | 1 + .../components/internal_request.dart | 1 + .../update_ppm/ppm_external_details_form.dart | 6 ++ .../ppm_wo/update_ppm/update_ppm.dart | 4 +- .../ppm_wo/update_ppm/wo_info_form.dart | 2 + .../components/task_info_widget.dart | 1 + .../update_device_transfer.dart | 1 + .../gas_refill/update_gas_refill_request.dart | 1 + lib/views/pages/user/profile_page.dart | 74 ++------------- .../update_user_contact_info_bottomsheet.dart | 91 +++++++++++++++++++ lib/views/widgets/timer/app_timer.dart | 4 + 16 files changed, 194 insertions(+), 70 deletions(-) create mode 100644 lib/views/pages/user/update_user_contact_info_bottomsheet.dart diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index d4640f05..3379296c 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -4,11 +4,11 @@ class URLs { static const String appReleaseBuildNumber = "16"; // static const host1 = "https://atomsm.hmg.com"; // production url - // static const host1 = "https://atomsmdev.hmg.com"; // local DEV url - static const host1 = "https://atomsmuat.hmg.com"; // local UAT url + static const host1 = "https://atomsmdev.hmg.com"; // local DEV url + // static const host1 = "https://atomsmuat.hmg.com"; // local UAT url - static String _baseUrl = "$_host/mobile"; - // static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis + // static String _baseUrl = "$_host/mobile"; + static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis // static final String _baseUrl = "$_host/mobile"; // host local UAT // static final String _baseUrl = "$_host/v3/mobile"; // v3 for new CM,PM,TM @@ -42,6 +42,8 @@ class URLs { static get getAssetById => "$_baseUrl/Asset/GetAssetById?assetId="; // get static get getModels => "$_baseUrl/ModelDefinition/GetModelDefinitionAsset"; // get ?client=2 static get getAllRequestsAndCount => "$_baseUrl/CallRequest/GetAllRequestsAndCount"; // get + static get updateUserContactInformation => "$_baseUrl/Account/UpdateContactInfo"; // get + //service request new flow urls. static get nurseDashboardCountUrl => '$_baseUrl/ServiceRequest/GetDashboardNurseCount'; diff --git a/lib/controllers/providers/api/user_provider.dart b/lib/controllers/providers/api/user_provider.dart index 5fd24da2..736f5246 100644 --- a/lib/controllers/providers/api/user_provider.dart +++ b/lib/controllers/providers/api/user_provider.dart @@ -3,9 +3,11 @@ import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:http/http.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/new_models/general_response_model.dart'; import 'package:test_sa/models/new_models/update_password.dart'; import 'package:test_sa/models/new_models/verify_otp_model.dart'; @@ -35,6 +37,7 @@ class UserProvider extends ChangeNotifier { VerifyOtpModel _verifyOtpModel = VerifyOtpModel(); SwipeTransaction _swipeTransactionModel = SwipeTransaction(); List _swipeHistory = []; + UserContactInfoModel userInfoModel =UserContactInfoModel(); SwipeTransaction get swipeTransactionModel => _swipeTransactionModel; @@ -263,6 +266,43 @@ class UserProvider extends ChangeNotifier { return -1; } } + // Future updateContactInfo({required UserContactInfoModel model}) async { + // Response response; + // try { + // isLoading = true; + // notifyListeners(); + // response = await ApiManager.instance.put('${URLs.updateUserContactInformation}/userId?userId=${model.userId}', body: model.toJson()); + // isLoading = false; + // notifyListeners(); + // return response.statusCode; + // } catch (e) { + // log("engineer mark as fixed [error] : $e"); + // isLoading = false; + // notifyListeners(); + // return -1; + // } + // } + + Future updateContactInfo({ + required BuildContext context, + }) async { + late Response response; + try { + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + response = await ApiManager.instance.put('${URLs.updateUserContactInformation}/userId?userId=${userInfoModel.userId}', body: userInfoModel.toJson()); + if (response.statusCode >= 200 && response.statusCode < 300) { + Navigator.pop(context); + } else { + print('i am here..'); + Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest} :${json.decode(response.body)['message']}"); + } + Navigator.pop(context); + } catch (error) { + notifyListeners(); + Navigator.pop(context); + print(error); + } + } Future makeSwipe({required Swipe model}) async { isLoading = true; diff --git a/lib/models/helper_data_models/workorder/work_order_helper_models.dart b/lib/models/helper_data_models/workorder/work_order_helper_models.dart index 917760c6..24e2fc20 100644 --- a/lib/models/helper_data_models/workorder/work_order_helper_models.dart +++ b/lib/models/helper_data_models/workorder/work_order_helper_models.dart @@ -57,16 +57,18 @@ class WorkOrderAttachments { int? id; String? name; - + String ?createdBy; WorkOrderAttachments.fromJson(Map json) { id = json['id']; name = json['name']; + createdBy = json['createdBy']; } Map toJson() { final Map data = {}; data['id'] = id; data['name'] = name; + data['createdBy'] = createdBy; return data; } } diff --git a/lib/models/user.dart b/lib/models/user.dart index dda5d765..b7a50619 100644 --- a/lib/models/user.dart +++ b/lib/models/user.dart @@ -300,3 +300,20 @@ class AssetGroup { return data; } } + +class UserContactInfoModel { + dynamic userId; + String? email; + String? phoneNo; + String? extensionNo; + + UserContactInfoModel({this.email, this.phoneNo, this.extensionNo, this.userId}); + + Map toJson() { + return { + 'email': email, + 'mobileNumber': phoneNo, + 'extensionNo': extensionNo, + }; + } +} diff --git a/lib/modules/cm_module/views/components/service_request_detail_view.dart b/lib/modules/cm_module/views/components/service_request_detail_view.dart index 2fb4ce2e..48bf552b 100644 --- a/lib/modules/cm_module/views/components/service_request_detail_view.dart +++ b/lib/modules/cm_module/views/components/service_request_detail_view.dart @@ -318,6 +318,13 @@ class _ServiceRequestDetailViewState extends State { ), ], //workOrderNextStepStatus == WorkOrderNextStepEnum.assignToMe + + // if (activity.activitySparePart?.acitiySparePartAttachments?.isNotEmpty ?? false) ...[ + // 2.height, + // const Divider().defaultStyle(context), + // FilesList(images: activity.activitySparePart!.acitiySparePartAttachments!.map((toElement) => URLs.getFileUrl(toElement.name!)!).toList()), + // ], + if (!requestProvider.isReadOnlyRequest && userProvider.user?.type == UsersTypes.engineer && workOrder.nextStep?.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) ...[ 8.height, const Divider().defaultStyle(context), diff --git a/lib/modules/cm_module/views/forms/maintenance_request/components/assistant_employee_card.dart b/lib/modules/cm_module/views/forms/maintenance_request/components/assistant_employee_card.dart index a999addc..04656fe2 100644 --- a/lib/modules/cm_module/views/forms/maintenance_request/components/assistant_employee_card.dart +++ b/lib/modules/cm_module/views/forms/maintenance_request/components/assistant_employee_card.dart @@ -106,6 +106,7 @@ class _AssistantEmployeeCardState extends State { label: context.translation.startTime, hideShadow: true, backgroundColor: AppColor.neutral100, + from:requestDetailProvider.currentWorkOrder?.data?.requestedDate, date: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, formatDateWithTime: true, onDatePicker: (selectedDate) { diff --git a/lib/modules/cm_module/views/forms/maintenance_request/components/internal_request.dart b/lib/modules/cm_module/views/forms/maintenance_request/components/internal_request.dart index 117c2a5d..92d42146 100644 --- a/lib/modules/cm_module/views/forms/maintenance_request/components/internal_request.dart +++ b/lib/modules/cm_module/views/forms/maintenance_request/components/internal_request.dart @@ -115,6 +115,7 @@ class _InternalMaintenanceRequestState extends State timer: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel, enabled: enableTimer, pickerTimer: requestDetailProvider.activityMaintenanceHelperModel?.activityTimePicker, + pickerFromDate: requestDetailProvider.currentWorkOrder?.data?.requestedDate, onPick: (time) { requestDetailProvider.activityMaintenanceHelperModel?.activityTimePicker = time; }, diff --git a/lib/modules/pm_module/ppm_wo/update_ppm/ppm_external_details_form.dart b/lib/modules/pm_module/ppm_wo/update_ppm/ppm_external_details_form.dart index 757a7f90..406431fd 100644 --- a/lib/modules/pm_module/ppm_wo/update_ppm/ppm_external_details_form.dart +++ b/lib/modules/pm_module/ppm_wo/update_ppm/ppm_external_details_form.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/ppm_provider.dart'; @@ -89,12 +91,14 @@ class ExternalDetailItem extends StatefulWidget { final PreventiveVisitSuppliers model; final VoidCallback onRemove; final int index; + final String ?createdDate; const ExternalDetailItem({ Key? key, required this.model, required this.onRemove, required this.index, + this.createdDate, }) : super(key: key); @override @@ -183,6 +187,7 @@ class _ExternalDetailItemState extends State { backgroundColor: AppColor.neutral100, date: widget.model.startDateTime, formatDateWithTime: true, + from:DateTime.tryParse(_ppmProvider?.planPreventiveVisit?.creationDate??'') , onDatePicker: (selectedDate) { showTimePicker( context: context, @@ -220,6 +225,7 @@ class _ExternalDetailItemState extends State { backgroundColor: AppColor.neutral100, date: widget.model.endDateTime, formatDateWithTime: true, + from:DateTime.tryParse(_ppmProvider?.planPreventiveVisit?.creationDate??'') , onDatePicker: (selectedDate) { showTimePicker( context: context, diff --git a/lib/modules/pm_module/ppm_wo/update_ppm/update_ppm.dart b/lib/modules/pm_module/ppm_wo/update_ppm/update_ppm.dart index efb73d24..20a66f47 100644 --- a/lib/modules/pm_module/ppm_wo/update_ppm/update_ppm.dart +++ b/lib/modules/pm_module/ppm_wo/update_ppm/update_ppm.dart @@ -185,7 +185,9 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { controller: _tabController, children: [ if (ppmProvider.totalTabs == 4) ...[ - PpmExternalDetailsForm(models: _planPreventiveVisit.preventiveVisitSuppliers), + PpmExternalDetailsForm( + models: _planPreventiveVisit.preventiveVisitSuppliers, + ), ], PpmCalibrationToolsForm(models: _planPreventiveVisit.preventiveVisitCalibrations), PpmPMKitsForm(models: _planPreventiveVisit.preventiveVisitKits, assetId: _planPreventiveVisit.asset?.id), diff --git a/lib/modules/pm_module/ppm_wo/update_ppm/wo_info_form.dart b/lib/modules/pm_module/ppm_wo/update_ppm/wo_info_form.dart index 403ec7fa..672ded7a 100644 --- a/lib/modules/pm_module/ppm_wo/update_ppm/wo_info_form.dart +++ b/lib/modules/pm_module/ppm_wo/update_ppm/wo_info_form.dart @@ -184,6 +184,7 @@ class _WoInfoFormState extends State { hideShadow: true, backgroundColor: AppColor.neutral100, date: widget.planPreventiveVisit.acutalDateOfVisit, + from: DateTime.tryParse(widget.planPreventiveVisit.creationDate??''), formatDateWithTime: true, onDatePicker: (selectedDate) { showTimePicker( @@ -355,6 +356,7 @@ class _WoInfoFormState extends State { width: double.infinity, timer: widget.planPreventiveVisit.tbsTimer, pickerTimer: widget.planPreventiveVisit.ppMTimePicker, + pickerFromDate: DateTime.tryParse(widget.planPreventiveVisit.creationDate??''), onPick: (time) { widget.planPreventiveVisit.ppMTimePicker = time; }, diff --git a/lib/modules/pm_module/recurrent_wo/components/task_info_widget.dart b/lib/modules/pm_module/recurrent_wo/components/task_info_widget.dart index 4e9f52e8..0264d52f 100644 --- a/lib/modules/pm_module/recurrent_wo/components/task_info_widget.dart +++ b/lib/modules/pm_module/recurrent_wo/components/task_info_widget.dart @@ -83,6 +83,7 @@ class RecurrentTaskInfoWidget extends StatelessWidget { borderRadius: BorderRadius.circular(10), ), pickerTimer: model?.recurrentWoTimePicker, + pickerFromDate: DateTime.tryParse(model?.scheduleDate ?? ''), onPick: (time) { model?.recurrentWoTimePicker = time; }, diff --git a/lib/views/pages/device_transfer/update_device_transfer.dart b/lib/views/pages/device_transfer/update_device_transfer.dart index 90254c4f..9efbb529 100644 --- a/lib/views/pages/device_transfer/update_device_transfer.dart +++ b/lib/views/pages/device_transfer/update_device_transfer.dart @@ -283,6 +283,7 @@ class _UpdateDeviceTransferState extends State { AppTimer( label: context.translation.workingHours, timer: _formModel.tbsTimer, + pickerFromDate: DateTime.tryParse(widget.model.createdDate??''), width: double.infinity, enabled: isTimerEnable, decoration: BoxDecoration( diff --git a/lib/views/pages/user/gas_refill/update_gas_refill_request.dart b/lib/views/pages/user/gas_refill/update_gas_refill_request.dart index 67b69981..c63b8851 100644 --- a/lib/views/pages/user/gas_refill/update_gas_refill_request.dart +++ b/lib/views/pages/user/gas_refill/update_gas_refill_request.dart @@ -286,6 +286,7 @@ class _UpdateGasRefillRequestState extends State { AppTimer( label: context.translation.workingHours, timer: _formModel.timer, + pickerFromDate: DateTime.tryParse(widget.gasRefillModel?.createdDate??''), pickerTimer: _formModel.gasRefillTimePicker, onPick: (time) { _formModel.gasRefillTimePicker = time; diff --git a/lib/views/pages/user/profile_page.dart b/lib/views/pages/user/profile_page.dart index 6d705337..ca97c54c 100644 --- a/lib/views/pages/user/profile_page.dart +++ b/lib/views/pages/user/profile_page.dart @@ -13,7 +13,7 @@ import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/user.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; -import 'package:test_sa/views/pages/user/update_profile_info_bottmsheet.dart'; +import 'package:test_sa/views/pages/user/update_user_contact_info_bottomsheet.dart'; import '../../../new_views/app_style/app_color.dart'; @@ -177,6 +177,12 @@ class _ProfilePageState extends State { label: "Update Information", buttonColor: AppColor.neutral50, onPressed: () { + _userProvider.userInfoModel = UserContactInfoModel( + userId: _user.userID, + email: _user.email, + phoneNo: _user.phoneNumber, + extensionNo: _user.extensionNo + ); showModalBottomSheet( context: context, isScrollControlled: true, @@ -191,57 +197,16 @@ class _ProfilePageState extends State { ), child: ConstrainedBox( constraints: BoxConstraints( - maxHeight: MediaQuery.of(context).size.height * 0.9, + maxHeight: MediaQuery.of(context).size.height * 0.4, ), - child: SingleChildScrollView( - child: UpdateProfileInfoBottmsheet( - userInfoModel: UpdateUserInfoModel( - email: _user.email, - phoneNo: _user.phoneNumber, - extensionNo: _user.extensionNo, - ), - ), + child: const UpdateUserContactInfoBottomsheet( + ), ), ); }, ); - // showModalBottomSheet( - // context: context, - // isScrollControlled: true, - // shape: const RoundedRectangleBorder( - // borderRadius: BorderRadius.vertical( - // top: Radius.circular(20), - // ), - // ), - // clipBehavior: Clip.antiAliasWithSaveLayer, - // builder: (BuildContext context) { - // return Padding( - // padding: EdgeInsets.only( - // bottom: MediaQuery.of(context).viewInsets.bottom, - // ), - // child: DraggableScrollableSheet( - // // initialChildSize: 0.6, // You can adjust this as needed - // minChildSize: 0.3, - // maxChildSize: 0.9, - // expand: false, - // builder: (context, scrollController) { - // return SingleChildScrollView( - // controller: scrollController, - // child: UpdateProfileInfoBottmsheet( - // userInfoModel: UpdateUserInfoModel( - // email: _user.email, - // phoneNo: _user.phoneNumber, - // extensionNo: _user.extensionNo, - // ), - // ), - // ); - // }, - // ), - // ); - // }, - // ); }, ) ], @@ -404,22 +369,3 @@ class _ProfilePageState extends State { ); } } - -class UpdateUserInfoModel { - dynamic userId; - String? email; - String? phoneNo; - String? extensionNo; - - UpdateUserInfoModel({this.email, this.phoneNo, this.extensionNo, this.userId}); - - Map toJson() { - return { - //need this to update user info.. - 'userId': userId, - 'email': email, - 'phoneNo': phoneNo, - 'extensionNo': extensionNo, - }; - } -} diff --git a/lib/views/pages/user/update_user_contact_info_bottomsheet.dart b/lib/views/pages/user/update_user_contact_info_bottomsheet.dart new file mode 100644 index 00000000..945cc825 --- /dev/null +++ b/lib/views/pages/user/update_user_contact_info_bottomsheet.dart @@ -0,0 +1,91 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_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'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; + +class UpdateUserContactInfoBottomsheet extends StatelessWidget { + const UpdateUserContactInfoBottomsheet({super.key}); + + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, userProvider,child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SingleChildScrollView( + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 16.toScreenHeight), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + AppTextFormField( + labelText: "Email", + backgroundColor: AppColor.neutral100, + initialValue: userProvider.userInfoModel.email, + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + showShadow: false, + onChange: (value) { + userProvider.userInfoModel.email = value; + }, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + AppTextFormField( + labelText: "Phone Number", + backgroundColor: AppColor.neutral100, + initialValue: userProvider.userInfoModel.phoneNo, + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + textInputType: TextInputType.number, + showShadow: false, + onChange: (value) { + userProvider.userInfoModel.phoneNo = value; + }, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + AppTextFormField( + labelText: "Extension No", + backgroundColor: AppColor.neutral100, + initialValue: userProvider.userInfoModel.extensionNo, + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + textInputType: TextInputType.text, + showShadow: false, + onChange: (value) { + userProvider.userInfoModel.extensionNo = value; + }, + style: Theme.of(context).textTheme.titleMedium, + ), + ], + ), + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 16.toScreenHeight), + color: AppColor.white10, + child: AppFilledButton( + label: "Update", + buttonColor: AppColor.neutral50, + onPressed: () async { + //TODO update user details and save to preferences.. + // await userProvider.updateContactInfo(context: context); + // Navigator.pop(context); + }, + ), + ), + ], + ); + } + ); + } +} diff --git a/lib/views/widgets/timer/app_timer.dart b/lib/views/widgets/timer/app_timer.dart index a4e15fd7..daaad568 100644 --- a/lib/views/widgets/timer/app_timer.dart +++ b/lib/views/widgets/timer/app_timer.dart @@ -17,6 +17,7 @@ class AppTimer extends StatefulWidget { final TimerModel? timer; final Future Function(TimerModel)? onChange; final TimerModel? pickerTimer; + final DateTime? pickerFromDate; final Function(TimerModel?)? onPick; final TextStyle? style; final BoxDecoration? decoration; @@ -35,6 +36,7 @@ class AppTimer extends StatefulWidget { this.decoration, this.width, this.pickerTimer, + this.pickerFromDate, this.onPick, this.timerProgress, this.enabled = true, @@ -162,6 +164,7 @@ class _AppTimerState extends State { hideShadow: true, backgroundColor: AppColor.neutral100, date: _pickerStartAt, + from: widget.pickerFromDate, enable: _tempPickerTimer == null, formatDateWithTime: true, onDatePicker: (selectedDate) { @@ -182,6 +185,7 @@ class _AppTimerState extends State { hideShadow: true, backgroundColor: AppColor.neutral100, enable: _pickerStartAt != null, + from:_pickerStartAt, date: _pickerEndAt, formatDateWithTime: true, onDatePicker: (selectedDate) {