import Layout from "@/components/High/Layout"; import TicketDisplay from "@/components/High/TicketDisplay"; import Select from "@/components/Low/Select"; import Modal from "@/components/Modal"; import useTickets from "@/hooks/useTickets"; import useUser from "@/hooks/useUser"; import useUsers from "@/hooks/useUsers"; import {Ticket, TicketStatus, TicketStatusLabel, TicketType, TicketTypeLabel, TicketWithCorporate} from "@/interfaces/ticket"; import {sessionOptions} from "@/lib/session"; import {shouldRedirectHome} from "@/utils/navigation.disabled"; import {createColumnHelper, flexRender, getCoreRowModel, useReactTable} from "@tanstack/react-table"; import clsx from "clsx"; import {withIronSessionSsr} from "iron-session/next"; import moment from "moment"; import Head from "next/head"; import {useEffect, useState} from "react"; import {BsArrowDown, BsArrowUp} from "react-icons/bs"; import {ToastContainer} from "react-toastify"; const columnHelper = createColumnHelper(); export const getServerSideProps = withIronSessionSsr(({req, res}) => { const user = req.session.user; if (!user || !user.isVerified) { return { redirect: { destination: "/login", permanent: false, }, }; } if (shouldRedirectHome(user) || !["admin", "developer", "agent"].includes(user.type)) { return { redirect: { destination: "/", permanent: false, }, }; } return { props: {user: req.session.user}, }; }, sessionOptions); const StatusClassNames: {[key in TicketStatus]: string} = { submitted: "bg-mti-gray-dim", "in-progress": "bg-mti-blue-dark", completed: "bg-mti-green-dark", }; const TypesClassNames: {[key in TicketType]: string} = { feedback: "bg-mti-green-light", bug: "bg-mti-red-dark", help: "bg-mti-blue-light", }; const escapedURL = process.env.NEXT_PUBLIC_WEBSITE_URL || "".replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); const fromHomepage = [new RegExp(`^${escapedURL}`), /\/contact$/]; type Source = "webpage" | "platform" | ""; const SOURCE_OPTIONS = [ {value: "", label: "All"}, {value: "webpage", label: "Webpage"}, {value: "platform", label: "Platform"}, ]; export default function Tickets() { const [filteredTickets, setFilteredTickets] = useState([]); const [selectedTicket, setSelectedTicket] = useState(); const [assigneeFilter, setAssigneeFilter] = useState(); const [sourceFilter, setSourceFilter] = useState(""); const [dateSorting, setDateSorting] = useState<"asc" | "desc">("desc"); const [typeFilter, setTypeFilter] = useState(); const [statusFilter, setStatusFilter] = useState(); const {user} = useUser({redirectTo: "/login"}); const {users} = useUsers(); const {tickets, reload} = useTickets(); const sortByDate = (a: Ticket, b: Ticket) => { return moment((dateSorting === "desc" ? b : a).date).diff(moment((dateSorting === "desc" ? a : b).date)); }; useEffect(() => { const filters = []; if (user?.type === "agent") filters.push((x: Ticket) => x.assignedTo === user.id); if (typeFilter) filters.push((x: Ticket) => x.type === typeFilter); if (statusFilter) filters.push((x: Ticket) => x.status === statusFilter); if (assigneeFilter) filters.push((x: Ticket) => x.assignedTo === assigneeFilter); if (sourceFilter) { if (sourceFilter === "webpage") 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([...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]); const columns = [ columnHelper.accessor("id", { header: "ID", cell: (info) => info.getValue(), }), columnHelper.accessor("type", { header: "Type", cell: (info) => ( {TicketTypeLabel[info.getValue()]} ), }), columnHelper.accessor("reporter", { header: "Reporter", cell: (info) => info.getValue().email, }), columnHelper.accessor("reportedFrom", { header: "Reported From", cell: (info) => info.getValue(), }), columnHelper.accessor("date", { id: "date", header: ( ) as any, cell: (info) => {moment(info.getValue()).format("DD/MM/YYYY - HH:mm")}, }), columnHelper.accessor("subject", { header: "Subject", cell: (info) => info.getValue().substring(0, 12) + (info.getValue().length > 12 ? "..." : ""), }), columnHelper.accessor("status", { header: "Status", cell: (info) => ( {TicketStatusLabel[info.getValue()]} ), }), columnHelper.accessor("assignedTo", { header: "Assignee", cell: (info) => users.find((x) => x.id === info.getValue())?.name || "", }), columnHelper.accessor("corporate", { header: "Corporate", cell: (info) => info.getValue(), }), ]; const getAssigneeValue = () => { if (user && user.type === "agent") return {value: user.id, label: `${user.name} - ${user.email}`}; if (assigneeFilter) { const assigneeUser = users.find((x) => x.id === assigneeFilter); return assigneeUser ? { value: assigneeFilter, label: `${assigneeUser.name} - ${assigneeUser.email}`, } : null; } return null; }; const table = useReactTable({ data: filteredTickets, columns: columns, getCoreRowModel: getCoreRowModel(), }); return ( <> { reload(); setSelectedTicket(undefined); }}> {selectedTicket && ( { reload(); setSelectedTicket(undefined); }} /> )} Tickets Panel | EnCoach {user && (

Tickets

({ value: x, label: TicketTypeLabel[x as keyof typeof TicketTypeLabel], }))} value={typeFilter ? {value: typeFilter, label: TicketTypeLabel[typeFilter]} : undefined} onChange={(value) => setTypeFilter((value?.value as TicketType) ?? undefined)} isClearable placeholder="Type..." />
x.value === sourceFilter)} onChange={(value) => setSourceFilter(value?.value as Source)} />
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( ))} ))} {table.getRowModel().rows.map((row) => ( setSelectedTicket(row.original)} key={row.id}> {row.getVisibleCells().map((cell) => ( ))} ))}
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
{flexRender(cell.column.columnDef.cell, cell.getContext())}
)} ); }