Files
superport/lib/screens/model/model_form_dialog.dart

189 lines
5.3 KiB
Dart

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<ModelFormDialog> createState() => _ModelFormDialogState();
}
class _ModelFormDialogState extends State<ModelFormDialog> {
final _formKey = GlobalKey<FormState>();
late final TextEditingController _nameController;
int? _selectedVendorId;
bool _isSubmitting = false;
@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<int>(
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: 16),
// 활성 상태는 백엔드에서 관리하므로 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<void> _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;
});
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;
});
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,
),
);
}
}
}
}