Files
Aislo/A01_Home/A01_Home_UI_Page.ts
T

206 lines
7.0 KiB
TypeScript

/* =============================================================================
* A01_Home_UI_Page.ts
* 로그인 전 01: 홈 (소개 히어로 + 최신 소식 + 주요 기능)
*
* 제약 준수:
* - 모든 문구는 ui_template_locale.ts 참조 (하드코딩 금지).
* - 색상/간격은 A01_Home_UI_Style.css + theme.css 변수만 사용.
* - 공통 컴포넌트(createButton/createCard/createTag) 우선 사용.
* - 이벤트 핸들러는 on[페이지]_[기능]_[액션] 명명.
* ========================================================================== */
import { ui_locales, currentLanguageIndex } from "@ui/ui_template_locale";
import { createButton, createCard, createTag } from "@ui/ui_template_elements";
import { navigateTo } from "../A00_Common/router";
import { ROUTES, AUTH_TOKEN_KEY } from "@config/config_frontend";
import "./A01_Home_UI_Style.css";
/** locale 헬퍼 */
function L(key: keyof typeof ui_locales): string {
return ui_locales[key][currentLanguageIndex];
}
/* -----------------------------------------------------------------------------
* Mock 데이터 (백엔드 연결 전) — 나중에 GET /api/a01/news로 교체
* -------------------------------------------------------------------------- */
interface NewsItem {
id: number;
title: string;
date: string;
}
const MOCK_NEWS: NewsItem[] = [
{ id: 1, title: "v0.1 프론트엔드 프로토타입 공개", date: "2026-07-05" },
{ id: 2, title: "3D 지형 뷰어 Three.js 엔진 확정", date: "2026-07-04" },
{ id: 3, title: "임도 설계 워크플로우 6단계 정의 완료", date: "2026-07-01" },
];
/* -----------------------------------------------------------------------------
* 이벤트 핸들러
* -------------------------------------------------------------------------- */
function onA01_Home_GetStarted_Click(): void {
navigateTo(ROUTES.A07_REGISTER);
}
function onA01_Home_Explore_Click(): void {
navigateTo(ROUTES.A02_PROG_DETAIL);
}
function navigateToDevPage(route: string): void {
localStorage.setItem(AUTH_TOKEN_KEY, "dev-temp-token");
navigateTo(route as never);
}
/* -----------------------------------------------------------------------------
* 섹션 빌더
* -------------------------------------------------------------------------- */
function buildHero(): HTMLElement {
const hero = document.createElement("section");
hero.className = "a01-hero";
const inner = document.createElement("div");
inner.className = "a01-hero__inner";
const title = document.createElement("h1");
title.className = "a01-hero__title";
title.textContent = L("A01_Home_Title");
const subtitle = document.createElement("p");
subtitle.className = "a01-hero__subtitle";
subtitle.textContent = L("A01_Home_Hero_Subtitle");
const ctas = document.createElement("div");
ctas.className = "a01-hero__ctas";
ctas.append(
createButton({
label: L("A01_Home_Hero_CtaPrimary"),
variant: "filled",
onClick: onA01_Home_GetStarted_Click,
}),
createButton({
label: L("A01_Home_Hero_CtaSecondary"),
variant: "ghost",
onClick: onA01_Home_Explore_Click,
}),
);
inner.append(title, subtitle, ctas);
hero.append(inner);
return hero;
}
function buildNews(): HTMLElement {
const section = document.createElement("section");
section.className = "a01-section";
const heading = document.createElement("h2");
heading.className = "a01-section__title";
heading.textContent = L("A01_Home_News_SectionTitle");
const list = document.createElement("div");
list.className = "a01-news-list";
for (const item of MOCK_NEWS) {
const row = document.createElement("div");
row.className = "a01-news-row";
const tag = createTag(L("A01_Home_News_Tag"), "accent");
const titleEl = document.createElement("span");
titleEl.className = "a01-news-row__title";
titleEl.textContent = item.title;
const dateEl = document.createElement("span");
dateEl.className = "a01-news-row__date";
dateEl.textContent = item.date;
row.append(tag, titleEl, dateEl);
list.append(row);
}
section.append(heading, list);
return section;
}
function buildFeatures(): HTMLElement {
const section = document.createElement("section");
section.className = "a01-section";
const heading = document.createElement("h2");
heading.className = "a01-section__title";
heading.textContent = L("A01_Home_Features_SectionTitle");
const grid = document.createElement("div");
grid.className = "a01-feature-grid";
const features: [keyof typeof ui_locales, keyof typeof ui_locales][] = [
["A01_Home_Feature1_Title", "A01_Home_Feature1_Desc"],
["A01_Home_Feature2_Title", "A01_Home_Feature2_Desc"],
["A01_Home_Feature3_Title", "A01_Home_Feature3_Desc"],
];
for (const [titleKey, descKey] of features) {
const desc = document.createElement("p");
desc.className = "a01-feature__desc";
desc.textContent = L(descKey);
const card = createCard({ title: L(titleKey), body: [desc] });
card.classList.add("a01-feature-card");
grid.append(card);
}
section.append(heading, grid);
return section;
}
function buildDevMenu(): HTMLElement {
const section = document.createElement("section");
section.className = "a01-section a01-dev-menu";
section.style.opacity = "0.6";
section.style.borderTop = "2px dashed var(--color-slate)";
section.style.marginTop = "var(--spacing-48)";
section.style.paddingTop = "var(--spacing-48)";
const heading = document.createElement("h2");
heading.className = "a01-section__title";
heading.textContent = "🔧 개발 모드 - B 그룹 테스트";
const grid = document.createElement("div");
grid.className = "a01-feature-grid";
grid.style.gridTemplateColumns = "repeat(auto-fit, minmax(200px, 1fr))";
const bPages: [string, string][] = [
[ROUTES.B01_ACCOUNT, "B01 · 계정 상세"],
[ROUTES.B02_PROJ_REGISTER, "B02 · 프로젝트 등록"],
[ROUTES.B03_FILE_INPUT, "B03 · 파일 입력"],
[ROUTES.B04_WF1_SURFACE, "B04 · 지표면 분석"],
[ROUTES.B05_WF2_ROUTE, "B05 · 경로 설계"],
[ROUTES.B06_WF3_PROFILE_CROSS, "B06 · 종횡단 생성"],
[ROUTES.B07_WF4_DESIGN_DETAIL, "B07 · 상세 설계"],
[ROUTES.B08_WF5_QUANTITY, "B08 · 수량 산출"],
[ROUTES.B09_WF6_ESTIMATION, "B09 · 견적/문서"],
[ROUTES.B10_PAYMENT, "B10 · 결재"],
[ROUTES.B11_STATUS, "B11 · 상태 출력"],
];
for (const [route, label] of bPages) {
const btn = createButton({
label,
variant: "ghost",
onClick: () => navigateToDevPage(route),
});
btn.style.width = "100%";
grid.append(btn);
}
section.append(heading, grid);
return section;
}
/* -----------------------------------------------------------------------------
* 페이지 진입점
* -------------------------------------------------------------------------- */
export function renderA01Home(root: HTMLElement): void {
const page = document.createElement("div");
page.className = "a01-home";
page.append(buildHero(), buildNews(), buildFeatures(), buildDevMenu());
root.append(page);
}