From 1fe25c1944072ce452421a7e9c1547cdbb22a03f Mon Sep 17 00:00:00 2001 From: ducanh Date: Mon, 20 Apr 2026 01:00:52 +0700 Subject: [PATCH] Revert "pig update: decentralization, format date time" This reverts commit 49b99289bb9b5d68d919f3c47baa763100add1bd. --- middleware.ts | 67 ---- .../(tables)/applications-tables/page.tsx | 8 +- .../(tables)/user-table/page.tsx | 369 +++++++++--------- .../profile/applications/page.tsx | 108 +++-- .../(error-pages)/error-403/page.tsx | 53 --- src/components/auth/ProtectedRoute.tsx | 62 --- src/components/auth/SignInForm.tsx | 3 - src/components/header/UserDropdown.tsx | 8 +- src/config/routes.config.ts | 144 ------- src/hooks/useAuth.ts | 66 ---- src/hooks/useRestoreUserData.ts | 19 - src/layout/AppSidebar.tsx | 39 +- src/lib/cookieStorage.ts | 37 -- src/store/StoreProvider.tsx | 14 +- src/store/features/userSlice.ts | 20 +- src/store/store.ts | 6 +- 16 files changed, 242 insertions(+), 781 deletions(-) delete mode 100644 middleware.ts delete mode 100644 src/app/(full-width-pages)/(error-pages)/error-403/page.tsx delete mode 100644 src/components/auth/ProtectedRoute.tsx delete mode 100644 src/config/routes.config.ts delete mode 100644 src/hooks/useAuth.ts delete mode 100644 src/hooks/useRestoreUserData.ts delete mode 100644 src/lib/cookieStorage.ts diff --git a/middleware.ts b/middleware.ts deleted file mode 100644 index 4037863..0000000 --- a/middleware.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { NextRequest, NextResponse } from "next/server" -import { PUBLIC_ROUTES, canAccessRoute, UserRole } from "./src/config/routes.config" - -/** - * Middleware để kiểm tra authentication và authorization - * Chạy TRƯỚC khi render page - */ -export async function middleware(request: NextRequest) { - const { pathname } = request.nextUrl - - // 1. Kiểm tra nếu là public route - if (PUBLIC_ROUTES.includes(pathname)) { - // Nếu user đã login, không cho vào signin/signup - const userDataCookie = request.cookies.get("userDataRedux") - if (userDataCookie && (pathname === "/signin" || pathname === "/signup")) { - return NextResponse.redirect(new URL("/", request.url)) - } - return NextResponse.next() - } - - // 2. Kiểm tra token (cookies) - const token = request.cookies.get("token") || request.cookies.get("access_token") - const userDataCookie = request.cookies.get("userDataRedux") - - // 3. Nếu không có token, redirect về signin - if (!token) { - const signinUrl = new URL("/signin", request.url) - signinUrl.searchParams.set("from", pathname) - return NextResponse.redirect(signinUrl) - } - - // 4. Kiểm tra role-based access - if (userDataCookie) { - try { - const userData = JSON.parse(userDataCookie.value) - const userRoles: UserRole[] = userData.roles?.map((r: any) => r.name) || [] - - // Kiểm tra user có quyền truy cập route này không - if (!canAccessRoute(userRoles, pathname)) { - // Redirect về dashboard hoặc 403 page - return NextResponse.redirect(new URL("/error-403", request.url)) - } - } catch (error) { - console.error("Error parsing user data in middleware:", error) - // Nếu lỗi parse, vẫn cho qua (để tránh infinite redirect) - return NextResponse.next() - } - } - - return NextResponse.next() -} - -/** - * Cấu hình matcher - middleware chỉ chạy cho những routes này - */ -export const config = { - matcher: [ - /* - * Chạy middleware cho tất cả paths ngoại trừ: - * - _next/static (static files) - * - _next/image (image optimization files) - * - favicon.ico (favicon file) - * - public folder - */ - "/((?!_next/static|_next/image|favicon.ico|public).*)", - ], -} diff --git a/src/app/(admin)/(others-pages)/(tables)/applications-tables/page.tsx b/src/app/(admin)/(others-pages)/(tables)/applications-tables/page.tsx index bf12559..38a2d8e 100644 --- a/src/app/(admin)/(others-pages)/(tables)/applications-tables/page.tsx +++ b/src/app/(admin)/(others-pages)/(tables)/applications-tables/page.tsx @@ -5,7 +5,6 @@ import ComponentCard from "@/components/common/ComponentCard"; import PageBreadcrumb from "@/components/common/PageBreadCrumb"; import Pagination from "@/components/tables/Pagination"; import Swal from "sweetalert2"; -import { ProtectedRoute } from "@/components/auth/ProtectedRoute"; import ApplicationTable, { AppSortColumn, @@ -191,9 +190,8 @@ export default function HistorianApplicationPage() { console.log(tableData) // console.log("Pagination info:", pagination); return ( - -
- +
+
} > + {/* Cập nhật Grid để chứa đủ các ô filter */}
@@ -355,6 +354,5 @@ export default function HistorianApplicationPage() { onRefresh={fetchApplications} />
- ); } diff --git a/src/app/(admin)/(others-pages)/(tables)/user-table/page.tsx b/src/app/(admin)/(others-pages)/(tables)/user-table/page.tsx index 5b557a1..28659ee 100644 --- a/src/app/(admin)/(others-pages)/(tables)/user-table/page.tsx +++ b/src/app/(admin)/(others-pages)/(tables)/user-table/page.tsx @@ -15,7 +15,6 @@ import { import { useEffect, useState, useCallback } from "react"; import Pagination from "@/components/tables/Pagination"; import { LIMIT_ITEM_TABLE } from "../../../../../../constant"; -import { ProtectedRoute } from "@/components/auth/ProtectedRoute"; export type SortColumn = "created_at" | "updated_at" | "display_name" | "email"; @@ -33,9 +32,7 @@ const formatDateTimeToISO = ( export default function UserTable() { const [page, setPage] = useState(1); - const [limitInput, setLimitInput] = useState( - LIMIT_ITEM_TABLE.toString(), - ); + const [limitInput, setLimitInput] = useState(LIMIT_ITEM_TABLE.toString()); const [selectedRole, setSelectedRole] = useState(""); const [roles, setRoles] = useState<{ id: string; name: string }[]>([]); @@ -146,6 +143,7 @@ export default function UserTable() { role_ids: selectedRole ? [selectedRole] : undefined, }; + // Thêm format ngày giờ vào payload const createdFrom = formatDateTimeToISO( debouncedParams.fromDate, debouncedParams.fromTime, @@ -187,7 +185,7 @@ export default function UserTable() { }; const pagination = tableData?.pagination; - + // console.log(pagination); const handleOpenDetail = (user: fullDataUser) => { @@ -253,197 +251,192 @@ export default function UserTable() { }; return ( - -
- -
- + +
+ + - - - - - } - > -
-
- - setSearchTerm(e.target.value)} - className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" + -
- -
- - -
- -
- - -
- -
- -
- setFromDate(e.target.value)} - className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" - /> - setFromTime(e.target.value)} - className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" - /> -
-
- -
- -
- setToDate(e.target.value)} - className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" - /> - setToTime(e.target.value)} - className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" - /> -
-
- -
- - setLimitInput(e.target.value)} - className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" - /> -
-
-
- - -
- {loading && ( -
-
-
- )} - - setSelectedRole(role)} + + + } + > +
+
+ + setSearchTerm(e.target.value)} + className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" />
-
-

