58 lines
1.7 KiB
TypeScript
58 lines
1.7 KiB
TypeScript
import { runtime } from "@/runtime"
|
|
import { Container, Flex, TextField } from "@radix-ui/themes"
|
|
import { createFileRoute } from "@tanstack/react-router"
|
|
import { Console, Effect, Schema, Stream } from "effect"
|
|
import { Component, Form } from "effect-fc"
|
|
import { useContext, useFork } from "effect-fc/hooks"
|
|
|
|
|
|
const LoginFormSchema = Schema.Struct({
|
|
email: Schema.String,
|
|
password: Schema.String,
|
|
})
|
|
|
|
class LoginForm extends Effect.Service<LoginForm>()("LoginForm", {
|
|
scoped: Form.make({
|
|
schema: LoginFormSchema,
|
|
initialValue: { email: "", password: "" },
|
|
})
|
|
}) {}
|
|
|
|
class LoginFormComponent extends Component.makeUntraced(function* LoginFormComponent() {
|
|
const form = yield* LoginForm
|
|
const emailInput = yield* form.useInput(["email"])
|
|
const passwordInput = yield* form.useInput(["password"])
|
|
|
|
yield* useFork(() => Stream.runForEach(form.latestValueSubscribable.changes, Console.log))
|
|
|
|
return (
|
|
<Container>
|
|
<Flex direction="column" gap="2">
|
|
<TextField.Root
|
|
value={emailInput.value}
|
|
onChange={e => emailInput.setValue(e.target.value)}
|
|
/>
|
|
|
|
<TextField.Root
|
|
value={passwordInput.value}
|
|
onChange={e => passwordInput.setValue(e.target.value)}
|
|
/>
|
|
</Flex>
|
|
</Container>
|
|
)
|
|
}) {}
|
|
|
|
|
|
const FormRoute = Component.makeUntraced(function* FormRoute() {
|
|
const context = yield* useContext(LoginForm.Default)
|
|
const LoginFormComponentFC = yield* Effect.provide(LoginFormComponent, context)
|
|
|
|
return <LoginFormComponentFC />
|
|
}).pipe(
|
|
Component.withRuntime(runtime.context)
|
|
)
|
|
|
|
export const Route = createFileRoute("/form")({
|
|
component: FormRoute
|
|
})
|