update webbase design

This commit is contained in:
ChiKyun Kim
2025-07-27 16:25:15 +09:00
parent afbac3248e
commit 0c5744c12c
17 changed files with 2414 additions and 225 deletions

View File

@@ -14,23 +14,97 @@
theme: {
extend: {
colors: {
primary: '#3B82F6',
secondary: '#6B7280',
success: '#10B981',
danger: '#EF4444',
warning: '#F59E0B'
primary: {
50: '#eff6ff',
100: '#dbeafe',
200: '#bfdbfe',
300: '#93c5fd',
400: '#60a5fa',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
},
success: {
50: '#f0fdf4',
100: '#dcfce7',
200: '#bbf7d0',
300: '#86efac',
400: '#4ade80',
500: '#22c55e',
600: '#16a34a',
700: '#15803d',
800: '#166534',
900: '#14532d',
},
warning: {
50: '#fffbeb',
100: '#fef3c7',
200: '#fde68a',
300: '#fcd34d',
400: '#fbbf24',
500: '#f59e0b',
600: '#d97706',
700: '#b45309',
800: '#92400e',
900: '#78350f',
},
danger: {
50: '#fef2f2',
100: '#fee2e2',
200: '#fecaca',
300: '#fca5a5',
400: '#f87171',
500: '#ef4444',
600: '#dc2626',
700: '#b91c1c',
800: '#991b1b',
900: '#7f1d1d',
}
},
animation: {
'fade-in': 'fadeIn 0.5s ease-in-out',
'slide-up': 'slideUp 0.3s ease-out',
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
slideUp: {
'0%': { transform: 'translateY(10px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
}
}
}
}
}
</script>
<style>
.glass-effect {
background: rgba(255, 255, 255, 0.25);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.card-hover {
transition: all 0.3s ease;
}
.card-hover:hover {
transform: translateY(-5px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.loading {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid #f3f3f3;
border-top: 3px solid #3B82F6;
border: 3px solid rgba(255, 255, 255, 0.3);
border-top: 3px solid #ffffff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@@ -45,41 +119,62 @@
overflow-y: auto;
}
.table-container::-webkit-scrollbar {
width: 8px;
/* 스크롤바 스타일링 */
.custom-scrollbar::-webkit-scrollbar {
width: var(--scrollbar-width, 16px);
}
.table-container::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4px;
.custom-scrollbar::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
border-radius: 8px;
}
.table-container::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 4px;
.custom-scrollbar::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.3);
border-radius: 8px;
border: 2px solid rgba(255, 255, 255, 0.1);
}
.table-container::-webkit-scrollbar-thumb:hover {
background: #a8a8a8;
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.5);
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<body class="gradient-bg min-h-screen">
<div class="container mx-auto px-4 py-8">
<!-- 헤더 -->
<div class="text-center mb-8 animate-fade-in">
<h1 class="text-4xl font-bold text-white mb-2">근태관리</h1>
<p class="text-white/80 text-lg">출퇴근 시간 및 휴가 관리</p>
</div>
<!-- 개발중 경고 메시지 -->
<div class="bg-orange-500 rounded-lg p-4 mb-6 border-l-4 border-orange-700 animate-slide-up shadow-lg">
<div class="flex items-center">
<svg class="w-5 h-5 text-orange-900 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path>
</svg>
<div>
<p class="text-white font-bold text-base">🚧 개발중인 기능입니다</p>
<p class="text-orange-100 text-sm font-medium">일부 기능이 정상적으로 동작하지 않을 수 있습니다.</p>
</div>
</div>
</div>
<!-- 검색 및 필터 섹션 -->
<div class="bg-white rounded-lg shadow-md p-6 mb-6">
<div class="glass-effect rounded-lg p-6 mb-6 animate-slide-up">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label for="startDate" class="block text-sm font-medium text-gray-700 mb-2">시작일</label>
<input type="date" id="startDate" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
<label for="startDate" class="block text-sm font-medium text-white/80 mb-2">시작일</label>
<input type="date" id="startDate" class="w-full px-3 py-2 bg-white/20 border border-white/30 rounded-md text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/50 focus:border-transparent">
</div>
<div>
<label for="endDate" class="block text-sm font-medium text-gray-700 mb-2">종료일</label>
<input type="date" id="endDate" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
<label for="endDate" class="block text-sm font-medium text-white/80 mb-2">종료일</label>
<input type="date" id="endDate" class="w-full px-3 py-2 bg-white/20 border border-white/30 rounded-md text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/50 focus:border-transparent">
</div>
<div class="flex items-end">
<button id="searchBtn" class="w-full bg-primary text-white px-4 py-2 rounded-md hover:bg-blue-600 transition-colors duration-200 flex items-center justify-center">
<button id="searchBtn" class="w-full glass-effect text-white px-4 py-2 rounded-md hover:bg-white/30 transition-colors duration-200 flex items-center justify-center">
<span id="searchBtnText">조회</span>
<div id="searchBtnLoading" class="loading ml-2 hidden"></div>
</button>
@@ -88,66 +183,66 @@
</div>
<!-- 통계 카드 -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
<div class="bg-white rounded-lg shadow-md p-6">
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6 animate-slide-up">
<div class="glass-effect rounded-lg p-6 card-hover">
<div class="flex items-center">
<div class="p-2 bg-blue-100 rounded-lg">
<svg class="w-6 h-6 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="p-3 bg-primary-500/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="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
</div>
<div class="ml-4">
<p class="text-sm font-medium text-gray-600">휴가사용</p>
<p id="totalDays" class="text-2xl font-bold text-gray-900">0</p>
<p class="text-sm font-medium text-white/80">휴가사용</p>
<p id="totalDays" class="text-2xl font-bold text-white">0</p>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow-md p-6">
<div class="glass-effect rounded-lg p-6 card-hover">
<div class="flex items-center">
<div class="p-2 bg-green-100 rounded-lg">
<svg class="w-6 h-6 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="p-3 bg-success-500/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="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<div class="ml-4">
<p class="text-sm font-medium text-gray-600">대체사용</p>
<p id="normalDays" class="text-2xl font-bold text-gray-900">0</p>
<p class="text-sm font-medium text-white/80">대체사용</p>
<p id="normalDays" class="text-2xl font-bold text-white">0</p>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow-md p-6">
<div class="glass-effect rounded-lg p-6 card-hover">
<div class="flex items-center">
<div class="p-2 bg-yellow-100 rounded-lg">
<svg class="w-6 h-6 text-yellow-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="p-3 bg-warning-500/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 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<div class="ml-4">
<p class="text-sm font-medium text-gray-600">잔량(년차)</p>
<p id="lateDays" class="text-2xl font-bold text-gray-900">0</p>
<p class="text-sm font-medium text-white/80">잔량(년차)</p>
<p id="lateDays" class="text-2xl font-bold text-white">0</p>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow-md p-6">
<div class="glass-effect rounded-lg p-6 card-hover">
<div class="flex items-center">
<div class="p-2 bg-red-100 rounded-lg">
<svg class="w-6 h-6 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="p-3 bg-danger-500/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="M6 18L18 6M6 6l12 12"></path>
</svg>
</div>
<div class="ml-4">
<p class="text-sm font-medium text-gray-600">잔량(대체)</p>
<p id="absentDays" class="text-2xl font-bold text-gray-900">0</p>
<p class="text-sm font-medium text-white/80">잔량(대체)</p>
<p id="absentDays" class="text-2xl font-bold text-white">0</p>
</div>
</div>
</div>
</div>
<!-- 데이터 테이블 -->
<div class="bg-white rounded-lg shadow-md">
<div class="px-6 py-4 border-b border-gray-200 flex justify-between items-center">
<h3 class="text-lg font-medium text-gray-900">근태 상세 내역</h3>
<button id="addBtn" class="bg-primary text-white px-4 py-2 rounded-md hover:bg-blue-600 transition-colors duration-200 flex items-center">
<div class="glass-effect rounded-lg animate-slide-up custom-scrollbar">
<div class="px-6 py-4 border-b border-white/20 flex justify-between items-center">
<h3 class="text-lg font-medium text-white">근태 상세 내역</h3>
<button id="addBtn" class="glass-effect text-white px-4 py-2 rounded-md hover:bg-white/30 transition-colors duration-200 flex items-center">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
</svg>
@@ -155,45 +250,45 @@
</button>
</div>
<div class="table-container">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50 sticky top-0">
<table class="min-w-full divide-y divide-white/20">
<thead class="bg-white/10 sticky top-0">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">구분</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">시작일</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">종료일</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">사번</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">성명</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">사용(일)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">사용(H)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">발생(일)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">발생(H)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">구분</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">시작일</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">종료일</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">사번</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">성명</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">사용(일)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">사용(H)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">발생(일)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">발생(H)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">내용</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">#</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">내용</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">#</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">잔량(일)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">잔량(H)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">전일(일)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">전일(H)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">잔량(일)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">잔량(H)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">전일(일)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">전일(H)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">소스</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">등록자</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">등록일</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">소스</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">등록자</th>
<th class="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">등록일</th>
</tr>
</thead>
<tbody id="dataTableBody" class="bg-white divide-y divide-gray-200">
<tbody id="dataTableBody" class="divide-y divide-white/10">
<tr id="loadingRow" class="hidden">
<td colspan="7" class="px-6 py-4 text-center">
<td colspan="18" class="px-6 py-4 text-center">
<div class="flex items-center justify-center">
<div class="loading mr-2"></div>
<span class="text-gray-500">데이터를 불러오는 중...</span>
<span class="text-white/80">데이터를 불러오는 중...</span>
</div>
</td>
</tr>
<tr id="noDataRow" class="hidden">
<td colspan="7" class="px-6 py-4 text-center text-gray-500">
<td colspan="18" class="px-6 py-4 text-center text-white/70">
조회된 데이터가 없습니다.
</td>
</tr>
@@ -291,12 +386,131 @@
</div>
<script>
// 공통 네비게이션 컴포넌트
class CommonNavigation {
constructor(currentPage = '') {
this.currentPage = currentPage;
this.init();
}
init() {
this.createNavigation();
this.addEventListeners();
}
createNavigation() {
const nav = document.createElement('nav');
nav.className = 'glass-effect border-b border-white/10';
nav.style.cssText = `
background: rgba(255, 255, 255, 0.25);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.18);
`;
nav.innerHTML = this.getNavigationHTML();
// body의 첫 번째 자식으로 추가
document.body.insertBefore(nav, document.body.firstChild);
}
getNavigationHTML() {
return `
<div class="container mx-auto px-4" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
<div class="flex items-center justify-between h-16">
<!-- 로고/타이틀 -->
<div class="flex items-center">
<h2 class="text-xl font-bold text-white">GroupWare</h2>
</div>
<!-- 메뉴 -->
<div class="hidden md:flex items-center space-x-8">
${this.getMenuItemHTML('dashboard', '/Dashboard/', '대시보드', 'M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z M8 5a2 2 0 012-2h4a2 2 0 012 2v2H8V5z')}
${this.getMenuItemHTML('common', '/Common', '공용코드', 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z')}
${this.getMenuItemHTML('jobreport', '/Jobreport/', '업무일지', 'M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2')}
${this.getMenuItemHTML('kuntae', '/Kuntae/', '근태관리', 'M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z')}
</div>
<!-- 모바일 메뉴 버튼 -->
<div class="md:hidden">
<button id="mobile-menu-button" class="text-white/80 hover:text-white transition-colors p-2">
<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="M4 6h16M4 12h16M4 18h16"></path>
</svg>
</button>
</div>
</div>
<!-- 모바일 메뉴 -->
<div id="mobile-menu" class="md:hidden hidden border-t border-white/10 pt-4 pb-4">
${this.getMobileMenuItemHTML('dashboard', '/Dashboard/', '대시보드', 'M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z M8 5a2 2 0 012-2h4a2 2 0 012 2v2H8V5z')}
${this.getMobileMenuItemHTML('common', '/Common', '공용코드', 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z')}
${this.getMobileMenuItemHTML('jobreport', '/Jobreport/', '업무일지', 'M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2')}
${this.getMobileMenuItemHTML('kuntae', '/Kuntae/', '근태관리', 'M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z')}
</div>
</div>
`;
}
getMenuItemHTML(pageKey, href, text, svgPath) {
const isActive = this.currentPage === pageKey;
const activeClass = isActive ? 'text-white bg-white/20' : 'text-white/80 hover:text-white hover:bg-white/10';
return `
<a href="${href}" class="${activeClass} transition-colors px-3 py-2 rounded-lg">
<svg class="w-4 h-4 inline mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="${svgPath}"></path>
</svg>
${text}
</a>
`;
}
getMobileMenuItemHTML(pageKey, href, text, svgPath) {
const isActive = this.currentPage === pageKey;
const activeClass = isActive ? 'text-white bg-white/20' : 'text-white/80 hover:text-white hover:bg-white/10';
return `
<a href="${href}" class="block ${activeClass} transition-colors px-3 py-2 rounded-lg mb-2">
<svg class="w-4 h-4 inline mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="${svgPath}"></path>
</svg>
${text}
</a>
`;
}
addEventListeners() {
// 모바일 메뉴 토글
const mobileMenuButton = document.getElementById('mobile-menu-button');
const mobileMenu = document.getElementById('mobile-menu');
if (mobileMenuButton && mobileMenu) {
mobileMenuButton.addEventListener('click', function() {
mobileMenu.classList.toggle('hidden');
});
}
}
}
// 전역 함수로 내비게이션 초기화
function initNavigation(currentPage = '') {
// DOM이 로드된 후에 실행
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
new CommonNavigation(currentPage);
});
} else {
new CommonNavigation(currentPage);
}
}
// 전역 변수
let currentData = [];
let currentEditId = null;
// 페이지 로드 시 초기화
document.addEventListener('DOMContentLoaded', function() {
// 네비게이션 초기화
initNavigation('kuntae');
initializeDates();
loadData();
setupEventListeners();
@@ -423,41 +637,41 @@
currentData.forEach(item => {
const row = document.createElement('tr');
row.className = 'hover:bg-gray-50 cursor-pointer';
row.className = 'hover:bg-white/10 cursor-pointer transition-colors';
row.setAttribute('data-id', item.idx);
const startDate = item.sdate ? new Date(item.sdate) : null;
const endDate = item.edate ? new Date(item.edate) : null;
row.innerHTML = `
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${item.cate || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${startDate ? formatDate(startDate) : '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${endDate ? formatDate(endDate) : '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${item.uid || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${item.uname || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${item.term || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${item.termdr || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${item.drtime || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${item.crtime || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 max-w-xs truncate" title="${item.contents || ''}">${item.contents || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">${item.cate || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">${startDate ? formatDate(startDate) : '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">${endDate ? formatDate(endDate) : '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">${item.uid || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">${item.uname || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">${item.term || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">${item.termdr || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">${item.drtime || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">${item.crtime || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white/80 max-w-xs truncate" title="${item.contents || ''}">${item.contents || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${item.tag || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">&nbsp;</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">&nbsp;</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">&nbsp;</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">&nbsp;</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">${item.tag || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">&nbsp;</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">&nbsp;</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">&nbsp;</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">&nbsp;</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${item.extcate || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${item.wuid || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${item.wdate || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">${item.extcate || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">${item.wuid || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white">${item.wdate || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-white/80">
<div class="flex space-x-2">
<button class="text-blue-600 hover:text-blue-800 edit-btn" data-id="${item.idx}">
<button class="text-blue-400 hover:text-blue-300 edit-btn transition-colors" data-id="${item.idx}">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
</svg>
</button>
<button class="text-red-600 hover:text-red-800 delete-btn" data-id="${item.idx}">
<button class="text-red-400 hover:text-red-300 delete-btn transition-colors" data-id="${item.idx}">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
</svg>