- 휴가 신청 모달에 결재선 드롭다운 + 미리보기 UI 추가 - 선택된 결재선으로 결재 생성 (미선택 시 기본결재선 fallback) - 휴가 목록에 결재진행 컬럼 추가 (원형 아이콘: ✓승인/✗반려/숫자대기/파랑현재) - approval.steps.approver eager load 추가
179 lines
9.6 KiB
PHP
179 lines
9.6 KiB
PHP
{{-- 휴가 목록 테이블 (HTMX로 로드) --}}
|
|
@php
|
|
use App\Models\HR\Leave;
|
|
@endphp
|
|
|
|
<x-table-swipe>
|
|
<table class="min-w-full">
|
|
<thead class="bg-gray-50 border-b border-gray-200">
|
|
<tr>
|
|
<th class="px-6 py-3 text-left text-sm font-semibold text-gray-600">사원</th>
|
|
<th class="px-6 py-3 text-left text-sm font-semibold text-gray-600">부서</th>
|
|
<th class="px-6 py-3 text-center text-sm font-semibold text-gray-600">유형</th>
|
|
<th class="px-6 py-3 text-center text-sm font-semibold text-gray-600">기간</th>
|
|
<th class="px-6 py-3 text-center text-sm font-semibold text-gray-600">일수</th>
|
|
<th class="px-6 py-3 text-left text-sm font-semibold text-gray-600">사유</th>
|
|
<th class="px-6 py-3 text-center text-sm font-semibold text-gray-600">상태</th>
|
|
<th class="px-6 py-3 text-center text-sm font-semibold text-gray-600">결재진행</th>
|
|
<th class="px-6 py-3 text-left text-sm font-semibold text-gray-600">처리자</th>
|
|
<th class="px-6 py-3 text-center text-sm font-semibold text-gray-600">액션</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-100">
|
|
@forelse($leaves as $leave)
|
|
@php
|
|
$profile = $leave->user?->tenantProfiles?->first();
|
|
$department = $profile?->department;
|
|
$displayName = $profile?->display_name ?? $leave->user?->name ?? '-';
|
|
$color = Leave::STATUS_COLORS[$leave->status] ?? 'gray';
|
|
$statusLabel = Leave::STATUS_MAP[$leave->status] ?? $leave->status;
|
|
$typeLabel = Leave::TYPE_MAP[$leave->leave_type] ?? $leave->leave_type;
|
|
@endphp
|
|
<tr class="hover:bg-gray-50 transition-colors">
|
|
{{-- 사원 --}}
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<div class="flex items-center gap-2">
|
|
<div class="shrink-0 w-8 h-8 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center text-xs font-medium">
|
|
{{ mb_substr($displayName, 0, 1) }}
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">{{ $displayName }}</span>
|
|
</div>
|
|
</td>
|
|
|
|
{{-- 부서 --}}
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700">
|
|
{{ $department?->name ?? '-' }}
|
|
</td>
|
|
|
|
{{-- 유형 --}}
|
|
<td class="px-6 py-4 whitespace-nowrap text-center text-sm text-gray-700">
|
|
{{ $typeLabel }}
|
|
</td>
|
|
|
|
{{-- 기간 --}}
|
|
<td class="px-6 py-4 whitespace-nowrap text-center text-sm text-gray-700">
|
|
{{ $leave->start_date->format('m-d') }}
|
|
@if($leave->start_date->ne($leave->end_date))
|
|
~ {{ $leave->end_date->format('m-d') }}
|
|
@endif
|
|
</td>
|
|
|
|
{{-- 일수 --}}
|
|
<td class="px-6 py-4 whitespace-nowrap text-center text-sm text-gray-700">
|
|
{{ $leave->days == intval($leave->days) ? intval($leave->days) : $leave->days }}일
|
|
</td>
|
|
|
|
{{-- 사유 --}}
|
|
<td class="px-6 py-4 text-sm text-gray-500" style="max-width: 200px;">
|
|
<span class="truncate block" title="{{ $leave->reason }}">{{ $leave->reason ?? '-' }}</span>
|
|
@if($leave->reject_reason)
|
|
<span class="text-xs text-red-500 block mt-0.5" title="{{ $leave->reject_reason }}">
|
|
반려: {{ Str::limit($leave->reject_reason, 20) }}
|
|
</span>
|
|
@endif
|
|
</td>
|
|
|
|
{{-- 상태 --}}
|
|
<td class="px-6 py-4 whitespace-nowrap text-center">
|
|
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-{{ $color }}-100 text-{{ $color }}-700">
|
|
{{ $statusLabel }}
|
|
</span>
|
|
</td>
|
|
|
|
{{-- 결재진행 --}}
|
|
<td class="px-4 py-4 whitespace-nowrap">
|
|
@if($leave->approval && $leave->approval->steps->count() > 0)
|
|
<div class="flex items-center gap-0.5">
|
|
@foreach($leave->approval->steps->sortBy('step_order') as $step)
|
|
@php
|
|
$stepColor = match($step->status) {
|
|
'approved' => 'bg-green-500',
|
|
'rejected' => 'bg-red-500',
|
|
'on_hold' => 'bg-amber-500',
|
|
default => 'bg-gray-300',
|
|
};
|
|
$isCurrent = $step->status === 'pending'
|
|
&& $step->step_order == $leave->approval->current_step
|
|
&& in_array($step->step_type, ['approval', 'agreement']);
|
|
if ($isCurrent) $stepColor = 'bg-blue-500 ring-2 ring-blue-200';
|
|
@endphp
|
|
<div class="relative group">
|
|
<div class="w-6 h-6 rounded-full {{ $stepColor }} flex items-center justify-center text-white text-xs font-medium"
|
|
title="{{ $step->approver?->name ?? '미지정' }} ({{ match($step->step_type) { 'approval' => '결재', 'agreement' => '합의', 'reference' => '참조', default => '' } }})">
|
|
@if($step->status === 'approved') ✓
|
|
@elseif($step->status === 'rejected') ✗
|
|
@else {{ $step->step_order }}
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
@else
|
|
<span class="text-xs text-gray-400">-</span>
|
|
@endif
|
|
</td>
|
|
|
|
{{-- 처리자 --}}
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
@if($leave->approver)
|
|
{{ $leave->approver->name }}
|
|
<span class="text-xs text-gray-400 block">{{ $leave->approved_at?->format('m-d H:i') }}</span>
|
|
@else
|
|
-
|
|
@endif
|
|
</td>
|
|
|
|
{{-- 액션 --}}
|
|
<td class="px-6 py-4 whitespace-nowrap text-center">
|
|
<div class="flex items-center justify-center gap-1">
|
|
@if($leave->approval_id)
|
|
<a href="{{ route('approvals.show', $leave->approval_id) }}"
|
|
class="px-2.5 py-1 text-xs font-medium text-blue-700 bg-blue-50 hover:bg-blue-100 rounded transition-colors">
|
|
결재 상세 →
|
|
</a>
|
|
@endif
|
|
|
|
@if($leave->status === 'approved')
|
|
<button type="button" onclick="cancelLeave({{ $leave->id }})"
|
|
class="px-2.5 py-1 text-xs font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded transition-colors">
|
|
취소
|
|
</button>
|
|
@elseif($leave->status === 'pending' && !$leave->approval_id)
|
|
{{-- 결재 연동 없는 기존 pending 건만 직접 승인/반려 허용 --}}
|
|
<button type="button" onclick="approveLeave({{ $leave->id }})"
|
|
class="px-2.5 py-1 text-xs font-medium text-emerald-700 bg-emerald-50 hover:bg-emerald-100 rounded transition-colors">
|
|
승인
|
|
</button>
|
|
<button type="button" onclick="openRejectModal({{ $leave->id }})"
|
|
class="px-2.5 py-1 text-xs font-medium text-red-700 bg-red-50 hover:bg-red-100 rounded transition-colors">
|
|
반려
|
|
</button>
|
|
@elseif(!$leave->approval_id && $leave->status !== 'pending' && $leave->status !== 'approved')
|
|
<span class="text-xs text-gray-400">-</span>
|
|
@endif
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr>
|
|
<td colspan="10" class="px-6 py-12 text-center">
|
|
<div class="flex flex-col items-center gap-2">
|
|
<svg class="w-12 h-12 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
|
|
</svg>
|
|
<p class="text-gray-500">휴가 신청 내역이 없습니다.</p>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</x-table-swipe>
|
|
|
|
{{-- 페이지네이션 --}}
|
|
@if($leaves->hasPages())
|
|
<div class="px-6 py-4 border-t border-gray-200 bg-gray-50">
|
|
{{ $leaves->links() }}
|
|
</div>
|
|
@endif
|