Finally gets the routing working in a somewhat reasonable way
This commit is contained in:
27
package-lock.json
generated
27
package-lock.json
generated
@@ -17,7 +17,8 @@
|
||||
"pocketbase": "^0.26.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"tailwindcss": "^4.0.6"
|
||||
"tailwindcss": "^4.0.6",
|
||||
"zod": "^4.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/ts-plugin": "^1.10.4",
|
||||
@@ -1926,6 +1927,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/router-generator/node_modules/zod": {
|
||||
"version": "3.25.76",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/router-plugin": {
|
||||
"version": "1.120.10",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/router-plugin/-/router-plugin-1.120.10.tgz",
|
||||
@@ -1982,6 +1992,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/router-plugin/node_modules/zod": {
|
||||
"version": "3.25.76",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/router-utils": {
|
||||
"version": "1.115.0",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/router-utils/-/router-utils-1.115.0.tgz",
|
||||
@@ -4503,9 +4522,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.25.28",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.28.tgz",
|
||||
"integrity": "sha512-/nt/67WYKnr5by3YS7LroZJbtcCBurDKKPBPWWzaxvVCGuG/NOsiKkrjoOhI8mJ+SQUXEbUzeB3S+6XDUEEj7Q==",
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-4.0.5.tgz",
|
||||
"integrity": "sha512-/5UuuRPStvHXu7RS+gmvRf4NXrNxpSllGwDnCBcJZtQsKrviYXm54yDGV2KYNLT5kq0lHGcl7lqWJLgSaG+tgA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
"pocketbase": "^0.26.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"tailwindcss": "^4.0.6"
|
||||
"tailwindcss": "^4.0.6",
|
||||
"zod": "^4.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/ts-plugin": "^1.10.4",
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
import { DocumentEditForm } from "@/components/documents/DocumentEditForm";
|
||||
import { useDocument } from "@/context/document/hooks";
|
||||
import { displayName, relationshipsForDocument } from "@/lib/relationships";
|
||||
import type { DocumentId } from "@/lib/types";
|
||||
import { RelationshipType, type DocumentId } from "@/lib/types";
|
||||
import { Route as CampaignRoute } from "@/routes/_app/_authenticated/campaigns.$campaignId";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import _ from "lodash";
|
||||
import { Loader } from "../Loader";
|
||||
import { Route as RelationshipRoute } from "@/routes/_app/_authenticated/document.$documentId/$relationshipType";
|
||||
import { DocumentTitle } from "./DocumentTitle";
|
||||
import { TabbedLayout } from "../layout/TabbedLayout";
|
||||
import { DocumentEditForm } from "./DocumentEditForm";
|
||||
import { RelatedDocumentList } from "./RelatedDocumentList";
|
||||
|
||||
export function DocumentView({ documentId }: { documentId: DocumentId }) {
|
||||
export function DocumentView({
|
||||
documentId,
|
||||
relationshipType,
|
||||
}: {
|
||||
documentId: DocumentId;
|
||||
relationshipType: RelationshipType | null;
|
||||
}) {
|
||||
const { docResult } = useDocument(documentId);
|
||||
|
||||
if (docResult?.type !== "ready") {
|
||||
@@ -19,17 +26,17 @@ export function DocumentView({ documentId }: { documentId: DocumentId }) {
|
||||
const doc = docResult.value.doc;
|
||||
const relationshipCounts = _.mapValues(docResult.value.relationships, (v) => {
|
||||
if (v.type === "ready") {
|
||||
return v.value.secondary.length;
|
||||
return v.value.secondary.length.toString();
|
||||
}
|
||||
return 0;
|
||||
return "...";
|
||||
});
|
||||
|
||||
const relationshipList = relationshipsForDocument(doc);
|
||||
|
||||
return (
|
||||
<div key={doc.id} className="max-w-xl mx-auto py-2 px-4">
|
||||
<DocumentTitle document={doc} />
|
||||
<div>
|
||||
<TabbedLayout
|
||||
navigation={
|
||||
<>
|
||||
<Link
|
||||
to={CampaignRoute.to}
|
||||
params={{ campaignId: doc.campaign }}
|
||||
@@ -44,14 +51,25 @@ export function DocumentView({ documentId }: { documentId: DocumentId }) {
|
||||
>
|
||||
Print
|
||||
</Link>
|
||||
</>
|
||||
}
|
||||
title={<DocumentTitle document={doc} />}
|
||||
tabs={[
|
||||
<Link
|
||||
key={""}
|
||||
to="/document/$documentId"
|
||||
params={{
|
||||
documentId,
|
||||
}}
|
||||
>
|
||||
<div className="px-3 py-2 rounded bg-slate-800 text-slate-100 border border-slate-700 focus:outline-none focus:ring-2 focus:ring-violet-500 data-selected:bg-violet-900 data-selected:border-violet-700 whitespace-nowrap">
|
||||
Attributes
|
||||
</div>
|
||||
<DocumentEditForm document={doc} />
|
||||
<nav>
|
||||
<ul className="flex flex-row gap-1">
|
||||
{relationshipList.map((relationshipType) => (
|
||||
</Link>,
|
||||
...relationshipList.map((relationshipType) => (
|
||||
<Link
|
||||
key={relationshipType}
|
||||
to={RelationshipRoute.to}
|
||||
to="/document/$documentId/$relationshipType"
|
||||
params={{
|
||||
documentId,
|
||||
relationshipType,
|
||||
@@ -62,9 +80,18 @@ export function DocumentView({ documentId }: { documentId: DocumentId }) {
|
||||
{relationshipCounts[relationshipType] ?? 0})
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
)),
|
||||
]}
|
||||
content={
|
||||
relationshipType === null ? (
|
||||
<DocumentEditForm document={doc} />
|
||||
) : (
|
||||
<RelatedDocumentList
|
||||
documentId={doc.id}
|
||||
relationshipType={relationshipType}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
16
src/components/layout/TabbedLayout.tsx
Normal file
16
src/components/layout/TabbedLayout.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
export type Props = {
|
||||
title: React.ReactNode;
|
||||
navigation: React.ReactNode;
|
||||
tabs: React.ReactNode[];
|
||||
content: React.ReactNode;
|
||||
};
|
||||
export function TabbedLayout({ navigation, title, tabs, content }: Props) {
|
||||
return (
|
||||
<div>
|
||||
<div>{navigation}</div>
|
||||
<div>{title}</div>
|
||||
<div>{tabs}</div>
|
||||
<div>{content}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -17,10 +17,8 @@ import { Route as AppLoginImport } from './routes/_app/login'
|
||||
import { Route as AppAboutImport } from './routes/_app/about'
|
||||
import { Route as AppAuthenticatedImport } from './routes/_app/_authenticated'
|
||||
import { Route as AppAuthenticatedCampaignsIndexImport } from './routes/_app/_authenticated/campaigns.index'
|
||||
import { Route as AppAuthenticatedDocumentDocumentIdImport } from './routes/_app/_authenticated/document.$documentId'
|
||||
import { Route as AppAuthenticatedCampaignsCampaignIdImport } from './routes/_app/_authenticated/campaigns.$campaignId'
|
||||
import { Route as AppauthenticatedDocumentDocumentIdPrintImport } from './routes/_app_._authenticated.document_.$documentId.print'
|
||||
import { Route as AppAuthenticatedDocumentDocumentIdRelationshipTypeImport } from './routes/_app/_authenticated/document.$documentId/$relationshipType'
|
||||
import { Route as AppAuthenticatedDocumentDocumentIdSplatImport } from './routes/_app/_authenticated/document.$documentId.$'
|
||||
|
||||
// Create/Update Routes
|
||||
|
||||
@@ -59,13 +57,6 @@ const AppAuthenticatedCampaignsIndexRoute =
|
||||
getParentRoute: () => AppAuthenticatedRoute,
|
||||
} as any)
|
||||
|
||||
const AppAuthenticatedDocumentDocumentIdRoute =
|
||||
AppAuthenticatedDocumentDocumentIdImport.update({
|
||||
id: '/document/$documentId',
|
||||
path: '/document/$documentId',
|
||||
getParentRoute: () => AppAuthenticatedRoute,
|
||||
} as any)
|
||||
|
||||
const AppAuthenticatedCampaignsCampaignIdRoute =
|
||||
AppAuthenticatedCampaignsCampaignIdImport.update({
|
||||
id: '/campaigns/$campaignId',
|
||||
@@ -73,18 +64,11 @@ const AppAuthenticatedCampaignsCampaignIdRoute =
|
||||
getParentRoute: () => AppAuthenticatedRoute,
|
||||
} as any)
|
||||
|
||||
const AppauthenticatedDocumentDocumentIdPrintRoute =
|
||||
AppauthenticatedDocumentDocumentIdPrintImport.update({
|
||||
id: '/_app_/_authenticated/document_/$documentId/print',
|
||||
path: '/document/$documentId/print',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const AppAuthenticatedDocumentDocumentIdRelationshipTypeRoute =
|
||||
AppAuthenticatedDocumentDocumentIdRelationshipTypeImport.update({
|
||||
id: '/$relationshipType',
|
||||
path: '/$relationshipType',
|
||||
getParentRoute: () => AppAuthenticatedDocumentDocumentIdRoute,
|
||||
const AppAuthenticatedDocumentDocumentIdSplatRoute =
|
||||
AppAuthenticatedDocumentDocumentIdSplatImport.update({
|
||||
id: '/document/$documentId/$',
|
||||
path: '/document/$documentId/$',
|
||||
getParentRoute: () => AppAuthenticatedRoute,
|
||||
} as any)
|
||||
|
||||
// Populate the FileRoutesByPath interface
|
||||
@@ -133,13 +117,6 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof AppAuthenticatedCampaignsCampaignIdImport
|
||||
parentRoute: typeof AppAuthenticatedImport
|
||||
}
|
||||
'/_app/_authenticated/document/$documentId': {
|
||||
id: '/_app/_authenticated/document/$documentId'
|
||||
path: '/document/$documentId'
|
||||
fullPath: '/document/$documentId'
|
||||
preLoaderRoute: typeof AppAuthenticatedDocumentDocumentIdImport
|
||||
parentRoute: typeof AppAuthenticatedImport
|
||||
}
|
||||
'/_app/_authenticated/campaigns/': {
|
||||
id: '/_app/_authenticated/campaigns/'
|
||||
path: '/campaigns'
|
||||
@@ -147,52 +124,30 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof AppAuthenticatedCampaignsIndexImport
|
||||
parentRoute: typeof AppAuthenticatedImport
|
||||
}
|
||||
'/_app/_authenticated/document/$documentId/$relationshipType': {
|
||||
id: '/_app/_authenticated/document/$documentId/$relationshipType'
|
||||
path: '/$relationshipType'
|
||||
fullPath: '/document/$documentId/$relationshipType'
|
||||
preLoaderRoute: typeof AppAuthenticatedDocumentDocumentIdRelationshipTypeImport
|
||||
parentRoute: typeof AppAuthenticatedDocumentDocumentIdImport
|
||||
}
|
||||
'/_app_/_authenticated/document_/$documentId/print': {
|
||||
id: '/_app_/_authenticated/document_/$documentId/print'
|
||||
path: '/document/$documentId/print'
|
||||
fullPath: '/document/$documentId/print'
|
||||
preLoaderRoute: typeof AppauthenticatedDocumentDocumentIdPrintImport
|
||||
parentRoute: typeof rootRoute
|
||||
'/_app/_authenticated/document/$documentId/$': {
|
||||
id: '/_app/_authenticated/document/$documentId/$'
|
||||
path: '/document/$documentId/$'
|
||||
fullPath: '/document/$documentId/$'
|
||||
preLoaderRoute: typeof AppAuthenticatedDocumentDocumentIdSplatImport
|
||||
parentRoute: typeof AppAuthenticatedImport
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create and export the route tree
|
||||
|
||||
interface AppAuthenticatedDocumentDocumentIdRouteChildren {
|
||||
AppAuthenticatedDocumentDocumentIdRelationshipTypeRoute: typeof AppAuthenticatedDocumentDocumentIdRelationshipTypeRoute
|
||||
}
|
||||
|
||||
const AppAuthenticatedDocumentDocumentIdRouteChildren: AppAuthenticatedDocumentDocumentIdRouteChildren =
|
||||
{
|
||||
AppAuthenticatedDocumentDocumentIdRelationshipTypeRoute:
|
||||
AppAuthenticatedDocumentDocumentIdRelationshipTypeRoute,
|
||||
}
|
||||
|
||||
const AppAuthenticatedDocumentDocumentIdRouteWithChildren =
|
||||
AppAuthenticatedDocumentDocumentIdRoute._addFileChildren(
|
||||
AppAuthenticatedDocumentDocumentIdRouteChildren,
|
||||
)
|
||||
|
||||
interface AppAuthenticatedRouteChildren {
|
||||
AppAuthenticatedCampaignsCampaignIdRoute: typeof AppAuthenticatedCampaignsCampaignIdRoute
|
||||
AppAuthenticatedDocumentDocumentIdRoute: typeof AppAuthenticatedDocumentDocumentIdRouteWithChildren
|
||||
AppAuthenticatedCampaignsIndexRoute: typeof AppAuthenticatedCampaignsIndexRoute
|
||||
AppAuthenticatedDocumentDocumentIdSplatRoute: typeof AppAuthenticatedDocumentDocumentIdSplatRoute
|
||||
}
|
||||
|
||||
const AppAuthenticatedRouteChildren: AppAuthenticatedRouteChildren = {
|
||||
AppAuthenticatedCampaignsCampaignIdRoute:
|
||||
AppAuthenticatedCampaignsCampaignIdRoute,
|
||||
AppAuthenticatedDocumentDocumentIdRoute:
|
||||
AppAuthenticatedDocumentDocumentIdRouteWithChildren,
|
||||
AppAuthenticatedCampaignsIndexRoute: AppAuthenticatedCampaignsIndexRoute,
|
||||
AppAuthenticatedDocumentDocumentIdSplatRoute:
|
||||
AppAuthenticatedDocumentDocumentIdSplatRoute,
|
||||
}
|
||||
|
||||
const AppAuthenticatedRouteWithChildren =
|
||||
@@ -220,10 +175,8 @@ export interface FileRoutesByFullPath {
|
||||
'/login': typeof AppLoginRoute
|
||||
'/': typeof AppIndexRoute
|
||||
'/campaigns/$campaignId': typeof AppAuthenticatedCampaignsCampaignIdRoute
|
||||
'/document/$documentId': typeof AppAuthenticatedDocumentDocumentIdRouteWithChildren
|
||||
'/campaigns': typeof AppAuthenticatedCampaignsIndexRoute
|
||||
'/document/$documentId/$relationshipType': typeof AppAuthenticatedDocumentDocumentIdRelationshipTypeRoute
|
||||
'/document/$documentId/print': typeof AppauthenticatedDocumentDocumentIdPrintRoute
|
||||
'/document/$documentId/$': typeof AppAuthenticatedDocumentDocumentIdSplatRoute
|
||||
}
|
||||
|
||||
export interface FileRoutesByTo {
|
||||
@@ -232,10 +185,8 @@ export interface FileRoutesByTo {
|
||||
'/login': typeof AppLoginRoute
|
||||
'/': typeof AppIndexRoute
|
||||
'/campaigns/$campaignId': typeof AppAuthenticatedCampaignsCampaignIdRoute
|
||||
'/document/$documentId': typeof AppAuthenticatedDocumentDocumentIdRouteWithChildren
|
||||
'/campaigns': typeof AppAuthenticatedCampaignsIndexRoute
|
||||
'/document/$documentId/$relationshipType': typeof AppAuthenticatedDocumentDocumentIdRelationshipTypeRoute
|
||||
'/document/$documentId/print': typeof AppauthenticatedDocumentDocumentIdPrintRoute
|
||||
'/document/$documentId/$': typeof AppAuthenticatedDocumentDocumentIdSplatRoute
|
||||
}
|
||||
|
||||
export interface FileRoutesById {
|
||||
@@ -246,10 +197,8 @@ export interface FileRoutesById {
|
||||
'/_app/login': typeof AppLoginRoute
|
||||
'/_app/': typeof AppIndexRoute
|
||||
'/_app/_authenticated/campaigns/$campaignId': typeof AppAuthenticatedCampaignsCampaignIdRoute
|
||||
'/_app/_authenticated/document/$documentId': typeof AppAuthenticatedDocumentDocumentIdRouteWithChildren
|
||||
'/_app/_authenticated/campaigns/': typeof AppAuthenticatedCampaignsIndexRoute
|
||||
'/_app/_authenticated/document/$documentId/$relationshipType': typeof AppAuthenticatedDocumentDocumentIdRelationshipTypeRoute
|
||||
'/_app_/_authenticated/document_/$documentId/print': typeof AppauthenticatedDocumentDocumentIdPrintRoute
|
||||
'/_app/_authenticated/document/$documentId/$': typeof AppAuthenticatedDocumentDocumentIdSplatRoute
|
||||
}
|
||||
|
||||
export interface FileRouteTypes {
|
||||
@@ -260,10 +209,8 @@ export interface FileRouteTypes {
|
||||
| '/login'
|
||||
| '/'
|
||||
| '/campaigns/$campaignId'
|
||||
| '/document/$documentId'
|
||||
| '/campaigns'
|
||||
| '/document/$documentId/$relationshipType'
|
||||
| '/document/$documentId/print'
|
||||
| '/document/$documentId/$'
|
||||
fileRoutesByTo: FileRoutesByTo
|
||||
to:
|
||||
| ''
|
||||
@@ -271,10 +218,8 @@ export interface FileRouteTypes {
|
||||
| '/login'
|
||||
| '/'
|
||||
| '/campaigns/$campaignId'
|
||||
| '/document/$documentId'
|
||||
| '/campaigns'
|
||||
| '/document/$documentId/$relationshipType'
|
||||
| '/document/$documentId/print'
|
||||
| '/document/$documentId/$'
|
||||
id:
|
||||
| '__root__'
|
||||
| '/_app'
|
||||
@@ -283,22 +228,17 @@ export interface FileRouteTypes {
|
||||
| '/_app/login'
|
||||
| '/_app/'
|
||||
| '/_app/_authenticated/campaigns/$campaignId'
|
||||
| '/_app/_authenticated/document/$documentId'
|
||||
| '/_app/_authenticated/campaigns/'
|
||||
| '/_app/_authenticated/document/$documentId/$relationshipType'
|
||||
| '/_app_/_authenticated/document_/$documentId/print'
|
||||
| '/_app/_authenticated/document/$documentId/$'
|
||||
fileRoutesById: FileRoutesById
|
||||
}
|
||||
|
||||
export interface RootRouteChildren {
|
||||
AppRoute: typeof AppRouteWithChildren
|
||||
AppauthenticatedDocumentDocumentIdPrintRoute: typeof AppauthenticatedDocumentDocumentIdPrintRoute
|
||||
}
|
||||
|
||||
const rootRouteChildren: RootRouteChildren = {
|
||||
AppRoute: AppRouteWithChildren,
|
||||
AppauthenticatedDocumentDocumentIdPrintRoute:
|
||||
AppauthenticatedDocumentDocumentIdPrintRoute,
|
||||
}
|
||||
|
||||
export const routeTree = rootRoute
|
||||
@@ -311,8 +251,7 @@ export const routeTree = rootRoute
|
||||
"__root__": {
|
||||
"filePath": "__root.tsx",
|
||||
"children": [
|
||||
"/_app",
|
||||
"/_app_/_authenticated/document_/$documentId/print"
|
||||
"/_app"
|
||||
]
|
||||
},
|
||||
"/_app": {
|
||||
@@ -329,8 +268,8 @@ export const routeTree = rootRoute
|
||||
"parent": "/_app",
|
||||
"children": [
|
||||
"/_app/_authenticated/campaigns/$campaignId",
|
||||
"/_app/_authenticated/document/$documentId",
|
||||
"/_app/_authenticated/campaigns/"
|
||||
"/_app/_authenticated/campaigns/",
|
||||
"/_app/_authenticated/document/$documentId/$"
|
||||
]
|
||||
},
|
||||
"/_app/about": {
|
||||
@@ -349,23 +288,13 @@ export const routeTree = rootRoute
|
||||
"filePath": "_app/_authenticated/campaigns.$campaignId.tsx",
|
||||
"parent": "/_app/_authenticated"
|
||||
},
|
||||
"/_app/_authenticated/document/$documentId": {
|
||||
"filePath": "_app/_authenticated/document.$documentId.tsx",
|
||||
"parent": "/_app/_authenticated",
|
||||
"children": [
|
||||
"/_app/_authenticated/document/$documentId/$relationshipType"
|
||||
]
|
||||
},
|
||||
"/_app/_authenticated/campaigns/": {
|
||||
"filePath": "_app/_authenticated/campaigns.index.tsx",
|
||||
"parent": "/_app/_authenticated"
|
||||
},
|
||||
"/_app/_authenticated/document/$documentId/$relationshipType": {
|
||||
"filePath": "_app/_authenticated/document.$documentId/$relationshipType.tsx",
|
||||
"parent": "/_app/_authenticated/document/$documentId"
|
||||
},
|
||||
"/_app_/_authenticated/document_/$documentId/print": {
|
||||
"filePath": "_app_._authenticated.document_.$documentId.print.tsx"
|
||||
"/_app/_authenticated/document/$documentId/$": {
|
||||
"filePath": "_app/_authenticated/document.$documentId.$.tsx",
|
||||
"parent": "/_app/_authenticated"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
49
src/routes/_app/_authenticated/document.$documentId.$.tsx
Normal file
49
src/routes/_app/_authenticated/document.$documentId.$.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { DocumentView } from "@/components/documents/DocumentView";
|
||||
import { DocumentLoader } from "@/context/document/DocumentLoader";
|
||||
import type { DocumentId } from "@/lib/types";
|
||||
import { RelationshipType } from "@/lib/types";
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import * as z from "zod";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_app/_authenticated/document/$documentId/$",
|
||||
)({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
const documentParams = z
|
||||
.templateLiteral([
|
||||
z.string(),
|
||||
z.optional(z.literal("/")),
|
||||
z.optional(z.string()),
|
||||
])
|
||||
.pipe(
|
||||
z.transform((path: string) => {
|
||||
if (path === "") {
|
||||
return {
|
||||
relationshipType: null,
|
||||
childDoc: null,
|
||||
};
|
||||
}
|
||||
const [relationshipType, childDoc] = path.split("/");
|
||||
return {
|
||||
relationshipType: (relationshipType ?? null) as RelationshipType | null,
|
||||
childDoc: (childDoc ?? null) as DocumentId | null,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
function RouteComponent() {
|
||||
const { documentId, _splat } = Route.useParams();
|
||||
|
||||
const { relationshipType, childDoc } = documentParams.parse(_splat);
|
||||
|
||||
return (
|
||||
<DocumentLoader documentId={documentId as DocumentId}>
|
||||
<DocumentView
|
||||
documentId={documentId as DocumentId}
|
||||
relationshipType={relationshipType}
|
||||
/>
|
||||
</DocumentLoader>
|
||||
);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import { DocumentView } from "@/components/documents/DocumentView";
|
||||
import { DocumentLoader } from "@/context/document/DocumentLoader";
|
||||
import type { DocumentId } from "@/lib/types";
|
||||
import { createFileRoute, Outlet } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_app/_authenticated/document/$documentId",
|
||||
)({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { documentId } = Route.useParams();
|
||||
|
||||
return (
|
||||
<DocumentLoader documentId={documentId as DocumentId}>
|
||||
<DocumentView documentId={documentId as DocumentId} />
|
||||
<Outlet />
|
||||
</DocumentLoader>
|
||||
);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { RelatedDocumentList } from "@/components/documents/RelatedDocumentList";
|
||||
import type { DocumentId, RelationshipType } from "@/lib/types";
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_app/_authenticated/document/$documentId/$relationshipType",
|
||||
)({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { documentId, relationshipType } = Route.useParams();
|
||||
return (
|
||||
<RelatedDocumentList
|
||||
documentId={documentId as DocumentId}
|
||||
relationshipType={relationshipType as RelationshipType}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import { DocumentPrintRow } from "@/components/documents/DocumentPrintRow";
|
||||
import { SessionPrintRow } from "@/components/documents/session/SessionPrintRow";
|
||||
import { Loader } from "@/components/Loader";
|
||||
import { useDocument, useDocumentCache } from "@/context/document/hooks";
|
||||
import { RelationshipType, type DocumentId, type Session } from "@/lib/types";
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import _ from "lodash";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_app_/_authenticated/document_/$documentId/print",
|
||||
)({
|
||||
component: RouteComponent,
|
||||
pendingComponent: Loader,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const params = Route.useParams();
|
||||
|
||||
const { cache } = useDocumentCache();
|
||||
const { docResult } = useDocument(params.documentId as DocumentId);
|
||||
|
||||
if (docResult.type !== "ready") {
|
||||
return <Loader />;
|
||||
}
|
||||
|
||||
const session = docResult.value.doc as Session;
|
||||
const relationships = _.mapValues(
|
||||
docResult.value.relationships,
|
||||
(relResult) => {
|
||||
if (relResult.type != "ready") {
|
||||
return [];
|
||||
}
|
||||
return relResult.value.secondary
|
||||
.map((id) => cache.documents[id])
|
||||
.flatMap((docResult) =>
|
||||
docResult.type === "ready" ? [docResult.value.doc] : [],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="fill-w py-8 columns-2 gap-8 text-sm">
|
||||
<SessionPrintRow session={session}></SessionPrintRow>
|
||||
{[
|
||||
RelationshipType.Scenes,
|
||||
RelationshipType.Secrets,
|
||||
RelationshipType.Locations,
|
||||
RelationshipType.Npcs,
|
||||
RelationshipType.Monsters,
|
||||
RelationshipType.Treasures,
|
||||
].map((relationshipType) => (
|
||||
<div className="break-inside-avoid">
|
||||
<h3 className="text-lg font-bold text-slate-600">
|
||||
{relationshipType.charAt(0).toUpperCase() +
|
||||
relationshipType.slice(1)}
|
||||
</h3>
|
||||
|
||||
<ul className="list-disc pl-5">
|
||||
{(relationships[relationshipType] ?? []).map((item) => (
|
||||
<DocumentPrintRow document={item} />
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user