import 'package:flutter/material.dart'; import '../theme.dart'; class DateTimePicker extends StatefulWidget { final DateTime? initialDate; final void Function(DateTime date) onDone; final VoidCallback onClear; const DateTimePicker({super.key, this.initialDate, required this.onDone, required this.onClear}); @override State createState() => _DateTimePickerState(); } class _DateTimePickerState extends State { late DateTime _viewMonth; DateTime? _selected; bool _showTime = false; int _hour = 12; int _minute = 0; @override void initState() { super.initState(); _selected = widget.initialDate; _viewMonth = widget.initialDate ?? DateTime.now(); if (widget.initialDate != null) { _hour = widget.initialDate!.hour; _minute = widget.initialDate!.minute; _showTime = _hour != 0 || _minute != 0; } } void _prevMonth() => setState(() => _viewMonth = DateTime(_viewMonth.year, _viewMonth.month - 1)); void _nextMonth() => setState(() => _viewMonth = DateTime(_viewMonth.year, _viewMonth.month + 1)); void _done() { if (_selected == null) return; final result = _showTime ? DateTime(_selected!.year, _selected!.month, _selected!.day, _hour, _minute) : DateTime(_selected!.year, _selected!.month, _selected!.day); widget.onDone(result); Navigator.of(context).pop(); } void _clear() { widget.onClear(); Navigator.of(context).pop(); } @override Widget build(BuildContext context) { final isDark = Theme.of(context).brightness == Brightness.dark; final now = DateTime.now(); final today = DateTime(now.year, now.month, now.day); final firstDay = DateTime(_viewMonth.year, _viewMonth.month, 1); final lastDay = DateTime(_viewMonth.year, _viewMonth.month + 1, 0); final startWeekday = firstDay.weekday; // 1=Mon const dayNames = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su']; const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; return Padding( padding: const EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Header Row( children: [ const Text('Date & Time', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600)), const Spacer(), GestureDetector( onTap: _done, child: const Text('Done', style: TextStyle(fontSize: 14, color: AppTheme.primary, fontWeight: FontWeight.w500)), ), ], ), const SizedBox(height: 16), // Month navigation Row( children: [ GestureDetector(onTap: _prevMonth, child: const Icon(Icons.chevron_left, size: 20)), Expanded( child: Center( child: Text('${months[_viewMonth.month - 1]} ${_viewMonth.year}', style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500)), ), ), GestureDetector(onTap: _nextMonth, child: const Icon(Icons.chevron_right, size: 20)), ], ), const SizedBox(height: 12), // Day names Row( children: [ for (final name in dayNames) Expanded( child: Center( child: Text(name, style: TextStyle(fontSize: 11, color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight)), ), ), ], ), const SizedBox(height: 4), // Calendar grid ...List.generate(6, (week) { return Row( children: List.generate(7, (dow) { final dayIndex = week * 7 + dow - (startWeekday - 1); if (dayIndex < 0 || dayIndex >= lastDay.day) return const Expanded(child: SizedBox(height: 32)); final day = dayIndex + 1; final date = DateTime(_viewMonth.year, _viewMonth.month, day); final isToday = date == today; final isSelected = _selected != null && date.year == _selected!.year && date.month == _selected!.month && date.day == _selected!.day; return Expanded( child: GestureDetector( onTap: () => setState(() => _selected = date), child: Container( height: 32, alignment: Alignment.center, decoration: BoxDecoration( shape: BoxShape.circle, color: isSelected ? AppTheme.primary : Colors.transparent, ), child: Text( '$day', style: TextStyle( fontSize: 13, fontWeight: isToday ? FontWeight.w700 : FontWeight.normal, color: isSelected ? Colors.white : (isToday ? AppTheme.primary : null), ), ), ), ), ); }), ); }), const SizedBox(height: 8), // Time toggle Container( padding: const EdgeInsets.only(top: 12), decoration: BoxDecoration( border: Border(top: BorderSide(color: isDark ? AppTheme.borderDark : AppTheme.borderLight, width: 0.5)), ), child: Column( children: [ GestureDetector( onTap: () => setState(() => _showTime = !_showTime), child: Row( children: [ Icon(Icons.access_time, size: 16, color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight), const SizedBox(width: 8), Text(_showTime ? 'Time' : 'Set time', style: TextStyle(fontSize: 13, color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight)), const Spacer(), Icon(_showTime ? Icons.expand_less : Icons.expand_more, size: 18, color: isDark ? AppTheme.textSecondaryDark : AppTheme.textSecondaryLight), ], ), ), if (_showTime) ...[ const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ // Hour Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( border: Border.all(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), borderRadius: BorderRadius.circular(6), ), child: DropdownButton( value: _hour, underline: const SizedBox.shrink(), isDense: true, style: TextStyle(fontSize: 14, color: isDark ? AppTheme.textDark : AppTheme.textLight), items: List.generate(24, (i) => DropdownMenuItem(value: i, child: Text(i.toString().padLeft(2, '0')))), onChanged: (v) => setState(() => _hour = v!), ), ), const Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: Text(':', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600))), // Minute Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( border: Border.all(color: isDark ? AppTheme.borderDark : AppTheme.borderLight), borderRadius: BorderRadius.circular(6), ), child: DropdownButton( value: _minute, underline: const SizedBox.shrink(), isDense: true, style: TextStyle(fontSize: 14, color: isDark ? AppTheme.textDark : AppTheme.textLight), items: List.generate(12, (i) => i * 5).map((m) => DropdownMenuItem(value: m, child: Text(m.toString().padLeft(2, '0')))).toList(), onChanged: (v) => setState(() => _minute = v!), ), ), ], ), ], ], ), ), // Clear button if (widget.initialDate != null) ...[ const SizedBox(height: 12), GestureDetector( onTap: _clear, child: const Text('Clear date', style: TextStyle(fontSize: 13, color: AppTheme.danger)), ), ], ], ), ); } }