feat: 안전 코드 tksafety 이관 + 사용자 관리 정리 + UI Tailwind 전환

Phase 1: tksafety에 출입신청/체크리스트 API·웹 추가, tkfb 안전 코드 삭제
Phase 2: 사용자 관리 페이지 삭제, API 축소, 알림 수신자 tkuser 이관
Phase 3: tkuser 권한 페이지 정의 업데이트
Phase 4: 전체 34개 페이지 Tailwind CSS + tkfb-core.js 전환,
         미사용 CSS 20개·인프라 JS 10개·템플릿·컴포넌트 삭제

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-03-13 10:46:22 +09:00
parent 8373fe9e75
commit 9fda89a374
133 changed files with 5255 additions and 26181 deletions

View File

@@ -1,286 +0,0 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>관리자 설정 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/common.css?v=1">
<link rel="stylesheet" href="/css/admin-settings.css?v=2">
<link rel="icon" type="image/png" href="/img/favicon.png">
</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">관리자 설정</h1>
<p class="page-description">시스템 사용자 계정 및 권한을 관리합니다</p>
</div>
</div>
<!-- 사용자 관리 섹션 -->
<div class="settings-section">
<div class="section-header">
<h2 class="section-title">사용자 계정 관리</h2>
<button class="btn btn-primary" id="addUserBtn">새 사용자 추가</button>
</div>
<div class="users-container">
<div class="users-header">
<div class="search-box">
<input type="text" id="userSearch" placeholder="사용자 검색..." class="search-input">
<span class="search-icon"></span>
</div>
<div class="filter-buttons">
<button class="filter-btn active" data-filter="all">전체</button>
<button class="filter-btn" data-filter="admin">관리자</button>
<button class="filter-btn" data-filter="leader">그룹장</button>
<button class="filter-btn" data-filter="user">작업자</button>
</div>
</div>
<div class="users-table-container">
<table class="users-table">
<thead>
<tr>
<th>사용자명</th>
<th>아이디</th>
<th>역할</th>
<th>상태</th>
<th>최종 로그인</th>
<th>관리</th>
</tr>
</thead>
<tbody id="usersTableBody">
<!-- 사용자 목록이 여기에 동적으로 생성됩니다 -->
</tbody>
</table>
</div>
<div class="empty-state" id="emptyState" style="display: none;">
<h3>등록된 사용자가 없습니다</h3>
<p>새 사용자를 추가해보세요.</p>
</div>
</div>
</div>
<!-- 알림 수신자 설정 섹션 -->
<div class="settings-section" id="notificationRecipientsSection">
<div class="section-header">
<h2 class="section-title">알림 수신자 설정</h2>
<p class="section-description">알림 유형별 수신자를 지정합니다. 지정된 사용자에게만 알림이 전송됩니다.</p>
</div>
<div class="notification-recipients-container">
<div class="notification-type-cards" id="notificationTypeCards">
<!-- 동적으로 생성됨 -->
</div>
</div>
</div>
</div>
</main>
</div>
<!-- 사용자 추가/수정 모달 -->
<div id="userModal" class="modal-overlay" style="display: none;">
<div class="modal-container">
<div class="modal-header">
<h2 id="modalTitle">새 사용자 추가</h2>
<button class="modal-close-btn" onclick="closeUserModal()">×</button>
</div>
<div class="modal-body">
<form id="userForm">
<div class="form-group">
<label class="form-label">사용자명 *</label>
<input type="text" id="userName" class="form-control" required>
</div>
<div class="form-group">
<label class="form-label">아이디 *</label>
<input type="text" id="userId" class="form-control" required>
<small class="form-help">영문, 숫자, 한글, 특수문자(._-) 사용 가능 (3-20자)</small>
</div>
<div class="form-group" id="passwordGroup">
<label class="form-label">비밀번호 *</label>
<input type="password" id="userPassword" class="form-control" required>
<small class="form-help">최소 6자 이상</small>
</div>
<div class="form-group">
<label class="form-label">역할 *</label>
<select id="userRole" class="form-control" required>
<option value="">역할 선택</option>
<option value="admin">관리자</option>
<option value="user">사용자</option>
</select>
</div>
<div class="form-group">
<label class="form-label">이메일</label>
<input type="email" id="userEmail" class="form-control">
</div>
<div class="form-group">
<label class="form-label">전화번호</label>
<input type="tel" id="userPhone" class="form-control">
</div>
<!-- 작업자 연결 (수정 시에만 표시) -->
<div class="form-group" id="workerLinkGroup" style="display: none;">
<label class="form-label">작업자 연결</label>
<div class="worker-link-container">
<div class="linked-worker-info" id="linkedWorkerInfo">
<span class="no-worker">연결된 작업자 없음</span>
</div>
<button type="button" class="btn btn-secondary btn-sm" onclick="openWorkerSelectModal()">
작업자 선택
</button>
</div>
<small class="form-help">계정과 작업자를 연결하면 출퇴근, 작업보고서 등의 기록이 연동됩니다</small>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeUserModal()">취소</button>
<button type="button" class="btn btn-primary" id="saveUserBtn">저장</button>
</div>
</div>
</div>
<!-- 사용자 삭제 확인 모달 -->
<div id="deleteModal" class="modal-overlay" style="display: none;">
<div class="modal-container small">
<div class="modal-header">
<h2>사용자 삭제</h2>
<button class="modal-close-btn" onclick="closeDeleteModal()">×</button>
</div>
<div class="modal-body">
<div class="delete-warning">
<div class="warning-icon"></div>
<p>정말로 이 사용자를 삭제하시겠습니까?</p>
<p class="warning-text">삭제된 사용자는 복구할 수 없습니다.</p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeDeleteModal()">취소</button>
<button type="button" class="btn btn-danger" id="confirmDeleteBtn">삭제</button>
</div>
</div>
</div>
<!-- 페이지 권한 관리 모달 -->
<div id="pageAccessModal" class="modal-overlay" style="display: none;">
<div class="modal-container">
<div class="modal-header">
<h2 id="pageAccessModalTitle">페이지 권한 관리</h2>
<button class="modal-close-btn" onclick="closePageAccessModal()">×</button>
</div>
<div class="modal-body">
<div class="page-access-user-info">
<div class="user-avatar-small" id="pageAccessUserAvatar">U</div>
<div>
<h3 id="pageAccessUserName">사용자</h3>
<p id="pageAccessUserRole">역할</p>
</div>
</div>
<div class="form-group">
<label class="form-label">접근 가능한 페이지</label>
<small class="form-help">체크된 페이지에만 접근할 수 있습니다</small>
<div id="pageAccessModalList" class="page-access-list">
<!-- 페이지 체크박스 목록 -->
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closePageAccessModal()">취소</button>
<button type="button" class="btn btn-primary" id="savePageAccessBtn">저장</button>
</div>
</div>
</div>
<!-- 작업자 선택 모달 -->
<div id="workerSelectModal" class="modal-overlay" style="display: none;">
<div class="modal-container">
<div class="modal-header">
<h2>작업자 선택</h2>
<button class="modal-close-btn" onclick="closeWorkerSelectModal()">×</button>
</div>
<div class="modal-body">
<div class="worker-select-layout">
<!-- 부서 목록 -->
<div class="department-list-panel">
<h3 class="panel-title">부서</h3>
<div class="department-list" id="departmentList">
<!-- 부서 목록이 동적으로 생성됩니다 -->
</div>
</div>
<!-- 작업자 목록 -->
<div class="worker-list-panel">
<h3 class="panel-title">작업자</h3>
<div class="worker-list" id="workerListForSelect">
<div class="empty-message">부서를 선택하세요</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeWorkerSelectModal()">취소</button>
<button type="button" class="btn btn-danger" onclick="unlinkWorker()">연결 해제</button>
</div>
</div>
</div>
<!-- 알림 수신자 편집 모달 -->
<div id="notificationRecipientModal" class="modal-overlay" style="display: none;">
<div class="modal-container">
<div class="modal-header">
<h2 id="recipientModalTitle">알림 수신자 설정</h2>
<button class="modal-close-btn" onclick="closeRecipientModal()">×</button>
</div>
<div class="modal-body">
<p class="modal-description" id="recipientModalDesc">이 알림을 받을 사용자를 선택하세요.</p>
<div class="recipient-search-box">
<input type="text" id="recipientSearchInput" placeholder="사용자 검색..." class="form-control">
</div>
<div class="recipient-user-list" id="recipientUserList">
<!-- 사용자 체크박스 목록 -->
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeRecipientModal()">취소</button>
<button type="button" class="btn btn-primary" onclick="saveNotificationRecipients()">저장</button>
</div>
</div>
</div>
<!-- 토스트 알림 -->
<div class="toast-container" id="toastContainer"></div>
<!-- JavaScript -->
<script src="/js/api-base.js?v=3"></script>
<script src="/js/app-init.js?v=9" defer></script>
<script src="https://instant.page/5.2.0" type="module"></script>
<script src="/js/admin-settings.js?v=9"></script>
</body>
</html>

