feat: hide statistics, work time, expenses and finances from regular users

This commit is contained in:
2024-12-09 20:17:32 +04:00
parent 2ee0ef3a52
commit d5598a10b8
4 changed files with 66 additions and 24 deletions

View File

@@ -15,10 +15,11 @@ import {
IconSun, IconSun,
} from "@tabler/icons-react"; } from "@tabler/icons-react";
import classes from "./Navbar.module.css"; import classes from "./Navbar.module.css";
import { useAppDispatch } from "../../redux/store.ts"; import { RootState, useAppDispatch } from "../../redux/store.ts";
import { logout } from "../../features/authSlice.ts"; import { logout } from "../../features/authSlice.ts";
import { useNavigate, useRouterState } from "@tanstack/react-router"; import { useNavigate, useRouterState } from "@tanstack/react-router";
import { setHideNavbar } from "../../features/uiSlice.ts"; import { setHideNavbar } from "../../features/uiSlice.ts";
import { useSelector } from "react-redux";
interface NavbarLinkProps { interface NavbarLinkProps {
icon: typeof IconHome2; icon: typeof IconHome2;
@@ -93,17 +94,21 @@ const mockdata = [
label: "Маркетплейсы", label: "Маркетплейсы",
href: "/marketplaces", href: "/marketplaces",
}, },
];
const adminMockdata = [
{ {
icon: IconChartDots, icon: IconChartDots,
label: "Статистика", label: "Статистика",
href: "/statistics", href: "/statistics",
} },
]; ];
export function Navbar() { export function Navbar() {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const navigate = useNavigate(); const navigate = useNavigate();
const router = useRouterState(); const router = useRouterState();
const role = useSelector((state: RootState) => state.auth.role);
const { colorScheme, toggleColorScheme } = useMantineColorScheme({ const { colorScheme, toggleColorScheme } = useMantineColorScheme({
keepTransitions: true, keepTransitions: true,
}); });
@@ -114,9 +119,17 @@ export function Navbar() {
const onNavlinkClick = (props: NavbarLinkProps) => { const onNavlinkClick = (props: NavbarLinkProps) => {
navigate({ to: props.href }); navigate({ to: props.href });
}; };
const links = mockdata.map((link, index) => (
<NavbarLink
const getLinksData = () => {
let data = mockdata;
if (role === "admin") {
data = data.concat(adminMockdata);
}
return data;
}
const links = getLinksData().map((link, index) => (
<NavbarLink
{...link} {...link}
index={index} index={index}
key={link.label} key={link.label}

View File

@@ -1,10 +1,11 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { jwtDecode, JwtPayload } from "jwt-decode"; import { jwtDecode, JwtPayload as JwtPayloadBase } from "jwt-decode";
interface AuthState { interface AuthState {
isAuthorized: boolean; isAuthorized: boolean;
accessToken: string; accessToken: string;
isGuest: boolean; isGuest: boolean;
role: string;
} }
const initialState = (): AuthState => { const initialState = (): AuthState => {
@@ -16,20 +17,26 @@ const initialState = (): AuthState => {
accessToken: "", accessToken: "",
isAuthorized: false, isAuthorized: false,
isGuest: false, isGuest: false,
role: "user",
}; };
}; };
interface JwtPayload extends JwtPayloadBase {
role: string;
}
const authSlice = createSlice({ const authSlice = createSlice({
name: "auth", name: "auth",
initialState, initialState,
reducers: { reducers: {
login: (state, action: PayloadAction<{ accessToken: string }>) => { login: (state, action: PayloadAction<{ accessToken: string }>) => {
try { try {
const { sub } = jwtDecode<JwtPayload>( const { sub, role } = jwtDecode<JwtPayload>(
action.payload.accessToken action.payload.accessToken,
); );
state.accessToken = action.payload.accessToken; state.accessToken = action.payload.accessToken;
state.isAuthorized = true; state.isAuthorized = true;
state.role = role;
if (sub === "guest") state.isGuest = true; if (sub === "guest") state.isGuest = true;
} catch (_) { } catch (_) {
const url = window.location.href; const url = window.location.href;

View File

@@ -3,8 +3,10 @@ import { Tabs } from "@mantine/core";
import PageBlock from "../../components/PageBlock/PageBlock.tsx"; import PageBlock from "../../components/PageBlock/PageBlock.tsx";
import { import {
IconBriefcase, IconBriefcase,
IconCalendarUser, IconCoins, IconCalendarUser,
IconCurrencyDollar, IconQrcode, IconCoins,
IconCurrencyDollar,
IconQrcode,
IconUser, IconUser,
} from "@tabler/icons-react"; } from "@tabler/icons-react";
import RolesAndPositionsTab from "./tabs/RolesAndPositions/RolesAndPositionsTab.tsx"; import RolesAndPositionsTab from "./tabs/RolesAndPositions/RolesAndPositionsTab.tsx";
@@ -14,8 +16,13 @@ import FinancesTab from "./tabs/Finances/FinancesTab.tsx";
import WorkTimeTable from "./tabs/WorkTimeTable/ui/WorkTimeTable.tsx"; import WorkTimeTable from "./tabs/WorkTimeTable/ui/WorkTimeTable.tsx";
import { WorkShiftsTab } from "./tabs/WorkShifts/WorkShiftsTab.tsx"; import { WorkShiftsTab } from "./tabs/WorkShifts/WorkShiftsTab.tsx";
import { ExpensesTab } from "./tabs/Expenses/ExpensesTab.tsx"; import { ExpensesTab } from "./tabs/Expenses/ExpensesTab.tsx";
import { useSelector } from "react-redux";
import { RootState } from "../../redux/store.ts";
const AdminPage = () => { const AdminPage = () => {
const userRole = useSelector((state: RootState) => state.auth.role);
const isAdmin = userRole === "admin";
return ( return (
<div className={styles["container"]}> <div className={styles["container"]}>
<PageBlock fullHeight> <PageBlock fullHeight>
@@ -29,31 +36,37 @@ const AdminPage = () => {
leftSection={<IconUser />}> leftSection={<IconUser />}>
Пользователи Пользователи
</Tabs.Tab> </Tabs.Tab>
<Tabs.Tab {isAdmin && (
value={"finances"} <Tabs.Tab
leftSection={<IconCurrencyDollar />}> value={"finances"}
Финансы leftSection={<IconCurrencyDollar />}>
</Tabs.Tab> Финансы
</Tabs.Tab>
)}
<Tabs.Tab <Tabs.Tab
value={"rolesAndPositions"} value={"rolesAndPositions"}
leftSection={<IconBriefcase />}> leftSection={<IconBriefcase />}>
Должности Должности
</Tabs.Tab> </Tabs.Tab>
<Tabs.Tab {isAdmin && (
value={"workTimeTable"} <Tabs.Tab
leftSection={<IconCalendarUser />}> value={"workTimeTable"}
Рабочее время leftSection={<IconCalendarUser />}>
</Tabs.Tab> Рабочее время
</Tabs.Tab>
)}
<Tabs.Tab <Tabs.Tab
value={"workShifts"} value={"workShifts"}
leftSection={<IconQrcode />}> leftSection={<IconQrcode />}>
Смены Смены
</Tabs.Tab> </Tabs.Tab>
<Tabs.Tab {isAdmin && (
value={"expenses"} <Tabs.Tab
leftSection={<IconCoins />}> value={"expenses"}
Расходы leftSection={<IconCoins />}>
</Tabs.Tab> Расходы
</Tabs.Tab>
)}
</Tabs.List> </Tabs.List>
<Tabs.Panel value={"users"}> <Tabs.Panel value={"users"}>
<motion.div <motion.div

View File

@@ -1,8 +1,17 @@
import { StatisticsTab } from "../components/StatisticsTabSegmentedControl/StatisticsTabSegmentedControl.tsx"; import { StatisticsTab } from "../components/StatisticsTabSegmentedControl/StatisticsTabSegmentedControl.tsx";
import styles from "./StatisticsPage.module.css"; import styles from "./StatisticsPage.module.css";
import { ProfitTab } from "../tabs/ProfitTab/ProfitTab.tsx"; import { ProfitTab } from "../tabs/ProfitTab/ProfitTab.tsx";
import { useSelector } from "react-redux";
import { RootState } from "../../../redux/store.ts";
import { Navigate } from "@tanstack/react-router";
export const StatisticsPage = () => { export const StatisticsPage = () => {
const userRole = useSelector((state: RootState) => state.auth.role);
if (userRole !== "admin") {
return <Navigate to={"/leads"} />;
}
const serviceType = StatisticsTab.PROFIT; const serviceType = StatisticsTab.PROFIT;
const getBody = () => { const getBody = () => {