- Hiển thị trang {pagination?.current_page || 1} /{" "} - {pagination?.total_pages || 1} ({pagination?.total_records || 0}{" "} - kết quả) -

- - {pagination && pagination.total_pages > 1 && ( - setPage(newPage)} - /> - )} +
+ +
- setIsModalOpen(false)} - user={selectedUser} - onChangeRole={handleOpenRoleModal} - onDelete={(u) => { - handleDelete(u); - setIsModalOpen(false); - }} - onRestore={(u) => { - handleRestore(u); - setIsModalOpen(false); - }} - /> +
+ + +
- setIsRoleModalOpen(false)} - user={roleUser} - onSuccess={fetchUsers} + {/* Từ ngày */} +
+ +
+ setFromDate(e.target.value)} + className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" + /> + setFromTime(e.target.value)} + className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" + /> +
+
+ + {/* Đến ngày */} +
+ +
+ setToDate(e.target.value)} + className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" + /> + setToTime(e.target.value)} + className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" + /> +
+
+ + {/* Limit */} +
+ + setLimitInput(e.target.value)} + className="w-full px-3 py-2 border rounded-lg dark:bg-gray-800 dark:border-gray-700 outline-none focus:border-brand-500" + /> +
+
+ + + +
+ {loading && ( +
+
+
+ )} + + setSelectedRole(role)} /> - -
+
+ +
+

