diff --git a/lib/modules/medical_gas_inspection/create_medical_gas_request_page.dart b/lib/modules/medical_gas_inspection/create_medical_gas_request_page.dart index f5674dad..88813f58 100644 --- a/lib/modules/medical_gas_inspection/create_medical_gas_request_page.dart +++ b/lib/modules/medical_gas_inspection/create_medical_gas_request_page.dart @@ -45,6 +45,7 @@ class _CreateMedicalGasRequestPageState extends State(context, listen: false).reset(); medicalGasInspectionProvider = Provider.of(context, listen: false); + siteProvider = Provider.of(context, listen: false); _populateFormData(); } _populateFormData() { + if (siteProvider.items.isEmpty) { + siteProvider.reset(); + } if (widget.dataModel != null) { MedicalGasDataModel dataModel = widget.dataModel!; _medicalGasFormModel = MedicalGasFormModel( @@ -97,7 +102,7 @@ class _CreateMedicalGasRequestPageState extends State { late MedicalGasInspectionProvider medicalGasInspectionProvider; bool pressureTestAcknowledgement = false; bool leakTestAcknowledgement = false; + final GlobalKey _formKey = GlobalKey(); + final GlobalKey _scaffoldKey = GlobalKey(); // List selectedItemList = []; @@ -56,7 +58,7 @@ class _UpdateDeliveryNotesState extends State { MedicalGasDataModel dataModel = widget.dataModel!; formModel = DeliveryNotesFormModel( id: dataModel.id, - deliveredItemList: dataModel.requestDetailDtos, + deliveredItemList: dataModel.requestDetailDtos.where((item) => item.requestedQuantity! > 0).toList(), isInspectedGasLeak: dataModel.isInspectedGasLeak, isPressureChecked: dataModel.isPressureChecked, deliveredDate: dataModel.deliveredDate, @@ -79,207 +81,210 @@ class _UpdateDeliveryNotesState extends State { // }, ), body: SafeArea( - child: Column( - children: [ - ListView( - padding: const EdgeInsets.all(16), - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ADatePicker( - label: "Delivered Date", - hideShadow: true, - backgroundColor: AppColor.fieldBgColor(context), - from: DateTime.now().subtract(const Duration(days: 365 * 3)), - date: formModel.deliveredDate, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - if (selectedTime != null) { - formModel.deliveredDate = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute); - setState(() {}); - } - }); - }, - ), - 16.height, - AppTextFormField( - initialValue: formModel.deliveryNoteNumber, - labelText: "Delivery Notes", - validator: (value) { - if ((value ?? "").isEmpty) return "Mandatory"; - return null; - }, - backgroundColor: AppColor.fieldBgColor(context), - labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), - floatingLabelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), - showShadow: false, - textInputType: TextInputType.multiline, - makeMultiLinesNull: true, - onChange: (value) { - formModel.deliveryNoteNumber = value; - }, - ), - 16.height, + child: Form( + key: _formKey, + child: Column( + children: [ + ListView( + padding: const EdgeInsets.all(16), + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ADatePicker( + label: "Delivered Date", + hideShadow: true, + backgroundColor: AppColor.fieldBgColor(context), + from: DateTime.now().subtract(const Duration(days: 365 * 3)), + date: formModel.deliveredDate, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + if (selectedTime != null) { + formModel.deliveredDate = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute); + setState(() {}); + } + }); + }, + ), + 16.height, + AppTextFormField( + initialValue: formModel.deliveryNoteNumber, + labelText: "Delivery Notes", + // validator: (value) { + // if ((value ?? "").isEmpty) return "Delivery Notes Required"; + // return null; + // }, + backgroundColor: AppColor.fieldBgColor(context), + labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), + floatingLabelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), + showShadow: false, + textInputType: TextInputType.multiline, + makeMultiLinesNull: true, + onChange: (value) { + formModel.deliveryNoteNumber = value; + }, + ), + 16.height, - //Older design code - // MultipleItemDropDownMenu( - // context: context, - // showAsBottomSheet: true, - // backgroundColor: AppColor.neutral100, - // showShadow: false, - // showCancel: true, - // requestById: context.userProvider.user?.clientId, - // title: 'Delivered Items'.addTranslation, - // staticData: formModel.deliveredItemList, - // initialValue: selectedItemList, - // onSelect: (value) { - // if ((value ?? []).isNotEmpty) { - // WidgetsBinding.instance.addPostFrameCallback((_) { - // if (!mounted) return; - // setState(() { - // selectedItemList = value ?? []; - // }); - // }); - // } - // }, - // ), - // if (selectedItemList.isNotEmpty) ...[ - // 8.height, - // ListView.separated( - // separatorBuilder: (_, __) => 12.height, - // itemCount: selectedItemList.length, - // shrinkWrap: true, - // physics: const NeverScrollableScrollPhysics(), - // itemBuilder: (context, index) { - // MedicalGasRequestDetailModel model = selectedItemList[index]; - // return AppTextFormField( - // labelText: '${model.name} (Req Qty =${model.requestedQuantity})', - // hintText: 'Enter Delivered Quantity'.addTranslation, - // backgroundColor: AppColor.fieldBgColor(context), - // initialValue: model.deliveredQuantity != null ? model.deliveredQuantity?.toInt().toString() : '', - // textAlign: TextAlign.center, - // enable: true, - // textInputType: TextInputType.number, - // labelStyle: AppTextStyles.textFieldLabelStyle, - // showShadow: false, - // onChange: (value) { - // if (value.isNotEmpty) { - // model.deliveredQuantity = double.tryParse(value); - // } - // }, - // style: Theme.of(context).textTheme.titleMedium, - // ); - // }, - // ) - // ], - if (formModel.deliveredItemList.isNotEmpty) ...[ - _ItemRowLayout( - left: 'Items'.addTranslation.bodyText(context).custom(color: AppColor.textColor(context)), - right: 'Delivered Qty'.addTranslation.bodyText(context).custom(color: AppColor.textColor(context)), + //Older design code + // MultipleItemDropDownMenu( + // context: context, + // showAsBottomSheet: true, + // backgroundColor: AppColor.neutral100, + // showShadow: false, + // showCancel: true, + // requestById: context.userProvider.user?.clientId, + // title: 'Delivered Items'.addTranslation, + // staticData: formModel.deliveredItemList, + // initialValue: selectedItemList, + // onSelect: (value) { + // if ((value ?? []).isNotEmpty) { + // WidgetsBinding.instance.addPostFrameCallback((_) { + // if (!mounted) return; + // setState(() { + // selectedItemList = value ?? []; + // }); + // }); + // } + // }, + // ), + // if (selectedItemList.isNotEmpty) ...[ + // 8.height, + // ListView.separated( + // separatorBuilder: (_, __) => 12.height, + // itemCount: selectedItemList.length, + // shrinkWrap: true, + // physics: const NeverScrollableScrollPhysics(), + // itemBuilder: (context, index) { + // MedicalGasRequestDetailModel model = selectedItemList[index]; + // return AppTextFormField( + // labelText: '${model.name} (Req Qty =${model.requestedQuantity})', + // hintText: 'Enter Delivered Quantity'.addTranslation, + // backgroundColor: AppColor.fieldBgColor(context), + // initialValue: model.deliveredQuantity != null ? model.deliveredQuantity?.toInt().toString() : '', + // textAlign: TextAlign.center, + // enable: true, + // textInputType: TextInputType.number, + // labelStyle: AppTextStyles.textFieldLabelStyle, + // showShadow: false, + // onChange: (value) { + // if (value.isNotEmpty) { + // model.deliveredQuantity = double.tryParse(value); + // } + // }, + // style: Theme.of(context).textTheme.titleMedium, + // ); + // }, + // ) + // ], + if (formModel.deliveredItemList.isNotEmpty) ...[ + _ItemRowLayout( + left: 'Items'.addTranslation.bodyText(context).custom(color: AppColor.textColor(context)), + right: 'Delivered Qty'.addTranslation.bodyText(context).custom(color: AppColor.textColor(context)), + ), + 8.height, + ListView.separated( + separatorBuilder: (_, __) => 12.height, + itemCount: formModel.deliveredItemList.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + MedicalGasRequestDetailModel model = formModel.deliveredItemList[index]; + return itemQuantityFieldWidget(index: index, model: model, context: context); + }, + ) + ], + 16.height, + + AttachmentPicker( + label: 'Upload Attachment', + attachment: formModel.attachments, + buttonColor: AppColor.primary10, + // showAsListView: true, + onlyImages: false, + buttonIcon: 'attachment_icon'.toSvgAsset( + color: AppColor.primary10, + ), + ), + 16.height, + //should create a reusable widget. + Row( + children: [ + Checkbox( + value: formModel.isPressureChecked, + visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0), + activeColor: AppColor.blueStatus(context), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + onChanged: (value) { + setState(() { + formModel.isPressureChecked = value!; + }); + }), + 12.width, + "I Acknowledge that the received medical gases cylinders have been tested for pressure." + .addTranslation + .bodyText(context) + .custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral120) + .expanded, + ], ), 8.height, - ListView.separated( - separatorBuilder: (_, __) => 12.height, - itemCount: formModel.deliveredItemList.length, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - MedicalGasRequestDetailModel model = formModel.deliveredItemList[index]; - return itemQuantityFieldWidget(index: index, model: model, context: context); - }, - ) + Row( + // mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Checkbox( + value: formModel.isInspectedGasLeak, + visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0), + activeColor: AppColor.blueStatus(context), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + onChanged: (value) { + setState(() { + formModel.isInspectedGasLeak = value!; + }); + }), + 12.width, + "I Acknowledge that the received medical gases cylinders have been inspected for leak test." + .addTranslation + .bodyText(context) + .custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral120) + .expanded, + ], + ), ], - 16.height, - - AttachmentPicker( - label: 'Upload Attachment', - attachment: formModel.attachments, + ).toShadowContainer(context, padding: 12), + ], + ).expanded, + FooterActionButton.footerContainer( + context: context, + child: Row( + children: [ + AppFilledButton( buttonColor: AppColor.primary10, - // showAsListView: true, - onlyImages: false, - buttonIcon: 'attachment_icon'.toSvgAsset( - color: AppColor.primary10, - ), - ), - 16.height, - //should create a reusable widget. - Row( - children: [ - Checkbox( - value: formModel.isPressureChecked, - visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0), - activeColor: AppColor.blueStatus(context), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - onChanged: (value) { - setState(() { - formModel.isPressureChecked = value!; - }); - }), - 12.width, - "I Acknowledge that the received medical gases cylinders have been tested for pressure." - .addTranslation - .bodyText(context) - .custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral120) - .expanded, - ], - ), - 8.height, - Row( - // mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Checkbox( - value: formModel.isInspectedGasLeak, - visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0), - activeColor: AppColor.blueStatus(context), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - onChanged: (value) { - setState(() { - formModel.isInspectedGasLeak = value!; - }); - }), - 12.width, - "I Acknowledge that the received medical gases cylinders have been inspected for leak test." - .addTranslation - .bodyText(context) - .custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral120) - .expanded, - ], - ), + label: 'Save'.addTranslation, + onPressed: () { + _update(context: context); + }, + // buttonColor: AppColor.primary10, + ).expanded, + 8.width, + AppFilledButton( + buttonColor: AppColor.primary10, + label: 'Submit'.addTranslation, + onPressed: () { + _update(context: context, isSubmitted: true); + }, + // buttonColor: AppColor.primary10, + ).expanded, ], - ).toShadowContainer(context, padding: 12), - ], - ).expanded, - FooterActionButton.footerContainer( - context: context, - child: Row( - children: [ - AppFilledButton( - buttonColor: AppColor.primary10, - label: 'Save'.addTranslation, - onPressed: () { - _update(context: context); - }, - // buttonColor: AppColor.primary10, - ).expanded, - 8.width, - AppFilledButton( - buttonColor: AppColor.primary10, - label: 'Submit'.addTranslation, - onPressed: () { - _update(context: context, isSubmitted: true); - }, - // buttonColor: AppColor.primary10, - ).expanded, - ], + ), ), - ), - ], + ], + ), ), )); // .handlePopScope( @@ -290,6 +295,24 @@ class _UpdateDeliveryNotesState extends State { } void _update({required BuildContext context, bool isSubmitted = false}) async { + if (!_formKey.currentState!.validate()) return; + if (formModel.deliveredDate == null) { + 'Delivered Date Required'.addTranslation.showToast; + return; + } + if (formModel.deliveryNoteNumber == null) { + 'Delivery Notes Required'.addTranslation.showToast; + return; + } + if (formModel.isPressureChecked == null || formModel.isPressureChecked == false) { + 'Please acknowledge cylinders are tested for pressure'.addTranslation.showToast; + return; + } + if (formModel.isInspectedGasLeak == null || formModel.isInspectedGasLeak == false) { + 'Please acknowledge cylinders have been inspected for leak test'.addTranslation.showToast; + return; + } + _formKey.currentState?.save(); formModel.gasDeliveredQuantityDtos = []; formModel.isSubmitted = isSubmitted; for (var item in formModel.deliveredItemList) { @@ -331,7 +354,7 @@ class _UpdateDeliveryNotesState extends State { color: context.isDark ? Colors.white : AppColor.white936, fontWeight: FontWeight.w500, ), - 'Req Qty ${model.requestedQuantity}'.bodyText2(context).custom( + 'Req Qty ${model.requestedQuantity?.toStringAsFixed(0)}'.bodyText2(context).custom( color: context.isDark ? Colors.white : AppColor.white936, fontWeight: FontWeight.w500, ), @@ -357,16 +380,32 @@ class _UpdateDeliveryNotesState extends State { return null; }, decoration: InputDecoration( - contentPadding: EdgeInsets.symmetric(horizontal: 5.toScreenWidth), + isDense: true, + contentPadding: EdgeInsets.symmetric( + horizontal: 5.toScreenWidth, + vertical: 6, // keeps normal height ~30 + ), filled: true, fillColor: AppColor.fieldBgColor(context), - constraints: BoxConstraints( - maxHeight: 30.toScreenHeight, - ), border: border, enabledBorder: border, focusedBorder: border, + errorStyle: const TextStyle( + height: 1.2, // controls extra height when error appears + fontSize: 12, + ), ), + // decoration: InputDecoration( + // contentPadding: EdgeInsets.symmetric(horizontal: 5.toScreenWidth), + // filled: true, + // fillColor: AppColor.fieldBgColor(context), + // constraints: BoxConstraints( + // maxHeight: 40.toScreenHeight, + // ), + // border: border, + // enabledBorder: border, + // focusedBorder: border, + // ), onChanged: (value) { model.deliveredQuantity = int.tryParse(value); }, @@ -387,7 +426,7 @@ class _ItemRowLayout extends StatelessWidget { @override Widget build(BuildContext context) { return Row( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded(child: left), // Items column SizedBox(