Start supporting edit forms for any document type.

This commit is contained in:
2025-06-13 11:14:58 -07:00
parent 38eee14253
commit 6845bd06bf
4 changed files with 63 additions and 26 deletions

View File

@@ -3,7 +3,7 @@ import { pb } from "@/lib/pocketbase";
import type { Document, RelationshipType } from "@/lib/types";
import { useState } from "react";
import { Loader } from "./Loader";
import { DocumentForm } from "./documents/DocumentForm";
import { NewRelatedDocumentForm } from "./documents/NewRelatedDocumentForm";
import { DocumentRow } from "./documents/DocumentRow";
interface RelationshipListProps {
@@ -68,7 +68,7 @@ export function RelationshipList({
error={error}
renderRow={(document) => <DocumentRow document={document} />}
newItemForm={(onSubmit) => (
<DocumentForm
<NewRelatedDocumentForm
campaignId={root.campaign}
relationshipType={relationshipType}
onCreate={async (doc: Document) => {

View File

@@ -0,0 +1,12 @@
import type { CampaignId, Document } from "@/lib/types";
export type FormTarget<T extends Document> =
| {
type: "new";
campaignId: CampaignId;
document?: undefined;
}
| {
type: "existing";
document: T;
};

View File

@@ -7,13 +7,13 @@ import { SecretForm } from "./secret/SecretForm";
import { TreasureForm } from "./treasure/TreasureForm";
function assertUnreachable(_x: never): never {
throw new Error("DocumentForm switch is not exhaustive");
throw new Error("NewRelatedDocumentForm switch is not exhaustive");
}
/**
* Renders a form for any document type depending on the relationship.
*/
export const DocumentForm = ({
export const NewRelatedDocumentForm = ({
campaignId,
relationshipType,
onCreate,
@@ -24,19 +24,27 @@ export const DocumentForm = ({
}) => {
switch (relationshipType) {
case RelationshipType.Locations:
return <LocationForm campaign={campaignId} onCreate={onCreate} />;
return (
<LocationForm
target={{
type: "new",
campaignId,
}}
onSubmit={onCreate}
/>
);
case RelationshipType.Monsters:
return <MonsterForm campaign={campaignId} onCreate={onCreate} />;
case RelationshipType.Npcs:
return <NpcForm campaign={campaignId} onCreate={onCreate} />;
case RelationshipType.Secrets:
return <SecretForm campaign={campaignId} onCreate={onCreate} />;
case RelationshipType.DiscoveredIn:
return "Form not supported here";
case RelationshipType.Treasures:
return <TreasureForm campaign={campaignId} onCreate={onCreate} />;
case RelationshipType.Scenes:
return <SceneForm campaign={campaignId} onCreate={onCreate} />;
case RelationshipType.DiscoveredIn:
return "Form not supported here";
}
return assertUnreachable(relationshipType);

View File

@@ -1,19 +1,22 @@
import { useState } from "react";
import type { CampaignId, Location } from "@/lib/types";
import type { Location } from "@/lib/types";
import { pb } from "@/lib/pocketbase";
import type { FormTarget } from "../Forms";
/**
* Renders a form to add a new location. Calls onCreate with the new location document.
*/
export const LocationForm = ({
campaign,
onCreate,
target,
onSubmit,
}: {
campaign: CampaignId;
onCreate: (location: Location) => Promise<void>;
target: FormTarget<Location>;
onSubmit: (location: Location) => Promise<void>;
}) => {
const [name, setName] = useState("");
const [description, setDescription] = useState("");
const [name, setName] = useState(target.document?.data.location.name ?? "");
const [description, setDescription] = useState(
target.document?.data.location.description ?? "",
);
const [adding, setAdding] = useState(false);
const [error, setError] = useState<string | null>(null);
@@ -23,8 +26,9 @@ export const LocationForm = ({
setAdding(true);
setError(null);
try {
if (target.type === "new") {
const locationDoc: Location = await pb.collection("documents").create({
campaign,
campaign: target.campaignId,
data: {
location: {
name,
@@ -34,7 +38,20 @@ export const LocationForm = ({
});
setName("");
setDescription("");
await onCreate(locationDoc);
await onSubmit(locationDoc);
} else {
const locationDoc: Location = await pb
.collection("documents")
.update(target.document.id, {
data: {
location: {
name,
description,
},
},
});
await onSubmit(locationDoc);
}
} catch (e: any) {
setError(e?.message || "Failed to add location.");
} finally {