import 'package:lucide_icons_flutter/lucide_icons.dart'; import 'package:flutter/material.dart'; import '../core/theme/app_dims.g.dart'; import '../core/theme/app_fonts.dart'; import '../core/theme/context_tokens.dart'; import '../core/utils/date_util.dart'; import 'wheel_date_picker.dart'; /// 日期字段(登记收支等表单用):点选打开统一日期下拉(面板内含可输入框 + /// 三列滚轮,见 wheel_date_picker.dart,桌面锚定下拉 / 窄屏底部 sheet)。 /// 值以 `yyyy-MM-dd` 字符串进出([value] / [onChanged])。 class DatePickerField extends StatefulWidget { final String? value; // yyyy-MM-dd final ValueChanged onChanged; final bool isRequired; final String? label; const DatePickerField({ super.key, this.value, required this.onChanged, this.isRequired = false, this.label, }); @override State createState() => _DatePickerFieldState(); } class _DatePickerFieldState extends State { Future _pick( BuildContext anchorCtx, FormFieldState field) async { final d = await showDsDateDropdown(anchorCtx, initial: parseYmd(widget.value)); if (d != null) { final v = formatYmd(d); field.didChange(v); widget.onChanged(v); } } @override Widget build(BuildContext context) { final t = context.tokens; return FormField( initialValue: widget.value, validator: widget.isRequired ? (_) => (widget.value == null || widget.value!.isEmpty) ? '请输入日期' : null : null, builder: (field) { final has = widget.value != null && widget.value!.isNotEmpty; return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Builder( builder: (anchorCtx) => InkWell( onTap: () => _pick(anchorCtx, field), borderRadius: BorderRadius.circular(AppDims.rMd), child: Container( height: 38, padding: const EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( color: t.surface, border: Border.all(color: field.hasError ? t.danger : t.border), borderRadius: BorderRadius.circular(AppDims.rMd), ), child: Row(children: [ Expanded( child: Text( has ? widget.value! : '年-月-日', overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: AppDims.fsBody, color: has ? t.text : t.faint, fontFamily: has ? AppFonts.mono : null, fontFamilyFallback: has ? AppFonts.monoFallback : null), ), ), Icon(LucideIcons.calendar, size: 16, color: t.muted), ]), ), ), ), if (field.errorText != null) Padding( padding: const EdgeInsets.only(top: 4, left: 2), child: Text(field.errorText!, style: TextStyle(fontSize: AppDims.fsXs, color: t.danger)), ), ], ); }, ); } }