Merge pull request 'truong-sprint-1' (#8) from truong-sprint-1 into master

Reviewed-on: #8
This commit is contained in:
joseph 2024-08-09 10:30:24 +10:00
commit 571ebb6a09
8 changed files with 392 additions and 283 deletions

View File

@ -49,6 +49,21 @@ class TicketController extends Controller
]
);
$this->searchRequest(
builder: $tickets,
value: $request->get('search'),
fields: [
'users.name',
"start_date",
"startPeriod.c_name",
"end_date",
"endPeriod.c_name",
"typeReason.c_name",
'status',
"reason",
]
);
$responseData = array_merge(
$tickets
->join('users', 'tickets.user_id', '=', 'users.id')
@ -111,8 +126,58 @@ class TicketController extends Controller
]
);
$this->searchRequest(
builder: $tickets,
value: $request->get('search'),
fields: [
'users.name',
"start_date",
"startPeriod.c_name",
"end_date",
"endPeriod.c_name",
"typeReason.c_name",
'status',
"reason",
"admin_note"
]
);
if ($request->typeReason != '') {
$tickets = $tickets->where('tickets.type', '=', $request->typeReason);
}
if ($request->statusFilter != '') {
$tickets = $tickets->where('tickets.status', '=', $request->statusFilter);
}
$responseData = array_merge(
$tickets->orderBy('created_at', 'desc')->paginate($request->get('per_page'))->toArray(),
$tickets
->join('users', 'tickets.user_id', '=', 'users.id')
->leftJoin("categories as startPeriod", function ($join) {
$join->on('start_period', '=', 'startPeriod.c_code');
$join->on('startPeriod.c_type', DB::raw("CONCAT('TIME_TYPE')"));
})
->leftJoin("categories as endPeriod", function ($join) {
$join->on('end_period', '=', 'endPeriod.c_code');
$join->on('endPeriod.c_type', DB::raw("CONCAT('TIME_TYPE')"));
})
->leftJoin("categories as typeReason", function ($join) {
$join->on('type', '=', 'typeReason.c_code');
$join->on('typeReason.c_type', DB::raw("CONCAT('REASON')"));
})
->leftJoin("categories as statusTickets", function ($join) {
$join->on('status', '=', 'statusTickets.c_code');
$join->on('statusTickets.c_type', DB::raw("CONCAT('STATUS_TICKETS')"));
})
->select(
'users.name as user_name',
'users.email',
'tickets.*',
'startPeriod.c_name as startPeriodName',
'endPeriod.c_name as endPeriodName',
'typeReason.c_name as typeReasonName',
'statusTickets.c_name as statusTicketsName',
)
->orderBy('tickets.created_at', 'desc')->paginate($request->get('per_page'))->toArray(),
['status' => true]
);
@ -251,6 +316,7 @@ class TicketController extends Controller
$ticket['updated_by'] = $admin->name;
$ticket['admin_note'] = $admin_note;
$ticket['status'] = 'REFUSED';
$ticket->save();
return response()->json(['message' => "refused", 'status' => true]);
}

View File

@ -78,6 +78,8 @@ export const getLeaveManagement = API_URL + 'v1/admin/leave-management'
export const updateNoteLeave = API_URL + 'v1/admin/leave-management/saveNoteLeave'
//Tickets
export const getTickets = API_URL + 'v1/admin/ticket/all'
export const getTicketsOfUser = API_URL + 'v1/admin/ticket/getByUserId'
export const deleteTicket = API_URL + 'v1/admin/ticket/delete'
export const addTicket = API_URL + 'v1/admin/ticket/create'
export const handleTicket = API_URL + 'v1/admin/ticket/handle-ticket'

View File

