tkfb-core.js v=2026040104, tksupport/tksafety/tkpurchase/tkuser-core.js, system2 api-base.js, system3 app.js 캐시 버스팅 일괄 갱신. 브라우저 캐시에 남은 구버전(tkds 리다이렉트) 강제 갱신. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2443 lines
167 KiB
HTML
2443 lines
167 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ko">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>통합 관리 - TK Factory Services</title>
|
|
<link rel="preload" href="https://cdn.tailwindcss.com" as="script">
|
|
<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/tkuser.css?v=2026031401">
|
|
</head>
|
|
<body>
|
|
<!-- Header -->
|
|
<header class="bg-slate-800 text-white sticky top-0 z-50">
|
|
<div id="headerInner" 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">
|
|
<i class="fas fa-cogs text-xl text-slate-300"></i>
|
|
<h1 class="text-lg font-semibold">TK 통합 관리</h1>
|
|
</div>
|
|
<div class="flex items-center gap-4">
|
|
<div class="text-right hidden sm:block">
|
|
<div id="headerUserName" class="text-sm font-medium truncate max-w-[200px]">-</div>
|
|
<div id="headerUserRole" class="text-xs text-slate-400">-</div>
|
|
</div>
|
|
<div id="headerUserAvatar" class="w-8 h-8 bg-slate-600 rounded-full flex items-center justify-center text-sm font-semibold flex-shrink-0">-</div>
|
|
<button onclick="doLogout()" class="text-slate-400 hover:text-white flex-shrink-0" title="로그아웃"><i class="fas fa-sign-out-alt"></i></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Tab Navigation -->
|
|
<nav id="tabNav" class="bg-white border-b shadow-sm sticky top-14 z-40 hidden">
|
|
<div id="tabNavInner" class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div class="flex gap-1 py-2 overflow-x-auto items-center">
|
|
<!-- 인력 관리 -->
|
|
<span class="tab-group-label">인력</span>
|
|
<button class="tab-btn active px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="users" onclick="switchTab('users', event)">
|
|
<i class="fas fa-users mr-2"></i>사용자
|
|
</button>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="workers" onclick="switchTab('workers', event)">
|
|
<i class="fas fa-hard-hat mr-2"></i>작업자
|
|
</button>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="departments" onclick="switchTab('departments', event)">
|
|
<i class="fas fa-sitemap mr-2"></i>부서
|
|
</button>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="permissions" onclick="switchTab('permissions', event)">
|
|
<i class="fas fa-shield-alt mr-2"></i>권한
|
|
</button>
|
|
<span class="tab-divider"></span>
|
|
<!-- 현장 관리 -->
|
|
<span class="tab-group-label">현장</span>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="projects" onclick="switchTab('projects', event)">
|
|
<i class="fas fa-folder-open mr-2"></i>프로젝트
|
|
</button>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="workplaces" onclick="switchTab('workplaces', event)">
|
|
<i class="fas fa-building mr-2"></i>작업장
|
|
</button>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="equipments" onclick="switchTab('equipments', event)">
|
|
<i class="fas fa-cogs mr-2"></i>설비
|
|
</button>
|
|
<span class="tab-divider"></span>
|
|
<!-- 업무 설정 -->
|
|
<span class="tab-group-label">업무</span>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="tasks" onclick="switchTab('tasks', event)">
|
|
<i class="fas fa-tasks mr-2"></i>작업
|
|
</button>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="issueTypes" onclick="switchTab('issueTypes', event)">
|
|
<i class="fas fa-exclamation-triangle mr-2"></i>이슈 유형
|
|
</button>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="vacations" onclick="switchTab('vacations', event)">
|
|
<i class="fas fa-umbrella-beach mr-2"></i>휴가
|
|
</button>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="vacationSettings" onclick="switchTab('vacationSettings', event)">
|
|
<i class="fas fa-sliders mr-2"></i>연차 설정
|
|
</button>
|
|
<span class="tab-divider"></span>
|
|
<!-- 거래/물품 -->
|
|
<span class="tab-group-label">거래</span>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="partners" onclick="switchTab('partners', event)">
|
|
<i class="fas fa-truck mr-2"></i>협력업체
|
|
</button>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="vendors" onclick="switchTab('vendors', event)">
|
|
<i class="fas fa-store mr-2"></i>업체
|
|
</button>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="consumables" onclick="switchTab('consumables', event)">
|
|
<i class="fas fa-box-open mr-2"></i>소모품
|
|
</button>
|
|
<span class="tab-divider"></span>
|
|
<!-- 시스템 -->
|
|
<span class="tab-group-label">시스템</span>
|
|
<button class="tab-btn px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap" data-tab="notificationRecipients" onclick="switchTab('notificationRecipients', event)">
|
|
<i class="fas fa-bell mr-2"></i>알림 수신자
|
|
</button>
|
|
</div>
|
|
<div class="tab-scroll-hint lg:hidden"></div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Main Content -->
|
|
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6 fade-in">
|
|
|
|
<!-- ============ 사용자 탭 ============ -->
|
|
<div id="tab-users">
|
|
<!-- 사용자 추가 + 목록 -->
|
|
<div id="adminSection" class="hidden">
|
|
<div class="grid lg:grid-cols-5 gap-6">
|
|
<!-- 사용자 추가 (좁게) -->
|
|
<div class="lg:col-span-2 bg-white rounded-xl shadow-sm p-5">
|
|
<h2 class="text-base font-semibold text-gray-800 mb-4"><i class="fas fa-user-plus text-slate-400 mr-2"></i>사용자 추가</h2>
|
|
<form id="addUserForm" class="space-y-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">사용자 ID</label>
|
|
<input type="text" id="newUsername" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="예: 홍길동" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">이름</label>
|
|
<input type="text" id="newFullName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="실명" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">비밀번호</label>
|
|
<input type="password" id="newPassword" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="초기 비밀번호" required>
|
|
</div>
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">부서</label>
|
|
<select id="newDepartmentId" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">권한</label>
|
|
<select id="newRole" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="user">사용자</option>
|
|
<option value="admin">관리자</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">입사일</label>
|
|
<input type="date" id="newHireDate" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<button type="submit" class="w-full px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium">
|
|
<i class="fas fa-plus mr-1"></i>추가
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- 사용자 목록 (넓게) -->
|
|
<div class="lg:col-span-3 bg-white rounded-xl shadow-sm p-5">
|
|
<h2 class="text-base font-semibold text-gray-800 mb-3">
|
|
<i class="fas fa-users text-slate-400 mr-2"></i>사용자 목록
|
|
<span id="activeUserCount" class="text-xs font-normal text-gray-400 ml-1"></span>
|
|
</h2>
|
|
<div class="flex gap-2 mb-3">
|
|
<input type="text" id="userSearchInput" class="input-field flex-1 px-3 py-1.5 rounded-lg text-sm" placeholder="이름/아이디 검색">
|
|
<select id="userDeptFilter" class="input-field px-2 py-1.5 rounded-lg text-sm">
|
|
<option value="">전체 부서</option>
|
|
</select>
|
|
</div>
|
|
<div id="userList" class="space-y-2 max-h-[420px] overflow-y-auto">
|
|
<div class="text-gray-400 text-center py-8"><i class="fas fa-spinner fa-spin text-2xl"></i><p class="mt-2 text-sm">로딩 중...</p></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 퇴사자 목록 -->
|
|
<div id="resignedSection" class="mt-6 bg-white rounded-xl shadow-sm p-5 hidden">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h2 class="text-base font-semibold text-gray-800">
|
|
<i class="fas fa-user-slash text-gray-400 mr-2"></i>퇴사자 목록
|
|
<span id="resignedCount" class="text-xs font-normal text-gray-400 ml-1"></span>
|
|
</h2>
|
|
<button onclick="toggleResignedList()" id="resignedToggleBtn" class="text-xs text-gray-500 hover:text-gray-700">
|
|
<i class="fas fa-chevron-down mr-1"></i>펼치기
|
|
</button>
|
|
</div>
|
|
<div id="resignedUserList" class="space-y-2 max-h-[300px] overflow-y-auto hidden"></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
<!-- 비밀번호 변경 (일반 사용자) -->
|
|
<div id="passwordChangeSection" class="hidden">
|
|
<div class="bg-white rounded-xl shadow-sm p-6 max-w-md mx-auto">
|
|
<h2 class="text-base font-semibold text-gray-800 mb-4"><i class="fas fa-key text-slate-400 mr-2"></i>비밀번호 변경</h2>
|
|
<form id="changePasswordForm" class="space-y-4">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">현재 비밀번호</label>
|
|
<input type="password" id="currentPassword" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">새 비밀번호</label>
|
|
<input type="password" id="newPasswordChange" class="input-field w-full px-3 py-2 rounded-lg text-sm" required minlength="6" placeholder="최소 6자">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">새 비밀번호 확인</label>
|
|
<input type="password" id="confirmPassword" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<button type="submit" class="w-full px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium">
|
|
<i class="fas fa-save mr-1"></i>비밀번호 변경
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ 권한 탭 ============ -->
|
|
<div id="tab-permissions" class="hidden">
|
|
<!-- 부서별 기본 권한 설정 -->
|
|
<div class="bg-white rounded-xl shadow-sm p-5">
|
|
<div class="flex items-center justify-between mb-5">
|
|
<h2 class="text-base font-semibold text-gray-800"><i class="fas fa-building text-slate-400 mr-2"></i>부서별 기본 권한</h2>
|
|
<select id="deptPermSelect" class="input-field px-3 py-1.5 rounded-lg text-sm min-w-0 w-full sm:min-w-[200px] sm:w-auto">
|
|
<option value="">부서 선택</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div id="deptPermPanel" class="hidden">
|
|
<!-- System 1 -->
|
|
<div class="system-section system1 rounded-lg mb-5 bg-white">
|
|
<div class="flex items-center justify-between px-4 py-3 bg-blue-50 rounded-t-lg border border-blue-100">
|
|
<div class="flex items-center gap-2">
|
|
<i class="fas fa-industry text-blue-500"></i>
|
|
<span class="font-semibold text-sm text-blue-900">공장관리</span>
|
|
<span class="text-xs text-blue-500 bg-blue-100 px-2 py-0.5 rounded-full">System 1</span>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<button onclick="toggleDeptSystemAll('s1', true)" class="text-xs text-blue-600 hover:underline">전체 허용</button>
|
|
<span class="text-gray-300">|</span>
|
|
<button onclick="toggleDeptSystemAll('s1', false)" class="text-xs text-blue-600 hover:underline">전체 해제</button>
|
|
</div>
|
|
</div>
|
|
<div id="dept-s1-perms" class="p-4 border border-t-0 border-blue-100 rounded-b-lg space-y-4"></div>
|
|
</div>
|
|
<!-- System 3 -->
|
|
<div class="system-section system3 rounded-lg mb-5 bg-white">
|
|
<div class="flex items-center justify-between px-4 py-3 bg-purple-50 rounded-t-lg border border-purple-100">
|
|
<div class="flex items-center gap-2">
|
|
<i class="fas fa-shield-halved text-purple-500"></i>
|
|
<span class="font-semibold text-sm text-purple-900">부적합관리</span>
|
|
<span class="text-xs text-purple-500 bg-purple-100 px-2 py-0.5 rounded-full">System 3</span>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<button onclick="toggleDeptSystemAll('s3', true)" class="text-xs text-purple-600 hover:underline">전체 허용</button>
|
|
<span class="text-gray-300">|</span>
|
|
<button onclick="toggleDeptSystemAll('s3', false)" class="text-xs text-purple-600 hover:underline">전체 해제</button>
|
|
</div>
|
|
</div>
|
|
<div id="dept-s3-perms" class="p-4 border border-t-0 border-purple-100 rounded-b-lg space-y-4"></div>
|
|
</div>
|
|
<!-- tkpurchase - 구매 관리 -->
|
|
<div class="system-section tkpurchase rounded-lg mb-5 bg-white">
|
|
<div class="flex items-center justify-between px-4 py-3 bg-green-50 rounded-t-lg border border-green-100">
|
|
<div class="flex items-center gap-2">
|
|
<i class="fas fa-truck text-green-500"></i>
|
|
<span class="font-semibold text-sm text-green-900">구매 관리</span>
|
|
<span class="text-xs text-green-500 bg-green-100 px-2 py-0.5 rounded-full">tkpurchase</span>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<button onclick="toggleDeptSystemAll('tkpurchase', true)" class="text-xs text-green-600 hover:underline">전체 허용</button>
|
|
<span class="text-gray-300">|</span>
|
|
<button onclick="toggleDeptSystemAll('tkpurchase', false)" class="text-xs text-green-600 hover:underline">전체 해제</button>
|
|
</div>
|
|
</div>
|
|
<div id="dept-tkpurchase-perms" class="p-4 border border-t-0 border-green-100 rounded-b-lg space-y-4"></div>
|
|
</div>
|
|
<!-- tksafety -->
|
|
<div>
|
|
<div class="flex items-center justify-between bg-orange-50 px-4 py-2 rounded-t-lg border border-orange-100">
|
|
<h4 class="font-semibold text-orange-800"><i class="fas fa-hard-hat mr-2"></i>안전 관리 (tksafety)</h4>
|
|
<div class="flex gap-2">
|
|
<button onclick="toggleDeptSystemAll('tksafety', true)" class="text-xs text-orange-600 hover:underline">전체 허용</button>
|
|
<span class="text-gray-300">|</span>
|
|
<button onclick="toggleDeptSystemAll('tksafety', false)" class="text-xs text-orange-600 hover:underline">전체 해제</button>
|
|
</div>
|
|
</div>
|
|
<div id="dept-tksafety-perms" class="p-4 border border-t-0 border-orange-100 rounded-b-lg space-y-4"></div>
|
|
</div>
|
|
<!-- tksupport - 행정 지원 -->
|
|
<div class="system-section tksupport rounded-lg mb-5 bg-white">
|
|
<div class="flex items-center justify-between px-4 py-3 bg-indigo-50 rounded-t-lg border border-indigo-100">
|
|
<div class="flex items-center gap-2">
|
|
<i class="fas fa-briefcase text-indigo-500"></i>
|
|
<span class="font-semibold text-sm text-indigo-900">행정 지원</span>
|
|
<span class="text-xs text-indigo-500 bg-indigo-100 px-2 py-0.5 rounded-full">tksupport</span>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<button onclick="toggleDeptSystemAll('tksupport', true)" class="text-xs text-indigo-600 hover:underline">전체 허용</button>
|
|
<span class="text-gray-300">|</span>
|
|
<button onclick="toggleDeptSystemAll('tksupport', false)" class="text-xs text-indigo-600 hover:underline">전체 해제</button>
|
|
</div>
|
|
</div>
|
|
<div id="dept-tksupport-perms" class="p-4 border border-t-0 border-indigo-100 rounded-b-lg space-y-4"></div>
|
|
</div>
|
|
<!-- tkuser - 통합 관리 -->
|
|
<div>
|
|
<div class="flex items-center justify-between bg-slate-50 px-4 py-2 rounded-t-lg border border-slate-200">
|
|
<h4 class="font-semibold text-slate-800"><i class="fas fa-cogs mr-2"></i>통합 관리 (tkuser)</h4>
|
|
<div class="flex gap-2">
|
|
<button onclick="toggleDeptSystemAll('tkuser', true)" class="text-xs text-slate-600 hover:underline">전체 허용</button>
|
|
<span class="text-gray-300">|</span>
|
|
<button onclick="toggleDeptSystemAll('tkuser', false)" class="text-xs text-slate-600 hover:underline">전체 해제</button>
|
|
</div>
|
|
</div>
|
|
<div id="dept-tkuser-perms" class="p-4 border border-t-0 border-slate-200 rounded-b-lg space-y-4"></div>
|
|
</div>
|
|
<!-- 저장 -->
|
|
<div class="flex items-center gap-3 pt-2">
|
|
<button id="saveDeptPermBtn" class="px-6 py-2.5 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium">
|
|
<i class="fas fa-save mr-2"></i>부서 권한 저장
|
|
</button>
|
|
<span id="deptPermSaveStatus" class="text-sm"></span>
|
|
</div>
|
|
<p class="text-xs text-gray-400 mt-1">
|
|
<i class="fas fa-info-circle mr-1"></i>부서 권한 저장 시 소속 사용자에게 자동 적용됩니다
|
|
</p>
|
|
</div>
|
|
|
|
<div id="deptPermEmpty" class="text-center text-gray-400 py-8 text-sm">
|
|
<i class="fas fa-building text-2xl mb-2"></i>
|
|
<p>부서를 선택하면 기본 권한을 설정할 수 있습니다</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 페이지 권한 관리 (개인) -->
|
|
<div class="mt-6 bg-white rounded-xl shadow-sm p-5">
|
|
<div class="flex items-center justify-between mb-5">
|
|
<h2 class="text-base font-semibold text-gray-800"><i class="fas fa-shield-alt text-slate-400 mr-2"></i>개인 페이지 권한</h2>
|
|
<select id="permissionUserSelect" class="input-field px-3 py-1.5 rounded-lg text-sm min-w-[200px]">
|
|
<option value="">사용자 선택</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div id="permissionPanel" class="hidden">
|
|
<!-- System 1 - 공장관리 -->
|
|
<div class="system-section system1 rounded-lg mb-5 bg-white">
|
|
<div class="flex items-center justify-between px-4 py-3 bg-blue-50 rounded-t-lg border border-blue-100">
|
|
<div class="flex items-center gap-2">
|
|
<i class="fas fa-industry text-blue-500"></i>
|
|
<span class="font-semibold text-sm text-blue-900">공장관리</span>
|
|
<span class="text-xs text-blue-500 bg-blue-100 px-2 py-0.5 rounded-full">System 1</span>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<button onclick="toggleSystemAll('s1', true)" class="text-xs text-blue-600 hover:underline">전체 허용</button>
|
|
<span class="text-gray-300">|</span>
|
|
<button onclick="toggleSystemAll('s1', false)" class="text-xs text-blue-600 hover:underline">전체 해제</button>
|
|
</div>
|
|
</div>
|
|
<div id="s1-perms" class="p-4 border border-t-0 border-blue-100 rounded-b-lg space-y-4"></div>
|
|
</div>
|
|
|
|
<!-- System 3 - 부적합관리 -->
|
|
<div class="system-section system3 rounded-lg mb-5 bg-white">
|
|
<div class="flex items-center justify-between px-4 py-3 bg-purple-50 rounded-t-lg border border-purple-100">
|
|
<div class="flex items-center gap-2">
|
|
<i class="fas fa-shield-halved text-purple-500"></i>
|
|
<span class="font-semibold text-sm text-purple-900">부적합관리</span>
|
|
<span class="text-xs text-purple-500 bg-purple-100 px-2 py-0.5 rounded-full">System 3</span>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<button onclick="toggleSystemAll('s3', true)" class="text-xs text-purple-600 hover:underline">전체 허용</button>
|
|
<span class="text-gray-300">|</span>
|
|
<button onclick="toggleSystemAll('s3', false)" class="text-xs text-purple-600 hover:underline">전체 해제</button>
|
|
</div>
|
|
</div>
|
|
<div id="s3-perms" class="p-4 border border-t-0 border-purple-100 rounded-b-lg space-y-4"></div>
|
|
</div>
|
|
|
|
<!-- tkpurchase - 구매 관리 -->
|
|
<div class="system-section tkpurchase rounded-lg mb-5 bg-white">
|
|
<div class="flex items-center justify-between px-4 py-3 bg-green-50 rounded-t-lg border border-green-100">
|
|
<div class="flex items-center gap-2">
|
|
<i class="fas fa-truck text-green-500"></i>
|
|
<span class="font-semibold text-sm text-green-900">구매 관리</span>
|
|
<span class="text-xs text-green-500 bg-green-100 px-2 py-0.5 rounded-full">tkpurchase</span>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<button onclick="toggleSystemAll('tkpurchase', true)" class="text-xs text-green-600 hover:underline">전체 허용</button>
|
|
<span class="text-gray-300">|</span>
|
|
<button onclick="toggleSystemAll('tkpurchase', false)" class="text-xs text-green-600 hover:underline">전체 해제</button>
|
|
</div>
|
|
</div>
|
|
<div id="tkpurchase-perms" class="p-4 border border-t-0 border-green-100 rounded-b-lg space-y-4"></div>
|
|
</div>
|
|
<!-- tksafety -->
|
|
<div>
|
|
<div class="flex items-center justify-between bg-orange-50 px-4 py-2 rounded-t-lg border border-orange-100">
|
|
<h4 class="font-semibold text-orange-800"><i class="fas fa-hard-hat mr-2"></i>안전 관리 (tksafety)</h4>
|
|
<div class="flex gap-2">
|
|
<button onclick="toggleSystemAll('tksafety', true)" class="text-xs text-orange-600 hover:underline">전체 허용</button>
|
|
<span class="text-gray-300">|</span>
|
|
<button onclick="toggleSystemAll('tksafety', false)" class="text-xs text-orange-600 hover:underline">전체 해제</button>
|
|
</div>
|
|
</div>
|
|
<div id="tksafety-perms" class="p-4 border border-t-0 border-orange-100 rounded-b-lg space-y-4"></div>
|
|
</div>
|
|
<!-- tksupport - 행정 지원 -->
|
|
<div class="system-section tksupport rounded-lg mb-5 bg-white">
|
|
<div class="flex items-center justify-between px-4 py-3 bg-indigo-50 rounded-t-lg border border-indigo-100">
|
|
<div class="flex items-center gap-2">
|
|
<i class="fas fa-briefcase text-indigo-500"></i>
|
|
<span class="font-semibold text-sm text-indigo-900">행정 지원</span>
|
|
<span class="text-xs text-indigo-500 bg-indigo-100 px-2 py-0.5 rounded-full">tksupport</span>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<button onclick="toggleSystemAll('tksupport', true)" class="text-xs text-indigo-600 hover:underline">전체 허용</button>
|
|
<span class="text-gray-300">|</span>
|
|
<button onclick="toggleSystemAll('tksupport', false)" class="text-xs text-indigo-600 hover:underline">전체 해제</button>
|
|
</div>
|
|
</div>
|
|
<div id="tksupport-perms" class="p-4 border border-t-0 border-indigo-100 rounded-b-lg space-y-4"></div>
|
|
</div>
|
|
<!-- tkuser - 통합 관리 -->
|
|
<div>
|
|
<div class="flex items-center justify-between bg-slate-50 px-4 py-2 rounded-t-lg border border-slate-200">
|
|
<h4 class="font-semibold text-slate-800"><i class="fas fa-cogs mr-2"></i>통합 관리 (tkuser)</h4>
|
|
<div class="flex gap-2">
|
|
<button onclick="toggleSystemAll('tkuser', true)" class="text-xs text-slate-600 hover:underline">전체 허용</button>
|
|
<span class="text-gray-300">|</span>
|
|
<button onclick="toggleSystemAll('tkuser', false)" class="text-xs text-slate-600 hover:underline">전체 해제</button>
|
|
</div>
|
|
</div>
|
|
<div id="tkuser-perms" class="p-4 border border-t-0 border-slate-200 rounded-b-lg space-y-4"></div>
|
|
</div>
|
|
|
|
<!-- 저장 버튼 -->
|
|
<div class="flex items-center gap-3 pt-2">
|
|
<button id="savePermissionsBtn" class="px-6 py-2.5 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium">
|
|
<i class="fas fa-save mr-2"></i>권한 저장
|
|
</button>
|
|
<button id="resetToDefaultBtn" class="px-4 py-2.5 border border-gray-300 text-gray-600 rounded-lg hover:bg-gray-50 text-sm font-medium">
|
|
<i class="fas fa-undo mr-2"></i>부서 기본으로 초기화
|
|
</button>
|
|
<span id="permissionSaveStatus" class="text-sm"></span>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="permissionEmpty" class="text-center text-gray-400 py-8 text-sm">
|
|
<i class="fas fa-hand-pointer text-2xl mb-2"></i>
|
|
<p>사용자를 선택하면 권한을 설정할 수 있습니다</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ 준비 중 탭 (placeholder) ============ -->
|
|
<div id="tab-projects" class="hidden">
|
|
<div class="grid lg:grid-cols-5 gap-6">
|
|
<!-- 프로젝트 추가 (좁게) -->
|
|
<div class="lg:col-span-2 bg-white rounded-xl shadow-sm p-5">
|
|
<h2 class="text-base font-semibold text-gray-800 mb-4"><i class="fas fa-folder-plus text-slate-400 mr-2"></i>프로젝트 추가</h2>
|
|
<form id="addProjectForm" class="space-y-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">Job No <span class="text-red-400">*</span></label>
|
|
<input type="text" id="newJobNo" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="예: JOB-2026-001" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">프로젝트명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="newProjectName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="프로젝트 이름" required>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">계약일</label>
|
|
<input type="date" id="newContractDate" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">납기일</label>
|
|
<input type="date" id="newDueDate" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">제품유형</label>
|
|
<select id="newProductType" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">현장</label>
|
|
<input type="text" id="newSite" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="설치 현장">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">PM</label>
|
|
<input type="text" id="newPm" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="담당 PM">
|
|
</div>
|
|
<button type="submit" class="w-full px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium">
|
|
<i class="fas fa-plus mr-1"></i>추가
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- 프로젝트 목록 (넓게) -->
|
|
<div class="lg:col-span-3 bg-white rounded-xl shadow-sm p-5">
|
|
<h2 class="text-base font-semibold text-gray-800 mb-4"><i class="fas fa-folder-open text-slate-400 mr-2"></i>프로젝트 목록</h2>
|
|
<div id="projectList" class="space-y-2 max-h-[520px] overflow-y-auto">
|
|
<div class="text-gray-400 text-center py-8"><i class="fas fa-spinner fa-spin text-2xl"></i><p class="mt-2 text-sm">로딩 중...</p></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- ============ 작업자 탭 ============ -->
|
|
<div id="tab-workers" class="hidden">
|
|
<div class="grid lg:grid-cols-5 gap-6">
|
|
<div class="lg:col-span-2 bg-white rounded-xl shadow-sm p-5">
|
|
<h2 class="text-base font-semibold text-gray-800 mb-4"><i class="fas fa-hard-hat text-slate-400 mr-2"></i>작업자 등록</h2>
|
|
<form id="addWorkerForm" class="space-y-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">이름 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="newWorkerName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="작업자 이름" required>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">직종</label>
|
|
<select id="newJobType" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
<option value="leader">반장</option>
|
|
<option value="worker">작업자</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">부서</label>
|
|
<select id="newWorkerDept" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">연락처</label>
|
|
<input type="text" id="newWorkerPhone" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="010-0000-0000">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">입사일</label>
|
|
<input type="date" id="newWorkerHireDate" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">메모</label>
|
|
<input type="text" id="newWorkerNotes" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="비고">
|
|
</div>
|
|
<button type="submit" class="w-full px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium">
|
|
<i class="fas fa-plus mr-1"></i>추가
|
|
</button>
|
|
</form>
|
|
</div>
|
|
<div class="lg:col-span-3 bg-white rounded-xl shadow-sm p-5">
|
|
<h2 class="text-base font-semibold text-gray-800 mb-4"><i class="fas fa-people-group text-slate-400 mr-2"></i>작업자 목록</h2>
|
|
<div id="workerList" class="space-y-2 max-h-[520px] overflow-y-auto">
|
|
<div class="text-gray-400 text-center py-8"><i class="fas fa-spinner fa-spin text-2xl"></i><p class="mt-2 text-sm">로딩 중...</p></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- ============ 부서 탭 ============ -->
|
|
<div id="tab-departments" class="hidden">
|
|
<div class="grid lg:grid-cols-5 gap-6">
|
|
<div class="lg:col-span-2 bg-white rounded-xl shadow-sm p-5">
|
|
<h2 class="text-base font-semibold text-gray-800 mb-4"><i class="fas fa-sitemap text-slate-400 mr-2"></i>부서 등록</h2>
|
|
<form id="addDepartmentForm" class="space-y-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">부서명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="newDeptName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="부서 이름" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설명</label>
|
|
<input type="text" id="newDeptDescription" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="부서 설명">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">표시순서</label>
|
|
<input type="number" id="newDeptOrder" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" value="0" min="0">
|
|
</div>
|
|
<button type="submit" class="w-full px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium">
|
|
<i class="fas fa-plus mr-1"></i>추가
|
|
</button>
|
|
</form>
|
|
</div>
|
|
<div class="lg:col-span-3 bg-white rounded-xl shadow-sm p-5">
|
|
<h2 class="text-base font-semibold text-gray-800 mb-4"><i class="fas fa-sitemap text-slate-400 mr-2"></i>부서 목록</h2>
|
|
<div id="departmentList" class="space-y-2 max-h-[520px] overflow-y-auto">
|
|
<div class="text-gray-400 text-center py-8"><i class="fas fa-spinner fa-spin text-2xl"></i><p class="mt-2 text-sm">로딩 중...</p></div>
|
|
</div>
|
|
<div id="deptMembersPanel" class="hidden mt-4 border-t pt-4">
|
|
<h3 class="text-sm font-semibold text-gray-700 mb-3"><i class="fas fa-users text-slate-400 mr-1.5"></i>소속 인원</h3>
|
|
<div id="deptMembersList" class="space-y-2"></div>
|
|
<div id="deptApprovalSection" class="hidden mt-4 border-t pt-4">
|
|
<div class="flex items-center justify-between mb-3">
|
|
<h4 class="text-sm font-semibold text-gray-700"><i class="fas fa-user-check text-slate-400 mr-1.5"></i>승인권한</h4>
|
|
<button onclick="openApprovalModal()" class="text-xs text-slate-500 hover:text-slate-700 px-1.5 py-0.5 rounded hover:bg-gray-100" title="승인권한 추가"><i class="fas fa-plus"></i></button>
|
|
</div>
|
|
<div id="deptApprovalList" class="space-y-2"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ 이슈 유형 탭 ============ -->
|
|
<div id="tab-issueTypes" class="hidden">
|
|
<div class="grid lg:grid-cols-5 gap-6">
|
|
<!-- 좌측: 등록 폼 -->
|
|
<div class="lg:col-span-2 space-y-4">
|
|
<!-- 카테고리 등록 -->
|
|
<div class="bg-white rounded-xl shadow-sm p-5">
|
|
<h2 class="text-base font-semibold text-gray-800 mb-4"><i class="fas fa-layer-group text-slate-400 mr-2"></i>카테고리 등록</h2>
|
|
<form id="addIssueCategoryForm" class="space-y-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">유형 <span class="text-red-400">*</span></label>
|
|
<div class="flex gap-3">
|
|
<label class="flex items-center gap-1.5 text-sm cursor-pointer">
|
|
<input type="radio" name="newIssueCatType" value="nonconformity" checked class="accent-slate-700"> 부적합
|
|
</label>
|
|
<label class="flex items-center gap-1.5 text-sm cursor-pointer">
|
|
<input type="radio" name="newIssueCatType" value="safety" class="accent-slate-700"> 안전
|
|
</label>
|
|
<label class="flex items-center gap-1.5 text-sm cursor-pointer">
|
|
<input type="radio" name="newIssueCatType" value="facility" class="accent-slate-700"> 시설설비
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">카테고리명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="newIssueCatName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="카테고리 이름" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설명</label>
|
|
<input type="text" id="newIssueCatDesc" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="카테고리 설명">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">표시순서</label>
|
|
<input type="number" id="newIssueCatOrder" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" value="0" min="0">
|
|
</div>
|
|
<button type="submit" class="w-full px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium">
|
|
<i class="fas fa-plus mr-1"></i>카테고리 추가
|
|
</button>
|
|
</form>
|
|
</div>
|
|
<!-- 아이템 등록 -->
|
|
<div class="bg-white rounded-xl shadow-sm p-5">
|
|
<h2 class="text-base font-semibold text-gray-800 mb-4"><i class="fas fa-list-ul text-slate-400 mr-2"></i>아이템 등록</h2>
|
|
<form id="addIssueItemForm" class="space-y-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">카테고리 <span class="text-red-400">*</span></label>
|
|
<select id="newIssueItemCategory" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" required>
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">아이템명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="newIssueItemName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="아이템 이름" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설명</label>
|
|
<input type="text" id="newIssueItemDesc" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="아이템 설명">
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">심각도</label>
|
|
<select id="newIssueItemSeverity" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="low">낮음</option>
|
|
<option value="medium" selected>보통</option>
|
|
<option value="high">높음</option>
|
|
<option value="critical">심각</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">표시순서</label>
|
|
<input type="number" id="newIssueItemOrder" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" value="0" min="0">
|
|
</div>
|
|
</div>
|
|
<button type="submit" class="w-full px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium">
|
|
<i class="fas fa-plus mr-1"></i>아이템 추가
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<!-- 우측: 카테고리/아이템 목록 -->
|
|
<div class="lg:col-span-3 bg-white rounded-xl shadow-sm p-5">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h2 class="text-base font-semibold text-gray-800"><i class="fas fa-exclamation-triangle text-slate-400 mr-2"></i>이슈 유형 목록</h2>
|
|
<div class="flex gap-1 bg-gray-100 rounded-lg p-0.5">
|
|
<button id="issueTypeToggleNonconformity" onclick="switchIssueType('nonconformity')" class="px-3 py-1 rounded-md text-xs font-medium bg-slate-700 text-white">부적합</button>
|
|
<button id="issueTypeToggleSafety" onclick="switchIssueType('safety')" class="px-3 py-1 rounded-md text-xs font-medium text-gray-500 hover:bg-gray-200">안전</button>
|
|
<button id="issueTypeToggleFacility" onclick="switchIssueType('facility')" class="px-3 py-1 rounded-md text-xs font-medium text-gray-500 hover:bg-gray-200">시설설비</button>
|
|
</div>
|
|
</div>
|
|
<div id="issueCategoryList" class="space-y-2 max-h-[600px] overflow-y-auto">
|
|
<div class="text-gray-400 text-center py-8"><i class="fas fa-spinner fa-spin text-2xl"></i><p class="mt-2 text-sm">로딩 중...</p></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ 작업 탭 ============ -->
|
|
<div id="tab-tasks" class="hidden">
|
|
<div class="flex flex-col lg:flex-row gap-6" style="height: calc(100vh - 9rem);">
|
|
<!-- 공정 사이드바 -->
|
|
<div class="w-full lg:w-64 lg:flex-shrink-0 bg-white rounded-xl shadow-sm p-4 flex flex-col overflow-hidden">
|
|
<div class="flex items-center justify-between mb-3">
|
|
<div class="text-xs font-semibold text-gray-400 uppercase tracking-wider">공정</div>
|
|
<button onclick="openWorkTypeModal()" class="text-xs text-slate-500 hover:text-slate-700 px-1.5 py-0.5 rounded hover:bg-gray-100" title="공정 추가"><i class="fas fa-plus"></i></button>
|
|
</div>
|
|
<div id="workTypeSidebar" class="space-y-1 flex-1 overflow-y-auto">
|
|
<div class="text-gray-400 text-center py-8 text-sm"><i class="fas fa-spinner fa-spin"></i></div>
|
|
</div>
|
|
</div>
|
|
<!-- 작업 목록 메인 -->
|
|
<div class="flex-1 overflow-hidden min-w-0 flex flex-col">
|
|
<div class="bg-white rounded-xl shadow-sm p-5 flex flex-col flex-1 overflow-hidden">
|
|
<div class="flex items-center justify-between mb-4 flex-wrap gap-2">
|
|
<h2 class="text-base font-semibold text-gray-800">
|
|
<i class="fas fa-tasks text-slate-400 mr-2"></i>작업 목록
|
|
<span id="taskFilterLabel" class="text-sm font-normal text-gray-500 ml-1">- 전체</span>
|
|
</h2>
|
|
<div class="flex items-center gap-2">
|
|
<span id="taskStats" class="text-xs text-gray-400"></span>
|
|
<button onclick="openTaskModal()" class="px-3 py-1.5 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-xs font-medium">
|
|
<i class="fas fa-plus mr-1"></i>작업 추가
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div id="taskList" class="space-y-2 flex-1 overflow-y-auto">
|
|
<div class="text-gray-400 text-center py-8"><i class="fas fa-spinner fa-spin text-2xl"></i><p class="mt-2 text-sm">로딩 중...</p></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 공정 추가/편집 모달 -->
|
|
<div id="workTypeModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-sm w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 id="workTypeModalTitle" class="text-base font-semibold text-gray-900">공정 추가</h3>
|
|
<button onclick="closeWorkTypeModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="workTypeForm" class="space-y-3">
|
|
<input type="hidden" id="wtEditId">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">공정명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="wtName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="예: 용접" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">카테고리</label>
|
|
<input type="text" id="wtCategory" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="예: 제작">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설명</label>
|
|
<textarea id="wtDesc" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" rows="2" placeholder="선택사항"></textarea>
|
|
</div>
|
|
<div class="flex gap-3 pt-2">
|
|
<button type="button" onclick="closeWorkTypeModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-save mr-1"></i>저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 작업 추가/편집 모달 -->
|
|
<div id="taskModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-md w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 id="taskModalTitle" class="text-base font-semibold text-gray-900">작업 추가</h3>
|
|
<button onclick="closeTaskModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="taskForm" class="space-y-3">
|
|
<input type="hidden" id="taskEditId">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">작업명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="taskName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="예: 서스 용접" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">소속 공정</label>
|
|
<select id="taskWorkType" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">미지정</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설명</label>
|
|
<textarea id="taskDesc" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" rows="3" placeholder="선택사항"></textarea>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<input type="checkbox" id="taskActive" checked class="rounded">
|
|
<label for="taskActive" class="text-sm text-gray-600">활성화 <span class="text-xs text-gray-400">(비활성 시 TBM 입력에서 숨김)</span></label>
|
|
</div>
|
|
<div class="flex gap-3 pt-2">
|
|
<button type="button" onclick="closeTaskModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-save mr-1"></i>저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ 휴가 탭 ============ -->
|
|
<div id="tab-vacations" class="hidden">
|
|
<div class="flex gap-6" style="height: calc(100vh - 9rem);">
|
|
<!-- 휴가 유형 사이드바 -->
|
|
<div class="w-72 flex-shrink-0 bg-white rounded-xl shadow-sm p-4 flex flex-col overflow-hidden">
|
|
<div class="flex items-center justify-between mb-3">
|
|
<div class="text-xs font-semibold text-gray-400 uppercase tracking-wider">휴가 유형</div>
|
|
<button onclick="openVacTypeModal()" class="text-xs text-slate-500 hover:text-slate-700 px-1.5 py-0.5 rounded hover:bg-gray-100" title="유형 추가"><i class="fas fa-plus"></i></button>
|
|
</div>
|
|
<div id="vacTypeSidebar" class="space-y-1 flex-1 overflow-y-auto">
|
|
<div class="text-gray-400 text-center py-8 text-sm"><i class="fas fa-spinner fa-spin"></i></div>
|
|
</div>
|
|
</div>
|
|
<!-- 연차 배정 메인 -->
|
|
<div class="flex-1 overflow-hidden min-w-0 flex flex-col">
|
|
<div class="bg-white rounded-xl shadow-sm p-5 flex flex-col flex-1 overflow-hidden">
|
|
<div class="flex items-center justify-between mb-4 flex-wrap gap-2">
|
|
<h2 class="text-base font-semibold text-gray-800"><i class="fas fa-calendar-check text-slate-400 mr-2"></i>연차 배정</h2>
|
|
<div class="flex items-center gap-2 flex-wrap">
|
|
<select id="vacDeptFilter" class="input-field px-3 py-1.5 rounded-lg text-sm" onchange="filterVacBalances()">
|
|
<option value="">전체 부서</option>
|
|
</select>
|
|
<input type="text" id="vacSearch" class="input-field px-3 py-1.5 rounded-lg text-sm w-36" placeholder="이름 검색" oninput="filterVacBalances()">
|
|
<select id="vacYear" class="input-field px-3 py-1.5 rounded-lg text-sm" onchange="loadVacBalances()">
|
|
</select>
|
|
<button onclick="autoCalcVacation()" class="px-3 py-1.5 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 text-xs font-medium" title="입사일 기반 연차 자동 계산">
|
|
<i class="fas fa-calculator mr-1"></i>자동 계산
|
|
</button>
|
|
<button onclick="openVacBalanceModal()" class="px-3 py-1.5 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-xs font-medium">
|
|
<i class="fas fa-plus mr-1"></i>개별 배정
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div id="vacBalanceTable" class="flex-1 overflow-auto">
|
|
<div class="text-gray-400 text-center py-8"><i class="fas fa-spinner fa-spin text-2xl"></i><p class="mt-2 text-sm">로딩 중...</p></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ 연차 설정 탭 ============ -->
|
|
<div id="tab-vacationSettings" class="hidden">
|
|
<div class="max-w-3xl mx-auto space-y-6">
|
|
<div id="vacSettingsContent">
|
|
<div class="text-gray-400 text-center py-8"><i class="fas fa-spinner fa-spin text-2xl"></i><p class="mt-2 text-sm">로딩 중...</p></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 휴가 유형 모달 -->
|
|
<div id="vacTypeModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-sm w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 id="vacTypeModalTitle" class="text-base font-semibold text-gray-900">휴가 유형 추가</h3>
|
|
<button onclick="closeVacTypeModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="vacTypeForm" class="space-y-3">
|
|
<input type="hidden" id="vtEditId">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">유형 코드 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="vtCode" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="예: ANNUAL" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">유형명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="vtName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="예: 연차" required>
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">차감 일수</label>
|
|
<input type="number" id="vtDeductDays" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" value="1.0" step="0.1" min="0">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">우선순위</label>
|
|
<input type="number" id="vtPriority" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" value="99" min="0">
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설명</label>
|
|
<textarea id="vtDescription" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" rows="2" placeholder="선택사항"></textarea>
|
|
</div>
|
|
<div class="flex items-center gap-3">
|
|
<label class="flex items-center gap-1.5 text-sm text-gray-600"><input type="checkbox" id="vtSpecial" class="rounded">특별휴가</label>
|
|
</div>
|
|
<div class="flex gap-3 pt-2">
|
|
<button type="button" onclick="closeVacTypeModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-save mr-1"></i>저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 개별 배정 모달 -->
|
|
<div id="vacBalanceModal" class="modal-overlay fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-md w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 id="vacBalModalTitle" class="text-base font-semibold text-gray-900">연차 배정</h3>
|
|
<button onclick="closeVacBalanceModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="vacBalanceForm" class="space-y-3">
|
|
<input type="hidden" id="vbEditId">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">사용자 <span class="text-red-400">*</span></label>
|
|
<select id="vbUser" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" required>
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
<input type="hidden" id="vbType" value="">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">유형 <span class="text-red-400">*</span></label>
|
|
<select id="vbBalanceType" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" onchange="onBalanceTypeChange()">
|
|
<option value="AUTO">기본연차</option>
|
|
<option value="MANUAL">추가부여</option>
|
|
<option value="CARRY_OVER">이월연차</option>
|
|
<option value="LONG_SERVICE">장기근속</option>
|
|
<option value="COMPANY_GRANT">경조사/특별휴가</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">배정 연도 <span class="text-red-400">*</span></label>
|
|
<input type="number" id="vbYear" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" min="2020" max="2035" required>
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">배정 일수</label>
|
|
<input type="number" id="vbTotalDays" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" value="0" step="0.25">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">사용 일수</label>
|
|
<input type="number" id="vbUsedDays" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" value="0" step="0.25" min="0">
|
|
</div>
|
|
</div>
|
|
<div id="vbSpecialTypeRow" class="hidden">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">경조사 유형</label>
|
|
<select id="vbSpecialType" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="WEDDING">결혼 (5일)</option>
|
|
<option value="SPOUSE_BIRTH">배우자 출산 (10일)</option>
|
|
<option value="CHILD_WEDDING">자녀 결혼 (1일)</option>
|
|
<option value="CONDOLENCE_PARENT">부모 사망 (5일)</option>
|
|
<option value="CONDOLENCE_SPOUSE_PARENT">배우자 부모 사망 (5일)</option>
|
|
<option value="CONDOLENCE_GRANDPARENT">조부모 사망 (3일)</option>
|
|
<option value="CONDOLENCE_SIBLING">형제자매 사망 (3일)</option>
|
|
<option value="OTHER">기타 (1일)</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">만료일</label>
|
|
<input type="date" id="vbExpiresAt" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">비고</label>
|
|
<input type="text" id="vbNotes" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="메모">
|
|
</div>
|
|
<div class="flex gap-3 pt-2">
|
|
<button type="button" onclick="closeVacBalanceModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-save mr-1"></i>저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ 작업장 탭 ============ -->
|
|
<div id="tab-workplaces" class="hidden">
|
|
<div class="flex gap-6" style="height: calc(100vh - 9rem);">
|
|
<!-- 사이드바 -->
|
|
<div class="w-72 flex-shrink-0 bg-white rounded-xl shadow-sm p-4 flex flex-col overflow-hidden">
|
|
<div id="wpSidebarContent" class="flex flex-col flex-1 overflow-hidden">
|
|
<div class="text-gray-400 text-center py-8"><i class="fas fa-spinner fa-spin text-2xl"></i><p class="mt-2 text-sm">로딩 중...</p></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 메인 영역 -->
|
|
<div class="flex-1 overflow-y-auto min-w-0">
|
|
<!-- 작업장 미선택 안내 -->
|
|
<div id="workplaceEmptyState" class="flex items-center justify-center h-full">
|
|
<div class="text-center text-gray-400">
|
|
<i class="fas fa-industry text-4xl mb-3"></i>
|
|
<p class="text-sm">왼쪽 목록에서 공장을 선택하세요</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 설비 섹션 -->
|
|
<div id="equipmentSection" class="bg-white rounded-xl shadow-sm p-5 hidden">
|
|
<div id="eqBackToCategory" class="mb-3 hidden">
|
|
<button onclick="backToCategory()" class="flex items-center gap-1.5 text-sm text-slate-500 hover:text-slate-700 px-2 py-1 rounded hover:bg-gray-100 transition-colors">
|
|
<i class="fas fa-arrow-left text-xs"></i><span id="eqBackLabel">구역지도로 돌아가기</span>
|
|
</button>
|
|
</div>
|
|
<div class="flex items-center justify-between mb-4 flex-wrap gap-2">
|
|
<h2 class="text-base font-semibold text-gray-800"><i class="fas fa-cog text-slate-400 mr-2"></i>설비 관리 - <span id="eqWorkplaceName">-</span></h2>
|
|
<div class="flex items-center gap-2 flex-wrap">
|
|
<select id="eqStatusFilter" class="input-field px-2 py-1 rounded-lg text-xs" onchange="filterEquipments()">
|
|
<option value="">전체 상태</option>
|
|
<option value="active">가동중</option>
|
|
<option value="maintenance">점검중</option>
|
|
<option value="inactive">비활성</option>
|
|
</select>
|
|
<select id="eqTypeFilter" class="input-field px-2 py-1 rounded-lg text-xs" onchange="filterEquipments()">
|
|
<option value="">전체 유형</option>
|
|
</select>
|
|
<button onclick="openEquipmentModal()" class="px-3 py-1 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-xs font-medium">
|
|
<i class="fas fa-plus mr-1"></i>설비 추가
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 설비 배치도 -->
|
|
<div class="mb-4 p-3 bg-gray-50 rounded-lg">
|
|
<div class="flex items-center justify-between mb-2">
|
|
<h3 class="text-sm font-semibold text-gray-700"><i class="fas fa-map-pin text-gray-400 mr-1"></i>설비 배치도</h3>
|
|
<div class="flex gap-2">
|
|
<label class="px-2 py-1 bg-white border border-gray-200 rounded text-xs cursor-pointer hover:bg-gray-50">
|
|
<i class="fas fa-upload mr-1 text-gray-400"></i>이미지 변경
|
|
<input type="file" id="wpLayoutImageFile" accept="image/jpeg,image/png,image/gif,image/webp" onchange="uploadWorkplaceLayoutImage()" class="hidden">
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div id="eqMapArea" class="text-center text-gray-400 py-4 text-sm">
|
|
<i class="fas fa-image text-2xl mb-1"></i>
|
|
<p>배치도 이미지를 업로드하세요</p>
|
|
</div>
|
|
<div id="eqMapCanvasWrap" class="hidden relative">
|
|
<canvas id="eqMapCanvas" style="max-width:100%; border:1px solid #e2e8f0; border-radius:8px; cursor:crosshair;"></canvas>
|
|
<p class="text-xs text-gray-400 mt-1"><i class="fas fa-info-circle mr-1"></i>설비를 드래그하여 위치 이동 | 목록의 <i class="fas fa-map-pin"></i> 버튼으로 새 위치 지정</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 설비 리스트 -->
|
|
<div id="equipmentList" class="space-y-2 max-h-[400px] overflow-y-auto">
|
|
<p class="text-gray-400 text-center py-4 text-sm">설비가 없습니다.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 구역지도 프리뷰 -->
|
|
<div id="zoneMapSection" class="bg-white rounded-xl shadow-sm p-5 hidden">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h2 id="zoneMapTitle" class="text-base font-semibold text-gray-800"><i class="fas fa-map text-slate-400 mr-2"></i>구역지도</h2>
|
|
<button onclick="openLayoutMapModal()" class="px-4 py-1.5 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium">
|
|
<i class="fas fa-cog mr-1"></i>지도 설정
|
|
</button>
|
|
</div>
|
|
<div id="layoutPreviewArea" class="text-center text-gray-400 py-8 text-sm">
|
|
<i class="fas fa-image text-3xl mb-2"></i>
|
|
<p>레이아웃 이미지가 없습니다. "지도 설정"에서 업로드하세요.</p>
|
|
</div>
|
|
<div id="layoutPreviewCanvas" class="hidden">
|
|
<canvas id="previewCanvas" style="max-width:100%; border:1px solid #e2e8f0; border-radius:8px; cursor:pointer;"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- ============ 설비 탭 ============ -->
|
|
<div id="tab-equipments" class="hidden">
|
|
<div class="grid lg:grid-cols-5 gap-6">
|
|
<!-- 설비 목록 -->
|
|
<div class="lg:col-span-2 bg-white rounded-xl shadow-sm p-5">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h2 class="text-base font-semibold text-gray-800"><i class="fas fa-cogs text-emerald-500 mr-2"></i>설비 목록</h2>
|
|
<button id="btnAddEquipment" onclick="openAddEquipmentTkuser()" class="hidden px-3 py-1.5 bg-slate-700 text-white rounded-lg text-xs hover:bg-slate-800">
|
|
<i class="fas fa-plus mr-1"></i>설비 등록
|
|
</button>
|
|
</div>
|
|
<div class="flex gap-2 mb-3">
|
|
<input type="text" id="equipmentSearchTkuser" class="input-field flex-1 px-3 py-1.5 rounded-lg text-sm" placeholder="설비명, 코드, 제조사 검색..." oninput="filterEquipmentsTkuser()">
|
|
<select id="equipmentFilterWorkplace" class="input-field px-2 py-1.5 rounded-lg text-sm" onchange="filterEquipmentsTkuser()">
|
|
<option value="">전체 작업장</option>
|
|
</select>
|
|
</div>
|
|
<div class="flex gap-2 mb-3">
|
|
<select id="equipmentFilterType" class="input-field flex-1 px-2 py-1.5 rounded-lg text-sm" onchange="filterEquipmentsTkuser()">
|
|
<option value="">전체 유형</option>
|
|
</select>
|
|
<select id="equipmentFilterStatus" class="input-field px-2 py-1.5 rounded-lg text-sm" onchange="filterEquipmentsTkuser()">
|
|
<option value="">전체 상태</option>
|
|
<option value="active">활성</option>
|
|
<option value="maintenance">정비중</option>
|
|
<option value="inactive">비활성</option>
|
|
</select>
|
|
</div>
|
|
<div id="equipmentsListTkuser" class="space-y-2 max-h-[60vh] overflow-y-auto">
|
|
<p class="text-gray-400 text-center py-4 text-sm">탭을 선택하면 데이터를 불러옵니다.</p>
|
|
</div>
|
|
</div>
|
|
<!-- 설비 상세 -->
|
|
<div class="lg:col-span-3">
|
|
<div id="equipmentDetailTkuser" class="hidden"></div>
|
|
<div id="equipmentEmptyTkuser" class="text-center text-gray-400 py-16">
|
|
<i class="fas fa-cogs text-4xl mb-3"></i>
|
|
<p>설비를 선택하면 상세 정보를 볼 수 있습니다</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</main>
|
|
|
|
<!-- 사용자 편집 모달 -->
|
|
<div id="editUserModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-md w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-base font-semibold text-gray-900">사용자 정보 수정</h3>
|
|
<button onclick="closeEditModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="editUserForm" class="space-y-3">
|
|
<input type="hidden" id="editUserId">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">사용자 ID</label>
|
|
<input type="text" id="editUsername" class="input-field w-full px-3 py-1.5 rounded-lg text-sm bg-gray-50" readonly>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">이름</label>
|
|
<input type="text" id="editFullName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">부서</label>
|
|
<select id="editDepartmentId" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">권한</label>
|
|
<select id="editRole" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="user">사용자</option>
|
|
<option value="admin">관리자</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">입사일</label>
|
|
<input type="date" id="editHireDate" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">퇴사일</label>
|
|
<input type="date" id="editResignedDate" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-3 pt-3">
|
|
<button type="button" onclick="closeEditModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-save mr-1"></i>저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 프로젝트 편집 모달 -->
|
|
<div id="editProjectModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-md w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-base font-semibold text-gray-900">프로젝트 수정</h3>
|
|
<button onclick="closeProjectModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="editProjectForm" class="space-y-3">
|
|
<input type="hidden" id="editProjectId">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">Job No</label>
|
|
<input type="text" id="editJobNo" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">프로젝트명</label>
|
|
<input type="text" id="editProjectName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" required>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">계약일</label>
|
|
<input type="date" id="editContractDate" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">납기일</label>
|
|
<input type="date" id="editDueDate" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">제품유형</label>
|
|
<select id="editProductType" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">현장</label>
|
|
<input type="text" id="editSite" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">PM</label>
|
|
<input type="text" id="editPm" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">상태</label>
|
|
<select id="editProjectStatus" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="active">진행중</option>
|
|
<option value="completed">완료</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">활성</label>
|
|
<select id="editIsActive" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="1">활성</option>
|
|
<option value="0">비활성</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-3 pt-3">
|
|
<button type="button" onclick="closeProjectModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-save mr-1"></i>저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 작업자 편집 모달 -->
|
|
<div id="editWorkerModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-md w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-base font-semibold text-gray-900">작업자 정보 수정</h3>
|
|
<button onclick="closeWorkerModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="editWorkerForm" class="space-y-3">
|
|
<input type="hidden" id="editWorkerId">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">이름</label>
|
|
<input type="text" id="editWorkerName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" required>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">직종</label>
|
|
<select id="editJobType" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
<option value="leader">반장</option>
|
|
<option value="worker">작업자</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">부서</label>
|
|
<select id="editWorkerDept" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">연락처</label>
|
|
<input type="text" id="editWorkerPhone" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">입사일</label>
|
|
<input type="date" id="editWorkerHireDate" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">메모</label>
|
|
<input type="text" id="editWorkerNotes" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">상태</label>
|
|
<select id="editWorkerStatus" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="active">재직</option>
|
|
<option value="inactive">비활성</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">재직 상태</label>
|
|
<select id="editEmploymentStatus" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="employed">재직</option>
|
|
<option value="resigned">퇴직</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-3 pt-3">
|
|
<button type="button" onclick="closeWorkerModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-save mr-1"></i>저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 부서 편집 모달 -->
|
|
<div id="editDepartmentModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-md w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-base font-semibold text-gray-900">부서 수정</h3>
|
|
<button onclick="closeDepartmentModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="editDepartmentForm" class="space-y-3">
|
|
<input type="hidden" id="editDeptId">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">부서명</label>
|
|
<input type="text" id="editDeptName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설명</label>
|
|
<input type="text" id="editDeptDescription" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">표시순서</label>
|
|
<input type="number" id="editDeptOrder" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" min="0">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">팀장</label>
|
|
<select id="editDeptLeader" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">미지정</option>
|
|
</select>
|
|
<p class="text-xs text-gray-400 mt-1">타부서 임원 등도 선택 가능</p>
|
|
</div>
|
|
<div class="flex gap-3 pt-3">
|
|
<button type="button" onclick="closeDepartmentModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-save mr-1"></i>저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 승인권한 추가 모달 -->
|
|
<div id="approvalAuthorityModal" class="modal-overlay fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-sm w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-base font-semibold text-gray-900">승인권한 추가</h3>
|
|
<button onclick="closeApprovalModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="approvalAuthorityForm" class="space-y-3">
|
|
<input type="hidden" id="approvalDeptId">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">승인 유형 <span class="text-red-400">*</span></label>
|
|
<select id="approvalType" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" required>
|
|
<option value="">선택</option>
|
|
<option value="VACATION">휴가</option>
|
|
<option value="PURCHASE">구매</option>
|
|
<option value="DOCUMENT">문서</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">승인자 <span class="text-red-400">*</span></label>
|
|
<select id="approvalUserId" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" required>
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">순서</label>
|
|
<input type="number" id="approvalOrder" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" value="1" min="1">
|
|
</div>
|
|
<div class="flex gap-3 pt-2">
|
|
<button type="button" onclick="closeApprovalModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-save mr-1"></i>저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 이슈 카테고리 수정 모달 -->
|
|
<div id="editIssueCategoryModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-md w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-base font-semibold text-gray-900">카테고리 수정</h3>
|
|
<button onclick="closeIssueCategoryModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="editIssueCategoryForm" class="space-y-3">
|
|
<input type="hidden" id="editIssueCatId">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">카테고리명</label>
|
|
<input type="text" id="editIssueCatName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설명</label>
|
|
<input type="text" id="editIssueCatDesc" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">표시순서</label>
|
|
<input type="number" id="editIssueCatOrder" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" min="0">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">활성</label>
|
|
<select id="editIssueCatActive" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="1">활성</option>
|
|
<option value="0">비활성</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-3 pt-3">
|
|
<button type="button" onclick="closeIssueCategoryModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-save mr-1"></i>저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 이슈 아이템 수정 모달 -->
|
|
<div id="editIssueItemModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-md w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-base font-semibold text-gray-900">아이템 수정</h3>
|
|
<button onclick="closeIssueItemModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="editIssueItemForm" class="space-y-3">
|
|
<input type="hidden" id="editIssueItemId">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">카테고리</label>
|
|
<select id="editIssueItemCategory" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" required>
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">아이템명</label>
|
|
<input type="text" id="editIssueItemName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설명</label>
|
|
<input type="text" id="editIssueItemDesc" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">심각도</label>
|
|
<select id="editIssueItemSeverity" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="low">낮음</option>
|
|
<option value="medium">보통</option>
|
|
<option value="high">높음</option>
|
|
<option value="critical">심각</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">표시순서</label>
|
|
<input type="number" id="editIssueItemOrder" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" min="0">
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">활성</label>
|
|
<select id="editIssueItemActive" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="1">활성</option>
|
|
<option value="0">비활성</option>
|
|
</select>
|
|
</div>
|
|
<div class="flex gap-3 pt-3">
|
|
<button type="button" onclick="closeIssueItemModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-save mr-1"></i>저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 작업장 편집 모달 -->
|
|
<div id="editWorkplaceModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-md w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-base font-semibold text-gray-900">작업장 수정</h3>
|
|
<button onclick="closeWorkplaceModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="editWorkplaceForm" class="space-y-3">
|
|
<input type="hidden" id="editWorkplaceId">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">작업장명</label>
|
|
<input type="text" id="editWorkplaceName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" required>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">공장</label>
|
|
<select id="editWorkplaceCategory" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">용도</label>
|
|
<select id="editWorkplacePurpose" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
<option value="작업구역">작업구역</option>
|
|
<option value="창고">창고</option>
|
|
<option value="설비">설비</option>
|
|
<option value="휴게시설">휴게시설</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설명</label>
|
|
<input type="text" id="editWorkplaceDesc" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">우선순위</label>
|
|
<input type="number" id="editWorkplacePriority" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" min="0">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">활성</label>
|
|
<select id="editWorkplaceActive" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="1">활성</option>
|
|
<option value="0">비활성</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-3 pt-3">
|
|
<button type="button" onclick="closeWorkplaceModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-save mr-1"></i>저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 작업장 추가 모달 -->
|
|
<div id="addWorkplaceModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-md w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-base font-semibold text-gray-900"><i class="fas fa-building text-slate-400 mr-2"></i>작업장 등록</h3>
|
|
<button onclick="closeAddWorkplaceModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="addWorkplaceForm" class="space-y-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">작업장명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="newWorkplaceName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="작업장 이름" required>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">공장</label>
|
|
<select id="newWorkplaceCategory" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">용도</label>
|
|
<select id="newWorkplacePurpose" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
<option value="작업구역">작업구역</option>
|
|
<option value="창고">창고</option>
|
|
<option value="설비">설비</option>
|
|
<option value="휴게시설">휴게시설</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설명</label>
|
|
<input type="text" id="newWorkplaceDesc" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="작업장 설명">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">우선순위</label>
|
|
<input type="number" id="newWorkplacePriority" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" value="0" min="0">
|
|
</div>
|
|
<div class="flex gap-3 pt-3">
|
|
<button type="button" onclick="closeAddWorkplaceModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-plus mr-1"></i>추가</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 구역지도 설정 모달 -->
|
|
<div id="layoutMapModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4" style="display:none;">
|
|
<div class="bg-white rounded-xl w-full max-w-4xl max-h-[90vh] overflow-y-auto p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-base font-semibold text-gray-900"><i class="fas fa-map mr-2 text-slate-400"></i>구역지도 설정</h3>
|
|
<button onclick="closeLayoutMapModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
|
|
<!-- 이미지 업로드 -->
|
|
<div class="mb-5 p-4 bg-gray-50 rounded-lg">
|
|
<h4 class="text-sm font-semibold text-gray-700 mb-3">레이아웃 이미지</h4>
|
|
<div id="currentLayoutImage" class="mb-3">
|
|
<span class="text-sm text-gray-400">업로드된 이미지가 없습니다</span>
|
|
</div>
|
|
<div class="flex items-center gap-3">
|
|
<input type="file" id="layoutImageFile" accept="image/jpeg,image/png,image/gif,image/webp" onchange="previewLayoutImage(event)" class="text-sm text-gray-500 file:mr-3 file:py-1.5 file:px-3 file:rounded-lg file:border-0 file:text-sm file:bg-slate-100 file:text-slate-700 hover:file:bg-slate-200">
|
|
<button onclick="uploadLayoutImage()" class="px-4 py-1.5 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium whitespace-nowrap">
|
|
<i class="fas fa-upload mr-1"></i>이미지 업로드
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 캔버스 영역 -->
|
|
<div class="mb-5">
|
|
<h4 class="text-sm font-semibold text-gray-700 mb-3">영역 그리기 <span class="text-xs text-gray-400 font-normal">(캔버스 위에서 드래그하여 사각형 영역을 그리세요)</span></h4>
|
|
<canvas id="regionCanvas" style="border:1px solid #e2e8f0; border-radius:8px; cursor:crosshair; max-width:100%;"></canvas>
|
|
</div>
|
|
|
|
<!-- 작업장 선택 + 저장 -->
|
|
<div class="mb-5 flex items-center gap-3 flex-wrap">
|
|
<select id="regionWorkplaceSelect" class="input-field px-3 py-1.5 rounded-lg text-sm min-w-[200px]">
|
|
<option value="">작업장을 선택하세요</option>
|
|
</select>
|
|
<button onclick="saveRegion()" class="px-4 py-1.5 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 text-sm font-medium">
|
|
<i class="fas fa-save mr-1"></i>영역 저장
|
|
</button>
|
|
<button onclick="clearCurrentRegion()" class="px-4 py-1.5 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">
|
|
<i class="fas fa-eraser mr-1"></i>초기화
|
|
</button>
|
|
</div>
|
|
|
|
<!-- 등록된 영역 목록 -->
|
|
<div>
|
|
<h4 class="text-sm font-semibold text-gray-700 mb-3">등록된 영역</h4>
|
|
<div id="regionList">
|
|
<p class="text-sm text-gray-400 text-center py-4">정의된 영역이 없습니다</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 설비 추가/편집 모달 -->
|
|
<div id="equipmentModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-lg w-full p-6 max-h-[90vh] overflow-y-auto">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 id="eqModalTitle" class="text-base font-semibold text-gray-900">설비 추가</h3>
|
|
<button onclick="closeEquipmentModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="equipmentForm" class="space-y-3">
|
|
<input type="hidden" id="eqEditId">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">관리번호 <span class="text-red-400">*</span></label>
|
|
<div class="flex gap-1">
|
|
<input type="text" id="eqCode" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="TKP-001" required>
|
|
<button type="button" onclick="generateEquipmentCode()" class="px-2 py-1.5 bg-gray-100 hover:bg-gray-200 rounded-lg text-xs text-gray-600 whitespace-nowrap" title="자동생성"><i class="fas fa-magic"></i></button>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설비명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="eqName" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="설비 이름" required>
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">유형</label>
|
|
<input type="text" id="eqType" list="eqTypeDatalist" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="유형 선택/입력">
|
|
<datalist id="eqTypeDatalist"></datalist>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">상태</label>
|
|
<select id="eqStatus" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<option value="active">가동중</option>
|
|
<option value="maintenance">점검중</option>
|
|
<option value="inactive">비활성</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">제조사</label>
|
|
<input type="text" id="eqManufacturer" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="제조사">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">모델명</label>
|
|
<input type="text" id="eqModel" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="모델명">
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">공급업체</label>
|
|
<input type="text" id="eqSupplier" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="공급업체">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">구매가격</label>
|
|
<input type="number" id="eqPrice" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="0" min="0">
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설치일</label>
|
|
<input type="date" id="eqInstallDate" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">시리얼번호</label>
|
|
<input type="text" id="eqSerial" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="시리얼번호">
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">사양</label>
|
|
<input type="text" id="eqSpecs" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="사양 정보">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">비고</label>
|
|
<input type="text" id="eqNotes" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" placeholder="비고">
|
|
</div>
|
|
<div class="flex gap-3 pt-3">
|
|
<button type="button" onclick="closeEquipmentModal()" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 text-sm">취소</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 text-sm font-medium"><i class="fas fa-save mr-1"></i>저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 설비 상세 모달 -->
|
|
<div id="eqDetailModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-base font-semibold text-gray-900"><i class="fas fa-cog text-slate-400 mr-2"></i><span id="eqDetailTitle">설비 상세</span></h3>
|
|
<button onclick="closeEqDetailModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<div id="eqDetailContent"></div>
|
|
<!-- 사진 -->
|
|
<div class="mt-4 border-t pt-4">
|
|
<div class="flex items-center justify-between mb-2">
|
|
<h4 class="text-sm font-semibold text-gray-700"><i class="fas fa-camera text-gray-400 mr-1"></i>설비 사진</h4>
|
|
<label class="px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs cursor-pointer">
|
|
<i class="fas fa-plus mr-1"></i>사진 추가
|
|
<input type="file" id="eqPhotoFile" accept="image/*" onchange="uploadEqPhoto()" class="hidden">
|
|
</label>
|
|
</div>
|
|
<div id="eqPhotoGrid" class="grid grid-cols-4 gap-2">
|
|
<p class="text-gray-400 text-xs col-span-4 text-center py-2">사진 없음</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ 협력업체 탭 ============ -->
|
|
<div id="tab-partners" class="hidden">
|
|
<div class="grid lg:grid-cols-5 gap-6">
|
|
<!-- 업체 목록 -->
|
|
<div class="lg:col-span-2 bg-white rounded-xl shadow-sm p-5">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h2 class="text-base font-semibold text-gray-800"><i class="fas fa-building text-emerald-500 mr-2"></i>협력업체</h2>
|
|
<button id="btnAddPartnerTkuser" onclick="openAddPartnerTkuser()" class="hidden px-3 py-1.5 bg-slate-700 text-white rounded-lg text-xs hover:bg-slate-800">
|
|
<i class="fas fa-plus mr-1"></i>업체 등록
|
|
</button>
|
|
</div>
|
|
<div class="flex gap-2 mb-3">
|
|
<input type="text" id="partnerSearchTkuser" class="input-field flex-1 px-3 py-1.5 rounded-lg text-sm" placeholder="업체명/사업자번호 검색">
|
|
<select id="partnerFilterActiveTkuser" class="input-field px-2 py-1.5 rounded-lg text-sm">
|
|
<option value="true">활성</option>
|
|
<option value="">전체</option>
|
|
<option value="false">비활성</option>
|
|
</select>
|
|
</div>
|
|
<div id="partnersListTkuser" class="space-y-2 max-h-[65vh] overflow-y-auto">
|
|
<p class="text-gray-400 text-center py-4 text-sm">탭을 선택하면 데이터를 불러옵니다.</p>
|
|
</div>
|
|
</div>
|
|
<!-- 업체 상세 -->
|
|
<div class="lg:col-span-3">
|
|
<div id="partnerDetailTkuser" class="hidden"></div>
|
|
<div id="partnerEmptyTkuser" class="text-center text-gray-400 py-16">
|
|
<i class="fas fa-building text-4xl mb-3"></i>
|
|
<p>업체를 선택하면 상세 정보를 볼 수 있습니다</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ 업체(공급업체) 탭 ============ -->
|
|
<div id="tab-vendors" class="hidden">
|
|
<div class="grid lg:grid-cols-5 gap-6">
|
|
<!-- 업체 목록 -->
|
|
<div class="lg:col-span-2 bg-white rounded-xl shadow-sm p-5">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h2 class="text-base font-semibold text-gray-800"><i class="fas fa-store text-indigo-500 mr-2"></i>업체 (공급업체)</h2>
|
|
<button id="btnAddVendorTkuser" onclick="openAddVendorTkuser()" class="hidden px-3 py-1.5 bg-slate-700 text-white rounded-lg text-xs hover:bg-slate-800">
|
|
<i class="fas fa-plus mr-1"></i>업체 등록
|
|
</button>
|
|
</div>
|
|
<div class="flex gap-2 mb-3">
|
|
<input type="text" id="vendorSearchTkuser" class="input-field flex-1 px-3 py-1.5 rounded-lg text-sm" placeholder="업체명/사업자번호/담당자 검색">
|
|
<select id="vendorFilterActiveTkuser" class="input-field px-2 py-1.5 rounded-lg text-sm">
|
|
<option value="true">활성</option>
|
|
<option value="">전체</option>
|
|
<option value="false">비활성</option>
|
|
</select>
|
|
</div>
|
|
<div id="vendorsListTkuser" class="space-y-2 max-h-[65vh] overflow-y-auto">
|
|
<p class="text-gray-400 text-center py-4 text-sm">탭을 선택하면 데이터를 불러옵니다.</p>
|
|
</div>
|
|
</div>
|
|
<!-- 업체 상세 -->
|
|
<div class="lg:col-span-3">
|
|
<div id="vendorDetailTkuser" class="hidden"></div>
|
|
<div id="vendorEmptyTkuser" class="text-center text-gray-400 py-16">
|
|
<i class="fas fa-store text-4xl mb-3"></i>
|
|
<p>업체를 선택하면 상세 정보를 볼 수 있습니다</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ 소모품 탭 ============ -->
|
|
<div id="tab-consumables" class="hidden">
|
|
<div class="bg-white rounded-xl shadow-sm p-5">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h2 class="text-base font-semibold text-gray-800"><i class="fas fa-box-open text-teal-500 mr-2"></i>소모품 마스터</h2>
|
|
<button id="btnAddConsumableTkuser" onclick="openAddConsumableTkuser()" class="hidden px-3 py-1.5 bg-slate-700 text-white rounded-lg text-xs hover:bg-slate-800">
|
|
<i class="fas fa-plus mr-1"></i>소모품 등록
|
|
</button>
|
|
</div>
|
|
<div class="flex gap-2 mb-4 flex-wrap">
|
|
<input type="text" id="consumableSearchTkuser" class="input-field flex-1 min-w-[160px] px-3 py-1.5 rounded-lg text-sm" placeholder="품명/메이커 검색">
|
|
<select id="consumableFilterCategoryTkuser" class="input-field px-2 py-1.5 rounded-lg text-sm">
|
|
<option value="">전체 분류</option>
|
|
</select>
|
|
<select id="consumableFilterActiveTkuser" class="input-field px-2 py-1.5 rounded-lg text-sm">
|
|
<option value="true">활성</option>
|
|
<option value="">전체</option>
|
|
<option value="false">비활성</option>
|
|
</select>
|
|
</div>
|
|
<div id="consumablesListTkuser">
|
|
<p class="text-gray-400 text-center py-4 text-sm">탭을 선택하면 데이터를 불러옵니다.</p>
|
|
</div>
|
|
</div>
|
|
<!-- 카테고리 관리 (admin) -->
|
|
<div id="categoryManageSection" class="hidden bg-white rounded-xl shadow-sm p-5 mt-4">
|
|
<div class="flex items-center justify-between mb-3">
|
|
<h3 class="text-sm font-semibold text-gray-700"><i class="fas fa-tags text-teal-500 mr-1"></i>카테고리 관리</h3>
|
|
<button onclick="addCategory()" class="px-2 py-1 bg-teal-600 text-white rounded text-xs hover:bg-teal-700"><i class="fas fa-plus mr-1"></i>추가</button>
|
|
</div>
|
|
<div id="categoryList" class="space-y-2"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ 알림 수신자 탭 ============ -->
|
|
<div id="tab-notificationRecipients" class="hidden">
|
|
<div class="mb-4">
|
|
<h2 class="text-base font-semibold text-gray-800"><i class="fas fa-bell text-slate-500 mr-2"></i>알림 수신자 관리</h2>
|
|
<p class="text-xs text-gray-400 mt-1">알림 유형별로 수신자를 관리합니다. 각 유형의 이벤트 발생 시 등록된 사용자에게 알림이 전달됩니다.</p>
|
|
</div>
|
|
<div id="nrContent">
|
|
<p class="text-gray-400 text-center py-8 text-sm">탭을 선택하면 데이터를 불러옵니다.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 수신자 추가 모달 -->
|
|
<div id="nrAddModal" class="hidden fixed inset-0 bg-black bg-opacity-40 z-50 flex items-center justify-center p-4" onclick="if(event.target===this)closeNrAddModal()">
|
|
<div class="bg-white rounded-xl shadow-xl max-w-md w-full p-6">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 id="nrAddModalTitle" class="text-lg font-semibold">수신자 추가</h3>
|
|
<button onclick="closeNrAddModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<div id="nrAddUserList" class="max-h-[50vh] overflow-y-auto space-y-1 mb-4"></div>
|
|
<div class="flex justify-end gap-2">
|
|
<button type="button" onclick="closeNrAddModal()" class="px-4 py-2 border rounded-lg text-sm hover:bg-gray-50">취소</button>
|
|
<button type="button" onclick="submitNrAdd()" class="px-4 py-2 bg-slate-700 text-white rounded-lg text-sm hover:bg-slate-800">추가</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ntfy 구독 추가 모달 -->
|
|
<div id="ntfyAddModal" class="hidden fixed inset-0 bg-black bg-opacity-40 z-50 flex items-center justify-center p-4" onclick="if(event.target===this)closeNtfyAddModal()">
|
|
<div class="bg-white rounded-xl shadow-xl max-w-md w-full p-6">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="text-lg font-semibold">ntfy 구독 등록</h3>
|
|
<button onclick="closeNtfyAddModal()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<div class="bg-amber-50 border border-amber-200 rounded-lg p-3 mb-4">
|
|
<p class="text-xs text-amber-700"><i class="fas fa-info-circle mr-1"></i>등록된 사용자가 실제로 알림을 받으려면 ntfy 앱을 설치하고 본인 토픽을 구독해야 합니다. 앱 설정은 각 사용자가 알림 벨의 ntfy 버튼을 통해 안내받을 수 있습니다.</p>
|
|
</div>
|
|
<div id="ntfyAddUserList" class="max-h-[50vh] overflow-y-auto space-y-1 mb-4"></div>
|
|
<div class="flex justify-end gap-2">
|
|
<button type="button" onclick="closeNtfyAddModal()" class="px-4 py-2 border rounded-lg text-sm hover:bg-gray-50">취소</button>
|
|
<button type="button" onclick="submitNtfyAdd()" class="px-4 py-2 bg-blue-600 text-white rounded-lg text-sm hover:bg-blue-700">등록</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 협력업체 등록 모달 -->
|
|
<div id="addPartnerModalTkuser" class="hidden fixed inset-0 bg-black bg-opacity-40 z-50 flex items-center justify-center p-4" onclick="if(event.target===this)closeAddPartnerTkuser()">
|
|
<div class="bg-white rounded-xl shadow-xl max-w-lg w-full p-6">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="text-lg font-semibold">협력업체 등록</h3>
|
|
<button onclick="closeAddPartnerTkuser()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="addPartnerFormTkuser">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">업체명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="newPartnerCompanyNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">사업자번호</label>
|
|
<input type="text" id="newPartnerBusinessNumberTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" placeholder="000-00-00000">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">대표자</label>
|
|
<input type="text" id="newPartnerRepresentativeTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">담당자명</label>
|
|
<input type="text" id="newPartnerContactNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">담당자 연락처</label>
|
|
<input type="text" id="newPartnerContactPhoneTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">주소</label>
|
|
<input type="text" id="newPartnerAddressTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">업종 (콤마 구분)</label>
|
|
<input type="text" id="newPartnerBusinessTypeTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" placeholder="배관, 용접">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">산재보험 관리번호</label>
|
|
<input type="text" id="newPartnerInsuranceNumberTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">산재보험 만료일</label>
|
|
<input type="date" id="newPartnerInsuranceExpiryTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">비고</label>
|
|
<input type="text" id="newPartnerNotesTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end mt-4 gap-2">
|
|
<button type="button" onclick="closeAddPartnerTkuser()" class="px-4 py-2 border rounded-lg text-sm hover:bg-gray-50">취소</button>
|
|
<button type="submit" class="px-4 py-2 bg-slate-700 text-white rounded-lg text-sm hover:bg-slate-800">등록</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 협력업체 수정 모달 -->
|
|
<div id="editPartnerModalTkuser" class="hidden fixed inset-0 bg-black bg-opacity-40 z-50 flex items-center justify-center p-4" onclick="if(event.target===this)closeEditPartnerTkuser()">
|
|
<div class="bg-white rounded-xl shadow-xl max-w-lg w-full p-6">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="text-lg font-semibold">협력업체 수정</h3>
|
|
<button onclick="closeEditPartnerTkuser()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="editPartnerFormTkuser">
|
|
<input type="hidden" id="editPartnerIdTkuser">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">업체명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="editPartnerCompanyNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">사업자번호</label>
|
|
<input type="text" id="editPartnerBusinessNumberTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">대표자</label>
|
|
<input type="text" id="editPartnerRepresentativeTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">담당자명</label>
|
|
<input type="text" id="editPartnerContactNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">담당자 연락처</label>
|
|
<input type="text" id="editPartnerContactPhoneTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">주소</label>
|
|
<input type="text" id="editPartnerAddressTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">업종 (콤마 구분)</label>
|
|
<input type="text" id="editPartnerBusinessTypeTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">산재보험 관리번호</label>
|
|
<input type="text" id="editPartnerInsuranceNumberTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">산재보험 만료일</label>
|
|
<input type="date" id="editPartnerInsuranceExpiryTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">비고</label>
|
|
<input type="text" id="editPartnerNotesTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end mt-4 gap-2">
|
|
<button type="button" onclick="closeEditPartnerTkuser()" class="px-4 py-2 border rounded-lg text-sm hover:bg-gray-50">취소</button>
|
|
<button type="submit" class="px-4 py-2 bg-slate-700 text-white rounded-lg text-sm hover:bg-slate-800">저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 작업자 등록 모달 -->
|
|
<div id="addWorkerModalTkuser" class="hidden fixed inset-0 bg-black bg-opacity-40 z-50 flex items-center justify-center p-4" onclick="if(event.target===this)closeAddWorkerTkuser()">
|
|
<div class="bg-white rounded-xl shadow-xl max-w-md w-full p-6">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="text-lg font-semibold">작업자 등록</h3>
|
|
<button onclick="closeAddWorkerTkuser()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="addWorkerFormTkuser">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">성명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="newWorkerNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">직위</label>
|
|
<input type="text" id="newWorkerPositionTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div class="flex items-end pb-1">
|
|
<label class="flex items-center gap-2 cursor-pointer">
|
|
<input type="checkbox" id="newWorkerIsLeaderTkuser" class="h-4 w-4 text-slate-600 rounded">
|
|
<span class="text-sm">팀장급</span>
|
|
</label>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">연락처</label>
|
|
<input type="text" id="newWorkerPhoneTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" placeholder="팀장급 필수">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">안전교육 이수일</label>
|
|
<input type="date" id="newWorkerSafetyDateTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">비고</label>
|
|
<input type="text" id="newWorkerNotesTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end mt-4 gap-2">
|
|
<button type="button" onclick="closeAddWorkerTkuser()" class="px-4 py-2 border rounded-lg text-sm hover:bg-gray-50">취소</button>
|
|
<button type="submit" class="px-4 py-2 bg-slate-700 text-white rounded-lg text-sm hover:bg-slate-800">등록</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 작업자 수정 모달 -->
|
|
<div id="editWorkerModalTkuser" class="hidden fixed inset-0 bg-black bg-opacity-40 z-50 flex items-center justify-center p-4" onclick="if(event.target===this)closeEditWorkerTkuser()">
|
|
<div class="bg-white rounded-xl shadow-xl max-w-md w-full p-6">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="text-lg font-semibold">작업자 수정</h3>
|
|
<button onclick="closeEditWorkerTkuser()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="editWorkerFormTkuser">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">성명</label>
|
|
<input type="text" id="editWorkerNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">직위</label>
|
|
<input type="text" id="editWorkerPositionTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div class="flex items-end pb-1">
|
|
<label class="flex items-center gap-2 cursor-pointer">
|
|
<input type="checkbox" id="editWorkerIsLeaderTkuser" class="h-4 w-4 text-slate-600 rounded">
|
|
<span class="text-sm">팀장급</span>
|
|
</label>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">연락처</label>
|
|
<input type="text" id="editWorkerPhoneTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">안전교육 이수일</label>
|
|
<input type="date" id="editWorkerSafetyDateTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">비고</label>
|
|
<input type="text" id="editWorkerNotesTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end mt-4 gap-2">
|
|
<button type="button" onclick="closeEditWorkerTkuser()" class="px-4 py-2 border rounded-lg text-sm hover:bg-gray-50">취소</button>
|
|
<button type="submit" class="px-4 py-2 bg-slate-700 text-white rounded-lg text-sm hover:bg-slate-800">저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 업체 등록 모달 -->
|
|
<div id="addVendorModalTkuser" class="hidden fixed inset-0 bg-black bg-opacity-40 z-50 flex items-center justify-center p-4" onclick="if(event.target===this)closeAddVendorTkuser()">
|
|
<div class="bg-white rounded-xl shadow-xl max-w-lg w-full p-6">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="text-lg font-semibold">업체 등록</h3>
|
|
<button onclick="closeAddVendorTkuser()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="addVendorFormTkuser">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">업체명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="newVendorNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">사업자번호</label>
|
|
<input type="text" id="newVendorBizNumTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" placeholder="000-00-00000">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">대표자</label>
|
|
<input type="text" id="newVendorRepTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">담당자명</label>
|
|
<input type="text" id="newVendorContactNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">담당자 연락처</label>
|
|
<input type="text" id="newVendorContactPhoneTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">주소</label>
|
|
<input type="text" id="newVendorAddressTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">은행명</label>
|
|
<input type="text" id="newVendorBankNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">계좌번호</label>
|
|
<input type="text" id="newVendorBankAccountTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">비고</label>
|
|
<input type="text" id="newVendorNotesTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end mt-4 gap-2">
|
|
<button type="button" onclick="closeAddVendorTkuser()" class="px-4 py-2 border rounded-lg text-sm hover:bg-gray-50">취소</button>
|
|
<button type="submit" class="px-4 py-2 bg-slate-700 text-white rounded-lg text-sm hover:bg-slate-800">등록</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 업체 수정 모달 -->
|
|
<div id="editVendorModalTkuser" class="hidden fixed inset-0 bg-black bg-opacity-40 z-50 flex items-center justify-center p-4" onclick="if(event.target===this)closeEditVendorTkuser()">
|
|
<div class="bg-white rounded-xl shadow-xl max-w-lg w-full p-6">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="text-lg font-semibold">업체 수정</h3>
|
|
<button onclick="closeEditVendorTkuser()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="editVendorFormTkuser">
|
|
<input type="hidden" id="editVendorIdTkuser">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">업체명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="editVendorNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">사업자번호</label>
|
|
<input type="text" id="editVendorBizNumTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">대표자</label>
|
|
<input type="text" id="editVendorRepTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">담당자명</label>
|
|
<input type="text" id="editVendorContactNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">담당자 연락처</label>
|
|
<input type="text" id="editVendorContactPhoneTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">주소</label>
|
|
<input type="text" id="editVendorAddressTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">은행명</label>
|
|
<input type="text" id="editVendorBankNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">계좌번호</label>
|
|
<input type="text" id="editVendorBankAccountTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">비고</label>
|
|
<input type="text" id="editVendorNotesTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end mt-4 gap-2">
|
|
<button type="button" onclick="closeEditVendorTkuser()" class="px-4 py-2 border rounded-lg text-sm hover:bg-gray-50">취소</button>
|
|
<button type="submit" class="px-4 py-2 bg-slate-700 text-white rounded-lg text-sm hover:bg-slate-800">저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 소모품 등록 모달 -->
|
|
<div id="addConsumableModalTkuser" class="hidden fixed inset-0 bg-black bg-opacity-40 z-50 flex items-center justify-center p-4" onclick="if(event.target===this)closeAddConsumableTkuser()">
|
|
<div class="bg-white rounded-xl shadow-xl max-w-lg w-full p-6">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="text-lg font-semibold">소모품 등록</h3>
|
|
<button onclick="closeAddConsumableTkuser()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="addConsumableFormTkuser">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">품명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="newConsumableNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">규격</label>
|
|
<input type="text" id="newConsumableSpecTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" placeholder='예: 4" 용접, M16, 면(500G)-10게이지'>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">메이커</label>
|
|
<input type="text" id="newConsumableMakerTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">분류 <span class="text-red-400">*</span></label>
|
|
<select id="newConsumableCategoryTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
<option value="">선택</option>
|
|
<option value="consumable">소모품</option>
|
|
<option value="safety">안전용품</option>
|
|
<option value="repair">수선비</option>
|
|
<option value="equipment">설비</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">기준가격</label>
|
|
<input type="number" id="newConsumablePriceTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" min="0">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">단위</label>
|
|
<input type="text" id="newConsumableUnitTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" value="EA">
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">사진</label>
|
|
<input type="file" id="newConsumablePhotoTkuser" accept="image/jpeg,image/png,image/webp" onchange="previewAddConsumablePhoto()" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<div id="addConsumablePhotoPreviewTkuser" class="mt-2"></div>
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end mt-4 gap-2">
|
|
<button type="button" onclick="closeAddConsumableTkuser()" class="px-4 py-2 border rounded-lg text-sm hover:bg-gray-50">취소</button>
|
|
<button type="submit" class="px-4 py-2 bg-slate-700 text-white rounded-lg text-sm hover:bg-slate-800">등록</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 소모품 수정 모달 -->
|
|
<div id="editConsumableModalTkuser" class="hidden fixed inset-0 bg-black bg-opacity-40 z-50 flex items-center justify-center p-4" onclick="if(event.target===this)closeEditConsumableTkuser()">
|
|
<div class="bg-white rounded-xl shadow-xl max-w-lg w-full p-6">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="text-lg font-semibold">소모품 수정</h3>
|
|
<button onclick="closeEditConsumableTkuser()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="editConsumableFormTkuser">
|
|
<input type="hidden" id="editConsumableIdTkuser">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">품명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="editConsumableNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">규격</label>
|
|
<input type="text" id="editConsumableSpecTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" placeholder='예: 4" 용접, M16, 면(500G)-10게이지'>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">메이커</label>
|
|
<input type="text" id="editConsumableMakerTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">분류 <span class="text-red-400">*</span></label>
|
|
<select id="editConsumableCategoryTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
<option value="consumable">소모품</option>
|
|
<option value="safety">안전용품</option>
|
|
<option value="repair">수선비</option>
|
|
<option value="equipment">설비</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">기준가격</label>
|
|
<input type="number" id="editConsumablePriceTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" min="0">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">단위</label>
|
|
<input type="text" id="editConsumableUnitTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">사진</label>
|
|
<input type="file" id="editConsumablePhotoTkuser" accept="image/jpeg,image/png,image/webp" onchange="previewEditConsumablePhoto()" class="input-field w-full px-3 py-1.5 rounded-lg text-sm">
|
|
<div id="editConsumablePhotoPreviewTkuser" class="mt-2"></div>
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end mt-4 gap-2">
|
|
<button type="button" onclick="closeEditConsumableTkuser()" class="px-4 py-2 border rounded-lg text-sm hover:bg-gray-50">취소</button>
|
|
<button type="submit" class="px-4 py-2 bg-slate-700 text-white rounded-lg text-sm hover:bg-slate-800">저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 설비 등록 모달 -->
|
|
<div id="addEquipmentModalTkuser" class="hidden fixed inset-0 bg-black bg-opacity-40 z-50 flex items-center justify-center p-4" onclick="if(event.target===this)closeAddEquipmentTkuser()">
|
|
<div class="bg-white rounded-xl shadow-xl max-w-lg w-full p-6 max-h-[90vh] overflow-y-auto">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="text-lg font-semibold">설비 등록</h3>
|
|
<button onclick="closeAddEquipmentTkuser()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="addEquipmentFormTkuser">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">관리번호 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="newEquipmentCodeTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설비명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="newEquipmentNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설비유형</label>
|
|
<input type="text" id="newEquipmentTypeTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" placeholder="예: 용접기, 절단기">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">작업장</label>
|
|
<select id="newEquipmentWorkplaceTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">제조사</label>
|
|
<input type="text" id="newEquipmentManufacturerTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">모델명</label>
|
|
<input type="text" id="newEquipmentModelTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">시리얼번호</label>
|
|
<input type="text" id="newEquipmentSerialTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설치일</label>
|
|
<input type="date" id="newEquipmentInstallDateTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">공급업체</label>
|
|
<input type="text" id="newEquipmentSupplierTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">구매가격</label>
|
|
<input type="number" id="newEquipmentPriceTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" min="0">
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">상태</label>
|
|
<select id="newEquipmentStatusTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
<option value="active">활성</option>
|
|
<option value="maintenance">정비중</option>
|
|
<option value="inactive">비활성</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">사양</label>
|
|
<textarea id="newEquipmentSpecsTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" rows="2"></textarea>
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">비고</label>
|
|
<textarea id="newEquipmentNotesTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" rows="2"></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end mt-4 gap-2">
|
|
<button type="button" onclick="closeAddEquipmentTkuser()" class="px-4 py-2 border rounded-lg text-sm hover:bg-gray-50">취소</button>
|
|
<button type="submit" class="px-4 py-2 bg-slate-700 text-white rounded-lg text-sm hover:bg-slate-800">등록</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 설비 수정 모달 -->
|
|
<div id="editEquipmentModalTkuser" class="hidden fixed inset-0 bg-black bg-opacity-40 z-50 flex items-center justify-center p-4" onclick="if(event.target===this)closeEditEquipmentTkuser()">
|
|
<div class="bg-white rounded-xl shadow-xl max-w-lg w-full p-6 max-h-[90vh] overflow-y-auto">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="text-lg font-semibold">설비 수정</h3>
|
|
<button onclick="closeEditEquipmentTkuser()" class="text-gray-400 hover:text-gray-600"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<form id="editEquipmentFormTkuser">
|
|
<input type="hidden" id="editEquipmentIdTkuser">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">관리번호 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="editEquipmentCodeTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설비명 <span class="text-red-400">*</span></label>
|
|
<input type="text" id="editEquipmentNameTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" required>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설비유형</label>
|
|
<input type="text" id="editEquipmentTypeTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" placeholder="예: 용접기, 절단기">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">작업장</label>
|
|
<select id="editEquipmentWorkplaceTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
<option value="">선택</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">제조사</label>
|
|
<input type="text" id="editEquipmentManufacturerTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">모델명</label>
|
|
<input type="text" id="editEquipmentModelTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">시리얼번호</label>
|
|
<input type="text" id="editEquipmentSerialTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">설치일</label>
|
|
<input type="date" id="editEquipmentInstallDateTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">공급업체</label>
|
|
<input type="text" id="editEquipmentSupplierTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">구매가격</label>
|
|
<input type="number" id="editEquipmentPriceTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" min="0">
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">상태</label>
|
|
<select id="editEquipmentStatusTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm">
|
|
<option value="active">활성</option>
|
|
<option value="maintenance">정비중</option>
|
|
<option value="inactive">비활성</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">사양</label>
|
|
<textarea id="editEquipmentSpecsTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" rows="2"></textarea>
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-xs font-medium text-gray-600 mb-1">비고</label>
|
|
<textarea id="editEquipmentNotesTkuser" class="input-field w-full px-3 py-2 rounded-lg text-sm" rows="2"></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end mt-4 gap-2">
|
|
<button type="button" onclick="closeEditEquipmentTkuser()" class="px-4 py-2 border rounded-lg text-sm hover:bg-gray-50">취소</button>
|
|
<button type="submit" class="px-4 py-2 bg-slate-700 text-white rounded-lg text-sm hover:bg-slate-800">저장</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 사진 확대 모달 -->
|
|
<div id="photoViewModal" class="fixed inset-0 bg-black bg-opacity-80 hidden z-[60] flex items-center justify-center p-4 cursor-pointer" onclick="this.classList.add('hidden')">
|
|
<img id="photoViewImage" class="max-w-full max-h-[90vh] rounded-lg shadow-2xl">
|
|
</div>
|
|
|
|
<!-- JS: Core (config, token, api, toast, helpers, init) -->
|
|
<script src="/static/js/tkuser-core.js?v=2026040101"></script>
|
|
<!-- JS: Tabs -->
|
|
<script src="/static/js/tkuser-tabs.js?v=2026032301"></script>
|
|
<!-- JS: Individual modules -->
|
|
<script src="/static/js/tkuser-users.js?v=2026033001"></script>
|
|
<script src="/static/js/tkuser-projects.js?v=2026032601"></script>
|
|
<script src="/static/js/tkuser-departments.js?v=2026032302"></script>
|
|
<script src="/static/js/tkuser-issue-types.js?v=2026031401"></script>
|
|
<script src="/static/js/tkuser-workplaces.js?v=2026031401"></script>
|
|
<script src="/static/js/tkuser-tasks.js?v=2026031401"></script>
|
|
<script src="/static/js/tkuser-vacations.js?v=2026033105"></script>
|
|
<script src="/static/js/tkuser-vacation-settings.js?v=2026032501"></script>
|
|
<script src="/static/js/tkuser-layout-map.js?v=2026031401"></script>
|
|
<script src="/static/js/tkuser-partners.js?v=2026031601"></script>
|
|
<script src="/static/js/tkuser-vendors.js?v=2026031401"></script>
|
|
<script src="/static/js/tkuser-consumables.js?v=2026031602"></script>
|
|
<script src="/static/js/tkuser-equipments.js?v=2026031701"></script>
|
|
<script src="/static/js/tkuser-notificationRecipients.js?v=2026031701"></script>
|
|
<!-- Boot -->
|
|
<script>init();</script>
|
|
</body>
|
|
</html>
|