Files
TK-FB-Project/web-ui/pages.backup.20260202/work/tbm.html
Hyungi Ahn 74d3a78aa3 feat: 페이지 구조 재구성 및 사이드바 네비게이션 구현
- 페이지 폴더 재구성: safety/, attendance/ 폴더 신규 생성
  - work/ → safety/: 이슈 신고, 출입 신청 관련 페이지 이동
  - common/ → attendance/: 근태/휴가 관련 페이지 이동
  - admin/ 정리: safety-* 파일들을 safety/로 이동

- 사이드바 네비게이션 메뉴 구현
  - 카테고리별 메뉴: 작업관리, 안전관리, 근태관리, 시스템관리
  - 접기/펼치기 기능 및 상태 저장
  - 관리자 전용 메뉴 자동 표시/숨김

- 날씨 API 연동 (기상청 단기예보)
  - TBM 및 navbar에 현재 날씨 표시
  - weatherService.js 추가

- 안전 체크리스트 확장
  - 기본/날씨별/작업별 체크 유형 추가
  - checklist-manage.html 페이지 추가

- 이슈 신고 시스템 구현
  - workIssueController, workIssueModel, workIssueRoutes 추가

- DB 마이그레이션 파일 추가 (실행 대기)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 14:27:22 +09:00

651 lines
32 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TBM 관리 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/common.css?v=2">
<link rel="stylesheet" href="/css/project-management.css?v=3">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/auth-check.js?v=1" defer></script>
<script type="module" src="/js/api-config.js?v=3"></script>
<style>
.date-group {
margin-bottom: 2rem;
}
.date-group-header {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem 1rem;
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
border-radius: 0.5rem;
margin-bottom: 1rem;
border-left: 4px solid var(--primary-500);
}
.date-group-header.today {
background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
border-left-color: #3b82f6;
}
.date-group-date {
font-size: 1.1rem;
font-weight: 700;
color: #1f2937;
}
.date-group-day {
font-size: 0.875rem;
color: #6b7280;
padding: 0.25rem 0.5rem;
background: white;
border-radius: 0.25rem;
}
.date-group-count {
margin-left: auto;
font-size: 0.875rem;
color: #6b7280;
}
.date-group-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 1rem;
}
@media (max-width: 768px) {
.date-group-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="work-report-container">
<!-- 네비게이션 바 -->
<div id="navbar-container"></div>
<!-- 메인 콘텐츠 -->
<main class="work-report-main">
<div class="dashboard-main">
<div class="page-header">
<div class="page-title-section">
<h1 class="page-title">
<span class="title-icon">🛠️</span>
TBM (Tool Box Meeting)
</h1>
<p class="page-description">아침 안전 회의 및 팀 구성 관리</p>
</div>
<div class="page-actions" id="headerActions">
<!-- 탭에 따라 동적으로 변경됩니다 -->
</div>
</div>
<!-- TBM 탭 -->
<div class="code-tabs">
<button class="tab-btn active" data-tab="tbm-input" onclick="switchTbmTab('tbm-input')">
<span class="tab-icon"></span>
TBM 입력
</button>
<button class="tab-btn" data-tab="tbm-manage" onclick="switchTbmTab('tbm-manage')">
<span class="tab-icon">📋</span>
TBM 관리
</button>
</div>
<!-- TBM 입력 탭 -->
<div id="tbm-input-tab" class="code-tab-content active">
<div class="code-section">
<div class="section-header">
<h2 class="section-title">
<span class="section-icon">🌅</span>
오늘의 TBM
</h2>
<div class="section-actions">
<button class="btn btn-primary" onclick="openNewTbmModal()">
<span class="btn-icon"></span>
새 TBM 시작
</button>
</div>
</div>
<div class="code-stats">
<span class="stat-item">
<span class="stat-icon">📋</span>
오늘 등록 <span id="todayTotalSessions">0</span>
</span>
<span class="stat-item">
<span class="stat-icon"></span>
완료 <span id="todayCompletedSessions">0</span>
</span>
<span class="stat-item">
<span class="stat-icon"></span>
진행중 <span id="todayActiveSessions">0</span>
</span>
</div>
<div class="code-grid" id="todayTbmGrid">
<!-- 오늘의 TBM 세션 카드들이 여기에 동적으로 생성됩니다 -->
</div>
<!-- Empty State -->
<div class="empty-state" id="todayEmptyState" style="display: none;">
<div class="empty-icon">🛠️</div>
<h3>오늘 등록된 TBM이 없습니다</h3>
<p>"새 TBM 시작" 버튼을 눌러 오늘의 TBM을 시작해보세요.</p>
<button class="btn btn-primary" onclick="openNewTbmModal()">
첫 TBM 시작하기
</button>
</div>
</div>
</div>
<!-- TBM 관리 탭 -->
<div id="tbm-manage-tab" class="code-tab-content">
<div class="code-section">
<div class="section-header">
<h2 class="section-title">
<span class="section-icon">📚</span>
TBM 기록
</h2>
<div class="section-actions">
<button class="btn btn-secondary" onclick="loadMoreTbmDays()" id="loadMoreBtn">
<span class="btn-icon">📅</span>
더 보기
</button>
</div>
</div>
<div class="code-stats">
<span class="stat-item">
<span class="stat-icon">📋</span>
<span id="totalSessions">0</span>
</span>
<span class="stat-item">
<span class="stat-icon"></span>
완료 <span id="completedSessions">0</span>
</span>
<span class="stat-item" id="viewModeIndicator" style="display: none;">
<span class="stat-icon">👤</span>
<span id="viewModeText">내 TBM만</span>
</span>
</div>
<!-- 날짜별 그룹 컨테이너 -->
<div id="tbmDateGroupsContainer">
<!-- 날짜별 TBM 그룹이 여기에 동적으로 생성됩니다 -->
</div>
<!-- Empty State -->
<div class="empty-state" id="emptyState" style="display: none;">
<div class="empty-icon">🛠️</div>
<h3>등록된 TBM 세션이 없습니다</h3>
<p>TBM 입력 탭에서 새로운 TBM을 시작해보세요.</p>
</div>
</div>
</div>
</div>
</main>
<!-- TBM 생성/수정 모달 -->
<div id="tbmModal" class="modal-overlay" style="display: none;">
<div class="modal-container" style="max-width: 1000px;">
<div class="modal-header">
<h2 id="modalTitle">새 TBM 시작</h2>
<button class="modal-close-btn" onclick="closeTbmModal()">×</button>
</div>
<div class="modal-body">
<form id="tbmForm" onsubmit="event.preventDefault(); saveTbmSession();">
<input type="hidden" id="sessionId">
<!-- 고정 정보 섹션 -->
<div class="form-section" style="background: #f9fafb; padding: 1rem; border-radius: 0.5rem; margin-bottom: 1.5rem;">
<div class="form-row">
<div class="form-group">
<label class="form-label">TBM 날짜 *</label>
<input type="date" id="sessionDate" class="form-control" required readonly style="background: #e5e7eb;">
</div>
<div class="form-group">
<label class="form-label">입력자 *</label>
<input type="text" id="leaderName" class="form-control" readonly style="background: #e5e7eb;">
<input type="hidden" id="leaderId">
</div>
</div>
</div>
<!-- 작업자 및 작업 정보 섹션 -->
<div class="form-section">
<div class="section-header" style="margin-bottom: 1rem;">
<h3 style="font-size: 1.1rem; font-weight: 600; color: #1f2937;">
<span style="margin-right: 0.5rem;">👷</span>
작업자 및 작업 정보
</h3>
<div style="display: flex; gap: 0.5rem;">
<button type="button" class="btn btn-sm btn-secondary" onclick="openBulkSettingModal()" style="display: flex; align-items: center; gap: 0.25rem;">
<span>📋</span>
일괄 설정
</button>
<button type="button" class="btn btn-sm btn-primary" onclick="openWorkerSelectionModal()">
<span style="font-size: 1.2rem; margin-right: 0.25rem;">+</span>
작업자 선택
</button>
</div>
</div>
<!-- 작업자 카드 리스트 -->
<div id="workerTaskList" style="display: flex; flex-direction: column; gap: 0.75rem; min-height: 100px;">
<!-- 작업자 카드들이 여기에 동적으로 추가됩니다 -->
<div class="empty-state-small" id="workerListEmpty" style="display: flex; align-items: center; justify-content: center; padding: 2rem; border: 2px dashed #d1d5db; border-radius: 0.5rem; color: #6b7280;">
<div style="text-align: center;">
<div style="font-size: 2rem; margin-bottom: 0.5rem;">👷‍♂️</div>
<p>작업자를 선택해주세요</p>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeTbmModal()">취소</button>
<button type="button" class="btn btn-primary" onclick="saveTbmSession()">
💾 저장하기
</button>
</div>
</div>
</div>
<!-- 일괄 설정 모달 -->
<div id="bulkSettingModal" class="modal-overlay" style="display: none; z-index: 1001;">
<div class="modal-container" style="max-width: 700px;">
<div class="modal-header">
<h2>일괄 설정</h2>
<button class="modal-close-btn" onclick="closeBulkSettingModal()">×</button>
</div>
<div class="modal-body">
<div style="background: #dbeafe; border: 1px solid #3b82f6; padding: 1rem; border-radius: 0.5rem; margin-bottom: 1.5rem;">
<div style="font-weight: 600; color: #1e40af; margin-bottom: 0.25rem;">💡 일괄 설정</div>
<div style="color: #1e40af; font-size: 0.9rem;">
선택한 작업자들의 <strong>첫 번째 작업 라인</strong>에 동일한 정보가 적용됩니다.
</div>
</div>
<!-- 작업자 선택 -->
<div class="form-group">
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.5rem;">
<label class="form-label" style="margin-bottom: 0;">적용할 작업자 선택 *</label>
<div style="display: flex; gap: 0.25rem;">
<button type="button" class="btn btn-sm btn-secondary" onclick="selectAllForBulk()" style="font-size: 0.75rem; padding: 0.25rem 0.5rem;">전체</button>
<button type="button" class="btn btn-sm btn-secondary" onclick="deselectAllForBulk()" style="font-size: 0.75rem; padding: 0.25rem 0.5rem;">해제</button>
</div>
</div>
<div id="bulkWorkerSelection" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.5rem; padding: 0.75rem; border: 1px solid #e5e7eb; border-radius: 0.5rem; max-height: 200px; overflow-y: auto; background: #f9fafb;">
<!-- 작업자 체크박스들이 여기에 생성됩니다 -->
</div>
</div>
<div style="border-top: 1px solid #e5e7eb; margin: 1.5rem 0; padding-top: 1.5rem;">
<h4 style="font-size: 0.95rem; font-weight: 600; margin-bottom: 1rem; color: #374151;">적용할 작업 정보</h4>
<div class="form-group">
<label class="form-label">프로젝트</label>
<button type="button" id="bulkProjectBtn" onclick="openBulkItemSelect('project')" class="btn btn-secondary" style="width: 100%; text-align: left; justify-content: flex-start;">
📁 프로젝트 선택
</button>
<input type="hidden" id="bulkProjectId">
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">공정 *</label>
<button type="button" id="bulkWorkTypeBtn" onclick="openBulkItemSelect('workType')" class="btn btn-secondary" style="width: 100%; text-align: left; justify-content: flex-start;">
⚙️ 공정 선택
</button>
<input type="hidden" id="bulkWorkTypeId">
</div>
<div class="form-group">
<label class="form-label">작업 *</label>
<button type="button" id="bulkTaskBtn" onclick="openBulkItemSelect('task')" class="btn btn-secondary" style="width: 100%; text-align: left; justify-content: flex-start;" disabled>
🔧 작업 선택
</button>
<input type="hidden" id="bulkTaskId">
</div>
</div>
<div class="form-group">
<label class="form-label">작업장 *</label>
<button type="button" id="bulkWorkplaceBtn" onclick="openBulkWorkplaceSelect()" class="btn btn-secondary" style="width: 100%; text-align: left; justify-content: flex-start;">
📍 작업장 선택
</button>
<input type="hidden" id="bulkWorkplaceCategoryId">
<input type="hidden" id="bulkWorkplaceId">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeBulkSettingModal()">취소</button>
<button type="button" class="btn btn-primary" onclick="applyBulkSettings()">
✓ 선택한 작업자에 적용
</button>
</div>
</div>
</div>
<!-- 작업자 선택 모달 -->
<div id="workerSelectionModal" class="modal-overlay" style="display: none; z-index: 1001;">
<div class="modal-container" style="max-width: 800px;">
<div class="modal-header">
<h2>작업자 선택</h2>
<button class="modal-close-btn" onclick="closeWorkerSelectionModal()">×</button>
</div>
<div class="modal-body">
<div style="margin-bottom: 1rem; display: flex; gap: 0.5rem;">
<button type="button" class="btn btn-sm btn-secondary" onclick="selectAllWorkersInModal()">전체 선택</button>
<button type="button" class="btn btn-sm btn-secondary" onclick="deselectAllWorkersInModal()">전체 해제</button>
</div>
<div id="workerCardGrid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 0.75rem; max-height: 500px; overflow-y: auto; padding: 0.5rem;">
<!-- 작업자 카드들이 여기에 생성됩니다 -->
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeWorkerSelectionModal()">취소</button>
<button type="button" class="btn btn-primary" onclick="confirmWorkerSelection()">
✓ 선택 완료
</button>
</div>
</div>
</div>
<!-- 항목 선택 모달 (프로젝트/공정/작업 선택용) -->
<div id="itemSelectModal" class="modal-overlay" style="display: none; z-index: 1002;">
<div class="modal-container" style="max-width: 600px;">
<div class="modal-header">
<h2 id="itemSelectModalTitle">항목 선택</h2>
<button class="modal-close-btn" onclick="closeItemSelectModal()">×</button>
</div>
<div class="modal-body">
<div id="itemSelectList" style="display: flex; flex-direction: column; gap: 0.5rem; max-height: 400px; overflow-y: auto; padding: 0.5rem;">
<!-- 선택 항목들이 여기에 생성됩니다 -->
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeItemSelectModal()">취소</button>
</div>
</div>
</div>
<!-- 작업장 선택 모달 (2단계: 공장 → 작업장) -->
<div id="workplaceSelectModal" class="modal-overlay" style="display: none; z-index: 1002;">
<div class="modal-container" style="max-width: 1000px; max-height: 90vh;">
<div class="modal-header">
<h2>작업장 선택</h2>
<button class="modal-close-btn" onclick="closeWorkplaceSelectModal()">×</button>
</div>
<div class="modal-body" style="overflow-y: auto;">
<!-- 1단계: 공장 선택 -->
<div style="margin-bottom: 1.5rem;">
<h3 style="font-size: 1rem; font-weight: 600; margin-bottom: 0.75rem; color: #374151;">
<span style="margin-right: 0.5rem;">🏭</span>
1. 공장 선택
</h3>
<div id="categoryList" style="display: flex; flex-wrap: wrap; gap: 0.5rem; padding: 0.75rem; border: 1px solid #e5e7eb; border-radius: 0.5rem; background: #f9fafb;">
<!-- 공장 카테고리 버튼들이 여기에 생성됩니다 -->
</div>
</div>
<!-- 2단계: 작업장 선택 (지도 + 리스트) -->
<div id="workplaceSelectionArea" style="display: none;">
<h3 style="font-size: 1rem; font-weight: 600; margin-bottom: 0.75rem; color: #374151;">
<span style="margin-right: 0.5rem;">📍</span>
2. 작업장 선택
</h3>
<!-- 지도 기반 선택 영역 -->
<div id="layoutMapArea" style="display: none; margin-bottom: 1.5rem; padding: 1rem; background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 0.5rem;">
<div style="font-size: 0.875rem; color: #6b7280; margin-bottom: 0.75rem;">
<span style="margin-right: 0.25rem;">🗺️</span>
지도에서 작업장을 클릭하여 선택하세요
</div>
<div style="text-align: center; position: relative; display: inline-block; max-width: 100%;">
<canvas id="workplaceMapCanvas" style="max-width: 100%; border-radius: 0.5rem; cursor: pointer; box-shadow: 0 2px 4px rgba(0,0,0,0.1);"></canvas>
</div>
</div>
<!-- 리스트 기반 선택 (오류 대비용) -->
<div>
<div style="font-size: 0.875rem; color: #6b7280; margin-bottom: 0.75rem; display: flex; align-items: center; justify-content: space-between;">
<span>
<span style="margin-right: 0.25rem;">📋</span>
리스트에서 선택 (지도 오류 시)
</span>
<button type="button" class="btn btn-sm btn-secondary" onclick="toggleWorkplaceList()" id="toggleListBtn">
<span id="toggleListIcon"></span>
리스트 보기
</button>
</div>
<div id="workplaceList" style="display: none; flex-direction: column; gap: 0.5rem; max-height: 300px; overflow-y: auto; padding: 0.75rem; border: 1px solid #e5e7eb; border-radius: 0.5rem; background: white;">
<div style="color: #9ca3af; text-align: center; padding: 2rem;">
공장을 먼저 선택해주세요
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeWorkplaceSelectModal()">취소</button>
<button type="button" class="btn btn-primary" onclick="confirmWorkplaceSelection()" id="confirmWorkplaceBtn" disabled>
✓ 선택 완료
</button>
</div>
</div>
</div>
<!-- 팀 구성 모달 -->
<div id="teamModal" class="modal-overlay" style="display: none;">
<div class="modal-container" style="max-width: 900px;">
<div class="modal-header">
<h2>팀 구성</h2>
<button class="modal-close-btn" onclick="closeTeamModal()">×</button>
</div>
<div class="modal-body">
<div class="section-header" style="margin-bottom: 1rem;">
<h3 style="font-size: 1rem; font-weight: 600;">작업자 선택</h3>
<div>
<button class="btn btn-sm btn-secondary" onclick="selectAllWorkers()">전체 선택</button>
<button class="btn btn-sm btn-secondary" onclick="deselectAllWorkers()">전체 해제</button>
</div>
</div>
<div id="workerSelectionGrid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 0.75rem; max-height: 400px; overflow-y: auto; padding: 0.5rem; border: 1px solid #e5e7eb; border-radius: 0.5rem;">
<!-- 작업자 체크박스 목록이 여기에 생성됩니다 -->
</div>
<div style="margin-top: 1.5rem;">
<h3 style="font-size: 1rem; font-weight: 600; margin-bottom: 0.75rem;">선택된 팀원 <span id="selectedCount">0</span></h3>
<div id="selectedWorkersList" style="display: flex; flex-wrap: wrap; gap: 0.5rem; min-height: 50px; padding: 0.75rem; background: #f9fafb; border-radius: 0.5rem;">
<p style="margin: 0; color: #9ca3af; font-size: 0.875rem;">작업자를 선택해주세요</p>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeTeamModal()">취소</button>
<button type="button" class="btn btn-primary" onclick="saveTeamComposition()">
👥 팀 구성 완료
</button>
</div>
</div>
</div>
<!-- 안전 체크리스트 모달 -->
<div id="safetyModal" class="modal-overlay" style="display: none;">
<div class="modal-container" style="max-width: 700px;">
<div class="modal-header">
<h2>안전 체크리스트</h2>
<button class="modal-close-btn" onclick="closeSafetyModal()">×</button>
</div>
<div class="modal-body">
<div id="safetyChecklistContainer" style="max-height: 500px; overflow-y: auto;">
<!-- 안전 체크리스트가 여기에 생성됩니다 -->
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeSafetyModal()">취소</button>
<button type="button" class="btn btn-primary" onclick="saveSafetyChecklist()">
✅ 안전 체크 완료
</button>
</div>
</div>
</div>
<!-- TBM 완료 모달 -->
<div id="completeModal" class="modal-overlay" style="display: none;">
<div class="modal-container" style="max-width: 500px;">
<div class="modal-header">
<h2>TBM 완료</h2>
<button class="modal-close-btn" onclick="closeCompleteModal()">×</button>
</div>
<div class="modal-body">
<p style="margin-bottom: 1rem;">이 TBM 세션을 완료 처리하시겠습니까?</p>
<p style="color: #6b7280; font-size: 0.875rem;">완료 후에는 수정할 수 없습니다.</p>
<div class="form-group" style="margin-top: 1.5rem;">
<label class="form-label">종료 시간</label>
<input type="time" id="endTime" class="form-control">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeCompleteModal()">취소</button>
<button type="button" class="btn btn-primary" onclick="completeTbmSession()">
✅ 완료
</button>
</div>
</div>
</div>
<!-- 작업 인계 모달 -->
<div id="handoverModal" class="modal-overlay" style="display: none;">
<div class="modal-container" style="max-width: 600px;">
<div class="modal-header">
<h2>작업 인계</h2>
<button class="modal-close-btn" onclick="closeHandoverModal()">×</button>
</div>
<div class="modal-body">
<form id="handoverForm">
<input type="hidden" id="handoverSessionId">
<div class="form-group">
<label class="form-label">인계 사유 *</label>
<select id="handoverReason" class="form-control" required>
<option value="">사유 선택...</option>
<option value="half_day">반차</option>
<option value="early_leave">조퇴</option>
<option value="emergency">긴급 상황</option>
<option value="other">기타</option>
</select>
</div>
<div class="form-group">
<label class="form-label">인수자 (다음 팀장) *</label>
<select id="toLeaderId" class="form-control" required>
<option value="">인수자 선택...</option>
</select>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">인계 날짜 *</label>
<input type="date" id="handoverDate" class="form-control" required>
</div>
<div class="form-group">
<label class="form-label">인계 시간</label>
<input type="time" id="handoverTime" class="form-control">
</div>
</div>
<div class="form-group">
<label class="form-label">인계 내용</label>
<textarea id="handoverNotes" class="form-control" rows="4" placeholder="인수자에게 전달할 내용을 입력하세요"></textarea>
</div>
<div class="form-group">
<label class="form-label" style="margin-bottom: 0.75rem; display: block;">인계할 팀원 선택</label>
<div id="handoverTeamList" style="max-height: 200px; overflow-y: auto; border: 1px solid #e5e7eb; border-radius: 0.5rem; padding: 0.5rem;">
<!-- 팀원 체크박스 목록 -->
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeHandoverModal()">취소</button>
<button type="button" class="btn btn-primary" onclick="saveHandover()">
📤 인계 요청
</button>
</div>
</div>
</div>
<!-- TBM 상세보기 모달 -->
<div id="detailModal" class="modal-overlay" style="display: none;">
<div class="modal-container" style="max-width: 900px;">
<div class="modal-header">
<h2>TBM 상세 정보</h2>
<button class="modal-close-btn" onclick="closeDetailModal()">×</button>
</div>
<div class="modal-body" style="max-height: 70vh; overflow-y: auto;">
<!-- 세션 기본 정보 -->
<div class="section" style="margin-bottom: 1.5rem;">
<h3 style="font-size: 1rem; font-weight: 600; margin-bottom: 1rem; color: #374151;">기본 정보</h3>
<div id="detailBasicInfo" style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.75rem;">
<!-- 동적 생성 -->
</div>
</div>
<!-- 팀 구성 -->
<div class="section" style="margin-bottom: 1.5rem;">
<h3 style="font-size: 1rem; font-weight: 600; margin-bottom: 1rem; color: #374151;">팀 구성</h3>
<div id="detailTeamMembers" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 0.75rem;">
<!-- 동적 생성 -->
</div>
</div>
<!-- 안전 체크 -->
<div class="section">
<h3 style="font-size: 1rem; font-weight: 600; margin-bottom: 1rem; color: #374151;">안전 체크리스트</h3>
<div id="detailSafetyChecks">
<!-- 동적 생성 -->
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeDetailModal()">닫기</button>
</div>
</div>
</div>
<!-- 토스트 알림 -->
<div class="toast-container" id="toastContainer"></div>
</div>
<script type="module" src="/js/load-navbar.js?v=5"></script>
<script type="module" src="/js/tbm.js?v=3"></script>
</body>
</html>