- 해시 ?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
63 lines
2.5 KiB
TypeScript
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;
|
|
}
|