Files
superport/lib/screens/model/components/model_vendor_cascade.dart
JiWoong Sul c419f8f458 backup: 사용하지 않는 파일 삭제 전 복구 지점
- 전체 371개 파일 중 82개 미사용 파일 식별
- Phase 1: 33개 파일 삭제 예정 (100% 안전)
- Phase 2: 30개 파일 삭제 검토 예정
- Phase 3: 19개 파일 수동 검토 예정

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-02 19:51:40 +09:00

228 lines
6.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import 'package:superport/data/models/model/model_dto.dart';
import 'package:superport/data/models/vendor_dto.dart';
import 'package:superport/screens/model/controllers/model_controller.dart';
/// Vendor → Model 캐스케이드 선택 컴포넌트
/// Equipment 등의 화면에서 재사용 가능
class ModelVendorCascade extends StatefulWidget {
final ModelController controller;
final int? initialVendorId;
final int? initialModelId;
final void Function(int? vendorId, int? modelId)? onChanged;
final bool isRequired;
const ModelVendorCascade({
super.key,
required this.controller,
this.initialVendorId,
this.initialModelId,
this.onChanged,
this.isRequired = true,
});
@override
State<ModelVendorCascade> createState() => _ModelVendorCascadeState();
}
class _ModelVendorCascadeState extends State<ModelVendorCascade> {
int? _selectedVendorId;
int? _selectedModelId;
List<ModelDto> _availableModels = [];
bool _isLoadingModels = false;
@override
void initState() {
super.initState();
_selectedVendorId = widget.initialVendorId;
_selectedModelId = widget.initialModelId;
// 초기 vendor가 있으면 모델 로드
if (_selectedVendorId != null) {
_loadModelsForVendor(_selectedVendorId!);
}
}
Future<void> _loadModelsForVendor(int vendorId) async {
setState(() {
_isLoadingModels = true;
});
try {
// Controller에서 해당 vendor의 모델 가져오기
final models = widget.controller.getModelsByVendor(vendorId);
setState(() {
_availableModels = models;
// 선택된 모델이 새 vendor의 모델 목록에 없으면 초기화
if (_selectedModelId != null &&
!models.any((m) => m.id == _selectedModelId)) {
_selectedModelId = null;
}
});
} finally {
setState(() {
_isLoadingModels = false;
});
}
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Vendor 선택
_buildVendorSelect(),
const SizedBox(height: 16),
// Model 선택 (Vendor가 선택된 경우에만 표시)
if (_selectedVendorId != null) _buildModelSelect(),
],
);
}
Widget _buildVendorSelect() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'제조사',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w500,
),
),
if (widget.isRequired)
const Text(
' *',
style: TextStyle(color: Colors.red),
),
],
),
const SizedBox(height: 8),
ShadSelect<int?>(
placeholder: const Text('제조사를 선택하세요'),
options: [
if (!widget.isRequired)
const ShadOption(
value: null,
child: Text('선택 안함'),
),
...widget.controller.vendors.map(
(vendor) => ShadOption(
value: vendor.id,
child: Text(vendor.name),
),
),
],
selectedOptionBuilder: (context, value) {
if (value == null) {
return const Text('선택 안함');
}
final vendor = widget.controller.vendors.firstWhere(
(v) => v.id == value,
orElse: () => const VendorDto(
name: 'Unknown',
),
);
return Text(vendor.name);
},
onChanged: (value) {
setState(() {
_selectedVendorId = value;
_selectedModelId = null; // Vendor 변경 시 Model 초기화
_availableModels.clear();
});
if (value != null) {
_loadModelsForVendor(value);
}
// 콜백 호출
widget.onChanged?.call(value, null);
},
initialValue: _selectedVendorId,
),
],
);
}
Widget _buildModelSelect() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'모델',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w500,
),
),
if (widget.isRequired)
const Text(
' *',
style: TextStyle(color: Colors.red),
),
],
),
const SizedBox(height: 8),
if (_isLoadingModels)
const ShadInput(
placeholder: Text('모델 로딩 중...'),
enabled: false,
)
else if (_availableModels.isEmpty)
const ShadInput(
placeholder: Text('해당 제조사에 등록된 모델이 없습니다'),
enabled: false,
)
else
ShadSelect<int?>(
placeholder: const Text('모델을 선택하세요'),
options: [
if (!widget.isRequired)
const ShadOption(
value: null,
child: Text('선택 안함'),
),
..._availableModels.map(
(model) => ShadOption(
value: model.id,
child: Text(model.name),
),
),
],
selectedOptionBuilder: (context, value) {
if (value == null) {
return const Text('선택 안함');
}
final model = _availableModels.firstWhere(
(m) => m.id == value,
orElse: () => ModelDto(
id: value,
vendorsId: _selectedVendorId!,
name: 'Unknown',
isDeleted: false,
registeredAt: DateTime.now(),
),
);
return Text(model.name);
},
onChanged: (value) {
setState(() {
_selectedModelId = value;
});
// 콜백 호출
widget.onChanged?.call(_selectedVendorId, value);
},
initialValue: _selectedModelId,
),
],
);
}
}