dialog_event_register.dart 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. import 'package:track_common/widget/prelude.dart';
  2. import '../../service/api.dart';
  3. import 'field_control.dart';
  4. class _ArgCreate {
  5. int mapId = 0;
  6. Iterable<EventInfo> eventList = [];
  7. }
  8. class _ArgEdit {
  9. int mapId = 0;
  10. EventRegisterInfo old = EventRegisterInfo();
  11. }
  12. Future<EventRegisterInfo?> showEventRegisterDialog(
  13. int mapId, Iterable<EventInfo> eventList) async {
  14. return await Get.dialog(const RegisterDialog(),
  15. arguments: _ArgCreate()
  16. ..mapId = mapId
  17. ..eventList = eventList);
  18. }
  19. Future<EventRegisterInfo?> showEventEditDialog(
  20. int mapId, EventRegisterInfo old) async {
  21. return await Get.dialog(const RegisterDialog(),
  22. arguments: _ArgEdit()
  23. ..mapId = mapId
  24. ..old = old);
  25. }
  26. class RegisterDialogController extends GetxController {
  27. var registerName = '';
  28. final date = Rx<DateTime?>(null);
  29. final registerStartAt = Rx<TimeOfDay?>(null);
  30. final registerStopAt = Rx<TimeOfDay?>(null);
  31. final selected = Rx<EventInfo?>(null);
  32. final hasPassword = false.obs;
  33. var password = '';
  34. late final int mapId;
  35. late final Iterable<EventInfo>? eventList;
  36. late final _args;
  37. String? get dateString {
  38. final d = date.value;
  39. if (d != null) {
  40. return '${d.month}/${d.day}';
  41. }
  42. return null;
  43. }
  44. @override
  45. void onInit() {
  46. final args = Get.arguments;
  47. _args = args;
  48. if (args is _ArgCreate) {
  49. mapId = args.mapId;
  50. eventList = args.eventList;
  51. }
  52. if (args is _ArgEdit) {
  53. eventList = null;
  54. mapId = args.mapId;
  55. registerName = args.old.name;
  56. final d = args.old.startAt;
  57. date.value = DateTime(d.year, d.month, d.day);
  58. registerStartAt.value = TimeOfDay.fromDateTime(args.old.startAt);
  59. registerStopAt.value = TimeOfDay.fromDateTime(args.old.stopAt);
  60. password = args.old.password ?? '';
  61. hasPassword.value = args.old.password != null;
  62. }
  63. super.onInit();
  64. }
  65. }
  66. class RegisterDialog extends GetView<RegisterDialogController> {
  67. const RegisterDialog({super.key});
  68. @override
  69. Widget build(BuildContext context) {
  70. return GetBuilder(
  71. init: RegisterDialogController(),
  72. builder: (c) {
  73. final children = <Widget>[];
  74. final eventList = controller.eventList;
  75. if (eventList != null) {
  76. children.addAll([
  77. SizedBox(
  78. child: DropdownMenu<EventInfo>(
  79. key: GlobalKey(),
  80. width: 320,
  81. hintText: '请选择活动',
  82. onSelected: (one) {
  83. controller.selected.value = one;
  84. },
  85. inputDecorationTheme: InputDecorationTheme(
  86. border: textBorder,
  87. isDense: true,
  88. ),
  89. dropdownMenuEntries: eventList
  90. .map((e) => DropdownMenuEntry<EventInfo>(
  91. value: e, label: e.name))
  92. .toList())),
  93. const SizedBox(height: 21.34),
  94. ]);
  95. }
  96. children.addAll([
  97. _TextField(
  98. hint: '请输入名称',
  99. onChanged: (v) {
  100. c.registerName = v;
  101. },
  102. initText: controller.registerName.isEmpty
  103. ? null
  104. : controller.registerName,
  105. ),
  106. const SizedBox(height: 21.34),
  107. Row(children: [
  108. Expanded(
  109. child: Obx(() => _TextField(
  110. hint: '日期',
  111. readOnly: true,
  112. initText: c.dateString,
  113. onTap: () async {
  114. c.date.value =
  115. await _showDatePicker(context, c.date.value);
  116. }))),
  117. const SizedBox(width: 15.64),
  118. Expanded(
  119. child: Obx(() => _TextField(
  120. hint: '开始时间',
  121. readOnly: true,
  122. initText: c.registerStartAt.value?.format(context),
  123. onTap: () async {
  124. c.registerStartAt.value = await _showTimePicker(
  125. context, c.registerStartAt.value);
  126. }))),
  127. const SizedBox(width: 15.64),
  128. Expanded(
  129. child: Obx(() => _TextField(
  130. hint: '结束时间',
  131. readOnly: true,
  132. initText: c.registerStopAt.value?.format(context),
  133. onTap: () async {
  134. c.registerStopAt.value = await _showTimePicker(
  135. context, c.registerStopAt.value);
  136. }))),
  137. ]),
  138. const SizedBox(height: 21.34),
  139. Row(
  140. mainAxisSize: MainAxisSize.min,
  141. children: [
  142. Obx(() => Switch(
  143. value: c.hasPassword.value,
  144. onChanged: (v) {
  145. c.hasPassword.value = v;
  146. })),
  147. const Text('查询密码'),
  148. const SizedBox(width: 12),
  149. Obx(() => Expanded(
  150. child: Visibility(
  151. visible: c.hasPassword.value,
  152. child: _TextField(
  153. hint: '请输入密码',
  154. onChanged: (v) {
  155. c.password = v;
  156. })))),
  157. ],
  158. ),
  159. const SizedBox(height: 21.34),
  160. SizedBox(
  161. width: double.infinity,
  162. child: DarkButton(
  163. onPressed: _onRegister,
  164. child: Text(eventList != null ? '注 册' : '确 定')))
  165. ]);
  166. return AlertDialog(
  167. title: Center(
  168. child: Text(
  169. eventList != null ? '注册比赛' : '编辑比赛',
  170. style: const TextStyle(fontSize: 17),
  171. )),
  172. backgroundColor: Colors.white,
  173. shape: RoundedRectangleBorder(
  174. borderRadius: BorderRadius.circular(17.78)),
  175. content: SizedBox(
  176. width: 320,
  177. child: ListView(shrinkWrap: true, children: children)),
  178. );
  179. });
  180. }
  181. void _onRegister() {
  182. final date = controller.date.value;
  183. final timeStartAt = controller.registerStartAt.value;
  184. final timeStopAt = controller.registerStopAt.value;
  185. final selected = controller.selected.value;
  186. final args = controller._args;
  187. var selectedId = -1;
  188. if (args is _ArgCreate) {
  189. if (selected == null) {
  190. Get.snackbar('错误', '请选择一个活动');
  191. return;
  192. }
  193. selectedId = selected.id;
  194. }
  195. if (args is _ArgEdit) {
  196. selectedId = args.old.id;
  197. }
  198. if (controller.registerName.isEmpty) {
  199. Get.snackbar('错误', '输入名称');
  200. return;
  201. }
  202. if (date == null) {
  203. Get.snackbar('错误', '请选择日期');
  204. return;
  205. }
  206. if (timeStartAt == null) {
  207. Get.snackbar('错误', '请选择开始时间');
  208. return;
  209. }
  210. if (timeStopAt == null) {
  211. Get.snackbar('错误', '请选择结束时间');
  212. return;
  213. }
  214. final startAt =
  215. date.copyWith(hour: timeStartAt.hour, minute: timeStartAt.minute);
  216. final stopAt =
  217. date.copyWith(hour: timeStopAt.hour, minute: timeStopAt.minute);
  218. if (startAt.isAfter(stopAt)) {
  219. Get.snackbar('错误', '结束时间应晚于开始时间');
  220. return;
  221. }
  222. Get.back(
  223. result: EventRegisterInfo()
  224. ..id = selectedId
  225. ..name = controller.registerName
  226. ..startAt = startAt
  227. ..stopAt = stopAt
  228. ..password =
  229. controller.hasPassword.value ? controller.password : null);
  230. }
  231. Future<TimeOfDay?> _showTimePicker(
  232. BuildContext context, TimeOfDay? init) async {
  233. final TimeOfDay? time = await showTimePicker(
  234. context: context,
  235. initialTime: init ?? TimeOfDay.now(),
  236. );
  237. return time;
  238. }
  239. Future<DateTime?> _showDatePicker(
  240. BuildContext context, DateTime? init) async {
  241. final DateTime? time = await showDatePicker(
  242. context: context,
  243. initialDate: init ?? DateTime.now(),
  244. firstDate: DateTime.now(),
  245. lastDate: DateTime.now().add(365.days),
  246. );
  247. return time;
  248. }
  249. }
  250. final textBorder = OutlineInputBorder(
  251. borderSide: const BorderSide(width: 0.71, color: Color(0xff818181)),
  252. borderRadius: BorderRadius.circular(2.13),
  253. );
  254. class _TextField extends StatelessWidget {
  255. const _TextField(
  256. {required this.hint,
  257. this.onChanged,
  258. this.readOnly = false,
  259. this.onTap,
  260. this.initText});
  261. final String hint;
  262. final void Function(String)? onChanged;
  263. final bool readOnly;
  264. final void Function()? onTap;
  265. final String? initText;
  266. @override
  267. Widget build(BuildContext context) {
  268. return SizedBox(
  269. child: TextFormField(
  270. key: GlobalKey(),
  271. initialValue: initText,
  272. maxLines: 1,
  273. onChanged: onChanged,
  274. onTap: onTap,
  275. readOnly: readOnly,
  276. decoration: InputDecoration(
  277. hintText: hint,
  278. border: textBorder,
  279. isDense: true,
  280. // contentPadding: const EdgeInsets.all(8.53)
  281. )),
  282. );
  283. }
  284. }