View File

@@ -3,13 +3,10 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>출퇴근-작업보고서 대조 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/admin-pages.css?v=8">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/api-base.js?v=3"></script>
<script src="/js/app-init.js?v=9" defer></script>
<script src="https://instant.page/5.2.0" type="module"></script>
<title>출퇴근-작업보고서 대조 - 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">
<style>
.comparison-grid {
display: grid;
@@ -98,13 +95,28 @@
}
</style>
</head>
<body>
<!-- 네비게이션 바 -->
<div id="navbar-container"></div>
<!-- 메인 콘텐츠 -->
<main class="main-content">
<div class="dashboard-main">
<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>
<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">
<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="page-header">
<div class="page-title-section">
<h1 class="page-title">출퇴근-작업보고서 대조</h1>
@@ -174,9 +186,12 @@
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<script src="/static/js/tkfb-core.js"></script>
<script src="/js/api-base.js?v=3"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="module">
import '/js/api-config.js?v=3';
@@ -482,5 +497,6 @@
container.innerHTML = tableHTML;
}
</script>
<script>initAuth();</script>
</body>
</html>

View File

@@ -3,13 +3,10 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>부서 관리 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/admin-pages.css?v=8">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/api-base.js?v=3"></script>
<script src="/js/app-init.js?v=9" defer></script>
<script src="https://instant.page/5.2.0" type="module"></script>
<title>부서 관리 - 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">
<style>
.department-grid {
display: grid;
@@ -215,12 +212,28 @@
}
</style>
</head>
<body>
<div id="navbar-container"></div>
<div class="page-container">
<main class="main-content">
<div class="dashboard-main">
<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>
<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">
<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="page-header">
<div class="page-title-section">
<h1 class="page-title">부서 관리</h1>
@@ -266,9 +279,9 @@
</div>
</div>
</div>
</div>
</main>
</div>
</div>
</div>
</div>
<!-- 부서 등록/수정 모달 -->
<div class="modal-backdrop" id="departmentModal">
@@ -311,6 +324,9 @@
</div>
</div>
<script src="/static/js/tkfb-core.js"></script>
<script src="/js/api-base.js?v=3"></script>
<script src="/js/department-management.js"></script>
<script>initAuth();</script>
</body>
</html>

