Skip to content
Snippets Groups Projects
Verified Commit 873c28ee authored by Sivert Kronen Hatteberg's avatar Sivert Kronen Hatteberg
Browse files

Add sorting for each column on the sponsor frontpage

parent b78ea391
No related branches found
No related tags found
1 merge request!385Add sorting for each column on the sponsor frontpage
Pipeline #179653 passed
......@@ -13,6 +13,7 @@ import {
TableContainer,
TableHead,
TableRow,
TableSortLabel,
TextField,
Typography,
} from '@mui/material'
......@@ -54,6 +55,14 @@ interface FrontPageProps {
loading: boolean
}
type SortDirection = 'desc' | 'asc'
type SortField = 'name' | 'role' | 'status' | 'endDate' | 'department'
interface GuestRole {
guest: Guest
role: Role
}
const StyledTableRow = styled(TableRow)({
borderTop: '0',
borderLeft: '0',
......@@ -172,22 +181,65 @@ const Status = ({ person, role }: StatusProps) => {
}
}
const sortByDate = (
guestRole: { guest: Guest; role: Role }[]
): { guest: Guest; role: Role }[] =>
guestRole.sort(
(a, b) => a.role.end_date.getTime() - b.role.end_date.getTime()
function createGuestsRoles(guests: Guest[]): GuestRole[] {
const guestRoles: GuestRole[] = []
guests.forEach((guest) =>
guest.roles.forEach((role) => {
guestRoles.push({ guest, role })
})
)
return guestRoles
}
function sortByName(
guestA: Guest,
guestB: Guest,
direction: SortDirection
): number {
const firstA = guestA.first.toLowerCase()
const firstB = guestB.first.toLowerCase()
if (firstA < firstB) {
return direction === 'asc' ? -1 : 1
}
if (firstA > firstB) {
return direction === 'asc' ? 1 : -1
}
return 0
}
function sortGuestsByName(guests: Guest[], direction: SortDirection) {
return createGuestsRoles(guests).sort((a, b) =>
sortByName(a.guest, b.guest, direction)
)
}
function sortGuestRolesByEndDate(
guestRole: GuestRole[],
direction: SortDirection
): GuestRole[] {
return guestRole.sort((a, b) => {
const aEndDate = a.role.end_date.getTime()
const bEndDate = b.role.end_date.getTime()
if (aEndDate < bEndDate) {
return direction === 'asc' ? -1 : 1
}
if (aEndDate > bEndDate) {
return direction === 'asc' ? 1 : -1
}
// Secondary sort on guest name, always asc
return sortByName(a.guest, b.guest, 'asc')
})
}
const sortByStatus = (guests: Guest[]): { guest: Guest; role: Role }[] => {
function sortByStatus(guests: Guest[], direction: SortDirection): GuestRole[] {
let activeRoleAndPerson: { guest: Guest; role: Role }[] = []
let expiringRoleAndPerson: { guest: Guest; role: Role }[] = []
let expiredRoleAndPerson: { guest: Guest; role: Role }[] = []
let status
guests.forEach((guest) =>
guest.roles.forEach((role) => {
;[status] = calculateStatus(guest, role)
const [status] = calculateStatus(guest, role)
if (status === 'active') {
activeRoleAndPerson.push({ guest, role })
} else if (status === 'expiring') {
......@@ -198,13 +250,71 @@ const sortByStatus = (guests: Guest[]): { guest: Guest; role: Role }[] => {
})
)
activeRoleAndPerson = sortByDate(activeRoleAndPerson)
expiringRoleAndPerson = sortByDate(expiringRoleAndPerson)
expiredRoleAndPerson = sortByDate(expiredRoleAndPerson)
// Always use 'asc' for secondary sorting
activeRoleAndPerson = sortGuestRolesByEndDate(activeRoleAndPerson, 'asc')
expiringRoleAndPerson = sortGuestRolesByEndDate(expiringRoleAndPerson, 'asc')
expiredRoleAndPerson = sortGuestRolesByEndDate(expiredRoleAndPerson, 'asc')
return expiringRoleAndPerson
if (direction === 'asc') {
return expiringRoleAndPerson
.concat(activeRoleAndPerson)
.concat(expiredRoleAndPerson)
}
return expiredRoleAndPerson
.concat(activeRoleAndPerson)
.concat(expiredRoleAndPerson)
.concat(expiringRoleAndPerson)
}
function sortGuestsByRoleName(guests: Guest[], direction: SortDirection) {
return createGuestsRoles(guests).sort((a, b) => {
const aRoleName = getRoleName(a.role).toLowerCase()
const bRoleName = getRoleName(b.role).toLowerCase()
if (aRoleName < bRoleName) {
return direction === 'asc' ? -1 : 1
}
if (aRoleName > bRoleName) {
return direction === 'asc' ? 1 : -1
}
// Secondary sort on guest name, always asc
return sortByName(a.guest, b.guest, 'asc')
})
}
function sortGuestsByDepartmentName(guests: Guest[], direction: SortDirection) {
return createGuestsRoles(guests).sort((a, b) => {
const aRoleOUName = getRoleOuName(a.role).toLowerCase()
const bRoleOUName = getRoleOuName(b.role).toLowerCase()
if (aRoleOUName < bRoleOUName) {
return direction === 'asc' ? -1 : 1
}
if (aRoleOUName > bRoleOUName) {
return direction === 'asc' ? 1 : -1
}
// Secondary sort on guest name, always asc
return sortByName(a.guest, b.guest, 'asc')
})
}
function sortGuestsAndRoles(
guests: Guest[],
sortField: SortField,
direction: SortDirection
): { guest: Guest; role: Role }[] {
switch (sortField) {
case 'department':
return sortGuestsByDepartmentName(guests, direction)
case 'endDate':
return sortGuestRolesByEndDate(createGuestsRoles(guests), direction)
case 'name':
return sortGuestsByName(guests, direction)
case 'role':
return sortGuestsByRoleName(guests, direction)
case 'status':
return sortByStatus(guests, direction)
default:
// Fallback to original sort
return createGuestsRoles(guests)
}
}
const PersonLine = ({ person, role }: PersonLineProps) => {
......@@ -236,6 +346,17 @@ const PersonLine = ({ person, role }: PersonLineProps) => {
const GuestTable = ({ guests, emptyText, marginWidth }: GuestTableProps) => {
const { t } = useTranslation('common')
const [direction, setDirection] = useState<SortDirection>('asc')
const [orderBy, setOrderBy] = useState<SortField>('status')
const handleRequestSort =
(sortBy: SortField) => (event: React.MouseEvent<unknown>) => {
event.preventDefault()
const isAsc = orderBy === sortBy && direction === 'asc'
setDirection(isAsc ? 'desc' : 'asc')
setOrderBy(sortBy)
}
return (
<TableContainer
component={Paper}
......@@ -248,17 +369,63 @@ const GuestTable = ({ guests, emptyText, marginWidth }: GuestTableProps) => {
<Table sx={{ minWidth: marginWidth }} aria-label="simple table">
<StyledTableHead>
<TableRow>
<StyledTableHeadCell>{t('common:name')}</StyledTableHeadCell>
<StyledTableHeadCell>{t('common:role')}</StyledTableHeadCell>
<StyledTableHeadCell>{t('common:status')}</StyledTableHeadCell>
<StyledTableHeadCell>{t('common:endDate')}</StyledTableHeadCell>
<StyledTableHeadCell>{t('common:department')}</StyledTableHeadCell>
<StyledTableHeadCell>
<TableSortLabel
key="name"
active={orderBy === 'name'}
direction={orderBy === 'name' ? direction : 'asc'}
onClick={handleRequestSort('name')}
>
{t('common:name')}
</TableSortLabel>
</StyledTableHeadCell>
<StyledTableHeadCell>
<TableSortLabel
key="role"
active={orderBy === 'role'}
direction={orderBy === 'role' ? direction : 'asc'}
onClick={handleRequestSort('role')}
>
{t('common:role')}
</TableSortLabel>
</StyledTableHeadCell>
<StyledTableHeadCell>
<TableSortLabel
key="status"
active={orderBy === 'status'}
direction={orderBy === 'status' ? direction : 'asc'}
onClick={handleRequestSort('status')}
>
{t('common:status')}
</TableSortLabel>
</StyledTableHeadCell>
<StyledTableHeadCell>
<TableSortLabel
key="endDate"
active={orderBy === 'endDate'}
direction={orderBy === 'endDate' ? direction : 'asc'}
onClick={handleRequestSort('endDate')}
>
{t('common:endDate')}
</TableSortLabel>
</StyledTableHeadCell>
<StyledTableHeadCell>
<TableSortLabel
key="department"
active={orderBy === 'department'}
direction={orderBy === 'department' ? direction : 'asc'}
onClick={handleRequestSort('department')}
>
{t('common:department')}
</TableSortLabel>
</StyledTableHeadCell>
<StyledTableHeadCell />
</TableRow>
</StyledTableHead>
<TableBody>
{guests.length > 0 ? (
sortByStatus(guests).map((personRole) => (
sortGuestsAndRoles(guests, orderBy, direction).map((personRole) => (
<PersonLine
key={`${personRole.guest.first} ${personRole.guest.last} ${personRole.role.id}`}
role={personRole.role}
......@@ -267,7 +434,7 @@ const GuestTable = ({ guests, emptyText, marginWidth }: GuestTableProps) => {
))
) : (
<StyledTableRow>
<TableCell> {emptyText}</TableCell>
<TableCell>{emptyText}</TableCell>
</StyledTableRow>
)}
</TableBody>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment