fix(tkuser): 연차 배정 모달 간소화 — 휴가유형 드롭다운 제거

- "휴가 유형" 드롭다운 → hidden (vacation_type_id 자동 설정)
- "배정 유형"이 메인 셀렉터: 기본연차/이월/장기근속/경조사
- balance_type별 vacation_type_id 자동 매핑:
  AUTO/MANUAL→ANNUAL_FULL, CARRY_OVER→CARRYOVER, LONG_SERVICE→LONG_SERVICE
- 경조사(COMPANY_GRANT) 선택 시 서브 드롭다운 표시

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-03-31 09:12:33 +09:00
parent 9528a544c6
commit 9bd3888738
7 changed files with 239 additions and 64 deletions

View File

@@ -898,21 +898,16 @@
<option value="">선택</option>
</select>
</div>
<div>
<label class="block text-xs font-medium text-gray-600 mb-1">휴가 유형 <span class="text-red-400">*</span></label>
<select id="vbType" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" required>
<option value="">선택</option>
</select>
</div>
<input type="hidden" id="vbType" value="">
<div class="grid grid-cols-2 gap-3">
<div>
<label class="block text-xs font-medium text-gray-600 mb-1">배정 유형</label>
<label class="block text-xs font-medium text-gray-600 mb-1">유형 <span class="text-red-400">*</span></label>
<select id="vbBalanceType" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" onchange="onBalanceTypeChange()">
<option value="AUTO">기본연차</option>
<option value="MANUAL">추가부여</option>
<option value="CARRY_OVER">이월연차</option>
<option value="LONG_SERVICE">장기근속</option>
<option value="COMPANY_GRANT">회사부여</option>
<option value="COMPANY_GRANT">경조사/특별휴가</option>
</select>
</div>
<div>
@@ -930,6 +925,19 @@
<input type="number" id="vbUsedDays" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" value="0" step="0.25" min="0">
</div>
</div>
<div id="vbSpecialTypeRow" class="hidden">
<label class="block text-xs font-medium text-gray-600 mb-1">경조사 유형</label>
<select id="vbSpecialType" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
<option value="WEDDING">결혼 (5일)</option>
<option value="SPOUSE_BIRTH">배우자 출산 (10일)</option>
<option value="CHILD_WEDDING">자녀 결혼 (1일)</option>
<option value="CONDOLENCE_PARENT">부모 사망 (5일)</option>
<option value="CONDOLENCE_SPOUSE_PARENT">배우자 부모 사망 (5일)</option>
<option value="CONDOLENCE_GRANDPARENT">조부모 사망 (3일)</option>
<option value="CONDOLENCE_SIBLING">형제자매 사망 (3일)</option>
<option value="OTHER">기타 (1일)</option>
</select>
</div>
<div>
<label class="block text-xs font-medium text-gray-600 mb-1">만료일</label>
<input type="date" id="vbExpiresAt" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
@@ -2416,7 +2424,7 @@
<script src="/static/js/tkuser-issue-types.js?v=2026031401"></script>
<script src="/static/js/tkuser-workplaces.js?v=2026031401"></script>
<script src="/static/js/tkuser-tasks.js?v=2026031401"></script>
<script src="/static/js/tkuser-vacations.js?v=2026033101"></script>
<script src="/static/js/tkuser-vacations.js?v=2026033102"></script>
<script src="/static/js/tkuser-vacation-settings.js?v=2026032501"></script>
<script src="/static/js/tkuser-layout-map.js?v=2026031401"></script>
<script src="/static/js/tkuser-partners.js?v=2026031601"></script>

View File

@@ -320,23 +320,45 @@ async function autoCalcVacation() {
} catch(e) { showToast(e.message, 'error'); }
}
// balance_type 변경 시 expires_at 기본값 조정
// vacation_type_id 자동 매핑 (vacTypes에서 type_code로 찾기)
function getVacTypeId(typeCode) {
const t = vacTypes.find(v => v.type_code === typeCode);
return t ? t.id : null;
}
// balance_type 변경 시 vacation_type_id + expires_at + 경조사 드롭다운 조정
function onBalanceTypeChange() {
const bt = document.getElementById('vbBalanceType').value;
const expiresInput = document.getElementById('vbExpiresAt');
const year = document.getElementById('vacYear')?.value || new Date().getFullYear();
const specialRow = document.getElementById('vbSpecialTypeRow');
const year = document.getElementById('vbYear')?.value || document.getElementById('vacYear')?.value || new Date().getFullYear();
if (bt === 'LONG_SERVICE') {
// vacation_type_id 자동 설정
const typeMap = { AUTO: 'ANNUAL_FULL', MANUAL: 'ANNUAL_FULL', CARRY_OVER: 'CARRYOVER', LONG_SERVICE: 'LONG_SERVICE' };
if (typeMap[bt]) {
document.getElementById('vbType').value = getVacTypeId(typeMap[bt]) || '';
}
// 경조사 드롭다운 표시/숨김
if (bt === 'COMPANY_GRANT') {
specialRow.classList.remove('hidden');
// 경조사 유형으로 vacation_type_id 설정
const specialCode = document.getElementById('vbSpecialType').value;
document.getElementById('vbType').value = getVacTypeId(specialCode) || getVacTypeId('ANNUAL_FULL') || '';
} else {
specialRow.classList.add('hidden');
}
// 만료일
if (bt === 'LONG_SERVICE' || bt === 'COMPANY_GRANT') {
expiresInput.disabled = true;
expiresInput.value = '';
} else {
expiresInput.disabled = false;
if (bt === 'CARRY_OVER') {
// 해당연 2월말
const febEnd = new Date(parseInt(year), 2, 0); // month=2, day=0 = last day of Feb
const febEnd = new Date(parseInt(year), 2, 0);
expiresInput.value = febEnd.toISOString().substring(0, 10);
} else {
// 연말
expiresInput.value = `${year}-12-31`;
}
}
@@ -376,10 +398,10 @@ function openVacBalanceModal(editId) {
});
uSel.appendChild(group);
});
// 유형 셀렉트
const tSel = document.getElementById('vbType');
tSel.innerHTML = '<option value="">선택</option>';
vacTypes.filter(t => t.is_active).forEach(t => { tSel.innerHTML += `<option value="${t.id}">${escHtml(t.type_name)} (${escHtml(t.type_code)})</option>`; });
// vacation_type_id 자동 설정 (기본: ANNUAL_FULL)
document.getElementById('vbType').value = getVacTypeId('ANNUAL_FULL') || '';
document.getElementById('vbSpecialTypeRow')?.classList.add('hidden');
if (editId) {
const b = vacBalances.find(x => x.id === editId);
if (!b) return;
@@ -387,8 +409,7 @@ function openVacBalanceModal(editId) {
document.getElementById('vbEditId').value = b.id;
uSel.value = b.user_id;
uSel.disabled = true;
tSel.value = b.vacation_type_id;
tSel.disabled = true;
document.getElementById('vbType').value = b.vacation_type_id;
if (b.balance_type) document.getElementById('vbBalanceType').value = b.balance_type;
document.getElementById('vbTotalDays').value = b.total_days;
document.getElementById('vbUsedDays').value = b.used_days;
@@ -397,15 +418,15 @@ function openVacBalanceModal(editId) {
if (b.balance_type === 'LONG_SERVICE') document.getElementById('vbExpiresAt').disabled = true;
} else {
uSel.disabled = false;
tSel.disabled = false;
}
onBalanceTypeChange(); // vacation_type_id + 만료일 + 경조사 드롭다운 설정
document.getElementById('vacBalanceModal').classList.remove('hidden');
}
function closeVacBalanceModal() {
document.getElementById('vacBalanceModal').classList.add('hidden');
document.getElementById('vbUser').disabled = false;
document.getElementById('vbType').disabled = false;
document.getElementById('vbExpiresAt').disabled = false;
document.getElementById('vbSpecialTypeRow')?.classList.add('hidden');
}
function editVacBalance(id) { openVacBalanceModal(id); }