Completes the three-panel layout
This commit is contained in:
@@ -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>
|
||||
);
|
||||
|
||||
21
src/components/documents/DocumentLink.tsx
Normal file
21
src/components/documents/DocumentLink.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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} />;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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} />;
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user