View File

@@ -3,23 +3,34 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>설비 상세 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/admin-pages.css?v=8">
<title>설비 상세 - 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">
<link rel="stylesheet" href="/css/equipment-detail.css?v=1">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/api-base.js?v=3"></script>
<script src="/js/app-init.js?v=9" defer></script>
</head>
<body>
<!-- 네비게이션 바 -->
<div id="navbar-container"></div>
<!-- 메인 레이아웃 -->
<div class="page-container">
<!-- 메인 콘텐츠 -->
<main class="main-content">
<div class="dashboard-main">
<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>
<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">
<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="page-header eq-detail-header">
<div class="page-title-section">
@@ -118,9 +129,9 @@
<div class="eq-history-empty">이동 이력이 없습니다</div>
</div>
</div>
</div>
</main>
</div>
</div>
</div>
</div>
<!-- 사진 추가 모달 -->
<div id="photoModal" class="modal-overlay" style="display: none;">
@@ -303,6 +314,8 @@
</div>
</div>
<script src="/static/js/tkfb-core.js"></script>
<script src="/js/api-base.js?v=3"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="module">
import '/js/api-config.js?v=3';
@@ -340,5 +353,6 @@
})();
</script>
<script src="/js/equipment-detail.js?v=1"></script>
<script>initAuth();</script>
</body>
</html>

View File

