fix: 캘린더 모달 중복 카드 문제 및 삭제 권한 개선

- monthly_worker_status 조회 시 GROUP BY로 중복 데이터 합산
- 작업보고서 삭제 권한을 그룹장 이상으로 제한 (admin, system, group_leader)
- 중복 데이터 정리를 위한 마이그레이션 SQL 추가 (009_fix_duplicate_monthly_status.sql)
- synology_deployment 버전에도 동일 수정 적용
This commit is contained in:
Hyungi Ahn
2025-12-02 13:08:44 +09:00
parent beaffcad49
commit a9bce9d20b
419 changed files with 275129 additions and 394 deletions

View File

@@ -0,0 +1,184 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>관리자 설정 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/common.css?v=1">
<link rel="stylesheet" href="/css/admin-settings.css?v=1">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/auth-check.js" defer></script>
</head>
<body>
<div class="work-report-container">
<!-- 네비게이션 바 -->
<div id="navbar-container"></div>
<!-- 헤더 -->
<header class="work-report-header">
<h1>⚙️ 관리자 설정</h1>
<p class="subtitle">시스템 사용자 계정 및 권한을 관리합니다</p>
</header>
<!-- 메인 콘텐츠 -->
<main class="work-report-main">
<!-- 뒤로가기 버튼 -->
<a href="javascript:history.back()" class="back-button">
← 뒤로가기
</a>
<div class="dashboard-main">
<div class="page-header">
<div class="page-title-section">
<h1 class="page-title">
<span class="title-icon">⚙️</span>
관리자 설정
</h1>
<p class="page-description">시스템 사용자 계정 및 권한을 관리합니다</p>
</div>
</div>
<!-- 사용자 관리 섹션 -->
<div class="settings-section">
<div class="section-header">
<h2 class="section-title">
<span class="section-icon">👥</span>
사용자 계정 관리
</h2>
<button class="btn btn-primary" id="addUserBtn">
<span class="btn-icon"></span>
새 사용자 추가
</button>
</div>
<div class="users-container">
<div class="users-header">
<div class="search-box">
<input type="text" id="userSearch" placeholder="사용자 검색..." class="search-input">
<span class="search-icon">🔍</span>
</div>
<div class="filter-buttons">
<button class="filter-btn active" data-filter="all">전체</button>
<button class="filter-btn" data-filter="admin">관리자</button>
<button class="filter-btn" data-filter="leader">그룹장</button>
<button class="filter-btn" data-filter="user">작업자</button>
</div>
</div>
<div class="users-table-container">
<table class="users-table">
<thead>
<tr>
<th>사용자명</th>
<th>아이디</th>
<th>역할</th>
<th>상태</th>
<th>최종 로그인</th>
<th>관리</th>
</tr>
</thead>
<tbody id="usersTableBody">
<!-- 사용자 목록이 여기에 동적으로 생성됩니다 -->
</tbody>
</table>
</div>
<div class="empty-state" id="emptyState" style="display: none;">
<div class="empty-icon">👥</div>
<h3>등록된 사용자가 없습니다</h3>
<p>새 사용자를 추가해보세요.</p>
</div>
</div>
</div>
</div>
</main>
</div>
<!-- 사용자 추가/수정 모달 -->
<div id="userModal" class="modal-overlay" style="display: none;">
<div class="modal-container">
<div class="modal-header">
<h2 id="modalTitle">새 사용자 추가</h2>
<button class="modal-close-btn" onclick="closeUserModal()">×</button>
</div>
<div class="modal-body">
<form id="userForm">
<div class="form-group">
<label class="form-label">사용자명 *</label>
<input type="text" id="userName" class="form-control" required>
</div>
<div class="form-group">
<label class="form-label">아이디 *</label>
<input type="text" id="userId" class="form-control" required>
<small class="form-help">영문, 숫자만 사용 가능 (4-20자)</small>
</div>
<div class="form-group" id="passwordGroup">
<label class="form-label">비밀번호 *</label>
<input type="password" id="userPassword" class="form-control" required>
<small class="form-help">최소 6자 이상</small>
</div>
<div class="form-group">
<label class="form-label">역할 *</label>
<select id="userRole" class="form-control" required>
<option value="">역할 선택</option>
<option value="admin">관리자</option>
<option value="leader">그룹장</option>
<option value="user">작업자</option>
</select>
</div>
<div class="form-group">
<label class="form-label">이메일</label>
<input type="email" id="userEmail" class="form-control">
</div>
<div class="form-group">
<label class="form-label">전화번호</label>
<input type="tel" id="userPhone" class="form-control">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeUserModal()">취소</button>
<button type="button" class="btn btn-primary" id="saveUserBtn">저장</button>
</div>
</div>
</div>
<!-- 사용자 삭제 확인 모달 -->
<div id="deleteModal" class="modal-overlay" style="display: none;">
<div class="modal-container small">
<div class="modal-header">
<h2>사용자 삭제</h2>
<button class="modal-close-btn" onclick="closeDeleteModal()">×</button>
</div>
<div class="modal-body">
<div class="delete-warning">
<div class="warning-icon">⚠️</div>
<p>정말로 이 사용자를 삭제하시겠습니까?</p>
<p class="warning-text">삭제된 사용자는 복구할 수 없습니다.</p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeDeleteModal()">취소</button>
<button type="button" class="btn btn-danger" id="confirmDeleteBtn">삭제</button>
</div>
</div>
</div>
<!-- 토스트 알림 -->
<div class="toast-container" id="toastContainer"></div>
<!-- JavaScript -->
<script src="/js/api-config.js?v=13"></script>
<script src="/js/load-navbar.js?v=4"></script>
<script src="/js/admin-settings.js?v=5"></script>
</body>
</html>