diff options
| -rw-r--r-- | package-lock.json | 138 | ||||
| -rw-r--r-- | package.json | 1 | ||||
| -rw-r--r-- | src/SignUpConfirm.tsx | 19 | ||||
| -rw-r--r-- | src/SignUpForm1.tsx | 6 | ||||
| -rw-r--r-- | src/SignUpForm2.tsx | 18 | ||||
| -rw-r--r-- | src/SignUpForm3.tsx | 104 | ||||
| -rw-r--r-- | src/routes.tsx | 2 | ||||
| -rw-r--r-- | src/signUpSchema.ts | 28 | 
8 files changed, 272 insertions, 44 deletions
| diff --git a/package-lock.json b/package-lock.json index 16b0459..a13efa2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@          "react": "^18.3.1",          "react-dom": "^18.3.1",          "react-hook-form": "^7.52.2", +        "react-query": "^3.39.3",          "react-router-dom": "^6.25.1",          "validator": "^13.12.0",          "zod": "^3.23.8" @@ -30,6 +31,17 @@          "vite": "^5.3.4"        }      }, +    "node_modules/@babel/runtime": { +      "version": "7.25.6", +      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", +      "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", +      "dependencies": { +        "regenerator-runtime": "^0.14.0" +      }, +      "engines": { +        "node": ">=6.9.0" +      } +    },      "node_modules/@esbuild/aix-ppc64": {        "version": "0.21.5",        "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -1318,8 +1330,15 @@      "node_modules/balanced-match": {        "version": "1.0.2",        "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", -      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", -      "dev": true +      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" +    }, +    "node_modules/big-integer": { +      "version": "1.6.52", +      "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", +      "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", +      "engines": { +        "node": ">=0.6" +      }      },      "node_modules/brace-expansion": {        "version": "2.0.1", @@ -1342,6 +1361,21 @@          "node": ">=8"        }      }, +    "node_modules/broadcast-channel": { +      "version": "3.7.0", +      "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", +      "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", +      "dependencies": { +        "@babel/runtime": "^7.7.2", +        "detect-node": "^2.1.0", +        "js-sha3": "0.8.0", +        "microseconds": "0.2.0", +        "nano-time": "1.0.0", +        "oblivious-set": "1.0.0", +        "rimraf": "3.0.2", +        "unload": "2.2.0" +      } +    },      "node_modules/callsites": {        "version": "3.1.0",        "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1388,8 +1422,7 @@      "node_modules/concat-map": {        "version": "0.0.1",        "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", -      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", -      "dev": true +      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="      },      "node_modules/cross-spawn": {        "version": "7.0.3", @@ -1434,6 +1467,11 @@        "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",        "dev": true      }, +    "node_modules/detect-node": { +      "version": "2.1.0", +      "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", +      "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" +    },      "node_modules/dir-glob": {        "version": "3.0.1",        "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1811,8 +1849,7 @@      "node_modules/fs.realpath": {        "version": "1.0.0",        "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", -      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", -      "dev": true +      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="      },      "node_modules/fsevents": {        "version": "2.3.3", @@ -1833,7 +1870,6 @@        "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",        "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",        "deprecated": "Glob versions prior to v9 are no longer supported", -      "dev": true,        "dependencies": {          "fs.realpath": "^1.0.0",          "inflight": "^1.0.4", @@ -1865,7 +1901,6 @@        "version": "1.1.11",        "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",        "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", -      "dev": true,        "dependencies": {          "balanced-match": "^1.0.0",          "concat-map": "0.0.1" @@ -1875,7 +1910,6 @@        "version": "3.1.2",        "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",        "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", -      "dev": true,        "dependencies": {          "brace-expansion": "^1.1.7"        }, @@ -1972,7 +2006,6 @@        "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",        "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",        "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", -      "dev": true,        "dependencies": {          "once": "^1.3.0",          "wrappy": "1" @@ -1981,8 +2014,7 @@      "node_modules/inherits": {        "version": "2.0.4",        "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", -      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", -      "dev": true +      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="      },      "node_modules/is-extglob": {        "version": "2.1.1", @@ -2029,6 +2061,11 @@        "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",        "dev": true      }, +    "node_modules/js-sha3": { +      "version": "0.8.0", +      "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", +      "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" +    },      "node_modules/js-tokens": {        "version": "4.0.0",        "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2123,6 +2160,15 @@          "loose-envify": "cli.js"        }      }, +    "node_modules/match-sorter": { +      "version": "6.3.4", +      "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.4.tgz", +      "integrity": "sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==", +      "dependencies": { +        "@babel/runtime": "^7.23.8", +        "remove-accents": "0.5.0" +      } +    },      "node_modules/merge2": {        "version": "1.4.1",        "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -2145,6 +2191,11 @@          "node": ">=8.6"        }      }, +    "node_modules/microseconds": { +      "version": "0.2.0", +      "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", +      "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" +    },      "node_modules/minimatch": {        "version": "9.0.5",        "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -2166,6 +2217,14 @@        "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",        "dev": true      }, +    "node_modules/nano-time": { +      "version": "1.0.0", +      "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", +      "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", +      "dependencies": { +        "big-integer": "^1.6.16" +      } +    },      "node_modules/nanoid": {        "version": "3.3.7",        "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -2190,11 +2249,15 @@        "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",        "dev": true      }, +    "node_modules/oblivious-set": { +      "version": "1.0.0", +      "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", +      "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" +    },      "node_modules/once": {        "version": "1.4.0",        "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",        "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", -      "dev": true,        "dependencies": {          "wrappy": "1"        } @@ -2271,7 +2334,6 @@        "version": "1.0.1",        "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",        "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", -      "dev": true,        "engines": {          "node": ">=0.10.0"        } @@ -2416,6 +2478,31 @@          "react": "^16.8.0 || ^17 || ^18 || ^19"        }      }, +    "node_modules/react-query": { +      "version": "3.39.3", +      "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", +      "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==", +      "dependencies": { +        "@babel/runtime": "^7.5.5", +        "broadcast-channel": "^3.4.1", +        "match-sorter": "^6.0.2" +      }, +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/tannerlinsley" +      }, +      "peerDependencies": { +        "react": "^16.8.0 || ^17.0.0 || ^18.0.0" +      }, +      "peerDependenciesMeta": { +        "react-dom": { +          "optional": true +        }, +        "react-native": { +          "optional": true +        } +      } +    },      "node_modules/react-router": {        "version": "6.25.1",        "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.1.tgz", @@ -2446,6 +2533,16 @@          "react-dom": ">=16.8"        }      }, +    "node_modules/regenerator-runtime": { +      "version": "0.14.1", +      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", +      "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" +    }, +    "node_modules/remove-accents": { +      "version": "0.5.0", +      "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", +      "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==" +    },      "node_modules/resolve-from": {        "version": "4.0.0",        "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2470,7 +2567,6 @@        "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",        "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",        "deprecated": "Rimraf versions prior to v4 are no longer supported", -      "dev": true,        "dependencies": {          "glob": "^7.1.3"        }, @@ -2701,6 +2797,15 @@          "node": ">=14.17"        }      }, +    "node_modules/unload": { +      "version": "2.2.0", +      "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", +      "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", +      "dependencies": { +        "@babel/runtime": "^7.6.2", +        "detect-node": "^2.0.4" +      } +    },      "node_modules/uri-js": {        "version": "4.4.1",        "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -2800,8 +2905,7 @@      "node_modules/wrappy": {        "version": "1.0.2",        "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", -      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", -      "dev": true +      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="      },      "node_modules/yocto-queue": {        "version": "0.1.0", diff --git a/package.json b/package.json index 000b4c5..9955903 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@      "react": "^18.3.1",      "react-dom": "^18.3.1",      "react-hook-form": "^7.52.2", +    "react-query": "^3.39.3",      "react-router-dom": "^6.25.1",      "validator": "^13.12.0",      "zod": "^3.23.8" diff --git a/src/SignUpConfirm.tsx b/src/SignUpConfirm.tsx index 295bad6..63b9d10 100644 --- a/src/SignUpConfirm.tsx +++ b/src/SignUpConfirm.tsx @@ -1,17 +1,19 @@  import './SignUp.css'  import { useLocation, Navigate } from 'react-router-dom'; -import { Form } from './signUpSchema' +import { Form1Data, Form2Data, Form3Data, FormData, displayTel } from './signUpSchema'  export const SignUpConfirm = () => {    const location = useLocation() -  const form = location.state as Form | null; +  const data = location.state as { form1: Form1Data, form2: Form2Data, form3: Form3Data } | null; -  // form1 のデータがない場合は form1 にリダイレクトする -  if (form === null) { +  if (data === null) {      return <Navigate replace to="/sign-up/form1" />    } +  const { form1, form2, form3 } = data +  const form: FormData = { ...form1, ...form2, ...form3 } +    return (      <>        <h1>会員登録 確認画面</h1> @@ -20,14 +22,21 @@ export const SignUpConfirm = () => {          <div className="signUpForm">            <p>お名前: {form.name}</p>            <p>名前カナ: {form.kana}</p> -          <p>電話番号: {form.tel1}-{form.tel2}-{form.tel3}</p> +          <p>電話番号: {displayTel(form)}</p>          </div>          <h2>ログイン関連の情報</h2>          <div className="signUpForm">            <p>メールアドレス: {form.email}</p>            <p>パスワード: セキュリティ上の理由のため非表示</p>          </div> +        <h2>プログラミング関連の情報</h2> +        <div className="signUpForm"> +          <p>GitHubのアカウントはある?: {form.hasGitHubRepo ? 'ある' : 'ない'}</p> +          <p>GitHub の username: {form.gitHubUsername}</p> +          <p>お気に入りの GitHub リポジトリ: {form.repoName}</p> +        </div>        </div> +      <button>送信</button>      </>    );  } diff --git a/src/SignUpForm1.tsx b/src/SignUpForm1.tsx index 76c6020..4be29e9 100644 --- a/src/SignUpForm1.tsx +++ b/src/SignUpForm1.tsx @@ -2,15 +2,15 @@ import './SignUp.css'  import { useForm } from 'react-hook-form'  import { zodResolver } from "@hookform/resolvers/zod"  import { useNavigate } from 'react-router-dom'; -import { Form1, form1Schema } from './signUpSchema' +import { Form1Data, form1Schema } from './signUpSchema'  export const SignUpForm1 = () => { -  const { register, handleSubmit, formState: { errors } } = useForm<Form1>({ +  const { register, handleSubmit, formState: { errors } } = useForm<Form1Data>({      resolver: zodResolver(form1Schema),    });    const navigate = useNavigate(); -  const onsubmit = (state: Form1) => { +  const onsubmit = (state: Form1Data) => {      navigate('/sign-up/form2', { state })    }    const onerror = (err: any) => console.log(err); diff --git a/src/SignUpForm2.tsx b/src/SignUpForm2.tsx index f355225..177373d 100644 --- a/src/SignUpForm2.tsx +++ b/src/SignUpForm2.tsx @@ -2,14 +2,14 @@ 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' +import { Form1Data, Form2Data, form2Schema } from './signUpSchema'  export const SignUpForm2 = () => { -  const { register, handleSubmit, formState: { errors } } = useForm<Form2>({ +  const { register, handleSubmit, formState: { errors } } = useForm<Form2Data>({      resolver: zodResolver(form2Schema),    });    const location = useLocation(); -  const form1 = location.state as Form1 | null; +  const form1 = location.state as Form1Data | null;    const navigate = useNavigate();    // form1 のデータがない場合は form1 にリダイレクトする @@ -17,13 +17,11 @@ export const SignUpForm2 = () => {      return <Navigate replace to="/sign-up/form1" />    } -  const onsubmit = (form2: Form2) => { -    const state = { -      ...form1, -      ...form2, -    } -    navigate('/sign-up/confirm', { state }) +  const onsubmit = (form2: Form2Data) => { +    const state = { form1, form2 } +    navigate('/sign-up/form3', { state })    } +    const onerror = (err: any) => console.log(err);    return ( @@ -41,7 +39,7 @@ export const SignUpForm2 = () => {            <div className="error">{errors.password?.message}</div>          </div>          <div> -          <button type="submit">確認画面へ</button> +          <button type="submit">次へ</button>          </div>        </form>      </> diff --git a/src/SignUpForm3.tsx b/src/SignUpForm3.tsx new file mode 100644 index 0000000..bfd71d0 --- /dev/null +++ b/src/SignUpForm3.tsx @@ -0,0 +1,104 @@ +import './SignUp.css' +import { useForm } from 'react-hook-form' +import { zodResolver } from "@hookform/resolvers/zod" +import { useLocation, Navigate, useNavigate } from 'react-router-dom'; +import { Form1Data, Form2Data, Form3Data, form3Schema } from './signUpSchema' + +import { useQuery, QueryClient, QueryClientProvider } from 'react-query' + +export const SignUpForm3 = () => { +  const queryClient = new QueryClient() + +  return ( +    <QueryClientProvider client={queryClient}> +      <SignUpForm3Main /> +    </QueryClientProvider> +  ) +} + + +export const SignUpForm3Main = () => { +  const { register, watch, setValue, handleSubmit, formState: { errors } } = useForm<Form3Data>({ +    resolver: zodResolver(form3Schema), + +  }); +  const location = useLocation(); +  const formData = location.state as { form1: Form1Data, form2: Form2Data } | null; +  const navigate = useNavigate(); +  const watchHasGitHubRepo = watch("hasGitHubRepo", false) +  const gitHubUsername = watch("gitHubUsername", '') + +  const repoQueryEnabled = watchHasGitHubRepo && gitHubUsername.length > 0; + +  console.log(gitHubUsername) +  console.log(repoQueryEnabled) + +  const { data: reposData, isLoading: reposIsLoading, isError: reposIsError, error: reposError } = useQuery({ +    queryKey: ['gitHubRepos', gitHubUsername], +    queryFn: async () => { +      const res = await fetch(`https://api.github.com/users/${gitHubUsername}/repos?sort=updated&direction=desc&per_page=100`) +      if (res.ok) { return res.json(); } +      throw new Error(res.statusText) +    }, +    enabled: repoQueryEnabled, +  }) + +  const repoNames: [string] = (repoQueryEnabled && !reposIsLoading && !reposIsError) ? +    (reposData.map((json: any) => (json['name']))) : +    [] + +  // TODO: watchHasGitHubRepo が false の場合は gitHubUsername と repoName が '' になって欲しい + +  // form1, form2 のデータがない場合は form1 にリダイレクトする +  if (formData === null) { +    return <Navigate replace to="/sign-up/form1" /> +  } + +  const { form1, form2 } = formData; + +  const onsubmit = (form3: Form3Data) => { +    const state = { form1, form2, form3 } +    navigate('/sign-up/confirm', { state }) +  } +  const onerror = (err: any) => console.log(err); + +  return ( +    <> +      <h1>会員登録 フェーズ 3</h1> +      <form className="SignUpForm" onSubmit={handleSubmit(onsubmit, onerror)}> +        <div> +          <label htmlFor="hasGitHubRepo">GitHubのリポジトリある?: </label> +          <input id="hasGitHubRepo" type="checkbox" {...register('hasGitHubRepo')}></input> +          <div className="error">{errors.hasGitHubRepo?.message}</div> +        </div> +        { +          (watchHasGitHubRepo && +            <div> +              <label htmlFor="gitHubUsername">github username: </label> +              <input id="gitHubUsername" type="text" {...register('gitHubUsername')}></input> +            </div> +          ) +        } +        { +          repoQueryEnabled && ( +            ( +              reposIsLoading ? 'Loading...' : +                reposIsError ? `Error: ${reposError}` : +                  <div> +                    <label htmlFor="repoName">お気に入りのリポジトリを選んでください:</label> +                    <select id="repoName" {...register('repoName')}> +                      {repoNames.map((repoName) => ( +                        <option key={repoName} value={repoName}>{repoName}</option> +                      ))} +                    </select> +                  </div> +            ) +          ) +        } +        <div> +          <button type="submit">確認画面へ</button> +        </div> +      </form > +    </> +  ); +} diff --git a/src/routes.tsx b/src/routes.tsx index 1a3daa1..c85de49 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -3,6 +3,7 @@ import { Top } from './Top';  import { SignUp } from './SignUp';  import { SignUpForm1 } from './SignUpForm1';  import { SignUpForm2 } from './SignUpForm2'; +import { SignUpForm3 } from './SignUpForm3';  import { SignUpConfirm } from './SignUpConfirm';  export const routes = createBrowserRouter([ @@ -10,5 +11,6 @@ export const routes = createBrowserRouter([    { path: '/sign-up', element: <SignUp /> },    { path: '/sign-up/form1', element: <SignUpForm1 /> },    { path: '/sign-up/form2', element: <SignUpForm2 /> }, +  { path: '/sign-up/form3', element: <SignUpForm3 /> },    { path: '/sign-up/confirm', element: <SignUpConfirm /> },  ]); diff --git a/src/signUpSchema.ts b/src/signUpSchema.ts index 4d8b71f..3b75ba1 100644 --- a/src/signUpSchema.ts +++ b/src/signUpSchema.ts @@ -11,7 +11,7 @@ const form1SchemaWithoutRefine = z.object({    tel3: z.string(),  }) -const addRefine = <Form1 extends z.ZodTypeAny>(schema: Form1) => ( +const addTelRefine = <Form1Data extends z.ZodTypeAny>(schema: Form1Data) => (    schema.refine(      ({ tel1, tel2, tel3 }) => (tel1.length > 0 && tel2.length > 0 && tel3.length > 0),      { @@ -30,9 +30,6 @@ const addRefine = <Form1 extends z.ZodTypeAny>(schema: Form1) => (      }    )) - -export type Form1 = z.infer<typeof form1SchemaWithoutRefine> -  export const form2Schema = z.object({    email: z.string().min(1, { message: '必須項目です' }).email({ message: 'メールアドレスを入力してください' }),    password: z.string() @@ -41,11 +38,24 @@ export const form2Schema = z.object({      .max(128, { message: '128文字以下で入力してください' })  }) -export type Form2 = z.infer<typeof form2Schema> +const favLangSchema = z.object({ +  name: z.string() +}) + +export const form3Schema = z.object({ +  // favLangs: z.array(favLangSchema), +  hasGitHubRepo: z.boolean(), +  gitHubUsername: z.string(), +  repoName: z.string(), +}) -const formSchemaWithoutRefine = form1SchemaWithoutRefine.merge(form2Schema) +const formSchemaWithoutRefine = form1SchemaWithoutRefine.merge(form2Schema).merge(form3Schema) +export const form1Schema = addTelRefine(form1SchemaWithoutRefine) +export const formSchema = addTelRefine(formSchemaWithoutRefine) -export type Form = z.infer<typeof formSchemaWithoutRefine> +export type Form1Data = z.infer<typeof form1SchemaWithoutRefine> +export type Form2Data = z.infer<typeof form2Schema> +export type Form3Data = z.infer<typeof form3Schema> +export type FormData = z.infer<typeof formSchemaWithoutRefine> -export const form1Schema = addRefine(form1SchemaWithoutRefine) -export const formSchema = addRefine(formSchemaWithoutRefine) +export const displayTel = ({ tel1, tel2, tel3 }: Form1Data) => (`${tel1}-${tel2}-${tel3}`) | 
