import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../core/utils/date_utils.dart' as du; import '../../core/utils/responsive.dart'; import '../../shared/widgets/form_section.dart'; import '../../shared/widgets/form_field_row.dart'; import 'overtime_apply_controller.dart'; class OvertimeApplyPage extends ConsumerStatefulWidget { final String? editId; const OvertimeApplyPage({super.key, this.editId}); @override ConsumerState createState() => _OvertimeApplyPageState(); } class _OvertimeApplyPageState extends ConsumerState { final _reasonController = TextEditingController(); static const _types = ['工作日加班', '休息日加班', '节假日加班']; static const _compensations = ['加班费', '调休']; @override void dispose() { _reasonController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final ctrl = ref.watch(overtimeApplyProvider(widget.editId).notifier); final state = ref.watch(overtimeApplyProvider(widget.editId)); final r = ResponsiveHelper.of(context); return Scaffold( appBar: AppBar( title: Text(widget.editId != null ? '编辑加班' : '加班申请')), body: Column( children: [ Expanded( child: Align(alignment: Alignment.topCenter, child: ConstrainedBox( constraints: BoxConstraints(maxWidth: r.formMaxWidth), child: SingleChildScrollView( padding: const EdgeInsets.symmetric(vertical: 8), child: Column( children: [ FormSection( title: '加班信息', children: [ FormFieldRow( label: '加班类型', value: state.overtime.otType, onTap: () => _showPicker(_types, ctrl.updateType), ), FormFieldRow( label: '补偿方式', value: state.overtime.compensationType, onTap: () => _showPicker(_compensations, ctrl.updateCompensation), ), FormFieldRow( label: '开始时间', value: du.DateUtils.formatDateTime(state.overtime.startTime), onTap: () => _pickDateTime(ctrl.updateStartTime, state.overtime.startTime), ), FormFieldRow( label: '结束时间', value: du.DateUtils.formatDateTime(state.overtime.endTime), onTap: () => _pickDateTime(ctrl.updateEndTime, state.overtime.endTime), ), FormFieldRow( label: '预估工时', value: '${state.overtime.otHours.toStringAsFixed(1)}h', showArrow: false), ], ), FormSection( title: '加班事由', children: [ Padding( padding: const EdgeInsets.all(14), child: TextField( maxLines: 4, decoration: const InputDecoration( hintText: '请详细描述加班内容和原因…', border: OutlineInputBorder(), ), onChanged: ctrl.updateReason, ), ), ], ), ], ), ), ), ), ), _buildBottomButtons(ctrl, state), ], ), ); } Widget _buildBottomButtons(OvertimeApplyController ctrl, OvertimeApplyState state) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white, boxShadow: [BoxShadow(color: Colors.black.withValues(alpha: 0.05), blurRadius: 4, offset: const Offset(0, -1))], ), child: Row( children: [ Expanded( child: OutlinedButton( onPressed: state.isSubmitting ? null : () async { await ctrl.saveDraft(); if (context.mounted) context.pop(); }, child: const Text('存草稿'), ), ), const SizedBox(width: 12), Expanded( flex: 2, child: ElevatedButton( onPressed: state.isSubmitting ? null : () async { final ok = await ctrl.submit(); if (context.mounted && ok) context.pop(); }, child: state.isSubmitting ? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white)) : const Text('提交申请'), ), ), ], ), ); } void _showPicker(List options, void Function(String) onPick) { showModalBottomSheet( context: context, builder: (_) => Column( mainAxisSize: MainAxisSize.min, children: options.map((t) => ListTile(title: Text(t), onTap: () { onPick(t); Navigator.pop(context); })).toList(), ), ); } Future _pickDateTime(void Function(DateTime) onPicked, DateTime initial) async { final date = await showDatePicker(context: context, initialDate: initial, firstDate: DateTime(2020), lastDate: DateTime(2030)); if (date == null || !context.mounted) return; final time = await showTimePicker(context: context, initialTime: TimeOfDay.fromDateTime(initial)); if (time == null) return; onPicked(DateTime(date.year, date.month, date.day, time.hour, time.minute)); } }