ENCOA-267

This commit is contained in:
Tiago Ribeiro
2024-12-23 10:18:52 +00:00
parent 9cf13e3f26
commit e9c961e633
6 changed files with 157 additions and 142 deletions

View File

@@ -8,163 +8,166 @@ import useGroups from "@/hooks/useGroups";
import useRecordStore from "@/stores/recordStore";
import { EntityWithRoles } from "@/interfaces/entity";
import { mapBy } from "@/utils";
import { useAllowedEntities } from "@/hooks/useEntityPermissions";
type TimeFilter = "months" | "weeks" | "days";
type Filter = TimeFilter | "assignments" | undefined;
interface Props {
user: User;
entities: EntityWithRoles[]
users: User[]
filterState: {
filter: Filter,
setFilter: React.Dispatch<React.SetStateAction<Filter>>
},
assignments?: boolean;
children?: ReactNode
user: User;
entities: EntityWithRoles[]
users: User[]
filterState: {
filter: Filter,
setFilter: React.Dispatch<React.SetStateAction<Filter>>
},
assignments?: boolean;
children?: ReactNode
}
const defaultSelectableCorporate = {
value: "",
label: "All",
value: "",
label: "All",
};
const RecordFilter: React.FC<Props> = ({
user,
entities,
users,
filterState,
assignments = true,
children
user,
entities,
users,
filterState,
assignments = true,
children
}) => {
const { filter, setFilter } = filterState;
const { filter, setFilter } = filterState;
const [entity, setEntity] = useState<string>()
const [entity, setEntity] = useState<string>()
const [, setStatsUserId] = useRecordStore((state) => [
state.selectedUser,
state.setSelectedUser
]);
const [, setStatsUserId] = useRecordStore((state) => [
state.selectedUser,
state.setSelectedUser
]);
const entityUsers = useMemo(() => !entity ? users : users.filter(u => mapBy(u.entities, 'id').includes(entity)), [users, entity])
const allowedViewEntities = useAllowedEntities(user, entities, 'view_student_record')
useEffect(() => setStatsUserId(user.id), [setStatsUserId, user.id])
const entityUsers = useMemo(() => !entity ? users : users.filter(u => mapBy(u.entities, 'id').includes(entity)), [users, entity])
const toggleFilter = (value: "months" | "weeks" | "days" | "assignments") => {
setFilter((prev) => (prev === value ? undefined : value));
};
useEffect(() => setStatsUserId(user.id), [setStatsUserId, user.id])
return (
<div className="w-full flex -xl:flex-col -xl:gap-4 justify-between items-center">
<div className="xl:w-3/4 flex gap-2">
{checkAccess(user, ["developer", "admin", "mastercorporate"]) && !children && (
<>
<div className="flex flex-col gap-2 w-full">
<label className="font-normal text-base text-mti-gray-dim">Entity</label>
const toggleFilter = (value: "months" | "weeks" | "days" | "assignments") => {
setFilter((prev) => (prev === value ? undefined : value));
};
<Select
options={entities.map((e) => ({value: e.id, label: e.label}))}
onChange={(value) => setEntity(value?.value || undefined)}
isClearable
styles={{
menuPortal: (base) => ({ ...base, zIndex: 9999 }),
option: (styles, state) => ({
...styles,
backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white",
color: state.isFocused ? "black" : styles.color,
}),
}} />
</div>
<div className="flex flex-col gap-2 w-full">
<label className="font-normal text-base text-mti-gray-dim">User</label>
return (
<div className="w-full flex -xl:flex-col -xl:gap-4 justify-between items-center">
<div className="xl:w-3/4 flex gap-2">
{checkAccess(user, ["developer", "admin", "mastercorporate"]) && !children && (
<>
<div className="flex flex-col gap-2 w-full">
<label className="font-normal text-base text-mti-gray-dim">Entity</label>
<Select
options={entityUsers.map((x) => ({
value: x.id,
label: `${x.name} - ${x.email}`,
}))}
defaultValue={{value: user.id, label: `${user.name} - ${user.email}`}}
onChange={(value) => setStatsUserId(value?.value!)}
styles={{
menuPortal: (base) => ({ ...base, zIndex: 9999 }),
option: (styles, state) => ({
...styles,
backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white",
color: state.isFocused ? "black" : styles.color,
}),
}}
/>
</div>
</>
)}
{(user.type === "corporate" || user.type === "teacher") && !children && (
<div className="flex flex-col gap-2">
<label className="font-normal text-base text-mti-gray-dim">User</label>
<Select
options={allowedViewEntities.map((e) => ({ value: e.id, label: e.label }))}
onChange={(value) => setEntity(value?.value || undefined)}
isClearable
styles={{
menuPortal: (base) => ({ ...base, zIndex: 9999 }),
option: (styles, state) => ({
...styles,
backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white",
color: state.isFocused ? "black" : styles.color,
}),
}} />
</div>
<div className="flex flex-col gap-2 w-full">
<label className="font-normal text-base text-mti-gray-dim">User</label>
<Select
options={users
.map((x) => ({
value: x.id,
label: `${x.name} - ${x.email}`,
}))}
defaultValue={{value: user.id, label: `${user.name} - ${user.email}`}}
onChange={(value) => setStatsUserId(value?.value!)}
styles={{
menuPortal: (base) => ({ ...base, zIndex: 9999 }),
option: (styles, state) => ({
...styles,
backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white",
color: state.isFocused ? "black" : styles.color,
}),
}}
/>
</div>
)}
{children}
</div>
<div className="flex gap-4 w-full justify-center xl:justify-end">
{assignments && (
<button
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",
filter === "assignments" && "!bg-mti-purple-light !text-white",
)}
onClick={() => toggleFilter("assignments")}>
Assignments
</button>
)}
<button
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",
filter === "months" && "!bg-mti-purple-light !text-white",
)}
onClick={() => toggleFilter("months")}>
Last month
</button>
<button
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",
filter === "weeks" && "!bg-mti-purple-light !text-white",
)}
onClick={() => toggleFilter("weeks")}>
Last week
</button>
<button
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",
filter === "days" && "!bg-mti-purple-light !text-white",
)}
onClick={() => toggleFilter("days")}>
Last day
</button>
</div>
</div>
);
<Select
options={entityUsers.map((x) => ({
value: x.id,
label: `${x.name} - ${x.email}`,
}))}
defaultValue={{ value: user.id, label: `${user.name} - ${user.email}` }}
onChange={(value) => setStatsUserId(value?.value!)}
styles={{
menuPortal: (base) => ({ ...base, zIndex: 9999 }),
option: (styles, state) => ({
...styles,
backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white",
color: state.isFocused ? "black" : styles.color,
}),
}}
/>
</div>
</>
)}
{(user.type === "corporate" || user.type === "teacher") && !children && (
<div className="flex flex-col gap-2">
<label className="font-normal text-base text-mti-gray-dim">User</label>
<Select
options={users
.map((x) => ({
value: x.id,
label: `${x.name} - ${x.email}`,
}))}
defaultValue={{ value: user.id, label: `${user.name} - ${user.email}` }}
onChange={(value) => setStatsUserId(value?.value!)}
styles={{
menuPortal: (base) => ({ ...base, zIndex: 9999 }),
option: (styles, state) => ({
...styles,
backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white",
color: state.isFocused ? "black" : styles.color,
}),
}}
/>
</div>
)}
{children}
</div>
<div className="flex gap-4 w-full justify-center xl:justify-end">
{assignments && (
<button
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",
filter === "assignments" && "!bg-mti-purple-light !text-white",
)}
onClick={() => toggleFilter("assignments")}>
Assignments
</button>
)}
<button
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",
filter === "months" && "!bg-mti-purple-light !text-white",
)}
onClick={() => toggleFilter("months")}>
Last month
</button>
<button
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",
filter === "weeks" && "!bg-mti-purple-light !text-white",
)}
onClick={() => toggleFilter("weeks")}>
Last week
</button>
<button
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",
filter === "days" && "!bg-mti-purple-light !text-white",
)}
onClick={() => toggleFilter("days")}>
Last day
</button>
</div>
</div>
);
}
export default RecordFilter;

View File

@@ -82,7 +82,7 @@ interface StatsGridItemProps {
selectedTrainingExams?: string[];
maxTrainingExams?: number;
setSelectedTrainingExams?: React.Dispatch<React.SetStateAction<string[]>>;
renderPdfIcon: (session: string, color: string, textColor: string) => React.ReactNode;
renderPdfIcon?: (session: string, color: string, textColor: string) => React.ReactNode;
}
const StatsGridItem: React.FC<StatsGridItemProps> = ({
@@ -236,7 +236,7 @@ const StatsGridItem: React.FC<StatsGridItemProps> = ({
{renderLevelScore()}
</span>
)}
{shouldRenderPDFIcon() && renderPdfIcon(session, textColor, textColor)}
{shouldRenderPDFIcon() && renderPdfIcon && renderPdfIcon(session, textColor, textColor)}
</div>
{examNumber === undefined ? (
<>