feat: [leave] 잔여연차 탭 도움말 기능 추가
- 휴가관리가이드.md 마크다운 콘텐츠 작성 (연차 산출 방식, 촉진 제도 등) - 잔여연차 탭 헤더에 도움말(?) 버튼 추가 - help-modal.blade.php 생성 (sales 패턴 재사용) - LeaveController에 helpGuide() 메서드 추가 - 도움말 라우트 등록
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
use App\Services\HR\LeaveService;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class LeaveController extends Controller
|
||||
{
|
||||
@@ -32,4 +33,21 @@ public function index(\Illuminate\Http\Request $request): View|Response
|
||||
'statusMap' => $statusMap,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 휴가관리 가이드 도움말 모달
|
||||
*/
|
||||
public function helpGuide(): View
|
||||
{
|
||||
$guidePath = resource_path('markdown/휴가관리가이드.md');
|
||||
|
||||
if (file_exists($guidePath)) {
|
||||
$markdown = file_get_contents($guidePath);
|
||||
$htmlContent = Str::markdown($markdown);
|
||||
} else {
|
||||
$htmlContent = '<p class="text-gray-500">가이드를 찾을 수 없습니다.</p>';
|
||||
}
|
||||
|
||||
return view('hr.leaves.partials.help-modal', compact('htmlContent'));
|
||||
}
|
||||
}
|
||||
|
||||
115
resources/markdown/휴가관리가이드.md
Normal file
115
resources/markdown/휴가관리가이드.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# 휴가관리 가이드
|
||||
|
||||
## 1. 연차 산출 방식
|
||||
|
||||
### 1.1 기본 연차 부여 규칙 (근로기준법 제60조)
|
||||
|
||||
- **입사 1년 미만**: 1개월 만근(개근) 시 **1일** 발생 (최대 11일)
|
||||
- **1년 이상 근무**: **15일** 부여
|
||||
- **매 2년 근속** 시 **+1일** 가산
|
||||
- **최대 한도**: 25일
|
||||
|
||||
### 1.2 연차발생일수 테이블
|
||||
|
||||
| 근속년수 | 연차일수 | 근속년수 | 연차일수 |
|
||||
|:--------:|:--------:|:--------:|:--------:|
|
||||
| 1년 미만 | 최대 11일 | 1년 | 15일 |
|
||||
| 3년 | 16일 | 5년 | 17일 |
|
||||
| 7년 | 18일 | 9년 | 19일 |
|
||||
| 11년 | 20일 | 13년 | 21일 |
|
||||
| 15년 | 22일 | 17년 | 23일 |
|
||||
| 19년 | 24일 | 21년~ | 25일 |
|
||||
|
||||
> **참고**: 매 2년 근속 시 1일이 가산됩니다. (예: 3년차 16일, 5년차 17일, ...)
|
||||
|
||||
### 1.3 회계일 기준 vs 입사일 기준
|
||||
|
||||
| 구분 | 회계일 기준 | 입사일 기준 |
|
||||
|------|-----------|-----------|
|
||||
| 1년차 (당해 입사) | 1달 만근 시 1일씩 발생 | 입사일 기준 11일 |
|
||||
| 2년차 | 1달 만근분 + 1년차 비례분 | 15일 |
|
||||
| 3년차~ | 15일 + 가산일 | 15일 + 가산일 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 연차 사용 규칙
|
||||
|
||||
### 2.1 휴가 유형별 차감
|
||||
|
||||
| 유형 | 차감일수 | 비고 |
|
||||
|------|:--------:|------|
|
||||
| 연차 | 1일 | 하루 전체 |
|
||||
| 오전반차 | 0.5일 | 오전 근무 면제 |
|
||||
| 오후반차 | 0.5일 | 오후 근무 면제 |
|
||||
| 병가 | 차감 없음 | 진단서 필요 |
|
||||
| 경조사 | 차감 없음 | 경조사 규정 적용 |
|
||||
| 출산/육아 | 차감 없음 | 법정 휴가 |
|
||||
| 공가 | 차감 없음 | 예비군/민방위 등 |
|
||||
|
||||
### 2.2 계산 기준
|
||||
|
||||
- **영업일 기준** 계산 (주말·공휴일 제외)
|
||||
- 연차/반차만 잔여연차에서 차감
|
||||
- 병가, 경조사, 출산, 공가 등은 별도 관리
|
||||
|
||||
---
|
||||
|
||||
## 3. 잔여연차 화면 설명
|
||||
|
||||
### 3.1 주요 항목
|
||||
|
||||
| 항목 | 설명 |
|
||||
|------|------|
|
||||
| **부여** | 연초 배정된 총 연차일수 |
|
||||
| **사용** | 승인 완료된 연차/반차 합계 |
|
||||
| **잔여** | 부여 - 사용 |
|
||||
| **소진율** | (사용 / 부여) x 100% |
|
||||
|
||||
### 3.2 연차관리대장 항목
|
||||
|
||||
- **사번/성명/부서/직급**: 사원 기본 정보
|
||||
- **입사일**: 연차 산출의 기준일
|
||||
- **근속개월수/근속년수**: 입사일로부터 자동 계산
|
||||
- **연차발생일수**: 근속년수에 따라 자동 산출
|
||||
- **사용연차합계**: 승인된 연차/반차 누적
|
||||
- **잔여연차**: 연차발생일수 - 사용연차합계
|
||||
|
||||
---
|
||||
|
||||
## 4. 연차촉진 제도 (근로기준법 제61조)
|
||||
|
||||
### 4.1 개요
|
||||
|
||||
연차 소멸 전 사용을 촉진하여 미사용 수당 부담을 줄이는 법적 절차입니다.
|
||||
|
||||
### 4.2 촉진 절차
|
||||
|
||||
| 단계 | 시기 | 내용 |
|
||||
|------|------|------|
|
||||
| **1차 촉진** | 소멸 6개월 전 | 미사용 일수를 서면 통보하고 10일 이내 사용 시기 지정 요청 |
|
||||
| **2차 촉진** | 1차 미응답 시 | 회사가 직접 사용 시기를 지정하여 서면 통보 |
|
||||
|
||||
### 4.3 효과
|
||||
|
||||
- 1차·2차 촉진을 모두 이행한 경우 → **미사용 수당 지급 의무 면제**
|
||||
- 촉진 미이행 시 → 미사용 연차에 대해 **수당 지급 의무** 발생
|
||||
|
||||
> **주의**: 촉진 통보는 반드시 서면(이메일, 문서)으로 하여 기록을 남겨야 합니다.
|
||||
|
||||
---
|
||||
|
||||
## 5. 휴가 신청·승인 프로세스
|
||||
|
||||
### 5.1 흐름
|
||||
|
||||
1. **관리자가 사원 선택** 후 휴가 유형/기간/사유 입력
|
||||
2. **신청 등록** → 상태: 대기
|
||||
3. **승인** → 연차 자동 차감 + 근태현황 반영
|
||||
4. **반려** → 반려 사유 기재, 연차 미차감
|
||||
5. **취소** → 승인 후라도 취소 가능, 연차 자동 복원
|
||||
|
||||
### 5.2 주의사항
|
||||
|
||||
- 잔여연차가 부족하면 연차/반차 신청 불가
|
||||
- 반차 신청 시 시작일·종료일이 동일해야 함
|
||||
- 승인된 휴가 취소 시 연차가 자동 복원됨
|
||||
@@ -135,6 +135,18 @@ class="px-3 py-1.5 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:
|
||||
<option value="{{ $y }}">{{ $y }}년</option>
|
||||
@endfor
|
||||
</select>
|
||||
|
||||
{{-- 도움말 버튼 --}}
|
||||
<button type="button"
|
||||
hx-get="{{ route('hr.leaves.help') }}"
|
||||
hx-target="#leave-help-modal-container"
|
||||
hx-swap="innerHTML"
|
||||
class="ml-auto inline-flex items-center justify-center w-8 h-8 rounded-full bg-blue-100 text-blue-600 hover:bg-blue-200 transition-colors"
|
||||
title="휴가관리 도움말">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div id="balance-container">
|
||||
<div class="flex justify-center items-center p-12">
|
||||
@@ -240,6 +252,9 @@ class="px-4 py-2 text-sm text-white bg-blue-600 hover:bg-blue-700 rounded-lg tra
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 도움말 모달 컨테이너 --}}
|
||||
<div id="leave-help-modal-container"></div>
|
||||
|
||||
{{-- 반려 사유 모달 --}}
|
||||
<div id="rejectModal" class="fixed inset-0 z-50 hidden">
|
||||
<div class="fixed inset-0 bg-black/40" onclick="closeRejectModal()"></div>
|
||||
|
||||
211
resources/views/hr/leaves/partials/help-modal.blade.php
Normal file
211
resources/views/hr/leaves/partials/help-modal.blade.php
Normal file
@@ -0,0 +1,211 @@
|
||||
{{-- 휴가관리 가이드 도움말 모달 --}}
|
||||
<div x-data="{ open: true }"
|
||||
x-show="open"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
class="fixed inset-0 z-50 overflow-y-auto"
|
||||
aria-labelledby="leave-help-modal-title"
|
||||
role="dialog"
|
||||
aria-modal="true">
|
||||
|
||||
{{-- 배경 오버레이 --}}
|
||||
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" @click="open = false; setTimeout(() => { document.getElementById('leave-help-modal-container').innerHTML = '' }, 200)"></div>
|
||||
|
||||
{{-- 모달 컨테이너 --}}
|
||||
<div class="flex min-h-full items-center justify-center p-4">
|
||||
<div x-show="open"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
class="relative transform overflow-hidden rounded-xl bg-white shadow-2xl transition-all w-full max-w-6xl max-h-[90vh] flex flex-col">
|
||||
|
||||
{{-- 헤더 --}}
|
||||
<div class="flex items-center justify-between px-6 py-4 border-b border-gray-200 bg-gradient-to-r from-blue-600 to-blue-700 flex-shrink-0">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="p-2 bg-white/20 rounded-lg">
|
||||
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-white" id="leave-help-modal-title">휴가관리 가이드</h3>
|
||||
</div>
|
||||
<button type="button"
|
||||
@click="open = false; setTimeout(() => { document.getElementById('leave-help-modal-container').innerHTML = '' }, 200)"
|
||||
class="p-2 text-white/80 hover:text-white hover:bg-white/20 rounded-lg transition-colors">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{-- 콘텐츠 영역 --}}
|
||||
<div class="flex-1 overflow-y-auto p-6">
|
||||
<div class="help-content">
|
||||
{!! $htmlContent !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 푸터 --}}
|
||||
<div class="flex items-center justify-end px-6 py-4 border-t border-gray-200 bg-gray-50 flex-shrink-0">
|
||||
<button type="button"
|
||||
@click="open = false; setTimeout(() => { document.getElementById('leave-help-modal-container').innerHTML = '' }, 200)"
|
||||
class="px-6 py-2.5 bg-gray-600 hover:bg-gray-700 text-white font-medium rounded-lg transition-colors">
|
||||
닫기
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.help-content {
|
||||
color: #374151;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
.help-content h1 {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: #111827;
|
||||
border-bottom: 2px solid #e5e7eb;
|
||||
padding-bottom: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.help-content h2 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: #1d4ed8;
|
||||
margin-top: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
padding-left: 1rem;
|
||||
border-left: 4px solid #3b82f6;
|
||||
}
|
||||
|
||||
.help-content h3 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.help-content h4 {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 500;
|
||||
color: #374151;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.help-content p {
|
||||
margin-bottom: 1rem;
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
.help-content a {
|
||||
color: #2563eb;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.help-content a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.help-content strong {
|
||||
font-weight: 600;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.help-content code {
|
||||
background-color: #f3f4f6;
|
||||
color: #db2777;
|
||||
padding: 0.125rem 0.375rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
font-family: ui-monospace, monospace;
|
||||
}
|
||||
|
||||
.help-content pre {
|
||||
background-color: #1f2937;
|
||||
color: #f3f4f6;
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
overflow-x: auto;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.help-content pre code {
|
||||
background: none;
|
||||
color: inherit;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.help-content blockquote {
|
||||
border-left: 4px solid #60a5fa;
|
||||
background-color: #eff6ff;
|
||||
padding: 0.75rem 1rem;
|
||||
margin: 1rem 0;
|
||||
border-radius: 0 0.5rem 0.5rem 0;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.help-content blockquote p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.help-content table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.help-content th {
|
||||
background-color: #f3f4f6;
|
||||
border: 1px solid #d1d5db;
|
||||
padding: 0.75rem 1rem;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
}
|
||||
|
||||
.help-content td {
|
||||
border: 1px solid #d1d5db;
|
||||
padding: 0.75rem 1rem;
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
.help-content tr:nth-child(even) {
|
||||
background-color: #f9fafb;
|
||||
}
|
||||
|
||||
.help-content ul {
|
||||
list-style-type: disc;
|
||||
padding-left: 1.5rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.help-content ol {
|
||||
list-style-type: decimal;
|
||||
padding-left: 1.5rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.help-content li {
|
||||
margin-bottom: 0.5rem;
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
.help-content hr {
|
||||
border: none;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
</style>
|
||||
@@ -909,6 +909,7 @@
|
||||
// 휴가관리
|
||||
Route::prefix('leaves')->name('leaves.')->group(function () {
|
||||
Route::get('/', [\App\Http\Controllers\HR\LeaveController::class, 'index'])->name('index');
|
||||
Route::get('/help', [\App\Http\Controllers\HR\LeaveController::class, 'helpGuide'])->name('help');
|
||||
});
|
||||
|
||||
// 급여관리
|
||||
|
||||
Reference in New Issue
Block a user