mirror of
https://github.com/ershisan99/todolist_next.git
synced 2025-12-16 12:33:57 +00:00
add sign-up page
This commit is contained in:
@@ -10,7 +10,8 @@ import { useMeQuery } from "@/services";
|
||||
export const AuthRedirect: FC<{ children: ReactNode }> = ({ children }) => {
|
||||
const router = useRouter();
|
||||
const { data: user, isLoading } = useMeQuery();
|
||||
const isAuthPage = router.pathname === "/login";
|
||||
const isAuthPage =
|
||||
router.pathname === "/login" || router.pathname === "/sign-up";
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading && !user && !isAuthPage) {
|
||||
|
||||
49
src/pages/sign-up.tsx
Normal file
49
src/pages/sign-up.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import type { FormEvent } from "react";
|
||||
import React from "react";
|
||||
|
||||
import type { NextPage } from "next";
|
||||
|
||||
import { Button, Input } from "@/components";
|
||||
import { useSignUpMutation } from "@/services";
|
||||
|
||||
const Login: NextPage = () => {
|
||||
const { mutate: signUp } = useSignUpMutation();
|
||||
|
||||
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(e.currentTarget);
|
||||
|
||||
const values = Object.fromEntries(formData) as any;
|
||||
signUp(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={"flex h-screen items-center justify-center"}>
|
||||
<form
|
||||
className={"flex w-96 flex-col gap-3 rounded-md border p-6"}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<h1 className={"text-2xl font-bold"}>Sign up</h1>
|
||||
<label className={"flex flex-col gap-1"}>
|
||||
Username (optional)
|
||||
<Input name={"username"} type="text" />
|
||||
</label>
|
||||
<label className={"flex flex-col gap-1"}>
|
||||
Email
|
||||
<Input name={"email"} type="email" />
|
||||
</label>
|
||||
|
||||
<label className={"flex flex-col gap-1"}>
|
||||
Password
|
||||
<Input type="password" name={"password"} />
|
||||
</label>
|
||||
|
||||
<Button className={"w-full"} type={"submit"}>
|
||||
Login
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Login;
|
||||
@@ -3,6 +3,7 @@ import type {
|
||||
LogoutResponse,
|
||||
MeResponse,
|
||||
PostLoginArgs,
|
||||
PostSignUpArgs,
|
||||
} from "../todolists";
|
||||
|
||||
import { handleError } from "@/helpers";
|
||||
@@ -12,7 +13,7 @@ export const AuthApi = {
|
||||
async login(args: PostLoginArgs) {
|
||||
const res = await todolistApiInstance.post<LoginResponse>(
|
||||
"/auth/login",
|
||||
args
|
||||
args,
|
||||
);
|
||||
|
||||
localStorage.setItem("accessToken", res.data.accessToken);
|
||||
@@ -20,7 +21,11 @@ export const AuthApi = {
|
||||
|
||||
return res.data;
|
||||
},
|
||||
async signUp(args: PostSignUpArgs) {
|
||||
const res = await todolistApiInstance.post<any>("/auth/sign-up", args);
|
||||
|
||||
return res.data;
|
||||
},
|
||||
async logout() {
|
||||
const res = await todolistApiInstance.delete<LogoutResponse>("/auth/login");
|
||||
|
||||
|
||||
@@ -38,3 +38,9 @@ export const useLogoutMutation = () => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useSignUpMutation = () => {
|
||||
return useMutation({
|
||||
mutationFn: AuthApi.signUp,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@ const mutex = new Mutex();
|
||||
let refreshedAt: number | null = null;
|
||||
|
||||
export const todolistApiInstance = axios.create({
|
||||
baseURL: "http://localhost:3000"
|
||||
baseURL: "http://localhost:3000",
|
||||
});
|
||||
|
||||
async function refreshAccessToken(): Promise<string> {
|
||||
@@ -19,9 +19,9 @@ async function refreshAccessToken(): Promise<string> {
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("refreshToken")}`
|
||||
}
|
||||
}
|
||||
Authorization: `Bearer ${localStorage.getItem("refreshToken")}`,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
localStorage.setItem("accessToken", res.data.accessToken);
|
||||
@@ -42,14 +42,15 @@ todolistApiInstance.interceptors.request.use(
|
||||
|
||||
return config;
|
||||
},
|
||||
(error) => Promise.reject(error)
|
||||
(error) => Promise.reject(error),
|
||||
);
|
||||
|
||||
todolistApiInstance.interceptors.response.use(
|
||||
(response) => response,
|
||||
async (error) => {
|
||||
if(error?.response?.request?.responseURL?.includes("refresh-token")){
|
||||
return }
|
||||
if (error?.response?.request?.responseURL?.includes("refresh-token")) {
|
||||
return;
|
||||
}
|
||||
await mutex.waitForUnlock();
|
||||
const originalRequest = error.config;
|
||||
// Check for a 401 response and if this request hasn't been retried yet
|
||||
@@ -61,9 +62,7 @@ todolistApiInstance.interceptors.response.use(
|
||||
|
||||
if (refreshedAt && refreshedAt + 60000 > new Date().getTime()) {
|
||||
// If the token has been refreshed within the last minute, use the refreshed token
|
||||
originalRequest.headers[
|
||||
"Authorization"
|
||||
] = `Bearer ${localStorage.getItem("accessToken")}`;
|
||||
originalRequest.headers.Authorization = `Bearer ${localStorage.getItem("accessToken")}`;
|
||||
release();
|
||||
|
||||
return todolistApiInstance(originalRequest);
|
||||
@@ -72,11 +71,14 @@ todolistApiInstance.interceptors.response.use(
|
||||
try {
|
||||
const newAccessToken = await refreshAccessToken();
|
||||
|
||||
originalRequest.headers["Authorization"] = `Bearer ${newAccessToken}`;
|
||||
originalRequest.headers.Authorization = `Bearer ${newAccessToken}`;
|
||||
|
||||
return todolistApiInstance(originalRequest); // Retry the original request with the new token
|
||||
} catch (error) {
|
||||
router.push("/login");
|
||||
console.log(window.location.pathname);
|
||||
if (!["/login", "/sign-up"].includes(window.location.pathname)) {
|
||||
router.push("/login");
|
||||
}
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
@@ -84,12 +86,12 @@ todolistApiInstance.interceptors.response.use(
|
||||
await mutex.waitForUnlock();
|
||||
const newAccessToken = localStorage.getItem("accessToken");
|
||||
|
||||
originalRequest.headers["Authorization"] = `Bearer ${newAccessToken}`;
|
||||
originalRequest.headers.Authorization = `Bearer ${newAccessToken}`;
|
||||
|
||||
return todolistApiInstance(originalRequest); // Retry the original request with the new token
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@@ -29,6 +29,12 @@ export type PostLoginArgs = {
|
||||
rememberMe: boolean;
|
||||
};
|
||||
|
||||
export type PostSignUpArgs = {
|
||||
email: string;
|
||||
password: string;
|
||||
username?: string;
|
||||
};
|
||||
|
||||
export type LoginResponseData = {
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
@@ -51,8 +57,8 @@ export type CreateTodolistResponseData = {
|
||||
};
|
||||
|
||||
export type CreateTaskResponse = Task;
|
||||
export type DeleteTaskResponse = void;
|
||||
export type UpdateTaskResponse = void;
|
||||
export type DeleteTaskResponse = undefined;
|
||||
export type UpdateTaskResponse = undefined;
|
||||
|
||||
export enum TaskStatus {
|
||||
OPEN = "OPEN",
|
||||
|
||||
Reference in New Issue
Block a user