Applied the same fix for other pages

This commit is contained in:
Tiago Ribeiro
2024-03-13 09:21:16 +00:00
parent 49ee3c45e5
commit 74dd96d000
2 changed files with 261 additions and 341 deletions

View File

@@ -22,16 +22,16 @@ export const getServerSideProps = withIronSessionSsr(({req, res}) => {
redirect: { redirect: {
destination: "/login", destination: "/login",
permanent: false, permanent: false,
} },
}; };
} }
if (shouldRedirectHome(user) || user.type !== "developer") { if (shouldRedirectHome(user) || !["developer", "admin", "corporate", "agent"].includes(user.type)) {
return { return {
redirect: { redirect: {
destination: "/", destination: "/",
permanent: false, permanent: false,
} },
}; };
} }

View File

@@ -5,22 +5,10 @@ import Modal from "@/components/Modal";
import useTickets from "@/hooks/useTickets"; import useTickets from "@/hooks/useTickets";
import useUser from "@/hooks/useUser"; import useUser from "@/hooks/useUser";
import useUsers from "@/hooks/useUsers"; import useUsers from "@/hooks/useUsers";
import { import {Ticket, TicketStatus, TicketStatusLabel, TicketType, TicketTypeLabel, TicketWithCorporate} from "@/interfaces/ticket";
Ticket,
TicketStatus,
TicketStatusLabel,
TicketType,
TicketTypeLabel,
TicketWithCorporate,
} from "@/interfaces/ticket";
import {sessionOptions} from "@/lib/session"; import {sessionOptions} from "@/lib/session";
import {shouldRedirectHome} from "@/utils/navigation.disabled"; import {shouldRedirectHome} from "@/utils/navigation.disabled";
import { import {createColumnHelper, flexRender, getCoreRowModel, useReactTable} from "@tanstack/react-table";
createColumnHelper,
flexRender,
getCoreRowModel,
useReactTable,
} from "@tanstack/react-table";
import clsx from "clsx"; import clsx from "clsx";
import {withIronSessionSsr} from "iron-session/next"; import {withIronSessionSsr} from "iron-session/next";
import moment from "moment"; import moment from "moment";
@@ -39,19 +27,16 @@ export const getServerSideProps = withIronSessionSsr(({ req, res }) => {
redirect: { redirect: {
destination: "/login", destination: "/login",
permanent: false, permanent: false,
} },
}; };
} }
if ( if (shouldRedirectHome(user) || !["admin", "developer", "agent"].includes(user.type)) {
shouldRedirectHome(user) ||
["admin", "developer", "agent"].includes(user.type)
) {
return { return {
redirect: { redirect: {
destination: "/", destination: "/",
permanent: false, permanent: false,
} },
}; };
} }
@@ -72,10 +57,7 @@ const TypesClassNames: { [key in TicketType]: string } = {
help: "bg-mti-blue-light", help: "bg-mti-blue-light",
}; };
const escapedURL = process.env.NEXT_PUBLIC_WEBSITE_URL || ''.replace( const escapedURL = process.env.NEXT_PUBLIC_WEBSITE_URL || "".replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
/[.*+?^${}()|[\]\\]/g,
"\\$&"
);
const fromHomepage = [new RegExp(`^${escapedURL}`), /\/contact$/]; const fromHomepage = [new RegExp(`^${escapedURL}`), /\/contact$/];
type Source = "webpage" | "platform" | ""; type Source = "webpage" | "platform" | "";
@@ -84,7 +66,7 @@ const SOURCE_OPTIONS = [
{value: "", label: "All"}, {value: "", label: "All"},
{value: "webpage", label: "Webpage"}, {value: "webpage", label: "Webpage"},
{value: "platform", label: "Platform"}, {value: "platform", label: "Platform"},
] ];
export default function Tickets() { export default function Tickets() {
const [filteredTickets, setFilteredTickets] = useState<Ticket[]>([]); const [filteredTickets, setFilteredTickets] = useState<Ticket[]>([]);
@@ -102,28 +84,21 @@ export default function Tickets() {
const {tickets, reload} = useTickets(); const {tickets, reload} = useTickets();
const sortByDate = (a: Ticket, b: Ticket) => { const sortByDate = (a: Ticket, b: Ticket) => {
return moment((dateSorting === "desc" ? b : a).date).diff( return moment((dateSorting === "desc" ? b : a).date).diff(moment((dateSorting === "desc" ? a : b).date));
moment((dateSorting === "desc" ? a : b).date)
);
}; };
useEffect(() => { useEffect(() => {
const filters = []; const filters = [];
if (user?.type === "agent") if (user?.type === "agent") filters.push((x: Ticket) => x.assignedTo === user.id);
filters.push((x: Ticket) => x.assignedTo === user.id);
if (typeFilter) filters.push((x: Ticket) => x.type === typeFilter); if (typeFilter) filters.push((x: Ticket) => x.type === typeFilter);
if (statusFilter) filters.push((x: Ticket) => x.status === statusFilter); if (statusFilter) filters.push((x: Ticket) => x.status === statusFilter);
if (assigneeFilter) if (assigneeFilter) filters.push((x: Ticket) => x.assignedTo === assigneeFilter);
filters.push((x: Ticket) => x.assignedTo === assigneeFilter);
if (sourceFilter) { if (sourceFilter) {
if (sourceFilter === "webpage") if (sourceFilter === "webpage") filters.push((x: Ticket) => fromHomepage.some((r) => r.test(x.reportedFrom)));
filters.push((x: Ticket) => fromHomepage.some((r) => r.test(x.reportedFrom))); if (sourceFilter === "platform") filters.push((x: Ticket) => !fromHomepage.some((r) => r.test(x.reportedFrom)));
if (sourceFilter === "platform")
filters.push((x: Ticket) => !fromHomepage.some((r) => r.test(x.reportedFrom)));
} }
setFilteredTickets( setFilteredTickets([...filters.reduce((d, f) => d.filter(f), tickets)].sort(sortByDate));
[...filters.reduce((d, f) => d.filter(f), tickets)].sort(sortByDate) // eslint-disable-next-line react-hooks/exhaustive-deps
);
}, [tickets, typeFilter, statusFilter, assigneeFilter, dateSorting, user, sourceFilter]); }, [tickets, typeFilter, statusFilter, assigneeFilter, dateSorting, user, sourceFilter]);
const columns = [ const columns = [
@@ -134,14 +109,7 @@ export default function Tickets() {
columnHelper.accessor("type", { columnHelper.accessor("type", {
header: "Type", header: "Type",
cell: (info) => ( cell: (info) => (
<span <span className={clsx("rounded-lg p-1 px-2 text-white", TypesClassNames[info.getValue()])}>{TicketTypeLabel[info.getValue()]}</span>
className={clsx(
"rounded-lg p-1 px-2 text-white",
TypesClassNames[info.getValue()]
)}
>
{TicketTypeLabel[info.getValue()]}
</span>
), ),
}), }),
columnHelper.accessor("reporter", { columnHelper.accessor("reporter", {
@@ -155,36 +123,22 @@ export default function Tickets() {
columnHelper.accessor("date", { columnHelper.accessor("date", {
id: "date", id: "date",
header: ( header: (
<button <button className="flex items-center gap-2" onClick={() => setDateSorting((prev) => (prev === "asc" ? "desc" : "asc"))}>
className="flex items-center gap-2"
onClick={() =>
setDateSorting((prev) => (prev === "asc" ? "desc" : "asc"))
}
>
<span>Date</span> <span>Date</span>
{dateSorting === "desc" && <BsArrowDown />} {dateSorting === "desc" && <BsArrowDown />}
{dateSorting === "asc" && <BsArrowUp />} {dateSorting === "asc" && <BsArrowUp />}
</button> </button>
) as any, ) as any,
cell: (info) => ( cell: (info) => <span className="whitespace-nowrap">{moment(info.getValue()).format("DD/MM/YYYY - HH:mm")}</span>,
<span className="whitespace-nowrap">{moment(info.getValue()).format("DD/MM/YYYY - HH:mm")}</span>
),
}), }),
columnHelper.accessor("subject", { columnHelper.accessor("subject", {
header: "Subject", header: "Subject",
cell: (info) => cell: (info) => info.getValue().substring(0, 12) + (info.getValue().length > 12 ? "..." : ""),
info.getValue().substring(0, 12) +
(info.getValue().length > 12 ? "..." : ""),
}), }),
columnHelper.accessor("status", { columnHelper.accessor("status", {
header: "Status", header: "Status",
cell: (info) => ( cell: (info) => (
<span <span className={clsx("rounded-lg p-1 px-2 text-white", StatusClassNames[info.getValue()])}>
className={clsx(
"rounded-lg p-1 px-2 text-white",
StatusClassNames[info.getValue()]
)}
>
{TicketStatusLabel[info.getValue()]} {TicketStatusLabel[info.getValue()]}
</span> </span>
), ),
@@ -200,8 +154,7 @@ export default function Tickets() {
]; ];
const getAssigneeValue = () => { const getAssigneeValue = () => {
if (user && user.type === "agent") if (user && user.type === "agent") return {value: user.id, label: `${user.name} - ${user.email}`};
return { value: user.id, label: `${user.name} - ${user.email}` };
if (assigneeFilter) { if (assigneeFilter) {
const assigneeUser = users.find((x) => x.id === assigneeFilter); const assigneeUser = users.find((x) => x.id === assigneeFilter);
@@ -229,8 +182,7 @@ export default function Tickets() {
onClose={() => { onClose={() => {
reload(); reload();
setSelectedTicket(undefined); setSelectedTicket(undefined);
}} }}>
>
{selectedTicket && ( {selectedTicket && (
<TicketDisplay <TicketDisplay
user={user!} user={user!}
@@ -259,9 +211,7 @@ export default function Tickets() {
<div className="flex w-full items-center gap-4"> <div className="flex w-full items-center gap-4">
<div className="flex w-full flex-col gap-3"> <div className="flex w-full flex-col gap-3">
<label className="text-mti-gray-dim text-base font-normal"> <label className="text-mti-gray-dim text-base font-normal">Status</label>
Status
</label>
<Select <Select
options={Object.keys(TicketStatusLabel).map((x) => ({ options={Object.keys(TicketStatusLabel).map((x) => ({
value: x, value: x,
@@ -275,45 +225,31 @@ export default function Tickets() {
} }
: undefined : undefined
} }
onChange={(value) => onChange={(value) => setStatusFilter((value?.value as TicketStatus) ?? undefined)}
setStatusFilter((value?.value as TicketStatus) ?? undefined)
}
isClearable isClearable
placeholder="Status..." placeholder="Status..."
/> />
</div> </div>
<div className="flex w-full flex-col gap-3"> <div className="flex w-full flex-col gap-3">
<label className="text-mti-gray-dim text-base font-normal"> <label className="text-mti-gray-dim text-base font-normal">Type</label>
Type
</label>
<Select <Select
options={Object.keys(TicketTypeLabel).map((x) => ({ options={Object.keys(TicketTypeLabel).map((x) => ({
value: x, value: x,
label: TicketTypeLabel[x as keyof typeof TicketTypeLabel], label: TicketTypeLabel[x as keyof typeof TicketTypeLabel],
}))} }))}
value={ value={typeFilter ? {value: typeFilter, label: TicketTypeLabel[typeFilter]} : undefined}
typeFilter onChange={(value) => setTypeFilter((value?.value as TicketType) ?? undefined)}
? { value: typeFilter, label: TicketTypeLabel[typeFilter] }
: undefined
}
onChange={(value) =>
setTypeFilter((value?.value as TicketType) ?? undefined)
}
isClearable isClearable
placeholder="Type..." placeholder="Type..."
/> />
</div> </div>
<div className="flex w-full flex-col gap-3"> <div className="flex w-full flex-col gap-3">
<label className="text-mti-gray-dim text-base font-normal"> <label className="text-mti-gray-dim text-base font-normal">Assignee</label>
Assignee
</label>
<Select <Select
options={[ options={[
{value: "me", label: "Assigned to me"}, {value: "me", label: "Assigned to me"},
...users ...users
.filter((x) => .filter((x) => ["admin", "developer", "agent"].includes(x.type))
["admin", "developer", "agent"].includes(x.type)
)
.map((u) => ({ .map((u) => ({
value: u.id, value: u.id,
label: `${u.name} - ${u.email}`, label: `${u.name} - ${u.email}`,
@@ -322,26 +258,19 @@ export default function Tickets() {
disabled={user.type === "agent"} disabled={user.type === "agent"}
value={getAssigneeValue()} value={getAssigneeValue()}
onChange={(value) => onChange={(value) =>
value value ? setAssigneeFilter(value.value === "me" ? user.id : value.value) : setAssigneeFilter(undefined)
? setAssigneeFilter(
value.value === "me" ? user.id : value.value
)
: setAssigneeFilter(undefined)
} }
placeholder="Assignee..." placeholder="Assignee..."
isClearable isClearable
/> />
</div> </div>
<div className="flex w-full flex-col gap-3"> <div className="flex w-full flex-col gap-3">
<label className="text-mti-gray-dim text-base font-normal"> <label className="text-mti-gray-dim text-base font-normal">Source</label>
Source
</label>
<Select <Select
options={SOURCE_OPTIONS} options={SOURCE_OPTIONS}
disabled={user.type === "agent"} disabled={user.type === "agent"}
value={SOURCE_OPTIONS.find((x) => x.value === sourceFilter)} value={SOURCE_OPTIONS.find((x) => x.value === sourceFilter)}
onChange={(value) => setSourceFilter(value?.value as Source) onChange={(value) => setSourceFilter(value?.value as Source)}
}
/> />
</div> </div>
</div> </div>
@@ -352,12 +281,7 @@ export default function Tickets() {
<tr key={headerGroup.id}> <tr key={headerGroup.id}>
{headerGroup.headers.map((header) => ( {headerGroup.headers.map((header) => (
<th className="px-4 py-4 text-left" key={header.id}> <th className="px-4 py-4 text-left" key={header.id}>
{header.isPlaceholder {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</th> </th>
))} ))}
</tr> </tr>
@@ -368,17 +292,13 @@ export default function Tickets() {
<tr <tr
className={clsx( className={clsx(
"even:bg-mti-purple-ultralight/40 hover:bg-mti-purple-ultralight cursor-pointer rounded-lg py-2 odd:bg-white", "even:bg-mti-purple-ultralight/40 hover:bg-mti-purple-ultralight cursor-pointer rounded-lg py-2 odd:bg-white",
"transition duration-300 ease-in-out" "transition duration-300 ease-in-out",
)} )}
onClick={() => setSelectedTicket(row.original)} onClick={() => setSelectedTicket(row.original)}
key={row.id} key={row.id}>
>
{row.getVisibleCells().map((cell) => ( {row.getVisibleCells().map((cell) => (
<td className="w-fit items-center px-4 py-2" key={cell.id}> <td className="w-fit items-center px-4 py-2" key={cell.id}>
{flexRender( {flexRender(cell.column.columnDef.cell, cell.getContext())}
cell.column.columnDef.cell,
cell.getContext()
)}
</td> </td>
))} ))}
</tr> </tr>