From 626ad87d882ef50188ceea96f3716582e3fca636 Mon Sep 17 00:00:00 2001 From: Sosokker Date: Fri, 14 Feb 2025 00:02:49 +0700 Subject: [PATCH] feat: use cookie instead of localstorage for token --- frontend/api/authentication.ts | 2 +- frontend/app/auth/signin/page.tsx | 13 ++++++++++--- frontend/app/auth/signup/page.tsx | 24 ++++++++++++++++-------- frontend/app/layout.tsx | 2 +- frontend/app/page.tsx | 2 +- frontend/context/SessionContext.tsx | 10 ++++------ frontend/hooks/useLogout.tsx | 5 +++++ frontend/package.json | 1 + frontend/pnpm-lock.yaml | 9 +++++++++ package.json | 5 +++++ pnpm-lock.yaml | 22 ++++++++++++++++++++++ 11 files changed, 75 insertions(+), 20 deletions(-) create mode 100644 package.json create mode 100644 pnpm-lock.yaml diff --git a/frontend/api/authentication.ts b/frontend/api/authentication.ts index 218c996..4ff06b4 100644 --- a/frontend/api/authentication.ts +++ b/frontend/api/authentication.ts @@ -2,7 +2,7 @@ import axios from "axios"; import axiosInstance from "./config"; export interface LoginResponse { - Token: string; + token: string; message?: string; } diff --git a/frontend/app/auth/signin/page.tsx b/frontend/app/auth/signin/page.tsx index 5891049..c56b67c 100644 --- a/frontend/app/auth/signin/page.tsx +++ b/frontend/app/auth/signin/page.tsx @@ -15,15 +15,17 @@ import Link from "next/link"; import Image from "next/image"; import { GoogleSigninButton } from "./google-oauth"; import { z } from "zod"; -import { useState } from "react"; +import { useContext, useState } from "react"; import { useRouter } from "next/navigation"; import { loginUser } from "@/api/authentication"; +import { SessionContext } from "@/context/SessionContext"; export default function SigninPage() { const [serverError, setServerError] = useState(null); const [isLoading, setIsLoading] = useState(false); const router = useRouter(); + const session = useContext(SessionContext); const { register, @@ -43,8 +45,13 @@ export default function SigninPage() { try { const data = await loginUser(values.email, values.password); - localStorage.setItem("token", data.Token); - localStorage.setItem("user", values.email); + + if (!data) { + setServerError("An error occurred while logging in. Please try again."); + throw new Error("No data received from the server."); + } + session!.setToken(data.token); + session!.setUser(values.email); router.push("/setup"); } catch (error: any) { diff --git a/frontend/app/auth/signup/page.tsx b/frontend/app/auth/signup/page.tsx index 360e237..3821817 100644 --- a/frontend/app/auth/signup/page.tsx +++ b/frontend/app/auth/signup/page.tsx @@ -5,24 +5,27 @@ import { useForm } from "react-hook-form"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { Checkbox } from "@/components/ui/checkbox"; import { Button } from "@/components/ui/button"; import { signUpSchema } from "@/schema/authSchema"; import Link from "next/link"; import Image from "next/image"; -import { useState } from "react"; +import { useContext, useState } from "react"; import { z } from "zod"; import { useRouter } from "next/navigation"; import { registerUser } from "@/api/authentication"; +import { SessionContext } from "@/context/SessionContext"; export default function SignupPage() { const [serverError, setServerError] = useState(null); const [successMessage, setSuccessMessage] = useState(null); + const [isLoading, setIsLoading] = useState(false); + const router = useRouter(); + const session = useContext(SessionContext); const { register, @@ -40,20 +43,25 @@ export default function SignupPage() { const onSubmit = async (values: z.infer) => { setServerError(null); setSuccessMessage(null); + setIsLoading(true); try { const data = await registerUser(values.email, values.password); - localStorage.setItem("token", data.token); - localStorage.setItem("user", values.email); + if (!data) { + setServerError("An error occurred while registering. Please try again."); + throw new Error("No data received from the server."); + } + session!.setToken(data.token); + session!.setUser(values.email); - console.log("Registration successful:", data); setSuccessMessage("Registration successful! You can now sign in."); - router.push("/setup"); } catch (error: any) { console.error("Error during registration:", error); setServerError(error.message); + } finally { + setIsLoading(false); } }; @@ -105,8 +113,8 @@ export default function SignupPage() { {serverError &&

{serverError}

} {successMessage &&

{successMessage}

} - diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index 6be9eda..17285cf 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -36,7 +36,7 @@ export default function RootLayout({ - +
{children}
diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index 1d68f3c..2664cbf 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -41,7 +41,7 @@ export default function Home() { It's a smart and easy way to optimize your agricultural business, with the help of AI-driven insights and real-time data.

- + diff --git a/frontend/context/SessionContext.tsx b/frontend/context/SessionContext.tsx index 721a41d..24c70a9 100644 --- a/frontend/context/SessionContext.tsx +++ b/frontend/context/SessionContext.tsx @@ -1,6 +1,7 @@ "use client"; import React, { createContext, useContext, useState, useEffect, ReactNode } from "react"; +import Cookies from "js-cookie"; interface SessionContextType { token: string | null; @@ -21,17 +22,15 @@ export function SessionProvider({ children }: SessionProviderProps) { const [user, setUserState] = useState(null); const [loading, setLoading] = useState(true); - // Save or remove token from localStorage accordingly const setToken = (newToken: string | null) => { if (newToken) { - localStorage.setItem("token", newToken); + Cookies.set("token", newToken, { expires: 7 }); } else { - localStorage.removeItem("token"); + Cookies.remove("token"); } setTokenState(newToken); }; - // Save or remove user from localStorage accordingly const setUser = (newUser: any | null) => { if (newUser) { localStorage.setItem("user", JSON.stringify(newUser)); @@ -41,9 +40,8 @@ export function SessionProvider({ children }: SessionProviderProps) { setUserState(newUser); }; - // On mount, check localStorage for token and user data useEffect(() => { - const storedToken = localStorage.getItem("token"); + const storedToken = Cookies.get("token") || null; const storedUser = localStorage.getItem("user"); if (storedToken) { setTokenState(storedToken); diff --git a/frontend/hooks/useLogout.tsx b/frontend/hooks/useLogout.tsx index 7468295..45a2578 100644 --- a/frontend/hooks/useLogout.tsx +++ b/frontend/hooks/useLogout.tsx @@ -3,6 +3,7 @@ import { useContext } from "react"; import { useRouter } from "next/navigation"; import { SessionContext } from "@/context/SessionContext"; +import Cookies from "js-cookie"; export function useLogout() { const router = useRouter(); @@ -15,9 +16,13 @@ export function useLogout() { const { setToken, setUser } = context; const logout = () => { + Cookies.remove("token"); + Cookies.remove("user"); + setToken(null); setUser(null); + console.log(Cookies.get("token")); router.push("/"); }; diff --git a/frontend/package.json b/frontend/package.json index d2fbb29..4ab6de3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -24,6 +24,7 @@ "axios": "^1.7.9", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "js-cookie": "^3.0.5", "lucide-react": "^0.475.0", "next": "15.1.0", "next-auth": "^4.24.11", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index a9fcf02..56a56e7 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -53,6 +53,9 @@ importers: clsx: specifier: ^2.1.1 version: 2.1.1 + js-cookie: + specifier: ^3.0.5 + version: 3.0.5 lucide-react: specifier: ^0.475.0 version: 0.475.0(react@19.0.0) @@ -1609,6 +1612,10 @@ packages: jose@4.15.9: resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==} + js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -3992,6 +3999,8 @@ snapshots: jose@4.15.9: {} + js-cookie@3.0.5: {} + js-tokens@4.0.0: {} js-yaml@4.1.0: diff --git a/package.json b/package.json new file mode 100644 index 0000000..f4dbddc --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@types/js-cookie": "^3.0.6" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..0157f1e --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,22 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@types/js-cookie': + specifier: ^3.0.6 + version: 3.0.6 + +packages: + + '@types/js-cookie@3.0.6': + resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} + +snapshots: + + '@types/js-cookie@3.0.6': {}