음성 재생과 운영 배포 정리

This commit is contained in:
Yun Chan 2026-06-28 12:18:20 +09:00
parent 8ed185ce6c
commit ac7db95542
1020 changed files with 46863 additions and 2175 deletions

View file

@ -1,7 +1,7 @@
import type { ReactNode } from "react";
import { useEffect, type ReactNode } from "react";
import { Topbar } from "./Topbar";
import { Sidebar } from "./Sidebar";
import { useAuth } from "../../lib/auth";
import { designRoleOf, useAuth, type Role } from "../../lib/auth";
export interface AppShellProps {
children: ReactNode;
@ -11,8 +11,12 @@ export interface AppShellProps {
hideNav?: boolean;
/** 메인 패딩·최대폭 제거 (풀-블리드 레이아웃) */
bleed?: boolean;
/** 운영형 대시보드/저작 화면용 넓은 작업폭 */
wide?: boolean;
/** 톱바까지 제거하는 실제 전체화면 작업 공간 */
hideTopbar?: boolean;
/** 현재 화면 컨텍스트에 맞춘 네비/크롬 역할 */
navRole?: Role;
}
/**
@ -20,16 +24,33 @@ export interface AppShellProps {
* body[data-role] AuthProvider ( ).
* ( ) (RequireAuth) .
*/
export function AppShell({ children, contextLabel, hideNav, bleed, hideTopbar }: AppShellProps) {
export function AppShell({ children, contextLabel, hideNav, bleed, wide, hideTopbar, navRole }: AppShellProps) {
const { user } = useAuth();
const showNav = !hideNav && !!user;
const shellRole = navRole ?? user?.role;
const mainClassName = [
"vg-main",
bleed ? "vg-main--bleed" : "",
wide ? "vg-main--wide" : "",
]
.filter(Boolean)
.join(" ");
useEffect(() => {
const body = document.body;
if (shellRole) body.setAttribute("data-role", designRoleOf(shellRole));
return () => {
if (user) body.setAttribute("data-role", designRoleOf(user.role));
else body.removeAttribute("data-role");
};
}, [shellRole, user]);
return (
<div className={"vg-shell" + (hideTopbar ? " vg-shell--fullscreen" : "")}>
{hideTopbar ? null : <Topbar contextLabel={contextLabel} />}
<div className={"vg-shell__body" + (showNav ? "" : " vg-shell__body--bare")}>
{showNav ? <Sidebar role={user.role} /> : null}
<main className={"vg-main" + (bleed ? " vg-main--bleed" : "")}>
{showNav ? <Sidebar role={shellRole ?? user.role} /> : null}
<main className={mainClassName}>
<div className="vg-main__inner">{children}</div>
</main>
</div>