83 lines
2.2 KiB
TypeScript
83 lines
2.2 KiB
TypeScript
import { AutoSaveTextarea } from "@/components/AutoSaveTextarea";
|
|
import { pb } from "@/lib/pocketbase";
|
|
import { getDocumentType, type AnyDocument } from "@/lib/types";
|
|
import { useDocumentCache } from "@/context/document/hooks";
|
|
import {
|
|
getFieldsForType,
|
|
type DocumentField,
|
|
type FieldType,
|
|
} from "@/lib/fields";
|
|
import { ToggleInput } from "../form/ToggleInput";
|
|
|
|
export type GenericFieldType = "multiline" | "singleline" | "checkbox";
|
|
|
|
export type Props<T extends AnyDocument> = {
|
|
doc: T;
|
|
};
|
|
|
|
export const GenericEditForm = <T extends AnyDocument>({ doc }: Props<T>) => {
|
|
const docType = getDocumentType(doc) as T["type"];
|
|
const fields = getFieldsForType(docType);
|
|
|
|
return (
|
|
<div className="">
|
|
{
|
|
// The type checker seems to lose the types when using Object.entries here.
|
|
fields.map((documentField) => (
|
|
<GenericEditFormField doc={doc} field={documentField} />
|
|
))
|
|
}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const GenericEditFormField = <T extends AnyDocument>({
|
|
doc,
|
|
field,
|
|
}: {
|
|
doc: T;
|
|
field: DocumentField<T["type"], FieldType>;
|
|
}) => {
|
|
const { dispatch } = useDocumentCache();
|
|
|
|
// The type checker really doesn't like indexing into this type implicitly, so we'll store it in a temporary to give it the right hints.
|
|
const data = doc.data as T["data"];
|
|
|
|
async function saveField(value: string | boolean) {
|
|
const updated: T = await pb.collection("documents").update(doc.id, {
|
|
data: field.setter(value, doc.data),
|
|
});
|
|
dispatch({ type: "setDocument", doc: updated });
|
|
}
|
|
|
|
switch (field.fieldType) {
|
|
case "longText":
|
|
return (
|
|
<AutoSaveTextarea
|
|
multiline={true}
|
|
value={field.getter(data) as string}
|
|
onSave={saveField}
|
|
id={field.name}
|
|
/>
|
|
);
|
|
case "shortText":
|
|
return (
|
|
<AutoSaveTextarea
|
|
multiline={false}
|
|
value={field.getter(data) as string}
|
|
onSave={saveField}
|
|
id={field.name}
|
|
/>
|
|
);
|
|
case "toggle":
|
|
return (
|
|
<ToggleInput
|
|
label={field.name}
|
|
value={!!field.getter(data)}
|
|
onChange={saveField}
|
|
placeholder={field.name}
|
|
/>
|
|
);
|
|
}
|
|
};
|