From 6a7dd74e525570d274515e1b90ec4e2235515e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eik=20Hvattum=20R=C3=B8geberg?= Date: Sat, 25 Jan 2025 08:27:18 +0100 Subject: [PATCH 1/2] Add group filters to attendance modal --- .../AttendanceModalContent.module.css | 24 ++++++ .../UserAttendance/AttendanceModalContent.tsx | 48 ++++++++--- app/components/UserAttendance/GroupFilter.tsx | 85 +++++++++++++++++++ 3 files changed, 144 insertions(+), 13 deletions(-) create mode 100644 app/components/UserAttendance/GroupFilter.tsx diff --git a/app/components/UserAttendance/AttendanceModalContent.module.css b/app/components/UserAttendance/AttendanceModalContent.module.css index 5da826a313..40ddc9f0b3 100644 --- a/app/components/UserAttendance/AttendanceModalContent.module.css +++ b/app/components/UserAttendance/AttendanceModalContent.module.css @@ -124,3 +124,27 @@ transition: opacity var(--linear-fast); opacity: 0.4; } + +.groupFilters { + position: relative; + flex-shrink: 0; + overflow: hidden; +} + +.collapsedIndicator { + position: absolute; + right: 0; + left: 0; + bottom: 0; + height: 50%; + background: linear-gradient(to bottom, transparent, var(--color-white) 90%); +} + +.groupFilterButton { + cursor: pointer; + + &.selected { + background-color: var(--lego-font-color); + color: var(--inverted-font-color); + } +} diff --git a/app/components/UserAttendance/AttendanceModalContent.tsx b/app/components/UserAttendance/AttendanceModalContent.tsx index 47aa06299d..09cbf6f6d3 100644 --- a/app/components/UserAttendance/AttendanceModalContent.tsx +++ b/app/components/UserAttendance/AttendanceModalContent.tsx @@ -2,18 +2,22 @@ import { Flex } from '@webkom/lego-bricks'; import cx from 'classnames'; import { flatMap } from 'lodash'; import { Send } from 'lucide-react'; -import { useState, useMemo } from 'react'; +import { useMemo, useState } from 'react'; import { Link } from 'react-router-dom'; import { TextInput } from 'app/components/Form'; import { ProfilePicture } from 'app/components/Image'; +import { GroupFilter } from 'app/components/UserAttendance/GroupFilter'; import EmptyState from '../EmptyState'; import styles from './AttendanceModalContent.module.css'; import type { EntityId } from '@reduxjs/toolkit'; -import type { PublicUser } from 'app/store/models/User'; +import type { + PublicUser, + PublicUserWithAbakusGroups, +} from 'app/store/models/User'; export type AttendanceModalRegistration = { id: EntityId; - user: PublicUser; + user: PublicUser | PublicUserWithAbakusGroups; pool?: EntityId; }; @@ -66,18 +70,28 @@ const AttendanceModalContent = ({ selectedPool, isMeeting, }: Props) => { - const [filter, setFilter] = useState(''); + const [search, setSearch] = useState(''); + const [groupFilter, setGroupFilter] = useState(null); const amendedPools = useMemo(() => generateAmendedPools(pools), [pools]); const registrations = useMemo( + () => amendedPools[selectedPool]?.registrations, + [amendedPools, selectedPool], + ); + + const filteredRegistrations = useMemo( () => - amendedPools[selectedPool]?.registrations.filter((registration) => { - return registration.user.fullName - .toLowerCase() - .includes(filter.toLowerCase()); - }), - [filter, amendedPools, selectedPool], + registrations.filter( + (registration) => + registration.user.fullName + .toLowerCase() + .includes(search.toLowerCase()) && + (groupFilter && 'abakusGroups' in registration.user + ? registration.user.abakusGroups.includes(groupFilter) + : true), + ), + [registrations, search, groupFilter], ); return ( @@ -86,13 +100,21 @@ const AttendanceModalContent = ({ type="text" prefix="search" placeholder="Søk etter navn" - onChange={(e) => setFilter(e.target.value)} + onChange={(e) => setSearch(e.target.value)} className={styles.searchInput} /> + {!isMeeting && ( + + )} +
    - {registrations.length > 0 ? ( - registrations?.map((registration) => ( + {filteredRegistrations.length > 0 ? ( + filteredRegistrations?.map((registration) => (
  • void; +}; + +export const GroupFilter = ({ + registrations, + groupFilter, + setGroupFilter, +}: Props) => { + const currentUser = useAppSelector(selectCurrentUser); + const allGroups = useAppSelector(selectAllGroups); + const [hovered, setHovered] = useState(false); + const expanded = hovered || groupFilter !== null; + + const topGroups = useMemo( + () => + allGroups + .filter( + (group) => + currentUser?.abakusGroups.includes(group.id) && + !excludeFilterGroups.includes(group.id), + ) + .map( + (group) => + [ + group, + registrations.filter( + (reg) => + 'abakusGroups' in reg.user && + reg.user.abakusGroups.includes(group.id), + ).length, + ] as const, + ) + .sort((a, b) => b[1] - a[1]), + [allGroups, currentUser?.abakusGroups, registrations], + ); + + return ( + setHovered(true)} + onMouseLeave={() => setHovered(false)} + > + {topGroups.map(([group]) => ( + + groupFilter === group.id + ? setGroupFilter(null) + : setGroupFilter(group.id) + } + className={cx( + styles.groupFilterButton, + groupFilter === group.id && styles.selected, + )} + > + {group.name} + + ))} + {!expanded &&
    } + + ); +}; From b2cde4720458994e3be8009b3ef18b9d6a61dbfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eik=20Hvattum=20R=C3=B8geberg?= Date: Tue, 28 Jan 2025 12:56:32 +0100 Subject: [PATCH 2/2] Add excluded groups in attendance groupfilter Co-authored-by: Falk Elvedal Bruskeland <66320400+falbru@users.noreply.github.com> --- app/components/UserAttendance/GroupFilter.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/components/UserAttendance/GroupFilter.tsx b/app/components/UserAttendance/GroupFilter.tsx index c987e4a270..f081015a06 100644 --- a/app/components/UserAttendance/GroupFilter.tsx +++ b/app/components/UserAttendance/GroupFilter.tsx @@ -13,6 +13,10 @@ const excludeFilterGroups: EntityId[] = [ 1, // Users 2, // Abakus 47, // Formaterte + 227, // Baksida-Komite + 228, // Baksida-Revy + 92, // Kasserere + 242, // Klassetillitsvalgt ]; type Props = {