@@ -6,7 +6,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build",
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"lint:tsc": "tsc --noEmit",
|
"lint:tsc": "tsc -b --noEmit",
|
||||||
"lint:biome": "biome lint",
|
"lint:biome": "biome lint",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"clean:cache": "rm -rf .turbo node_modules/.tmp node_modules/.vite* .tanstack",
|
"clean:cache": "rm -rf .turbo node_modules/.tmp node_modules/.vite* .tanstack",
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
import { Button, Container, Flex, Text, TextField } from "@radix-ui/themes"
|
import { Button, Container, Flex, Text } from "@radix-ui/themes"
|
||||||
import { createFileRoute } from "@tanstack/react-router"
|
import { createFileRoute } from "@tanstack/react-router"
|
||||||
import { Console, Effect, Schema } from "effect"
|
import { Console, Effect, Schema } from "effect"
|
||||||
import { Component, Form, MutationForm, View } from "effect-fc-next"
|
import { Component, Form, MutationForm, View } from "effect-fc-next"
|
||||||
|
import { TextFieldFormInputView } from "@/lib/form/TextFieldFormInputView"
|
||||||
import { runtime } from "@/runtime"
|
import { runtime } from "@/runtime"
|
||||||
|
|
||||||
|
|
||||||
const RegisterSchema = Schema.Struct({
|
const RegisterSchema = Schema.Struct({
|
||||||
email: Schema.String,
|
email: Schema.String.check(
|
||||||
password: Schema.String,
|
Schema.isPattern(/^[^\s@]+@[^\s@]+\.[^\s@]+$/, {
|
||||||
|
message: "Enter a valid email address",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
password: Schema.String.check(
|
||||||
|
Schema.isMinLength(5, {
|
||||||
|
message: "Password must be at least 5 characters long",
|
||||||
|
}),
|
||||||
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
const RegisterRouteComponent = Component.make("RegisterRouteView")(function*() {
|
const RegisterRouteComponent = Component.make("RegisterRouteView")(function*() {
|
||||||
@@ -29,31 +38,32 @@ const RegisterRouteComponent = Component.make("RegisterRouteView")(function*() {
|
|||||||
return [form, emailField, passwordField] as const
|
return [form, emailField, passwordField] as const
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const emailInput = yield* Form.useInput(emailField)
|
|
||||||
const passwordInput = yield* Form.useInput(passwordField)
|
|
||||||
const [canCommit, isCommitting] = yield* View.useAll([
|
const [canCommit, isCommitting] = yield* View.useAll([
|
||||||
form.canCommit,
|
form.canCommit,
|
||||||
form.isCommitting,
|
form.isCommitting,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
const TextFieldFormInput = yield* TextFieldFormInputView.use
|
||||||
const runPromise = yield* Component.useRunPromise()
|
const runPromise = yield* Component.useRunPromise()
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container width="300">
|
<Container width="300">
|
||||||
<form onSubmit={(event) => {
|
<form onSubmit={event => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
void runPromise(form.submit)
|
void runPromise(form.submit)
|
||||||
}}>
|
}}>
|
||||||
<Flex direction="column" gap="2">
|
<Flex direction="column" gap="2">
|
||||||
<TextField.Root
|
<TextFieldFormInput
|
||||||
value={emailInput.value}
|
form={emailField}
|
||||||
onChange={event => emailInput.setValue(event.currentTarget.value)}
|
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
|
debounce="250 millis"
|
||||||
/>
|
/>
|
||||||
<TextField.Root
|
<TextFieldFormInput
|
||||||
value={passwordInput.value}
|
form={passwordField}
|
||||||
onChange={event => passwordInput.setValue(event.currentTarget.value)}
|
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
type="password"
|
type="password"
|
||||||
|
debounce="250 millis"
|
||||||
/>
|
/>
|
||||||
<Button disabled={!canCommit || isCommitting}>
|
<Button disabled={!canCommit || isCommitting}>
|
||||||
{isCommitting ? "Submitting…" : "Submit"}
|
{isCommitting ? "Submitting…" : "Submit"}
|
||||||
|
|||||||
Reference in New Issue
Block a user