import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:marco/controller/task_planing/report_task_controller.dart'; import 'package:marco/helpers/theme/app_theme.dart'; import 'package:marco/helpers/utils/mixins/ui_mixin.dart'; import 'package:marco/helpers/widgets/my_button.dart'; import 'package:marco/helpers/widgets/my_spacing.dart'; import 'package:marco/helpers/widgets/my_text.dart'; import 'package:marco/helpers/widgets/my_text_style.dart'; class ReportTaskBottomSheet extends StatefulWidget { final Map taskData; final VoidCallback? onReportSuccess; const ReportTaskBottomSheet({super.key, required this.taskData,this.onReportSuccess,}); @override State createState() => _ReportTaskBottomSheetState(); } class _ReportTaskBottomSheetState extends State with UIMixin { late final ReportTaskController controller; @override void initState() { super.initState(); // Initialize the controller with a unique tag (optional) controller = Get.put(ReportTaskController(), tag: widget.taskData['taskId'] ?? UniqueKey().toString()); final taskData = widget.taskData; controller.basicValidator.getController('assigned_date')?.text = taskData['assignedOn'] ?? ''; controller.basicValidator.getController('assigned_by')?.text = taskData['assignedBy'] ?? ''; controller.basicValidator.getController('work_area')?.text = taskData['location'] ?? ''; controller.basicValidator.getController('activity')?.text = taskData['activity'] ?? ''; controller.basicValidator.getController('team_size')?.text = taskData['teamSize']?.toString() ?? ''; controller.basicValidator.getController('assigned')?.text = taskData['assigned'] ?? ''; controller.basicValidator.getController('task_id')?.text = taskData['taskId'] ?? ''; controller.basicValidator.getController('completed_work')?.clear(); controller.basicValidator.getController('comment')?.clear(); } @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), ), child: SingleChildScrollView( padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom + 24, left: 24, right: 24, top: 12, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Drag handle Container( width: 40, height: 4, margin: const EdgeInsets.only(bottom: 12), decoration: BoxDecoration( color: Colors.grey.shade400, borderRadius: BorderRadius.circular(2), ), ), GetBuilder( tag: widget.taskData['taskId'] ?? '', init: controller, builder: (_) { return Form( key: controller.basicValidator.formKey, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 4.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: MyText.titleMedium( "Report Task", fontWeight: 600, ), ), MySpacing.height(16), buildRow( "Assigned Date", controller.basicValidator .getController('assigned_date') ?.text .trim()), buildRow( "Assigned By", controller.basicValidator .getController('assigned_by') ?.text .trim()), buildRow( "Work Area", controller.basicValidator .getController('work_area') ?.text .trim()), buildRow( "Activity", controller.basicValidator .getController('activity') ?.text .trim()), buildRow( "Team Size", controller.basicValidator .getController('team_size') ?.text .trim()), buildRow( "Assigned", "${controller.basicValidator.getController('assigned')?.text.trim()} " "of ${widget.taskData['pendingWork'] ?? '-'} Pending"), Row( children: [ Icon(Icons.work_outline, size: 18, color: Colors.grey[700]), MySpacing.width(8), MyText.titleSmall( "Completed Work:", fontWeight: 600, ), ], ), MySpacing.height(8), TextFormField( validator: (value) { if (value == null || value.trim().isEmpty) { return 'Please enter completed work'; } final completed = int.tryParse(value.trim()); final pending = widget.taskData['pendingWork'] ?? 0; if (completed == null) { return 'Enter a valid number'; } if (completed > pending) { return 'Completed work cannot exceed pending work $pending'; } return null; }, controller: controller.basicValidator .getController('completed_work'), keyboardType: TextInputType.number, decoration: InputDecoration( hintText: "eg: 10", hintStyle: MyTextStyle.bodySmall(xMuted: true), border: outlineInputBorder, enabledBorder: outlineInputBorder, focusedBorder: focusedInputBorder, contentPadding: MySpacing.all(16), isCollapsed: true, floatingLabelBehavior: FloatingLabelBehavior.never, ), ), MySpacing.height(24), Row( children: [ Icon(Icons.comment_outlined, size: 18, color: Colors.grey[700]), MySpacing.width(8), MyText.titleSmall( "Comment:", fontWeight: 600, ), ], ), MySpacing.height(8), TextFormField( validator: controller.basicValidator .getValidation('comment'), controller: controller.basicValidator .getController('comment'), keyboardType: TextInputType.text, decoration: InputDecoration( hintText: "eg: Work done successfully", hintStyle: MyTextStyle.bodySmall(xMuted: true), border: outlineInputBorder, enabledBorder: outlineInputBorder, focusedBorder: focusedInputBorder, contentPadding: MySpacing.all(16), isCollapsed: true, floatingLabelBehavior: FloatingLabelBehavior.never, ), ), MySpacing.height(24), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ MyButton.text( onPressed: () => Navigator.of(context).pop(), padding: MySpacing.xy(20, 16), splashColor: contentTheme.secondary.withAlpha(25), child: MyText.bodySmall('Cancel'), ), MySpacing.width(12), Obx(() { return MyButton( onPressed: controller.reportStatus.value == ApiStatus.loading ? null : () async { if (controller.basicValidator .validateForm()) { await controller.reportTask( projectId: controller.basicValidator .getController('task_id') ?.text ?? '', comment: controller.basicValidator .getController('comment') ?.text ?? '', completedTask: int.tryParse( controller.basicValidator .getController( 'completed_work') ?.text ?? '') ?? 0, checklist: [], reportedDate: DateTime.now(), ); if (widget.onReportSuccess != null) { widget.onReportSuccess!(); } } }, elevation: 0, padding: MySpacing.xy(20, 16), backgroundColor: Colors.blueAccent, borderRadiusAll: AppStyle.buttonRadius.medium, child: controller.reportStatus.value == ApiStatus.loading ? SizedBox( height: 16, width: 16, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( contentTheme.onPrimary), ), ) : MyText.bodySmall( 'Report', color: contentTheme.onPrimary, ), ); }), ], ), ], ), ), ); }, ), ], ), ), ); } Widget buildRow(String label, String? value) { IconData icon; switch (label) { case "Assigned Date": icon = Icons.calendar_today_outlined; break; case "Assigned By": icon = Icons.person_outline; break; case "Work Area": icon = Icons.place_outlined; break; case "Activity": icon = Icons.run_circle_outlined; break; case "Team Size": icon = Icons.group_outlined; break; case "Assigned": icon = Icons.assignment_turned_in_outlined; break; default: icon = Icons.info_outline; } return Padding( padding: const EdgeInsets.only(bottom: 16), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon(icon, size: 18, color: Colors.grey[700]), MySpacing.width(8), MyText.titleSmall( "$label:", fontWeight: 600, ), MySpacing.width(12), Expanded( child: MyText.bodyMedium(value?.isNotEmpty == true ? value! : "-"), ), ], ), ); } }