134 lines
4.1 KiB
Dart
134 lines
4.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:intl/intl.dart' as intl;
|
|
import 'package:lucide_icons_flutter/lucide_icons.dart' as lucide;
|
|
import 'package:shadcn_ui/shadcn_ui.dart';
|
|
|
|
/// 단일 날짜 선택을 위한 공통 버튼 위젯.
|
|
class SuperportDatePickerButton extends StatelessWidget {
|
|
const SuperportDatePickerButton({
|
|
super.key,
|
|
required this.value,
|
|
required this.onChanged,
|
|
this.firstDate,
|
|
this.lastDate,
|
|
this.dateFormat,
|
|
this.placeholder = '날짜 선택',
|
|
this.enabled = true,
|
|
this.initialDate,
|
|
});
|
|
|
|
final DateTime? value;
|
|
final ValueChanged<DateTime> onChanged;
|
|
final DateTime? firstDate;
|
|
final DateTime? lastDate;
|
|
final intl.DateFormat? dateFormat;
|
|
final String placeholder;
|
|
final bool enabled;
|
|
final DateTime? initialDate;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final format = dateFormat ?? intl.DateFormat('yyyy-MM-dd');
|
|
final displayText = value != null ? format.format(value!) : placeholder;
|
|
return ShadButton.outline(
|
|
onPressed: !enabled
|
|
? null
|
|
: () async {
|
|
final now = DateTime.now();
|
|
final baseFirst = firstDate ?? DateTime(now.year - 10);
|
|
final baseLast = lastDate ?? DateTime(now.year + 5);
|
|
final seed = value ?? initialDate ?? now;
|
|
final adjustedInitial = seed.clamp(baseFirst, baseLast);
|
|
final picked = await showDatePicker(
|
|
context: context,
|
|
initialDate: adjustedInitial,
|
|
firstDate: baseFirst,
|
|
lastDate: baseLast,
|
|
);
|
|
if (picked != null) {
|
|
onChanged(picked);
|
|
}
|
|
},
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Text(displayText),
|
|
const SizedBox(width: 8),
|
|
const Icon(lucide.LucideIcons.calendar, size: 16),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 날짜 범위 선택을 위한 공통 버튼 위젯.
|
|
class SuperportDateRangePickerButton extends StatelessWidget {
|
|
const SuperportDateRangePickerButton({
|
|
super.key,
|
|
required this.value,
|
|
required this.onChanged,
|
|
this.firstDate,
|
|
this.lastDate,
|
|
this.dateFormat,
|
|
this.placeholder = '기간 선택',
|
|
this.enabled = true,
|
|
this.initialDateRange,
|
|
});
|
|
|
|
final DateTimeRange? value;
|
|
final ValueChanged<DateTimeRange?> onChanged;
|
|
final DateTime? firstDate;
|
|
final DateTime? lastDate;
|
|
final intl.DateFormat? dateFormat;
|
|
final String placeholder;
|
|
final bool enabled;
|
|
final DateTimeRange? initialDateRange;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final format = dateFormat ?? intl.DateFormat('yyyy-MM-dd');
|
|
final label = value == null
|
|
? placeholder
|
|
: '${format.format(value!.start)} ~ ${format.format(value!.end)}';
|
|
return ShadButton.outline(
|
|
onPressed: !enabled
|
|
? null
|
|
: () async {
|
|
final now = DateTime.now();
|
|
final baseFirst = firstDate ?? DateTime(now.year - 10);
|
|
final baseLast = lastDate ?? DateTime(now.year + 5);
|
|
final initialRange = value ?? initialDateRange;
|
|
final currentDate = initialRange?.start ?? now;
|
|
final picked = await showDateRangePicker(
|
|
context: context,
|
|
firstDate: baseFirst,
|
|
lastDate: baseLast,
|
|
initialDateRange: initialRange,
|
|
currentDate: currentDate.clamp(baseFirst, baseLast),
|
|
);
|
|
if (picked != null) {
|
|
onChanged(picked);
|
|
}
|
|
},
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
const Icon(lucide.LucideIcons.calendar, size: 16),
|
|
const SizedBox(width: 8),
|
|
Flexible(child: Text(label, overflow: TextOverflow.ellipsis)),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
extension _ClampDate on DateTime {
|
|
DateTime clamp(DateTime min, DateTime max) {
|
|
if (isBefore(min)) return min;
|
|
if (isAfter(max)) return max;
|
|
return this;
|
|
}
|
|
}
|