Files
effect-fc/packages/example/src/routes/form.tsx
Julien Valverdé 040e671fd3
All checks were successful
Lint / lint (push) Successful in 12s
Working field
2025-09-30 15:54:59 +02:00

80 lines
2.5 KiB
TypeScript

import { TextFieldFormInput } from "@/lib/form/TextFieldFormInput"
import { runtime } from "@/runtime"
import { Button, Container, Flex } from "@radix-ui/themes"
import { createFileRoute } from "@tanstack/react-router"
import { Effect, Schema } from "effect"
import { Component, Form } from "effect-fc"
import { useContext, useSubscribables } from "effect-fc/hooks"
const email = Schema.pattern<typeof Schema.String>(
/^(?!\.)(?!.*\.\.)([A-Z0-9_+-.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9-]*\.)+[A-Z]{2,}$/i,
{
identifier: "email",
title: "email",
message: () => "Not an email address",
},
)
const RegisterFormSchema = Schema.Struct({
email: Schema.String.pipe(email),
password: Schema.String.pipe(Schema.minLength(3)),
})
class RegisterForm extends Effect.Service<RegisterForm>()("RegisterForm", {
scoped: Form.service({
schema: RegisterFormSchema,
initialEncodedValue: { email: "", password: "" },
submit: () => Effect.andThen(
Effect.sleep("500 millis"),
Effect.sync(() => alert("Done!")),
),
})
}) {}
class RegisterPage extends Component.makeUntraced("RegisterPage")(function*() {
const form = yield* RegisterForm
const submit = yield* Form.useSubmit(form)
const [canSubmit] = yield* useSubscribables(form.canSubmitSubscribable)
const TextFieldFormInputFC = yield* TextFieldFormInput
return (
<Container>
<form onSubmit={e => {
e.preventDefault()
void submit()
}}>
<Flex direction="column" gap="2">
<TextFieldFormInputFC
field={Form.useField(form, ["email"])}
debounce="500 millis"
/>
<TextFieldFormInputFC
field={Form.useField(form, ["password"])}
debounce="500 millis"
/>
<Button disabled={!canSubmit}>Submit</Button>
</Flex>
</form>
</Container>
)
}) {}
const RegisterRoute = Component.makeUntraced(function* RegisterRoute() {
const context = yield* useContext(RegisterForm.Default, { finalizerExecutionMode: "fork" })
const RegisterRouteFC = yield* Effect.provide(RegisterPage, context)
return <RegisterRouteFC />
}).pipe(
Component.withRuntime(runtime.context)
)
export const Route = createFileRoute("/form")({
component: RegisterRoute
})