diff --git a/frontend/src/components/ActivityLogTable.tsx b/frontend/src/components/ActivityLogTable.tsx index 2bce4994a..a01682ddf 100644 --- a/frontend/src/components/ActivityLogTable.tsx +++ b/frontend/src/components/ActivityLogTable.tsx @@ -370,9 +370,9 @@ const ActivityLogTable = ({ }); }; - const onStatusChange = (status: SelectItem) => { + const onStatusChange = (status: SelectItem | undefined) => { setStatus(status); - setQuery({ status: status.key }); + setQuery({ status: status?.key }); }; const onExecutionOnRangeChange = ([executionDateStart, executionDateEnd]: Date[]) => { @@ -479,12 +479,12 @@ const ActivityLogTable = ({

{resolutionStatus === ActivityLogResolutionStatus.NEW ? i18n.t('activity_log:pending_header', { - hours: counters?.pending ?? '-', - }) + hours: counters?.pending ?? '-', + }) : `${i18n.t('activity_log:past_header', { - hours: counters?.approved ?? '-', - rejected: counters?.rejected ?? '-', - })}`} + hours: counters?.approved ?? '-', + rejected: counters?.rejected ?? '-', + })}`}

{resolutionStatus === ActivityLogResolutionStatus.SOLVED && (
diff --git a/frontend/src/components/ContractsTable.tsx b/frontend/src/components/ContractsTable.tsx index a1ff436eb..3b00eb34c 100644 --- a/frontend/src/components/ContractsTable.tsx +++ b/frontend/src/components/ContractsTable.tsx @@ -389,8 +389,8 @@ const ContractsTable = ({ query, setQuery, volunteerName, volunteerId }: Contrac }); }; - const onStatusChange = (item: SelectItem) => { - setQuery({ status: item.key }); + const onStatusChange = (item: SelectItem | undefined) => { + setQuery({ status: item?.key }); }; const onCloseSidePanel = (shouldRefetch?: boolean) => { diff --git a/frontend/src/components/LineChartCard.tsx b/frontend/src/components/LineChartCard.tsx index 754ac5cb2..2e565f8ef 100644 --- a/frontend/src/components/LineChartCard.tsx +++ b/frontend/src/components/LineChartCard.tsx @@ -40,13 +40,13 @@ const YearXAxisTick = (props: any) => { }; const LineChartCard = () => { - const [chartFilter, setChartFilter] = useState>( + const [chartFilter, setChartFilter] = useState | undefined>( LINE_CHART_FILTER_OPTIONS[0], ); - const { data, isLoading } = useVolunteerLineChartQuery(chartFilter.key); + const { data, isLoading } = useVolunteerLineChartQuery(chartFilter?.key || LINE_CHART_FILTER_OPTIONS[0].key); - const switchXAxisTick = (option: LineChartOption) => { + const switchXAxisTick = (option: LineChartOption | undefined) => { switch (option) { case LineChartOption.YEARLY: { return ; @@ -73,7 +73,7 @@ const LineChartCard = () => { {data && ( { - const [chartFilter, setChartFilter] = useState>( + const [chartFilter, setChartFilter] = useState | undefined>( PIE_CHART_FILTER_OPTIONS[0], ); - const { data, isLoading } = useVolunteerPieChartQuery(chartFilter.key); + const { data, isLoading } = useVolunteerPieChartQuery(chartFilter?.key || PIE_CHART_FILTER_OPTIONS[0].key); return ( @@ -42,7 +42,7 @@ const PieChartCard = () => { className={`h-3.5 w-3.5 border-solid ${PIE_CHART_LEGEND_COLORS[index]} rounded-full self-center`} /> - {chartFilter.key === PieChartOption.AGE + {chartFilter?.key === PieChartOption.AGE ? i18n.t('general:years_old', { age: item.name }) : i18n.t('general:sex', { sex_type: i18n.t(`general:${item.name}`) })} diff --git a/frontend/src/components/RsvpTable.tsx b/frontend/src/components/RsvpTable.tsx index 982986f40..3d8e30fc7 100644 --- a/frontend/src/components/RsvpTable.tsx +++ b/frontend/src/components/RsvpTable.tsx @@ -116,8 +116,8 @@ const RsvpTable = ({ eventId, query, setQuery }: RsvpTableProps) => { ); }; - const onResponseChange = (response: SelectItem) => { - setQuery({ going: response.key as RSVPGoingEnum }, 'replaceIn'); + const onResponseChange = (response: SelectItem | undefined) => { + setQuery({ going: response?.key as RSVPGoingEnum }, 'replaceIn'); }; const onResetFilters = () => { @@ -142,7 +142,7 @@ const RsvpTable = ({ eventId, query, setQuery }: RsvpTableProps) => { downloadExcel(eventRSVPsData as BlobPart, i18n.t('events:download_rsvp')); }; - const onSetBranchFilter = (branch: SelectItem) => { + const onSetBranchFilter = (branch: SelectItem | undefined) => { setBranch(branch); setQuery( { @@ -152,7 +152,7 @@ const RsvpTable = ({ eventId, query, setQuery }: RsvpTableProps) => { ); }; - const onSetDepartmentFilter = (department: SelectItem) => { + const onSetDepartmentFilter = (department: SelectItem | undefined) => { setDepartment(department); setQuery( { @@ -162,7 +162,7 @@ const RsvpTable = ({ eventId, query, setQuery }: RsvpTableProps) => { ); }; - const onSetRoleFilter = (role: SelectItem) => { + const onSetRoleFilter = (role: SelectItem | undefined) => { setRole(role); setQuery( { @@ -238,6 +238,7 @@ const RsvpTable = ({ eventId, query, setQuery }: RsvpTableProps) => { onChange={onResponseChange} options={ResponseSelectOptions} defaultValue={query.going} + allowDeselect /> diff --git a/frontend/src/components/Select.tsx b/frontend/src/components/Select.tsx index 2b772a2e9..59e88c0ba 100644 --- a/frontend/src/components/Select.tsx +++ b/frontend/src/components/Select.tsx @@ -10,11 +10,12 @@ export interface SelectItem { export interface SelectProps { label?: string; options: SelectItem[]; - onChange: (item: SelectItem) => void; - selected?: SelectItem; + onChange: (item: SelectItem | undefined) => void; + selected?: SelectItem | undefined; placeholder?: string; helper?: ReactNode; minWidth?: boolean; + allowDeselect?: boolean; } const Select = ({ @@ -25,17 +26,25 @@ const Select = ({ placeholder, helper, minWidth, + allowDeselect = false }: SelectProps) => { + const handleChange = (item: SelectItem) => { + if (allowDeselect && selected && item?.key === selected.key) { + onChange(undefined); + } else { + onChange(item); + } + }; + return ( - + {({ open }) => (
{label && {label}}
{selected ? ( diff --git a/frontend/src/components/Tabs.tsx b/frontend/src/components/Tabs.tsx index e76464482..69f585872 100644 --- a/frontend/src/components/Tabs.tsx +++ b/frontend/src/components/Tabs.tsx @@ -11,13 +11,15 @@ interface TabsProps { const Tabs = ({ children, tabs, onClick, defaultTab }: TabsProps) => { const [activeTab, setActiveTab] = useState>(defaultTab || tabs[0]); - const onTabClick = (selected: SelectItem): void => { - setActiveTab(selected); - onClick(selected.key); + const onTabClick = (selected: SelectItem | undefined): void => { + if (selected) { + setActiveTab(selected); + onClick(selected?.key); + } }; useEffect(() => { - if (defaultTab && defaultTab?.key !== activeTab.key) { + if (defaultTab && defaultTab?.key !== activeTab?.key) { setActiveTab(defaultTab); } }, [defaultTab]); @@ -31,11 +33,10 @@ const Tabs = ({ children, tabs, onClick, defaultTab }: Tabs key={tab.key} aria-label={tab.value} onClick={onTabClick.bind(null, tab)} - className={`${ - activeTab.key === tab.key - ? 'bg-yellow-500/[0.5]' - : 'font-roboto hover:bg-yellow-500/[0.5]' - } min-w-fit leading-5 text-cool-gray-800 hover:text-cool-gray-800 px-4 py-2 rounded-md active:bg-yellow-500`} + className={`${activeTab?.key === tab.key + ? 'bg-yellow-500/[0.5]' + : 'font-roboto hover:bg-yellow-500/[0.5]' + } min-w-fit leading-5 text-cool-gray-800 hover:text-cool-gray-800 px-4 py-2 rounded-md active:bg-yellow-500`} > {tab.value} diff --git a/frontend/src/containers/OrganizationStructureSelect.tsx b/frontend/src/containers/OrganizationStructureSelect.tsx index b35fa0c5d..7b2357483 100644 --- a/frontend/src/containers/OrganizationStructureSelect.tsx +++ b/frontend/src/containers/OrganizationStructureSelect.tsx @@ -32,6 +32,7 @@ const OrganizationStructureSelect = ({ {...selectProps} selected={selected} onChange={onChange} + allowDeselect options={ divisionListItems && divisionListItems.items?.length > 0 ? divisionListItems.items?.map(mapDivisionListItemToSelectItem) diff --git a/frontend/src/pages/ActivityTypes.tsx b/frontend/src/pages/ActivityTypes.tsx index 9b27a292d..9ae95342b 100644 --- a/frontend/src/pages/ActivityTypes.tsx +++ b/frontend/src/pages/ActivityTypes.tsx @@ -63,21 +63,21 @@ const ActivityTypes = ({ query, setQuery }: ActivityTypesProps) => { }); }; - const onSetBranchFilter = (branch: SelectItem) => { + const onSetBranchFilter = (branch: SelectItem | undefined) => { setBranch(branch); setQuery({ branch: branch?.value, }); }; - const onSetDepartmentFilter = (department: SelectItem) => { + const onSetDepartmentFilter = (department: SelectItem | undefined) => { setDepartment(department); setQuery({ department: department?.value, }); }; - const onSetRoleFilter = (role: SelectItem) => { + const onSetRoleFilter = (role: SelectItem | undefined) => { setRole(role); setQuery({ role: role?.value, diff --git a/frontend/src/pages/Volunteers.tsx b/frontend/src/pages/Volunteers.tsx index d008a34c7..60ef2d634 100644 --- a/frontend/src/pages/Volunteers.tsx +++ b/frontend/src/pages/Volunteers.tsx @@ -75,9 +75,8 @@ const ActiveVolunteersTableHeader = [ minWidth: '9rem', selector: (row: IVolunteer) => row.profile?.department || row?.profile?.role - ? `${row.profile?.role?.name || ''}${ - row.profile?.role && row.profile?.department ? '\n' : '' - }${row.profile?.department?.name || ''}` + ? `${row.profile?.role?.name || ''}${row.profile?.role && row.profile?.department ? '\n' : '' + }${row.profile?.department?.name || ''}` : '-', }, { @@ -362,7 +361,7 @@ const Volunteers = ({ query, setQuery }: VolunteersProps) => { ); }; - const onSetBranchFilter = (branch: SelectItem) => { + const onSetBranchFilter = (branch: SelectItem | undefined) => { setBranch(branch); setQuery( { @@ -372,7 +371,7 @@ const Volunteers = ({ query, setQuery }: VolunteersProps) => { ); }; - const onSetDepartmentFilter = (department: SelectItem) => { + const onSetDepartmentFilter = (department: SelectItem | undefined) => { setDepartment(department); setQuery( { @@ -382,7 +381,7 @@ const Volunteers = ({ query, setQuery }: VolunteersProps) => { ); }; - const onSetRoleFilter = (role: SelectItem) => { + const onSetRoleFilter = (role: SelectItem | undefined) => { setRole(role); setQuery( { @@ -412,10 +411,10 @@ const Volunteers = ({ query, setQuery }: VolunteersProps) => { ); }; - const onAgeRangeChange = (selectedRange: SelectItem) => { + const onAgeRangeChange = (selectedRange: SelectItem | undefined) => { setQuery( { - age: selectedRange.key, + age: selectedRange?.key, }, 'replaceIn', ); diff --git a/frontend/src/services/volunteer/volunteer.service.ts b/frontend/src/services/volunteer/volunteer.service.ts index ef8c11aa9..3f5f7d9be 100644 --- a/frontend/src/services/volunteer/volunteer.service.ts +++ b/frontend/src/services/volunteer/volunteer.service.ts @@ -122,6 +122,7 @@ export const useVolunteerStatisticsQuery = () => { //Volunteer Line Chart export const useVolunteerLineChartQuery = (filter: LineChartOption) => { return useQuery(['volunteer-line-chart', filter], () => getVolunteerLineChart(filter), { + enabled: !!filter, onError: (error: AxiosError>) => error, }); }; @@ -129,6 +130,7 @@ export const useVolunteerLineChartQuery = (filter: LineChartOption) => { //Volunteer Pie Chart export const useVolunteerPieChartQuery = (filter: PieChartOption) => { return useQuery(['volunteer-pie-chart', filter], () => getVolunteerPieChart(filter), { + enabled: !!filter, onError: (error: AxiosError>) => error, }); };