Files
dbx-main/app/templates/main.html
T
king e8a85be36c feat: 주문리스트를 /orderlist/ 리버스 프록시 경로로 통합
- 메뉴 카드 새 탭 열기 + /orderlist/health/db 헬스 배지 (온라인/오프라인) 추가
- CUSTOMER_ORDER_LIST_URL 기본값을 /orderlist/ 로 (NPM 같은 도메인 하위 경로)
- orderlist 측 compose 정리 스크립트 추가 (ports 제거, npm_default 외부 네트워크 attach)
2026-05-24 05:04:29 +09:00

156 lines
6.4 KiB
HTML

<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>업무 포털 — DBX Corporation</title>
<link rel="stylesheet" href="/static/styles.css" />
</head>
<body>
<!-- ── 헤더 ── -->
<header class="header">
<div class="header-brand">
<img src="/static/dbx-logo.png" alt="DBX Corporation" class="header-logo-img" />
<span class="header-portal">업무 포털</span>
</div>
<div class="header-user">
<div class="header-user-info">
<span class="header-user-name">{{ user.name }}</span>
<span class="header-user-email">{{ user.email }}</span>
</div>
{% if user.picture %}
<img class="header-avatar" src="{{ user.picture }}" alt="{{ user.name }}" />
{% else %}
<div class="header-avatar-placeholder">
{{ user.name[0] | upper }}
</div>
{% endif %}
<a class="btn-logout" href="/logout">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/>
<polyline points="16 17 21 12 16 7"/>
<line x1="21" y1="12" x2="9" y2="12"/>
</svg>
<span>로그아웃</span>
</a>
</div>
</header>
<!-- ── 히어로 배너 ── -->
<section class="hero">
<p class="hero-greeting">안녕하세요, {{ user.name }}님 👋</p>
<p class="hero-sub">오늘도 좋은 하루 되세요.</p>
<p class="hero-date" id="today-date"></p>
</section>
<!-- ── 메뉴 콘텐츠 ── -->
<main class="content">
<div class="section-header">
<h2 class="section-title">업무 바로가기</h2>
<span class="section-count">{{ menu_items | length }}</span>
</div>
<div class="card-grid">
{% for item in menu_items %}
<a class="menu-card" href="{{ item.url }}" target="_blank" rel="noopener noreferrer"
{% if item.health_url %}data-health-url="{{ item.health_url }}"{% endif %}>
<div class="card-icon">
{% if loop.index == 1 %}
<!-- 클립보드 / 발주 아이콘 -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/>
<rect x="8" y="2" width="8" height="4" rx="1" ry="1"/>
<line x1="8" y1="13" x2="16" y2="13"/>
<line x1="8" y1="17" x2="14" y2="17"/>
</svg>
{% elif loop.index == 2 %}
<!-- 리스트 / 주문 아이콘 -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="8" y1="6" x2="21" y2="6"/>
<line x1="8" y1="12" x2="21" y2="12"/>
<line x1="8" y1="18" x2="21" y2="18"/>
<line x1="3" y1="6" x2="3.01" y2="6"/>
<line x1="3" y1="12" x2="3.01" y2="12"/>
<line x1="3" y1="18" x2="3.01" y2="18"/>
</svg>
{% elif loop.index == 3 %}
<!-- 차트 아이콘 -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="20" x2="18" y2="10"/>
<line x1="12" y1="20" x2="12" y2="4"/>
<line x1="6" y1="20" x2="6" y2="14"/>
<line x1="2" y1="20" x2="22" y2="20"/>
</svg>
{% else %}
<!-- 기본 링크 아이콘 -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"/>
<line x1="12" y1="8" x2="12" y2="16"/>
<line x1="8" y1="12" x2="16" y2="12"/>
</svg>
{% endif %}
</div>
<div class="card-body">
<p class="card-title">
{{ item.title }}
{% if item.health_url %}
<span class="status-badge" data-status="checking" aria-live="polite">확인 중</span>
{% endif %}
</p>
<p class="card-desc">{{ item.description }}</p>
</div>
<div class="card-footer">
<span class="card-link">
바로가기
<svg width="14" height="14" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<line x1="5" y1="12" x2="19" y2="12"/>
<polyline points="12 5 19 12 12 19"/>
</svg>
</span>
</div>
</a>
{% endfor %}
</div>
</main>
<script>
// 오늘 날짜 표시
const d = new Date();
const days = ["일요일","월요일","화요일","수요일","목요일","금요일","토요일"];
document.getElementById("today-date").textContent =
d.getFullYear() + "년 " + (d.getMonth()+1) + "월 " + d.getDate() + "일 " + days[d.getDay()];
// 헬스 배지 — data-health-url 이 있는 카드만 갱신
async function refreshHealthBadges() {
const cards = document.querySelectorAll(".menu-card[data-health-url]");
await Promise.all(Array.from(cards).map(async (card) => {
const url = card.getAttribute("data-health-url");
const badge = card.querySelector(".status-badge");
if (!badge) return;
try {
const res = await fetch(url, { cache: "no-store", credentials: "omit" });
const ok = res.ok;
badge.dataset.status = ok ? "online" : "offline";
badge.textContent = ok ? "온라인" : "오프라인";
} catch {
badge.dataset.status = "offline";
badge.textContent = "오프라인";
}
}));
}
refreshHealthBadges();
setInterval(refreshHealthBadges, 30000);
</script>
</body>
</html>