import 'package:flutter/material.dart'; import 'package:superport/services/mock_data_service.dart'; import 'package:superport/utils/constants.dart'; import 'package:superport/screens/common/main_layout.dart'; import 'package:superport/screens/common/custom_widgets.dart'; import 'package:superport/screens/common/widgets/pagination.dart'; import 'package:superport/screens/common/theme_tailwind.dart'; import 'package:superport/screens/common/widgets/category_autocomplete_field.dart'; /// 물품 관리(등록) 화면 /// 이름, 제조사, 대분류, 중분류, 소분류만 등록/조회 가능 class GoodsListScreen extends StatefulWidget { const GoodsListScreen({super.key}); @override State createState() => _GoodsListScreenState(); } class _GoodsListScreenState extends State { final MockDataService _dataService = MockDataService(); late List<_GoodsItem> _goodsList; int _currentPage = 1; final int _pageSize = 10; @override void initState() { super.initState(); _loadGoods(); } void _loadGoods() { final allEquipments = _dataService.getAllEquipmentIns(); final goodsSet = {}; for (final equipmentIn in allEquipments) { final eq = equipmentIn.equipment; final key = '${eq.manufacturer}|${eq.name}|${eq.category}|${eq.subCategory}|${eq.subSubCategory}'; goodsSet[key] = _GoodsItem( name: eq.name, manufacturer: eq.manufacturer, category: eq.category, subCategory: eq.subCategory, subSubCategory: eq.subSubCategory, ); } setState(() { _goodsList = goodsSet.values.toList(); }); } void _showAddGoodsDialog() async { final result = await showDialog<_GoodsItem>( context: context, builder: (context) => _GoodsFormDialog(), ); if (result != null) { setState(() { _goodsList.add(result); }); ScaffoldMessenger.of( context, ).showSnackBar(const SnackBar(content: Text('물품이 등록되었습니다.'))); } } void _showEditGoodsDialog(int index) async { final result = await showDialog<_GoodsItem>( context: context, builder: (context) => _GoodsFormDialog(item: _goodsList[index]), ); if (result != null) { setState(() { _goodsList[index] = result; }); ScaffoldMessenger.of( context, ).showSnackBar(const SnackBar(content: Text('물품 정보가 수정되었습니다.'))); } } void _deleteGoods(int index) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('삭제 확인'), content: const Text('이 물품 정보를 삭제하시겠습니까?'), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('취소'), ), TextButton( onPressed: () { setState(() { _goodsList.removeAt(index); }); Navigator.pop(context); ScaffoldMessenger.of( context, ).showSnackBar(const SnackBar(content: Text('물품이 삭제되었습니다.'))); }, child: const Text('삭제'), ), ], ), ); } @override Widget build(BuildContext context) { final screenWidth = MediaQuery.of(context).size.width; final maxContentWidth = screenWidth > 1200 ? 1200.0 : screenWidth - 32; final int totalCount = _goodsList.length; final int startIndex = (_currentPage - 1) * _pageSize; final int endIndex = (startIndex + _pageSize) > totalCount ? totalCount : (startIndex + _pageSize); final pagedGoods = _goodsList.sublist(startIndex, endIndex); return MainLayout( title: '물품 관리', currentRoute: Routes.goods, actions: [ IconButton( icon: const Icon(Icons.refresh), onPressed: _loadGoods, color: Colors.grey, ), ], child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ PageTitle( title: '물품 목록', width: maxContentWidth - 32, rightWidget: ElevatedButton.icon( onPressed: _showAddGoodsDialog, icon: const Icon(Icons.add), label: const Text('추가'), style: AppThemeTailwind.primaryButtonStyle, ), ), Expanded( child: DataTableCard( width: maxContentWidth - 32, child: pagedGoods.isEmpty ? const Center(child: Text('등록된 물품이 없습니다.')) : SingleChildScrollView( scrollDirection: Axis.horizontal, child: Container( constraints: BoxConstraints( minWidth: maxContentWidth - 64, ), child: SingleChildScrollView( scrollDirection: Axis.vertical, child: DataTable( columns: const [ DataColumn(label: Text('번호')), DataColumn(label: Text('이름')), DataColumn(label: Text('제조사')), DataColumn(label: Text('대분류')), DataColumn(label: Text('중분류')), DataColumn(label: Text('소분류')), DataColumn(label: Text('관리')), ], rows: List.generate(pagedGoods.length, (i) { final item = pagedGoods[i]; final realIndex = startIndex + i; return DataRow( cells: [ DataCell(Text('${realIndex + 1}')), DataCell(Text(item.name)), DataCell(Text(item.manufacturer)), DataCell(Text(item.category)), DataCell(Text(item.subCategory)), DataCell(Text(item.subSubCategory)), DataCell( Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: const Icon( Icons.edit, color: AppThemeTailwind.primary, ), onPressed: () => _showEditGoodsDialog( realIndex, ), ), IconButton( icon: const Icon( Icons.delete, color: AppThemeTailwind.danger, ), onPressed: () => _deleteGoods(realIndex), ), ], ), ), ], ); }), ), ), ), ), ), ), if (totalCount > _pageSize) Padding( padding: const EdgeInsets.symmetric(vertical: 12), child: Pagination( totalCount: totalCount, currentPage: _currentPage, pageSize: _pageSize, onPageChanged: (page) { setState(() { _currentPage = page; }); }, ), ), ], ), ), ); } } /// 물품 데이터 모델 (이름, 제조사, 대중소분류) class _GoodsItem { final String name; final String manufacturer; final String category; final String subCategory; final String subSubCategory; _GoodsItem({ required this.name, required this.manufacturer, required this.category, required this.subCategory, required this.subSubCategory, }); } /// 물품 등록/수정 폼 다이얼로그 class _GoodsFormDialog extends StatefulWidget { final _GoodsItem? item; const _GoodsFormDialog({this.item}); @override State<_GoodsFormDialog> createState() => _GoodsFormDialogState(); } class _GoodsFormDialogState extends State<_GoodsFormDialog> { final _formKey = GlobalKey(); late String _name; late String _manufacturer; late String _category; late String _subCategory; late String _subSubCategory; late final MockDataService _dataService; late final List _manufacturerList; late final List _nameList; late final List _categoryList; late final List _subCategoryList; late final List _subSubCategoryList; @override void initState() { super.initState(); _name = widget.item?.name ?? ''; _manufacturer = widget.item?.manufacturer ?? ''; _category = widget.item?.category ?? ''; _subCategory = widget.item?.subCategory ?? ''; _subSubCategory = widget.item?.subSubCategory ?? ''; _dataService = MockDataService(); _manufacturerList = _dataService.getAllManufacturers(); _nameList = _dataService.getAllEquipmentNames(); _categoryList = _dataService.getAllCategories(); _subCategoryList = _dataService.getAllSubCategories(); _subSubCategoryList = _dataService.getAllSubSubCategories(); } @override Widget build(BuildContext context) { return Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 420), child: Padding( padding: const EdgeInsets.all(24.0), child: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.item == null ? '신상품 등록' : '신상품 정보 수정', style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 24), FormFieldWrapper( label: '이름', isRequired: true, child: CategoryAutocompleteField( hintText: '이름을 입력 또는 선택하세요', value: _name, items: _nameList, isRequired: true, onSelect: (v) => setState(() => _name = v), ), ), FormFieldWrapper( label: '제조사', isRequired: true, child: CategoryAutocompleteField( hintText: '제조사를 입력 또는 선택하세요', value: _manufacturer, items: _manufacturerList, isRequired: true, onSelect: (v) => setState(() => _manufacturer = v), ), ), FormFieldWrapper( label: '대분류', isRequired: true, child: CategoryAutocompleteField( hintText: '대분류를 입력 또는 선택하세요', value: _category, items: _categoryList, isRequired: true, onSelect: (v) => setState(() => _category = v), ), ), FormFieldWrapper( label: '중분류', isRequired: true, child: CategoryAutocompleteField( hintText: '중분류를 입력 또는 선택하세요', value: _subCategory, items: _subCategoryList, isRequired: true, onSelect: (v) => setState(() => _subCategory = v), ), ), FormFieldWrapper( label: '소분류', isRequired: true, child: CategoryAutocompleteField( hintText: '소분류를 입력 또는 선택하세요', value: _subSubCategory, items: _subSubCategoryList, isRequired: true, onSelect: (v) => setState(() => _subSubCategory = v), ), ), const SizedBox(height: 24), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('취소'), ), const SizedBox(width: 8), ElevatedButton( style: AppThemeTailwind.primaryButtonStyle, onPressed: () { if (_formKey.currentState?.validate() ?? false) { Navigator.of(context).pop( _GoodsItem( name: _name, manufacturer: _manufacturer, category: _category, subCategory: _subCategory, subSubCategory: _subSubCategory, ), ); } }, child: Text(widget.item == null ? '등록' : '수정'), ), ], ), ], ), ), ), ), ); } }