+ Hiển thị trang {pagination?.current_page || 1} /{" "} + {pagination?.total_pages || 1} ({pagination?.total_records || 0}{" "} + kết quả) +

+ + {pagination && pagination.total_pages > 1 && ( + setPage(newPage)} + /> + )} +
+ + setIsModalOpen(false)} + user={selectedUser} + onChangeRole={handleOpenRoleModal} + onDelete={(u) => { + handleDelete(u); + setIsModalOpen(false); + }} + onRestore={(u) => { + handleRestore(u); + setIsModalOpen(false); + }} + /> + + setIsRoleModalOpen(false)} + user={roleUser} + onSuccess={fetchUsers} + /> +
- +
); -} +} \ No newline at end of file diff --git a/src/app/(admin)/(others-pages)/profile/applications/page.tsx b/src/app/(admin)/(others-pages)/profile/applications/page.tsx index a9dd032..1b20d8d 100644 --- a/src/app/(admin)/(others-pages)/profile/applications/page.tsx +++ b/src/app/(admin)/(others-pages)/profile/applications/page.tsx @@ -38,18 +38,6 @@ export default function ApplicationDetailPage() { const config = statusConfig[application.status] || statusConfig.PENDING; - const formatDate = (dateString: string | null | undefined) => { - if (!dateString) return "-"; - const date = new Date(dateString); - return date.toLocaleDateString("vi-VN", { - day: "2-digit", - month: "2-digit", - year: "numeric", - hour: "2-digit", - minute: "2-digit", - }); - }; - const isImageFile = (file: any) => { const isImageMime = file.mime_type?.startsWith("image/"); const isImageExt = /\.(jpg|jpeg|png|webp|gif)$/i.test(file.storage_key); @@ -226,57 +214,55 @@ export default function ApplicationDetailPage() {
)} - {application?.reviewer && ( -
- + {application?.reviewer && ( +
+ -
-
-
- {application?.reviewer?.avatar_url ? ( - {application.reviewer.display_name - ) : ( -
- {application?.reviewer?.display_name?.charAt(0) || "R"} -
- )} - -
-

- {application?.reviewer?.display_name} -

-

- {application?.reviewer?.email} -

-
-
- - {formatDate(application?.reviewed_at)} - -
- -
-
- {application?.review_note ? ( -

{application.review_note}

- ) : ( -

- Không có ghi chú bổ sung. -

- )} -
-
+
+
+
+ {application?.reviewer?.avatar_url ? ( + {application.reviewer.display_name + ) : ( +
+ {application?.reviewer?.display_name?.charAt(0) || "R"}
-
- )} + )} + +
+

+ {application?.reviewer?.display_name} +

+

+ {application?.reviewer?.email} +

+
+
+ + {application?.reviewed_at} + +
+ +
+
+ {application?.review_note ? ( +

{application.review_note}

+ ) : ( +

Không có ghi chú bổ sung.

+ )} +
+
+
+ +)}
- -
-

- 403 - ACCESS DENIED -

- - 403 - 403 - -

- You do not have permission to access this resource. Please contact your administrator if you believe this is a mistake. -

- - - Back to Home Page - -
-

- © {new Date().getFullYear()} - Admin Dashboard -

-
- ); -} diff --git a/src/components/auth/ProtectedRoute.tsx b/src/components/auth/ProtectedRoute.tsx deleted file mode 100644 index 1ac545a..0000000 --- a/src/components/auth/ProtectedRoute.tsx +++ /dev/null @@ -1,62 +0,0 @@ -"use client" - -import { ReactNode, useEffect } from "react" -import { useRouter } from "next/navigation" -import { useAuth } from "@/hooks/useAuth" -import { UserRole } from "@/config/routes.config" - -interface ProtectedRouteProps { - children: ReactNode - requiredRoles?: UserRole[] - fallback?: ReactNode -} - -/** - * Component để protect routes dựa trên role - * Sử dụng ở client-side trong layouts hoặc pages - */ -export const ProtectedRoute: React.FC = ({ - children, - requiredRoles = [], - fallback, -}) => { - const router = useRouter() - const { isAuthenticated, userRoles, hasAnyRole } = useAuth() - - useEffect(() => { - if (!isAuthenticated) { - router.replace("/signin") - } - }, [isAuthenticated, router]) - - if (!isAuthenticated) { - return null - } - - if (requiredRoles.length > 0 && !hasAnyRole(requiredRoles)) { - if (fallback) { - return <>{fallback} - } - router.replace("/error-403") - return null - } - - return <>{children} -} - -/** - * Wrapper để render UI dựa trên role - */ -export const RoleGate: React.FC<{ - requiredRoles: UserRole[] - children: ReactNode - fallback?: ReactNode -}> = ({ requiredRoles, children, fallback }) => { - const { hasAnyRole } = useAuth() - - if (!hasAnyRole(requiredRoles)) { - return <>{fallback || null} - } - - return <>{children} -} diff --git a/src/components/auth/SignInForm.tsx b/src/components/auth/SignInForm.tsx index 714ac94..bf11c12 100644 --- a/src/components/auth/SignInForm.tsx +++ b/src/components/auth/SignInForm.tsx @@ -12,7 +12,6 @@ import { API, HOME_URL } from "../../../api"; import { setUserData } from "@/store/features/userSlice"; import { useDispatch } from "react-redux"; import { useRouter } from "next/navigation"; -import { saveUserToCookie } from "@/lib/cookieStorage"; export default function SignInForm() { const router = useRouter(); @@ -74,9 +73,7 @@ export default function SignInForm() { // console.log("Current User Data:", data); if (data?.data) { - // Lưu user data vào Redux và cookies dispatch(setUserData(data.data)); - saveUserToCookie(data.data); router.push("/"); } } else { diff --git a/src/components/header/UserDropdown.tsx b/src/components/header/UserDropdown.tsx index 97abb7f..59832e7 100644 --- a/src/components/header/UserDropdown.tsx +++ b/src/components/header/UserDropdown.tsx @@ -4,11 +4,14 @@ import Link from "next/link"; import React, { useEffect, useState } from "react"; import { Dropdown } from "../ui/dropdown/Dropdown"; import { DropdownItem } from "../ui/dropdown/DropdownItem"; +import { fullDataUser } from "@/interface/admin"; import { UserMetaCardProps } from "@/interface/user"; import { apiGetCurrentUser, apiLogout } from "@/service/auth"; -import { removeUserFromCookie } from "@/lib/cookieStorage"; +import { useRouter } from "next/navigation"; export default function UserDropdown() { + const router = useRouter(); + const [isOpen, setIsOpen] = useState(false); const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); @@ -44,9 +47,6 @@ export default function UserDropdown() { } catch (error) { console.error("Logout failed", error); } finally { - // Xóa user data từ cookies - removeUserFromCookie(); - localStorage.clear(); sessionStorage.clear(); diff --git a/src/config/routes.config.ts b/src/config/routes.config.ts deleted file mode 100644 index 5c36d08..0000000 --- a/src/config/routes.config.ts +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Role-Based Access Control Configuration - * Định nghĩa routes theo role và quyền truy cập - */ - -export type UserRole = "ADMIN" | "MOD" | "HISTORIAN" | "USER" - -export interface RouteConfig { - path: string - allowedRoles: UserRole[] - label?: string -} - -/** - * Public routes - không cần authentication - */ -export const PUBLIC_ROUTES = [ - "/signin", - "/signup", - "/reset-password", - "/error-403", - "/error-404", - "/error-500", -] - - -export const PROTECTED_ROUTES: RouteConfig[] = [ - // Dashboard - { - path: "/", - allowedRoles: ["ADMIN", "MOD", "HISTORIAN", "USER"], - label: "Dashboard", - }, - - // Admin/MOD + Historian routes - { - path: "/user-table", - allowedRoles: ["ADMIN", "MOD"], - label: "User Management", - }, - { - path: "/applications-tables", - allowedRoles: ["ADMIN", "MOD"], - label: "Applications", - }, - - // All authenticated users - { - path: "/profile", - allowedRoles: ["ADMIN", "MOD", "HISTORIAN", "USER"], - label: "User Profile", - }, - { - path: "/calendar", - allowedRoles: ["ADMIN", "MOD", "HISTORIAN", "USER"], - label: "Calendar", - }, - { - path: "/line-chart", - allowedRoles: ["ADMIN", "MOD", "HISTORIAN", "USER"], - label: "Line Chart", - }, - { - path: "/bar-chart", - allowedRoles: ["ADMIN", "MOD", "HISTORIAN", "USER"], - label: "Bar Chart", - }, -] - -/** - * Kiểm tra user role có được phép truy cập route không - */ -export const canAccessRoute = ( - userRoles: UserRole[] | undefined, - routePath: string -): boolean => { - // Nếu không có role, không được truy cập - if (!userRoles || userRoles.length === 0) { - return false - } - - // Public routes không cần check - if (PUBLIC_ROUTES.includes(routePath)) { - return true - } - - // Tìm route config theo độ dài path giảm dần để tránh route '/' khớp với tất cả - const routeConfig = PROTECTED_ROUTES - .slice() - .sort((a, b) => b.path.length - a.path.length) - .find( - (route) => - routePath === route.path || - (route.path !== "/" && routePath.startsWith(route.path + "/")) - ) - - // Nếu route không được định nghĩa, cho phép (mặc định) - if (!routeConfig) { - return true - } - - // Check xem user có role được phép không - return userRoles.some((role) => routeConfig.allowedRoles.includes(role)) -} - -/** - * Lấy danh sách routes cho user role - */ -export const getAvailableRoutes = (userRoles: UserRole[] | undefined): RouteConfig[] => { - if (!userRoles || userRoles.length === 0) { - return [] - } - - return PROTECTED_ROUTES.filter((route) => - userRoles.some((role) => route.allowedRoles.includes(role)) - ) -} - -/** - * Kiểm tra user có role nào không - */ -export const hasRole = (userRoles: UserRole[] | undefined, role: UserRole): boolean => { - return userRoles?.includes(role) ?? false -} - -/** - * Kiểm tra user có ít nhất một trong các role không - */ -export const hasAnyRole = ( - userRoles: UserRole[] | undefined, - roles: UserRole[] -): boolean => { - return userRoles?.some((role) => roles.includes(role)) ?? false -} - -/** - * Kiểm tra user có tất cả các role không - */ -export const hasAllRoles = ( - userRoles: UserRole[] | undefined, - roles: UserRole[] -): boolean => { - return roles.every((role) => userRoles?.includes(role)) -} diff --git a/src/hooks/useAuth.ts b/src/hooks/useAuth.ts deleted file mode 100644 index 57ebee5..0000000 --- a/src/hooks/useAuth.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { useAppSelector } from '@/store/store'; - -import { - canAccessRoute, - hasRole, - hasAnyRole, - hasAllRoles, - getAvailableRoutes, - UserRole, -} from "@/config/routes.config" - -/** - * Hook để kiểm tra authentication và authorization - */ -export const useAuth = () => { - const user = useAppSelector((state) => state.user.data) - const isAuthenticated = useAppSelector((state) => state.user.isAuthenticated) - - const userRoles = user?.roles?.map((r) => r.name) as UserRole[] | undefined - - return { - user, - isAuthenticated, - userRoles, - - /** - * Kiểm tra user có role cụ thể không - */ - hasRole: (role: UserRole) => hasRole(userRoles, role), - - /** - * Kiểm tra user có ít nhất một trong các role không - */ - hasAnyRole: (roles: UserRole[]) => hasAnyRole(userRoles, roles), - - /** - * Kiểm tra user có tất cả các role không - */ - hasAllRoles: (roles: UserRole[]) => hasAllRoles(userRoles, roles), - - /** - * Kiểm tra user có quyền truy cập route không - */ - canAccessRoute: (path: string) => canAccessRoute(userRoles, path), - - /** - * Kiểm tra user là admin - */ - isAdmin: () => hasRole(userRoles, "ADMIN"), - - /** - * Kiểm tra user là moderator - */ - isModerator: () => hasRole(userRoles, "MOD"), - - /** - * Kiểm tra user là historian - */ - isHistorian: () => hasRole(userRoles, "HISTORIAN"), - - /** - * Lấy danh sách routes user có thể truy cập - */ - getAvailableRoutes: () => getAvailableRoutes(userRoles), - } -} diff --git a/src/hooks/useRestoreUserData.ts b/src/hooks/useRestoreUserData.ts deleted file mode 100644 index 61b98fa..0000000 --- a/src/hooks/useRestoreUserData.ts +++ /dev/null @@ -1,19 +0,0 @@ -"use client" - -import { useEffect } from "react" -import { useDispatch } from "react-redux" -import { setUserData, clearUserData } from "@/store/features/userSlice" -import { getUserFromCookie } from "@/lib/cookieStorage" - -export const useRestoreUserData = () => { - const dispatch = useDispatch() - - useEffect(() => { - const userData = getUserFromCookie() - if (userData) { - dispatch(setUserData(userData)) - } else { - dispatch(clearUserData()) - } - }, [dispatch]) -} diff --git a/src/layout/AppSidebar.tsx b/src/layout/AppSidebar.tsx index 51f5fad..d12a378 100644 --- a/src/layout/AppSidebar.tsx +++ b/src/layout/AppSidebar.tsx @@ -18,8 +18,6 @@ import { UserCircleIcon, } from "../icons/index"; import SidebarWidget from "./SidebarWidget"; -import { useAuth } from "@/hooks/useAuth"; -import { canAccessRoute, PUBLIC_ROUTES } from "@/config/routes.config"; type NavItem = { name: string; @@ -103,39 +101,6 @@ const othersItems: NavItem[] = [ const AppSidebar: React.FC = () => { const { isExpanded, isMobileOpen, isHovered, setIsHovered } = useSidebar(); const pathname = usePathname(); - const { userRoles } = useAuth(); - - const hasAccess = (path?: string) => { - if (!path) return true; - if (!userRoles || userRoles.length === 0) { - return PUBLIC_ROUTES.includes(path) || ["/", "/profile", "/calendar"].includes(path); - } - return canAccessRoute(userRoles, path); - }; - - const buildNavItems = (items: NavItem[]) => - items - .map((nav) => { - if (nav.path && !hasAccess(nav.path)) { - return null; - } - - if (nav.subItems) { - const filteredItems = nav.subItems.filter((subItem) => - hasAccess(subItem.path), - ); - if (filteredItems.length === 0) { - return null; - } - return { ...nav, subItems: filteredItems }; - } - - return nav; - }) - .filter((item): item is NavItem => item !== null); - - const filteredMainNavItems = buildNavItems(navItems); - const filteredOthersNavItems = buildNavItems(othersItems); const renderMenuItems = ( navItems: NavItem[], @@ -392,7 +357,7 @@ const AppSidebar: React.FC = () => { )} - {renderMenuItems(filteredMainNavItems, "main")} + {renderMenuItems(navItems, "main")}
@@ -409,7 +374,7 @@ const AppSidebar: React.FC = () => { )} - {renderMenuItems(filteredOthersNavItems, "others")} + {renderMenuItems(othersItems, "others")}
diff --git a/src/lib/cookieStorage.ts b/src/lib/cookieStorage.ts deleted file mode 100644 index 2c9ce3b..0000000 --- a/src/lib/cookieStorage.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { UserData } from "@/interface/user" - -export const saveUserToCookie = (userData: UserData) => { - if (typeof document === "undefined") return - - const userDataJson = JSON.stringify(userData) - document.cookie = `userDataRedux=${encodeURIComponent(userDataJson)}; path=/; max-age=86400` -} - - -export const removeUserFromCookie = () => { - if (typeof document === "undefined") return - - document.cookie = "userDataRedux=; path=/; max-age=0" -} - -export const getUserFromCookie = (): UserData | null => { - if (typeof document === "undefined") return null - - const name = "userDataRedux=" - const decodedCookie = decodeURIComponent(document.cookie) - const cookieArray = decodedCookie.split(";") - - for (let cookie of cookieArray) { - cookie = cookie.trim() - if (cookie.indexOf(name) === 0) { - try { - const userData = JSON.parse(cookie.substring(name.length)) - return userData - } catch (error) { - console.error("Error parsing user cookie:", error) - return null - } - } - } - return null -} diff --git a/src/store/StoreProvider.tsx b/src/store/StoreProvider.tsx index 38495e7..f4adf37 100644 --- a/src/store/StoreProvider.tsx +++ b/src/store/StoreProvider.tsx @@ -3,13 +3,6 @@ import { useRef } from 'react'; import { Provider } from 'react-redux'; import { store } from './store'; -import { useRestoreUserData } from '@/hooks/useRestoreUserData'; - - -function RestoreUserDataComponent() { - useRestoreUserData(); - return null; -} export default function StoreProvider({ children, @@ -17,10 +10,5 @@ export default function StoreProvider({ children: React.ReactNode; }) { const storeRef = useRef(store); - return ( - - - {children} - - ); + return {children}; } \ No newline at end of file diff --git a/src/store/features/userSlice.ts b/src/store/features/userSlice.ts index 41711e8..aed21c5 100644 --- a/src/store/features/userSlice.ts +++ b/src/store/features/userSlice.ts @@ -1,6 +1,5 @@ import { UserData } from '@/interface/user'; import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { getUserFromCookie } from '@/lib/cookieStorage'; const getStoredApplication = () => { if (typeof window !== "undefined") { @@ -10,24 +9,15 @@ const getStoredApplication = () => { return null; }; -const getStoredUserData = (): UserData | null => { - if (typeof window === "undefined") { - return null; - } - return getUserFromCookie(); -}; - interface UserState { data: UserData | null; isAuthenticated: boolean; selectedApplication: any | null; } -const storedUserData = getStoredUserData(); - const initialState: UserState = { - data: storedUserData, - isAuthenticated: Boolean(storedUserData), + data: null, + isAuthenticated: false, selectedApplication: getStoredApplication(), }; @@ -39,10 +29,6 @@ const userSlice = createSlice({ state.data = action.payload; state.isAuthenticated = true; }, - clearUserData: (state) => { - state.data = null; - state.isAuthenticated = false; - }, setSelectedApplication: (state, action: PayloadAction) => { state.selectedApplication = action.payload; if (typeof window !== "undefined") { @@ -58,5 +44,5 @@ const userSlice = createSlice({ }, }); -export const { setUserData, clearUserData, setSelectedApplication, clearSelectedApplication } = userSlice.actions; +export const { setUserData, setSelectedApplication, clearSelectedApplication } = userSlice.actions; export default userSlice.reducer; \ No newline at end of file diff --git a/src/store/store.ts b/src/store/store.ts index 29c2bd1..c3c8be0 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -1,5 +1,4 @@ import { configureStore } from '@reduxjs/toolkit'; -import { useDispatch, useSelector, TypedUseSelectorHook } from 'react-redux'; // Thêm dòng này import userReducer from './features/userSlice'; export const store = configureStore({ @@ -9,7 +8,4 @@ export const store = configureStore({ }); export type RootState = ReturnType; -export type AppDispatch = typeof store.dispatch; - -export const useAppDispatch = () => useDispatch(); -export const useAppSelector: TypedUseSelectorHook = useSelector; \ No newline at end of file +export type AppDispatch = typeof store.dispatch; \ No newline at end of file