diff --git a/src/api/auth.ts b/src/api/auth.ts index deec527..51ea8b2 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -1,4 +1,4 @@ -import { APICommonResponse, ApiId, HttpMethod, request } from "."; +import { APICommonResponse, ApiId, HttpMethod, makeParam, request } from "."; import { getUrl } from "./url"; export type Me = { @@ -41,3 +41,34 @@ export const logout = async () => { }); return res; }; + +// -------パスワード設定開始--------------- +export type StartPasswordSettingRequest = { + email: string; +}; +export const startPasswordSetting = async ( + param: StartPasswordSettingRequest +) => { + const res = await request({ + url: getUrl(ApiId.PASSWORD_SETTING_START), + method: HttpMethod.POST, + data: makeParam(param), + }); + return res; +}; + +// -------パスワード設定認証--------------- +export type VerifyPasswordSettingRequest = { + token: string; + password: string; +}; +export const verifyPasswordSetting = async ( + param: VerifyPasswordSettingRequest +) => { + const res = await request({ + url: getUrl(ApiId.PASSWORD_SETTING_VERIFY), + method: HttpMethod.POST, + data: makeParam(param), + }); + return res; +}; diff --git a/src/api/index.ts b/src/api/index.ts index f3902fa..165ac77 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -14,6 +14,9 @@ export const ApiId = { LOGIN: id++, LOGOUT: id++, + PASSWORD_SETTING_START: id++, + PASSWORD_SETTING_VERIFY: id++, + SEASON_TICKET_CONTRACTS: id++, PAYMENT_PLANS: id++, diff --git a/src/api/url.ts b/src/api/url.ts index 40ffe93..9971867 100644 --- a/src/api/url.ts +++ b/src/api/url.ts @@ -6,6 +6,8 @@ const urls = { [A.ME]: "me", [A.LOGIN]: "login", [A.LOGOUT]: "logout", + [A.PASSWORD_SETTING_START]: "password/setting/start", + [A.PASSWORD_SETTING_VERIFY]: "password/setting/verify", [A.SEASON_TICKET_CONTRACTS]: "season-ticket-contracts", [A.PAYMENT_PLANS]: "season-ticket-contract/payment-plans", [A.STICKER_RE_ORDER]: "season-ticket-contract/sticker-re-order", diff --git a/src/pages/auth/login.tsx b/src/pages/auth/login.tsx index 6d8f4e6..4968942 100644 --- a/src/pages/auth/login.tsx +++ b/src/pages/auth/login.tsx @@ -73,7 +73,14 @@ export default function Login() { ログイン - + diff --git a/src/pages/auth/password-setting-start.tsx b/src/pages/auth/password-setting-start.tsx new file mode 100644 index 0000000..c1d6c27 --- /dev/null +++ b/src/pages/auth/password-setting-start.tsx @@ -0,0 +1,120 @@ +import { yupResolver } from "@hookform/resolvers/yup"; +import { Box, Button, Stack, Typography } from "@mui/material"; +import { HasChildren } from "@types"; +import { startPasswordSetting } from "api/auth"; +import RequireChip from "components/chip/RequireChip"; +import { FormProvider, RHFTextField } from "components/hook-form"; +import StackRow from "components/stack/StackRow"; +import useAPICall from "hooks/useAPICall"; +import useNavigateCustom from "hooks/useNavigateCustom"; +import { PageID } from "pages"; +import { useState } from "react"; +import { useForm } from "react-hook-form"; +import { getPath } from "routes/path"; +import { object as YupObject, string as YupString } from "yup"; + +type AreaBoxProps = { + label: string; + require?: boolean; +} & HasChildren; +function AreaBox({ label, children, require }: AreaBoxProps) { + return ( + + + 〇{label} + + + {children} + + ); +} + +type FormProps = { + email: string; + retype_email: string; +}; + +export default function PasswordSettingStart() { + const { navigateWhenChanged } = useNavigateCustom(); + + const [done, setDone] = useState(null); + + const form = useForm({ + defaultValues: { + email: "", + retype_email: "", + }, + resolver: yupResolver( + YupObject().shape({ + email: YupString().required("必須項目です"), + retype_email: YupString() + .required("必須項目です") + .test("retype", "一致しません", function (value) { + return value === this.parent.email; + }), + }) + ), + }); + + const { callAPI: callStartPasswordSetting } = useAPICall({ + apiMethod: startPasswordSetting, + backDrop: true, + form, + onSuccess: () => { + setDone(true); + }, + onFailed: () => {}, + }); + + const handleSubmit = (data: FormProps) => { + callStartPasswordSetting({ ...data }); + }; + + const toLogin = () => { + navigateWhenChanged(getPath(PageID.LOGIN)); + }; + + if (done === true) { + return ( + + + + + メールアドレスに設定手続きのご案内を送信しました。 + + ご確認ください。 + + + + + + + ); + } + + return ( + + + + + + + + + 登録済みのメールアドレスへ変更用のURLを送信します。 + + + + + + + + + + + + + + + ); +} diff --git a/src/pages/auth/password-setting-verify.tsx b/src/pages/auth/password-setting-verify.tsx new file mode 100644 index 0000000..c5502fb --- /dev/null +++ b/src/pages/auth/password-setting-verify.tsx @@ -0,0 +1,117 @@ +import { yupResolver } from "@hookform/resolvers/yup"; +import { Box, Button, Stack, Typography } from "@mui/material"; +import { HasChildren } from "@types"; +import { verifyPasswordSetting } from "api/auth"; +import RequireChip from "components/chip/RequireChip"; +import { FormProvider, RHFTextField } from "components/hook-form"; +import StackRow from "components/stack/StackRow"; +import useAPICall from "hooks/useAPICall"; +import useNavigateCustom from "hooks/useNavigateCustom"; +import { PageID } from "pages"; +import { useState } from "react"; +import { useForm } from "react-hook-form"; +import { useParams } from "react-router-dom"; +import { getPath } from "routes/path"; +import { object as YupObject, string as YupString } from "yup"; + +type AreaBoxProps = { + label: string; + require?: boolean; +} & HasChildren; +function AreaBox({ label, children, require }: AreaBoxProps) { + return ( + + + 〇{label} + + + {children} + + ); +} + +type FormProps = { + password: string; + retype_password: string; +}; + +export default function PasswordSettingVerify() { + const { navigateWhenChanged } = useNavigateCustom(); + const { token: paramToken } = useParams(); + + const [done, setDone] = useState(null); + + const form = useForm({ + defaultValues: { + password: "", + retype_password: "", + }, + resolver: yupResolver( + YupObject().shape({ + password: YupString().required("必須項目です"), + retype_password: YupString() + .required("必須項目です") + .test("retype", "一致しません", function (value) { + return value === this.parent.password; + }), + }) + ), + }); + + const { callAPI: callVerifyPasswordSetting } = useAPICall({ + apiMethod: verifyPasswordSetting, + backDrop: true, + form, + onSuccess: () => { + setDone(true); + }, + onFailed: () => {}, + }); + + const handleSubmit = (data: FormProps) => { + if (!paramToken) return; + callVerifyPasswordSetting({ ...data, token: paramToken }); + }; + + const toLogin = () => { + navigateWhenChanged(getPath(PageID.LOGIN)); + }; + + if (done === true) { + return ( + + + + パスワードを設定しました + + + + + + + ); + } + + return ( + + + + + + 新たに設定するログインパスワードを入力してください + + + + + + + + + + + + + + + ); +} diff --git a/src/pages/index.ts b/src/pages/index.ts index eac2f66..3f48ac4 100644 --- a/src/pages/index.ts +++ b/src/pages/index.ts @@ -5,6 +5,8 @@ export const PageID = { LOGIN: id++, LOGOUT: id++, USER_CHANGE_EMAIL_VERIFY: id++, + USER_SETTING_PASSWORD_START: id++, + USER_SETTING_PASSWORD_VERIFY: id++, DASHBOARD_OVERVIEW: id++, diff --git a/src/routes/index.tsx b/src/routes/index.tsx index c99ffce..dfbafad 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -35,7 +35,14 @@ const AuthRoutes = (): RouteObject => ({ path: getRoute(PageID.USER_CHANGE_EMAIL_VERIFY), element: , }, - {}, + { + path: getRoute(PageID.USER_SETTING_PASSWORD_START), + element: , + }, + { + path: getRoute(PageID.USER_SETTING_PASSWORD_VERIFY), + element: , + }, ], }); @@ -63,6 +70,12 @@ const Logout = Loadable(lazy(() => import("pages/auth/logout"))); const ChangeEmailVerify = Loadable( lazy(() => import("pages/auth/change-email-verify")) ); +const PasswordSettingStart = Loadable( + lazy(() => import("pages/auth/password-setting-start")) +); +const PasswordSettingVerify = Loadable( + lazy(() => import("pages/auth/password-setting-verify")) +); // その他 --------------------------------- diff --git a/src/routes/path.ts b/src/routes/path.ts index 230bc36..67d8531 100644 --- a/src/routes/path.ts +++ b/src/routes/path.ts @@ -66,6 +66,9 @@ const PATHS = { [makePathKey(PageID.LOGIN)]: "/login", [makePathKey(PageID.LOGOUT)]: "/logout", [makePathKey(PageID.USER_CHANGE_EMAIL_VERIFY)]: "/change/email/verify/:token", + [makePathKey(PageID.USER_SETTING_PASSWORD_START)]: "/setting/password/start", + [makePathKey(PageID.USER_SETTING_PASSWORD_VERIFY)]: + "/setting/password/verify/:token", // ダッシュボード---------------- ...PATHS_DASHBOARD,