import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; import '../../data/models/maintenance_dto.dart'; import '../../data/models/equipment_history_dto.dart'; import '../equipment/controllers/equipment_history_controller.dart'; import 'controllers/maintenance_controller.dart'; class MaintenanceFormDialog extends StatefulWidget { final MaintenanceDto? maintenance; const MaintenanceFormDialog({ super.key, this.maintenance, }); @override State createState() => _MaintenanceFormDialogState(); } class _MaintenanceFormDialogState extends State { final _formKey = GlobalKey(); late final TextEditingController _periodController; int? _selectedEquipmentHistoryId; String _maintenanceType = 'O'; // O: Onsite, R: Remote DateTime _startDate = DateTime.now(); DateTime? _endDate; List _equipmentHistories = []; bool _isLoadingHistories = false; @override void initState() { super.initState(); // 컨트롤러 초기화 - 백엔드 스키마 기준 _periodController = TextEditingController( text: widget.maintenance?.periodMonth.toString() ?? '12', ); // 기존 데이터 설정 if (widget.maintenance != null) { final maintenance = widget.maintenance!; _selectedEquipmentHistoryId = maintenance.equipmentHistoryId; _maintenanceType = maintenance.maintenanceType ?? 'O'; if (maintenance.startedAt != null) { _startDate = maintenance.startedAt; } if (maintenance.endedAt != null) { _endDate = maintenance.endedAt; } } // Equipment History 목록 로드 _loadEquipmentHistories(); } @override void dispose() { _periodController.dispose(); super.dispose(); } void _loadEquipmentHistories() async { setState(() { _isLoadingHistories = true; }); try { final controller = context.read(); await controller.loadHistory(refresh: true); setState(() { _equipmentHistories = controller.historyList; _isLoadingHistories = false; }); } catch (e) { setState(() { _isLoadingHistories = false; }); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('장비 이력 로드 실패: $e')), ); } } } // _calculateNextDate 메서드 제거 - 백엔드에 nextMaintenanceDate 필드 없음 @override Widget build(BuildContext context) { final isEditMode = widget.maintenance != null; return AlertDialog( title: Text(isEditMode ? '유지보수 수정' : '유지보수 등록'), content: SizedBox( width: MediaQuery.of(context).size.width * 0.6, child: Form( key: _formKey, child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Equipment History 선택 _buildEquipmentHistorySelector(), const SizedBox(height: 16), // 유지보수 타입 _buildMaintenanceTypeSelector(), const SizedBox(height: 16), // 시작일 및 주기 Row( children: [ Expanded( child: _buildDateField( '시작일', _startDate, (date) => setState(() => _startDate = date), ), ), const SizedBox(width: 16), Expanded( child: TextFormField( controller: _periodController, decoration: const InputDecoration( labelText: '주기 (개월)', suffixText: '개월', border: OutlineInputBorder(), ), keyboardType: TextInputType.number, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, LengthLimitingTextInputFormatter(2), ], validator: (value) { if (value == null || value.isEmpty) { return '주기를 입력해주세요'; } final period = int.tryParse(value); if (period == null || period <= 0 || period > 60) { return '1-60 사이의 값을 입력해주세요'; } return null; }, ), ), ], ), const SizedBox(height: 16), // nextMaintenanceDate 필드가 백엔드에 없으므로 제거 const SizedBox(height: 16), // cost 필드와 totalCount 필드가 백엔드에 없으므로 제거 const SizedBox(height: 16), // 업체 정보와 연락처 필드가 백엔드에 없으므로 제거 const SizedBox(height: 16), // 메모 필드가 백엔드에 없으므로 제거 const SizedBox(height: 16), // isActive 필드가 백엔드에 없으므로 제거 (백엔드에는 isDeleted만 있음) ], ), ), ), ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('취소'), ), Consumer( builder: (context, controller, child) { return ElevatedButton( onPressed: controller.isLoading ? null : _submit, child: controller.isLoading ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2), ) : Text(isEditMode ? '수정' : '등록'), ); }, ), ], ); } Widget _buildEquipmentHistorySelector() { if (_isLoadingHistories) { return const Center(child: CircularProgressIndicator()); } return DropdownButtonFormField( value: _selectedEquipmentHistoryId, decoration: const InputDecoration( labelText: '장비 이력 선택', border: OutlineInputBorder(), ), items: _equipmentHistories.map((history) { final equipment = history.equipment; return DropdownMenuItem( value: history.id, child: Text( '${equipment?.serialNumber ?? "Unknown"} - ' '${equipment?.serialNumber ?? "No Serial"} ' '(${history.transactionType == "I" ? "입고" : "출고"})', ), ); }).toList(), onChanged: widget.maintenance == null ? (value) => setState(() => _selectedEquipmentHistoryId = value) : null, // 수정 모드에서는 변경 불가 validator: (value) { if (value == null) { return '장비 이력을 선택해주세요'; } return null; }, ); } Widget _buildMaintenanceTypeSelector() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '유지보수 타입', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), ), const SizedBox(height: 8), Row( children: [ Expanded( child: RadioListTile( title: const Text('현장 (Onsite)'), value: 'O', groupValue: _maintenanceType, onChanged: (value) { setState(() { _maintenanceType = value!; }); }, contentPadding: EdgeInsets.zero, ), ), Expanded( child: RadioListTile( title: const Text('원격 (Remote)'), value: 'R', groupValue: _maintenanceType, onChanged: (value) { setState(() { _maintenanceType = value!; }); }, contentPadding: EdgeInsets.zero, ), ), ], ), ], ); } Widget _buildDateField( String label, DateTime value, Function(DateTime) onChanged, ) { return InkWell( onTap: () async { final picked = await showDatePicker( context: context, initialDate: value, firstDate: DateTime(2020), lastDate: DateTime(2030), ); if (picked != null) { onChanged(picked); // _calculateNextDate() 메서드 제거 - 백엔드에 nextMaintenanceDate 필드 없음 } }, child: InputDecorator( decoration: InputDecoration( labelText: label, border: const OutlineInputBorder(), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(DateFormat('yyyy-MM-dd').format(value)), const Icon(Icons.calendar_today, size: 20), ], ), ), ); } void _submit() async { if (!_formKey.currentState!.validate()) return; final controller = context.read(); bool success; if (widget.maintenance != null) { // 수정 - MaintenanceUpdateRequestDto 사용 final request = MaintenanceUpdateRequestDto( startedAt: _startDate, endedAt: _endDate, periodMonth: int.tryParse(_periodController.text), maintenanceType: _maintenanceType, ); success = await controller.updateMaintenance( id: widget.maintenance!.id!, startedAt: _startDate, endedAt: _endDate, periodMonth: int.tryParse(_periodController.text), maintenanceType: _maintenanceType, ); } else { // 생성 - named 파라미터로 직접 전달 success = await controller.createMaintenance( equipmentHistoryId: _selectedEquipmentHistoryId!, startedAt: _startDate, endedAt: _endDate ?? DateTime.now().add(const Duration(days: 30)), // 기본값: 30일 후 periodMonth: int.tryParse(_periodController.text) ?? 1, maintenanceType: _maintenanceType, ); } if (success && mounted) { Navigator.of(context).pop(true); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(widget.maintenance != null ? '유지보수가 수정되었습니다' : '유지보수가 등록되었습니다'), backgroundColor: Colors.green, ), ); } else if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(controller.error ?? '오류가 발생했습니다'), backgroundColor: Colors.red, ), ); } } }