diff --git a/src/api/zipcode.ts b/src/api/zipcode.ts new file mode 100644 index 0000000..959371a --- /dev/null +++ b/src/api/zipcode.ts @@ -0,0 +1,67 @@ +export type GetAddressFromZipCodeResponse = { + success: boolean; + zipcode: string; + prefcode?: string; + address1?: string; + address2?: string; +}; + +type APIResponse = { + status: number; + message: string | null; + results: + | { + zipcode: string; // 郵便番号 7桁の郵便番号。ハイフンなし。 + prefcode: string; // 都道府県コード JIS X 0401 に定められた2桁の都道府県コード。 + address1: string; // 都道府県名 + address2: string; // 市区町村名 + address3: string; // 町域名 + kana1: string; // 都道府県名カナ + kana2: string; // 市区町村名カナ + kana3: string; // + }[] + | null; +}; + +// 郵便番号から住所を検索するAPIを呼ぶ +export async function getAddressFromZipCode( + zipcode: string +): Promise { + const url = 'https://zipcloud.ibsnet.co.jp/api/search?zipcode=' + zipcode; + + try { + const data = await callAPI(url); + + if (data.status !== 200) { + throw Error('ステータス不正:' + data.status); + } + if (data.results === null || data.results.length === 0) { + throw Error('結果0件:' + data.status); + } + + const target = data.results[0]; + + // 正常返却 + return { + success: true, + zipcode, + prefcode: target.prefcode, + address1: target.address2, + address2: target.address3, + }; + } catch (e) { + if (e instanceof Error) { + console.error('zipcode error', e.message); + } + // エラー返却 + return { + success: false, + zipcode, + }; + } +} + +async function callAPI(url: string): Promise { + const data = await (await fetch(url)).json(); + return data; +} diff --git a/src/pages/app/hooks/useInputMailStep.tsx b/src/pages/app/hooks/useInputMailStep.tsx index 7bca1a3..d481a23 100644 --- a/src/pages/app/hooks/useInputMailStep.tsx +++ b/src/pages/app/hooks/useInputMailStep.tsx @@ -1,9 +1,11 @@ import { yupResolver } from "@hookform/resolvers/yup"; import { Box, Button, Divider, Stack, Typography } from "@mui/material"; import { HasChildren } from "@types"; +import { getAddressFromZipCode } from "api/zipcode"; import { FormProvider, RHFTextField } from "components/hook-form"; import RHFDatePicker from "components/hook-form/RHFDatePicker"; import RHFPrefCodeSelect from "components/hook-form/ex/RHFPrefCodeSelect"; +import useBackDrop from "hooks/useBackDrop"; import useNavigateCustom from "hooks/useNavigateCustom"; import { useForm } from "react-hook-form"; import * as Yup from "yup"; @@ -34,6 +36,8 @@ type Props = { onPrev?: VoidFunction; }; export default function useInputMailStep({ onNext, onPrev }: Props) { + const { setShowBackDrop } = useBackDrop(); + const form = useForm({ defaultValues: { mail_pref_code: "", @@ -65,6 +69,24 @@ export default function useInputMailStep({ onNext, onPrev }: Props) { ), }); + const zipCode = form.watch("mail_zip_code"); + const handleBlurZipCode = () => { + if (/^[0-9]{7}$/.test(zipCode)) { + setShowBackDrop(true); + getAddressFromZipCode(zipCode) + .then((res) => { + if (res.success) { + form.setValue("mail_pref_code", res.prefcode ?? ""); + form.setValue("mail_address1", res.address1 ?? ""); + form.setValue("mail_address2", res.address2 ?? ""); + } + }) + .finally(() => { + setShowBackDrop(false); + }); + } + }; + const handleSubmit = () => { if (onNext) { onNext(); @@ -80,16 +102,17 @@ export default function useInputMailStep({ onNext, onPrev }: Props) { const element = ( - - - ハイフン無の7桁 〒 }} + onBlur={handleBlurZipCode} /> + + +