import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../../data/models/rent_dto.dart'; class RentFormDialog extends StatefulWidget { final RentDto? rent; final Future Function(RentRequestDto) onSubmit; const RentFormDialog({ super.key, this.rent, required this.onSubmit, }); @override State createState() => _RentFormDialogState(); } class _RentFormDialogState extends State { final _formKey = GlobalKey(); // 백엔드 스키마에 맞는 필드만 유지 int? _selectedEquipmentHistoryId; DateTime _startDate = DateTime.now(); DateTime? _endDate; bool _isLoading = false; @override void initState() { super.initState(); if (widget.rent != null) { _initializeForm(widget.rent!); } } @override void dispose() { super.dispose(); } void _initializeForm(RentDto rent) { _selectedEquipmentHistoryId = rent.equipmentHistoryId; _startDate = rent.startedAt; _endDate = rent.endedAt; } Future _selectStartDate() async { final date = await showDatePicker( context: context, initialDate: _startDate, firstDate: DateTime(2020), lastDate: DateTime(2030), ); if (date != null) { setState(() { _startDate = date; }); } } Future _selectEndDate() async { final date = await showDatePicker( context: context, initialDate: _endDate ?? DateTime.now().add(const Duration(days: 30)), firstDate: _startDate, lastDate: DateTime(2030), ); if (date != null) { setState(() { _endDate = date; }); } } Future _submit() async { if (_selectedEquipmentHistoryId == null || _endDate == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('장비 이력과 종료일을 선택해주세요')), ); return; } setState(() => _isLoading = true); try { final request = RentRequestDto( equipmentHistoryId: _selectedEquipmentHistoryId!, startedAt: _startDate, endedAt: _endDate!, ); await widget.onSubmit(request); } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('오류가 발생했습니다: $e')), ); } } finally { if (mounted) { setState(() => _isLoading = false); } } } @override Widget build(BuildContext context) { return Dialog( child: Container( width: 500, constraints: const BoxConstraints(maxHeight: 600), padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ // 제목 Text( widget.rent != null ? '임대 계약 수정' : '새 임대 계약', style: Theme.of(context).textTheme.headlineSmall, ), const SizedBox(height: 24), // 폼 (백엔드 스키마 3개 필드만 포함) Expanded( child: Form( key: _formKey, child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 장비 이력 ID (백엔드 필수 필드) TextFormField( decoration: const InputDecoration( labelText: '장비 이력 ID *', border: OutlineInputBorder(), helperText: '임대할 장비의 이력 ID를 입력하세요', ), keyboardType: TextInputType.number, inputFormatters: [FilteringTextInputFormatter.digitsOnly], validator: (value) { if (value == null || value.isEmpty) { return '장비 이력 ID는 필수입니다'; } return null; }, onChanged: (value) { _selectedEquipmentHistoryId = int.tryParse(value); }, initialValue: _selectedEquipmentHistoryId?.toString(), ), const SizedBox(height: 20), // 임대 기간 (백엔드 필수 필드) Text('임대 기간', style: Theme.of(context).textTheme.titleMedium), const SizedBox(height: 12), Row( children: [ Expanded( child: InkWell( onTap: _selectStartDate, child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(4), ), child: Row( children: [ const Icon(Icons.calendar_today), const SizedBox(width: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('시작일 *', style: TextStyle(fontSize: 12, color: Colors.grey)), Text( '${_startDate.year}-${_startDate.month.toString().padLeft(2, '0')}-${_startDate.day.toString().padLeft(2, '0')}', style: const TextStyle(fontSize: 16), ), ], ), ], ), ), ), ), const SizedBox(width: 16), Expanded( child: InkWell( onTap: _selectEndDate, child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(4), ), child: Row( children: [ const Icon(Icons.calendar_today), const SizedBox(width: 8), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('종료일 *', style: TextStyle(fontSize: 12, color: Colors.grey)), Text( _endDate != null ? '${_endDate!.year}-${_endDate!.month.toString().padLeft(2, '0')}-${_endDate!.day.toString().padLeft(2, '0')}' : '날짜 선택', style: TextStyle( fontSize: 16, color: _endDate != null ? Colors.black : Colors.grey, ), ), ], ), ], ), ), ), ), ], ), const SizedBox(height: 16), // 임대 기간 표시 if (_endDate != null) Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.blue.shade50, borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.blue.shade200), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.info, color: Colors.blue), const SizedBox(width: 8), Text( '임대 기간: ${_endDate!.difference(_startDate).inDays + 1}일', style: const TextStyle(fontWeight: FontWeight.bold), ), ], ), ), ], ), ), ), ), const SizedBox(height: 24), // 버튼 Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( onPressed: _isLoading ? null : () => Navigator.of(context).pop(), child: const Text('취소'), ), const SizedBox(width: 8), ElevatedButton( onPressed: _isLoading ? null : _submit, child: _isLoading ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2), ) : Text(widget.rent != null ? '수정' : '생성'), ), ], ), ], ), ), ); } }