refactor: 작업자 관리 페이지를 카드에서 테이블 형식으로 변경
## 변경 사항 - UI 형식: 카드 그리드 → 엑셀 스타일 테이블 - 더 많은 정보를 한눈에 볼 수 있음 - 공간 활용 효율성 향상 ## HTML 변경 (workers.html) - 테이블 구조 추가 - 컬럼: 상태, 이름, 직책, 전화번호, 이메일, 입사일, 부서, 계정, 현장직, 등록일, 관리 - tbody id="workersGrid" 유지 (기존 코드 호환성) ## JavaScript 변경 (worker-management.js) - renderWorkers() 함수 리팩토링 - 카드 HTML 생성 → 테이블 행 생성 - 상태 배지: 현장직(초록), 사무직(노랑), 퇴사(빨강) - 아바타 아이콘 유지 (이름 첫 글자) - 아이콘 버튼으로 편집/상태변경/삭제 기능 ## CSS 변경 (admin-pages.css) - 테이블 내 버튼 스타일 추가 - .data-table .btn-icon - hover 효과 및 transform ## 유지된 기능 - 검색 및 필터링 - 정렬 - 통계 표시 - 편집/삭제/상태 변경 - Empty state 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -813,6 +813,22 @@ tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* 테이블 내 버튼 스타일 */
|
||||
.data-table .btn-icon {
|
||||
padding: 0.375rem 0.5rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
transition: all 0.2s ease;
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.data-table .btn-icon:hover {
|
||||
background: var(--bg-hover);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
11. 모달
|
||||
============================================ */
|
||||
|
||||
@@ -175,18 +175,19 @@ async function loadWorkers() {
|
||||
function renderWorkers() {
|
||||
const workersGrid = document.getElementById('workersGrid');
|
||||
const emptyState = document.getElementById('emptyState');
|
||||
|
||||
const tableContainer = document.querySelector('.table-container');
|
||||
|
||||
if (!workersGrid || !emptyState) return;
|
||||
|
||||
|
||||
if (filteredWorkers.length === 0) {
|
||||
workersGrid.style.display = 'none';
|
||||
emptyState.style.display = 'block';
|
||||
if (tableContainer) tableContainer.style.display = 'none';
|
||||
emptyState.style.display = 'flex';
|
||||
return;
|
||||
}
|
||||
|
||||
workersGrid.style.display = 'grid';
|
||||
|
||||
if (tableContainer) tableContainer.style.display = 'block';
|
||||
emptyState.style.display = 'none';
|
||||
|
||||
|
||||
const workersHtml = filteredWorkers.map(worker => {
|
||||
// 작업자 상태 및 직책 아이콘
|
||||
const jobTypeMap = {
|
||||
@@ -194,66 +195,66 @@ function renderWorkers() {
|
||||
'leader': { icon: '👨💼', text: '그룹장', color: '#3b82f6' },
|
||||
'admin': { icon: '👨💻', text: '관리자', color: '#8b5cf6' }
|
||||
};
|
||||
|
||||
|
||||
const jobType = jobTypeMap[worker.job_type] || jobTypeMap['worker'];
|
||||
const isInactive = worker.status === 'inactive' || worker.is_active === 0 || worker.is_active === false;
|
||||
const isResigned = worker.employment_status === 'resigned';
|
||||
const hasAccount = worker.user_id !== null && worker.user_id !== undefined;
|
||||
|
||||
console.log('🎨 카드 렌더링:', {
|
||||
worker_id: worker.worker_id,
|
||||
worker_name: worker.worker_name,
|
||||
status: worker.status,
|
||||
is_active: worker.is_active,
|
||||
isInactive: isInactive,
|
||||
isResigned: isResigned,
|
||||
user_id: worker.user_id,
|
||||
hasAccount: hasAccount
|
||||
});
|
||||
// 상태 배지
|
||||
let statusBadge = '';
|
||||
if (isResigned) {
|
||||
statusBadge = '<span style="display: inline-block; padding: 0.25rem 0.5rem; background: #fee2e2; color: #dc2626; border-radius: 0.25rem; font-size: 0.75rem; font-weight: 600;">퇴사</span>';
|
||||
} else if (isInactive) {
|
||||
statusBadge = '<span style="display: inline-block; padding: 0.25rem 0.5rem; background: #fef3c7; color: #92400e; border-radius: 0.25rem; font-size: 0.75rem; font-weight: 600;">사무직</span>';
|
||||
} else {
|
||||
statusBadge = '<span style="display: inline-block; padding: 0.25rem 0.5rem; background: #d1fae5; color: #065f46; border-radius: 0.25rem; font-size: 0.75rem; font-weight: 600;">현장직</span>';
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="project-card worker-card ${isResigned ? 'resigned' : ''} ${isInactive ? 'inactive' : ''}" onclick="editWorker(${worker.worker_id})">
|
||||
${isResigned ? '<div class="inactive-overlay"><span class="inactive-badge" style="background: #dc2626;">🚪 퇴사</span></div>' :
|
||||
isInactive ? '<div class="inactive-overlay"><span class="inactive-badge">🏢 사무직</span></div>' : ''}
|
||||
<div class="project-header">
|
||||
<div class="project-info">
|
||||
<div class="worker-avatar">
|
||||
<span class="avatar-initial">${worker.worker_name.charAt(0)}</span>
|
||||
</div>
|
||||
<h3 class="project-name">
|
||||
${worker.worker_name}
|
||||
${hasAccount ? '<span style="color: #10b981; font-size: 0.8rem; margin-left: 0.5rem;">🔐</span>' : ''}
|
||||
${isResigned ? '<span class="inactive-label" style="color: #dc2626;">(퇴사)</span>' :
|
||||
isInactive ? '<span class="inactive-label">(사무직)</span>' : ''}
|
||||
</h3>
|
||||
<div class="project-meta">
|
||||
<span style="color: ${jobType.color}; font-weight: 500;">${jobType.icon} ${jobType.text}</span>
|
||||
${hasAccount ? '<span style="color: #10b981;">🔐 계정 연동됨</span>' : '<span style="color: #9ca3af;">⚪ 계정 없음</span>'}
|
||||
${worker.phone_number ? `<span>📞 ${worker.phone_number}</span>` : ''}
|
||||
${worker.email ? `<span>📧 ${worker.email}</span>` : ''}
|
||||
${worker.department ? `<span>🏢 ${worker.department}</span>` : ''}
|
||||
${worker.hire_date ? `<span>📅 입사: ${formatDate(worker.hire_date)}</span>` : ''}
|
||||
${isResigned ? '<span class="inactive-notice" style="color: #dc2626;">⚠️ 퇴사 처리됨</span>' : ''}
|
||||
<tr class="${isResigned ? 'row-resigned' : ''}" style="${isResigned ? 'opacity: 0.6;' : ''}">
|
||||
<td style="text-align: center;">${statusBadge}</td>
|
||||
<td style="font-weight: 600;">
|
||||
<div style="display: flex; align-items: center; gap: 0.5rem;">
|
||||
<div style="width: 32px; height: 32px; border-radius: 50%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 0.875rem;">
|
||||
${worker.worker_name.charAt(0)}
|
||||
</div>
|
||||
${worker.worker_name}
|
||||
</div>
|
||||
<div class="project-actions">
|
||||
<button class="btn-toggle ${isInactive ? 'btn-activate' : 'btn-deactivate'}"
|
||||
onclick="event.stopPropagation(); toggleWorkerStatus(${worker.worker_id})"
|
||||
title="${isInactive ? '현장직으로 변경' : '사무직으로 변경'}">
|
||||
${isInactive ? '🏭' : '🏢'}
|
||||
</button>
|
||||
<button class="btn-edit" onclick="event.stopPropagation(); editWorker(${worker.worker_id})" title="수정">
|
||||
</td>
|
||||
<td>
|
||||
<span style="color: ${jobType.color}; font-weight: 500;">
|
||||
${jobType.icon} ${jobType.text}
|
||||
</span>
|
||||
</td>
|
||||
<td>${worker.phone_number || '-'}</td>
|
||||
<td style="font-size: 0.875rem;">${worker.email || '-'}</td>
|
||||
<td>${worker.hire_date ? formatDate(worker.hire_date) : '-'}</td>
|
||||
<td>${worker.department || '-'}</td>
|
||||
<td style="text-align: center;">
|
||||
${hasAccount ? '<span style="color: #10b981; font-size: 1.25rem;" title="계정 연동됨">🔐</span>' : '<span style="color: #d1d5db; font-size: 1.25rem;" title="계정 없음">⚪</span>'}
|
||||
</td>
|
||||
<td style="text-align: center;">
|
||||
${isInactive ? '<span style="color: #d1d5db; font-size: 1.25rem;">🏢</span>' : '<span style="color: #10b981; font-size: 1.25rem;">🏭</span>'}
|
||||
</td>
|
||||
<td style="font-size: 0.875rem; color: #6b7280;">${worker.created_at ? formatDate(worker.created_at) : '-'}</td>
|
||||
<td>
|
||||
<div style="display: flex; gap: 0.25rem; justify-content: center;">
|
||||
<button class="btn-icon" onclick="editWorker(${worker.worker_id})" title="수정">
|
||||
✏️
|
||||
</button>
|
||||
<button class="btn-delete" onclick="event.stopPropagation(); confirmDeleteWorker(${worker.worker_id})" title="삭제">
|
||||
<button class="btn-icon" onclick="toggleWorkerStatus(${worker.worker_id})" title="${isInactive ? '현장직으로 변경' : '사무직으로 변경'}">
|
||||
${isInactive ? '🏭' : '🏢'}
|
||||
</button>
|
||||
<button class="btn-icon" onclick="confirmDeleteWorker(${worker.worker_id})" title="삭제" style="color: #ef4444;">
|
||||
🗑️
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
|
||||
workersGrid.innerHTML = workersHtml;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,11 +138,31 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="projects-grid" id="workersGrid">
|
||||
<!-- 작업자 카드들이 여기에 동적으로 생성됩니다 -->
|
||||
|
||||
<!-- 작업자 테이블 -->
|
||||
<div class="table-container">
|
||||
<table class="data-table" id="workersTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 60px;">상태</th>
|
||||
<th style="width: 100px;">이름</th>
|
||||
<th style="width: 100px;">직책</th>
|
||||
<th style="width: 130px;">전화번호</th>
|
||||
<th style="width: 180px;">이메일</th>
|
||||
<th style="width: 100px;">입사일</th>
|
||||
<th style="width: 100px;">부서</th>
|
||||
<th style="width: 80px;">계정</th>
|
||||
<th style="width: 80px;">현장직</th>
|
||||
<th style="width: 120px;">등록일</th>
|
||||
<th style="width: 100px;">관리</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="workersGrid">
|
||||
<!-- 작업자 행들이 여기에 동적으로 생성됩니다 -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Empty State -->
|
||||
<div class="empty-state" id="emptyState" style="display: none;">
|
||||
<div class="empty-icon">👥</div>
|
||||
|
||||
Reference in New Issue
Block a user