tbmModal에 편집 모드용 workerTaskListSection/workerTaskList/workerListEmpty 요소 추가. openTeamCompositionModal에서 생성↔편집 모드 전환 로직 추가, closeTbmModal에서 원복. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
587 lines
36 KiB
HTML
587 lines
36 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ko">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>TBM 관리 - TK 공장관리</title>
|
||
<script src="https://cdn.tailwindcss.com"></script>
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||
<link rel="stylesheet" href="/static/css/tkfb.css?v=2026031601">
|
||
<link rel="stylesheet" href="/css/tbm.css?v=2026031602">
|
||
</head>
|
||
<body class="bg-gray-50">
|
||
<header class="bg-orange-700 text-white sticky top-0 z-50">
|
||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||
<div class="flex justify-between items-center h-14">
|
||
<div class="flex items-center gap-3">
|
||
<button id="mobileMenuBtn" class="lg:hidden text-orange-200 hover:text-white">
|
||
<i class="fas fa-bars text-xl"></i>
|
||
</button>
|
||
<i class="fas fa-industry text-xl text-orange-200"></i>
|
||
<h1 class="text-lg font-semibold">TK 공장관리</h1>
|
||
</div>
|
||
<div class="flex items-center gap-4">
|
||
<span id="headerUserName" class="text-sm hidden sm:block">-</span>
|
||
<div id="headerUserAvatar" class="w-8 h-8 bg-orange-600 rounded-full flex items-center justify-center text-sm font-bold">-</div>
|
||
<button onclick="doLogout()" class="text-orange-200 hover:text-white" title="로그아웃">
|
||
<i class="fas fa-sign-out-alt"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Mobile overlay -->
|
||
<div id="mobileOverlay" class="hidden fixed inset-0 bg-black/50 z-30 lg:hidden"></div>
|
||
|
||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 fade-in">
|
||
<div class="flex gap-6">
|
||
<!-- Sidebar Nav -->
|
||
<nav id="sideNav" class="hidden lg:flex flex-col gap-1 w-52 flex-shrink-0 pt-2 fixed lg:static z-40 bg-white lg:bg-transparent p-4 lg:p-0 rounded-lg lg:rounded-none shadow-lg lg:shadow-none top-14 left-0 bottom-0 overflow-y-auto"></nav>
|
||
|
||
<div class="flex-1 min-w-0">
|
||
<div class="tbm-container">
|
||
<!-- 페이지 헤더 -->
|
||
<div class="tbm-page-header">
|
||
<div class="tbm-title-section">
|
||
<h1 class="tbm-page-title">
|
||
<span class="tbm-page-title-icon">🛠</span>
|
||
TBM (Tool Box Meeting)
|
||
</h1>
|
||
<p class="tbm-page-description">아침 안전 회의 및 팀 구성 관리</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TBM 탭 메뉴 -->
|
||
<div class="tbm-tab-menu">
|
||
<button class="tbm-tab-btn active" data-tab="tbm-input" onclick="switchTbmTab('tbm-input')">
|
||
<span class="tbm-tab-icon">📝</span>
|
||
TBM 입력
|
||
</button>
|
||
<button class="tbm-tab-btn" data-tab="tbm-manage" onclick="switchTbmTab('tbm-manage')">
|
||
<span class="tbm-tab-icon">📊</span>
|
||
TBM 관리
|
||
</button>
|
||
</div>
|
||
|
||
<!-- TBM 입력 탭 -->
|
||
<div id="tbm-input-tab" class="tbm-tab-content active">
|
||
<div class="tbm-section">
|
||
<div class="tbm-section-header">
|
||
<h2 class="tbm-section-title">
|
||
<span>📅</span>
|
||
오늘의 TBM
|
||
</h2>
|
||
<div class="tbm-section-actions">
|
||
<button class="tbm-btn tbm-btn-primary" onclick="openNewTbmModal()">
|
||
<span class="tbm-btn-icon">+</span>
|
||
새 TBM 시작
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="tbm-stats-bar">
|
||
<span class="tbm-stat-item">
|
||
<span class="tbm-stat-label">오늘 등록</span>
|
||
<span class="tbm-stat-value highlight" id="todayTotalSessions">0</span>
|
||
<span class="tbm-stat-label">개</span>
|
||
</span>
|
||
<span class="tbm-stat-item">
|
||
<span class="tbm-stat-label">완료</span>
|
||
<span class="tbm-stat-value success" id="todayCompletedSessions">0</span>
|
||
<span class="tbm-stat-label">개</span>
|
||
</span>
|
||
<span class="tbm-stat-item">
|
||
<span class="tbm-stat-label">진행중</span>
|
||
<span class="tbm-stat-value warning" id="todayActiveSessions">0</span>
|
||
<span class="tbm-stat-label">개</span>
|
||
</span>
|
||
</div>
|
||
|
||
<div class="tbm-card-grid" id="todayTbmGrid"></div>
|
||
|
||
<div class="tbm-empty-state" id="todayEmptyState" style="display: none;">
|
||
<div class="tbm-empty-icon">📋</div>
|
||
<h3 class="tbm-empty-title">오늘 등록된 TBM이 없습니다</h3>
|
||
<p class="tbm-empty-description">"새 TBM 시작" 버튼을 눌러 오늘의 TBM을 시작해보세요.</p>
|
||
<button class="tbm-btn tbm-btn-primary" onclick="openNewTbmModal()">
|
||
<span class="tbm-btn-icon">+</span>
|
||
첫 TBM 시작하기
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TBM 관리 탭 -->
|
||
<div id="tbm-manage-tab" class="tbm-tab-content">
|
||
<div class="tbm-section">
|
||
<div class="tbm-section-header">
|
||
<h2 class="tbm-section-title">
|
||
<span>📚</span>
|
||
TBM 기록
|
||
</h2>
|
||
<div class="tbm-section-actions">
|
||
<button class="tbm-btn tbm-btn-secondary" onclick="loadMoreTbmDays()" id="loadMoreBtn">
|
||
더 보기
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="tbm-stats-bar">
|
||
<span class="tbm-stat-item">
|
||
<span class="tbm-stat-label">총</span>
|
||
<span class="tbm-stat-value" id="totalSessions">0</span>
|
||
<span class="tbm-stat-label">개</span>
|
||
</span>
|
||
<span class="tbm-stat-item">
|
||
<span class="tbm-stat-label">완료</span>
|
||
<span class="tbm-stat-value success" id="completedSessions">0</span>
|
||
<span class="tbm-stat-label">개</span>
|
||
</span>
|
||
<span class="tbm-stat-item" id="viewModeIndicator" style="display: none;">
|
||
<span class="tbm-stat-value" id="viewModeText">내 TBM만</span>
|
||
</span>
|
||
</div>
|
||
|
||
<div class="tbm-section-body" id="tbmDateGroupsContainer"></div>
|
||
|
||
<div class="tbm-empty-state" id="emptyState" style="display: none;">
|
||
<div class="tbm-empty-icon">📚</div>
|
||
<h3 class="tbm-empty-title">등록된 TBM 세션이 없습니다</h3>
|
||
<p class="tbm-empty-description">TBM 입력 탭에서 새로운 TBM을 시작해보세요.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TBM 생성 모달 -->
|
||
<div id="tbmModal" class="tbm-modal-overlay" style="display: none;">
|
||
<div class="tbm-modal" style="max-width: 800px;">
|
||
<div class="tbm-modal-header">
|
||
<h2 class="tbm-modal-title" id="modalTitle"><span>📝</span> 새 TBM 시작</h2>
|
||
<button class="tbm-modal-close" onclick="closeTbmModal()">×</button>
|
||
</div>
|
||
<div class="tbm-modal-body">
|
||
<form id="tbmForm" onsubmit="event.preventDefault(); saveTbmSession();">
|
||
<input type="hidden" id="sessionId">
|
||
<div class="tbm-form-section">
|
||
<h3 class="tbm-form-section-title"><span>📅</span> 기본 정보</h3>
|
||
<div class="tbm-form-row">
|
||
<div class="tbm-form-group">
|
||
<label class="tbm-form-label">TBM 날짜<span class="tbm-form-required">*</span></label>
|
||
<div class="tbm-form-input-readonly" id="sessionDateDisplay">-</div>
|
||
<input type="hidden" id="sessionDate">
|
||
</div>
|
||
<div class="tbm-form-group">
|
||
<label class="tbm-form-label">입력자<span class="tbm-form-required">*</span></label>
|
||
<div class="tbm-form-input-readonly" id="leaderName">-</div>
|
||
<input type="hidden" id="leaderId">
|
||
</div>
|
||
</div>
|
||
<div class="tbm-form-row">
|
||
<div class="tbm-form-group">
|
||
<label class="tbm-form-label">프로젝트</label>
|
||
<select id="newTbmProjectId" class="tbm-form-input"><option value="">선택 안함</option></select>
|
||
</div>
|
||
<div class="tbm-form-group">
|
||
<label class="tbm-form-label">공정<span class="tbm-form-required">*</span></label>
|
||
<select id="newTbmWorkTypeId" class="tbm-form-input" required><option value="">공정 선택...</option></select>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="tbm-form-section">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
|
||
<h3 class="tbm-form-section-title" style="margin: 0; border: 0; padding: 0;">
|
||
<span>👥</span> 작업자 선택
|
||
<span id="newTbmWorkerCount" style="color: #3b82f6; font-size: 0.875rem;">(0명)</span>
|
||
</h3>
|
||
<div style="display: flex; gap: 0.5rem;">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary tbm-btn-sm" onclick="selectAllNewTbmWorkers()">전체 선택</button>
|
||
<button type="button" class="tbm-btn tbm-btn-secondary tbm-btn-sm" onclick="deselectAllNewTbmWorkers()">전체 해제</button>
|
||
</div>
|
||
</div>
|
||
<div id="newTbmWorkerGrid" class="tbm-worker-select-grid"></div>
|
||
<div class="tbm-alert tbm-alert-info" style="margin-top: 1rem;">
|
||
<span class="tbm-alert-icon">💡</span>
|
||
<div class="tbm-alert-content">
|
||
<div class="tbm-alert-text">저장 후 카드를 클릭하면 작업자별 <strong>작업/작업장</strong>을 입력할 수 있습니다.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- 편집 모드: 작업자별 작업 목록 (openTeamCompositionModal에서 사용) -->
|
||
<div id="workerTaskListSection" class="tbm-form-section" style="display: none;">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
|
||
<h3 class="tbm-form-section-title" style="margin: 0; border: 0; padding: 0;">
|
||
<span>👥</span> 작업자별 작업 배정
|
||
</h3>
|
||
<button type="button" class="tbm-btn tbm-btn-secondary tbm-btn-sm" onclick="openBulkSettingModal()">⚙ 일괄 설정</button>
|
||
</div>
|
||
<div id="workerListEmpty" style="display: none; justify-content: center; align-items: center; padding: 2rem; color: #94a3b8; font-size: 0.875rem;">
|
||
배정된 작업자가 없습니다.
|
||
</div>
|
||
<div id="workerTaskList" style="display: flex; flex-direction: column; gap: 1rem;"></div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<div class="tbm-modal-footer">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary" onclick="closeTbmModal()">취소</button>
|
||
<button type="button" class="tbm-btn tbm-btn-primary" onclick="saveTbmSession()"><span class="tbm-btn-icon">✓</span> 저장하기</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 일괄 설정 모달 -->
|
||
<div id="bulkSettingModal" class="tbm-modal-overlay" style="display: none; z-index: 1101;">
|
||
<div class="tbm-modal" style="max-width: 700px;">
|
||
<div class="tbm-modal-header">
|
||
<h2 class="tbm-modal-title"><span>⚙</span> 일괄 설정</h2>
|
||
<button class="tbm-modal-close" onclick="closeBulkSettingModal()">×</button>
|
||
</div>
|
||
<div class="tbm-modal-body">
|
||
<div class="tbm-alert tbm-alert-info">
|
||
<span class="tbm-alert-icon">💡</span>
|
||
<div class="tbm-alert-content">
|
||
<div class="tbm-alert-title">일괄 설정</div>
|
||
<div class="tbm-alert-text">선택한 작업자들의 <strong>첫 번째 작업 라인</strong>에 동일한 정보가 적용됩니다.</div>
|
||
</div>
|
||
</div>
|
||
<div class="tbm-form-section">
|
||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.75rem;">
|
||
<label class="tbm-form-label">적용할 작업자 선택<span class="tbm-form-required">*</span></label>
|
||
<div style="display: flex; gap: 0.25rem;">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary tbm-btn-sm" onclick="selectAllForBulk()">전체</button>
|
||
<button type="button" class="tbm-btn tbm-btn-secondary tbm-btn-sm" onclick="deselectAllForBulk()">해제</button>
|
||
</div>
|
||
</div>
|
||
<div id="bulkWorkerSelection" class="tbm-worker-select-grid" style="max-height: 180px;"></div>
|
||
</div>
|
||
<div class="tbm-form-section" style="border-top: 1px solid #e2e8f0; padding-top: 1.5rem;">
|
||
<h3 class="tbm-form-section-title" style="border: 0; padding: 0; margin-bottom: 1rem;"><span>🛠</span> 적용할 작업 정보</h3>
|
||
<div class="tbm-form-group">
|
||
<label class="tbm-form-label">프로젝트</label>
|
||
<button type="button" id="bulkProjectBtn" onclick="openBulkItemSelect('project')" class="tbm-select-btn">프로젝트 선택 <span class="tbm-select-arrow">▼</span></button>
|
||
<input type="hidden" id="bulkProjectId">
|
||
</div>
|
||
<div class="tbm-form-row">
|
||
<div class="tbm-form-group">
|
||
<label class="tbm-form-label">공정<span class="tbm-form-required">*</span></label>
|
||
<button type="button" id="bulkWorkTypeBtn" onclick="openBulkItemSelect('workType')" class="tbm-select-btn">공정 선택 <span class="tbm-select-arrow">▼</span></button>
|
||
<input type="hidden" id="bulkWorkTypeId">
|
||
</div>
|
||
<div class="tbm-form-group">
|
||
<label class="tbm-form-label">작업<span class="tbm-form-required">*</span></label>
|
||
<button type="button" id="bulkTaskBtn" onclick="openBulkItemSelect('task')" class="tbm-select-btn" disabled>작업 선택 <span class="tbm-select-arrow">▼</span></button>
|
||
<input type="hidden" id="bulkTaskId">
|
||
</div>
|
||
</div>
|
||
<div class="tbm-form-group">
|
||
<label class="tbm-form-label">작업장<span class="tbm-form-required">*</span></label>
|
||
<button type="button" id="bulkWorkplaceBtn" onclick="openBulkWorkplaceSelect()" class="tbm-select-btn">작업장 선택 <span class="tbm-select-arrow">▼</span></button>
|
||
<input type="hidden" id="bulkWorkplaceCategoryId">
|
||
<input type="hidden" id="bulkWorkplaceId">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="tbm-modal-footer">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary" onclick="closeBulkSettingModal()">취소</button>
|
||
<button type="button" class="tbm-btn tbm-btn-primary" onclick="applyBulkSettings()"><span class="tbm-btn-icon">✓</span> 선택한 작업자에 적용</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 작업자 선택 모달 -->
|
||
<div id="workerSelectionModal" class="tbm-modal-overlay" style="display: none; z-index: 1101;">
|
||
<div class="tbm-modal" style="max-width: 800px;">
|
||
<div class="tbm-modal-header">
|
||
<h2 class="tbm-modal-title"><span>👥</span> 작업자 선택</h2>
|
||
<button class="tbm-modal-close" onclick="closeWorkerSelectionModal()">×</button>
|
||
</div>
|
||
<div class="tbm-modal-body">
|
||
<div style="margin-bottom: 1rem; display: flex; gap: 0.5rem;">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary tbm-btn-sm" onclick="selectAllWorkersInModal()">전체 선택</button>
|
||
<button type="button" class="tbm-btn tbm-btn-secondary tbm-btn-sm" onclick="deselectAllWorkersInModal()">전체 해제</button>
|
||
</div>
|
||
<div id="workerCardGrid" class="tbm-worker-select-grid"></div>
|
||
</div>
|
||
<div class="tbm-modal-footer">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary" onclick="closeWorkerSelectionModal()">취소</button>
|
||
<button type="button" class="tbm-btn tbm-btn-primary" onclick="confirmWorkerSelection()"><span class="tbm-btn-icon">✓</span> 선택 완료</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 항목 선택 모달 -->
|
||
<div id="itemSelectModal" class="tbm-modal-overlay" style="display: none; z-index: 1102;">
|
||
<div class="tbm-modal" style="max-width: 600px;">
|
||
<div class="tbm-modal-header">
|
||
<h2 class="tbm-modal-title" id="itemSelectModalTitle">항목 선택</h2>
|
||
<button class="tbm-modal-close" onclick="closeItemSelectModal()">×</button>
|
||
</div>
|
||
<div class="tbm-modal-body">
|
||
<div id="itemSelectList" class="tbm-item-list"></div>
|
||
</div>
|
||
<div class="tbm-modal-footer">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary" onclick="closeItemSelectModal()">취소</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 작업장 선택 모달 -->
|
||
<div id="workplaceSelectModal" class="tbm-modal-overlay" style="display: none; z-index: 1102;">
|
||
<div class="tbm-modal" style="max-width: 1000px;">
|
||
<div class="tbm-modal-header">
|
||
<h2 class="tbm-modal-title"><span>🏭</span> 작업장 선택</h2>
|
||
<button class="tbm-modal-close" onclick="closeWorkplaceSelectModal()">×</button>
|
||
</div>
|
||
<div class="tbm-modal-body">
|
||
<div class="tbm-form-section">
|
||
<h3 class="tbm-form-section-title">
|
||
<span style="background: #3b82f6; color: white; width: 24px; height: 24px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 0.8rem;">1</span>
|
||
공장 선택
|
||
</h3>
|
||
<div id="categoryList" style="display: flex; flex-wrap: wrap; gap: 0.5rem;"></div>
|
||
</div>
|
||
<div id="workplaceSelectionArea" style="display: none;">
|
||
<div class="tbm-form-section">
|
||
<h3 class="tbm-form-section-title">
|
||
<span style="background: #3b82f6; color: white; width: 24px; height: 24px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 0.8rem;">2</span>
|
||
작업장 선택
|
||
</h3>
|
||
<div id="layoutMapArea" style="display: none; padding: 1rem; background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 10px;">
|
||
<div style="font-size: 0.875rem; color: #64748b; margin-bottom: 0.75rem;">지도에서 작업장을 클릭하여 선택하세요</div>
|
||
<div class="tbm-workplace-map-container">
|
||
<canvas id="workplaceMapCanvas"></canvas>
|
||
</div>
|
||
<button type="button" class="landscape-trigger-btn" id="landscapeTriggerBtn" onclick="openLandscapeMap()" style="display:none;">📺 전체화면 지도</button>
|
||
</div>
|
||
<div style="margin-top: 0.75rem;">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary tbm-btn-sm" onclick="toggleWorkplaceList()" id="toggleListBtn" style="display: none;">리스트로 선택</button>
|
||
<div id="workplaceListSection">
|
||
<div id="workplaceList" class="tbm-item-list">
|
||
<div style="color: #94a3b8; text-align: center; padding: 2rem;">공장을 먼저 선택해주세요</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="tbm-modal-footer">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary" onclick="closeWorkplaceSelectModal()">취소</button>
|
||
<button type="button" class="tbm-btn tbm-btn-primary" onclick="confirmWorkplaceSelection()" id="confirmWorkplaceBtn" disabled><span class="tbm-btn-icon">✓</span> 선택 완료</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 팀 구성 모달 -->
|
||
<div id="teamModal" class="tbm-modal-overlay" style="display: none;">
|
||
<div class="tbm-modal" style="max-width: 900px;">
|
||
<div class="tbm-modal-header">
|
||
<h2 class="tbm-modal-title"><span>👥</span> 팀 구성</h2>
|
||
<button class="tbm-modal-close" onclick="closeTeamModal()">×</button>
|
||
</div>
|
||
<div class="tbm-modal-body">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
|
||
<h3 class="tbm-form-section-title" style="margin: 0; border: 0; padding: 0;">작업자 선택</h3>
|
||
<div style="display: flex; gap: 0.5rem;">
|
||
<button class="tbm-btn tbm-btn-secondary tbm-btn-sm" onclick="selectAllWorkers()">전체 선택</button>
|
||
<button class="tbm-btn tbm-btn-secondary tbm-btn-sm" onclick="deselectAllWorkers()">전체 해제</button>
|
||
</div>
|
||
</div>
|
||
<div id="workerSelectionGrid" class="tbm-worker-select-grid"></div>
|
||
<div style="margin-top: 1.5rem;">
|
||
<h3 class="tbm-form-section-title">선택된 팀원 <span id="selectedCount" style="color: #3b82f6;">0</span>명</h3>
|
||
<div id="selectedWorkersList" style="display: flex; flex-wrap: wrap; gap: 0.5rem; min-height: 50px; padding: 0.75rem; background: #f8fafc; border-radius: 10px; border: 1px solid #e2e8f0;">
|
||
<p style="margin: 0; color: #94a3b8; font-size: 0.875rem;">작업자를 선택해주세요</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="tbm-modal-footer">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary" onclick="closeTeamModal()">취소</button>
|
||
<button type="button" class="tbm-btn tbm-btn-primary" onclick="saveTeamComposition()"><span class="tbm-btn-icon">✓</span> 팀 구성 완료</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 안전 체크리스트 모달 -->
|
||
<div id="safetyModal" class="tbm-modal-overlay" style="display: none;">
|
||
<div class="tbm-modal" style="max-width: 700px;">
|
||
<div class="tbm-modal-header">
|
||
<h2 class="tbm-modal-title"><span>🛡</span> 안전 체크리스트</h2>
|
||
<button class="tbm-modal-close" onclick="closeSafetyModal()">×</button>
|
||
</div>
|
||
<div class="tbm-modal-body">
|
||
<div id="safetyChecklistContainer" class="tbm-safety-list"></div>
|
||
</div>
|
||
<div class="tbm-modal-footer">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary" onclick="closeSafetyModal()">취소</button>
|
||
<button type="button" class="tbm-btn tbm-btn-success" onclick="saveSafetyChecklist()"><span class="tbm-btn-icon">✓</span> 안전 체크 완료</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TBM 완료 모달 -->
|
||
<div id="completeModal" class="tbm-modal-overlay" style="display: none;">
|
||
<div class="tbm-modal" style="max-width: 500px;">
|
||
<div class="tbm-modal-header">
|
||
<h2 class="tbm-modal-title"><span>✓</span> TBM 완료</h2>
|
||
<button class="tbm-modal-close" onclick="closeCompleteModal()">×</button>
|
||
</div>
|
||
<div class="tbm-modal-body">
|
||
<div class="tbm-alert tbm-alert-warning">
|
||
<span class="tbm-alert-icon">⚠</span>
|
||
<div class="tbm-alert-content">
|
||
<div class="tbm-alert-title">TBM 완료 확인</div>
|
||
<div class="tbm-alert-text">완료 후에는 수정할 수 없습니다.</div>
|
||
</div>
|
||
</div>
|
||
<div class="tbm-form-group" style="margin-top: 1.5rem;">
|
||
<label class="tbm-form-label">종료 시간</label>
|
||
<input type="time" id="endTime" class="tbm-form-input">
|
||
</div>
|
||
<div class="tbm-form-group" style="margin-top: 1rem;">
|
||
<label class="tbm-form-label">작업자 근태</label>
|
||
<div id="completeAttendanceList" style="max-height: 300px; overflow-y: auto; border: 1px solid #e5e7eb; border-radius: 0.5rem; padding: 0.5rem;">
|
||
<div style="text-align:center; color:#9ca3af; padding:1rem;">로딩 중...</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="tbm-modal-footer">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary" onclick="closeCompleteModal()">취소</button>
|
||
<button type="button" class="tbm-btn tbm-btn-success" id="completeModalBtn" onclick="completeTbmSession()"><span class="tbm-btn-icon">✓</span> 완료</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 작업 인계 모달 -->
|
||
<div id="handoverModal" class="tbm-modal-overlay" style="display: none;">
|
||
<div class="tbm-modal" style="max-width: 600px;">
|
||
<div class="tbm-modal-header">
|
||
<h2 class="tbm-modal-title"><span>👉</span> 작업 인계</h2>
|
||
<button class="tbm-modal-close" onclick="closeHandoverModal()">×</button>
|
||
</div>
|
||
<div class="tbm-modal-body">
|
||
<form id="handoverForm">
|
||
<input type="hidden" id="handoverSessionId">
|
||
<div class="tbm-form-group">
|
||
<label class="tbm-form-label">인계 사유<span class="tbm-form-required">*</span></label>
|
||
<select id="handoverReason" class="tbm-form-input" 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="tbm-form-group">
|
||
<label class="tbm-form-label">인수자 (다음 팀장)<span class="tbm-form-required">*</span></label>
|
||
<select id="toLeaderId" class="tbm-form-input" required><option value="">인수자 선택...</option></select>
|
||
</div>
|
||
<div class="tbm-form-row">
|
||
<div class="tbm-form-group">
|
||
<label class="tbm-form-label">인계 날짜<span class="tbm-form-required">*</span></label>
|
||
<input type="date" id="handoverDate" class="tbm-form-input" required>
|
||
</div>
|
||
<div class="tbm-form-group">
|
||
<label class="tbm-form-label">인계 시간</label>
|
||
<input type="time" id="handoverTime" class="tbm-form-input">
|
||
</div>
|
||
</div>
|
||
<div class="tbm-form-group">
|
||
<label class="tbm-form-label">인계 내용</label>
|
||
<textarea id="handoverNotes" class="tbm-form-input" rows="4" placeholder="인수자에게 전달할 내용을 입력하세요" style="resize: vertical;"></textarea>
|
||
</div>
|
||
<div class="tbm-form-group">
|
||
<label class="tbm-form-label" style="margin-bottom: 0.75rem;">인계할 팀원 선택</label>
|
||
<div id="handoverTeamList" style="max-height: 200px; overflow-y: auto; border: 1px solid #e2e8f0; border-radius: 10px; padding: 0.75rem; background: #f8fafc;"></div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<div class="tbm-modal-footer">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary" onclick="closeHandoverModal()">취소</button>
|
||
<button type="button" class="tbm-btn tbm-btn-primary" onclick="saveHandover()"><span class="tbm-btn-icon">👉</span> 인계 요청</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TBM 상세보기 모달 -->
|
||
<div id="detailModal" class="tbm-modal-overlay" style="display: none;">
|
||
<div class="tbm-modal" style="max-width: 900px;">
|
||
<div class="tbm-modal-header">
|
||
<h2 class="tbm-modal-title"><span>📋</span> TBM 상세 정보</h2>
|
||
<button class="tbm-modal-close" onclick="closeDetailModal()">×</button>
|
||
</div>
|
||
<div class="tbm-modal-body">
|
||
<div class="tbm-form-section">
|
||
<h3 class="tbm-form-section-title"><span>📅</span> 기본 정보</h3>
|
||
<div id="detailBasicInfo" style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem;"></div>
|
||
</div>
|
||
<div class="tbm-form-section">
|
||
<h3 class="tbm-form-section-title"><span>👥</span> 팀 구성</h3>
|
||
<div id="detailTeamMembers" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 0.75rem;"></div>
|
||
</div>
|
||
<div class="tbm-form-section">
|
||
<h3 class="tbm-form-section-title"><span>🛡</span> 안전 체크리스트</h3>
|
||
<div id="detailSafetyChecks"></div>
|
||
</div>
|
||
</div>
|
||
<div class="tbm-modal-footer" id="detailModalFooter">
|
||
<button type="button" class="tbm-btn tbm-btn-secondary" onclick="closeDetailModal()">닫기</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 가로모드 전체화면 지도 -->
|
||
<div id="landscapeOverlay" class="landscape-overlay" style="display:none;">
|
||
<div id="landscapeInner" class="landscape-inner">
|
||
<div class="landscape-header">
|
||
<h3>🏭 작업장 선택</h3>
|
||
<button type="button" class="landscape-close-btn" onclick="closeLandscapeMap()">×</button>
|
||
</div>
|
||
<div class="landscape-canvas-wrap">
|
||
<canvas id="landscapeCanvas"></canvas>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 분할 모달 -->
|
||
<div id="splitModal" class="tbm-modal-overlay" style="display:none;">
|
||
<div class="tbm-modal-container" style="max-width:500px;">
|
||
<div class="tbm-modal-header"><h2>작업 분할</h2><button type="button" class="tbm-modal-close" onclick="closeSplitModal()">×</button></div>
|
||
<div class="tbm-modal-body">
|
||
<p style="font-size:0.8125rem; color:#6b7280; margin-bottom:0.75rem;">작업자의 배정 시간을 분할합니다.</p>
|
||
<div id="splitMemberList" style="display:flex; flex-direction:column; gap:0.5rem;"></div>
|
||
</div>
|
||
<div class="tbm-modal-footer"><button type="button" class="tbm-btn tbm-btn-secondary" onclick="closeSplitModal()">닫기</button></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 빼오기 모달 -->
|
||
<div id="pullModal" class="tbm-modal-overlay" style="display:none;">
|
||
<div class="tbm-modal-container" style="max-width:500px;">
|
||
<div class="tbm-modal-header"><h2>빼오기</h2><button type="button" class="tbm-modal-close" onclick="closePullModal()">×</button></div>
|
||
<div class="tbm-modal-body">
|
||
<p style="font-size:0.8125rem; color:#6b7280; margin-bottom:0.75rem;">다른 반장의 TBM에서 작업자를 빼옵니다.</p>
|
||
<div id="pullSessionList"></div>
|
||
</div>
|
||
<div class="tbm-modal-footer"><button type="button" class="tbm-btn tbm-btn-secondary" onclick="closePullModal()">닫기</button></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 토스트 -->
|
||
<div class="toast-container" id="toastContainer"></div>
|
||
|
||
<script src="/static/js/tkfb-core.js?v=2026031601"></script>
|
||
<script src="/js/api-base.js?v=2026031602"></script>
|
||
<script src="/js/common/utils.js?v=2026031602"></script>
|
||
<script src="/js/common/base-state.js?v=2026031602"></script>
|
||
<script src="/js/tbm/state.js?v=2026031602"></script>
|
||
<script src="/js/tbm/utils.js?v=2026031602"></script>
|
||
<script src="/js/tbm/api.js?v=2026031602"></script>
|
||
<script defer src="/js/tbm.js?v=2026031602"></script>
|
||
<script>initAuth();</script>
|
||
</body>
|
||
</html>
|