feat: 대시보드 작업장 현황 지도 구현
- 실시간 작업장 현황을 지도로 시각화 - 작업장 관리 페이지에서 정의한 구역 정보 활용 - TBM 작업자 및 방문자 현황 표시 주요 변경사항: - dashboard.html: 작업장 현황 섹션 추가 (기존 작업 현황 테이블 제거) - workplace-status.js: 지도 렌더링 및 데이터 통합 로직 구현 - modern-dashboard.js: 삭제된 DOM 요소 조건부 체크 추가 시각화 방식: - 인원 없음: 회색 테두리 + 작업장 이름 - 내부 작업자: 파란색 영역 + 인원 수 - 외부 방문자: 보라색 영역 + 인원 수 - 둘 다: 초록색 영역 + 총 인원 수 기술 구현: - Canvas API 기반 사각형 영역 렌더링 - map-regions API를 통한 데이터 일관성 보장 - 클릭 이벤트로 상세 정보 모달 표시 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
<script type="module" src="/js/load-navbar.js"></script>
|
||||
<script type="module" src="/js/modern-dashboard.js?v=10" defer></script>
|
||||
<script type="module" src="/js/group-leader-dashboard.js?v=1" defer></script>
|
||||
<script src="/js/workplace-status.js" defer></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -46,6 +47,22 @@
|
||||
<div class="action-arrow" style="color: white;">→</div>
|
||||
</a>
|
||||
|
||||
<a href="/pages/work/visit-request.html" class="quick-action-card" style="background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%); color: white;">
|
||||
<div class="action-content">
|
||||
<h3 style="color: white;">🚪 출입 신청</h3>
|
||||
<p style="color: rgba(255, 255, 255, 0.9);">작업장 출입 및 안전교육을 신청합니다</p>
|
||||
</div>
|
||||
<div class="action-arrow" style="color: white;">→</div>
|
||||
</a>
|
||||
|
||||
<a href="/pages/admin/safety-management.html" class="quick-action-card admin-only" style="background: linear-gradient(135deg, #ec4899 0%, #db2777 100%); color: white;">
|
||||
<div class="action-content">
|
||||
<h3 style="color: white;">🛡️ 안전관리</h3>
|
||||
<p style="color: rgba(255, 255, 255, 0.9);">출입 신청 승인 및 안전교육 관리</p>
|
||||
</div>
|
||||
<div class="action-arrow" style="color: white;">→</div>
|
||||
</a>
|
||||
|
||||
<a href="/pages/work/report-create.html" class="quick-action-card">
|
||||
<div class="action-content">
|
||||
<h3>작업 보고서 작성</h3>
|
||||
@@ -77,46 +94,111 @@
|
||||
</div>
|
||||
<div class="action-arrow">→</div>
|
||||
</a>
|
||||
|
||||
<a href="/pages/common/daily-attendance.html" class="quick-action-card" style="background: linear-gradient(135deg, #06b6d4 0%, #0891b2 100%); color: white;">
|
||||
<div class="action-content">
|
||||
<h3 style="color: white;">📅 일일 출퇴근 입력</h3>
|
||||
<p style="color: rgba(255, 255, 255, 0.9);">오늘의 출퇴근 기록을 입력합니다</p>
|
||||
</div>
|
||||
<div class="action-arrow" style="color: white;">→</div>
|
||||
</a>
|
||||
|
||||
<a href="/pages/common/monthly-attendance.html" class="quick-action-card">
|
||||
<div class="action-content">
|
||||
<h3>📆 월별 출퇴근 현황</h3>
|
||||
<p>이번 달 출퇴근 현황을 조회합니다</p>
|
||||
</div>
|
||||
<div class="action-arrow">→</div>
|
||||
</a>
|
||||
|
||||
<a href="/pages/common/vacation-request.html" class="quick-action-card">
|
||||
<div class="action-content">
|
||||
<h3>📝 휴가 신청</h3>
|
||||
<p>휴가를 신청하고 신청 내역을 확인합니다</p>
|
||||
</div>
|
||||
<div class="action-arrow">→</div>
|
||||
</a>
|
||||
|
||||
<a href="/pages/common/vacation-management.html" class="quick-action-card admin-only">
|
||||
<div class="action-content">
|
||||
<h3>🏖️ 휴가 관리</h3>
|
||||
<p>휴가 승인, 직접 입력, 전체 내역을 관리합니다</p>
|
||||
</div>
|
||||
<div class="action-arrow">→</div>
|
||||
</a>
|
||||
|
||||
<a href="/pages/common/annual-vacation-overview.html" class="quick-action-card admin-only">
|
||||
<div class="action-content">
|
||||
<h3>📊 연간 연차 현황</h3>
|
||||
<p>모든 작업자의 연간 휴가 현황을 차트로 확인합니다</p>
|
||||
</div>
|
||||
<div class="action-arrow">→</div>
|
||||
</a>
|
||||
|
||||
<a href="/pages/common/vacation-allocation.html" class="quick-action-card admin-only">
|
||||
<div class="action-content">
|
||||
<h3>➕ 휴가 발생 입력</h3>
|
||||
<p>작업자별 휴가를 입력하고 특별 휴가를 관리합니다</p>
|
||||
</div>
|
||||
<div class="action-arrow">→</div>
|
||||
</a>
|
||||
|
||||
<a href="/pages/admin/attendance-report-comparison.html" class="quick-action-card admin-only">
|
||||
<div class="action-content">
|
||||
<h3>🔍 출퇴근-작업보고서 대조</h3>
|
||||
<p>출퇴근 기록과 작업보고서를 비교 분석합니다</p>
|
||||
</div>
|
||||
<div class="action-arrow">→</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 오늘의 작업 현황 -->
|
||||
<section class="work-status-section">
|
||||
<!-- 작업장 현황 -->
|
||||
<section class="workplace-status-section">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="flex justify-between items-center">
|
||||
<h2 class="card-title">오늘의 작업 현황</h2>
|
||||
<div class="date-selector">
|
||||
<input type="date" id="selectedDate" class="date-input">
|
||||
<button class="btn btn-primary btn-sm" id="refreshBtn">
|
||||
<h2 class="card-title">작업장 현황</h2>
|
||||
<div class="flex items-center" style="gap: 12px;">
|
||||
<select id="categorySelect" class="form-select" style="width: 200px;">
|
||||
<option value="">공장을 선택하세요</option>
|
||||
</select>
|
||||
<button class="btn btn-primary btn-sm" id="refreshMapBtn">
|
||||
새로고침
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="work-status-table-container">
|
||||
<table class="work-status-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>작업자</th>
|
||||
<th>상태</th>
|
||||
<th>작업시간</th>
|
||||
<th>작업건수</th>
|
||||
<th>액션</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="workStatusTableBody">
|
||||
<tr>
|
||||
<td colspan="5" class="loading-state">
|
||||
<div class="spinner"></div>
|
||||
<p>작업 현황을 불러오는 중...</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- 지도 영역 -->
|
||||
<div id="workplaceMapContainer" style="position: relative; min-height: 500px; display: none;">
|
||||
<canvas id="workplaceMapCanvas" style="width: 100%; max-width: 100%; cursor: pointer; border: 2px solid var(--gray-300); border-radius: var(--radius-md);"></canvas>
|
||||
<div id="mapLegend" style="position: absolute; top: 16px; right: 16px; background: white; padding: 16px; border-radius: var(--radius-md); box-shadow: var(--shadow-md);">
|
||||
<h4 style="font-size: var(--text-sm); font-weight: 700; margin-bottom: 12px;">범례</h4>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<div style="width: 16px; height: 16px; background: rgba(59, 130, 246, 0.3); border: 2px solid rgb(59, 130, 246); border-radius: 4px;"></div>
|
||||
<span style="font-size: var(--text-sm);">작업 중 (내부 작업자)</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<div style="width: 16px; height: 16px; background: rgba(168, 85, 247, 0.3); border: 2px solid rgb(168, 85, 247); border-radius: 4px;"></div>
|
||||
<span style="font-size: var(--text-sm);">방문 예정 (외부 인원)</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<div style="width: 16px; height: 16px; background: rgba(34, 197, 94, 0.3); border: 2px solid rgb(34, 197, 94); border-radius: 4px;"></div>
|
||||
<span style="font-size: var(--text-sm);">작업 + 방문</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 안내 메시지 -->
|
||||
<div id="mapPlaceholder" style="display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 400px; color: var(--gray-500);">
|
||||
<div style="font-size: 48px; margin-bottom: 16px;">🏭</div>
|
||||
<h3 style="margin-bottom: 8px;">공장을 선택하세요</h3>
|
||||
<p style="font-size: var(--text-sm);">위에서 공장을 선택하면 작업장 현황을 확인할 수 있습니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -144,6 +226,28 @@
|
||||
<!-- 알림 토스트 -->
|
||||
<div class="toast-container" id="toastContainer"></div>
|
||||
|
||||
<!-- 작업장 상세 정보 모달 -->
|
||||
<div id="workplaceDetailModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); z-index: 1000; align-items: center; justify-content: center;">
|
||||
<div style="background: white; border-radius: var(--radius-lg); padding: 32px; max-width: 800px; width: 90%; max-height: 80vh; overflow-y: auto; box-shadow: var(--shadow-2xl);">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px;">
|
||||
<h2 id="modalWorkplaceName" style="margin: 0; font-size: var(--text-2xl); font-weight: 700;"></h2>
|
||||
<button class="btn btn-secondary btn-sm" onclick="closeWorkplaceModal()">닫기</button>
|
||||
</div>
|
||||
|
||||
<!-- 내부 작업자 -->
|
||||
<div id="internalWorkersSection" style="margin-bottom: 24px;">
|
||||
<h3 style="font-size: var(--text-lg); font-weight: 600; margin-bottom: 16px; color: var(--primary-600);">👷 내부 작업자</h3>
|
||||
<div id="internalWorkersList"></div>
|
||||
</div>
|
||||
|
||||
<!-- 외부 방문자 -->
|
||||
<div id="externalVisitorsSection">
|
||||
<h3 style="font-size: var(--text-lg); font-weight: 600; margin-bottom: 16px; color: var(--purple-600);">🚪 외부 방문자</h3>
|
||||
<div id="externalVisitorsList"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user