)
}
function Screen({
mode = "compact",
data = dashboardWorks,
loading,
longTitle,
wide,
thirdLevel,
}: {
mode?: Mode
data?: DashboardWork[]
loading?: boolean
longTitle?: boolean
wide?: boolean
thirdLevel?: boolean
}) {
const [current, setCurrent] = useState(thirdLevel ? "projects/tasks/all" : "projects/tasks")
const [compactStatus, setCompactStatus] = useState("all")
const compact = mode === "compact"
const resultData = compact ? data.filter((row) => matchesDashboardWorkStatus(row, compactStatus)) : data
const [openGroups, setOpenGroups] = useState>({})
const go = (id: string) => (event: MouseEvent) => {
event.preventDefault()
setCurrent(id)
}
const isCurrent = (id: string) => current === id || current.startsWith(`${id}/`)
const nav = localNav(thirdLevel)
const dashboardMenu = (nodes: LocalNode[]): ReactNode =>
nodes.map((node) =>
node.children ? (
setOpenGroups((state) => ({ ...state, [node.id]: value }))}
>
{dashboardMenu(node.children)}
) : (
)
)
const title = longTitle ? "전사 프로젝트 포트폴리오의 진행 현황과 담당 부서별 업무 상세 현황" : "업무 현황"
const sidebar = (
프로젝트 대시보드{profileData.name}
} />
)
// Variant C content: heading, then the result card (Page Header's own 20px bottom spacing; no breadcrumb, actions or KPI cards in the reference).
const compactMain = (
업무 현황을 한눈에 확인하세요 setCompactStatus("all")} />
)
const main = compact ? compactMain : (
홈프로젝트업무 현황{title}프로젝트별 업무 진행 상황을 확인하고 조회합니다.일괄 수정보관
{wide ? (
넓은 내용페이지를 밀지 않고 카드 안에서 가로 스크롤합니다.
) : null}
)
return (
: mode === "header-sidebar" ? 업무 현황 : undefined}
sidebar={compact ? undefined : sidebar}
>
{main}
)
}
const frame = (height?: number): CSSProperties | undefined => (height ? ({ "--hm-dashboard-height": `${height}px` } as CSSProperties) : undefined)
// Shared by Storybook and the standalone Vite export. Keeping the representative
// story composition here prevents the export from becoming a second hand-written UI.
export function DashboardAll() {
return (
)
}
// Menu label is Dashboard; the fixed id keeps the existing story IDs (patterns-layout-dashboard-layout--*) used by links and QA inventory.
const meta = { id: "patterns-layout-dashboard-layout", title: "Patterns/Layout/Dashboard", excludeStories: ["DashboardAll"], parameters: { layout: "fullscreen", controls: { disable: true } } } satisfies Meta
export default meta
type Story = StoryObj
// Representative Story reproduces the ui_viz Variant C layout (48px Compact Header, centred status bar, content) with HM parts.
// Operating DASHBOARD Mode has no Sidebar; retained Sidebar examples are compatibility verification only.
// The page heading and Dashboard's native minimum-width scroll frame share the common Inner.
export const All: Story = {
name: "Dashboard",
render: () => ,
}
// Keep existing Sidebar coverage and Story IDs; these are not operating references.
function SidebarVerification({ children }: { children: ReactNode }) {
return <>
VERIFICATION ONLY — 운영 사용 금지
{children}
>
}
export const WithSidebar: Story = { tags: ["verification"], name: "VERIFICATION ONLY — 운영 사용 금지 · Dashboard Header + Sidebar", render: () => }
export const ThirdLevel: Story = { tags: ["verification"], name: "VERIFICATION ONLY — 운영 사용 금지 · Third Level", render: () => }
export const SidebarOnly: Story = { tags: ["verification"], name: "VERIFICATION ONLY — 운영 사용 금지 · Dashboard Sidebar", render: () => }
export const LongContent: Story = { tags: ["verification"], name: "VERIFICATION ONLY — 운영 사용 금지 · Long Content", render: () => }
export const Loading: Story = { tags: ["verification"], render: () => }
export const Empty: Story = { tags: ["verification"], render: () => }
export const Framed: Story = { tags: ["verification"], name: "VERIFICATION ONLY — 운영 사용 금지 · Framed", render: () =>