backup: 사용하지 않는 파일 삭제 전 복구 지점
- 전체 371개 파일 중 82개 미사용 파일 식별 - Phase 1: 33개 파일 삭제 예정 (100% 안전) - Phase 2: 30개 파일 삭제 검토 예정 - Phase 3: 19개 파일 수동 검토 예정 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:superport/data/models/equipment_history_dto.dart';
|
||||
import 'package:superport/data/models/stock_status_dto.dart';
|
||||
import 'package:superport/domain/usecases/equipment_history_usecase.dart';
|
||||
import 'package:superport/services/equipment_history_service.dart';
|
||||
import 'package:superport/injection_container.dart';
|
||||
import 'package:superport/utils/constants.dart';
|
||||
import 'package:superport/core/constants/app_constants.dart';
|
||||
|
||||
class EquipmentHistoryController extends ChangeNotifier {
|
||||
final EquipmentHistoryUseCase _useCase = getIt<EquipmentHistoryUseCase>();
|
||||
final EquipmentHistoryService _service = EquipmentHistoryService();
|
||||
|
||||
// 상태 관리
|
||||
bool _isLoading = false;
|
||||
@@ -15,9 +18,10 @@ class EquipmentHistoryController extends ChangeNotifier {
|
||||
|
||||
// 데이터 (백엔드 스키마 기반)
|
||||
List<EquipmentHistoryDto> _histories = [];
|
||||
List<StockStatusDto> _stockStatus = [];
|
||||
int _totalCount = 0;
|
||||
int _currentPage = 1;
|
||||
final int _pageSize = PaginationConstants.defaultPageSize;
|
||||
final int _pageSize = AppConstants.historyPageSize;
|
||||
|
||||
// 필터
|
||||
int? _filterEquipmentId;
|
||||
@@ -34,6 +38,7 @@ class EquipmentHistoryController extends ChangeNotifier {
|
||||
String? get errorMessage => _errorMessage;
|
||||
String? get successMessage => _successMessage;
|
||||
List<EquipmentHistoryDto> get histories => _histories;
|
||||
List<StockStatusDto> get stockStatus => _stockStatus;
|
||||
int get totalCount => _totalCount;
|
||||
int get currentPage => _currentPage;
|
||||
int get pageSize => _pageSize;
|
||||
@@ -271,6 +276,23 @@ class EquipmentHistoryController extends ChangeNotifier {
|
||||
};
|
||||
}
|
||||
|
||||
/// 재고 현황 조회 (핵심 기능)
|
||||
Future<void> loadStockStatus() async {
|
||||
_isLoading = true;
|
||||
_errorMessage = null;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
_stockStatus = await _service.getStockStatus();
|
||||
} catch (e) {
|
||||
_errorMessage = e.toString();
|
||||
_stockStatus = [];
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// 메시지 클리어
|
||||
void clearMessages() {
|
||||
_errorMessage = null;
|
||||
@@ -281,6 +303,7 @@ class EquipmentHistoryController extends ChangeNotifier {
|
||||
@override
|
||||
void dispose() {
|
||||
_histories.clear();
|
||||
_stockStatus.clear();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import '../equipment/controllers/equipment_history_controller.dart';
|
||||
import 'controllers/equipment_history_controller.dart';
|
||||
|
||||
class InventoryDashboard extends StatefulWidget {
|
||||
const InventoryDashboard({super.key});
|
||||
@@ -16,7 +16,7 @@ class _InventoryDashboardState extends State<InventoryDashboard> {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final controller = context.read<EquipmentHistoryController>();
|
||||
controller.loadHistory(refresh: true);
|
||||
controller.loadStockStatus(); // 재고 현황 로드
|
||||
});
|
||||
}
|
||||
|
||||
@@ -68,8 +68,8 @@ class _InventoryDashboardState extends State<InventoryDashboard> {
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
controller.loadInventoryStatus();
|
||||
controller.loadWarehouseStock();
|
||||
controller.loadStockStatus();
|
||||
controller.loadHistories();
|
||||
},
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
@@ -127,7 +127,7 @@ class _InventoryDashboardState extends State<InventoryDashboard> {
|
||||
_buildStatCard(
|
||||
theme,
|
||||
title: '총 거래',
|
||||
value: '${controller.historyList.length}',
|
||||
value: '${controller.histories.length}',
|
||||
unit: '건',
|
||||
icon: Icons.history,
|
||||
color: Colors.blue,
|
||||
@@ -145,12 +145,12 @@ class _InventoryDashboardState extends State<InventoryDashboard> {
|
||||
ShadCard(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: controller.historyList.isEmpty
|
||||
child: controller.histories.isEmpty
|
||||
? const Center(
|
||||
child: Text('거래 이력이 없습니다.'),
|
||||
)
|
||||
: Column(
|
||||
children: controller.historyList.take(10).map((history) {
|
||||
children: controller.histories.take(10).map((history) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Row(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import '../../core/constants/app_constants.dart';
|
||||
import '../../screens/equipment/controllers/equipment_history_controller.dart';
|
||||
import 'components/transaction_type_badge.dart';
|
||||
import '../common/layouts/base_list_screen.dart';
|
||||
@@ -34,17 +35,28 @@ class _InventoryHistoryScreenState extends State<InventoryHistoryScreen> {
|
||||
}
|
||||
|
||||
void _onSearch() {
|
||||
final searchQuery = _searchController.text.trim();
|
||||
setState(() {
|
||||
_appliedSearchKeyword = _searchController.text;
|
||||
_appliedSearchKeyword = searchQuery;
|
||||
});
|
||||
// 검색 로직은 Controller에 추가 예정
|
||||
// ✅ Controller 검색 메서드 연동
|
||||
context.read<EquipmentHistoryController>().setFilters(
|
||||
searchQuery: searchQuery.isNotEmpty ? searchQuery : null,
|
||||
transactionType: _selectedType != 'all' ? _selectedType : null,
|
||||
);
|
||||
}
|
||||
|
||||
void _clearSearch() {
|
||||
_searchController.clear();
|
||||
setState(() {
|
||||
_appliedSearchKeyword = '';
|
||||
_selectedType = 'all';
|
||||
});
|
||||
// ✅ Controller 필터 초기화
|
||||
context.read<EquipmentHistoryController>().setFilters(
|
||||
searchQuery: null,
|
||||
transactionType: null,
|
||||
);
|
||||
}
|
||||
|
||||
/// 헤더 셀 빌더
|
||||
@@ -282,6 +294,11 @@ class _InventoryHistoryScreenState extends State<InventoryHistoryScreen> {
|
||||
setState(() {
|
||||
_selectedType = value;
|
||||
});
|
||||
// ✅ 필터 변경 시 즉시 Controller에 반영
|
||||
context.read<EquipmentHistoryController>().setFilters(
|
||||
searchQuery: _appliedSearchKeyword.isNotEmpty ? _appliedSearchKeyword : null,
|
||||
transactionType: value != 'all' ? value : null,
|
||||
);
|
||||
}
|
||||
},
|
||||
style: ShadTheme.of(context).textTheme.large,
|
||||
@@ -480,7 +497,7 @@ class _InventoryHistoryScreenState extends State<InventoryHistoryScreen> {
|
||||
? Pagination(
|
||||
totalCount: controller.totalCount,
|
||||
currentPage: controller.currentPage,
|
||||
pageSize: 10, // controller.pageSize 대신 고정값 사용
|
||||
pageSize: AppConstants.historyPageSize, // controller.pageSize 대신 고정값 사용
|
||||
onPageChanged: (page) => {
|
||||
// 페이지 변경 로직 - 추후 Controller에 추가 예정
|
||||
},
|
||||
|
||||
@@ -4,6 +4,9 @@ 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});
|
||||
@@ -14,6 +17,7 @@ class StockInForm extends StatefulWidget {
|
||||
|
||||
class _StockInFormState extends State<StockInForm> {
|
||||
final _formKey = GlobalKey<ShadFormState>();
|
||||
final _warehouseService = GetIt.instance<WarehouseService>();
|
||||
|
||||
int? _selectedEquipmentId;
|
||||
int? _selectedWarehouseId;
|
||||
@@ -21,15 +25,53 @@ class _StockInFormState extends State<StockInForm> {
|
||||
DateTime _transactionDate = DateTime.now();
|
||||
String? _notes;
|
||||
|
||||
// 창고 관련 상태
|
||||
List<WarehouseDto> _warehouses = [];
|
||||
bool _isLoadingWarehouses = false;
|
||||
String? _warehouseError;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
// 장비 목록 로드
|
||||
context.read<EquipmentListController>().refresh();
|
||||
// 창고 목록 로드
|
||||
_loadWarehouses();
|
||||
});
|
||||
}
|
||||
|
||||
/// 사용 중인 창고 목록 로드
|
||||
Future<void> _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<void> _handleSubmit() async {
|
||||
if (_formKey.currentState?.saveAndValidate() ?? false) {
|
||||
final controller = context.read<EquipmentHistoryController>();
|
||||
@@ -130,31 +172,80 @@ class _StockInFormState extends State<StockInForm> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// 창고 선택
|
||||
ShadSelect<int>(
|
||||
placeholder: const Text('창고 선택'),
|
||||
options: [
|
||||
const ShadOption(value: 1, child: Text('본사 창고')),
|
||||
const ShadOption(value: 2, child: Text('지사 창고')),
|
||||
const ShadOption(value: 3, child: Text('외부 창고')),
|
||||
// 창고 선택 (백엔드 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<int>(
|
||||
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;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
selectedOptionBuilder: (context, value) {
|
||||
switch (value) {
|
||||
case 1:
|
||||
return const Text('본사 창고');
|
||||
case 2:
|
||||
return const Text('지사 창고');
|
||||
case 3:
|
||||
return const Text('외부 창고');
|
||||
default:
|
||||
return const Text('');
|
||||
}
|
||||
},
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_selectedWarehouseId = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
@@ -201,43 +292,6 @@ class _StockInFormState extends State<StockInForm> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// 상태
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text('상태', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500)),
|
||||
const SizedBox(height: 8),
|
||||
ShadSelect<String>(
|
||||
placeholder: const Text('상태 선택'),
|
||||
initialValue: 'available',
|
||||
options: const [
|
||||
ShadOption(value: 'available', child: Text('사용 가능')),
|
||||
ShadOption(value: 'in_use', child: Text('사용 중')),
|
||||
ShadOption(value: 'maintenance', child: Text('정비 중')),
|
||||
ShadOption(value: 'reserved', child: Text('예약됨')),
|
||||
],
|
||||
selectedOptionBuilder: (context, value) {
|
||||
switch (value) {
|
||||
case 'available':
|
||||
return const Text('사용 가능');
|
||||
case 'in_use':
|
||||
return const Text('사용 중');
|
||||
case 'maintenance':
|
||||
return const Text('정비 중');
|
||||
case 'reserved':
|
||||
return const Text('예약됨');
|
||||
default:
|
||||
return const Text('');
|
||||
}
|
||||
},
|
||||
onChanged: (value) {
|
||||
// 상태 변경 시 필요한 로직이 있다면 여기에 추가
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// 비고
|
||||
ShadInputFormField(
|
||||
label: const Text('비고'),
|
||||
|
||||
Reference in New Issue
Block a user