Browse Source

親子アカウント対応

develop
sosuke.iwabuchi 1 year ago
parent
commit
8da12c4e84
5 changed files with 133 additions and 41 deletions
  1. +24
    -1
      src/api/auth.ts
  2. +1
    -0
      src/api/index.ts
  3. +1
    -0
      src/api/url.ts
  4. +16
    -4
      src/contexts/AuthContext.tsx
  5. +91
    -36
      src/pages/auth/login.tsx

+ 24
- 1
src/api/auth.ts View File

@@ -31,7 +31,30 @@ export const me = async () => {
return res;
};

export const login = async (param: { email: string; password: string }) => {
export type LoginCheckRequest = {
email: string;
password: string;
};
export type LoginCheckResponse = {
data: {
customer_code: number;
name: string;
}[];
} & APICommonResponse;
export const loginCheck = async (param: LoginCheckRequest) => {
const res = await request<LoginCheckResponse>({
url: getUrl(ApiId.LOGIN_CHECK),
method: HttpMethod.POST,
data: param,
});
return res;
};

export const login = async (param: {
email: string;
password: string;
customer_code: number;
}) => {
const res = await request<MeResponse>({
url: getUrl(ApiId.LOGIN),
method: HttpMethod.POST,


+ 1
- 0
src/api/index.ts View File

@@ -13,6 +13,7 @@ export const ApiId = {
// 認証関連 ----------------------------------
ME: id++,
LOGIN: id++,
LOGIN_CHECK: id++,
LOGOUT: id++,
PASSWORD_SETTING_START: id++,
PASSWORD_SETTING_VERIFY: id++,


+ 1
- 0
src/api/url.ts View File

@@ -5,6 +5,7 @@ const urls = {
[A.CSRF_TOKEN]: "sanctum/csrf-cookie",
[A.ME]: "me",
[A.LOGIN]: "login",
[A.LOGIN_CHECK]: "login/check",
[A.LOGOUT]: "logout",
[A.PASSWORD_SETTING_START]: "password/setting/start",
[A.PASSWORD_SETTING_VERIFY]: "password/setting/verify",


+ 16
- 4
src/contexts/AuthContext.tsx View File

@@ -12,7 +12,11 @@ type Auth = {
email: string;
user: Me | null;

login: (email: string, password: string) => Promise<boolean>;
login: (
email: string,
password: string,
customerCode: number
) => Promise<boolean>;
logout: VoidFunction;
me: VoidFunction;
};
@@ -25,7 +29,7 @@ export const AuthContext = createContext<Auth>({
email: "",
user: null,

login: async (email: string, password: string) => false,
login: async (email: string, password: string, customerCode: number) => false,
logout: () => {},
me: () => {},
});
@@ -80,8 +84,16 @@ function AuthContextProvider({ children }: Props) {
setUser(null);
};

const login = async (email: string, password: string) => {
const res = await callLogin({ email, password });
const login = async (
email: string,
password: string,
customerCode: number
) => {
const res = await callLogin({
email,
password,
customer_code: customerCode,
});
return res?.result === ResultCode.SUCCESS;
};
const logout = () => {


+ 91
- 36
src/pages/auth/login.tsx View File

@@ -1,13 +1,14 @@
import { yupResolver } from "@hookform/resolvers/yup";
import { LoadingButton } from "@mui/lab";
import { Box, Button, Stack, Typography } from "@mui/material";
import { Box, Button, Card, Stack, Typography } from "@mui/material";
import { LoginCheckResponse, loginCheck } from "api/auth";
import InputAlert from "components/form/InputAlert";
import { FormProvider, RHFTextField } from "components/hook-form";
import useAPICall from "hooks/useAPICall";
import useAuth from "hooks/useAuth";
import useNavigateCustom from "hooks/useNavigateCustom";
import useSnackbarCustom from "hooks/useSnackbarCustom";
import { PageID } from "pages";
import { useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { useForm } from "react-hook-form";
import { useLocation } from "react-router-dom";
import { getPath } from "routes/path";
@@ -28,7 +29,9 @@ export default function Login() {
const { pathname } = useLocation();

const [message, setMessage] = useState("");
const [sending, setSending] = useState(false);
const [checkResponse, setCheckResponse] = useState<LoginCheckResponse | null>(
null
);

const { login } = useAuth();

@@ -42,49 +45,101 @@ export default function Login() {
resolver: yupResolver(LoginSchema),
});

const handleSubmit = async (data: FormProps) => {
setMessage("");
setSending(true);
const ret = await login(data.email, data.password);
const { callAPI: callLoginCheck } = useAPICall({
apiMethod: loginCheck,
backDrop: true,
form,
onSuccess: (res) => {
setCheckResponse(res);
},
onFailed: () => {
error("ログイン失敗");
setMessage("入力情報を確認してください");
setCheckResponse(null);
},
});

setSending(false);
const handleSubmit = async (data: FormProps) => {
callLoginCheck(data);
};

if (ret) {
success("ログイン成功");
if (pathname === getPath(PageID.LOGIN)) {
navigateWhenChanged(getPath(PageID.DASHBOARD_OVERVIEW));
const handleSelect = (customerCode: number) => {
login(
form.getValues("email"),
form.getValues("password"),
customerCode
).then((ret) => {
if (ret) {
success("ログイン成功");
if (pathname === getPath(PageID.LOGIN)) {
navigateWhenChanged(getPath(PageID.DASHBOARD_OVERVIEW));
}
} else {
error("ログイン失敗");
setMessage("入力情報を確認してください");
setCheckResponse(null);
}
} else {
error("ログイン失敗");
setMessage("入力情報を確認してください");
}
});
};

const needSelectUser: boolean = useMemo(() => {
return checkResponse !== null && 1 < checkResponse.data.length;
}, [checkResponse]);

useEffect(() => {
if (checkResponse && checkResponse.data.length === 1) {
const customerCode = checkResponse.data[0].customer_code;
handleSelect(customerCode);
}
}, [checkResponse]);

return (
<FormProvider methods={form} onSubmit={form.handleSubmit(handleSubmit)}>
<Box sx={{ p: 3, pt: 5, mx: "auto", maxWidth: 500 }} textAlign="center">
<Stack spacing={3}>
<Typography variant="h5">ログイン</Typography>
<InputAlert error="none" message={message} />
<RHFTextField name="email" label="email" size="small" />
<RHFTextField
name="password"
type="password"
label="password"
size="small"
/>
{needSelectUser && (
<>
<Typography variant="h6">ユーザー選択</Typography>
{checkResponse?.data.map((ele) => {
return (
<Button
variant="outlined"
key={ele.customer_code}
onClick={() => handleSelect(ele.customer_code)}
>
<Typography>{ele.name}</Typography>
</Button>
);
})}
</>
)}
{!needSelectUser && (
<>
<InputAlert error="none" message={message} />
<RHFTextField name="email" label="email" size="small" />
<RHFTextField
name="password"
type="password"
label="password"
size="small"
/>

<LoadingButton loading={sending} type="submit" variant="contained">
ログイン
</LoadingButton>
<Button
variant="outlined"
onClick={() => {
navigateWhenChanged(getPath(PageID.USER_SETTING_PASSWORD_START));
}}
>
パスワードを忘れた/設定したい
</Button>
<Button type="submit" variant="contained">
ログイン
</Button>
<Button
variant="outlined"
onClick={() => {
navigateWhenChanged(
getPath(PageID.USER_SETTING_PASSWORD_START)
);
}}
>
パスワードを忘れた/設定したい
</Button>
</>
)}
</Stack>
</Box>
</FormProvider>


Loading…
Cancel
Save