첫 커밋: 로컬 프로젝트 업로드
This commit is contained in:
147
baron-sso/common/shell/index.ts
Normal file
147
baron-sso/common/shell/index.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
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, string | number>,
|
||||
) => 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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user