Adding UI for threads

This commit is contained in:
2025-08-09 15:49:36 -07:00
parent 135debdf7f
commit 1c26daa828
5 changed files with 124 additions and 0 deletions

View 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"
/>
);
}
};