64 lines
2.3 KiB
TypeScript
64 lines
2.3 KiB
TypeScript
import { Button, Container, Flex, Text, TextField } from "@radix-ui/themes"
|
|
import { createFileRoute } from "@tanstack/react-router"
|
|
import { Effect, Schema } from "effect"
|
|
import { Component, Form, MutationForm, View } from "effect-fc-next"
|
|
import { runtime } from "@/runtime"
|
|
|
|
|
|
const RegisterSchema = Schema.Struct({
|
|
email: Schema.String,
|
|
password: Schema.String,
|
|
})
|
|
|
|
const RegisterRouteComponent = Component.make("RegisterRouteView")(function*() {
|
|
const form = yield* Component.useOnMount(() => MutationForm.service({
|
|
schema: RegisterSchema,
|
|
initialEncodedValue: { email: "", password: "" },
|
|
f: ([value]) => Effect.log(`Registered ${value.email}`),
|
|
}))
|
|
const emailField = yield* Form.useInput(
|
|
Form.focusObjectOn(form, "email"),
|
|
)
|
|
const passwordField = yield* Form.useInput(
|
|
Form.focusObjectOn(form, "password"),
|
|
)
|
|
const [canCommit, isCommitting] = yield* View.useAll([
|
|
form.canCommit,
|
|
form.isCommitting,
|
|
])
|
|
const runPromise = yield* Component.useRunPromise()
|
|
|
|
return (
|
|
<Container width="300">
|
|
<form onSubmit={(event) => {
|
|
event.preventDefault()
|
|
void runPromise(form.submit)
|
|
}}>
|
|
<Flex direction="column" gap="2">
|
|
<TextField.Root
|
|
value={emailField.value}
|
|
onChange={event => emailField.setValue(event.currentTarget.value)}
|
|
placeholder="Email"
|
|
/>
|
|
<TextField.Root
|
|
value={passwordField.value}
|
|
onChange={event => passwordField.setValue(event.currentTarget.value)}
|
|
placeholder="Password"
|
|
type="password"
|
|
/>
|
|
<Button disabled={!canCommit || isCommitting}>
|
|
{isCommitting ? "Submitting…" : "Submit"}
|
|
</Button>
|
|
</Flex>
|
|
</form>
|
|
<Text size="2">A MutationForm validates local input, then submits it.</Text>
|
|
</Container>
|
|
)
|
|
}).pipe(
|
|
Component.withRuntime(runtime.context),
|
|
)
|
|
|
|
export const Route = createFileRoute("/form")({
|
|
component: RegisterRouteComponent,
|
|
})
|