Completes the three-panel layout

This commit is contained in:
2025-07-21 20:50:18 -07:00
parent 3390ecfb95
commit 8533f63a22
11 changed files with 184 additions and 74 deletions

View File

@@ -1,10 +1,11 @@
import type { AnyDocument } from "@/lib/types";
import { Link } from "@tanstack/react-router";
import type { AnyDocument, DocumentId } from "@/lib/types";
import { DocumentLink } from "./DocumentLink";
export type Props = {
doc: AnyDocument;
title: string;
description?: string;
link: (id: DocumentId) => string;
};
/**
@@ -13,13 +14,12 @@ export type Props = {
export const BasicRow = ({ doc, title, description }: Props) => {
return (
<div>
<Link
to="/document/$documentId"
params={{ documentId: doc.id }}
<DocumentLink
childDocId={doc.id}
className="text-lg !no-underline text-slate-100 hover:underline hover:text-violet-400"
>
<h4>{title}</h4>
</Link>
</DocumentLink>
{description && <p>{description}</p>}
</div>
);

View File

@@ -0,0 +1,21 @@
import { makeDocumentPath, useDocumentPath } from "@/lib/documentPath";
import type { DocumentId, RelationshipType } from "@/lib/types";
import { Link } from "@tanstack/react-router";
export type Props = React.PropsWithChildren<{
childDocId: DocumentId;
className?: string;
}>;
export function DocumentLink({ childDocId, className, children }: Props) {
const { documentId, relationshipType } = useDocumentPath();
return (
<Link
to={makeDocumentPath(documentId, relationshipType, childDocId)}
className={className}
>
{children}
</Link>
);
}

View File

@@ -11,10 +11,10 @@ import { TreasureToggleRow } from "./treasure/TreasureToggleRow";
*/
export const DocumentRow = ({
document,
session,
root,
}: {
document: AnyDocument;
session?: Session;
root?: AnyDocument;
}) => {
switch (document.type) {
case "location":
@@ -48,12 +48,12 @@ export const DocumentRow = ({
);
case "secret":
return <SecretToggleRow secret={document} session={session} />;
return <SecretToggleRow secret={document} root={root} />;
case "scene":
return <BasicRow doc={document} title={document.data.text} />;
case "treasure":
return <TreasureToggleRow treasure={document} session={session} />;
return <TreasureToggleRow treasure={document} root={root} />;
}
};

View File

@@ -6,16 +6,18 @@ import { Link } from "@tanstack/react-router";
import _ from "lodash";
import { Loader } from "../Loader";
import { DocumentTitle } from "./DocumentTitle";
import { TabbedLayout } from "../layout/TabbedLayout";
import { Tab, TabbedLayout } from "../layout/TabbedLayout";
import { DocumentEditForm } from "./DocumentEditForm";
import { RelatedDocumentList } from "./RelatedDocumentList";
export function DocumentView({
documentId,
relationshipType,
childDocId,
}: {
documentId: DocumentId;
relationshipType: RelationshipType | null;
childDocId: DocumentId | null;
}) {
const { docResult } = useDocument(documentId);
@@ -55,31 +57,24 @@ export function DocumentView({
}
title={<DocumentTitle document={doc} />}
tabs={[
<Link
key={""}
<Tab
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>
</Link>,
...relationshipList.map((relationshipType) => (
<Link
key={relationshipType}
label="Attributes"
active={relationshipType === null}
/>,
...relationshipList.map((relationshipEntry) => (
<Tab
to="/document/$documentId/$relationshipType"
params={{
documentId,
relationshipType,
relationshipType: relationshipEntry,
}}
>
<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">
{displayName(relationshipType)} (
{relationshipCounts[relationshipType] ?? 0})
</div>
</Link>
label={`${displayName(relationshipEntry)} (${relationshipCounts[relationshipEntry] ?? 0})`}
active={relationshipEntry === relationshipType}
/>
)),
]}
content={
@@ -92,6 +87,19 @@ export function DocumentView({
/>
)
}
flyout={childDocId && <Flyout docId={childDocId} />}
/>
);
}
function Flyout({ docId }: { docId: DocumentId }) {
const { docResult } = useDocument(docId);
if (docResult?.type !== "ready") {
return <Loader />;
}
const doc = docResult.value.doc;
return <DocumentEditForm document={doc} />;
}

View File

@@ -1,7 +1,7 @@
// SecretRow.tsx
// Displays a single secret with discovered checkbox and text.
import { pb } from "@/lib/pocketbase";
import type { Secret, Session } from "@/lib/types";
import type { AnyDocument, Secret } from "@/lib/types";
import { useState } from "react";
/**
@@ -10,10 +10,10 @@ import { useState } from "react";
*/
export const SecretToggleRow = ({
secret,
session,
root,
}: {
secret: Secret;
session?: Session;
root?: AnyDocument;
}) => {
const [checked, setChecked] = useState(
!!(secret.data as any)?.secret?.discovered,
@@ -36,7 +36,7 @@ export const SecretToggleRow = ({
},
},
});
if (session || !newChecked) {
if (root || !newChecked) {
// If the session exists or the element is being unchecked, remove any
// existing discoveredIn relationship
const rels = await pb.collection("relationships").getList(1, 1, {
@@ -46,11 +46,11 @@ export const SecretToggleRow = ({
await pb.collection("relationships").delete(rels.items[0].id);
}
}
if (session) {
if (root) {
if (newChecked) {
await pb.collection("relationships").create({
primary: secret.id,
secondary: [session.id],
secondary: [root.id],
type: "discoveredIn",
});
}

View File

@@ -1,7 +1,7 @@
// TreasureRow.tsx
// Displays a single treasure with discovered checkbox and text.
import { pb } from "@/lib/pocketbase";
import type { Session, Treasure } from "@/lib/types";
import type { AnyDocument, Treasure } from "@/lib/types";
import { Link } from "@tanstack/react-router";
import { useState } from "react";
@@ -11,10 +11,10 @@ import { useState } from "react";
*/
export const TreasureToggleRow = ({
treasure,
session,
root,
}: {
treasure: Treasure;
session?: Session;
root?: AnyDocument;
}) => {
const [checked, setChecked] = useState(
!!(treasure.data as any)?.treasure?.discovered,
@@ -35,7 +35,7 @@ export const TreasureToggleRow = ({
},
},
});
if (session || !newChecked) {
if (root || !newChecked) {
// If the session exists or the element is being unchecked, remove any
// existing discoveredIn relationship
const rels = await pb.collection("relationships").getList(1, 1, {
@@ -45,11 +45,11 @@ export const TreasureToggleRow = ({
await pb.collection("relationships").delete(rels.items[0].id);
}
}
if (session) {
if (root) {
if (newChecked) {
await pb.collection("relationships").create({
primary: treasure.id,
secondary: [session.id],
secondary: [root.id],
type: "discoveredIn",
});
}