@@ -3,23 +3,34 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>설비 관리 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/admin-pages.css?v=8">
<title>설비 관리 - 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">
<link rel="stylesheet" href="/css/equipment-management.css?v=1">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/api-base.js?v=3"></script>
<script src="/js/app-init.js?v=9" defer></script>
</head>
<body>
<!-- 네비게이션 바 -->
<div id="navbar-container"></div>
<!-- 메인 레이아웃 -->
<div class="page-container">
<!-- 메인 콘텐츠 -->
<main class="main-content">
<div class="dashboard-main">
<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>
<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">
<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="page-header">
<div class="page-title-section">
<h1 class="page-title">설비 관리</h1>
@@ -71,9 +82,9 @@
<div id="equipmentList" class="eq-table-container">
<!-- 설비 목록이 여기에 동적으로 렌더링됩니다 -->
</div>
</div>
</main>
</div>
</div>
</div>
</div>
<!-- 설비 추가/수정 모달 -->
<div id="equipmentModal" class="modal-overlay" style="display: none;">
@@ -179,6 +190,8 @@
</div>
</div>
<script src="/static/js/tkfb-core.js"></script>
<script src="/js/api-base.js?v=3"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="module">
import '/js/api-config.js?v=3';
@@ -216,5 +229,6 @@
})();
</script>
<script src="/js/equipment-management.js?v=8"></script>
<script>initAuth();</script>
</body>
</html>

View File

@@ -3,13 +3,10 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>신고 카테고리 관리 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/admin-pages.css?v=8">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/api-base.js?v=3"></script>
<script src="/js/app-init.js?v=9" defer></script>
<script src="https://instant.page/5.2.0" type="module"></script>
<title>신고 카테고리 관리 - 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">
<style>
.type-tabs {
display: flex;
@@ -211,12 +208,28 @@
}
</style>
</head>
<body>
<div id="navbar-container"></div>
<div class="page-container">
<main class="main-content">
<div class="dashboard-main">
<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>
<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">
<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="page-header">
<div class="page-title-section">
<h1 class="page-title">신고 카테고리 관리</h1>
@@ -237,9 +250,9 @@
<div id="categoryList">
<div class="empty-state">카테고리를 불러오는 중...</div>
</div>
</div>
</main>
</div>
</div>
</div>
</div>
<!-- 카테고리 추가/수정 모달 -->
<div id="categoryModal" class="modal-overlay" style="display: none;">
@@ -316,6 +329,9 @@
</div>
</div>
<script src="/static/js/tkfb-core.js"></script>
<script src="/js/api-base.js?v=3"></script>
<script type="module" src="/js/issue-category-manage.js"></script>
<script>initAuth();</script>
</body>
</html>

View File

@@ -3,18 +3,14 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>알림 관리 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/admin-pages.css?v=8">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/api-base.js?v=3"></script>
<script src="/js/app-init.js?v=9" defer></script>
<script src="https://instant.page/5.2.0" type="module"></script>
<title>알림 관리 - 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">
<style>
.notification-page-container {
max-width: 1000px;
margin: 0 auto;
padding: 1.5rem;
}
.notification-header {
@@ -308,11 +304,28 @@
}
</style>
</head>
<body>
<div id="navbar-placeholder"></div>
<div id="sidebar-placeholder"></div>
<main class="main-content">
<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>
<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">
<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="notification-page-container">
<div class="notification-header">
<h1>알림 관리</h1>
@@ -358,9 +371,12 @@
</div>
</div>
</div>
</main>
</div>
</div>
</div>
<script src="/js/load-sidebar.js"></script>
<script src="/static/js/tkfb-core.js"></script>
<script src="/js/api-base.js?v=3"></script>
<script>
let currentPage = 1;
let totalPages = 1;
@@ -550,5 +566,6 @@
}
}
</script>
<script>initAuth();</script>
</body>
</html>

View File

