결재 단계 UI 보완 및 분석 통과
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart' as lucide;
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
|
||||
@@ -442,6 +441,7 @@ class _ApprovalTemplateEnabledPageState
|
||||
|
||||
Future<bool?> _openTemplateForm({ApprovalTemplate? template}) async {
|
||||
final isEdit = template != null;
|
||||
final existingTemplate = template;
|
||||
final codeController = TextEditingController(text: template?.code ?? '');
|
||||
final nameController = TextEditingController(text: template?.name ?? '');
|
||||
final descriptionController = TextEditingController(
|
||||
@@ -587,77 +587,76 @@ class _ApprovalTemplateEnabledPageState
|
||||
),
|
||||
actions: [
|
||||
ShadButton.ghost(
|
||||
onPressed: isSaving ? null : () => Navigator.of(context).pop(false),
|
||||
onPressed: () {
|
||||
if (isSaving) return;
|
||||
Navigator.of(context).pop(false);
|
||||
},
|
||||
child: const Text('취소'),
|
||||
),
|
||||
ShadButton(
|
||||
onPressed: isSaving
|
||||
? null
|
||||
: () async {
|
||||
final codeValue = codeController.text.trim();
|
||||
final nameValue = nameController.text.trim();
|
||||
if (!isEdit && codeValue.isEmpty) {
|
||||
modalSetState?.call(() => errorText = '템플릿 코드를 입력하세요.');
|
||||
return;
|
||||
}
|
||||
if (nameValue.isEmpty) {
|
||||
modalSetState?.call(() => errorText = '템플릿명을 입력하세요.');
|
||||
return;
|
||||
}
|
||||
final validation = _validateSteps(steps);
|
||||
if (validation != null) {
|
||||
modalSetState?.call(() => errorText = validation);
|
||||
return;
|
||||
}
|
||||
modalSetState?.call(() => errorText = null);
|
||||
final stepInputs = steps
|
||||
.map(
|
||||
(field) => ApprovalTemplateStepInput(
|
||||
id: field.id,
|
||||
stepOrder: int.parse(
|
||||
field.orderController.text.trim(),
|
||||
),
|
||||
approverId: int.parse(
|
||||
field.approverController.text.trim(),
|
||||
),
|
||||
note: field.noteController.text.trim().isEmpty
|
||||
? null
|
||||
: field.noteController.text.trim(),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
final input = ApprovalTemplateInput(
|
||||
code: isEdit ? template!.code : codeValue,
|
||||
name: nameValue,
|
||||
description: descriptionController.text.trim().isEmpty
|
||||
onPressed: () async {
|
||||
if (isSaving) return;
|
||||
final codeValue = codeController.text.trim();
|
||||
final nameValue = nameController.text.trim();
|
||||
if (!isEdit && codeValue.isEmpty) {
|
||||
modalSetState?.call(() => errorText = '템플릿 코드를 입력하세요.');
|
||||
return;
|
||||
}
|
||||
if (nameValue.isEmpty) {
|
||||
modalSetState?.call(() => errorText = '템플릿명을 입력하세요.');
|
||||
return;
|
||||
}
|
||||
final validation = _validateSteps(steps);
|
||||
if (validation != null) {
|
||||
modalSetState?.call(() => errorText = validation);
|
||||
return;
|
||||
}
|
||||
modalSetState?.call(() => errorText = null);
|
||||
final stepInputs = steps
|
||||
.map(
|
||||
(field) => ApprovalTemplateStepInput(
|
||||
id: field.id,
|
||||
stepOrder: int.parse(field.orderController.text.trim()),
|
||||
approverId: int.parse(field.approverController.text.trim()),
|
||||
note: field.noteController.text.trim().isEmpty
|
||||
? null
|
||||
: descriptionController.text.trim(),
|
||||
note: noteController.text.trim().isEmpty
|
||||
? null
|
||||
: noteController.text.trim(),
|
||||
isActive: statusNotifier.value,
|
||||
);
|
||||
modalSetState?.call(() => isSaving = true);
|
||||
final success = isEdit
|
||||
? await _controller.update(
|
||||
template!.id,
|
||||
input,
|
||||
stepInputs,
|
||||
)
|
||||
: await _controller.create(input, stepInputs);
|
||||
if (success != null && mounted) {
|
||||
Navigator.of(context).pop(true);
|
||||
} else {
|
||||
modalSetState?.call(() => isSaving = false);
|
||||
}
|
||||
},
|
||||
child: isSaving
|
||||
? const SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
: field.noteController.text.trim(),
|
||||
),
|
||||
)
|
||||
: Text(isEdit ? '수정 완료' : '생성 완료'),
|
||||
.toList();
|
||||
final input = ApprovalTemplateInput(
|
||||
code: isEdit ? existingTemplate?.code : codeValue,
|
||||
name: nameValue,
|
||||
description: descriptionController.text.trim().isEmpty
|
||||
? null
|
||||
: descriptionController.text.trim(),
|
||||
note: noteController.text.trim().isEmpty
|
||||
? null
|
||||
: noteController.text.trim(),
|
||||
isActive: statusNotifier.value,
|
||||
);
|
||||
if (isEdit && existingTemplate == null) {
|
||||
modalSetState?.call(() => errorText = '템플릿 정보를 불러오지 못했습니다.');
|
||||
modalSetState?.call(() => isSaving = false);
|
||||
return;
|
||||
}
|
||||
|
||||
modalSetState?.call(() => isSaving = true);
|
||||
|
||||
final success = isEdit && existingTemplate != null
|
||||
? await _controller.update(
|
||||
existingTemplate.id,
|
||||
input,
|
||||
stepInputs,
|
||||
)
|
||||
: await _controller.create(input, stepInputs);
|
||||
if (success != null && mounted) {
|
||||
Navigator.of(context).pop(true);
|
||||
} else {
|
||||
modalSetState?.call(() => isSaving = false);
|
||||
}
|
||||
},
|
||||
child: Text(isEdit ? '수정 완료' : '생성 완료'),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -780,7 +779,9 @@ class _StepEditorRow extends StatelessWidget {
|
||||
margin: const EdgeInsets.symmetric(vertical: 6),
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: theme.colorScheme.border.withOpacity(0.6)),
|
||||
border: Border.all(
|
||||
color: theme.colorScheme.border.withValues(alpha: 0.6),
|
||||
),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
|
||||
Reference in New Issue
Block a user