Files
ai-dev-portal/views/_header.ejs
2620227 355798a506 fix(header,announcements): 헤더 종·관리자 뱃지 순서 교체 + 공지 수정폼 겹침 수정
- 헤더 우측: 알림 종 → 관리자 뱃지 → 프로필 순으로 변경(관리자 뱃지가 프로필 바로 왼쪽)
- 공지 화면 '관리자 공지 모아보기' 서브 문구 제거
- 공지 수정폼이 hidden 이어도 항상 보여 보기/수정이 2단으로 겹치던 버그 수정
  (.ann-form 의 display:flex 가 [hidden] 기본 규칙을 이기던 문제 → .ann-form[hidden]{display:none})

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 20:08:47 +09:00

100 lines
5.3 KiB
Plaintext

<!DOCTYPE html>
<html lang="ko" data-aidev-theme="light">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%= brand %></title>
<link rel="icon" href="/public/favicon.svg" type="image/svg+xml" />
<!-- Pretendard 폰트 (CDN · 인터넷 연결 환경) -->
<link rel="stylesheet" as="style" crossorigin href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.min.css" />
<link rel="stylesheet" href="/public/css/tokens.css" />
<link rel="stylesheet" href="/public/css/base.css" />
<link rel="stylesheet" href="/public/css/layout.css" />
<link rel="stylesheet" href="/public/css/components.css" />
<link rel="stylesheet" href="/public/css/modal.css" />
<!-- 반응형(모바일) — 데스크톱 규칙을 덮어써야 하므로 반드시 맨 마지막에 로드. 순서 바꾸지 말 것. -->
<link rel="stylesheet" href="/public/css/responsive.css" />
<script>
// FOUC 방지: 저장된 테마를 페인트 전에 documentElement 에 적용
(function () {
try {
var t = localStorage.getItem("aidev-theme");
if (t === "dark" || t === "light") document.documentElement.setAttribute("data-aidev-theme", t);
} catch (e) {}
})();
</script>
</head>
<body<% if (typeof toast !== "undefined" && toast) { %> data-toast="<%= toast %>"<% } %><% if (typeof egg !== "undefined" && egg) { %> data-egg="<%= egg %>"<% } %><% if (typeof openModal !== "undefined" && openModal) { %> data-open-modal="<%= openModal %>"<% } %>>
<header class="hdr">
<div class="hdr-inner">
<a class="brand" href="/" id="brandLink">
<span class="brand-mark"><%- icon("codeslash", { size: 22 }) %></span>
<span class="brand-name"><%= brand %></span>
<span class="brand-sub">사내 개발 포털</span>
</a>
<% if (user) { %>
<div class="hdr-search">
<span class="hdr-search-ico"><%- icon("search", { size: 15 }) %></span>
<input type="search" id="feedSearch" placeholder="<%= typeof searchPlaceholder !== 'undefined' && searchPlaceholder ? searchPlaceholder : '공유 프로젝트 검색…' %>" autocomplete="off" />
</div>
<div class="hdr-right">
<button class="icon-btn" id="themeToggle" type="button" title="테마 전환" aria-label="테마 전환">
<span class="theme-ico theme-ico-moon"><%- icon("moon", { size: 16 }) %></span>
<span class="theme-ico theme-ico-sun"><%- icon("sun", { size: 16 }) %></span>
</button>
<a class="hdr-link" href="/announcements" title="공지사항">
<%- icon("megaphone", { size: 15 }) %><span>공지</span>
</a>
<a class="hdr-link" href="<%= manualUrl %>" target="_blank" rel="noopener" title="포털 사용 매뉴얼">
<%- icon("book", { size: 15 }) %><span>매뉴얼</span>
</a>
<!-- 알림(🔔) 종 — 관리자 뱃지 왼쪽. 목록/배지는 app.js(notifications.js)가 fetch 로 채운다. -->
<div class="notif">
<button class="icon-btn notif-btn" id="notifBtn" type="button" aria-haspopup="true" aria-expanded="false" title="알림" aria-label="알림">
<%- icon("bell", { size: 16 }) %>
<span class="notif-badge" id="notifBadge" hidden></span>
</button>
<div class="notif-pop" id="notifPop" hidden>
<div class="notif-head">
<span class="notif-title">알림</span>
<button type="button" class="notif-readall" id="notifReadAll">모두 읽음</button>
</div>
<div class="notif-list" id="notifList">
<div class="notif-empty">불러오는 중…</div>
</div>
<a class="notif-foot" href="/announcements"><%- icon("megaphone", { size: 14 }) %>공지 전체 보기</a>
</div>
</div>
<!-- 관리자 뱃지 — 프로필 바로 왼쪽 -->
<% if (user.isAdmin) { %>
<span class="admin-pill"><%- icon("lock", { size: 11 }) %>관리자</span>
<% } %>
<div class="usermenu">
<button class="usermenu-btn" id="userMenuBtn" type="button" aria-haspopup="true" aria-expanded="false">
<span class="who"><%= user.sabun %></span>
<%- avatar(user.sabun, 26) %>
<span class="caret"><%- icon("caret", { size: 14 }) %></span>
</button>
<div class="usermenu-pop" id="userMenuPop" hidden>
<div class="usermenu-head">
<div class="usermenu-label">로그인 계정</div>
<div class="usermenu-sabun"><%= user.sabun %></div>
<div class="usermenu-role"><%= user.isAdmin ? "관리자 (admin)" : "일반 사용자" %></div>
</div>
<a class="usermenu-item" href="/u/<%= user.sabun %>"><span class="usermenu-ico"><%- icon("repo", { size: 15 }) %></span>내 프로필</a>
<a class="usermenu-item" href="/announcements"><span class="usermenu-ico"><%- icon("megaphone", { size: 15 }) %></span>공지사항</a>
<a class="usermenu-item" href="/logout"><span class="usermenu-ico"><%- icon("signout", { size: 15 }) %></span>로그아웃</a>
</div>
</div>
</div>
<% } %>
</div>
</header>