@@ -3,13 +3,12 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>프로젝트 관리 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/admin-pages.css?v=8">
<link rel="icon" type="image/png" href="/img/favicon.png">
<title>프로젝트 관리 - 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">
<style>
.page-wrapper {
padding: 1rem 1.5rem;
max-width: 1600px;
}
.page-header {
@@ -226,11 +225,28 @@
}
</style>
</head>
<body class="has-sidebar">
<div id="navbar-container"></div>
<div id="sidebar-container"></div>
<main class="main-content">
<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>
<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">
<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="page-wrapper">
<div class="page-header">
<h1 class="page-title">프로젝트 관리</h1>
@@ -280,7 +296,9 @@
</table>
</div>
</div>
</main>
</div>
</div>
</div>
<!-- 프로젝트 모달 -->
<div id="projectModal" class="modal-overlay" style="display: none;">
@@ -366,8 +384,8 @@
</div>
</div>
<script src="/static/js/tkfb-core.js"></script>
<script src="/js/api-base.js?v=3"></script>
<script src="/js/app-init.js?v=9" defer></script>
<script>
let allProjects = [];
let filteredProjects = [];
@@ -683,5 +701,6 @@
window.refreshProjectList = refreshProjectList;
window.filterByStatus = filterByStatus;
</script>
<script>initAuth();</script>
</body>
</html>

View File

@@ -3,17 +3,14 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>시설설비 관리 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/admin-pages.css?v=8">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/api-base.js?v=3"></script>
<script src="/js/app-init.js?v=9" defer></script>
<title>시설설비 관리 - 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">
<style>
.repair-page {
max-width: 1400px;
margin: 0 auto;
padding: 1.5rem;
}
.page-header {
@@ -358,11 +355,28 @@
}
</style>
</head>
<body>
<div id="navbar-container"></div>
<div id="sidebar-container"></div>
<main class="main-content">
<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>
<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">
<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="repair-page">
<div class="page-header">
<h1>시설설비 관리</h1>
@@ -408,7 +422,9 @@
</table>
</div>
</div>
</main>
</div>
</div>
</div>
<!-- 접수 모달 -->
<div class="modal-overlay" id="receiveModal">
@@ -471,6 +487,8 @@
</div>
</div>
<script src="/static/js/tkfb-core.js"></script>
<script src="/js/api-base.js?v=3"></script>
<script>
let currentReportId = null;
let allRepairs = [];
@@ -848,5 +866,6 @@
});
});
</script>
<script>initAuth();</script>
</body>
</html>

View File

