import 'package:track_common/widget/prelude.dart'; import '../../service/api.dart'; import 'field_control.dart'; class _ArgCreate { int mapId = 0; Iterable eventList = []; } class _ArgEdit { int mapId = 0; EventRegisterInfo old = EventRegisterInfo(); } extension DateTimeExt on DateTime { (DateTime, TimeOfDay) split() { return (DateTime(year, month, day), TimeOfDay.fromDateTime(this)); } } Future showEventRegisterDialog( int mapId, Iterable eventList) async { return await Get.dialog(const RegisterDialog(), arguments: _ArgCreate() ..mapId = mapId ..eventList = eventList); } Future showEventEditDialog( int mapId, EventRegisterInfo old) async { return await Get.dialog(const RegisterDialog(), arguments: _ArgEdit() ..mapId = mapId ..old = old); } class RegisterDialogController extends GetxController { var registerName = ''; final selected = Rx(null); final hasPasswordQuery = false.obs; final hasPasswordEvent = false.obs; final isAutoBegin = false.obs; var passwordQuery = ''; var passwordEvent = ''; late final int mapId; late final Iterable? eventList; late final Object _args; Rx eventDate = Rx(null); TimeOfDay? eventStartAt; TimeOfDay? eventEndAt; Rx showDateStart = Rx(null); TimeOfDay? showStartAt; Rx showDateEnd = Rx(null); TimeOfDay? showEndAt; @override void onInit() { final args = Get.arguments; _args = args; if (args is _ArgCreate) { mapId = args.mapId; eventList = args.eventList; } if (args is _ArgEdit) { eventList = null; mapId = args.mapId; registerName = args.old.name; { final (date, time) = args.old.eventStartAt.split(); eventDate.value = date; eventStartAt = time; eventEndAt = TimeOfDay.fromDateTime(args.old.eventStopAt); } { final (date, time) = args.old.showStartAt.split(); showDateStart.value = date; showStartAt = time; } { final (date, time) = args.old.showStopAt.split(); showDateEnd.value = date; showEndAt = time; } passwordQuery = args.old.passwordQuery ?? ''; hasPasswordQuery.value = args.old.passwordQuery != null; passwordEvent = args.old.passwordEvent ?? ''; hasPasswordEvent.value = args.old.passwordEvent != null; isAutoBegin.value = args.old.isAutoBegin; } super.onInit(); } void updateShowTime(DateTime? dateStart, TimeOfDay? startAt, DateTime? dateEnd, TimeOfDay? endAt) { if (dateStart != null) { showDateStart.value = dateStart; } if (startAt != null) { showStartAt = startAt; } if (endAt != null) { showEndAt = endAt; } if (dateEnd != null) { showDateEnd.value = dateEnd; } } void updateEventTime(DateTime? date, TimeOfDay? startAt, TimeOfDay? endAt) { if (date != null) { eventDate.value = date; } if (startAt != null) { eventStartAt = startAt; } if (endAt != null) { eventEndAt = endAt; } } } const double dialogWidth = 400.0; class RegisterDialog extends GetView { const RegisterDialog({super.key}); @override Widget build(BuildContext context) { return GetBuilder( init: RegisterDialogController(), builder: (c) { final children = []; final eventList = controller.eventList; if (eventList != null) { children.addAll([ SizedBox( child: DropdownMenu( key: GlobalKey(), width: dialogWidth, hintText: '请选择活动', onSelected: (one) { controller.selected.value = one; }, inputDecorationTheme: InputDecorationTheme( border: textBorder, isDense: true, ), dropdownMenuEntries: eventList .map((e) => DropdownMenuEntry( value: e, label: e.name)) .toList())), const SizedBox(height: 21.34), ]); } children.addAll([ _TextField( hint: '请输入名称', onChanged: (v) { c.registerName = v; }, initText: controller.registerName.isEmpty ? null : controller.registerName, ), const SizedBox(height: 21.34), Obx(() => _EventTimeSelect( date: c.eventDate.value, startAt: c.eventStartAt, endAt: c.eventEndAt, onChanged: c.updateEventTime)), const SizedBox(height: 12), Obx(() => _ShowTimeSelect( dateStart: c.showDateStart.value, startAt: c.showStartAt, dateEnd: c.showDateEnd.value, endAt: c.showEndAt, onChanged: c.updateShowTime)), password('查询密码', c.hasPasswordQuery, (v) { c.passwordQuery = v; }), // password('赛事密码', c.hasPasswordEvent, (v) { // c.passwordEvent = v; // }), autoBegin(c.isAutoBegin), const SizedBox(height: 21.34), SizedBox( width: double.infinity, child: DarkButton( onPressed: _onRegister, child: Text(eventList != null ? '注 册' : '确 定'))) ]); return AlertDialog( title: Center( child: Text( eventList != null ? '注册比赛' : '编辑比赛', style: const TextStyle(fontSize: 17), )), backgroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(17.78)), content: SizedBox( width: dialogWidth, child: ListView(shrinkWrap: true, children: children)), ); }); } Widget password( String title, Rx hasPassword, void Function(String) onChanged, ) { return SizedBox( height: 80, child: Row(mainAxisSize: MainAxisSize.min, children: [ Obx(() => Switch( value: hasPassword.value, onChanged: (v) { hasPassword.value = v; })), Text(title), const SizedBox(width: 12), Obx(() => Expanded( child: Visibility( visible: hasPassword.value, child: _TextField(hint: '请输入密码', onChanged: onChanged)))) ])); } Widget autoBegin( Rx b, ) { return SizedBox( height: 80, child: Row(mainAxisSize: MainAxisSize.min, children: [ Obx(() => Switch( value: b.value, onChanged: (v) { b.value = v; })), const Text('自动开始'), ])); } void _onRegister() { final showDateStart = controller.showDateStart.value; final showDateEnd = controller.showDateEnd.value; final showTimeStartAt = controller.showStartAt; final showTimeStopAt = controller.showEndAt; final evenDate = controller.eventDate; final eventTimeStartAt = controller.eventStartAt; final eventTimeStopAt = controller.eventEndAt; final selected = controller.selected.value; final args = controller._args; var selectedId = -1; if (args is _ArgCreate) { if (selected == null) { Get.snackbar('错误', '请选择一个活动'); return; } selectedId = selected.id; } if (args is _ArgEdit) { selectedId = args.old.id; } if (controller.registerName.isEmpty) { Get.snackbar('错误', '输入名称'); return; } if (showDateStart == null) { Get.snackbar('错误', '请选择显示开始日期'); return; } if (showDateEnd == null) { Get.snackbar('错误', '请选择显示结束日期'); return; } if (showTimeStartAt == null) { Get.snackbar('错误', '请选择开始时间'); return; } if (showTimeStopAt == null) { Get.snackbar('错误', '请选择结束时间'); return; } if (evenDate.value == null) { Get.snackbar('错误', '请选择日期'); return; } if (eventTimeStartAt == null) { Get.snackbar('错误', '请选择开始时间'); return; } if (eventTimeStopAt == null) { Get.snackbar('错误', '请选择结束时间'); return; } final eventStartAt = evenDate.value! .copyWith(hour: eventTimeStartAt.hour, minute: eventTimeStartAt.minute); final eventStopAt = evenDate.value! .copyWith(hour: eventTimeStopAt.hour, minute: eventTimeStopAt.minute); if (eventStartAt.isAfter(eventStopAt)) { Get.snackbar('错误', '结束时间应晚于开始时间'); return; } final showStartAt = showDateStart.copyWith( hour: showTimeStartAt.hour, minute: showTimeStartAt.minute); final showStopAt = showDateEnd.copyWith( hour: showTimeStopAt.hour, minute: showTimeStopAt.minute); if (showStartAt.isAfter(showStopAt)) { Get.snackbar('错误', '结束时间应晚于开始时间'); return; } Get.back( result: EventRegisterInfo() ..id = selectedId ..name = controller.registerName ..showStartAt = showStartAt ..showStopAt = showStopAt ..eventStartAt = eventStartAt ..eventStopAt = eventStopAt ..isAutoBegin = controller.isAutoBegin.value ..passwordQuery = controller.hasPasswordQuery.value ? controller.passwordQuery : null ..passwordEvent = controller.hasPasswordEvent.value ? controller.passwordEvent : null); } } Future _showTimePicker( BuildContext context, TimeOfDay? init) async { final TimeOfDay? time = await showTimePicker( context: context, initialTime: init ?? TimeOfDay.now(), ); return time; } Future _showDatePicker(BuildContext context, DateTime? init) async { final DateTime? time = await showDatePicker( context: context, initialDate: init ?? DateTime.now(), firstDate: DateTime.now(), lastDate: DateTime.now().add(365.days), ); return time; } final textBorder = OutlineInputBorder( borderSide: const BorderSide(width: 0.71, color: Color(0xff818181)), borderRadius: BorderRadius.circular(2.13), ); class _TextField extends StatelessWidget { const _TextField( {required this.hint, this.onChanged, this.readOnly = false, this.onTap, this.initText}); final String hint; final void Function(String)? onChanged; final bool readOnly; final void Function()? onTap; final String? initText; @override Widget build(BuildContext context) { return SizedBox( child: TextFormField( key: GlobalKey(), initialValue: initText, maxLines: 1, onChanged: onChanged, onTap: onTap, readOnly: readOnly, decoration: InputDecoration( hintText: hint, border: textBorder, isDense: true, // contentPadding: const EdgeInsets.all(8.53) )), ); } } const timeColor = Color(0xff6e6e6e); class _TimeSelect extends StatelessWidget { const _TimeSelect({required this.children, required this.title}); final String title; final List children; @override Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle(color: Colors.black), ), Container( height: 54, width: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.circular(2.5), border: Border.all(color: timeColor, width: 1)), child: DefaultTextStyle( style: const TextStyle(color: timeColor), child: Row( children: children, ))) ], ); } } class _TimeButton extends StatelessWidget { const _TimeButton( {required this.onPressed, required this.hint, required this.value}); final VoidCallback onPressed; final String hint; final String? value; @override Widget build(BuildContext context) { return TextButton( onPressed: onPressed, child: Text(value ?? hint, style: const TextStyle(color: timeColor))); } } class _EventTimeSelect extends StatefulWidget { const _EventTimeSelect( {this.date, this.startAt, this.endAt, required this.onChanged}); final DateTime? date; final TimeOfDay? startAt; final TimeOfDay? endAt; final void Function(DateTime? date, TimeOfDay? startAt, TimeOfDay? endAt) onChanged; @override State createState() { return _EventTimeSelectState(); } } class _EventTimeSelectState extends State<_EventTimeSelect> { DateTime? date; TimeOfDay? startAt; TimeOfDay? endAt; @override void initState() { date = widget.date; startAt = widget.startAt; endAt = widget.endAt; super.initState(); } @override Widget build(BuildContext context) { return _TimeSelect( title: '比赛时间', children: [ Expanded( child: _TimeButton( onPressed: () async { date = await _showDatePicker(context, date); setState(() {}); widget.onChanged(date, null, null); }, hint: '比赛日期', value: dateString(date))), const Text('-'), Expanded( child: _TimeButton( onPressed: () async { startAt = await _showTimePicker(context, startAt); setState(() {}); widget.onChanged(null, startAt, null); }, hint: '开始时间', value: startAt?.format(context))), const Text("-"), Expanded( child: _TimeButton( onPressed: () async { endAt = await _showTimePicker(context, endAt); setState(() {}); widget.onChanged(null, null, endAt); }, hint: '结束时间', value: endAt?.format(context))), const Text(' '), Expanded(child: TextButton(onPressed: () {}, child: const SizedBox())) ], ); } } class _ShowTimeSelect extends StatefulWidget { const _ShowTimeSelect( {this.dateStart, this.dateEnd, this.startAt, this.endAt, required this.onChanged}); final DateTime? dateStart; final DateTime? dateEnd; final TimeOfDay? startAt; final TimeOfDay? endAt; final void Function(DateTime? dateStart, TimeOfDay? startAt, DateTime? dateEnd, TimeOfDay? endAt) onChanged; @override State createState() { return _ShowTimeSelectState(); } } class _ShowTimeSelectState extends State<_ShowTimeSelect> { DateTime? dateStart; DateTime? dateEnd; TimeOfDay? startAt; TimeOfDay? endAt; @override void initState() { dateStart = widget.dateStart; dateEnd = widget.dateEnd; startAt = widget.startAt; endAt = widget.endAt; super.initState(); } @override Widget build(BuildContext context) { return _TimeSelect( title: '显示时间', children: [ Expanded( child: _TimeButton( onPressed: () async { dateStart = await _showDatePicker(context, dateStart); setState(() {}); widget.onChanged(dateStart, null, null, null); }, hint: '开始日期', value: dateString(dateStart))), const Text('-'), Expanded( child: _TimeButton( onPressed: () async { startAt = await _showTimePicker(context, startAt); setState(() {}); widget.onChanged(null, startAt, null, null); }, hint: '开始时间', value: startAt?.format(context))), const Text('至'), Expanded( child: _TimeButton( onPressed: () async { dateEnd = await _showDatePicker(context, dateEnd); setState(() {}); widget.onChanged(null, null, dateEnd, null); }, hint: '结束日期', value: dateString(dateEnd))), const Text("-"), Expanded( child: _TimeButton( onPressed: () async { endAt = await _showTimePicker(context, endAt); setState(() {}); widget.onChanged(null, null, null, endAt); }, hint: '结束时间', value: endAt?.format(context))), ], ); } } String? dateString(DateTime? d) { if (d != null) { return '${d.month}/${d.day}'; } return null; } class _DateTimeSelect extends StatefulWidget { const _DateTimeSelect( {required this.title, this.date, this.startAt, this.endAt, required this.onChanged}); final String title; final DateTime? date; final TimeOfDay? startAt; final TimeOfDay? endAt; final void Function(DateTime? date, TimeOfDay? startAt, TimeOfDay? endAt) onChanged; @override State createState() { return _DateTimeSelectState(); } } class _DateTimeSelectState extends State<_DateTimeSelect> { DateTime? date; TimeOfDay? startAt; TimeOfDay? endAt; @override void initState() { date = widget.date; startAt = widget.startAt; endAt = widget.endAt; super.initState(); } String? dateString(DateTime? d) { if (d != null) { return '${d.month}/${d.day}'; } return null; } @override Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(widget.title), Row(children: [ Expanded( child: _TextField( hint: '日期', readOnly: true, initText: dateString(date), onTap: () async { date = await _showDatePicker(context, date); setState(() {}); widget.onChanged(date, null, null); })), const SizedBox(width: 15.64), Expanded( child: _TextField( hint: '开始时间', readOnly: true, initText: startAt?.format(context), onTap: () async { startAt = await _showTimePicker(context, startAt); setState(() {}); widget.onChanged(null, startAt, null); })), const SizedBox(width: 15.64), Expanded( child: _TextField( hint: '结束时间', readOnly: true, initText: endAt?.format(context), onTap: () async { endAt = await _showTimePicker(context, endAt); setState(() {}); widget.onChanged(null, null, endAt); })), ]), ], ); } }