import 'package:flutter/material.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import 'package:superport/data/models/model_dto.dart'; import 'package:superport/screens/model/controllers/model_controller.dart'; class ModelFormDialog extends StatefulWidget { final ModelController controller; final ModelDto? model; const ModelFormDialog({ super.key, required this.controller, this.model, }); @override State createState() => _ModelFormDialogState(); } class _ModelFormDialogState extends State { final _formKey = GlobalKey(); late final TextEditingController _nameController; int? _selectedVendorId; bool _isSubmitting = false; String? _statusMessage; @override void initState() { super.initState(); _nameController = TextEditingController(text: widget.model?.name); _selectedVendorId = widget.model?.vendorsId; } @override void dispose() { _nameController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final isEditMode = widget.model != null; return ShadDialog( title: Text(isEditMode ? '모델 수정' : '새 모델 등록'), child: Container( width: 400, padding: const EdgeInsets.all(16), child: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, children: [ // Vendor 선택 ShadSelect( placeholder: const Text('제조사 선택'), options: widget.controller.vendors.map( (vendor) => ShadOption( value: vendor.id, child: Text(vendor.name), ), ).toList(), selectedOptionBuilder: (context, value) { final vendor = widget.controller.vendors.firstWhere( (v) => v.id == value, ); return Text(vendor.name); }, onChanged: (value) { setState(() { _selectedVendorId = value; }); }, initialValue: _selectedVendorId, ), const SizedBox(height: 16), // 모델명 입력 ShadInputFormField( controller: _nameController, label: const Text('모델명'), placeholder: const Text('모델명을 입력하세요'), validator: (value) { if (value.isEmpty) { return '모델명은 필수입니다'; } return null; }, ), const SizedBox(height: 8), // 상태 메시지 영역 (고정 높이) SizedBox( height: 20, child: _statusMessage != null ? Text( _statusMessage!, style: TextStyle( fontSize: 12, color: _statusMessage!.contains('존재') ? Colors.red : Colors.grey, ), ) : const SizedBox.shrink(), ), const SizedBox(height: 8), // 활성 상태는 백엔드에서 관리하므로 UI에서 제거 // 버튼들 Row( mainAxisAlignment: MainAxisAlignment.end, children: [ ShadButton.outline( onPressed: _isSubmitting ? null : () { Navigator.of(context).pop(); }, child: const Text('취소'), ), const SizedBox(width: 8), ShadButton( onPressed: _isSubmitting ? null : _handleSubmit, child: _isSubmitting ? const SizedBox( width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2), ) : Text(isEditMode ? '수정' : '등록'), ), ], ), ], ), ), ), ); } Future _checkDuplicate() async { final name = _nameController.text.trim(); if (name.isEmpty) return false; // 수정 모드일 때 현재 이름과 같으면 검사하지 않음 if (widget.model != null && widget.model!.name == name) { return false; } try { final isDuplicate = await widget.controller.checkDuplicateName( name, excludeId: widget.model?.id, ); return isDuplicate; } catch (e) { // 네트워크 오류 시 false 반환 return false; } } Future _handleSubmit() async { if (!_formKey.currentState!.validate()) { return; } if (_selectedVendorId == null) { ShadToaster.of(context).show( const ShadToast( title: Text('오류'), description: Text('제조사를 선택해주세요'), backgroundColor: Colors.red, ), ); return; } setState(() { _isSubmitting = true; _statusMessage = '중복 확인 중...'; }); // 저장 시 중복 검사 수행 final isDuplicate = await _checkDuplicate(); if (isDuplicate) { setState(() { _isSubmitting = false; _statusMessage = '이미 존재하는 모델명입니다.'; }); return; } setState(() { _statusMessage = '저장 중...'; }); bool success; if (widget.model != null) { // 수정 success = await widget.controller.updateModel( id: widget.model!.id!, vendorsId: _selectedVendorId!, name: _nameController.text, ); } else { // 생성 success = await widget.controller.createModel( vendorsId: _selectedVendorId!, name: _nameController.text, ); } setState(() { _isSubmitting = false; _statusMessage = null; }); if (mounted) { if (success) { Navigator.of(context).pop(); ShadToaster.of(context).show( ShadToast( title: const Text('성공'), description: Text( widget.model != null ? '모델이 수정되었습니다.' : '모델이 등록되었습니다.', ), ), ); } else { ShadToaster.of(context).show( ShadToast( title: const Text('오류'), description: Text(widget.controller.errorMessage ?? '처리 실패'), backgroundColor: Colors.red, ), ); } } } }