@ -47,7 +47,11 @@ const data = [
icon: IconCalendarClock,
},
{ link: '/tickets', label: 'Tickets', icon: IconTicket },
{ link: '/tickets-management', label: 'Tickets Management', icon: IconDevices },
{
link: '/tickets-management',
label: 'Tickets Management',
icon: IconDevices,
},
// { link: '/jira', label: 'Jira', icon: IconSubtask },
// { link: '/custom-theme', label: 'Custom Theme', icon: IconBrush },
// { link: '/general-setting', label: 'General Setting', icon: IconSettings },
@ -102,7 +106,10 @@ const Navbar = ({
getInitialValueInEffect: true,
})
const links = data.map((item) => (
const links = data.map((item) => {
if (user?.user?.permission !== 'admin' && item.link === '/tickets-management')
return null
return (
<a
className={classes.link}
data-active={item.label === active || undefined}
@ -124,7 +131,8 @@ const Navbar = ({
{item.label}
</span>
</a>
))
)
})
const handleLogout = useCallback(() => {
dispatch(logout(navigate))

View File

@ -1,5 +1,9 @@
import { useAppSelector } from '@/rtk/hooks'
import { checkExpToken, removeTokens } from '@/rtk/localStorage'
import {
checkExpToken,
checkPermissionAdmin,
removeTokens,
} from '@/rtk/localStorage'
import { selectAuthentication } from '@/rtk/slices/auth'
import type { ReactNode } from 'react'
import { Navigate } from 'react-router-dom'
@ -7,16 +11,31 @@ import { Navigate } from 'react-router-dom'
interface ProtectedRouteProps {
children: ReactNode
mode: string
permission: string
}
const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ children, mode }) => {
const ProtectedRoute: React.FC<ProtectedRouteProps> = ({
children,
mode,
permission = 'staff',
}) => {
const auth = useAppSelector(selectAuthentication)
switch (mode) {
case 'login':
return checkExpToken() ? <Navigate to="/" /> : <>{children}</>
case 'route':
return !auth.user ? <Navigate to="/login" /> : <>{children}</>
return !auth.user ? (
<Navigate to="/login" />
) : permission == 'admin' ? (
checkPermissionAdmin() ? (
<>{children}</>
) : (
<Navigate to="/" />
)
) : (
<>{children}</>
)
case 'home':
if (checkExpToken()) {

View File

@ -64,6 +64,12 @@ interface DataTimeType {
c_name: string
}
interface FilterInfo {
key: string
name: string
type: string
}
const Tickets = () => {
const [listTickets, setListTiskets] = useState<TListTickets>({
data: [],
@ -127,7 +133,7 @@ const Tickets = () => {
},
{
name: 'start_date',
size: '11%',
size: '8%',
header: 'From Date',
render: (row: any) => {
return moment(row.start_date).format('DD/MM/YYYY')
@ -140,7 +146,7 @@ const Tickets = () => {
},
{
name: 'end_date',
size: '10%',
size: '8%',
header: 'End Date',
render: (row: any) => {
return moment(row.end_date).format('DD/MM/YYYY')
@ -153,7 +159,7 @@ const Tickets = () => {
},
{
name: 'reason',
size: '20%',
size: '15%',
header: 'Notes',
render: (row: any) => {
return (
@ -178,7 +184,7 @@ const Tickets = () => {
},
{
name: 'status',
size: '8%',
size: '5%',
header: 'Status',
render: (row: any) => {
switch (row.status) {
@ -193,6 +199,31 @@ const Tickets = () => {
}
},
},
{
name: 'admin_note',
size: '15%',
header: 'Admin Notes',
render: (row: any) => {
return (
<HoverCard width={280} shadow="md">
<HoverCard.Target>
<Text fz={'sm'}>
{row.admin_note !== null &&
row.admin_note !== '' &&
row.admin_note.length > 25
? row.admin_note.slice(0, 25) + '...'
: row.admin_note}
</Text>
</HoverCard.Target>
<HoverCard.Dropdown>
<Textarea size="sm" autosize>
{row.admin_note}
</Textarea>
</HoverCard.Dropdown>
</HoverCard>
)
},
},
{
name: '#',
size: '5%',
@ -215,23 +246,7 @@ const Tickets = () => {
},
]
const filterInfo = [
{
key: 'reason',
name: 'Notes',
type: 'text',
},
{
key: 'start_date',
name: 'From Date',
type: 'date',
},
{
key: 'end_date',
name: 'End Date',
type: 'date',
},
]
const filterInfo: FilterInfo[] = []
const getAllTickets = async () => {
try {
@ -330,7 +345,7 @@ const Tickets = () => {
filterInfo={filterInfo}
data={listTickets}
columns={columns}
// searchInput
searchInput
size=""
/>
)}

View File

@ -1,38 +1,28 @@
import {
addTicket,
deleteTicket,
getListMaster,
getTicketsOfUser
} from '@/api/Admin'
import { getListMaster, getTickets, handleTicket } from '@/api/Admin'
import { DataTablePagination } from '@/components/DataTable/DataTable'
import { Xdelete, create } from '@/rtk/helpers/CRUD'
import { create } from '@/rtk/helpers/CRUD'
import { get } from '@/rtk/helpers/apiService'
import {
Badge,
Box,
Button,
Dialog,
Group,
HoverCard,
Modal,
Select,
Text,
Textarea,
} from '@mantine/core'
import { DateInput } from '@mantine/dates'
import { useForm } from '@mantine/form'
import { notifications } from '@mantine/notifications'
import { IconTrash } from '@tabler/icons-react'
import { IconCheckbox, IconSquareXFilled } from '@tabler/icons-react'
import moment from 'moment'
import { useEffect, useState } from 'react'
import classes from './TicketsManagement.module.css'
type TTickets = {
id: number
start_period: string
end_period: string
type: string
start_date: Date
end_date: Date
reason: string
ticket_id: number
admin_note: string
action: string
}
type TListTickets = {
@ -50,13 +40,13 @@ interface User {
updated_at: string | null
}
interface DataReason {
id: number
c_code: string
c_name: string
interface FilterInfo {
key: string
name: string
type: string
}
interface DataTimeType {
interface DataReason {
id: number
c_code: string
c_name: string
@ -68,10 +58,11 @@ const TicketsManagement = () => {
})
const [action, setAction] = useState('')
const [item, setItem] = useState({ id: 0 })
const [activeBtn, setActiveBtn] = useState(false)
const [disableBtn, setDisableBtn] = useState(false)
const [dataTimeType, setDataTimeType] = useState<DataTimeType[]>([])
const [filter, setFilter] = useState({
typeReason: '',
statusFilter: '',
})
const [dataReason, setDataReason] = useState<DataReason[]>([])
const getListMasterByType = async (type: string) => {
@ -95,11 +86,6 @@ const TicketsManagement = () => {
useEffect(() => {
const fetchData = async () => {
const resultTimeType = await getListMasterByType('TIME_TYPE')
setDataTimeType(
resultTimeType.filter((item: DataTimeType) => item.c_code !== 'ALL'),
)
const resultReason = await getListMasterByType('REASON')
setDataReason(resultReason)
}
@ -125,7 +111,7 @@ const TicketsManagement = () => {
},
{
name: 'start_date',
size: '11%',
size: '8%',
header: 'From Date',
render: (row: any) => {
return moment(row.start_date).format('DD/MM/YYYY')
@ -138,7 +124,7 @@ const TicketsManagement = () => {
},
{
name: 'end_date',
size: '10%',
size: '8%',
header: 'End Date',
render: (row: any) => {
return moment(row.end_date).format('DD/MM/YYYY')
@ -151,58 +137,150 @@ const TicketsManagement = () => {
},
{
name: 'reason',
size: '20%',
size: '15%',
header: 'Notes',
render: (row: any) => {
return (
<HoverCard width={280} shadow="md">
<HoverCard.Target>
<Text fz={'sm'}>
{row.reason !== null &&
row.reason !== '' &&
row.reason.length > 25
? row.reason.slice(0, 25) + '...'
: row.reason}
</Text>
</HoverCard.Target>
<HoverCard.Dropdown>
<Textarea size="sm" autosize>
{row.reason}
</Textarea>
</HoverCard.Dropdown>
</HoverCard>
)
},
},
{
name: 'status',
size: '8%',
size: '5%',
header: 'Status',
render: (row: any) => {
switch (row.status) {
case 'WAITING':
return <Badge color="blue">Waiting</Badge>
case 'CONFIRMED':
return <Badge color="green">Confirmed</Badge>
case 'REFUSED':
return <Badge color="red">Refused</Badge>
default:
return null
}
},
},
{
name: 'admin_note',
size: '15%',
header: 'Admin Notes',
render: (row: any) => {
return (
<HoverCard width={280} shadow="md">
<HoverCard.Target>
<Text fz={'sm'}>
{row.admin_note !== null &&
row.admin_note !== '' &&
row.admin_note.length > 25
? row.admin_note.slice(0, 25) + '...'
: row.admin_note}
</Text>
</HoverCard.Target>
<HoverCard.Dropdown>
<Textarea size="sm" autosize>
{row.admin_note}
</Textarea>
</HoverCard.Dropdown>
</HoverCard>
)
},
},
{
name: '#',
size: '5%',
header: 'Action',
render: (row: any) => {
return (
return row.status === 'WAITING' ? (
<Box className={classes.optionIcon}>
<IconTrash
<IconCheckbox
className={classes.editIcon}
onClick={() => {
setAction('confirm')
setItem(row)
form.reset()
}}
width={20}
height={20}
/>
<IconSquareXFilled
className={classes.deleteIcon}
onClick={() => {
setAction('delete')
setAction('refuse')
setItem(row)
form.reset()
}}
width={20}
height={20}
/>
</Box>
)
) : null
},
},
]
const filterInfo = [
{
key: 'reason',
name: 'Notes',
type: 'text',
},
{
key: 'start_date',
name: 'From Date',
type: 'date',
},
{
key: 'end_date',
name: 'End Date',
type: 'date',
},
const filterInfo: FilterInfo[] = [
// {
// key: 'users.name',
// name: 'User',
// type: 'text',
// },
// {
// key: 'start_date',
// name: 'From Date',
// type: 'date',
// },
// {
// key: 'startPeriod.c_name',
// name: 'Start Period',
// type: 'text',
// },
// {
// key: 'end_date',
// name: 'End Date',
// type: 'date',
// },
// {
// key: 'endPeriod.c_name',
// name: 'End Period',
// type: 'text',
// },
// {
// key: 'typeReason.c_name',
// name: 'Reason',
// type: 'text',
// },
// {
// key: 'status',
// name: 'Status',
// type: 'text',
// }
]
const getAllTickets = async () => {
try {
const searchParams = new URLSearchParams(window.location.search)
const params = {}
const params = {
typeReason: filter.typeReason,
statusFilter: filter.statusFilter,
}
for (const [key, value] of searchParams.entries()) {
if (key === 'page' && value === '') {
@ -212,7 +290,7 @@ const TicketsManagement = () => {
}
}
const res = await get(getTicketsOfUser, params)
const res = await get(getTickets, params)
if (res.status) {
setListTiskets(res)
}
@ -225,18 +303,14 @@ const TicketsManagement = () => {
}
}
const handleCreate = async (values: TTickets) => {
const handleSave = async (values: TTickets) => {
try {
const res = await create(
addTicket,
handleTicket,
{
// time_string: moment(values.time_string).format('YYYY-MM-DD HH:mm:ss'),
start_date: moment(values.start_date).format('YYYY-MM-DD'),
start_period: values.start_period,
end_date: moment(values.end_date).format('YYYY-MM-DD'),
end_period: values.end_period,
type: values.type,
reason: values.reason,
ticket_id: item.id,
action: action,
admin_note: values.admin_note,
},
getAllTickets,
)
@ -249,27 +323,15 @@ const TicketsManagement = () => {
}
}
const handleDelete = async (id: number) => {
try {
await Xdelete(deleteTicket, { ticket_id: id }, getAllTickets)
} catch (error) {
console.log(error)
}
}
useEffect(() => {
getAllTickets()
}, [])
}, [filter])
const form = useForm({
initialValues: {
id: 0,
start_date: new Date(),
start_period: '',
end_date: new Date(),
end_period: '',
type: '',
reason: '',
ticket_id: 0,
action: '',
admin_note: '',
},
})
@ -280,172 +342,94 @@ const TicketsManagement = () => {
<Text>Admin/</Text>
Tickets Management
</h3>
<Button
m={5}
onClick={() => {
setAction('add')
form.reset()
}}
>
+ Add
</Button>
</div>
<Box p={20}>
<Box display={'flex'} p={15}>
<Box style={{ display: 'flex', flexFlow: 'column' }} w={'40%'}>
<Box w="100%" display={'flex'}>
<Select
clearable
w="50%"
value={filter.typeReason}
size="xs"
label="Reason"
data={dataReason.map((user) => ({
value: user.c_code.toString(),
label: user.c_name,
}))}
onChange={(e) => {
setFilter({ ...filter, typeReason: e! })
}}
></Select>
<Select
clearable
w="50%"
value={filter.statusFilter}
size="xs"
ml={'sm'}
label="Status"
data={[
{ value: 'WAITING', label: 'WAITING' },
{ value: 'CONFIRM', label: 'CONFIRM' },
{ value: 'REFUSED', label: 'REFUSED' },
]}
onChange={(e) => {
setFilter({ ...filter, statusFilter: e! })
}}
></Select>
</Box>
</Box>
</Box>
<Box>
{listTickets.data.length > 0 && (
<DataTablePagination
filterInfo={filterInfo}
data={listTickets}
columns={columns}
// searchInput
searchInput
size=""
/>
)}
</Box>
{/* Add/Edit User modal */}
<Modal
opened={action === 'add' || action === 'edit'}
opened={action === 'confirm' || action === 'refuse'}
onClose={() => {
setAction('')
form.reset()
}}
title={
<Text pl={'sm'} fw={700} fz={'lg'}>
{action === 'add' && 'Add Ticket'}
{action === 'confirm' ? 'Confirm Ticket' : 'Refuse Ticket'}
</Text>
}
>
<form
onSubmit={form.onSubmit(async (values) => {
setDisableBtn(true)
action === 'add' && (await handleCreate(values))
await handleSave(values)
setDisableBtn(false)
})}
>
<Box pl={'md'} pr={'md'}>
<Box display={'flex'}>
<Box style={{ display: 'flex', flexFlow: 'column' }} w={'40%'}>
<DateInput
required
mb={'md'}
label={'From Date'}
value={new Date(form.values.start_date)}
valueFormat="DD/MM/YYYY"
onChange={(e) => form.setFieldValue('start_date', e!)}
></DateInput>
<Select
required
mb={'md'}
label={'Start Period'}
data={dataTimeType.map((item) => {
return { value: item.c_code.toString(), label: item.c_name }
})}
value={form.values.start_period}
error={form.errors.start_period}
onChange={(e) => form.setFieldValue('start_period', e!)}
/>
<Select
required
mb={'md'}
searchable
label="Type"
data={dataReason.map((user) => ({
value: user.c_code.toString(),
label: user.c_name,
}))}
value={form.values.type}
error={form.errors.type}
onChange={(e) => form.setFieldValue('type', e!)}
/>
</Box>
<Box
style={{ display: 'flex', flexFlow: 'column' }}
w={'20%'}
></Box>
<Box style={{ display: 'flex', flexFlow: 'column' }} w={'40%'}>
<DateInput
required
mb={'md'}
label={'End Date'}
value={new Date(form.values.end_date)}
valueFormat="DD/MM/YYYY"
onChange={(e) => form.setFieldValue('end_date', e!)}
></DateInput>
<Select
required
mb={'md'}
label={'End Period'}
data={dataTimeType.map((item) => {
return { value: item.c_code.toString(), label: item.c_name }
})}
value={form.values.end_period}
error={form.errors.end_period}
onChange={(e) => form.setFieldValue('end_period', e!)}
/>
</Box>
</Box>
<Textarea
label="Reason"
label="Admin Notes"
required
value={form.values.reason}
onChange={(e) => form.setFieldValue('reason', e.target.value)}
value={form.values.admin_note}
onChange={(e) => form.setFieldValue('admin_note', e.target.value)}
/>
<Box ta={'center'}>
{action === 'add' && (
<Button
mt={'lg'}
bg={'green'}
type="submit"
disabled={disableBtn}
>
Create
Save
</Button>
)}
</Box>
</Box>
</form>
</Modal>
<Dialog
className={classes.dialog}
opened={action === 'delete'}
withCloseButton
onClose={() => setAction('')}
size="lg"
radius="md"
position={{ top: 30, right: 10 }}
>
<Text className={classes.dialogText} size="sm" mb="xs" fw={500}>
Do you want to delete this record?
<Group justify="center" m={10}>
<Button
disabled={activeBtn}
fw={700}
size="xs"
variant="light"
onClick={async () => {
setActiveBtn(true)
await handleDelete(item.id)
setActiveBtn(false)
setAction('')
}}
>
Yes
</Button>
<Button
fw={700}
size="xs"
variant="light"
onClick={() => setAction('')}
>
Cancel
</Button>
</Group>
</Text>
</Dialog>
</div>
)
}

View File

@ -21,7 +21,7 @@ const mainRoutes = [
path: '/',
// element: <ProtectedRoute mode="home"><PageHome /></ProtectedRoute>,
element: (
<ProtectedRoute mode="home">
<ProtectedRoute mode="home" permission="staff">
<Navigate to="/timekeeping"></Navigate>
</ProtectedRoute>
),
@ -29,7 +29,7 @@ const mainRoutes = [
{
path: '/welcome',
element: (
<ProtectedRoute mode="route">
<ProtectedRoute mode="route" permission="staff">
<PageWelcome />
</ProtectedRoute>
),
@ -37,7 +37,7 @@ const mainRoutes = [
{
path: '/dashboard',
element: (
<ProtectedRoute mode="route">
<ProtectedRoute mode="route" permission="staff">
<BasePage
main={
<>
@ -51,7 +51,7 @@ const mainRoutes = [
{
path: '/general-setting',
element: (
<ProtectedRoute mode="route">
<ProtectedRoute mode="home" permission="staff">
<BasePage
main={
<>
@ -65,7 +65,7 @@ const mainRoutes = [
{
path: '/custom-theme',
element: (
<ProtectedRoute mode="route">
<ProtectedRoute mode="home" permission="staff">
<BasePage
main={
<>
@ -79,7 +79,7 @@ const mainRoutes = [
{
path: '/tracking',
element: (
<ProtectedRoute mode="route">
<ProtectedRoute mode="home" permission="staff">
<BasePage
main={
<>
@ -93,7 +93,7 @@ const mainRoutes = [
// {
// path: '/jira',
// element: (
// <ProtectedRoute mode="route">
// <ProtectedRoute mode="home" permission="staff">
// <BasePage
// main={
// <>
@ -107,7 +107,7 @@ const mainRoutes = [
{
path: '/worklogs',
element: (
<ProtectedRoute mode="route">
<ProtectedRoute mode="home" permission="staff">
<BasePage
main={
<>
@ -121,7 +121,7 @@ const mainRoutes = [
{
path: '/timekeeping',
element: (
<ProtectedRoute mode="route">
<ProtectedRoute mode="home" permission="staff">
<BasePage
main={
<>
@ -135,7 +135,7 @@ const mainRoutes = [
{
path: '/leave-management',
element: (
<ProtectedRoute mode="route">
<ProtectedRoute mode="home" permission="staff">
<BasePage
main={
<>
@ -149,7 +149,7 @@ const mainRoutes = [
{
path: '/tickets',
element: (
<ProtectedRoute mode="route">
<ProtectedRoute mode="route" permission="staff">
<BasePage
main={
<>
@ -163,7 +163,7 @@ const mainRoutes = [
{
path: '/tickets-management',
element: (
<ProtectedRoute mode="route">
<ProtectedRoute mode="route" permission="admin">
<BasePage
main={
<>
@ -177,7 +177,7 @@ const mainRoutes = [
// {
// path: '/packages',
// element: (
// <ProtectedRoute mode="route">
// <ProtectedRoute mode="home" permission="staff">
// <BasePage
// main={
// <>
@ -191,7 +191,7 @@ const mainRoutes = [
// {
// path: '/discounts',
// element: (
// <ProtectedRoute mode="route">
// <ProtectedRoute mode="home" permission="staff">
// <BasePage
// main={
// <>
@ -205,7 +205,7 @@ const mainRoutes = [
// {
// path: '/client',
// element: (
// <ProtectedRoute mode="route">
// <ProtectedRoute mode="home" permission="staff">
// <BasePage
// main={
// <>
@ -219,7 +219,7 @@ const mainRoutes = [
// {
// path: '/banner',
// element: (
// <ProtectedRoute mode="route">
// <ProtectedRoute mode="home" permission="staff">
// <BasePage
// main={
// <>
@ -233,7 +233,7 @@ const mainRoutes = [
// {
// path: '/order',
// element: (
// <ProtectedRoute mode="route">
// <ProtectedRoute mode="home" permission="staff">
// <BasePage
// main={
// <>
@ -247,7 +247,7 @@ const mainRoutes = [
// {
// path: '/sn-check-history',
// element: (
// <ProtectedRoute mode="route">
// <ProtectedRoute mode="home" permission="staff">
// <BasePage
// main={
// <>
@ -261,7 +261,7 @@ const mainRoutes = [
// {
// path: '/contacts',
// element: (
// <ProtectedRoute mode="route">
// <ProtectedRoute mode="home" permission="staff">
// <BasePage
// main={
// <>
@ -275,7 +275,7 @@ const mainRoutes = [
{
path: '/login',
element: (
<ProtectedRoute mode="login">
<ProtectedRoute mode="login" permission="staff">
<PageLogin />
</ProtectedRoute>
),

View File

@ -17,6 +17,21 @@ export const checkExpToken = () => {
return false
}
}
export const checkPermissionAdmin = () => {
const user = localStorage.getItem('user')
if (user) {
const parsedUser = JSON.parse(user)
if (parsedUser.user.permission == 'admin') {
return true
} else {
return false
}
} else {
return false
}
}
export const getUser = () => localStorage.getItem('user') as string
export const getAccessToken = () =>
localStorage.getItem('token')?.slice(1, -1) as string