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

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

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

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

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

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

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

391 lines
9.2 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🔐 비밀번호 변경 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/main-layout.css">
<script src="/js/auth-check.js" defer></script>
<style>
/* 페이지 전용 스타일 */
.password-page {
max-width: 600px;
margin: 0 auto;
padding: 40px 20px;
}
.page-title {
text-align: center;
margin-bottom: 40px;
}
.page-title h1 {
font-size: 2rem;
color: #333;
margin-bottom: 12px;
}
.page-title p {
color: #666;
font-size: 1.1rem;
}
/* 카드 스타일 */
.password-card {
background: white;
border-radius: 16px;
box-shadow: 0 4px 20px rgba(0,0,0,0.08);
overflow: hidden;
}
.card-header {
background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%);
color: white;
padding: 24px 32px;
}
.card-header h2 {
margin: 0;
font-size: 1.5rem;
font-weight: 600;
display: flex;
align-items: center;
gap: 12px;
}
.card-body {
padding: 32px;
}
/* 알림 박스 */
.info-box {
background: #e3f2fd;
border: 1px solid #90caf9;
border-radius: 8px;
padding: 16px;
margin-bottom: 28px;
}
.info-box h4 {
margin: 0 0 12px 0;
color: #1565c0;
font-size: 1rem;
display: flex;
align-items: center;
gap: 8px;
}
.info-box ul {
margin: 0;
padding-left: 24px;
color: #0d47a1;
}
.info-box li {
margin-bottom: 6px;
}
/* 폼 스타일 */
.password-form {
display: flex;
flex-direction: column;
gap: 24px;
}
.form-group {
display: flex;
flex-direction: column;
gap: 10px;
}
.form-group label {
font-weight: 600;
color: #333;
font-size: 0.95rem;
display: flex;
align-items: center;
gap: 8px;
}
.input-wrapper {
position: relative;
}
.form-control {
width: 100%;
padding: 14px 48px 14px 16px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 1rem;
transition: all 0.3s ease;
font-family: inherit;
}
.form-control:focus {
outline: none;
border-color: #ff9800;
box-shadow: 0 0 0 3px rgba(255, 152, 0, 0.1);
}
.password-toggle {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
cursor: pointer;
padding: 8px;
font-size: 1.2rem;
opacity: 0.6;
transition: opacity 0.2s;
}
.password-toggle:hover {
opacity: 1;
}
/* 버튼 */
.form-actions {
display: flex;
gap: 12px;
margin-top: 12px;
}
.btn {
padding: 14px 28px;
border: none;
border-radius: 8px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
font-family: inherit;
}
.btn-primary {
background: #ff9800;
color: white;
flex: 1;
}
.btn-primary:hover {
background: #f57c00;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(255, 152, 0, 0.3);
}
.btn-primary:disabled {
background: #ccc;
cursor: not-allowed;
transform: none;
}
.btn-secondary {
background: #f5f5f5;
color: #666;
border: 1px solid #e0e0e0;
}
.btn-secondary:hover {
background: #e0e0e0;
}
/* 메시지 */
.message-box {
padding: 16px;
border-radius: 8px;
margin-bottom: 20px;
animation: slideDown 0.3s ease-out;
}
.message-box.error {
background: #ffebee;
border: 1px solid #ffcdd2;
color: #c62828;
}
.message-box.success {
background: #e8f5e9;
border: 1px solid #c8e6c9;
color: #2e7d32;
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 하단 링크 */
.back-link {
text-align: center;
margin-top: 32px;
padding-top: 32px;
border-top: 1px solid #e0e0e0;
}
.back-link a {
color: #1976d2;
text-decoration: none;
font-size: 0.95rem;
display: inline-flex;
align-items: center;
gap: 6px;
transition: color 0.2s;
}
.back-link a:hover {
color: #1565c0;
text-decoration: underline;
}
/* 반응형 */
@media (max-width: 768px) {
.password-page {
padding: 20px 16px;
}
.card-body {
padding: 24px;
}
.form-actions {
flex-direction: column;
}
.btn {
width: 100%;
}
}
</style>
</head>
<body>
<div class="main-layout-no-sidebar">
<div id="navbar-container"></div>
<div class="password-page">
<div class="page-title">
<h1>🔐 비밀번호 변경</h1>
<p>계정 보안을 위해 정기적으로 비밀번호를 변경해주세요</p>
</div>
<div class="password-card">
<div class="card-header">
<h2>
<span>🔑</span>
<span>새 비밀번호 설정</span>
</h2>
</div>
<div class="card-body">
<!-- 메시지 영역 -->
<div id="message-area"></div>
<!-- 안내 정보 -->
<div class="info-box">
<h4>
<span></span>
<span>비밀번호 요구사항</span>
</h4>
<ul>
<li>최소 6자 이상 입력해주세요</li>
<li>영문 대/소문자, 숫자, 특수문자를 조합하면 더 안전합니다</li>
<li>개인정보나 쉬운 단어는 피해주세요</li>
<li>이전 비밀번호와 다르게 설정해주세요</li>
</ul>
</div>
<!-- 비밀번호 변경 폼 -->
<form id="changePasswordForm" class="password-form">
<div class="form-group">
<label for="currentPassword">
<span>🔓</span>
<span>현재 비밀번호</span>
</label>
<div class="input-wrapper">
<input
type="password"
id="currentPassword"
class="form-control"
placeholder="현재 비밀번호를 입력하세요"
required
autocomplete="current-password"
/>
<button type="button" class="password-toggle" data-target="currentPassword">👁️</button>
</div>
</div>
<div class="form-group">
<label for="newPassword">
<span>🔐</span>
<span>새 비밀번호</span>
</label>
<div class="input-wrapper">
<input
type="password"
id="newPassword"
class="form-control"
placeholder="새 비밀번호를 입력하세요"
required
autocomplete="new-password"
/>
<button type="button" class="password-toggle" data-target="newPassword">👁️</button>
</div>
<div id="passwordStrength"></div>
</div>
<div class="form-group">
<label for="confirmPassword">
<span></span>
<span>새 비밀번호 확인</span>
</label>
<div class="input-wrapper">
<input
type="password"
id="confirmPassword"
class="form-control"
placeholder="새 비밀번호를 다시 입력하세요"
required
autocomplete="new-password"
/>
<button type="button" class="password-toggle" data-target="confirmPassword">👁️</button>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary" id="submitBtn">
<span>🔑</span>
<span>비밀번호 변경</span>
</button>
<button type="button" class="btn btn-secondary" id="resetBtn">
초기화
</button>
</div>
</form>
<div class="back-link">
<a href="javascript:history.back()">
<span></span>
<span>이전 페이지로 돌아가기</span>
</a>
</div>
</div>
</div>
</div>
</div>
<script type="module" src="/js/load-navbar.js"></script>
<script type="module" src="/js/change-password.js"></script>
</body>
</html>