import 'dart:async'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_view_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/covid_get_test_proceedure_resp.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/ui_models/covid_questionnare_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:provider/provider.dart'; import 'package:hmg_patient_app_new/presentation/covid19test/covid_payment_screen.dart'; class CovidReviewScreen extends StatefulWidget { final HospitalsModel selectedHospital; final List qaList; const CovidReviewScreen({super.key, required this.selectedHospital, required this.qaList}); @override State createState() => _CovidReviewScreenState(); } class _CovidReviewScreenState extends State { late HmgServicesViewModel hmgServicesViewModel; bool _acceptedTerms =false; Covid19GetTestProceduresResp? _selectedProcedure; @override void initState() { super.initState(); hmgServicesViewModel = Provider.of(context, listen: false); scheduleMicrotask(() { }); } @override Widget build(BuildContext context) { return CollapsingListView( title: "COVID-19", bottomChild: Consumer(builder: (context, vm, _) { final info = vm.covidPaymentInfo; return Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true, ), child: SizedBox( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (info == null) ...[ // show a placeholder/loading while payment info is null SizedBox(height: 24.h), Center(child: CircularProgressIndicator()), SizedBox(height: 24.h), ] else ...[ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ "Amount before tax".needTranslation.toText18(isBold: true), Utils.getPaymentAmountWithSymbol( (info.patientShareField ?? 0).toString().toText16(isBold: true), AppColors.blackColor, 13, isSaudiCurrency: true), ], ), SizedBox(height: 4.h), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ "Tax Amount".needTranslation.toText14(isBold: true), Utils.getPaymentAmountWithSymbol( (info.patientTaxAmountField ?? 0).toString().toText16(isBold: true), AppColors.blackColor, 13, isSaudiCurrency: true) ], ), SizedBox(height: 18.h), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox( width: 150.h, child: Utils.getPaymentMethods(), ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Utils.getPaymentAmountWithSymbol( (info.patientShareWithTaxField ?? 0).toString().toText24(isBold: true), AppColors.blackColor, 17, isSaudiCurrency: true), ], ), ], ) ], ).paddingOnly(left: 16.h, top: 24.h, right: 16.h, bottom: 0.h), GestureDetector( onTap: () { setState(() { _acceptedTerms = !_acceptedTerms; }); }, child: Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, borderRadius: 12.r, hasShadow: false, ), padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h), child: Row( children: [ Container( width: 20.w, height: 20.h, decoration: BoxDecoration( color: _acceptedTerms ? AppColors.primaryRedColor : AppColors.whiteColor, border: Border.all( color: _acceptedTerms ? AppColors.primaryRedColor : AppColors.greyTextColor.withValues(alpha: 0.3), width: 2, ), borderRadius: BorderRadius.circular(4.r), ), child: _acceptedTerms ? Icon( Icons.check, size: 14.h, color: AppColors.whiteColor, ) : null, ), SizedBox(width: 12.w), Expanded( child: RichText( text: TextSpan( style: TextStyle( fontSize: 14.f, color: AppColors.textColor, fontWeight: FontWeight.w400, ), children: [ const TextSpan(text: "I agree to the "), TextSpan( text: "terms and conditions", style: TextStyle( color: AppColors.primaryRedColor, fontWeight: FontWeight.w600, decoration: TextDecoration.underline, decorationColor: AppColors.primaryRedColor, ), ), ], ), ), ), ], ), ), ), // Two-button layout: Cancel (left) and Next (right) Padding( padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 24.h), child: Row( children: [ Expanded( child: CustomButton( height: 56.h, text: LocaleKeys.cancel.tr(), onPressed: () { Navigator.of(context).pop(); }, backgroundColor: AppColors.secondaryLightRedColor, borderColor: AppColors.secondaryLightRedColor, textColor: AppColors.primaryRedColor, // icon: AppAssets.cancel, // iconColor: AppColors.primaryRedColor, borderRadius: 12.r, ), ), SizedBox(width: 8.h), Expanded( child: CustomButton( height: 56.h, text: "Next".needTranslation, onPressed: () async { // Validate selection and payment info if (_selectedProcedure == null) { showCommonBottomSheetWithoutHeight( context, child: Utils.getErrorWidget(loadingText: "Please select a procedure".needTranslation), callBackFunc: () {}, isFullScreen: false, isCloseButtonVisible: true, ); return; } if (info == null) { // If payment info missing, attempt to fetch LoaderBottomSheet.showLoader(); try { await hmgServicesViewModel.getPaymentInfo(procedureID: _selectedProcedure!.procedureId!); } catch (e) { debugPrint('getPaymentInfo error: $e'); } finally { LoaderBottomSheet.hideLoader(); } if (hmgServicesViewModel.covidPaymentInfo == null) { showCommonBottomSheetWithoutHeight( context, child: Utils.getErrorWidget(loadingText: "Payment information not available".needTranslation), callBackFunc: () {}, isFullScreen: false, isCloseButtonVisible: true, ); return; } } // Compute amount and project/clinic IDs defensively final paymentInfo = hmgServicesViewModel.covidPaymentInfo ?? info!; final double amount = paymentInfo.patientShareWithTaxField ?? (paymentInfo.patientShareField?.toDouble() ?? 0.0); // projectID may be int or string; parse defensively int projectID = 0; try { final p = widget.selectedHospital.mainProjectID; if (p is int) projectID = p; else if (p is String) projectID = int.tryParse(p) ?? 0; } catch (_) {} int clinicID = 0; try { clinicID = int.tryParse(widget.selectedHospital.setupID ?? '') ?? int.tryParse(widget.selectedHospital.iD?.toString() ?? '') ?? 0; } catch (_) {} // Navigate to payment screen Navigator.of(context).push( CustomPageRoute( page: CovidPaymentScreen( amount: amount, projectID: projectID, clinicID: clinicID, procedureId: _selectedProcedure!.procedureId ?? '', taxAmount: paymentInfo.patientTaxAmountField?.toDouble() ?? 0.0, ), ), ); }, backgroundColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedColor, textColor: AppColors.whiteColor, fontSize: 16.f, fontWeight: FontWeight.w500, borderRadius: 12.r, padding: EdgeInsets.symmetric(horizontal: 10.w), // icon: AppAssets.add_icon, // iconColor: AppColors.whiteColor, iconSize: 18.h, ), ), ], ), ) ] ], ), ), ); }), child: SingleChildScrollView( child: Padding( padding: EdgeInsets.all(24.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "Please select the procedure:".toText14( color: AppColors.textColor, weight: FontWeight.w500, ), SizedBox(height: 16.h), Consumer( builder: (context, vm, _) { final procedures = vm.covidTestProcedureList; // ensure default selection is first item (once available) if (_selectedProcedure == null && procedures.isNotEmpty) { WidgetsBinding.instance.addPostFrameCallback((_) { if (mounted) { setState(() { _selectedProcedure = procedures[0]; }); // also fetch payment info for default selection and show loader while loading if (procedures[0].procedureId != null) { LoaderBottomSheet.showLoader(); hmgServicesViewModel .getPaymentInfo(procedureID: procedures[0].procedureId!) .whenComplete(() { LoaderBottomSheet.hideLoader(); }); } } }); } // Use a shrink-wrapped ListView.separated and match prescription styling return Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: false, ), child: Padding( padding: EdgeInsets.symmetric(horizontal: 16.h), child: ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: procedures.length, separatorBuilder: (context, index) => Divider( height: 1.h, thickness: 1.h, color: AppColors.borderOnlyColor.withValues(alpha: 0.05), ).paddingOnly(top:8,bottom:16.h), itemBuilder: (context, index) { final item = procedures[index]; // Let the radio option widget manage its own padding to avoid doubled spacing return _buildRadioOption(value: item, title: item.procedureName ?? ''); }, ).paddingOnly(bottom:16.h) ), ); }, ), ], ), ), ), ); } Widget _buildRadioOption({ required Covid19GetTestProceduresResp value, required String title, }) { final bool isSelected = _selectedProcedure?.procedureId == value.procedureId; return GestureDetector( onTap: () async { setState(() { _selectedProcedure = value; }); // show bottomsheet loader while fetching payment info if (value.procedureId != null) { LoaderBottomSheet.showLoader(); try { await hmgServicesViewModel.getPaymentInfo(procedureID: value.procedureId!, projectID: widget.selectedHospital.mainProjectID); } catch (e) { debugPrint('getPaymentInfo error: $e'); } finally { LoaderBottomSheet.hideLoader(); } } }, child: Row( children: [ Container( width: 20.h, height: 20.h, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: isSelected ? AppColors.primaryRedColor : AppColors.greyTextColor.withValues(alpha: 0.3), width: 2, ), ), child: isSelected ? Center( child: Container( width: 10.h, height: 10.h, decoration: BoxDecoration( shape: BoxShape.circle, color: AppColors.primaryRedColor, ), ), ) : null, ), SizedBox(width: 12.h), Expanded( child: title.toText14( color: AppColors.textColor, weight: FontWeight.w400, ), ), ], ) // Keep only bottom padding here and rely on the surrounding container's left/right inset .paddingOnly(left: 0.h, right: 0.h, top: 0.h, bottom: 12.h), ); } }