Files
superport_v2/lib/widgets/components/superport_date_picker.dart
2025-09-29 01:51:47 +09:00

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;
}
}