Adding UI for threads
This commit is contained in:
87
src/components/documents/GenericEditForm.tsx
Normal file
87
src/components/documents/GenericEditForm.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
import { AutoSaveTextarea } from "@/components/AutoSaveTextarea";
|
||||
import { pb } from "@/lib/pocketbase";
|
||||
import type { AnyDocument, Location } from "@/lib/types";
|
||||
import { useDocumentCache } from "@/context/document/hooks";
|
||||
|
||||
export type GenericFieldType = "multiline" | "singleline" | "checkbox";
|
||||
|
||||
export type Props<T extends AnyDocument> = {
|
||||
doc: T;
|
||||
fields: { [K in keyof T["data"]]: GenericFieldType };
|
||||
};
|
||||
|
||||
export const GenericEditForm = <T extends AnyDocument>({
|
||||
doc,
|
||||
fields,
|
||||
}: Props<T>) => {
|
||||
return (
|
||||
<div className="">
|
||||
{
|
||||
// The type checker seems to lose the types when using Object.entries here.
|
||||
Object.entries(fields).map(
|
||||
([fieldName, fieldType]: [string, unknown]) => (
|
||||
<GenericEditFormField
|
||||
key={fieldName}
|
||||
doc={doc}
|
||||
fieldName={fieldName as keyof T["data"]}
|
||||
fieldType={fieldType as GenericFieldType}
|
||||
/>
|
||||
),
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const GenericEditFormField = <T extends AnyDocument>({
|
||||
doc,
|
||||
fieldName,
|
||||
fieldType,
|
||||
}: {
|
||||
doc: T;
|
||||
fieldName: keyof T["data"];
|
||||
fieldType: GenericFieldType;
|
||||
}) => {
|
||||
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) {
|
||||
const updated: T = await pb.collection("documents").update(doc.id, {
|
||||
data: {
|
||||
...doc.data,
|
||||
[fieldName]: value,
|
||||
},
|
||||
});
|
||||
dispatch({ type: "setDocument", doc: updated });
|
||||
}
|
||||
|
||||
switch (fieldType) {
|
||||
case "multiline":
|
||||
return (
|
||||
<AutoSaveTextarea
|
||||
multiline={true}
|
||||
value={data[fieldName] as string}
|
||||
onSave={saveField}
|
||||
/>
|
||||
);
|
||||
case "singleline":
|
||||
return (
|
||||
<AutoSaveTextarea
|
||||
multiline={false}
|
||||
value={data[fieldName] as string}
|
||||
onSave={saveField}
|
||||
/>
|
||||
);
|
||||
case "checkbox":
|
||||
return (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={data[fieldName] as boolean}
|
||||
onChange={(e) => saveField(e.target.value)}
|
||||
className="accent-emerald-500 w-5 h-5"
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user