feat: use cookie instead of localstorage for token

This commit is contained in:
Sosokker 2025-02-14 00:02:49 +07:00
parent 29c9c4e07a
commit 626ad87d88
11 changed files with 75 additions and 20 deletions

View File

@ -2,7 +2,7 @@ import axios from "axios";
import axiosInstance from "./config";
export interface LoginResponse {
Token: string;
token: string;
message?: string;
}

View File

@ -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<string | null>(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) {

View File

@ -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<string | null>(null);
const [successMessage, setSuccessMessage] = useState<string | null>(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<typeof signUpSchema>) => {
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 && <p className="text-red-600 mt-2 text-sm">{serverError}</p>}
{successMessage && <p className="text-green-600 mt-2 text-sm">{successMessage}</p>}
<Button type="submit" className="mt-5 rounded-full">
Sign up
<Button type="submit" className="mt-5 rounded-full" disabled={isLoading}>
{isLoading ? "Signing up..." : "Sign up"}
</Button>
</form>

View File

@ -36,7 +36,7 @@ export default function RootLayout({
<html lang="en" suppressHydrationWarning>
<head />
<SessionProvider>
<body className={`${openSans.variable} ${robotoMono.variable} font-sans antialiased`}>
<body className={`${openSans.variable} ${robotoMono.variable} antialiased`}>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<div className="relative flex min-h-screen flex-col">
<div className="flex-1 bg-background">{children}</div>

View File

@ -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.
</p>
<Link href="/auth/signin">
<Link href="/setup">
<Button className="bg-black text-white text-md font-bold px-4 py-6 rounded-full hover:bg-gray-600">
Manage your farm
</Button>

View File

@ -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<any | null>(null);
const [loading, setLoading] = useState<boolean>(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);

View File

@ -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("/");
};

View File

@ -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",

View File

@ -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:

5
package.json Normal file
View File

@ -0,0 +1,5 @@
{
"dependencies": {
"@types/js-cookie": "^3.0.6"
}
}

22
pnpm-lock.yaml Normal file
View File

@ -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': {}