From c0638e34a845d0d007647748ea41e9740fd7a5e6 Mon Sep 17 00:00:00 2001 From: Drew Haven Date: Thu, 9 Oct 2025 16:48:50 -0700 Subject: [PATCH] Uses generic forms everywhere, gets rid of most doc-specific stuff --- src/components/documents/DocumentEditForm.tsx | 33 -------- src/components/documents/DocumentPreview.tsx | 4 +- src/components/documents/DocumentPrintRow.tsx | 33 -------- src/components/documents/DocumentView.tsx | 10 +-- .../documents/NewCampaignDocumentForm.tsx | 7 +- .../documents/NewRelatedDocumentForm.tsx | 31 +++----- .../documents/location/LocationEditForm.tsx | 48 ------------ .../documents/location/LocationPrintRow.tsx | 13 ---- .../documents/location/NewLocationForm.tsx | 76 ------------------- .../documents/monsters/MonsterEditForm.tsx | 32 -------- .../documents/monsters/MonsterPrintRow.tsx | 8 -- .../documents/monsters/NewMonsterForm.tsx | 61 --------------- src/components/documents/npc/NewNpcForm.tsx | 76 ------------------- src/components/documents/npc/NpcEditForm.tsx | 44 ----------- src/components/documents/npc/NpcPrintRow.tsx | 13 ---- .../documents/scene/NewSceneForm.tsx | 67 ---------------- .../documents/scene/SceneEditForm.tsx | 27 ------- .../documents/scene/ScenePrintRow.tsx | 8 -- .../documents/secret/NewSecretForm.tsx | 64 ---------------- .../documents/secret/SecretEditForm.tsx | 65 ---------------- .../documents/secret/SecretPrintRow.tsx | 24 ------ .../documents/session/SessionEditForm.tsx | 33 -------- .../documents/session/SessionPrintRow.tsx | 10 --- .../documents/session/SessionRow.tsx | 19 ----- .../documents/treasure/NewTreasureForm.tsx | 67 ---------------- .../documents/treasure/TreasureEditForm.tsx | 70 ----------------- .../documents/treasure/TreasurePrintRow.tsx | 24 ------ src/lib/relationships.ts | 21 ++++- 28 files changed, 37 insertions(+), 951 deletions(-) delete mode 100644 src/components/documents/DocumentEditForm.tsx delete mode 100644 src/components/documents/DocumentPrintRow.tsx delete mode 100644 src/components/documents/location/LocationEditForm.tsx delete mode 100644 src/components/documents/location/LocationPrintRow.tsx delete mode 100644 src/components/documents/location/NewLocationForm.tsx delete mode 100644 src/components/documents/monsters/MonsterEditForm.tsx delete mode 100644 src/components/documents/monsters/MonsterPrintRow.tsx delete mode 100644 src/components/documents/monsters/NewMonsterForm.tsx delete mode 100644 src/components/documents/npc/NewNpcForm.tsx delete mode 100644 src/components/documents/npc/NpcEditForm.tsx delete mode 100644 src/components/documents/npc/NpcPrintRow.tsx delete mode 100644 src/components/documents/scene/NewSceneForm.tsx delete mode 100644 src/components/documents/scene/SceneEditForm.tsx delete mode 100644 src/components/documents/scene/ScenePrintRow.tsx delete mode 100644 src/components/documents/secret/NewSecretForm.tsx delete mode 100644 src/components/documents/secret/SecretEditForm.tsx delete mode 100644 src/components/documents/secret/SecretPrintRow.tsx delete mode 100644 src/components/documents/session/SessionEditForm.tsx delete mode 100644 src/components/documents/session/SessionPrintRow.tsx delete mode 100644 src/components/documents/session/SessionRow.tsx delete mode 100644 src/components/documents/treasure/NewTreasureForm.tsx delete mode 100644 src/components/documents/treasure/TreasureEditForm.tsx delete mode 100644 src/components/documents/treasure/TreasurePrintRow.tsx diff --git a/src/components/documents/DocumentEditForm.tsx b/src/components/documents/DocumentEditForm.tsx deleted file mode 100644 index 06f11c8..0000000 --- a/src/components/documents/DocumentEditForm.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { type AnyDocument } from "@/lib/types"; -import { LocationEditForm } from "./location/LocationEditForm"; -import { MonsterEditForm } from "./monsters/MonsterEditForm"; -import { NpcEditForm } from "./npc/NpcEditForm"; -import { SceneEditForm } from "./scene/SceneEditForm"; -import { SecretEditForm } from "./secret/SecretEditForm"; -import { SessionEditForm } from "./session/SessionEditForm"; -import { TreasureEditForm } from "./treasure/TreasureEditForm"; -import { GenericEditForm } from "./GenericEditForm"; - -/** - * Renders a form for any document type depending on the relationship. - */ -export const DocumentEditForm = ({ document }: { document: AnyDocument }) => { - switch (document.type) { - case "location": - return ; - case "monster": - return ; - case "npc": - return ; - case "scene": - return ; - case "secret": - return ; - case "session": - return ; - case "treasure": - return ; - case "thread": - return ; - } -}; diff --git a/src/components/documents/DocumentPreview.tsx b/src/components/documents/DocumentPreview.tsx index 86d6d4e..8b63922 100644 --- a/src/components/documents/DocumentPreview.tsx +++ b/src/components/documents/DocumentPreview.tsx @@ -5,7 +5,7 @@ import { type AnyDocument } from "@/lib/types"; import { Link } from "@tanstack/react-router"; import { Editing, EditToggle, NotEditing } from "../EditToggle"; import { BasicPreview } from "./BasicPreview"; -import { DocumentEditForm } from "./DocumentEditForm"; +import { GenericEditForm } from "./GenericEditForm"; export const DocumentPreview = ({ doc }: { doc: AnyDocument }) => { const relationships = relationshipsForDocument(doc); @@ -13,7 +13,7 @@ export const DocumentPreview = ({ doc }: { doc: AnyDocument }) => {
- + diff --git a/src/components/documents/DocumentPrintRow.tsx b/src/components/documents/DocumentPrintRow.tsx deleted file mode 100644 index 835edb3..0000000 --- a/src/components/documents/DocumentPrintRow.tsx +++ /dev/null @@ -1,33 +0,0 @@ -// DocumentRow.tsx -// Generic row component for displaying any document type. -import { type AnyDocument } from "@/lib/types"; -import { LocationPrintRow } from "./location/LocationPrintRow"; -import { MonsterPrintRow } from "./monsters/MonsterPrintRow"; -import { NpcPrintRow } from "./npc/NpcPrintRow"; -import { ScenePrintRow } from "./scene/ScenePrintRow"; -import { SecretPrintRow } from "./secret/SecretPrintRow"; -import { SessionPrintRow } from "./session/SessionPrintRow"; -import { TreasurePrintRow } from "./treasure/TreasurePrintRow"; - -/** - * Renders a row for any document type. Prioritizes Session, then Secret, then falls back to ID and creation time. - * If rendering a SecretRow, uses the provided session prop if available. - */ -export const DocumentPrintRow = ({ document }: { document: AnyDocument }) => { - switch (document.type) { - case "location": - return ; - case "monster": - return ; - case "npc": - return ; - case "scene": - return ; - case "secret": - return ; - case "session": - return ; - case "treasure": - return ; - } -}; diff --git a/src/components/documents/DocumentView.tsx b/src/components/documents/DocumentView.tsx index 2f19aa0..224189d 100644 --- a/src/components/documents/DocumentView.tsx +++ b/src/components/documents/DocumentView.tsx @@ -3,12 +3,12 @@ import { displayName, relationshipsForDocument } from "@/lib/relationships"; import { RelationshipType, type DocumentId } from "@/lib/types"; import { Link } from "@tanstack/react-router"; import _ from "lodash"; -import { Loader } from "../Loader"; -import { DocumentTitle } from "./DocumentTitle"; import { Tab, TabbedLayout } from "../layout/TabbedLayout"; -import { DocumentEditForm } from "./DocumentEditForm"; -import { RelatedDocumentList } from "./RelatedDocumentList"; +import { Loader } from "../Loader"; import { DocumentPreview } from "./DocumentPreview"; +import { DocumentTitle } from "./DocumentTitle"; +import { GenericEditForm } from "./GenericEditForm"; +import { RelatedDocumentList } from "./RelatedDocumentList"; export function DocumentView({ documentId, @@ -83,7 +83,7 @@ export function DocumentView({ ]} content={ relationshipType === null ? ( - + ) : ( ; - case "thread": - case "location": + default: return ( ); - default: - throw new Error( - `Rendered NewCampaignDocumentForm with unsupported docType: ${docType}`, - ); } }; diff --git a/src/components/documents/NewRelatedDocumentForm.tsx b/src/components/documents/NewRelatedDocumentForm.tsx index 0199274..f07b6ac 100644 --- a/src/components/documents/NewRelatedDocumentForm.tsx +++ b/src/components/documents/NewRelatedDocumentForm.tsx @@ -3,12 +3,8 @@ import { type CampaignId, type AnyDocument, } from "@/lib/types"; -import { NewLocationForm } from "./location/NewLocationForm"; -import { NewMonsterForm } from "./monsters/NewMonsterForm"; -import { NewNpcForm } from "./npc/NewNpcForm"; -import { NewSceneForm } from "./scene/NewSceneForm"; -import { NewSecretForm } from "./secret/NewSecretForm"; -import { NewTreasureForm } from "./treasure/NewTreasureForm"; +import { GenericNewDocumentForm } from "./GenericNewDocumentForm"; +import { docTypeForRelationshipType } from "@/lib/relationships"; /** * Renders a form for any document type depending on the relationship. @@ -22,20 +18,11 @@ export const NewRelatedDocumentForm = ({ relationshipType: RelationshipType; onCreate: (doc: AnyDocument) => Promise; }) => { - switch (relationshipType) { - case RelationshipType.Locations: - return ; - case RelationshipType.Monsters: - return ; - case RelationshipType.Npcs: - return ; - case RelationshipType.Secrets: - return ; - case RelationshipType.Treasures: - return ; - case RelationshipType.Scenes: - return ; - case RelationshipType.DiscoveredIn: - return "Form not supported here"; - } + return ( + + ); }; diff --git a/src/components/documents/location/LocationEditForm.tsx b/src/components/documents/location/LocationEditForm.tsx deleted file mode 100644 index bc13c82..0000000 --- a/src/components/documents/location/LocationEditForm.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; -import { pb } from "@/lib/pocketbase"; -import type { Location } from "@/lib/types"; -import { useDocumentCache } from "@/context/document/hooks"; - -/** - * Renders an editable location form - */ -export const LocationEditForm = ({ location }: { location: Location }) => { - const { dispatch } = useDocumentCache(); - async function saveLocationName(name: string) { - const updated: Location = await pb - .collection("documents") - .update(location.id, { - data: { - ...location.data, - name, - }, - }); - dispatch({ type: "setDocument", doc: updated }); - } - - async function saveLocationDescription(description: string) { - const updated: Location = await pb - .collection("documents") - .update(location.id, { - data: { - ...location.data, - description, - }, - }); - dispatch({ type: "setDocument", doc: updated }); - } - - return ( -
- - -
- ); -}; diff --git a/src/components/documents/location/LocationPrintRow.tsx b/src/components/documents/location/LocationPrintRow.tsx deleted file mode 100644 index 0b1acf1..0000000 --- a/src/components/documents/location/LocationPrintRow.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import type { Location } from "@/lib/types"; - -/** - * Renders an print-friendly location row - */ -export const LocationPrintRow = ({ location }: { location: Location }) => { - return ( -
-

{location.data.name}

-

{location.data.description}

-
- ); -}; diff --git a/src/components/documents/location/NewLocationForm.tsx b/src/components/documents/location/NewLocationForm.tsx deleted file mode 100644 index 0860ac9..0000000 --- a/src/components/documents/location/NewLocationForm.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { useState } from "react"; -import type { CampaignId, Location } from "@/lib/types"; -import { pb } from "@/lib/pocketbase"; -import { BaseForm } from "@/components/form/BaseForm"; -import { MultiLineInput } from "@/components/form/MultiLineInput"; -import { SingleLineInput } from "@/components/form/SingleLineInput"; -import { useDocumentCache } from "@/context/document/hooks"; - -/** - * Renders a form to add a new location. Calls onCreate with the new location document. - */ -export const NewLocationForm = ({ - campaign, - onCreate, -}: { - campaign: CampaignId; - onCreate: (location: Location) => Promise; -}) => { - const { dispatch } = useDocumentCache(); - const [name, setName] = useState(""); - const [description, setDescription] = useState(""); - const [adding, setAdding] = useState(false); - const [error, setError] = useState(null); - - async function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - if (!name.trim()) return; - setAdding(true); - setError(null); - try { - const locationDoc: Location = await pb.collection("documents").create({ - campaign, - type: "location", - data: { - name, - description, - }, - }); - setName(""); - setDescription(""); - dispatch({ type: "setDocument", doc: locationDoc }); - await onCreate(locationDoc); - } catch (e: any) { - setError(e?.message || "Failed to add location."); - } finally { - setAdding(false); - } - } - - return ( - - - - - } - /> - ); -}; diff --git a/src/components/documents/monsters/MonsterEditForm.tsx b/src/components/documents/monsters/MonsterEditForm.tsx deleted file mode 100644 index fccc8b4..0000000 --- a/src/components/documents/monsters/MonsterEditForm.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; -import { pb } from "@/lib/pocketbase"; -import type { Monster } from "@/lib/types"; -import { useDocumentCache } from "@/context/document/hooks"; - -/** - * Renders an editable monster row - */ -export const MonsterEditForm = ({ monster }: { monster: Monster }) => { - const { dispatch } = useDocumentCache(); - async function saveMonsterName(name: string) { - const updated: Monster = await pb - .collection("documents") - .update(monster.id, { - data: { - ...monster.data, - name, - }, - }); - dispatch({ type: "setDocument", doc: updated }); - } - - return ( -
- -
- ); -}; diff --git a/src/components/documents/monsters/MonsterPrintRow.tsx b/src/components/documents/monsters/MonsterPrintRow.tsx deleted file mode 100644 index a849dd4..0000000 --- a/src/components/documents/monsters/MonsterPrintRow.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import type { Monster } from "@/lib/types"; - -/** - * Renders an editable monster row - */ -export const MonsterPrintRow = ({ monster }: { monster: Monster }) => { - return
{monster.data.name}
; -}; diff --git a/src/components/documents/monsters/NewMonsterForm.tsx b/src/components/documents/monsters/NewMonsterForm.tsx deleted file mode 100644 index 6f54209..0000000 --- a/src/components/documents/monsters/NewMonsterForm.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { useState } from "react"; -import type { CampaignId, Monster } from "@/lib/types"; -import { pb } from "@/lib/pocketbase"; -import { BaseForm } from "@/components/form/BaseForm"; -import { SingleLineInput } from "@/components/form/SingleLineInput"; -import { useDocumentCache } from "@/context/document/hooks"; - -/** - * Renders a form to add a new monster. Calls onCreate with the new monster document. - */ -export const NewMonsterForm = ({ - campaign, - onCreate, -}: { - campaign: CampaignId; - onCreate: (monster: Monster) => Promise; -}) => { - const { dispatch } = useDocumentCache(); - const [name, setName] = useState(""); - const [adding, setAdding] = useState(false); - const [error, setError] = useState(null); - - async function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - if (!name.trim()) return; - setAdding(true); - setError(null); - try { - const monsterDoc: Monster = await pb.collection("documents").create({ - campaign, - type: "monster", - data: { - name, - }, - }); - setName(""); - dispatch({ type: "setDocument", doc: monsterDoc }); - await onCreate(monsterDoc); - } catch (e: any) { - setError(e?.message || "Failed to add monster."); - } finally { - setAdding(false); - } - } - - return ( - - } - /> - ); -}; diff --git a/src/components/documents/npc/NewNpcForm.tsx b/src/components/documents/npc/NewNpcForm.tsx deleted file mode 100644 index a6846b9..0000000 --- a/src/components/documents/npc/NewNpcForm.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { useState } from "react"; -import type { CampaignId, Npc } from "@/lib/types"; -import { pb } from "@/lib/pocketbase"; -import { BaseForm } from "@/components/form/BaseForm"; -import { SingleLineInput } from "@/components/form/SingleLineInput"; -import { MultiLineInput } from "@/components/form/MultiLineInput"; -import { useDocumentCache } from "@/context/document/hooks"; - -/** - * Renders a form to add a new npc. Calls onCreate with the new npc document. - */ -export const NewNpcForm = ({ - campaign, - onCreate, -}: { - campaign: CampaignId; - onCreate: (npc: Npc) => Promise; -}) => { - const { dispatch } = useDocumentCache(); - const [name, setName] = useState(""); - const [description, setDescription] = useState(""); - const [adding, setAdding] = useState(false); - const [error, setError] = useState(null); - - async function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - if (!name.trim()) return; - setAdding(true); - setError(null); - try { - const npcDoc: Npc = await pb.collection("documents").create({ - campaign, - type: "npc", - data: { - name, - description, - }, - }); - setName(""); - setDescription(""); - dispatch({ type: "setDocument", doc: npcDoc }); - await onCreate(npcDoc); - } catch (e: any) { - setError(e?.message || "Failed to add npc."); - } finally { - setAdding(false); - } - } - - return ( - - - - - } - /> - ); -}; diff --git a/src/components/documents/npc/NpcEditForm.tsx b/src/components/documents/npc/NpcEditForm.tsx deleted file mode 100644 index b035514..0000000 --- a/src/components/documents/npc/NpcEditForm.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; -import { useDocumentCache } from "@/context/document/hooks"; -import { pb } from "@/lib/pocketbase"; -import type { Npc } from "@/lib/types"; - -/** - * Renders an editable npc form - */ -export const NpcEditForm = ({ npc }: { npc: Npc }) => { - const { dispatch } = useDocumentCache(); - async function saveNpcName(name: string) { - const updated: Npc = await pb.collection("documents").update(npc.id, { - data: { - ...npc.data, - name, - }, - }); - dispatch({ type: "setDocument", doc: updated }); - } - - async function saveNpcDescription(description: string) { - const updated: Npc = await pb.collection("documents").update(npc.id, { - data: { - ...npc.data, - description, - }, - }); - dispatch({ type: "setDocument", doc: updated }); - } - - return ( -
- - -
- ); -}; diff --git a/src/components/documents/npc/NpcPrintRow.tsx b/src/components/documents/npc/NpcPrintRow.tsx deleted file mode 100644 index 088c4b7..0000000 --- a/src/components/documents/npc/NpcPrintRow.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import type { Npc } from "@/lib/types"; - -/** - * Renders an editable npc row - */ -export const NpcPrintRow = ({ npc }: { npc: Npc }) => { - return ( -
-

{npc.data.name}

-

{npc.data.description}

-
- ); -}; diff --git a/src/components/documents/scene/NewSceneForm.tsx b/src/components/documents/scene/NewSceneForm.tsx deleted file mode 100644 index 2698bb2..0000000 --- a/src/components/documents/scene/NewSceneForm.tsx +++ /dev/null @@ -1,67 +0,0 @@ -// SceneForm.tsx -// Form for adding a new scene to a session. -import { useState } from "react"; -import type { CampaignId, Scene } from "@/lib/types"; -import { pb } from "@/lib/pocketbase"; -import { BaseForm } from "@/components/form/BaseForm"; -import { MultiLineInput } from "@/components/form/MultiLineInput"; -import { useDocumentCache } from "@/context/document/hooks"; - -/** - * Renders a form to add a new scene. Calls onCreate with the new scene document. - */ -export const NewSceneForm = ({ - campaign, - onCreate, -}: { - campaign: CampaignId; - onCreate: (scene: Scene) => Promise; -}) => { - const { dispatch } = useDocumentCache(); - const [text, setText] = useState(""); - const [adding, setAdding] = useState(false); - const [error, setError] = useState(null); - - async function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - if (!text.trim()) return; - setAdding(true); - setError(null); - try { - const sceneDoc: Scene = await pb.collection("documents").create({ - campaign, - type: "scene", - data: { - text, - }, - }); - setText(""); - dispatch({ type: "setDocument", doc: sceneDoc }); - await onCreate(sceneDoc); - } catch (e: any) { - setError(e?.message || "Failed to add scene."); - } finally { - setAdding(false); - } - } - - return ( - - setText(v)} - disabled={adding} - placeholder="Scene description..." - aria-label="Add new scene" - /> - - } - /> - ); -}; diff --git a/src/components/documents/scene/SceneEditForm.tsx b/src/components/documents/scene/SceneEditForm.tsx deleted file mode 100644 index 6a92124..0000000 --- a/src/components/documents/scene/SceneEditForm.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; -import { pb } from "@/lib/pocketbase"; -import type { Scene } from "@/lib/types"; -import { useDocumentCache } from "@/context/document/hooks"; - -/** - * Renders an editable scene form - */ -export const SceneEditForm = ({ scene }: { scene: Scene }) => { - const { dispatch } = useDocumentCache(); - - async function saveScene(text: string) { - const updated: Scene = await pb.collection("documents").update(scene.id, { - data: { - ...scene.data, - text, - }, - }); - dispatch({ type: "setDocument", doc: updated }); - } - - return ( -
- -
- ); -}; diff --git a/src/components/documents/scene/ScenePrintRow.tsx b/src/components/documents/scene/ScenePrintRow.tsx deleted file mode 100644 index 970f23e..0000000 --- a/src/components/documents/scene/ScenePrintRow.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import type { Scene } from "@/lib/types"; - -/** - * Renders an editable scene row - */ -export const ScenePrintRow = ({ scene }: { scene: Scene }) => { - return
{scene.data.text}
; -}; diff --git a/src/components/documents/secret/NewSecretForm.tsx b/src/components/documents/secret/NewSecretForm.tsx deleted file mode 100644 index d08e389..0000000 --- a/src/components/documents/secret/NewSecretForm.tsx +++ /dev/null @@ -1,64 +0,0 @@ -// SecretForm.tsx -// Form for adding a new secret to a session. -import { useState } from "react"; -import type { CampaignId, Secret } from "@/lib/types"; -import { pb } from "@/lib/pocketbase"; -import { BaseForm } from "@/components/form/BaseForm"; -import { SingleLineInput } from "@/components/form/SingleLineInput"; -import { useDocumentCache } from "@/context/document/hooks"; - -/** - * Renders a form to add a new secret. Calls onCreate with the new secret document. - */ -export const NewSecretForm = ({ - campaign, - onCreate, -}: { - campaign: CampaignId; - onCreate: (secret: Secret) => Promise; -}) => { - const { dispatch } = useDocumentCache(); - const [newSecret, setNewSecret] = useState(""); - const [adding, setAdding] = useState(false); - const [error, setError] = useState(null); - - async function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - if (!newSecret.trim()) return; - setAdding(true); - setError(null); - try { - const secretDoc: Secret = await pb.collection("documents").create({ - campaign, - type: "secret", - data: { - text: newSecret, - discovered: false, - }, - }); - setNewSecret(""); - dispatch({ type: "setDocument", doc: secretDoc as Secret }); - await onCreate(secretDoc); - } catch (e: any) { - setError(e?.message || "Failed to add secret."); - } finally { - setAdding(false); - } - } - - return ( - - } - /> - ); -}; diff --git a/src/components/documents/secret/SecretEditForm.tsx b/src/components/documents/secret/SecretEditForm.tsx deleted file mode 100644 index 5539a1e..0000000 --- a/src/components/documents/secret/SecretEditForm.tsx +++ /dev/null @@ -1,65 +0,0 @@ -// Displays a single secret with discovered checkbox and text. -import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; -import { useDocumentCache } from "@/context/document/hooks"; -import { pb } from "@/lib/pocketbase"; -import type { Secret } from "@/lib/types"; -import { useState } from "react"; - -/** - * Renders an editable secret form. - * Handles updating the discovered state and discoveredIn relationship. - */ -export const SecretEditForm = ({ secret }: { secret: Secret }) => { - const { dispatch } = useDocumentCache(); - const [checked, setChecked] = useState( - !!(secret.data as any)?.secret?.discovered, - ); - const [loading, setLoading] = useState(false); - - async function handleChange(e: React.ChangeEvent) { - const newChecked = e.target.checked; - setLoading(true); - setChecked(newChecked); - try { - const updated: Secret = await pb - .collection("documents") - .update(secret.id, { - data: { - ...secret.data, - discovered: newChecked, - }, - }); - dispatch({ type: "setDocument", doc: updated }); - } finally { - setLoading(false); - } - } - - async function saveText(text: string) { - const updated: Secret = await pb.collection("documents").update(secret.id, { - data: { - ...secret.data, - text, - }, - }); - dispatch({ type: "setDocument", doc: updated }); - } - - return ( -
- - -
- ); -}; diff --git a/src/components/documents/secret/SecretPrintRow.tsx b/src/components/documents/secret/SecretPrintRow.tsx deleted file mode 100644 index ac68c0a..0000000 --- a/src/components/documents/secret/SecretPrintRow.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// SecretRow.tsx -// Displays a single secret with discovered checkbox and text. -import type { Secret } from "@/lib/types"; - -/** - * Renders a secret row with a discovered checkbox and secret text. - * Handles updating the discovered state and discoveredIn relationship. - */ -export const SecretPrintRow = ({ secret }: { secret: Secret }) => { - return ( -
  • - - - {(secret.data as any)?.secret?.text || ( - (No secret text) - )} - -
  • - ); -}; diff --git a/src/components/documents/session/SessionEditForm.tsx b/src/components/documents/session/SessionEditForm.tsx deleted file mode 100644 index 7334a0a..0000000 --- a/src/components/documents/session/SessionEditForm.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; -import { useDocumentCache } from "@/context/document/hooks"; -import { pb } from "@/lib/pocketbase"; -import type { Session } from "@/lib/types"; - -export const SessionEditForm = ({ session }: { session: Session }) => { - const { dispatch } = useDocumentCache(); - - async function saveStrongStart(strongStart: string) { - const doc: Session = await pb.collection("documents").update(session.id, { - data: { - ...session.data, - strongStart, - }, - }); - dispatch({ - type: "setDocument", - doc, - }); - } - - return ( -
    -

    Strong Start

    - - - ); -}; diff --git a/src/components/documents/session/SessionPrintRow.tsx b/src/components/documents/session/SessionPrintRow.tsx deleted file mode 100644 index fbfd3ec..0000000 --- a/src/components/documents/session/SessionPrintRow.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import type { Session } from "@/lib/types"; - -export const SessionPrintRow = ({ session }: { session: Session }) => { - return ( -
    -

    StrongStart

    -
    {session.data.strongStart}
    -
    - ); -}; diff --git a/src/components/documents/session/SessionRow.tsx b/src/components/documents/session/SessionRow.tsx deleted file mode 100644 index 24503b9..0000000 --- a/src/components/documents/session/SessionRow.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { FormattedDate } from "@/components/FormattedDate"; -import type { Session } from "@/lib/types"; -import { Link } from "@tanstack/react-router"; - -export const SessionRow = ({ session }: { session: Session }) => { - return ( -
    - - {session.name ? session.name : } - -
    {session.data.strongStart}
    -
    - ); -}; diff --git a/src/components/documents/treasure/NewTreasureForm.tsx b/src/components/documents/treasure/NewTreasureForm.tsx deleted file mode 100644 index c37a6f5..0000000 --- a/src/components/documents/treasure/NewTreasureForm.tsx +++ /dev/null @@ -1,67 +0,0 @@ -// TreasureForm.tsx -// Form for adding a new treasure to a session. -import { useState } from "react"; -import type { CampaignId, Treasure } from "@/lib/types"; -import { pb } from "@/lib/pocketbase"; -import { BaseForm } from "@/components/form/BaseForm"; -import { SingleLineInput } from "@/components/form/SingleLineInput"; -import { useDocumentCache } from "@/context/document/hooks"; - -/** - * Renders a form to add a new treasure. Calls onCreate with the new treasure document. - */ -export const NewTreasureForm = ({ - campaign, - onCreate, -}: { - campaign: CampaignId; - onCreate: (treasure: Treasure) => Promise; -}) => { - const { dispatch } = useDocumentCache(); - const [newTreasure, setNewTreasure] = useState(""); - const [adding, setAdding] = useState(false); - const [error, setError] = useState(null); - - async function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - if (!newTreasure.trim()) return; - setAdding(true); - setError(null); - try { - const treasureDoc: Treasure = await pb.collection("documents").create({ - campaign, - type: "treasure", - data: { - text: newTreasure, - discovered: false, - }, - }); - setNewTreasure(""); - dispatch({ - type: "setDocument", - doc: treasureDoc, - }); - await onCreate(treasureDoc); - } catch (e: any) { - setError(e?.message || "Failed to add treasure."); - } finally { - setAdding(false); - } - } - - return ( - - } - /> - ); -}; diff --git a/src/components/documents/treasure/TreasureEditForm.tsx b/src/components/documents/treasure/TreasureEditForm.tsx deleted file mode 100644 index 913369b..0000000 --- a/src/components/documents/treasure/TreasureEditForm.tsx +++ /dev/null @@ -1,70 +0,0 @@ -// Displays a single treasure with discovered checkbox and text. -import { AutoSaveTextarea } from "@/components/AutoSaveTextarea"; -import { useDocumentCache } from "@/context/document/hooks"; -import { pb } from "@/lib/pocketbase"; -import type { Treasure } from "@/lib/types"; -import { useState } from "react"; - -/** - * Renders an editable treasure form. - * Handles updating the discovered state and discoveredIn relationship. - */ -export const TreasureEditForm = ({ treasure }: { treasure: Treasure }) => { - const { dispatch } = useDocumentCache(); - const [checked, setChecked] = useState( - !!(treasure.data as any)?.treasure?.discovered, - ); - const [loading, setLoading] = useState(false); - - async function handleChange(e: React.ChangeEvent) { - const newChecked = e.target.checked; - setLoading(true); - setChecked(newChecked); - try { - const updated: Treasure = await pb - .collection("documents") - .update(treasure.id, { - data: { - ...treasure.data, - treasure: { - ...(treasure.data as any).treasure, - discovered: newChecked, - }, - }, - }); - dispatch({ type: "setDocument", doc: updated }); - } finally { - setLoading(false); - } - } - - async function saveText(text: string) { - const updated: Treasure = await pb - .collection("documents") - .update(treasure.id, { - data: { - ...treasure.data, - text, - }, - }); - dispatch({ type: "setDocument", doc: updated }); - } - - return ( -
    - - -
    - ); -}; diff --git a/src/components/documents/treasure/TreasurePrintRow.tsx b/src/components/documents/treasure/TreasurePrintRow.tsx deleted file mode 100644 index 09f9459..0000000 --- a/src/components/documents/treasure/TreasurePrintRow.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// TreasureRow.tsx -// Displays a single treasure with discovered checkbox and text. -import type { Treasure } from "@/lib/types"; - -/** - * Renders a treasure row with a discovered checkbox and treasure text. - * Handles updating the discovered state and discoveredIn relationship. - */ -export const TreasurePrintRow = ({ treasure }: { treasure: Treasure }) => { - return ( -
    - - - {(treasure.data as any)?.treasure?.text || ( - (No treasure text) - )} - -
    - ); -}; diff --git a/src/lib/relationships.ts b/src/lib/relationships.ts index f864081..43388b3 100644 --- a/src/lib/relationships.ts +++ b/src/lib/relationships.ts @@ -1,4 +1,9 @@ -import { getDocumentType, RelationshipType, type AnyDocument } from "./types"; +import { + getDocumentType, + RelationshipType, + type AnyDocument, + type DocumentType, +} from "./types"; export function displayName(relationshipType: RelationshipType) { return relationshipType.charAt(0).toUpperCase() + relationshipType.slice(1); @@ -19,3 +24,17 @@ export function relationshipsForDocument(doc: AnyDocument): RelationshipType[] { return []; } } + +const DocTypeForRelationshipType: { [k in RelationshipType]: DocumentType } = { + [RelationshipType.DiscoveredIn]: "session", + [RelationshipType.Locations]: "location", + [RelationshipType.Monsters]: "monster", + [RelationshipType.Npcs]: "npc", + [RelationshipType.Scenes]: "scene", + [RelationshipType.Secrets]: "secret", + [RelationshipType.Treasures]: "treasure", +} as const; + +export function docTypeForRelationshipType(rt: RelationshipType): DocumentType { + return DocTypeForRelationshipType[rt]; +}