Updated the User list to also show their demographic information
This commit is contained in:
@@ -110,6 +110,10 @@ const CreatePanel = ({user, users, group, onCreate}: CreateDialogProps) => {
|
|||||||
className="w-full max-w-[200px] self-end"
|
className="w-full max-w-[200px] self-end"
|
||||||
disabled={!name}
|
disabled={!name}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (name !== group?.name && (name === "Students" || name === "Teachers")) {
|
||||||
|
toast.error("That group name is reserved and cannot be used, please enter another one.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
onCreate({name: name!, admin, participants, id: group?.id || uuidv4()});
|
onCreate({name: name!, admin, participants, id: group?.id || uuidv4()});
|
||||||
}}>
|
}}>
|
||||||
{!group ? "Create" : "Update"}
|
{!group ? "Create" : "Update"}
|
||||||
|
|||||||
@@ -9,13 +9,17 @@ import axios from "axios";
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import {capitalize} from "lodash";
|
import {capitalize} from "lodash";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import {Fragment} from "react";
|
import {Fragment, useState} from "react";
|
||||||
import {BsCheck, BsCheckCircle, BsFillExclamationOctagonFill, BsPerson, BsStop, BsTrash} from "react-icons/bs";
|
import {BsCheck, BsCheckCircle, BsFillExclamationOctagonFill, BsPerson, BsStop, BsTrash} from "react-icons/bs";
|
||||||
import {toast} from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
|
import {countries, TCountries} from "countries-list";
|
||||||
|
import countryCodes from "country-codes-list";
|
||||||
|
|
||||||
const columnHelper = createColumnHelper<User>();
|
const columnHelper = createColumnHelper<User>();
|
||||||
|
|
||||||
export default function UserList({user}: {user: User}) {
|
export default function UserList({user}: {user: User}) {
|
||||||
|
const [showDemographicInformation, setShowDemographicInformation] = useState(false);
|
||||||
|
|
||||||
const {users, reload} = useUsers();
|
const {users, reload} = useUsers();
|
||||||
const {groups} = useGroups(user.id);
|
const {groups} = useGroups(user.id);
|
||||||
|
|
||||||
@@ -80,6 +84,122 @@ export default function UserList({user}: {user: User}) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const actionColumn = ({row}: {row: {original: User}}) => {
|
||||||
|
return (
|
||||||
|
<div className="flex gap-4">
|
||||||
|
{PERMISSIONS.updateUser[row.original.type].includes(user.type) && (
|
||||||
|
<Popover className="relative">
|
||||||
|
<Popover.Button>
|
||||||
|
<div data-tip="Change Type" className="cursor-pointer tooltip">
|
||||||
|
<BsPerson className="hover:text-mti-purple-light transition ease-in-out duration-300" />
|
||||||
|
</div>
|
||||||
|
</Popover.Button>
|
||||||
|
<Transition
|
||||||
|
as={Fragment}
|
||||||
|
enter="transition ease-out duration-200"
|
||||||
|
enterFrom="opacity-0 translate-y-1"
|
||||||
|
enterTo="opacity-100 translate-y-0"
|
||||||
|
leave="transition ease-in duration-150"
|
||||||
|
leaveFrom="opacity-100 translate-y-0"
|
||||||
|
leaveTo="opacity-0 translate-y-1">
|
||||||
|
<Popover.Panel className="absolute z-10 w-screen right-1/2 translate-x-1/3 max-w-sm">
|
||||||
|
<div className="bg-white p-4 rounded-lg grid grid-cols-2 gap-2 w-full drop-shadow-xl">
|
||||||
|
<Button
|
||||||
|
onClick={() => updateAccountType(row.original, "student")}
|
||||||
|
className="text-sm !py-2 !px-4"
|
||||||
|
disabled={row.original.type === "student" || !PERMISSIONS.generateCode["student"].includes(user.type)}>
|
||||||
|
Student
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => updateAccountType(row.original, "teacher")}
|
||||||
|
className="text-sm !py-2 !px-4"
|
||||||
|
disabled={row.original.type === "teacher" || !PERMISSIONS.generateCode["teacher"].includes(user.type)}>
|
||||||
|
Teacher
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => updateAccountType(row.original, "admin")}
|
||||||
|
className="text-sm !py-2 !px-4"
|
||||||
|
disabled={row.original.type === "admin" || !PERMISSIONS.generateCode["admin"].includes(user.type)}>
|
||||||
|
Admin
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => updateAccountType(row.original, "owner")}
|
||||||
|
className="text-sm !py-2 !px-4"
|
||||||
|
disabled={row.original.type === "owner" || !PERMISSIONS.generateCode["owner"].includes(user.type)}>
|
||||||
|
Owner
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Popover.Panel>
|
||||||
|
</Transition>
|
||||||
|
</Popover>
|
||||||
|
)}
|
||||||
|
{!row.original.isVerified && PERMISSIONS.updateUser[row.original.type].includes(user.type) && (
|
||||||
|
<div data-tip="Verify User" className="cursor-pointer tooltip" onClick={() => verifyAccount(row.original)}>
|
||||||
|
<BsCheck className="hover:text-mti-purple-light transition ease-in-out duration-300" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{PERMISSIONS.updateUser[row.original.type].includes(user.type) && (
|
||||||
|
<div
|
||||||
|
data-tip={row.original.isDisabled ? "Enable User" : "Disable User"}
|
||||||
|
className="cursor-pointer tooltip"
|
||||||
|
onClick={() => toggleDisableAccount(row.original)}>
|
||||||
|
{row.original.isDisabled ? (
|
||||||
|
<BsCheckCircle className="hover:text-mti-purple-light transition ease-in-out duration-300" />
|
||||||
|
) : (
|
||||||
|
<BsFillExclamationOctagonFill className="hover:text-mti-purple-light transition ease-in-out duration-300" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{PERMISSIONS.deleteUser[row.original.type].includes(user.type) && (
|
||||||
|
<div data-tip="Delete" className="cursor-pointer tooltip" onClick={() => deleteAccount(row.original)}>
|
||||||
|
<BsTrash className="hover:text-mti-purple-light transition ease-in-out duration-300" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
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: (
|
||||||
|
<span className="cursor-pointer" onClick={() => setShowDemographicInformation((prev) => !prev)}>
|
||||||
|
Switch
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
id: "actions",
|
||||||
|
cell: actionColumn,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const defaultColumns = [
|
const defaultColumns = [
|
||||||
columnHelper.accessor("name", {
|
columnHelper.accessor("name", {
|
||||||
header: "Name",
|
header: "Name",
|
||||||
@@ -114,92 +234,19 @@ export default function UserList({user}: {user: User}) {
|
|||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
header: "",
|
header: (
|
||||||
|
<span className="cursor-pointer" onClick={() => setShowDemographicInformation((prev) => !prev)}>
|
||||||
|
Switch
|
||||||
|
</span>
|
||||||
|
),
|
||||||
id: "actions",
|
id: "actions",
|
||||||
cell: ({row}: {row: {original: User}}) => {
|
cell: actionColumn,
|
||||||
return (
|
|
||||||
<div className="flex gap-4">
|
|
||||||
{PERMISSIONS.updateUser[row.original.type].includes(user.type) && (
|
|
||||||
<Popover className="relative">
|
|
||||||
<Popover.Button>
|
|
||||||
<div data-tip="Change Type" className="cursor-pointer tooltip">
|
|
||||||
<BsPerson className="hover:text-mti-purple-light transition ease-in-out duration-300" />
|
|
||||||
</div>
|
|
||||||
</Popover.Button>
|
|
||||||
<Transition
|
|
||||||
as={Fragment}
|
|
||||||
enter="transition ease-out duration-200"
|
|
||||||
enterFrom="opacity-0 translate-y-1"
|
|
||||||
enterTo="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-in duration-150"
|
|
||||||
leaveFrom="opacity-100 translate-y-0"
|
|
||||||
leaveTo="opacity-0 translate-y-1">
|
|
||||||
<Popover.Panel className="absolute z-10 w-screen right-1/2 translate-x-1/3 max-w-sm">
|
|
||||||
<div className="bg-white p-4 rounded-lg grid grid-cols-2 gap-2 w-full drop-shadow-xl">
|
|
||||||
<Button
|
|
||||||
onClick={() => updateAccountType(row.original, "student")}
|
|
||||||
className="text-sm !py-2 !px-4"
|
|
||||||
disabled={
|
|
||||||
row.original.type === "student" || !PERMISSIONS.generateCode["student"].includes(user.type)
|
|
||||||
}>
|
|
||||||
Student
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => updateAccountType(row.original, "teacher")}
|
|
||||||
className="text-sm !py-2 !px-4"
|
|
||||||
disabled={
|
|
||||||
row.original.type === "teacher" || !PERMISSIONS.generateCode["teacher"].includes(user.type)
|
|
||||||
}>
|
|
||||||
Teacher
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => updateAccountType(row.original, "admin")}
|
|
||||||
className="text-sm !py-2 !px-4"
|
|
||||||
disabled={row.original.type === "admin" || !PERMISSIONS.generateCode["admin"].includes(user.type)}>
|
|
||||||
Admin
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => updateAccountType(row.original, "owner")}
|
|
||||||
className="text-sm !py-2 !px-4"
|
|
||||||
disabled={row.original.type === "owner" || !PERMISSIONS.generateCode["owner"].includes(user.type)}>
|
|
||||||
Owner
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</Popover.Panel>
|
|
||||||
</Transition>
|
|
||||||
</Popover>
|
|
||||||
)}
|
|
||||||
{!row.original.isVerified && PERMISSIONS.updateUser[row.original.type].includes(user.type) && (
|
|
||||||
<div data-tip="Verify User" className="cursor-pointer tooltip" onClick={() => verifyAccount(row.original)}>
|
|
||||||
<BsCheck className="hover:text-mti-purple-light transition ease-in-out duration-300" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{PERMISSIONS.updateUser[row.original.type].includes(user.type) && (
|
|
||||||
<div
|
|
||||||
data-tip={row.original.isDisabled ? "Enable User" : "Disable User"}
|
|
||||||
className="cursor-pointer tooltip"
|
|
||||||
onClick={() => toggleDisableAccount(row.original)}>
|
|
||||||
{row.original.isDisabled ? (
|
|
||||||
<BsCheckCircle className="hover:text-mti-purple-light transition ease-in-out duration-300" />
|
|
||||||
) : (
|
|
||||||
<BsFillExclamationOctagonFill className="hover:text-mti-purple-light transition ease-in-out duration-300" />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{PERMISSIONS.deleteUser[row.original.type].includes(user.type) && (
|
|
||||||
<div data-tip="Delete" className="cursor-pointer tooltip" onClick={() => deleteAccount(row.original)}>
|
|
||||||
<BsTrash className="hover:text-mti-purple-light transition ease-in-out duration-300" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
data: user.type === "admin" || user.type === "student" ? users.filter((u) => groups.flatMap((g) => g.participants).includes(u.id)) : users,
|
data: user.type === "admin" || user.type === "student" ? users.filter((u) => groups.flatMap((g) => g.participants).includes(u.id)) : users,
|
||||||
columns: defaultColumns,
|
columns: (!showDemographicInformation ? defaultColumns : demographicColumns) as any,
|
||||||
getCoreRowModel: getCoreRowModel(),
|
getCoreRowModel: getCoreRowModel(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user