diff options
author | Masaya Tojo <masaya@tojo.tokyo> | 2024-09-01 22:36:21 +0900 |
---|---|---|
committer | Masaya Tojo <masaya@tojo.tokyo> | 2024-09-01 22:36:21 +0900 |
commit | 71abc48fd4525b9194df848a6915ab4dfc11c354 (patch) | |
tree | e736f111b82921ac730195e7aa9036af9a824005 | |
parent | 1d3b5fcf0dc02557aa2eba02074ec84bd497a768 (diff) |
確認画面まで作成する
-rw-r--r-- | src/SignUpConfirm.tsx | 33 | ||||
-rw-r--r-- | src/SignUpForm1.tsx | 48 | ||||
-rw-r--r-- | src/SignUpForm2.tsx | 40 | ||||
-rw-r--r-- | src/routes.tsx | 2 | ||||
-rw-r--r-- | src/signUpSchema.ts | 51 |
5 files changed, 134 insertions, 40 deletions
diff --git a/src/SignUpConfirm.tsx b/src/SignUpConfirm.tsx new file mode 100644 index 0000000..295bad6 --- /dev/null +++ b/src/SignUpConfirm.tsx @@ -0,0 +1,33 @@ +import './SignUp.css' +import { useLocation, Navigate } from 'react-router-dom'; +import { Form } from './signUpSchema' + +export const SignUpConfirm = () => { + const location = useLocation() + + const form = location.state as Form | null; + + // form1 のデータがない場合は form1 にリダイレクトする + if (form === null) { + return <Navigate replace to="/sign-up/form1" /> + } + + return ( + <> + <h1>会員登録 確認画面</h1> + <div> + <h2>あなたの情報</h2> + <div className="signUpForm"> + <p>お名前: {form.name}</p> + <p>名前カナ: {form.kana}</p> + <p>電話番号: {form.tel1}-{form.tel2}-{form.tel3}</p> + </div> + <h2>ログイン関連の情報</h2> + <div className="signUpForm"> + <p>メールアドレス: {form.email}</p> + <p>パスワード: セキュリティ上の理由のため非表示</p> + </div> + </div> + </> + ); +} diff --git a/src/SignUpForm1.tsx b/src/SignUpForm1.tsx index fee515f..76c6020 100644 --- a/src/SignUpForm1.tsx +++ b/src/SignUpForm1.tsx @@ -1,49 +1,18 @@ import './SignUp.css' import { useForm } from 'react-hook-form' import { zodResolver } from "@hookform/resolvers/zod" -import * as z from "zod" -import parsePhoneNumber from 'libphonenumber-js' - -const kanaRegex = /^[ァ-ン]+$/ - -const schema = z.object({ - name: z.string().min(1, { message: '必須項目です' }), - kana: z.string().min(1, { message: '必須項目です' }).regex(kanaRegex, { message: 'カタカナを入力してください' }), - tel1: z.string(), - tel2: z.string(), - tel3: z.string(), -}).refine( - ({ tel1, tel2, tel3 }) => (tel1.length > 0 && tel2.length > 0 && tel3.length > 0), - { - message: '必須項目です', - path: ['tel3'], - } -).refine( - ({ tel1, tel2, tel3 }) => { - const phoneNumber = parsePhoneNumber('+81' + `${tel1}${tel2}${tel3}`) - console.log([`${tel1}${tel2}${tel3}`, phoneNumber?.isValid()]) - return phoneNumber?.isValid() - }, - { - message: '電話番号が不正です', - path: ['tel3'], - } -) - -type Form1 = { - name: string, - kana: string, - tel1: string, - tel2: string, - tel3: string, -} +import { useNavigate } from 'react-router-dom'; +import { Form1, form1Schema } from './signUpSchema' export const SignUpForm1 = () => { const { register, handleSubmit, formState: { errors } } = useForm<Form1>({ - resolver: zodResolver(schema), + resolver: zodResolver(form1Schema), }); + const navigate = useNavigate(); - const onsubmit = (data: Form1) => console.log(data); + const onsubmit = (state: Form1) => { + navigate('/sign-up/form2', { state }) + } const onerror = (err: any) => console.log(err); return ( @@ -70,8 +39,7 @@ export const SignUpForm1 = () => { <div> <button type="submit">次へ</button> </div> - </form > + </form> </> ); } - diff --git a/src/SignUpForm2.tsx b/src/SignUpForm2.tsx index 1824fd6..f355225 100644 --- a/src/SignUpForm2.tsx +++ b/src/SignUpForm2.tsx @@ -1,9 +1,49 @@ import './SignUp.css' +import { useForm } from 'react-hook-form' +import { zodResolver } from "@hookform/resolvers/zod" +import { useLocation, Navigate, useNavigate } from 'react-router-dom'; +import { Form1, Form2, form2Schema } from './signUpSchema' export const SignUpForm2 = () => { + const { register, handleSubmit, formState: { errors } } = useForm<Form2>({ + resolver: zodResolver(form2Schema), + }); + const location = useLocation(); + const form1 = location.state as Form1 | null; + const navigate = useNavigate(); + + // form1 のデータがない場合は form1 にリダイレクトする + if (form1 === null) { + return <Navigate replace to="/sign-up/form1" /> + } + + const onsubmit = (form2: Form2) => { + const state = { + ...form1, + ...form2, + } + navigate('/sign-up/confirm', { state }) + } + const onerror = (err: any) => console.log(err); + return ( <> <h1>会員登録 フェーズ 2</h1> + <form className="SignUpForm" onSubmit={handleSubmit(onsubmit, onerror)}> + <div> + <label htmlFor="email">メールアドレス: </label> + <input id="email" type="email" {...register('email')}></input> + <div className="error">{errors.email?.message}</div> + </div> + <div> + <label htmlFor="password">パスワード: </label> + <input id="password" type="password" {...register('password')}></input> + <div className="error">{errors.password?.message}</div> + </div> + <div> + <button type="submit">確認画面へ</button> + </div> + </form> </> ); } diff --git a/src/routes.tsx b/src/routes.tsx index cb2b37c..1a3daa1 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -3,10 +3,12 @@ import { Top } from './Top'; import { SignUp } from './SignUp'; import { SignUpForm1 } from './SignUpForm1'; import { SignUpForm2 } from './SignUpForm2'; +import { SignUpConfirm } from './SignUpConfirm'; export const routes = createBrowserRouter([ { path: '/', element: <Top /> }, { path: '/sign-up', element: <SignUp /> }, { path: '/sign-up/form1', element: <SignUpForm1 /> }, { path: '/sign-up/form2', element: <SignUpForm2 /> }, + { path: '/sign-up/confirm', element: <SignUpConfirm /> }, ]); diff --git a/src/signUpSchema.ts b/src/signUpSchema.ts new file mode 100644 index 0000000..4d8b71f --- /dev/null +++ b/src/signUpSchema.ts @@ -0,0 +1,51 @@ +import * as z from "zod" +import parsePhoneNumber from 'libphonenumber-js' + +const kanaRegex = /^[ァ-ン]+$/; + +const form1SchemaWithoutRefine = z.object({ + name: z.string().min(1, { message: '必須項目です' }), + kana: z.string().min(1, { message: '必須項目です' }).regex(kanaRegex, { message: 'カタカナを入力してください' }), + tel1: z.string(), + tel2: z.string(), + tel3: z.string(), +}) + +const addRefine = <Form1 extends z.ZodTypeAny>(schema: Form1) => ( + schema.refine( + ({ tel1, tel2, tel3 }) => (tel1.length > 0 && tel2.length > 0 && tel3.length > 0), + { + message: '必須項目です', + path: ['tel3'], + } + ).refine( + ({ tel1, tel2, tel3 }) => { + const phoneNumber = parsePhoneNumber('+81' + `${tel1}${tel2}${tel3}`) + console.log([`${tel1}${tel2}${tel3}`, phoneNumber?.isValid()]) + return phoneNumber?.isValid() + }, + { + message: '電話番号が不正です', + path: ['tel3'], + } + )) + + +export type Form1 = z.infer<typeof form1SchemaWithoutRefine> + +export const form2Schema = z.object({ + email: z.string().min(1, { message: '必須項目です' }).email({ message: 'メールアドレスを入力してください' }), + password: z.string() + .min(1, { message: '必須項目です' }) + .min(12, { message: '12文字以上で入力してください' }) + .max(128, { message: '128文字以下で入力してください' }) +}) + +export type Form2 = z.infer<typeof form2Schema> + +const formSchemaWithoutRefine = form1SchemaWithoutRefine.merge(form2Schema) + +export type Form = z.infer<typeof formSchemaWithoutRefine> + +export const form1Schema = addRefine(form1SchemaWithoutRefine) +export const formSchema = addRefine(formSchemaWithoutRefine) |