From a70a3f5b8bfb754a9059a54ce4ae4f37fbab8b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Mon, 16 Mar 2026 21:11:49 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[dashboard]=20=EB=8B=AC=EB=A0=A5?= =?UTF-8?q?=EC=97=90=20=EC=8A=B9=EC=9D=B8=EB=90=9C=20=ED=9C=B4=EA=B0=80/?= =?UTF-8?q?=EA=B7=BC=ED=83=9C=20=ED=91=9C=EC=8B=9C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Leave 모델에서 승인된 휴가 데이터 조회 - 달력에 [연차] 홍길동 형태로 휴가 표시 - 휴가 유형별 색상 구분 (연차/반차: amber, 병가/경조사: pink, 출장/외근: blue 등) --- .../DashboardCalendarController.php | 37 ++++++++++++++++++- app/Models/HR/Leave.php | 25 +++++++++++++ .../dashboard/partials/calendar.blade.php | 17 +++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/DashboardCalendarController.php b/app/Http/Controllers/DashboardCalendarController.php index 2308f8c6..180a37e9 100644 --- a/app/Http/Controllers/DashboardCalendarController.php +++ b/app/Http/Controllers/DashboardCalendarController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use App\Models\Boards\File; +use App\Models\HR\Leave; use App\Models\System\Holiday; use App\Models\System\Schedule; use App\Services\GoogleCloudStorageService; @@ -40,8 +41,11 @@ public function calendar(Request $request): View $holidayMap = $this->getHolidayMap($tenantId, $year, $month); + // 승인된 휴가/근태신청 데이터 (날짜별 그룹화) + $leaveData = $this->getLeaveMap($tenantId, $startOfWeek->toDateString(), $endOfWeek->toDateString()); + return view('dashboard.partials.calendar', compact( - 'year', 'month', 'calendarData', 'holidayMap' + 'year', 'month', 'calendarData', 'holidayMap', 'leaveData' )); } @@ -286,6 +290,37 @@ private function determineFileType(string $mimeType): string return 'document'; } + /** + * 승인된 휴가를 날짜별로 펼쳐서 맵 생성 + * 반환: ['Y-m-d' => [['type_label' => '연차', 'user_name' => '홍길동', ...], ...]] + */ + private function getLeaveMap(int $tenantId, string $startDate, string $endDate): array + { + $leaves = Leave::forTenant($tenantId) + ->where('status', 'approved') + ->betweenDates($startDate, $endDate) + ->with('user:id,name') + ->orderBy('start_date') + ->get(); + + $map = []; + foreach ($leaves as $leave) { + $start = $leave->start_date->copy(); + $end = $leave->end_date->copy(); + + for ($d = $start; $d->lte($end); $d->addDay()) { + $key = $d->format('Y-m-d'); + $map[$key][] = [ + 'type_label' => $leave->type_label, + 'leave_type' => $leave->leave_type, + 'user_name' => $leave->user?->name ?? '(미지정)', + ]; + } + } + + return $map; + } + /** * 해당 월의 휴일 맵 생성 (날짜 => 휴일명) */ diff --git a/app/Models/HR/Leave.php b/app/Models/HR/Leave.php index ce4986bf..e9b85a15 100644 --- a/app/Models/HR/Leave.php +++ b/app/Models/HR/Leave.php @@ -163,6 +163,31 @@ public function getIsDeductibleAttribute(): bool return in_array($this->leave_type, self::DEDUCTIBLE_TYPES); } + // ========================================================================= + // 달력 표시용 스타일 + // ========================================================================= + + private const LEAVE_CALENDAR_STYLES = [ + 'annual' => ['bg' => '#fef3c7', 'text' => '#92400e', 'border' => '#fcd34d'], // amber + 'half_am' => ['bg' => '#fef3c7', 'text' => '#92400e', 'border' => '#fcd34d'], // amber + 'half_pm' => ['bg' => '#fef3c7', 'text' => '#92400e', 'border' => '#fcd34d'], // amber + 'sick' => ['bg' => '#fce7f3', 'text' => '#9d174d', 'border' => '#f9a8d4'], // pink + 'family' => ['bg' => '#fce7f3', 'text' => '#9d174d', 'border' => '#f9a8d4'], // pink + 'maternity' => ['bg' => '#ede9fe', 'text' => '#5b21b6', 'border' => '#c4b5fd'], // violet + 'parental' => ['bg' => '#ede9fe', 'text' => '#5b21b6', 'border' => '#c4b5fd'], // violet + 'business_trip' => ['bg' => '#dbeafe', 'text' => '#1e40af', 'border' => '#93c5fd'], // blue + 'remote' => ['bg' => '#d1fae5', 'text' => '#065f46', 'border' => '#6ee7b7'], // emerald + 'field_work' => ['bg' => '#dbeafe', 'text' => '#1e40af', 'border' => '#93c5fd'], // blue + 'early_leave' => ['bg' => '#fee2e2', 'text' => '#991b1b', 'border' => '#fca5a5'], // red + ]; + + public static function leaveCalendarStyle(string $leaveType): string + { + $style = self::LEAVE_CALENDAR_STYLES[$leaveType] ?? ['bg' => '#f3f4f6', 'text' => '#374151', 'border' => '#d1d5db']; + + return "background-color: {$style['bg']}; color: {$style['text']}; border-color: {$style['border']};"; + } + // ========================================================================= // 스코프 // ========================================================================= diff --git a/resources/views/dashboard/partials/calendar.blade.php b/resources/views/dashboard/partials/calendar.blade.php index 547348db..753547ee 100644 --- a/resources/views/dashboard/partials/calendar.blade.php +++ b/resources/views/dashboard/partials/calendar.blade.php @@ -121,6 +121,23 @@ class="text-gray-300 hover:text-emerald-600 hover:bg-emerald-50 rounded transiti @endif + {{-- 휴가/근태 목록 --}} + @php $dayLeaves = $leaveData[$dateKey] ?? []; @endphp + @if(count($dayLeaves) > 0) +
+ @foreach($dayLeaves as $leave) +
+ + [{{ $leave['type_label'] }}] + {{ $leave['user_name'] }} + +
+ @endforeach +
+ @endif + {{-- 일정 목록 --}}
@foreach($daySchedules as $schedule)