Added more filters to the classroom

This commit is contained in:
Tiago Ribeiro
2024-10-17 22:41:20 +01:00
parent 4917583c67
commit 87d7d6f12b
7 changed files with 90 additions and 15 deletions

View File

@@ -8,7 +8,7 @@ import { EntityWithRoles } from "@/interfaces/entity";
import {GroupWithUsers, User} from "@/interfaces/user";
import {sessionOptions} from "@/lib/session";
import {USER_TYPE_LABELS} from "@/resources/user";
import { mapBy, redirect, serialize } from "@/utils";
import { filterBy, mapBy, redirect, serialize } from "@/utils";
import { requestUser } from "@/utils/api";
import { getEntitiesWithRoles, getEntityWithRoles } from "@/utils/entities.be";
import {convertToUsers, getGroup} from "@/utils/groups.be";
@@ -19,6 +19,7 @@ import {getEntityUsers, getLinkedUsers, getSpecificUsers} from "@/utils/users.be
import axios from "axios";
import clsx from "clsx";
import {withIronSessionSsr} from "iron-session/next";
import { capitalize } from "lodash";
import moment from "moment";
import Head from "next/head";
import Link from "next/link";
@@ -84,8 +85,6 @@ export default function Home({user, group, users, entity}: Props) {
const router = useRouter();
const allowGroupEdit = useMemo(() => checkAccess(user, ["admin", "developer", "mastercorporate"]) || user.id === group.admin.id, [user, group]);
const toggleUser = (u: User) => setSelectedUsers((prev) => (prev.includes(u.id) ? prev.filter((p) => p !== u.id) : [...prev, u.id]));
const removeParticipants = () => {
@@ -263,6 +262,31 @@ export default function Home({user, group, users, entity}: Props) {
{renderSearch()}
{renderMinimal()}
</div>
<div className="flex items-center gap-2 mt-4">
{['student', 'teacher', 'corporate'].map((type) => (
<button
key={type}
onClick={() => {
const typeUsers = mapBy(filterBy(isAdding ? nonParticipantUsers : group.participants, 'type', type), 'id')
if (typeUsers.every((u) => selectedUsers.includes(u))) {
setSelectedUsers((prev) => prev.filter((a) => !typeUsers.includes(a)));
} else {
setSelectedUsers((prev) => [...prev.filter((a) => !typeUsers.includes(a)), ...typeUsers]);
}
}}
disabled={filterBy(isAdding ? nonParticipantUsers : group.participants, 'type', type).length === 0}
className={clsx(
"bg-mti-purple-ultralight text-mti-purple px-4 py-2 rounded-full hover:text-white hover:bg-mti-purple-light",
"transition duration-300 ease-in-out",
"disabled:grayscale disabled:hover:bg-mti-purple-ultralight disabled:hover:text-mti-purple disabled:cursor-not-allowed",
filterBy(isAdding ? nonParticipantUsers : group.participants, 'type', type).length > 0 &&
filterBy(isAdding ? nonParticipantUsers : group.participants, 'type', type).every((u) => selectedUsers.includes(u.id)) &&
"!bg-mti-purple-light !text-white",
)}>
{capitalize(type)}
</button>
))}
</div>
</section>
<section className="w-full h-full grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">

View File

@@ -12,7 +12,7 @@ import {USER_TYPE_LABELS} from "@/resources/user";
import {filterBy, mapBy, redirect, serialize} from "@/utils";
import {getEntities, getEntitiesWithRoles} from "@/utils/entities.be";
import {shouldRedirectHome} from "@/utils/navigation.disabled";
import {getUserName} from "@/utils/users";
import {getUserName, isAdmin} from "@/utils/users";
import {getEntitiesUsers, getLinkedUsers} from "@/utils/users.be";
import axios from "axios";
import clsx from "clsx";
@@ -22,11 +22,12 @@ import Head from "next/head";
import Link from "next/link";
import {useRouter} from "next/router";
import {Divider} from "primereact/divider";
import {useMemo, useState} from "react";
import {useEffect, useMemo, useState} from "react";
import {BsCheck, BsChevronLeft, BsClockFill, BsEnvelopeFill, BsStopwatchFill} from "react-icons/bs";
import {toast, ToastContainer} from "react-toastify";
import { requestUser } from "@/utils/api";
import { findAllowedEntities } from "@/utils/permissions";
import { capitalize } from "lodash";
export const getServerSideProps = withIronSessionSsr(async ({req, res}) => {
const user = await requestUser(req, res)
@@ -34,8 +35,8 @@ export const getServerSideProps = withIronSessionSsr(async ({req, res}) => {
if (shouldRedirectHome(user)) return redirect("/")
const users = await getEntitiesUsers(mapBy(user.entities, 'id'))
const entities = await getEntitiesWithRoles(mapBy(user.entities, "id"));
const entities = await getEntitiesWithRoles(isAdmin(user) ? undefined : mapBy(user.entities, "id"));
const users = await getEntitiesUsers(mapBy(entities, 'id'))
const allowedEntities = findAllowedEntities(user, entities, "create_classroom")
return {
@@ -57,11 +58,16 @@ export default function Home({user, users, entities}: Props) {
const entityUsers = useMemo(() => !entity ? users : users.filter(u => mapBy(u.entities, 'id').includes(entity)), [entity, users])
const {rows, renderSearch} = useListSearch<User>([["name"], ["corporateInformation", "companyInformation", "name"]], entityUsers);
const {rows, renderSearch} = useListSearch<User>(
[["name"], ["type"], ["corporateInformation", "companyInformation", "name"]], entityUsers
);
const {items, renderMinimal} = usePagination<User>(rows, 16);
const router = useRouter();
useEffect(() => setSelectedUsers([]), [entity])
const createGroup = () => {
if (!name.trim()) return;
if (!entity) return;
@@ -140,6 +146,31 @@ export default function Home({user, users, entities}: Props) {
{renderSearch()}
{renderMinimal()}
</div>
<div className="flex items-center gap-2 mt-4">
{['student', 'teacher', 'corporate'].map((type) => (
<button
key={type}
onClick={() => {
const typeUsers = mapBy(filterBy(entityUsers, 'type', type), 'id')
if (typeUsers.every((u) => selectedUsers.includes(u))) {
setSelectedUsers((prev) => prev.filter((a) => !typeUsers.includes(a)));
} else {
setSelectedUsers((prev) => [...prev.filter((a) => !typeUsers.includes(a)), ...typeUsers]);
}
}}
disabled={filterBy(entityUsers, 'type', type).length === 0}
className={clsx(
"bg-mti-purple-ultralight text-mti-purple px-4 py-2 rounded-full hover:text-white hover:bg-mti-purple-light",
"transition duration-300 ease-in-out",
"disabled:grayscale disabled:hover:bg-mti-purple-ultralight disabled:hover:text-mti-purple disabled:cursor-not-allowed",
filterBy(entityUsers, 'type', type).length > 0 &&
filterBy(entityUsers, 'type', type).every((u) => selectedUsers.includes(u.id)) &&
"!bg-mti-purple-light !text-white",
)}>
{capitalize(type)}
</button>
))}
</div>
</section>
<section className="w-full h-full grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">

View File

@@ -6,7 +6,7 @@ import {ToastContainer} from "react-toastify";
import Layout from "@/components/High/Layout";
import {GroupWithUsers, User} from "@/interfaces/user";
import {shouldRedirectHome} from "@/utils/navigation.disabled";
import {getUserName} from "@/utils/users";
import {getUserName, isAdmin} from "@/utils/users";
import {convertToUsers, getGroupsForEntities} from "@/utils/groups.be";
import {getSpecificUsers} from "@/utils/users.be";
import Link from "next/link";
@@ -28,7 +28,7 @@ export const getServerSideProps = withIronSessionSsr(async ({req, res}) => {
if (shouldRedirectHome(user)) return redirect("/")
const entityIDS = mapBy(user.entities, "id");
const entities = await getEntitiesWithRoles(entityIDS)
const entities = await getEntitiesWithRoles(isAdmin(user) ? undefined : entityIDS)
const allowedEntities = findAllowedEntities(user, entities, "view_classrooms")
const groups = await getGroupsForEntities(mapBy(allowedEntities, 'id'));