결재 비활성 안내 개선 및 테이블 기능 보강

This commit is contained in:
JiWoong Sul
2025-09-29 15:49:06 +09:00
parent fef7108479
commit 98724762ec
18 changed files with 1134 additions and 297 deletions

View File

@@ -13,7 +13,7 @@ import '../../../../widgets/components/filter_bar.dart';
import '../../../../widgets/components/superport_date_picker.dart';
import '../../../../widgets/components/superport_dialog.dart';
import '../../../../widgets/components/superport_table.dart';
import '../../../../widgets/spec_page.dart';
import '../../../../widgets/components/feature_disabled_placeholder.dart';
import '../../domain/entities/approval.dart';
import '../../domain/entities/approval_template.dart';
import '../../domain/repositories/approval_repository.dart';
@@ -29,69 +29,28 @@ class ApprovalPage extends StatelessWidget {
Widget build(BuildContext context) {
final enabled = Environment.flag('FEATURE_APPROVALS_ENABLED');
if (!enabled) {
return SpecPage(
return AppLayout(
title: '결재 관리',
summary: '결재 요청 상태와 단계/이력을 모니터링합니다.',
trailing: ShadBadge(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
child: Row(
mainAxisSize: MainAxisSize.min,
children: const [
Icon(lucide.LucideIcons.info, size: 14),
SizedBox(width: 6),
Text('비활성화 (백엔드 준비 중)'),
],
),
),
),
sections: const [
SpecSection(
title: '입력 폼',
items: [
'트랜잭션번호 [Dropdown]',
'상신자 [ReadOnly]',
'결재상태 [Dropdown]',
'비고 [Textarea]',
],
),
SpecSection(
title: '상세 패널',
items: [
'개요 탭: 현재 상태/단계/요청·결정 일시',
'단계 탭: 단계 리스트 + 템플릿 불러오기',
'이력 탭: 행위/상태 변경/일시/비고',
],
),
SpecSection(
title: '테이블 리스트',
description: '1행 예시',
table: SpecTable(
columns: [
'번호',
'결재번호',
'트랜잭션번호',
'상태',
'상신자',
'요청일시',
'최종결정일시',
'비고',
],
rows: [
[
'1',
'AP-24001',
'TRX-202404-01',
'대기',
'김철수',
'2024-04-01 09:12',
'-',
'-',
],
],
subtitle: '결재 요청 상태와 단계/이력을 한 화면에서 확인합니다.',
breadcrumbs: const [
AppBreadcrumbItem(label: '대시보드', path: dashboardRoutePath),
AppBreadcrumbItem(label: '결재', path: '/approvals/requests'),
AppBreadcrumbItem(label: '결재 관리'),
],
actions: [
Tooltip(
message: '백엔드 연동 후 사용 가능합니다.',
child: ShadButton(
onPressed: null,
leading: const Icon(lucide.LucideIcons.plus, size: 16),
child: const Text('신규 결재'),
),
),
],
child: const FeatureDisabledPlaceholder(
title: '결재 관리 기능 준비 중',
description: '결재 API 연결이 완료되면 실제 결재 요청 목록과 단계 정보를 제공합니다.',
),
);
}
@@ -181,6 +140,10 @@ class _ApprovalEnabledPageState extends State<_ApprovalEnabledPage> {
_approvalsResourcePath,
PermissionAction.approve,
);
final canManageTemplates = permissionManager.can(
_approvalsResourcePath,
PermissionAction.edit,
);
if (templates.isNotEmpty && _selectedTemplateId == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -367,6 +330,7 @@ class _ApprovalEnabledPageState extends State<_ApprovalEnabledPage> {
applyingTemplateId: applyingTemplateId,
selectedTemplateId: _selectedTemplateId,
canPerformStepActions: canPerformStepActions,
canApplyTemplate: canManageTemplates,
dateFormat: _dateTimeFormat,
onRefresh: () {
final id = selectedApproval?.id;
@@ -745,6 +709,7 @@ class _DetailSection extends StatelessWidget {
required this.applyingTemplateId,
required this.selectedTemplateId,
required this.canPerformStepActions,
required this.canApplyTemplate,
required this.dateFormat,
required this.onRefresh,
required this.onClose,
@@ -766,6 +731,7 @@ class _DetailSection extends StatelessWidget {
final int? applyingTemplateId;
final int? selectedTemplateId;
final bool canPerformStepActions;
final bool canApplyTemplate;
final intl.DateFormat dateFormat;
final VoidCallback onRefresh;
final VoidCallback? onClose;
@@ -845,6 +811,7 @@ class _DetailSection extends StatelessWidget {
applyingTemplateId: applyingTemplateId,
selectedTemplateId: selectedTemplateId,
canPerformStepActions: canPerformStepActions,
canApplyTemplate: canApplyTemplate,
onSelectTemplate: onSelectTemplate,
onApplyTemplate: onApplyTemplate,
onReloadTemplates: onReloadTemplates,
@@ -942,6 +909,7 @@ class _StepTab extends StatelessWidget {
required this.applyingTemplateId,
required this.selectedTemplateId,
required this.canPerformStepActions,
required this.canApplyTemplate,
required this.onSelectTemplate,
required this.onApplyTemplate,
required this.onReloadTemplates,
@@ -961,6 +929,7 @@ class _StepTab extends StatelessWidget {
final int? applyingTemplateId;
final int? selectedTemplateId;
final bool canPerformStepActions;
final bool canApplyTemplate;
final void Function(int?) onSelectTemplate;
final void Function(int templateId) onApplyTemplate;
final VoidCallback onReloadTemplates;
@@ -980,12 +949,20 @@ class _StepTab extends StatelessWidget {
selectedTemplateId: selectedTemplateId,
isApplyingTemplate: isApplyingTemplate,
applyingTemplateId: applyingTemplateId,
canApplyTemplate: canPerformStepActions,
canApplyTemplate: canApplyTemplate,
onSelectTemplate: onSelectTemplate,
onApplyTemplate: onApplyTemplate,
onReload: onReloadTemplates,
),
),
if (!canApplyTemplate)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Text(
'템플릿 적용 권한이 없어 단계 구성을 변경할 수 없습니다.',
style: theme.textTheme.muted,
),
),
if (!isLoadingTemplates && templates.isEmpty)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),