This commit is contained in:
@@ -34,6 +34,7 @@ export namespace Form {
|
|||||||
export interface Result<I> {
|
export interface Result<I> {
|
||||||
readonly value: I
|
readonly value: I
|
||||||
readonly setValue: React.Dispatch<React.SetStateAction<I>>
|
readonly setValue: React.Dispatch<React.SetStateAction<I>>
|
||||||
|
readonly issues: readonly ParseResult.ArrayFormatterIssue[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import { runtime } from "@/runtime"
|
import { runtime } from "@/runtime"
|
||||||
import { Container, Flex, TextField } from "@radix-ui/themes"
|
import { Callout, Container, Flex, TextField } from "@radix-ui/themes"
|
||||||
import { createFileRoute } from "@tanstack/react-router"
|
import { createFileRoute } from "@tanstack/react-router"
|
||||||
import { Console, Effect, Schema, Stream } from "effect"
|
import { Array, Console, Effect, Option, Schema, Stream } from "effect"
|
||||||
import { Component, Form } from "effect-fc"
|
import { Component, Form } from "effect-fc"
|
||||||
import { useContext, useFork } from "effect-fc/hooks"
|
import { useContext, useFork } from "effect-fc/hooks"
|
||||||
|
|
||||||
|
|
||||||
const LoginFormSchema = Schema.Struct({
|
const LoginFormSchema = Schema.Struct({
|
||||||
email: Schema.String,
|
email: Schema.String,
|
||||||
password: Schema.String,
|
password: Schema.String.pipe(Schema.minLength(3)),
|
||||||
})
|
})
|
||||||
|
|
||||||
class LoginForm extends Effect.Service<LoginForm>()("LoginForm", {
|
class LoginForm extends Effect.Service<LoginForm>()("LoginForm", {
|
||||||
scoped: Form.make({
|
scoped: Form.make({
|
||||||
schema: LoginFormSchema,
|
schema: LoginFormSchema,
|
||||||
initialValue: { email: "", password: "" },
|
initialValue: { email: "", password: "xxx" },
|
||||||
})
|
})
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
@@ -33,10 +33,30 @@ class LoginFormComponent extends Component.makeUntraced(function* LoginFormCompo
|
|||||||
onChange={e => emailInput.setValue(e.target.value)}
|
onChange={e => emailInput.setValue(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{Option.match(Array.head(emailInput.issues), {
|
||||||
|
onSome: issue => (
|
||||||
|
<Callout.Root>
|
||||||
|
<Callout.Text>{issue.message}</Callout.Text>
|
||||||
|
</Callout.Root>
|
||||||
|
),
|
||||||
|
|
||||||
|
onNone: () => <></>,
|
||||||
|
})}
|
||||||
|
|
||||||
<TextField.Root
|
<TextField.Root
|
||||||
value={passwordInput.value}
|
value={passwordInput.value}
|
||||||
onChange={e => passwordInput.setValue(e.target.value)}
|
onChange={e => passwordInput.setValue(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{Option.match(Array.head(passwordInput.issues), {
|
||||||
|
onSome: issue => (
|
||||||
|
<Callout.Root>
|
||||||
|
<Callout.Text>{issue.message}</Callout.Text>
|
||||||
|
</Callout.Root>
|
||||||
|
),
|
||||||
|
|
||||||
|
onNone: () => <></>,
|
||||||
|
})}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user