feat: [approval] 결재서명란 테이블 추가 (전통 결재 양식)
- 문서 상세 우측 상단에 결재서명란 테이블 배치 - 작성자 + 결재자 컬럼, 직급/이름/서명/날짜 표시 - 승인/반려/보류/전결 상태별 도장 아이콘 - 기존 원형 타임라인 결재 진행 제거, 결재 의견만 유지
This commit is contained in:
@@ -0,0 +1,83 @@
|
|||||||
|
{{--
|
||||||
|
결재서명란 (전통 테이블 형식)
|
||||||
|
Props:
|
||||||
|
$approval (Approval model) - 결재 문서
|
||||||
|
--}}
|
||||||
|
@php
|
||||||
|
$drafter = $approval->drafter;
|
||||||
|
$approverSteps = $approval->steps->whereIn('step_type', ['approval', 'agreement'])->sortBy('step_order')->values();
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<table style="border-collapse: collapse; border: 2px solid #4338ca; font-size: 12px; min-width: 120px;">
|
||||||
|
<tbody>
|
||||||
|
{{-- 1행: 직급/역할 --}}
|
||||||
|
<tr>
|
||||||
|
<td rowspan="3" style="border: 1px solid #a5b4fc; padding: 4px 6px; text-align: center; font-weight: 700; color: #4338ca; background: #eef2ff; writing-mode: vertical-rl; letter-spacing: 6px; width: 28px; font-size: 13px;">
|
||||||
|
결재
|
||||||
|
</td>
|
||||||
|
<td style="border: 1px solid #c7d2fe; padding: 4px 10px; text-align: center; font-weight: 600; color: #374151; background: #f9fafb; min-width: 64px; white-space: nowrap;">
|
||||||
|
작성자
|
||||||
|
</td>
|
||||||
|
@foreach($approverSteps as $step)
|
||||||
|
<td style="border: 1px solid #c7d2fe; padding: 4px 10px; text-align: center; font-weight: 600; color: #374151; background: #f9fafb; min-width: 64px; white-space: nowrap;">
|
||||||
|
{{ $step->approver_position ?: ($step->step_type === 'agreement' ? '합의' : '결재') }}
|
||||||
|
</td>
|
||||||
|
@endforeach
|
||||||
|
</tr>
|
||||||
|
{{-- 2행: 서명/도장 영역 --}}
|
||||||
|
<tr>
|
||||||
|
<td style="border: 1px solid #c7d2fe; padding: 6px 10px; text-align: center; height: 40px; vertical-align: middle;">
|
||||||
|
@if(in_array($approval->status, ['pending', 'approved', 'rejected', 'cancelled', 'on_hold']))
|
||||||
|
<span style="color: #2563eb; font-size: 11px; font-weight: 500;">{{ $drafter?->name ?? '-' }}</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
@foreach($approverSteps as $step)
|
||||||
|
<td style="border: 1px solid #c7d2fe; padding: 6px 10px; text-align: center; height: 40px; vertical-align: middle;">
|
||||||
|
@if($step->status === 'approved')
|
||||||
|
@if(($step->approval_type ?? 'normal') === 'pre_decided')
|
||||||
|
<div style="display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: 2px solid #6366f1; border-radius: 50%; color: #6366f1; font-size: 9px; font-weight: 700; line-height: 1;">
|
||||||
|
전결
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<div style="display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: 2px solid #dc2626; border-radius: 50%; color: #dc2626; font-size: 9px; font-weight: 700; line-height: 1;">
|
||||||
|
승인
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@elseif($step->status === 'rejected')
|
||||||
|
<div style="display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: 2px solid #dc2626; border-radius: 50%; color: #dc2626; font-size: 9px; font-weight: 700; line-height: 1;">
|
||||||
|
반려
|
||||||
|
</div>
|
||||||
|
@elseif($step->status === 'on_hold')
|
||||||
|
<div style="display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: 2px solid #d97706; border-radius: 50%; color: #d97706; font-size: 9px; font-weight: 700; line-height: 1;">
|
||||||
|
보류
|
||||||
|
</div>
|
||||||
|
@elseif($step->status === 'skipped')
|
||||||
|
<span style="color: #9ca3af; font-size: 10px;">-</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
@endforeach
|
||||||
|
</tr>
|
||||||
|
{{-- 3행: 이름 + 처리일시 --}}
|
||||||
|
<tr>
|
||||||
|
<td style="border: 1px solid #c7d2fe; padding: 3px 10px; text-align: center; white-space: nowrap;">
|
||||||
|
@if(in_array($approval->status, ['pending', 'approved', 'rejected', 'cancelled', 'on_hold']))
|
||||||
|
<div style="font-size: 10px; color: #6b7280;">
|
||||||
|
{{ $approval->drafted_at?->format('m/d') ?? '' }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
@foreach($approverSteps as $step)
|
||||||
|
<td style="border: 1px solid #c7d2fe; padding: 3px 10px; text-align: center; white-space: nowrap;">
|
||||||
|
<div style="font-size: 11px; color: #374151; font-weight: 500;">
|
||||||
|
{{ $step->approver_name ?? ($step->approver?->name ?? '') }}
|
||||||
|
</div>
|
||||||
|
@if($step->acted_at)
|
||||||
|
<div style="font-size: 10px; color: #6b7280;">
|
||||||
|
{{ $step->acted_at->format('m/d') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
@endforeach
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
@@ -23,44 +23,51 @@ class="bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-lg transition
|
|||||||
|
|
||||||
{{-- 문서 정보 --}}
|
{{-- 문서 정보 --}}
|
||||||
<div class="bg-white rounded-lg shadow-sm p-6 mb-6">
|
<div class="bg-white rounded-lg shadow-sm p-6 mb-6">
|
||||||
<div class="flex flex-wrap gap-y-3 mb-4" style="gap-column: 0;">
|
<div class="flex justify-between items-start gap-4 mb-4">
|
||||||
<div class="pr-6 border-r border-gray-200 mr-6">
|
<div class="flex flex-wrap gap-y-3" style="gap-column: 0;">
|
||||||
<span class="text-xs text-gray-500">상태</span>
|
<div class="pr-6 border-r border-gray-200 mr-6">
|
||||||
<div class="mt-1">
|
<span class="text-xs text-gray-500">상태</span>
|
||||||
@include('approvals.partials._status-badge', ['status' => $approval->status])
|
<div class="mt-1">
|
||||||
@if($approval->is_urgent)
|
@include('approvals.partials._status-badge', ['status' => $approval->status])
|
||||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-700 ml-1">긴급</span>
|
@if($approval->is_urgent)
|
||||||
@endif
|
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-700 ml-1">긴급</span>
|
||||||
</div>
|
@endif
|
||||||
</div>
|
|
||||||
<div class="pr-6 border-r border-gray-200 mr-6">
|
|
||||||
<span class="text-xs text-gray-500">양식</span>
|
|
||||||
<div class="mt-1 text-sm font-medium">{{ $approval->form?->name ?? '-' }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="pr-6 border-r border-gray-200 mr-6">
|
|
||||||
<span class="text-xs text-gray-500">기안자</span>
|
|
||||||
<div class="mt-1 text-sm font-medium">{{ $approval->drafter?->name ?? '-' }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="pr-6{{ $approval->completed_at || $approval->parent_doc_id ? ' border-r border-gray-200 mr-6' : '' }}">
|
|
||||||
<span class="text-xs text-gray-500">기안일</span>
|
|
||||||
<div class="mt-1 text-sm">{{ $approval->drafted_at?->format('Y-m-d H:i') ?? '-' }}</div>
|
|
||||||
</div>
|
|
||||||
@if($approval->completed_at)
|
|
||||||
<div class="pr-6{{ $approval->parent_doc_id ? ' border-r border-gray-200 mr-6' : '' }}">
|
|
||||||
<span class="text-xs text-gray-500">완료일</span>
|
|
||||||
<div class="mt-1 text-sm">{{ $approval->completed_at->format('Y-m-d H:i') }}</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
@if($approval->parent_doc_id)
|
|
||||||
<div class="pr-6">
|
|
||||||
<span class="text-xs text-gray-500">원본 문서</span>
|
|
||||||
<div class="mt-1 text-sm">
|
|
||||||
<a href="{{ route('approvals.show', $approval->parent_doc_id) }}" class="text-blue-600 hover:underline">
|
|
||||||
{{ $approval->parentDocument?->document_number ?? '원본 보기' }}
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
<div class="pr-6 border-r border-gray-200 mr-6">
|
||||||
|
<span class="text-xs text-gray-500">양식</span>
|
||||||
|
<div class="mt-1 text-sm font-medium">{{ $approval->form?->name ?? '-' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="pr-6 border-r border-gray-200 mr-6">
|
||||||
|
<span class="text-xs text-gray-500">기안자</span>
|
||||||
|
<div class="mt-1 text-sm font-medium">{{ $approval->drafter?->name ?? '-' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="pr-6{{ $approval->completed_at || $approval->parent_doc_id ? ' border-r border-gray-200 mr-6' : '' }}">
|
||||||
|
<span class="text-xs text-gray-500">기안일</span>
|
||||||
|
<div class="mt-1 text-sm">{{ $approval->drafted_at?->format('Y-m-d H:i') ?? '-' }}</div>
|
||||||
|
</div>
|
||||||
|
@if($approval->completed_at)
|
||||||
|
<div class="pr-6{{ $approval->parent_doc_id ? ' border-r border-gray-200 mr-6' : '' }}">
|
||||||
|
<span class="text-xs text-gray-500">완료일</span>
|
||||||
|
<div class="mt-1 text-sm">{{ $approval->completed_at->format('Y-m-d H:i') }}</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@if($approval->parent_doc_id)
|
||||||
|
<div class="pr-6">
|
||||||
|
<span class="text-xs text-gray-500">원본 문서</span>
|
||||||
|
<div class="mt-1 text-sm">
|
||||||
|
<a href="{{ route('approvals.show', $approval->parent_doc_id) }}" class="text-blue-600 hover:underline">
|
||||||
|
{{ $approval->parentDocument?->document_number ?? '원본 보기' }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- 결재서명란 --}}
|
||||||
|
<div class="shrink-0">
|
||||||
|
@include('approvals.partials._approval-stamp-table', ['approval' => $approval])
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- 회수 사유 표시 --}}
|
{{-- 회수 사유 표시 --}}
|
||||||
@@ -85,56 +92,47 @@ class="bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-lg transition
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- 결재 진행 단계 --}}
|
{{-- 결재 의견 --}}
|
||||||
|
@php
|
||||||
|
$stepsWithComments = $approval->steps->filter(fn($s) => $s->comment);
|
||||||
|
@endphp
|
||||||
|
@if($stepsWithComments->isNotEmpty())
|
||||||
<div class="bg-white rounded-lg shadow-sm p-6 mb-6">
|
<div class="bg-white rounded-lg shadow-sm p-6 mb-6">
|
||||||
<h3 class="text-lg font-semibold text-gray-800 mb-2">결재 진행</h3>
|
<h3 class="text-lg font-semibold text-gray-800 mb-2">결재 의견</h3>
|
||||||
@include('approvals.partials._step-progress', [
|
<div class="space-y-2">
|
||||||
'steps' => $approval->steps->toArray(),
|
@foreach($stepsWithComments as $step)
|
||||||
'currentStep' => $approval->current_step,
|
<div class="flex gap-3 p-3 bg-gray-50 rounded-lg">
|
||||||
])
|
<div class="shrink-0">
|
||||||
|
@if($step->status === 'approved')
|
||||||
{{-- 결재 의견 목록 --}}
|
@if(($step->approval_type ?? 'normal') === 'pre_decided')
|
||||||
@php
|
<span class="inline-flex items-center justify-center w-6 h-6 rounded-full bg-indigo-100 text-indigo-600 text-xs">⚡</span>
|
||||||
$stepsWithComments = $approval->steps->filter(fn($s) => $s->comment);
|
@else
|
||||||
@endphp
|
<span class="inline-flex items-center justify-center w-6 h-6 rounded-full bg-green-100 text-green-600 text-xs">✓</span>
|
||||||
@if($stepsWithComments->isNotEmpty())
|
@endif
|
||||||
<div class="mt-4 border-t pt-4">
|
@elseif($step->status === 'on_hold')
|
||||||
<h4 class="text-sm font-medium text-gray-700 mb-2">결재 의견</h4>
|
<span class="inline-flex items-center justify-center w-6 h-6 rounded-full bg-amber-100 text-amber-600 text-xs">⏸</span>
|
||||||
<div class="space-y-2">
|
@else
|
||||||
@foreach($stepsWithComments as $step)
|
<span class="inline-flex items-center justify-center w-6 h-6 rounded-full bg-red-100 text-red-600 text-xs">✗</span>
|
||||||
<div class="flex gap-3 p-3 bg-gray-50 rounded-lg">
|
@endif
|
||||||
<div class="shrink-0">
|
</div>
|
||||||
@if($step->status === 'approved')
|
<div>
|
||||||
@if(($step->approval_type ?? 'normal') === 'pre_decided')
|
<div class="text-sm font-medium">
|
||||||
<span class="inline-flex items-center justify-center w-6 h-6 rounded-full bg-indigo-100 text-indigo-600 text-xs">⚡</span>
|
{{ $step->approver_name ?? ($step->approver?->name ?? '') }}
|
||||||
@else
|
@if(($step->approval_type ?? 'normal') === 'pre_decided')
|
||||||
<span class="inline-flex items-center justify-center w-6 h-6 rounded-full bg-green-100 text-green-600 text-xs">✓</span>
|
<span class="text-xs text-indigo-500 font-normal">(전결)</span>
|
||||||
@endif
|
@endif
|
||||||
@elseif($step->status === 'on_hold')
|
@if($step->status === 'on_hold')
|
||||||
<span class="inline-flex items-center justify-center w-6 h-6 rounded-full bg-amber-100 text-amber-600 text-xs">⏸</span>
|
<span class="text-xs text-amber-500 font-normal">(보류)</span>
|
||||||
@else
|
@endif
|
||||||
<span class="inline-flex items-center justify-center w-6 h-6 rounded-full bg-red-100 text-red-600 text-xs">✗</span>
|
<span class="text-gray-400 font-normal text-xs">{{ $step->acted_at?->format('Y-m-d H:i') }}</span>
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-sm font-medium">
|
|
||||||
{{ $step->approver_name ?? ($step->approver?->name ?? '') }}
|
|
||||||
@if(($step->approval_type ?? 'normal') === 'pre_decided')
|
|
||||||
<span class="text-xs text-indigo-500 font-normal">(전결)</span>
|
|
||||||
@endif
|
|
||||||
@if($step->status === 'on_hold')
|
|
||||||
<span class="text-xs text-amber-500 font-normal">(보류)</span>
|
|
||||||
@endif
|
|
||||||
<span class="text-gray-400 font-normal text-xs">{{ $step->acted_at?->format('Y-m-d H:i') }}</span>
|
|
||||||
</div>
|
|
||||||
<p class="text-sm text-gray-600 mt-1">{{ $step->comment }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
<p class="text-sm text-gray-600 mt-1">{{ $step->comment }}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
@endforeach
|
||||||
@endif
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
{{-- 결재 처리 (승인/반려/보류/전결) --}}
|
{{-- 결재 처리 (승인/반려/보류/전결) --}}
|
||||||
@if($approval->isActionable() && $approval->isCurrentApprover(auth()->id()))
|
@if($approval->isActionable() && $approval->isCurrentApprover(auth()->id()))
|
||||||
|
|||||||
Reference in New Issue
Block a user