Files
Aislo/B01_Dashboard/B01_Dashboard_UI_Tabs.ts
T
eomsangdonandClaude Sonnet 5.5 2a2c4d0f62 feat(B01): 대시보드 항목별 탭 — 해시 탭 줄 · 개요 · 프로젝트 · 회사 · 내 계정 · 시스템 (92-1·92-2)
- 해시 ?tab= 탭 줄(B08 단추 꼴) · 고른 탭 자료만 받음 · 설정 카드는 탭 줄 위 · 회사 고르기 알약은 탭 줄 오른쪽 하나
- 회사 없음 진입 두 곳(router · M02 Layer)은 ?tab=company · 회사 관리자 프로젝트 목록 한 번만 받음
- 개요 숫자 카드(단계별 · 실패 · 재확인 · 가입 대기 · 보관함 · 리소스) · 프로젝트 표 칸 보강 · 찾기 · 거르기 · 쪽 넘김 · 진행 현황
- 회사 정보 칸(사업자번호 · 대표 · 상태) · 팀원 읽기 · 자산 표 · 내 계정 마지막 로그인 · 시스템 리소스 7·30·90일 · 활성 추이 · 전체 회사 · 사용자 · 로그 쪽 · 고객 문의
- 시험 test_b01_dashboard_tabs 신규 · test_b01_settings_cards 고침

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MgChuAcyBqUkhHMTXomQC7
2026-10-08 13:58:34 +09:00

63 lines
2.5 KiB
TypeScript

/* =============================================================================
* 대시보드 탭 줄(92장) — 한 주소(`#/b01-account`) 안에서 해시 `?tab=` 으로 나눔.
* 라우터는 그대로 — 저장 뒤 해시로 다시 그려도 같은 탭이 남음.
* ========================================================================== */
import { ROUTES } from "@config/config_frontend";
import { createButton } from "@ui/ui_template_elements";
import { navigateTo } from "../A00_Common/router";
import type { DashboardUser } from "./B01_Dashboard_Api_Fetch";
import { L } from "./B01_Dashboard_UI_Common";
import "./B01_Dashboard_UI_Style_Tabs.css";
export type DashboardTab = "overview" | "projects" | "company" | "account" | "system";
const TAB_LABELS = {
overview: "B01_Tab_Overview",
projects: "B01_Tab_Projects",
company: "B01_Tab_Company",
account: "B01_Tab_Account",
system: "B01_Tab_System",
} as const;
/** 역할이 보는 탭 — 시스템은 시스템 관리자만 */
export function tabsFor(role: DashboardUser["role"]): DashboardTab[] {
const base: DashboardTab[] = ["overview", "projects", "company", "account"];
return role === "SYSTEM_ADMIN" ? [...base, "system"] : base;
}
/** 해시 값 → 탭 · 없거나 역할에 없는 값이면 첫 탭(개요) */
export function resolveTab(role: DashboardUser["role"], raw: string | null): DashboardTab {
return tabsFor(role).find((tab) => tab === raw) ?? "overview";
}
/** 탭으로 이동 — 같은 주소라 hashchange 로 다시 그림 · `extra` = 거르기 같은 덧인자 */
export function goTab(tab: DashboardTab, extra: Record<string, string> = {}): void {
navigateTo(ROUTES.B01_ACCOUNT, { tab, ...extra });
}
/** B08 위 탭과 같은 단추 줄 · `trailing` = 줄 오른쪽 끝에 붙는 것(회사 고르기 알약) */
export function buildTabBar(
active: DashboardTab,
role: DashboardUser["role"],
trailing: HTMLElement | null,
): HTMLElement {
const bar = document.createElement("div");
bar.className = "b01-dashboard__tabs";
bar.setAttribute("role", "tablist");
bar.setAttribute("aria-label", L("B01_Tab_Aria"));
for (const tab of tabsFor(role)) {
const button = createButton({
label: L(TAB_LABELS[tab]),
variant: tab === active ? "filled" : "ghost",
onClick: () => tab !== active && goTab(tab),
});
button.setAttribute("role", "tab");
button.setAttribute("aria-selected", String(tab === active));
button.dataset.b01Tab = tab;
bar.append(button);
}
if (trailing) bar.append(trailing);
return bar;
}