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; 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>({ const res = await request<MeResponse>({
url: getUrl(ApiId.LOGIN), url: getUrl(ApiId.LOGIN),
method: HttpMethod.POST, method: HttpMethod.POST,


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

@@ -13,6 +13,7 @@ export const ApiId = {
// 認証関連 ---------------------------------- // 認証関連 ----------------------------------
ME: id++, ME: id++,
LOGIN: id++, LOGIN: id++,
LOGIN_CHECK: id++,
LOGOUT: id++, LOGOUT: id++,
PASSWORD_SETTING_START: id++, PASSWORD_SETTING_START: id++,
PASSWORD_SETTING_VERIFY: 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.CSRF_TOKEN]: "sanctum/csrf-cookie",
[A.ME]: "me", [A.ME]: "me",
[A.LOGIN]: "login", [A.LOGIN]: "login",
[A.LOGIN_CHECK]: "login/check",
[A.LOGOUT]: "logout", [A.LOGOUT]: "logout",
[A.PASSWORD_SETTING_START]: "password/setting/start", [A.PASSWORD_SETTING_START]: "password/setting/start",
[A.PASSWORD_SETTING_VERIFY]: "password/setting/verify", [A.PASSWORD_SETTING_VERIFY]: "password/setting/verify",


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

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


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


login: async (email: string, password: string) => false,
login: async (email: string, password: string, customerCode: number) => false,
logout: () => {}, logout: () => {},
me: () => {}, me: () => {},
}); });
@@ -80,8 +84,16 @@ function AuthContextProvider({ children }: Props) {
setUser(null); 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; return res?.result === ResultCode.SUCCESS;
}; };
const logout = () => { const logout = () => {


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

@@ -1,13 +1,14 @@
import { yupResolver } from "@hookform/resolvers/yup"; 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 InputAlert from "components/form/InputAlert";
import { FormProvider, RHFTextField } from "components/hook-form"; import { FormProvider, RHFTextField } from "components/hook-form";
import useAPICall from "hooks/useAPICall";
import useAuth from "hooks/useAuth"; import useAuth from "hooks/useAuth";
import useNavigateCustom from "hooks/useNavigateCustom"; import useNavigateCustom from "hooks/useNavigateCustom";
import useSnackbarCustom from "hooks/useSnackbarCustom"; import useSnackbarCustom from "hooks/useSnackbarCustom";
import { PageID } from "pages"; import { PageID } from "pages";
import { useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
import { getPath } from "routes/path"; import { getPath } from "routes/path";
@@ -28,7 +29,9 @@ export default function Login() {
const { pathname } = useLocation(); const { pathname } = useLocation();


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


const { login } = useAuth(); const { login } = useAuth();


@@ -42,49 +45,101 @@ export default function Login() {
resolver: yupResolver(LoginSchema), 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 ( return (
<FormProvider methods={form} onSubmit={form.handleSubmit(handleSubmit)}> <FormProvider methods={form} onSubmit={form.handleSubmit(handleSubmit)}>
<Box sx={{ p: 3, pt: 5, mx: "auto", maxWidth: 500 }} textAlign="center"> <Box sx={{ p: 3, pt: 5, mx: "auto", maxWidth: 500 }} textAlign="center">
<Stack spacing={3}> <Stack spacing={3}>
<Typography variant="h5">ログイン</Typography> <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> </Stack>
</Box> </Box>
</FormProvider> </FormProvider>


Loading…
Cancel
Save