결재 단계 UI 보완 및 분석 통과

This commit is contained in:
JiWoong Sul
2025-09-25 17:18:08 +09:00
parent c31f6217ef
commit 6d6781f552
7 changed files with 99 additions and 103 deletions

View File

@@ -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(