import Button from "@/components/Low/Button"; import {PERMISSIONS} from "@/constants/userPermissions"; import useGroups from "@/hooks/useGroups"; import useUsers from "@/hooks/useUsers"; import {Type, User} from "@/interfaces/user"; import {Popover, Transition} from "@headlessui/react"; import {createColumnHelper, flexRender, getCoreRowModel, useReactTable} from "@tanstack/react-table"; import axios from "axios"; import clsx from "clsx"; import {capitalize} from "lodash"; import moment from "moment"; import {Fragment, useState} from "react"; import {BsCheck, BsCheckCircle, BsFillExclamationOctagonFill, BsPerson, BsTrash} from "react-icons/bs"; import {toast} from "react-toastify"; import {countries, TCountries} from "countries-list"; import countryCodes from "country-codes-list"; const columnHelper = createColumnHelper(); export default function UserList({user}: {user: User}) { const [showDemographicInformation, setShowDemographicInformation] = useState(false); const {users, reload} = useUsers(); const {groups} = useGroups(user ? user.id : undefined); const deleteAccount = (user: User) => { if (!confirm(`Are you sure you want to delete ${user.name}'s account?`)) return; axios .delete<{ok: boolean}>(`/api/user?id=${user.id}`) .then(() => { toast.success("User deleted successfully!"); reload(); }) .catch(() => { toast.error("Something went wrong!", {toastId: "delete-error"}); }); }; const updateAccountType = (user: User, type: Type) => { if (!confirm(`Are you sure you want to update ${user.name}'s account from ${capitalize(user.type)} to ${capitalize(type)}?`)) return; axios .post<{user?: User; ok?: boolean}>(`/api/users/update?id=${user.id}`, {...user, type}) .then(() => { toast.success("User type updated successfully!"); reload(); }) .catch(() => { toast.error("Something went wrong!", {toastId: "update-error"}); }); }; const verifyAccount = (user: User) => { axios .post<{user?: User; ok?: boolean}>(`/api/users/update?id=${user.id}`, {...user, isVerified: true}) .then(() => { toast.success("User verified successfully!"); reload(); }) .catch(() => { toast.error("Something went wrong!", {toastId: "update-error"}); }); }; const toggleDisableAccount = (user: User) => { if ( !confirm( `Are you sure you want to ${user.isDisabled ? "enable" : "disable"} ${ user.name }'s account? This change is usually related to their payment state.`, ) ) return; axios .post<{user?: User; ok?: boolean}>(`/api/users/update?id=${user.id}`, {...user, isDisabled: !user.isDisabled}) .then(() => { toast.success(`User ${user.isDisabled ? "enabled" : "disabled"} successfully!`); reload(); }) .catch(() => { toast.error("Something went wrong!", {toastId: "update-error"}); }); }; const actionColumn = ({row}: {row: {original: User}}) => { return (
{PERMISSIONS.updateUser[row.original.type].includes(user.type) && (
)} {!row.original.isVerified && PERMISSIONS.updateUser[row.original.type].includes(user.type) && (
verifyAccount(row.original)}>
)} {PERMISSIONS.updateUser[row.original.type].includes(user.type) && (
toggleDisableAccount(row.original)}> {row.original.isDisabled ? ( ) : ( )}
)} {PERMISSIONS.deleteUser[row.original.type].includes(user.type) && (
deleteAccount(row.original)}>
)}
); }; const demographicColumns = [ columnHelper.accessor("name", { header: "Name", cell: (info) => info.getValue(), enableSorting: true, }), columnHelper.accessor("demographicInformation.country", { header: "Country", cell: (info) => info.getValue() ? `${countryCodes.findOne("countryCode" as any, info.getValue()).flag} ${ countries[info.getValue() as unknown as keyof TCountries].name } (+${countryCodes.findOne("countryCode" as any, info.getValue()).countryCallingCode})` : "Not available", }), columnHelper.accessor("demographicInformation.phone", { header: "Phone", cell: (info) => info.getValue() || "Not available", enableSorting: true, }), columnHelper.accessor("demographicInformation.employment", { header: "Employment", cell: (info) => capitalize(info.getValue()) || "Not available", enableSorting: true, }), columnHelper.accessor("demographicInformation.gender", { header: "Gender", cell: (info) => capitalize(info.getValue()) || "Not available", enableSorting: true, }), { header: ( setShowDemographicInformation((prev) => !prev)}> Switch ), id: "actions", cell: actionColumn, }, ]; const defaultColumns = [ columnHelper.accessor("name", { header: "Name", cell: (info) => info.getValue(), enableSorting: true, }), columnHelper.accessor("email", { header: "E-mail", cell: (info) => info.getValue(), }), columnHelper.accessor("type", { header: "Type", cell: (info) => capitalize(info.getValue()), }), columnHelper.accessor("subscriptionExpirationDate", { header: "Expiry Date", cell: (info) => (!info.getValue() ? "No expiry date" : moment(info.getValue()).format("DD/MM/YYYY")), }), columnHelper.accessor("isVerified", { header: "Verification", cell: (info) => (
), }), { header: ( setShowDemographicInformation((prev) => !prev)}> Switch ), id: "actions", cell: actionColumn, }, ]; const table = useReactTable({ data: user && (user.type === "admin" || user.type === "student") ? users.filter((u) => groups.flatMap((g) => g.participants).includes(u.id)) : users, columns: (!showDemographicInformation ? defaultColumns : demographicColumns) as any, getCoreRowModel: getCoreRowModel(), }); return ( {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( ))} ))} {table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( ))} ))}
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
{flexRender(cell.column.columnDef.cell, cell.getContext())}
); }