Files
template-app/apps/web/src/routes/$org.$workspace.index.tsx
T
2026-11-14 09:56:45 +00:00

82 lines
3.1 KiB
TypeScript

// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
// A workspace: its projects, and a form to create another (spec §3.1). The projects are listed
// through `tenancy.project.list`, which reads them inside the workspace's own scope -- a workspace of
// another organization, or one the person has no place in, is the not-found page.
import { moduleSelected } from "@app/modules/inclusion"
import { GuidesSetupCard } from "@conusai-kit/guides/panel" // kit:guides
import { FormPanel, Page as PageFrame, PageHeader, PageSection, ResourceList } from "@conusai-kit/ui/patterns"
import { createFileRoute } from "@tanstack/react-router"
import { createServerFn } from "@tanstack/react-start"
import type { ReactElement } from "react"
import type { WorkspaceHomeData, WorkspaceParams } from "../server/org-pages"
import { useFrameRouter } from "../ui/frame-router"
import { ProcedureForm } from "../ui/procedure-form"
import { projectHref } from "../ui/projects"
const ROUTE = "/$org/$workspace/"
const read = createServerFn({ method: "GET" })
.validator((params: WorkspaceParams) => params)
.handler(async ({ data }): Promise<WorkspaceHomeData> => {
const [{ reported }, { workspaceHomeData }] = await Promise.all([
import("../server/page"),
import("../server/org-pages"),
])
return reported(ROUTE, () => workspaceHomeData(data))
})
export const Route = createFileRoute("/$org/$workspace/")({
loader: ({ params }) => read({ data: { org: params.org, workspace: params.workspace } }),
head: ({ loaderData }) => ({ meta: loaderData ? [{ title: loaderData.title }] : [] }),
component: Page,
})
function Page(): ReactElement {
const { org, workspace } = Route.useParams()
const data = Route.useLoaderData()
const create = data.create
const { navigate } = useFrameRouter()
return (
<PageFrame>
<PageHeader
title={data.title}
description={data.description}
actions={
create ? (
<FormPanel label={create.title}>
{(complete) => (
<ProcedureForm
procedure="tenancy.project.create"
onComplete={complete}
hidden={{ org, workspace }}
submitLabel={create.submit}
fields={create.fields}
/>
)}
</FormPanel>
) : undefined
}
/>
{/* kit:guides:begin */}
{moduleSelected("guides") && <GuidesSetupCard locale={data.locale} scope={{ org, workspace }} />}
{/* kit:guides:end */}
<PageSection title={data.projectsHeading}>
<ResourceList
label={data.projectsHeading}
columns={[
{ id: "name", header: data.columnName, wrap: true },
{ id: "moduleKey", header: data.columnModule },
]}
data={data.projects}
rowId={(project) => project.slug}
rowHref={(project) => projectHref(org, workspace, project.slug)}
navigate={navigate}
rowLabel={(project) => project.name}
empty={{ title: data.none }}
/>
</PageSection>
</PageFrame>
)
}