// UI: Cleaner Search Details View import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_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/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/views/widgets/qr/scan_qr.dart'; import '../models/cleaner_task_search_result.dart'; import '../provider/cleaner_provider.dart'; import '../../pm_module/recurrent_wo/recurrent_work_order_view.dart'; import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; class CleanerSearchDetailsView extends StatefulWidget { static const String routeName = '/cleaner_search_details'; final int requestId; final CleanerTaskSearchResult? taskResult; const CleanerSearchDetailsView({ Key? key, required this.requestId, this.taskResult, }) : super(key: key); @override _CleanerSearchDetailsViewState createState() => _CleanerSearchDetailsViewState(); } class _CleanerSearchDetailsViewState extends State { late CleanerProvider _cleanerProvider; bool _isQRScanned = false; CleanerTaskSearchResult? _taskData; bool _isLoading = false; @override void initState() { super.initState(); _cleanerProvider = Provider.of(context, listen: false); _taskData = widget.taskResult; WidgetsBinding.instance.addPostFrameCallback((_) { getInitialData(); }); } Future getInitialData() async { // If taskResult is null, fetch data from recurrent work order API if (widget.taskResult == null) { setState(() { _isLoading = true; }); try { final allRequestsProvider = Provider.of(context, listen: false); await allRequestsProvider.getRecurrentWoById(id: widget.requestId); // Map RecurrentWoData to CleanerTaskSearchResult if (allRequestsProvider.recurrentWoData != null) { final recurrentData = allRequestsProvider.recurrentWoData!; _taskData = CleanerTaskSearchResult( id: recurrentData.id, taskNo: recurrentData.taskNo, siteName: recurrentData.site?.siteName, buildingName: recurrentData.building?.name, floorName: recurrentData.floor?.name, departmentName: recurrentData.department?.name, roomName: recurrentData.room?.name, locationDescription: null, createdDate: recurrentData.scheduleDate, ); } } catch (e) { debugPrint('Error fetching recurrent work order: $e'); } finally { setState(() { _isLoading = false; }); } } else { await _cleanerProvider.getCleanerRequestById(id: widget.requestId); } } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Theme.of(context).scaffoldBackgroundColor, appBar: DefaultAppBar( title: 'Request Details'.addTranslation, onBackPress: () => Navigator.pop(context), ), body: _isLoading ? const Center(child: CircularProgressIndicator()) : SafeArea( child: Selector( selector: (_, model) => model.isLoading, builder: (_, isLoading, __) { if (isLoading) { return const Center(child: CircularProgressIndicator()); } return Column( children: [ SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildCleanerRequestDetailCard(context), ], ), ).expanded, FooterActionButton.footerContainer( context: context, child: Column( mainAxisSize: MainAxisSize.min, children: [ if (!_isQRScanned) ...[ Row( children: [ Icon(Icons.info_outline_rounded, size: 16, color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), 8.width, Expanded( child: Text( 'By scanning the QR code you will accept this task'.addTranslation, // textAlign: TextAlign.center, style: AppTextStyles.bodyText.copyWith( color: context.isDark ? AppColor.neutral10 : AppColor.neutral120, ), ), ), ], ), 8.height, ], AppFilledButton( label: _isQRScanned ? 'Update' : 'Scan QR Code', maxWidth: true, buttonColor: AppColor.primary10, onPressed: () async { if (_isQRScanned) { // If QR is already scanned, navigate to recurrent work order view Navigator.of(context).push( MaterialPageRoute( builder: (_) => RecurrentWorkOrderView(taskId: widget.requestId), ), ); } else { // Open QR scanner final result = await Navigator.push( context, MaterialPageRoute( builder: (context) => const ScanQr(), ), ); // If QR code was scanned successfully, check if it matches the room if (result != null && result is String && result.isNotEmpty) { // Show loading indicator showDialog( context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading(), ); // Call the API to check if QR matches the same room final isValid = await CleanerProvider().checkQRSameRoom( planRecurrentTaskId: widget.requestId, qrCode: result, ); // Close loading dialog if (mounted) Navigator.pop(context); if (isValid) { // Update state to show "Update" button instead of navigating if (mounted) { setState(() { _isQRScanned = true; }); } } } } }, ), ], ), ).toShadowContainer(context, padding: 0, showShadow: false, borderRadius: 0), ], ); }, ), ), ); } Widget _buildCleanerRequestDetailCard(BuildContext context) { final taskResult = _taskData; if (taskResult == null) { return const SizedBox(); } return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Task Number and Date Row Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Request Information', style: AppTextStyles.heading4.copyWith( color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, ), ), if (taskResult.createdDate != null) Text( taskResult.createdDate!.toServiceRequestCardFormat, textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), ], ), 8.height, if (taskResult.taskNo != null && taskResult.taskNo!.isNotEmpty) Text( 'Task No: ${taskResult.taskNo!}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), if (taskResult.siteName != null && taskResult.siteName!.isNotEmpty) Text( 'Site: ${taskResult.siteName}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), if (taskResult.buildingName != null && taskResult.buildingName!.isNotEmpty) Text( 'Building: ${taskResult.buildingName}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), if (taskResult.floorName != null && taskResult.floorName!.isNotEmpty) Text( 'Floor: ${taskResult.floorName}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), if (taskResult.departmentName != null && taskResult.departmentName!.isNotEmpty) Text( 'Department: ${taskResult.departmentName}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), if (taskResult.roomName != null && taskResult.roomName!.isNotEmpty) Text( 'Room: ${taskResult.roomName}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), if (taskResult.locationDescription != null && taskResult.locationDescription!.isNotEmpty) Text( 'Location: ${taskResult.locationDescription}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), ], ).expanded, ], ), ], ).paddingOnly(start: 16, end: 16, top: 16, bottom: 8), ], ).toShadowContainer(context, padding: 0); } }