Compare commits

...

1 Commits

Author SHA1 Message Date
Anselm
71f68b0f60 Try using react-hook-form 2024-08-09 15:09:33 +01:00
4 changed files with 55 additions and 59 deletions

View File

@@ -27,6 +27,7 @@
"qrcode": "^1.5.3", "qrcode": "^1.5.3",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-hook-form": "^7.52.2",
"react-router": "^6.16.0", "react-router": "^6.16.0",
"react-router-dom": "^6.16.0", "react-router-dom": "^6.16.0",
"tailwind-merge": "^1.14.0", "tailwind-merge": "^1.14.0",

View File

@@ -6,7 +6,7 @@ import {
} from "react-router-dom"; } from "react-router-dom";
import "./index.css"; import "./index.css";
import { createJazzReactContext, PasskeyAuth } from "jazz-react"; import { createJazzReactContext, DemoAuth, PasskeyAuth } from "jazz-react";
import { import {
Button, Button,
@@ -31,9 +31,8 @@ import { TodoAccount, TodoProject } from "./1_schema.ts";
const appName = "Jazz Todo List Example"; const appName = "Jazz Todo List Example";
const auth = PasskeyAuth<TodoAccount>({ const auth = DemoAuth<TodoAccount>({
appName, appName,
Component: PrettyAuthUI,
accountSchema: TodoAccount, accountSchema: TodoAccount,
}); });
const Jazz = createJazzReactContext<TodoAccount>({ const Jazz = createJazzReactContext<TodoAccount>({

View File

@@ -19,6 +19,7 @@ import uniqolor from "uniqolor";
import { useParams } from "react-router"; import { useParams } from "react-router";
import { ID } from "jazz-tools"; import { ID } from "jazz-tools";
import { useCoState } from "./2_main"; import { useCoState } from "./2_main";
import { useForm } from "react-hook-form";
/** Walkthrough: Reactively rendering a todo project as a table, /** Walkthrough: Reactively rendering a todo project as a table,
* adding and editing tasks * adding and editing tasks
@@ -76,68 +77,50 @@ export function ProjectTodoTable() {
</h1> </h1>
<InviteButton value={project} valueHint="project" /> <InviteButton value={project} valueHint="project" />
</div> </div>
<Table>
<TableHeader> {project?.tasks?.map(
<TableRow> (task) => task && <TaskRow key={task.id} task={task} />,
<TableHead className="w-[40px]">Done</TableHead> )}
<TableHead>Task</TableHead> <NewTaskInputRow createTask={createTask} disabled={!project} />
</TableRow>
</TableHeader>
<TableBody>
{project?.tasks?.map(
(task) => task && <TaskRow key={task.id} task={task} />,
)}
<NewTaskInputRow
createTask={createTask}
disabled={!project}
/>
</TableBody>
</Table>
</div> </div>
); );
} }
export function TaskRow({ task }: { task: Task | undefined }) { export function TaskRow({ task }: { task: Task | undefined }) {
const { register, handleSubmit, formState } = useForm({
values: task && { text: task.text, done: task.done },
});
return ( return (
<TableRow> <form
<TableCell> onSubmit={handleSubmit((newValues) => task?.applyDiff(newValues))}
<Checkbox className="flex gap-2 items-center"
className="mt-1" >
checked={task?.done} <Checkbox className="mt-1" {...register("done")} />
onCheckedChange={(checked) => { {task?.text ? (
// Tick or untick the task // <span className={task?.done ? "line-through" : ""}>
// Task is also immutable, but this will update all queries // {task.text}
// that include this task as a reference // </span>
if (task) task.done = !!checked; <input type="text" {...register("text")} />
}} ) : (
/> <Skeleton className="mt-1 w-[200px] h-[1em] rounded-full" />
</TableCell> )}
<TableCell> {formState.isDirty && <input type="submit" value="Save" />}
<div className="flex flex-row justify-between items-center gap-2"> {
{task?.text ? ( // Here we see for the first time how we can access edit history
<span className={task?.done ? "line-through" : ""}> // for a CoValue, and use it to display who created the task.
{task.text} task?._edits.text?.by?.profile?.name ? (
</span> <span
) : ( className="rounded-full py-0.5 px-2 text-xs"
<Skeleton className="mt-1 w-[200px] h-[1em] rounded-full" /> style={uniqueColoring(task._edits.text.by.id)}
)} >
{ {task._edits.text.by.profile.name}
// Here we see for the first time how we can access edit history </span>
// for a CoValue, and use it to display who created the task. ) : (
task?._edits.text?.by?.profile?.name ? ( <Skeleton className="mt-1 w-[50px] h-[1em] rounded-full" />
<span )
className="rounded-full py-0.5 px-2 text-xs" }
style={uniqueColoring(task._edits.text.by.id)} </form>
>
{task._edits.text.by.profile.name}
</span>
) : (
<Skeleton className="mt-1 w-[50px] h-[1em] rounded-full" />
)
}
</div>
</TableCell>
</TableRow>
); );
} }

13
pnpm-lock.yaml generated
View File

@@ -368,6 +368,9 @@ importers:
react-dom: react-dom:
specifier: ^18.2.0 specifier: ^18.2.0
version: 18.2.0(react@18.2.0) version: 18.2.0(react@18.2.0)
react-hook-form:
specifier: ^7.52.2
version: 7.52.2(react@18.2.0)
react-router: react-router:
specifier: ^6.16.0 specifier: ^6.16.0
version: 6.21.0(react@18.2.0) version: 6.21.0(react@18.2.0)
@@ -3760,6 +3763,12 @@ packages:
peerDependencies: peerDependencies:
react: ^18.2.0 react: ^18.2.0
react-hook-form@7.52.2:
resolution: {integrity: sha512-pqfPEbERnxxiNMPd0bzmt1tuaPcVccywFDpyk2uV5xCIBphHV5T8SVnX9/o3kplPE1zzKt77+YIoq+EMwJp56A==}
engines: {node: '>=18.0.0'}
peerDependencies:
react: ^16.8.0 || ^17 || ^18 || ^19
react-is@18.2.0: react-is@18.2.0:
resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
@@ -8027,6 +8036,10 @@ snapshots:
react: 18.2.0 react: 18.2.0
scheduler: 0.23.0 scheduler: 0.23.0
react-hook-form@7.52.2(react@18.2.0):
dependencies:
react: 18.2.0
react-is@18.2.0: {} react-is@18.2.0: {}
react-router-dom@6.21.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): react-router-dom@6.21.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0):