import { readSessionExpiryEnabled, SESSION_EXPIRY_STORAGE_KEY, writeSessionExpiryEnabled, } from "../core/session"; export type ShellTheme = "light" | "dark"; export type ShellTranslator = ( key: string, fallback: string, vars?: Record, ) => string; type ShellSessionStatusParams = { expiresAtSec?: number | null; nowMs: number; t: ShellTranslator; }; type ShellProfileSummaryParams = { profileName?: string | null; profileEmail?: string | null; fallbackName: string; fallbackEmail: string; }; export const SHELL_THEME_STORAGE_KEY = "admin_theme"; export const SHELL_SESSION_EXPIRY_STORAGE_KEY = SESSION_EXPIRY_STORAGE_KEY; export const SHELL_SIDEBAR_COLLAPSED_STORAGE_KEY = "baron_shell_sidebar_collapsed"; export type { ShellSidebarNavItem } from "./AppSidebar"; export { AppSidebar } from "./AppSidebar"; export { shellLayoutClasses } from "./layout"; export function readShellTheme(): ShellTheme { return window.localStorage.getItem(SHELL_THEME_STORAGE_KEY) === "dark" ? "dark" : "light"; } export function applyShellTheme(theme: ShellTheme) { const root = document.documentElement; root.classList.remove("light", "dark"); root.classList.add(theme); window.localStorage.setItem(SHELL_THEME_STORAGE_KEY, theme); } export function readShellSessionExpiryEnabled(defaultEnabled = true) { return readSessionExpiryEnabled({ defaultEnabled }); } export function writeShellSessionExpiryEnabled(isEnabled: boolean) { writeSessionExpiryEnabled(isEnabled); } export function readShellSidebarCollapsed(defaultCollapsed = false) { const stored = window.localStorage.getItem( SHELL_SIDEBAR_COLLAPSED_STORAGE_KEY, ); if (stored === null) { return defaultCollapsed; } return stored === "true"; } export function writeShellSidebarCollapsed(isCollapsed: boolean) { window.localStorage.setItem( SHELL_SIDEBAR_COLLAPSED_STORAGE_KEY, String(isCollapsed), ); } export function buildShellProfileSummary({ profileName, profileEmail, fallbackName, fallbackEmail, }: ShellProfileSummaryParams) { const resolvedName = profileName?.trim() || fallbackName; const resolvedEmail = profileEmail?.trim() || fallbackEmail; return { name: resolvedName, email: resolvedEmail, initial: resolvedName.charAt(0).toUpperCase(), }; } export function buildShellSessionStatus({ expiresAtSec, nowMs, t, }: ShellSessionStatusParams) { const remainingMs = typeof expiresAtSec === "number" ? expiresAtSec * 1000 - nowMs : null; const remainingTotalSec = remainingMs !== null ? Math.max(0, Math.floor(remainingMs / 1000)) : null; const remainingMinutes = remainingTotalSec !== null ? Math.floor(remainingTotalSec / 60) : null; const remainingSeconds = remainingTotalSec !== null ? remainingTotalSec % 60 : null; let toneClass = "border-emerald-500/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300"; let text = t("ui.shell.session.active", "세션 활성"); if (remainingMs === null) { toneClass = "border-border bg-card text-muted-foreground"; text = t("ui.shell.session.unknown", "알 수 없음"); } else if (remainingMs <= 0) { toneClass = "border-rose-500/30 bg-rose-500/10 text-rose-700 dark:text-rose-300"; text = t("ui.shell.session.expired", "세션 만료"); } else if ( remainingMinutes !== null && remainingSeconds !== null && remainingMinutes <= 5 ) { toneClass = "border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300"; text = t( "ui.shell.session.expiring", "만료 임박: {{minutes}}분 {{seconds}}초 남음", { minutes: remainingMinutes, seconds: remainingSeconds, }, ); } else { text = t( "ui.shell.session.remaining", "만료 예정: {{minutes}}분 {{seconds}}초 남음", { minutes: remainingMinutes ?? 0, seconds: remainingSeconds ?? 0, }, ); } return { toneClass, text, }; }