dialog_event_register.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  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 Object _args;
  37. DateTime? showDate;
  38. TimeOfDay? showStartAt;
  39. TimeOfDay? showEndAt;
  40. String? get dateString {
  41. final d = date.value;
  42. if (d != null) {
  43. return '${d.month}/${d.day}';
  44. }
  45. return null;
  46. }
  47. @override
  48. void onInit() {
  49. final args = Get.arguments;
  50. _args = args;
  51. if (args is _ArgCreate) {
  52. mapId = args.mapId;
  53. eventList = args.eventList;
  54. }
  55. if (args is _ArgEdit) {
  56. eventList = null;
  57. mapId = args.mapId;
  58. registerName = args.old.name;
  59. final d = args.old.startAt;
  60. date.value = DateTime(d.year, d.month, d.day);
  61. registerStartAt.value = TimeOfDay.fromDateTime(args.old.startAt);
  62. registerStopAt.value = TimeOfDay.fromDateTime(args.old.stopAt);
  63. password = args.old.password ?? '';
  64. hasPassword.value = args.old.password != null;
  65. }
  66. super.onInit();
  67. }
  68. void updateShowTime(DateTime? date, TimeOfDay? startAt, TimeOfDay? endAt) {
  69. if (date != null) {
  70. showDate = date;
  71. }
  72. if (startAt != null) {
  73. showStartAt = startAt;
  74. }
  75. if (endAt != null) {
  76. showEndAt = endAt;
  77. }
  78. }
  79. }
  80. class RegisterDialog extends GetView<RegisterDialogController> {
  81. const RegisterDialog({super.key});
  82. @override
  83. Widget build(BuildContext context) {
  84. return GetBuilder(
  85. init: RegisterDialogController(),
  86. builder: (c) {
  87. final children = <Widget>[];
  88. final eventList = controller.eventList;
  89. if (eventList != null) {
  90. children.addAll([
  91. SizedBox(
  92. child: DropdownMenu<EventInfo>(
  93. key: GlobalKey(),
  94. width: 320,
  95. hintText: '请选择活动',
  96. onSelected: (one) {
  97. controller.selected.value = one;
  98. },
  99. inputDecorationTheme: InputDecorationTheme(
  100. border: textBorder,
  101. isDense: true,
  102. ),
  103. dropdownMenuEntries: eventList
  104. .map((e) => DropdownMenuEntry<EventInfo>(
  105. value: e, label: e.name))
  106. .toList())),
  107. const SizedBox(height: 21.34),
  108. ]);
  109. }
  110. children.addAll([
  111. _TextField(
  112. hint: '请输入名称',
  113. onChanged: (v) {
  114. c.registerName = v;
  115. },
  116. initText: controller.registerName.isEmpty
  117. ? null
  118. : controller.registerName,
  119. ),
  120. const SizedBox(height: 21.34),
  121. Row(children: [
  122. Expanded(
  123. child: Obx(() => _TextField(
  124. hint: '日期',
  125. readOnly: true,
  126. initText: c.dateString,
  127. onTap: () async {
  128. c.date.value =
  129. await _showDatePicker(context, c.date.value);
  130. }))),
  131. const SizedBox(width: 15.64),
  132. Expanded(
  133. child: Obx(() => _TextField(
  134. hint: '开始时间',
  135. readOnly: true,
  136. initText: c.registerStartAt.value?.format(context),
  137. onTap: () async {
  138. c.registerStartAt.value = await _showTimePicker(
  139. context, c.registerStartAt.value);
  140. }))),
  141. const SizedBox(width: 15.64),
  142. Expanded(
  143. child: Obx(() => _TextField(
  144. hint: '结束时间',
  145. readOnly: true,
  146. initText: c.registerStopAt.value?.format(context),
  147. onTap: () async {
  148. c.registerStopAt.value = await _showTimePicker(
  149. context, c.registerStopAt.value);
  150. }))),
  151. ]),
  152. const SizedBox(height: 21.34),
  153. // _DateTimeSelect(
  154. // title: '显示时间',
  155. // date: c.showDate,
  156. // startAt: c.showStartAt,
  157. // endAt: c.showEndAt,
  158. // onChanged: c.updateShowTime),
  159. Row(
  160. mainAxisSize: MainAxisSize.min,
  161. children: [
  162. Obx(() => Switch(
  163. value: c.hasPassword.value,
  164. onChanged: (v) {
  165. c.hasPassword.value = v;
  166. })),
  167. const Text('查询密码'),
  168. const SizedBox(width: 12),
  169. Obx(() => Expanded(
  170. child: Visibility(
  171. visible: c.hasPassword.value,
  172. child: _TextField(
  173. hint: '请输入密码',
  174. onChanged: (v) {
  175. c.password = v;
  176. })))),
  177. ],
  178. ),
  179. const SizedBox(height: 21.34),
  180. SizedBox(
  181. width: double.infinity,
  182. child: DarkButton(
  183. onPressed: _onRegister,
  184. child: Text(eventList != null ? '注 册' : '确 定')))
  185. ]);
  186. return AlertDialog(
  187. title: Center(
  188. child: Text(
  189. eventList != null ? '注册比赛' : '编辑比赛',
  190. style: const TextStyle(fontSize: 17),
  191. )),
  192. backgroundColor: Colors.white,
  193. shape: RoundedRectangleBorder(
  194. borderRadius: BorderRadius.circular(17.78)),
  195. content: SizedBox(
  196. width: 320,
  197. child: ListView(shrinkWrap: true, children: children)),
  198. );
  199. });
  200. }
  201. void _onRegister() {
  202. final date = controller.date.value;
  203. final timeStartAt = controller.registerStartAt.value;
  204. final timeStopAt = controller.registerStopAt.value;
  205. final selected = controller.selected.value;
  206. final args = controller._args;
  207. var selectedId = -1;
  208. if (args is _ArgCreate) {
  209. if (selected == null) {
  210. Get.snackbar('错误', '请选择一个活动');
  211. return;
  212. }
  213. selectedId = selected.id;
  214. }
  215. if (args is _ArgEdit) {
  216. selectedId = args.old.id;
  217. }
  218. if (controller.registerName.isEmpty) {
  219. Get.snackbar('错误', '输入名称');
  220. return;
  221. }
  222. if (date == null) {
  223. Get.snackbar('错误', '请选择日期');
  224. return;
  225. }
  226. if (timeStartAt == null) {
  227. Get.snackbar('错误', '请选择开始时间');
  228. return;
  229. }
  230. if (timeStopAt == null) {
  231. Get.snackbar('错误', '请选择结束时间');
  232. return;
  233. }
  234. final startAt =
  235. date.copyWith(hour: timeStartAt.hour, minute: timeStartAt.minute);
  236. final stopAt =
  237. date.copyWith(hour: timeStopAt.hour, minute: timeStopAt.minute);
  238. if (startAt.isAfter(stopAt)) {
  239. Get.snackbar('错误', '结束时间应晚于开始时间');
  240. return;
  241. }
  242. Get.back(
  243. result: EventRegisterInfo()
  244. ..id = selectedId
  245. ..name = controller.registerName
  246. ..startAt = startAt
  247. ..stopAt = stopAt
  248. ..password =
  249. controller.hasPassword.value ? controller.password : null);
  250. }
  251. }
  252. Future<TimeOfDay?> _showTimePicker(
  253. BuildContext context, TimeOfDay? init) async {
  254. final TimeOfDay? time = await showTimePicker(
  255. context: context,
  256. initialTime: init ?? TimeOfDay.now(),
  257. );
  258. return time;
  259. }
  260. Future<DateTime?> _showDatePicker(BuildContext context, DateTime? init) async {
  261. final DateTime? time = await showDatePicker(
  262. context: context,
  263. initialDate: init ?? DateTime.now(),
  264. firstDate: DateTime.now(),
  265. lastDate: DateTime.now().add(365.days),
  266. );
  267. return time;
  268. }
  269. final textBorder = OutlineInputBorder(
  270. borderSide: const BorderSide(width: 0.71, color: Color(0xff818181)),
  271. borderRadius: BorderRadius.circular(2.13),
  272. );
  273. class _TextField extends StatelessWidget {
  274. const _TextField(
  275. {required this.hint,
  276. this.onChanged,
  277. this.readOnly = false,
  278. this.onTap,
  279. this.initText});
  280. final String hint;
  281. final void Function(String)? onChanged;
  282. final bool readOnly;
  283. final void Function()? onTap;
  284. final String? initText;
  285. @override
  286. Widget build(BuildContext context) {
  287. return SizedBox(
  288. child: TextFormField(
  289. key: GlobalKey(),
  290. initialValue: initText,
  291. maxLines: 1,
  292. onChanged: onChanged,
  293. onTap: onTap,
  294. readOnly: readOnly,
  295. decoration: InputDecoration(
  296. hintText: hint,
  297. border: textBorder,
  298. isDense: true,
  299. // contentPadding: const EdgeInsets.all(8.53)
  300. )),
  301. );
  302. }
  303. }
  304. class _DateTimeSelect extends StatefulWidget {
  305. const _DateTimeSelect(
  306. {required this.title,
  307. this.date,
  308. this.startAt,
  309. this.endAt,
  310. required this.onChanged});
  311. final String title;
  312. final DateTime? date;
  313. final TimeOfDay? startAt;
  314. final TimeOfDay? endAt;
  315. final void Function(DateTime? date, TimeOfDay? startAt, TimeOfDay? endAt)
  316. onChanged;
  317. @override
  318. State<StatefulWidget> createState() {
  319. return _DateTimeSelectState();
  320. }
  321. }
  322. class _DateTimeSelectState extends State<_DateTimeSelect> {
  323. DateTime? date;
  324. TimeOfDay? startAt;
  325. TimeOfDay? endAt;
  326. String? dateString(DateTime? d) {
  327. if (d != null) {
  328. return '${d.month}/${d.day}';
  329. }
  330. return null;
  331. }
  332. @override
  333. Widget build(BuildContext context) {
  334. return Column(
  335. mainAxisSize: MainAxisSize.min,
  336. children: [
  337. Text(widget.title),
  338. Row(children: [
  339. Expanded(
  340. child: Obx(() => _TextField(
  341. hint: '日期',
  342. readOnly: true,
  343. initText: dateString(date),
  344. onTap: () async {
  345. date = await _showDatePicker(context, date);
  346. setState(() {});
  347. widget.onChanged(date, null, null);
  348. }))),
  349. const SizedBox(width: 15.64),
  350. Expanded(
  351. child: Obx(() => _TextField(
  352. hint: '开始时间',
  353. readOnly: true,
  354. initText: startAt?.format(context),
  355. onTap: () async {
  356. startAt = await _showTimePicker(context, startAt);
  357. setState(() {});
  358. widget.onChanged(null, startAt, null);
  359. }))),
  360. const SizedBox(width: 15.64),
  361. Expanded(
  362. child: Obx(() => _TextField(
  363. hint: '结束时间',
  364. readOnly: true,
  365. initText: endAt?.format(context),
  366. onTap: () async {
  367. endAt = await _showTimePicker(context, endAt);
  368. setState(() {});
  369. widget.onChanged(null, null, endAt);
  370. }))),
  371. ]),
  372. ],
  373. );
  374. }
  375. }