dialog_event_register.dart 9.1 KB

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