diff --git a/frontend/components/ClubEditPage/EventsCard.tsx b/frontend/components/ClubEditPage/EventsCard.tsx index e0acc1feb..b8fbaf946 100644 --- a/frontend/components/ClubEditPage/EventsCard.tsx +++ b/frontend/components/ClubEditPage/EventsCard.tsx @@ -1,7 +1,6 @@ import { Field } from 'formik' import moment from 'moment' import React, { ReactElement, useState } from 'react' -import CreatableSelect from 'react-select/creatable' import TimeAgo from 'react-timeago' import styled from 'styled-components' @@ -297,7 +296,22 @@ const eventTableFields = [ { name: 'is_ics_event', label: 'ICS', - converter: (a: boolean): ReactElement => , + converter: (a: boolean): ReactElement => ( + + ), + }, +] + +const eventTableFilter = [ + { + label: 'Types', + options: EVENT_TYPES.map((obj) => { + return { key: obj.value, label: obj.label } + }), + filterFunction: (selection, object) => object.type === selection, }, ] @@ -343,12 +357,6 @@ const eventFields = ( placeholder="Type your event description here!" as={RichTextField} /> - ) @@ -415,6 +423,7 @@ export default function EventsCard({ club }: EventsCardProps): ReactElement { fields={eventFields} fileFields={['image']} tableFields={eventTableFields} + filterOptions={eventTableFilter} noun="Event" currentTitle={(obj) => (obj != null ? obj.name : 'Deleted Event')} onChange={(obj) => { diff --git a/frontend/components/ClubEditPage/MembersCard.tsx b/frontend/components/ClubEditPage/MembersCard.tsx index 74d1585e8..a50937225 100644 --- a/frontend/components/ClubEditPage/MembersCard.tsx +++ b/frontend/components/ClubEditPage/MembersCard.tsx @@ -95,7 +95,16 @@ export default function MembersCard({ club }: MembersCardProps): ReactElement { ], filterFunction: (selection, object) => object.role === selection, }, + { + label: 'Active', + options: [ + { key: true, label: 'Active' }, + { key: false, label: 'Inactive' }, + ], + filterFunction: (selection, object) => object.active === selection, + }, ]} + searchableColumns={['name', 'email']} currentTitle={(obj) => obj != null ? `${obj.name} (${obj.email})` : 'Kicked Member' } diff --git a/frontend/components/ModelForm.tsx b/frontend/components/ModelForm.tsx index f76248bff..80c9ee12a 100644 --- a/frontend/components/ModelForm.tsx +++ b/frontend/components/ModelForm.tsx @@ -74,6 +74,7 @@ type ModelFormProps = { fields: any tableFields?: TableField[] filterOptions?: FilterOption[] + searchableColumns?: string[] currentTitle?: (object: ModelObject) => ReactElement | string noun?: string deleteVerb?: string @@ -111,6 +112,7 @@ export const doFormikInitialValueFixes = (currentObject: { type ModelTableProps = { tableFields: TableField[] filterOptions?: FilterOption[] + searchableColumns?: string[] objects: ModelObject[] allowEditing?: boolean allowDeletion?: boolean @@ -130,6 +132,7 @@ type ModelTableProps = { export const ModelTable = ({ tableFields, filterOptions, + searchableColumns, objects, allowEditing = false, allowDeletion = false, @@ -150,16 +153,16 @@ export const ModelTable = ({ })), [tableFields], ) - tableFields = tableFields.map((column, index) => { if (column.converter) { const renderFunction = column.converter return { ...column, - render: (id, _) => { - const obj = objects?.[id] + render: (id) => { + const obj = + objects?.filter((item) => item.id === id)[0] || objects?.[id] const value = obj?.[column.name] - return obj && value ? renderFunction(value, obj) : 'N/A' + return obj && value !== null ? renderFunction(value, obj) : 'None' }, } } else return column @@ -215,7 +218,9 @@ export const ModelTable = ({ field.name) + } filterOptions={filterOptions || []} draggable={draggable} onDragEnd={onDragEnd} @@ -255,6 +260,7 @@ export const ModelForm = (props: ModelFormProps): ReactElement => { fields, tableFields, filterOptions, + searchableColumns, onUpdate, currentTitle, noun = 'Object', @@ -464,6 +470,7 @@ export const ModelForm = (props: ModelFormProps): ReactElement => { noun={noun} tableFields={tableFields} filterOptions={filterOptions} + searchableColumns={searchableColumns} objects={objects} allowDeletion={allowDeletion} confirmDeletion={confirmDeletion} diff --git a/frontend/components/PaginatedClubDisplay.tsx b/frontend/components/PaginatedClubDisplay.tsx index d65bb35a5..db61b9519 100644 --- a/frontend/components/PaginatedClubDisplay.tsx +++ b/frontend/components/PaginatedClubDisplay.tsx @@ -101,7 +101,7 @@ const PaginatedClubDisplay = ({ /> )} {isLoading && } - {clubs && clubs.length <= 0 && ( + {(clubs == null || clubs.length <= 0) && ( ('') const [tableData, setTableData] = useState([]) const [selectedFilter, setSelectedFilter] = useState({}) + const [sortedColumn, setSortedColumn] = useState(null) useEffect(() => { const searchedData = data.filter((item) => { if (!searchQuery || searchQuery.length < 3) { return true } return searchableColumns.some((searchId) => { - const strings = item[searchId].split(' ') - return strings.some((string) => - string.toLowerCase().startsWith(searchQuery.toLowerCase()), - ) + if (typeof item[searchId] === 'string') { + const strings = item[searchId].split(' ') + return strings.some((string) => + string.toLowerCase().startsWith(searchQuery.toLowerCase()), + ) + } + return false }) }) const filteredData = searchedData.filter((item) => { @@ -216,6 +224,18 @@ const Table = ({ setSearchQuery(e.target.value) } + const handleColumnsSort = (target) => { + if (sortedColumn && sortedColumn.name === target) { + if (sortedColumn.status === 'asc') { + setSortedColumn({ name: target, status: 'desc' }) + } else { + setSortedColumn(null) + } + } else { + setSortedColumn({ name: target, status: 'asc' }) + } + } + const components = { IndicatorSeparator: () => null, } @@ -225,7 +245,6 @@ const Table = ({ newFilters[newFilter.label] = newFilter.value setSelectedFilter(newFilters) } - if (data.length <= 0) { return <> } else if (setInitialPage != null) { @@ -233,8 +252,8 @@ const Table = ({ } return ( - -
+ +
-
-
- {filterOptions && - filterOptions.map((filterOption) => ( -
- + handleFilterChange({ + value: value || null, + label: filterOption.label ? filterOption.label : null, + }) + } + isClearable={true} + placeholder={`Filter by ${titleize(filterOption.label)}`} + options={filterOption.options.map((option) => { + return { value: option.key, label: option.label } + })} + /> + + ))}
- {tableData.length > 0 ? ( + {headerGroups.length > 0 ? (
{headerGroups.map((headerGroup) => ( {headerGroup.headers.map((column) => ( ))} @@ -334,8 +352,12 @@ const Table = ({ return ( ) })} @@ -412,23 +434,25 @@ const Table = ({ )}
- {titleize(column.render('Header'))} - - {column.isSorted ? ( - column.isSortedDesc ? ( - +
handleColumnsSort(column.Header)}> + {titleize(column.render('Header'))} + + {column.isSorted ? ( + column.isSortedDesc ? ( + + ) : ( + + ) + ) : sortedColumn === null ? ( + ) : ( - - ) - ) : ( - '' - )} - + '' + )} + +
{column.render - ? column.render(row.original.id, row.id) - : row.original[column.name]} + ? column.render(row.original.id) || ( + None + ) + : row.original[column.name] || ( + None + )}
) : ( -

No matches were found. Please change your filters.

+

Nothing to Show.

)} {pageOptions.length > 1 && ( -
+