import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import '../../screens/equipment/controllers/equipment_history_controller.dart'; import '../../screens/equipment/controllers/equipment_list_controller.dart'; import '../../data/models/equipment_history_dto.dart'; import '../../data/models/warehouse/warehouse_dto.dart'; import '../../services/warehouse_service.dart'; import 'package:get_it/get_it.dart'; class StockInForm extends StatefulWidget { const StockInForm({super.key}); @override State createState() => _StockInFormState(); } class _StockInFormState extends State { final _formKey = GlobalKey(); final _warehouseService = GetIt.instance(); int? _selectedEquipmentId; int? _selectedWarehouseId; int _quantity = 1; DateTime _transactionDate = DateTime.now(); String? _notes; // 창고 관련 상태 List _warehouses = []; bool _isLoadingWarehouses = false; String? _warehouseError; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { // 장비 목록 로드 context.read().refresh(); // 창고 목록 로드 _loadWarehouses(); }); } /// 사용 중인 창고 목록 로드 Future _loadWarehouses() async { setState(() { _isLoadingWarehouses = true; _warehouseError = null; }); try { final warehouses = await _warehouseService.getInUseWarehouseLocations(); if (mounted) { setState(() { // WarehouseLocation을 WarehouseDto로 변환 (임시 - 추후 DTO 직접 사용 메서드 추가 예정) _warehouses = warehouses.map((location) => WarehouseDto( id: location.id, name: location.name, remark: location.remark, isDeleted: !location.isActive, )).toList(); _isLoadingWarehouses = false; }); } } catch (e) { if (mounted) { setState(() { _warehouseError = '창고 목록을 불러오는데 실패했습니다: ${e.toString()}'; _isLoadingWarehouses = false; }); } } } Future _handleSubmit() async { if (_formKey.currentState?.saveAndValidate() ?? false) { final controller = context.read(); // 백엔드 스키마에 맞는 요청 데이터 생성 final request = EquipmentHistoryRequestDto( equipmentsId: _selectedEquipmentId!, warehousesId: _selectedWarehouseId ?? 1, // 기본 창고 ID transactionType: 'I', // 입고 quantity: _quantity, transactedAt: _transactionDate, remark: _notes, ); await controller.createHistory(request); if (controller.error == null && mounted) { ShadToaster.of(context).show( const ShadToast( title: Text('입고 등록 완료'), description: Text('장비가 성공적으로 입고되었습니다'), ), ); Navigator.pop(context, true); } else if (controller.error != null && mounted) { ShadToaster.of(context).show( ShadToast.destructive( title: const Text('입고 등록 실패'), description: Text(controller.error!), ), ); } } } @override Widget build(BuildContext context) { final theme = ShadTheme.of(context); return Scaffold( backgroundColor: theme.colorScheme.background, appBar: AppBar( backgroundColor: theme.colorScheme.card, title: const Text('장비 입고 등록'), leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () => Navigator.pop(context), ), ), body: SingleChildScrollView( padding: const EdgeInsets.all(24), child: Center( child: Container( constraints: const BoxConstraints(maxWidth: 600), child: ShadCard( child: Padding( padding: const EdgeInsets.all(24), child: ShadForm( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '입고 정보 입력', style: theme.textTheme.h3, ), const SizedBox(height: 8), Text( '입고할 장비와 창고 정보를 입력하세요', style: theme.textTheme.muted, ), const SizedBox(height: 24), // 장비 선택 Consumer( builder: (context, controller, _) { return ShadSelect( placeholder: const Text('장비 선택'), options: controller.equipments.map((equipment) { return ShadOption( value: equipment.id!, child: Text('${equipment.equipment.modelDto?.name ?? 'Unknown'} (${equipment.equipment.serialNumber})'), ); }).toList(), selectedOptionBuilder: (context, value) { final equipment = controller.equipments.firstWhere( (e) => e.id == value, ); return Text('${equipment.equipment.modelDto?.name ?? 'Unknown'} (${equipment.equipment.serialNumber})'); }, onChanged: (value) { setState(() { _selectedEquipmentId = value; }); }, ); }, ), const SizedBox(height: 16), // 창고 선택 (백엔드 API 연동) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('창고', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500)), const SizedBox(height: 8), if (_isLoadingWarehouses) Container( height: 40, decoration: BoxDecoration( border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(8), ), child: const Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2), ), SizedBox(width: 8), Text('창고 목록 로딩 중...', style: TextStyle(fontSize: 14)), ], ), ), ) else if (_warehouseError != null) Column( children: [ Container( height: 40, decoration: BoxDecoration( border: Border.all(color: Colors.red.shade300), borderRadius: BorderRadius.circular(8), ), child: Center( child: Text( _warehouseError!, style: TextStyle(color: Colors.red.shade600, fontSize: 14), ), ), ), const SizedBox(height: 8), ShadButton.outline( onPressed: _loadWarehouses, child: const Text('재시도'), ), ], ) else ShadSelect( placeholder: const Text('창고 선택'), options: _warehouses.map((warehouse) { return ShadOption( value: warehouse.id!, child: Text(warehouse.name), ); }).toList(), selectedOptionBuilder: (context, value) { final warehouse = _warehouses.firstWhere( (w) => w.id == value, orElse: () => WarehouseDto(name: 'Unknown'), ); return Text(warehouse.name); }, onChanged: (value) { setState(() { _selectedWarehouseId = value; }); }, ), ], ), const SizedBox(height: 16), // 수량 ShadInputFormField( label: const Text('수량'), initialValue: '1', keyboardType: TextInputType.number, validator: (v) { if (_quantity <= 0) { return '수량은 1 이상이어야 합니다'; } return null; }, onChanged: (value) { setState(() { _quantity = int.tryParse(value) ?? 1; }); }, ), const SizedBox(height: 16), // 입고일 ShadInputFormField( label: const Text('입고일'), initialValue: '${_transactionDate.year}-${_transactionDate.month.toString().padLeft(2, '0')}-${_transactionDate.day.toString().padLeft(2, '0')}', enabled: false, trailing: IconButton( icon: const Icon(Icons.calendar_today, size: 16), onPressed: () async { final picked = await showDatePicker( context: context, initialDate: _transactionDate, firstDate: DateTime(2020), lastDate: DateTime.now(), ); if (picked != null) { setState(() { _transactionDate = picked; }); } }, ), ), const SizedBox(height: 16), // 비고 ShadInputFormField( label: const Text('비고'), maxLines: 3, placeholder: const Text('추가 정보를 입력하세요'), onChanged: (value) { _notes = value.isEmpty ? null : value; }, ), const SizedBox(height: 32), // 버튼 Row( mainAxisAlignment: MainAxisAlignment.end, children: [ ShadButton.outline( child: const Text('취소'), onPressed: () => Navigator.pop(context), ), const SizedBox(width: 8), Consumer( builder: (context, controller, _) { return ShadButton( enabled: !controller.isLoading, onPressed: _handleSubmit, child: controller.isLoading ? const SizedBox( width: 16, height: 16, child: CircularProgressIndicator( strokeWidth: 2, ), ) : const Text('입고 등록'), ); }, ), ], ), ], ), ), ), ), ), ), ), ); } }