- Leave, LeavePolicy, LeaveGrant 모델 생성 - LeaveBalance 헬퍼 메서드 추가 (useLeave, restoreLeave, canUse) - LeaveService 핵심 로직 (신청, 승인, 반려, 취소, 잔여연차, 통계) - API 컨트롤러 (목록, 등록, 승인/반려/취소, 잔여연차, 통계, CSV 내보내기) - 뷰 컨트롤러 + 라우트 등록 (web, api) - Blade 뷰 (index + 3개 탭 partials: table, balance, stats)
90 lines
4.3 KiB
PHP
90 lines
4.3 KiB
PHP
{{-- 사용현황 통계 (HTMX로 로드) --}}
|
|
@php
|
|
use App\Models\HR\Leave;
|
|
|
|
$byType = $stats['by_type'] ?? collect();
|
|
$byUser = $stats['by_user'] ?? collect();
|
|
$year = $stats['year'] ?? now()->year;
|
|
$typeMap = Leave::TYPE_MAP;
|
|
$totalApproved = $byType->sum('count');
|
|
$totalDays = $byType->sum('total_days');
|
|
@endphp
|
|
|
|
<div class="p-6 space-y-6">
|
|
{{-- 유형별 집계 카드 --}}
|
|
<div>
|
|
<h3 class="text-sm font-semibold text-gray-700 mb-3">{{ $year }}년 유형별 현황</h3>
|
|
<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-3">
|
|
{{-- 전체 합계 --}}
|
|
<div class="p-4 bg-gray-50 rounded-lg border border-gray-200">
|
|
<div class="text-xs text-gray-500 mb-1">전체</div>
|
|
<div class="text-2xl font-bold text-gray-800">{{ $totalApproved }}건</div>
|
|
<div class="text-xs text-gray-400 mt-0.5">{{ $totalDays }}일</div>
|
|
</div>
|
|
|
|
@foreach($typeMap as $typeKey => $typeLabel)
|
|
@php
|
|
$typeData = $byType->get($typeKey);
|
|
$count = $typeData->count ?? 0;
|
|
$days = $typeData->total_days ?? 0;
|
|
@endphp
|
|
<div class="p-4 bg-white rounded-lg border border-gray-200">
|
|
<div class="text-xs text-gray-500 mb-1">{{ $typeLabel }}</div>
|
|
<div class="text-2xl font-bold text-gray-800">{{ $count }}건</div>
|
|
<div class="text-xs text-gray-400 mt-0.5">{{ $days }}일</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
|
|
{{-- 사원별 유형 크로스 테이블 --}}
|
|
@if($byUser->isNotEmpty())
|
|
<div>
|
|
<h3 class="text-sm font-semibold text-gray-700 mb-3">사원별 사용현황 (승인된 휴가)</h3>
|
|
<x-table-swipe>
|
|
<table class="min-w-full">
|
|
<thead class="bg-gray-50 border-b border-gray-200">
|
|
<tr>
|
|
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-600">사원</th>
|
|
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-600">부서</th>
|
|
@foreach($typeMap as $typeLabel)
|
|
<th class="px-3 py-3 text-center text-xs font-semibold text-gray-600">{{ $typeLabel }}</th>
|
|
@endforeach
|
|
<th class="px-4 py-3 text-center text-xs font-semibold text-gray-600 bg-gray-100">합계</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-100">
|
|
@foreach($byUser as $userId => $userLeaves)
|
|
@php
|
|
$firstLeave = $userLeaves->first();
|
|
$profile = $firstLeave?->user?->tenantProfiles?->first();
|
|
$department = $profile?->department;
|
|
$displayName = $profile?->display_name ?? $firstLeave?->user?->name ?? '-';
|
|
$userTypeMap = $userLeaves->keyBy('leave_type');
|
|
$userTotal = $userLeaves->sum('total_days');
|
|
@endphp
|
|
<tr class="hover:bg-gray-50 transition-colors">
|
|
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">{{ $displayName }}</td>
|
|
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">{{ $department?->name ?? '-' }}</td>
|
|
@foreach($typeMap as $typeKey => $typeLabel)
|
|
<td class="px-3 py-3 whitespace-nowrap text-center text-sm text-gray-700">
|
|
@php $val = $userTypeMap->get($typeKey)?->total_days ?? 0; @endphp
|
|
{{ $val > 0 ? $val : '-' }}
|
|
</td>
|
|
@endforeach
|
|
<td class="px-4 py-3 whitespace-nowrap text-center text-sm font-semibold text-blue-600 bg-blue-50/50">
|
|
{{ $userTotal }}일
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</x-table-swipe>
|
|
</div>
|
|
@else
|
|
<div class="text-center py-8 text-gray-500">
|
|
{{ $year }}년 승인된 휴가가 없습니다.
|
|
</div>
|
|
@endif
|
|
</div>
|