add protected route
This commit is contained in:
parent
ee5a3b7b14
commit
a5f54f1794
|
|
@ -5,11 +5,13 @@ import { Spin } from "antd";
|
|||
import { hasAbility } from "./utils/hasAbility";
|
||||
import { renderRoutesRecursively } from "./Components/Routes/RenderRoutesRecursively";
|
||||
import { RenderRouteElement } from "./Components/Routes/RenderRouteElement";
|
||||
import { UserTypeEnum } from "./enums/UserType";
|
||||
import { RoleByType } from "./utils/RoleByType";
|
||||
|
||||
const Page404 = lazy(() => import("./Layout/Ui/NotFoundPage"));
|
||||
const Auth = lazy(() => import("./Pages/Auth/Page"));
|
||||
|
||||
const App = () => {
|
||||
|
||||
return (
|
||||
<Routes>
|
||||
<Route
|
||||
|
|
@ -31,10 +33,14 @@ const App = () => {
|
|||
}
|
||||
/>
|
||||
|
||||
|
||||
{renderRoutesRecursively(menuItems)}
|
||||
|
||||
{CrudRoute.map((route) => {
|
||||
const useAbility = hasAbility(route.abilities, route.abilities_value);
|
||||
if(!RoleByType(route)){
|
||||
return false ;
|
||||
}
|
||||
if (!useAbility) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,17 @@ import { TMenuItem } from "../../types/App";
|
|||
import { hasAbility } from "../../utils/hasAbility";
|
||||
import { Route } from "react-router-dom";
|
||||
import { RenderRouteElement } from "./RenderRouteElement";
|
||||
import { UserTypeEnum } from "../../enums/UserType";
|
||||
import Item from "antd/es/list/Item";
|
||||
import { RoleByType } from "../../utils/RoleByType";
|
||||
|
||||
export const renderRoutesRecursively = (routes: TMenuItem[]) =>
|
||||
routes.map((route: TMenuItem) => {
|
||||
const useAbility = hasAbility(route.abilities, route.abilities_value);
|
||||
if(!RoleByType(route)){
|
||||
return false ;
|
||||
}
|
||||
|
||||
if (!useAbility) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import { useTranslation } from "react-i18next";
|
|||
import { getLocalStorage } from "../../utils/LocalStorage";
|
||||
import { BRANCH_OBJECT_KEY } from "../../config/AppKey";
|
||||
import { MenuItem } from "../../Components/Layout/SideBar/MenuItem";
|
||||
import { UserTypeEnum } from "../../enums/UserType";
|
||||
import { RoleByType } from "../../utils/RoleByType";
|
||||
|
||||
const SideBar = () => {
|
||||
const location = useLocation();
|
||||
|
|
@ -17,7 +19,6 @@ const SideBar = () => {
|
|||
const { logout } = useAuthState();
|
||||
const [t] = useTranslation();
|
||||
const branch_name = getLocalStorage(BRANCH_OBJECT_KEY)?.name;
|
||||
|
||||
return (
|
||||
<div className="side_bar">
|
||||
<h1>
|
||||
|
|
@ -31,6 +32,11 @@ const SideBar = () => {
|
|||
if (!useAbility) {
|
||||
return <React.Fragment key={index}></React.Fragment>;
|
||||
}
|
||||
if(!RoleByType(item)){
|
||||
|
||||
return <React.Fragment key={index}></React.Fragment> ;
|
||||
}
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
key={index}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { Formik } from "formik";
|
||||
import useAuthState from "../../zustand/AuthState";
|
||||
import useNavigateOnSuccess from "../../Hooks/useNavigateOnSuccess";
|
||||
|
|
@ -8,6 +8,9 @@ import { initialValues } from "./formutils";
|
|||
import { FormValues } from "../../types/Auth";
|
||||
import { toast } from "react-toastify";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { getLocalStorage } from "../../utils/LocalStorage";
|
||||
import { USER_KEY } from "../../config/AppKey";
|
||||
|
||||
const LoginForm = () => {
|
||||
const { mutate, isLoading, isSuccess, data } = useLoginAdmin();
|
||||
|
|
@ -16,11 +19,27 @@ const LoginForm = () => {
|
|||
mutate(values);
|
||||
};
|
||||
|
||||
const { login } = useAuthState();
|
||||
const { login,isAuthenticated} = useAuthState();
|
||||
const LoginData = {
|
||||
...data,
|
||||
|
||||
} as any;
|
||||
useNavigateOnSuccess(isSuccess, "/", () => login(LoginData?.data as any));
|
||||
const navigate = useNavigate()
|
||||
const LocalType = getLocalStorage(USER_KEY)?.type ?? false ;
|
||||
useEffect(() => {
|
||||
|
||||
if(isSuccess){
|
||||
login(LoginData?.data as any)
|
||||
|
||||
}
|
||||
}, [isSuccess])
|
||||
|
||||
useEffect(() => {
|
||||
if(LocalType ){
|
||||
window.location.href = ("/")
|
||||
}
|
||||
}, [LocalType])
|
||||
|
||||
|
||||
return (
|
||||
<div className="LoginForm">
|
||||
|
|
|
|||
|
|
@ -18,7 +18,10 @@ const Form = ({ isEdit = false }: { isEdit?: boolean }) => {
|
|||
const canChangeGradePage = !!Grade?.links?.next;
|
||||
const GradePage = Grade?.meta?.currentPage;
|
||||
|
||||
|
||||
const sex = [
|
||||
{name:"male" , id :"male"},
|
||||
{name:"female" , id :"female"}
|
||||
]
|
||||
return (
|
||||
<Row className="w-100">
|
||||
<Col>
|
||||
|
|
@ -45,6 +48,7 @@ const Form = ({ isEdit = false }: { isEdit?: boolean }) => {
|
|||
page={GradePage}
|
||||
|
||||
/>
|
||||
<ValidationField type="Select" name="sex" option={sex} />
|
||||
|
||||
</Col>
|
||||
</Row>
|
||||
|
|
|
|||
|
|
@ -5,17 +5,23 @@ export const getInitialValues = (
|
|||
objectToEdit: Partial<Student>,
|
||||
): StudentInitialValues => {
|
||||
return {
|
||||
id: objectToEdit?.id,
|
||||
id: objectToEdit?.user_id,
|
||||
first_name: objectToEdit?.first_name ?? "",
|
||||
last_name: objectToEdit?.last_name ?? "",
|
||||
username: objectToEdit?.user?.username ?? null ,
|
||||
password: null ,
|
||||
// address: objectToEdit?.address ?? "",
|
||||
// birthday: objectToEdit?.birthday ?? "",
|
||||
// city: objectToEdit?.city ?? "",
|
||||
grade_id: objectToEdit?.grade_id ,
|
||||
// image: objectToEdit?.image ?? "",
|
||||
sex: objectToEdit?.sex ,
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
export const getValidationSchema = () => {
|
||||
// validate input
|
||||
return Yup.object().shape({
|
||||
name: Yup.string().required("validation.required"),
|
||||
first_name: Yup.string().required("validation.required"),
|
||||
last_name: Yup.string().required("validation.required"),
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import {
|
|||
canShowStudent,
|
||||
} from "../../utils/hasAbilityFn";
|
||||
import ActionButtons from "../../Components/Table/ActionButtons";
|
||||
import ColumnsImage from "../../Components/Columns/ColumnsImage";
|
||||
|
||||
export const useColumns = () => {
|
||||
const { handel_open_model } = useModalHandler();
|
||||
|
|
@ -22,7 +21,7 @@ export const useColumns = () => {
|
|||
const navigate = useNavigate();
|
||||
|
||||
const handelShow = (record: Student) => {
|
||||
navigate(`${record?.id}`);
|
||||
navigate(`${record?.user_id}`);
|
||||
};
|
||||
|
||||
const handelDelete = (data: Student) => {
|
||||
|
|
@ -42,15 +41,31 @@ export const useColumns = () => {
|
|||
dataIndex: "id",
|
||||
key: "id",
|
||||
align: "center",
|
||||
render: (_text, record) => record?.id,
|
||||
render: (_text, record) => record?.user_id,
|
||||
},
|
||||
{
|
||||
title: `${t("columns.name")}`,
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
title: `${t("columns.first_name")}`,
|
||||
dataIndex: "first_name",
|
||||
key: "first_name",
|
||||
align: "center",
|
||||
render: (_text, record) => record?.first_name,
|
||||
},
|
||||
{
|
||||
title: `${t("columns.last_name")}`,
|
||||
dataIndex: "last_name",
|
||||
key: "last_name",
|
||||
align: "center",
|
||||
render: (_text, record) => record?.last_name,
|
||||
},
|
||||
{
|
||||
title: `${t("columns.sex")}`,
|
||||
dataIndex: "sex",
|
||||
key: "sex",
|
||||
align: "center",
|
||||
render: (_text, record) => record?.sex,
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
title: canAddStudent ? (
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import { hasAbility } from "./utils/hasAbility";
|
|||
import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "./enums/abilities";
|
||||
import { ParamsEnum } from "./enums/params";
|
||||
import { BsPeople } from "react-icons/bs";
|
||||
import { UserTypeEnum } from "./enums/UserType";
|
||||
|
||||
export const menuItems: TMenuItem[] = [
|
||||
{
|
||||
|
|
@ -42,6 +43,7 @@ export const menuItems: TMenuItem[] = [
|
|||
abilities: ABILITIES_ENUM?.PASS,
|
||||
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
||||
prevPath: 0,
|
||||
type:UserTypeEnum?.PASS
|
||||
|
||||
},
|
||||
{
|
||||
|
|
@ -105,16 +107,17 @@ export const menuItems: TMenuItem[] = [
|
|||
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
||||
prevPath: 0,
|
||||
},
|
||||
// {
|
||||
// header: "page_header.studentPackage",
|
||||
// element: <StudentPackage />,
|
||||
// icon: <BsPeople />,
|
||||
// text: "sidebar.studentPackage",
|
||||
// path: `/${ABILITIES_ENUM?.STUDENT_PACKAGE}`,
|
||||
// abilities: ABILITIES_ENUM?.STUDENT_PACKAGE,
|
||||
// abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
||||
// prevPath: 0,
|
||||
// },
|
||||
{
|
||||
header: "page_header.studentPackage",
|
||||
element: <StudentPackage />,
|
||||
icon: <BsPeople />,
|
||||
text: "sidebar.studentPackage",
|
||||
path: `/${ABILITIES_ENUM?.STUDENT_PACKAGE}`,
|
||||
abilities: ABILITIES_ENUM?.STUDENT_PACKAGE,
|
||||
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
||||
prevPath: 0,
|
||||
type:UserTypeEnum.RE_SELLER
|
||||
},
|
||||
];
|
||||
|
||||
export const CrudRoute: TCrudRoute[] = [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
export enum UserTypeEnum {
|
||||
ADMIN = "ADMIN",
|
||||
RE_SELLER = "RE_SELLER",
|
||||
ADMIN = "admin",
|
||||
RE_SELLER = "reseller",
|
||||
PASS="pass"
|
||||
}
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ export type TCrudRoute = {
|
|||
element: ReactElement | LazyExoticComponent<any>;
|
||||
abilities: ABILITIES_ENUM;
|
||||
abilities_value: ABILITIES_VALUES_ENUM;
|
||||
type?:ABILITIES_ENUM
|
||||
type?:UserTypeEnum
|
||||
prevPath: number;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,51 +1,34 @@
|
|||
import { Nullable } from "./App";
|
||||
import { DateType, Nullable } from "./App";
|
||||
|
||||
// Define the Teacher interface
|
||||
|
||||
|
||||
interface StudentUser {
|
||||
id: number;
|
||||
username: string;
|
||||
phone_number: string | null;
|
||||
type: 'Student' | 'other'; // Specify other types if needed
|
||||
}
|
||||
|
||||
interface StudentLocation {
|
||||
lat: string;
|
||||
lng: string;
|
||||
}
|
||||
|
||||
interface ContactInfo {
|
||||
contact_number1: string;
|
||||
contact_number2: string;
|
||||
card_number: string | null;
|
||||
}
|
||||
|
||||
|
||||
export interface Student {
|
||||
id: number;
|
||||
user: StudentUser;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
location: StudentLocation;
|
||||
contact_info: ContactInfo;
|
||||
contact_number1 : string | number
|
||||
contact_number2 : string | number
|
||||
first_name: string; // The first name of the user
|
||||
last_name: string; // The last name of the user
|
||||
city: string | null; // The city of the user, can be null
|
||||
sex: string; // The sex of the user, using a union type for possible values
|
||||
image: string | null; // The URL of the user's image, can be null
|
||||
address: string | null; // The address of the user, can be null
|
||||
card: string | null; // The card information, can be null
|
||||
birthday: DateType; // The birthday of the user, can be null
|
||||
grade_id: number | string; // The ID of the user's grade
|
||||
user_id: number; // The unique ID of the user
|
||||
}
|
||||
|
||||
export interface InitialValues {
|
||||
id: number;
|
||||
user: StudentUser;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
location: StudentLocation;
|
||||
lat: string | Number;
|
||||
lng: string | Number;
|
||||
contact_info: ContactInfo;
|
||||
contact_number1 : string | number
|
||||
contact_number2 : string | number
|
||||
username : string;
|
||||
password:any
|
||||
first_name: string; // The first name of the user
|
||||
last_name: string; // The last name of the user
|
||||
city: string | null; // The city of the user, can be null
|
||||
sex: string; // The sex of the user, using a union type for possible values
|
||||
image: string | null; // The URL of the user's image, can be null
|
||||
address: string | null; // The address of the user, can be null
|
||||
card: string | null; // The card information, can be null
|
||||
birthday: DateType; // The birthday of the user, can be null
|
||||
grade_id: number | string; // The ID of the user's grade
|
||||
user_id: number; // The unique ID of the user
|
||||
}
|
||||
|
||||
export type StudentInitialValues = Partial<Nullable<InitialValues>>;
|
||||
|
|
|
|||
28
src/utils/RoleByType.ts
Normal file
28
src/utils/RoleByType.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { USER_KEY } from "../config/AppKey";
|
||||
import { UserTypeEnum } from "../enums/UserType";
|
||||
import { getLocalStorage } from "./LocalStorage";
|
||||
|
||||
export const RoleByType = (item: { type?: string }):boolean=>{
|
||||
const type = item?.type ?? UserTypeEnum.ADMIN;
|
||||
const LocalType = getLocalStorage(USER_KEY)?.type ?? undefined ;
|
||||
const isAdmin = LocalType === UserTypeEnum.ADMIN ;
|
||||
const isReSeller = LocalType === UserTypeEnum.RE_SELLER;
|
||||
const isAdminRoute = type === UserTypeEnum.ADMIN ;
|
||||
const isReSellerRoute = type === UserTypeEnum.RE_SELLER;
|
||||
console.log(LocalType);
|
||||
|
||||
if(!LocalType){
|
||||
return false
|
||||
}
|
||||
if(type === UserTypeEnum.PASS) { return true } ;
|
||||
|
||||
if(isAdmin && isReSellerRoute ){
|
||||
return false ;
|
||||
}
|
||||
|
||||
if(isReSeller && !isReSellerRoute ){
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,12 +1,11 @@
|
|||
import { create } from "zustand";
|
||||
import { ABILITIES_KEY, TOKEN_KEY, USER_KEY } from "../config/AppKey";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import { RoleByType } from "../utils/RoleByType";
|
||||
import { getLocalStorage } from "../utils/LocalStorage";
|
||||
interface AuthStore {
|
||||
token: string | null | undefined;
|
||||
abilities: any;
|
||||
isAuthenticated: boolean;
|
||||
|
||||
login: (Data: any) => Promise<void>;
|
||||
logout: () => Promise<void>;
|
||||
}
|
||||
|
|
@ -14,9 +13,11 @@ interface AuthStore {
|
|||
const useAuthState = create<AuthStore>((set) => {
|
||||
const storedToken = localStorage.getItem(TOKEN_KEY);
|
||||
const storedAbilities = localStorage.getItem(ABILITIES_KEY);
|
||||
const storedType = getLocalStorage(USER_KEY) ;
|
||||
console.log(RoleByType(storedType));
|
||||
|
||||
return {
|
||||
isAuthenticated: true,
|
||||
isAuthenticated: !!storedToken,
|
||||
token: storedToken,
|
||||
abilities: storedAbilities,
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user