@@ -3,14 +3,12 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>작업 관리 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/admin-pages.css?v=8">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/api-base.js?v=3"></script>
<script src="/js/app-init.js?v=9" defer></script>
<title>작업 관리 - 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">
<style>
.page-wrapper { padding: 1rem 1.5rem; max-width: 1400px; }
.page-wrapper { max-width: 1400px; }
.page-header {
display: flex; justify-content: space-between; align-items: center;
margin-bottom: 1rem;
@@ -140,11 +138,28 @@
.form-hint { font-size: 0.7rem; color: #6b7280; margin-top: 0.25rem; }
</style>
</head>
<body class="has-sidebar">
<div id="navbar-container"></div>
<div id="sidebar-container"></div>
<main class="main-content">
<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>
<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">
<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="page-wrapper">
<div class="page-header">
<h1 class="page-title">작업 관리</h1>
@@ -193,7 +208,9 @@
</div>
</div>
</div>
</main>
</div>
</div>
</div>
<!-- 작업 모달 -->
<div id="taskModal" class="modal-overlay" style="display:none;">
@@ -268,6 +285,8 @@
</div>
</div>
<script src="/static/js/tkfb-core.js"></script>
<script src="/js/api-base.js?v=3"></script>
<script>
let workTypes = [];
let tasks = [];
@@ -592,5 +611,6 @@
window.deleteWorkType = deleteWorkType;
window.refreshData = refreshData;
</script>
<script>initAuth();</script>
</body>
</html>

View File

@@ -1,495 +0,0 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>작업자 관리 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/admin-pages.css?v=8">
<link rel="icon" type="image/png" href="/img/favicon.png">
<!-- 최적화된 로딩: API 설정 → 앱 초기화 (병렬 컴포넌트 로딩) -->
<script src="/js/api-base.js?v=3"></script>
<script src="/js/app-init.js?v=9" defer></script>
<!-- instant.page: 링크 호버 시 페이지 프리로딩 -->
<script src="https://instant.page/5.2.0" type="module"></script>
<style>
.department-layout {
display: grid;
grid-template-columns: 280px 1fr;
gap: 1.5rem;
min-height: calc(100vh - 200px);
}
/* 부서 패널 */
.department-panel {
background: white;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
display: flex;
flex-direction: column;
}
.department-panel-header {
padding: 1rem 1.25rem;
border-bottom: 1px solid #e5e7eb;
display: flex;
justify-content: space-between;
align-items: center;
}
.department-panel-header h3 {
margin: 0;
font-size: 1rem;
font-weight: 600;
color: #1f2937;
}
.department-list {
flex: 1;
overflow-y: auto;
padding: 0.5rem;
}
.department-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.75rem 1rem;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s;
margin-bottom: 0.25rem;
}
.department-item:hover {
background: #f3f4f6;
}
.department-item.active {
background: #dbeafe;
border-left: 3px solid #3b82f6;
}
.department-info {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.department-name {
font-weight: 500;
color: #1f2937;
}
.department-count {
font-size: 0.75rem;
color: #6b7280;
}
.department-actions {
display: flex;
gap: 0.25rem;
opacity: 0;
transition: opacity 0.2s;
}
.department-item:hover .department-actions {
opacity: 1;
}
.btn-icon {
padding: 0.375rem;
border: none;
background: transparent;
border-radius: 4px;
cursor: pointer;
color: #6b7280;
transition: all 0.2s;
}
.btn-icon:hover {
background: #e5e7eb;
color: #1f2937;
}
.btn-icon.danger:hover {
background: #fee2e2;
color: #dc2626;
}
/* 작업자 패널 */
.worker-panel {
background: white;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
display: flex;
flex-direction: column;
}
.worker-panel-header {
padding: 1rem 1.25rem;
border-bottom: 1px solid #e5e7eb;
display: flex;
justify-content: space-between;
align-items: center;
}
.worker-panel-header h3 {
margin: 0;
font-size: 1rem;
font-weight: 600;
color: #1f2937;
}
.worker-toolbar {
padding: 1rem 1.25rem;
border-bottom: 1px solid #e5e7eb;
display: flex;
gap: 1rem;
align-items: center;
flex-wrap: wrap;
}
.worker-toolbar .search-input {
flex: 1;
min-width: 200px;
padding: 0.5rem 1rem;
border: 1px solid #d1d5db;
border-radius: 6px;
font-size: 0.875rem;
}
.worker-toolbar .filter-select {
padding: 0.5rem 1rem;
border: 1px solid #d1d5db;
border-radius: 6px;
font-size: 0.875rem;
background: white;
}
.worker-list {
flex: 1;
overflow-y: auto;
padding: 1rem;
}
/* 작업자 테이블 스타일 */
.workers-table {
width: 100%;
border-collapse: collapse;
}
.workers-table th,
.workers-table td {
padding: 0.75rem 1rem;
text-align: left;
border-bottom: 1px solid #e5e7eb;
}
.workers-table th {
background: #f9fafb;
font-weight: 600;
font-size: 0.75rem;
text-transform: uppercase;
color: #6b7280;
}
.workers-table tr:hover {
background: #f9fafb;
}
.worker-name-cell {
display: flex;
align-items: center;
gap: 0.75rem;
}
.worker-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: linear-gradient(135deg, #3b82f6, #1d4ed8);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 0.875rem;
}
.status-badge {
display: inline-flex;
align-items: center;
padding: 0.25rem 0.5rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
}
.status-badge.active {
background: #dcfce7;
color: #166534;
}
.status-badge.inactive {
background: #f3f4f6;
color: #6b7280;
}
.status-badge.resigned {
background: #fee2e2;
color: #dc2626;
}
.account-badge {
display: inline-flex;
align-items: center;
gap: 0.25rem;
padding: 0.25rem 0.5rem;
border-radius: 4px;
font-size: 0.75rem;
}
.account-badge.has-account {
background: #dbeafe;
color: #1d4ed8;
}
.account-badge.no-account {
background: #f3f4f6;
color: #9ca3af;
}
/* 빈 상태 */
.empty-state {
text-align: center;
padding: 3rem;
color: #6b7280;
}
.empty-state h4 {
margin: 0 0 0.5rem 0;
color: #374151;
}
/* 반응형 */
@media (max-width: 1024px) {
.department-layout {
grid-template-columns: 1fr;
}
.department-panel {
max-height: 300px;
}
}
/* 부서 모달 스타일 */
.form-check {
display: flex;
align-items: center;
gap: 0.5rem;
}
.form-check input[type="checkbox"] {
width: 1rem;
height: 1rem;
}
</style>
</head>
<body>
<!-- 네비게이션 바 -->
<div id="navbar-container"></div>
<!-- 메인 레이아웃 -->
<div class="page-container">
<main class="main-content">
<div class="dashboard-main">
<div class="page-header">
<div class="page-title-section">
<h1 class="page-title">작업자 관리</h1>
<p class="page-description">부서별 작업자를 관리합니다. 부서를 선택하면 해당 부서의 작업자를 확인하고 관리할 수 있습니다.</p>
</div>
</div>
<!-- 부서 기반 레이아웃 -->
<div class="department-layout">
<!-- 왼쪽: 부서 목록 -->
<div class="department-panel">
<div class="department-panel-header">
<h3>부서 목록</h3>
<button class="btn btn-sm btn-primary" onclick="openDepartmentModal()">+ 부서 추가</button>
</div>
<div class="department-list" id="departmentList">
<!-- 부서 목록이 여기에 렌더링됩니다 -->
</div>
</div>
<!-- 오른쪽: 작업자 목록 -->
<div class="worker-panel">
<div class="worker-panel-header">
<h3 id="workerListTitle">부서를 선택하세요</h3>
<button class="btn btn-sm btn-primary" id="addWorkerBtn" onclick="openWorkerModal()" style="display: none;">+ 작업자 추가</button>
</div>
<div class="worker-toolbar" id="workerToolbar" style="display: none;">
<input type="text" class="search-input" id="workerSearch" placeholder="작업자 검색..." oninput="filterWorkers()">
<select class="filter-select" id="statusFilter" onchange="filterWorkers()">
<option value="">모든 상태</option>
<option value="active">활성</option>
<option value="inactive">비활성</option>
<option value="resigned">퇴사</option>
</select>
</div>
<div class="worker-list" id="workerList">
<div class="empty-state">
<h4>부서를 선택해주세요</h4>
<p>왼쪽에서 부서를 선택하면 해당 부서의 작업자가 표시됩니다.</p>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
<!-- 부서 추가/수정 모달 -->
<div id="departmentModal" class="modal-overlay" style="display: none;">
<div class="modal-container" style="max-width: 500px;">
<div class="modal-header">
<h2 id="departmentModalTitle">새 부서 등록</h2>
<button class="modal-close-btn" onclick="closeDepartmentModal()">×</button>
</div>
<div class="modal-body">
<form id="departmentForm" onsubmit="event.preventDefault(); saveDepartment();">
<input type="hidden" id="departmentId">
<div class="form-group">
<label class="form-label">부서명 *</label>
<input type="text" id="departmentName" class="form-control" placeholder="예: 생산팀, 품질관리팀" required>
</div>
<div class="form-group">
<label class="form-label">상위 부서</label>
<select id="parentDepartment" class="form-control">
<option value="">없음 (최상위 부서)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">설명</label>
<textarea id="departmentDescription" class="form-control" rows="2" placeholder="부서에 대한 설명"></textarea>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">표시 순서</label>
<input type="number" id="displayOrder" class="form-control" value="0" min="0">
</div>
<div class="form-group">
<label class="form-label">&nbsp;</label>
<div class="form-check">
<input type="checkbox" id="isActiveDept" checked>
<label for="isActiveDept">활성화</label>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeDepartmentModal()">취소</button>
<button type="button" class="btn btn-danger" id="deleteDeptBtn" onclick="deleteDepartment()" style="display: none;">삭제</button>
<button type="button" class="btn btn-primary" onclick="saveDepartment()">저장</button>
</div>
</div>
</div>
<!-- 작업자 추가/수정 모달 -->
<div id="workerModal" class="modal-overlay" style="display: none;">
<div class="modal-container">
<div class="modal-header">
<h2 id="workerModalTitle">새 작업자 등록</h2>
<button class="modal-close-btn" onclick="closeWorkerModal()">×</button>
</div>
<div class="modal-body">
<form id="workerForm" onsubmit="event.preventDefault(); saveWorker();">
<input type="hidden" id="workerId">
<div class="form-row">
<div class="form-group">
<label class="form-label">작업자명 *</label>
<input type="text" id="workerName" class="form-control" placeholder="작업자 이름을 입력하세요" required>
</div>
<div class="form-group">
<label class="form-label">직책</label>
<select id="jobType" class="form-control">
<option value="worker">작업자</option>
<option value="leader">그룹장</option>
<option value="admin">관리자</option>
</select>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">입사일</label>
<input type="date" id="joinDate" class="form-control">
</div>
<div class="form-group">
<label class="form-label">급여</label>
<input type="number" id="salary" class="form-control" placeholder="월급여">
</div>
</div>
<div class="form-group">
<label class="form-label">연차</label>
<input type="number" id="annualLeave" class="form-control" placeholder="연차 일수" value="0">
</div>
<!-- 상태 관리 섹션 -->
<div class="form-group">
<label class="form-label" style="font-weight: 600; margin-bottom: 0.75rem; display: block;">상태 관리</label>
<div style="display: flex; flex-direction: column; gap: 0.75rem;">
<!-- 계정 생성/연동 -->
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="checkbox" id="createAccount" style="margin: 0; cursor: pointer;">
<span>계정 생성/연동</span>
</label>
<small style="color: #6b7280; font-size: 0.75rem; margin-top: -0.5rem; margin-left: 1.5rem;">
체크 시 로그인 계정이 자동 생성됩니다 (ID: 이름 로마자 변환, 초기 비밀번호: 1234)
</small>
<!-- 현장직/사무직 구분 -->
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="checkbox" id="isActiveWorker" checked style="margin: 0; cursor: pointer;">
<span>현장직 (활성화)</span>
</label>
<small style="color: #6b7280; font-size: 0.75rem; margin-top: -0.5rem; margin-left: 1.5rem;">
체크: 현장직 (TBM, 작업보고서에 표시) / 체크 해제: 사무직
</small>
<!-- 퇴사 처리 -->
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="checkbox" id="isResigned" style="margin: 0; cursor: pointer;">
<span style="color: #ef4444;">퇴사 처리</span>
</label>
<small style="color: #ef4444; font-size: 0.75rem; margin-top: -0.5rem; margin-left: 1.5rem;">
퇴사한 작업자로 표시됩니다. TBM/작업 보고서에서 제외됩니다
</small>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeWorkerModal()">취소</button>
<button type="button" class="btn btn-danger" id="deleteWorkerBtn" onclick="deleteWorker()" style="display: none;">삭제</button>
<button type="button" class="btn btn-primary" onclick="saveWorker()">저장</button>
</div>
</div>
</div>
<!-- worker-management.js만 로드 (navbar/sidebar는 app-init.js에서 처리) -->
<script type="module" src="/js/worker-management.js?v=8"></script>
</body>
</html>

View File

@@ -3,22 +3,34 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>작업장 관리 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/admin-pages.css?v=8">
<title>작업장 관리 - 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">
<link rel="stylesheet" href="/css/workplace-management.css?v=7">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/api-base.js?v=3"></script>
<script src="/js/app-init.js?v=9" defer></script>
<script src="https://instant.page/5.2.0" type="module"></script>
</head>
<body>
<!-- 네비게이션 바 -->
<div id="navbar-container"></div>
<!-- 메인 레이아웃 (기존 admin 레이아웃과 호환) -->
<div class="page-container">
<main class="main-content">
<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>
<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">
<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="wp-content">
<!-- 페이지 헤더 -->
<div class="wp-page-header">
@@ -128,8 +140,9 @@
</div>
</div>
</div>
</main>
</div>
</div>
</div>
</div>
<!-- 공장(카테고리) 추가/수정 모달 -->
<div id="categoryModal" class="wp-modal-overlay" style="display: none;">
@@ -418,6 +431,8 @@
</div>
<!-- 작업장 관리 모듈 (리팩토링된 구조) -->
<script src="/static/js/tkfb-core.js"></script>
<script src="/js/api-base.js?v=3"></script>
<script src="/js/workplace-management/state.js?v=1"></script>
<script src="/js/workplace-management/utils.js?v=1"></script>
<script src="/js/workplace-management/api.js?v=1"></script>
@@ -425,5 +440,6 @@
<!-- 기존 UI 로직 (점진적 마이그레이션) -->
<script type="module" src="/js/workplace-management.js?v=9"></script>
<script type="module" src="/js/workplace-layout-map.js?v=2"></script>
<script>initAuth();</script>
</body>
</html>