diff --git a/frontend/src/components/BCDataGrid/components/Filters/BCColumnSetFilter.jsx b/frontend/src/components/BCDataGrid/components/Filters/BCColumnSetFilter.jsx
index fec6ab853..e16772dc7 100644
--- a/frontend/src/components/BCDataGrid/components/Filters/BCColumnSetFilter.jsx
+++ b/frontend/src/components/BCDataGrid/components/Filters/BCColumnSetFilter.jsx
@@ -6,7 +6,9 @@ import CheckBoxIcon from '@mui/icons-material/CheckBox'
const icon =
const checkedIcon =
-
+/**
+ * @deprecated
+ */
export const BCColumnSetFilter = forwardRef((props, ref) => {
const { apiQuery, params } = props
const [options, setOptions] = useState([])
diff --git a/frontend/src/components/BCDataGrid/components/Filters/BCDateFloatingFilter.jsx b/frontend/src/components/BCDataGrid/components/Filters/BCDateFloatingFilter.jsx
new file mode 100644
index 000000000..6a924492b
--- /dev/null
+++ b/frontend/src/components/BCDataGrid/components/Filters/BCDateFloatingFilter.jsx
@@ -0,0 +1,128 @@
+import { useState, useEffect, useCallback } from 'react'
+import { FormControl, IconButton, InputAdornment } from '@mui/material'
+import {
+ Clear as ClearIcon,
+ CalendarToday as CalendarIcon
+} from '@mui/icons-material'
+import { DatePicker } from '@mui/x-date-pickers'
+import { format, isValid } from 'date-fns'
+
+export const BCDateFloatingFilter = ({
+ model,
+ onModelChange,
+ disabled = false,
+ initialFilterType = 'equals',
+ label = 'Select Date'
+}) => {
+ const [selectedDate, setSelectedDate] = useState(null)
+ const [open, setOpen] = useState(false)
+
+ const handleChange = useCallback((newDate) => {
+ setSelectedDate(newDate)
+
+ if (newDate && isValid(newDate)) {
+ onModelChange({
+ type: initialFilterType,
+ dateFrom: format(newDate, 'yyyy-MM-dd'),
+ dateTo: null,
+ filterType: 'date'
+ })
+ } else {
+ onModelChange(null)
+ }
+ }, [])
+
+ const handleClear = (event) => {
+ event.stopPropagation()
+ setSelectedDate(null)
+ onModelChange(null)
+ }
+
+ const handleOpen = () => {
+ setOpen(true)
+ }
+
+ const handleClose = () => {
+ setOpen(false)
+ }
+
+ useEffect(() => {
+ if (!model) {
+ setSelectedDate(null)
+ return
+ }
+
+ if (model.filter) {
+ const date = new Date(model.dateFrom)
+ setSelectedDate(isValid(date) ? date : null)
+ }
+ }, [model])
+
+ return (
+
+
+ setOpen(true)}
+ aria-label="Open calendar"
+ >
+
+
+
+ ),
+ endAdornment: selectedDate && (
+
+ event.stopPropagation()}
+ edge="end"
+ aria-label="Clear date"
+ >
+
+
+
+ )
+ }
+ }
+ }}
+ />
+
+ )
+}
+
+BCDateFloatingFilter.displayName = 'BCDateFloatingFilter'
diff --git a/frontend/src/components/BCDataGrid/components/Filters/BCSelectFloatingFilter.jsx b/frontend/src/components/BCDataGrid/components/Filters/BCSelectFloatingFilter.jsx
new file mode 100644
index 000000000..ccb30136d
--- /dev/null
+++ b/frontend/src/components/BCDataGrid/components/Filters/BCSelectFloatingFilter.jsx
@@ -0,0 +1,140 @@
+import { useState, useCallback, useEffect } from 'react'
+import { IconButton } from '@mui/material'
+import { Clear as ClearIcon } from '@mui/icons-material'
+const ITEM_HEIGHT = 48
+const ITEM_PADDING_TOP = 8
+
+export const BCSelectFloatingFilter = ({
+ model,
+ onModelChange,
+ optionsQuery,
+ valueKey = 'value',
+ labelKey = 'label',
+ disabled = false,
+ params,
+ initialFilterType = 'equals',
+ multiple = false,
+ initialSelectedValues = []
+}) => {
+ const [selectedValues, setSelectedValues] = useState([])
+ const { data: optionsData, isLoading, isError, error } = optionsQuery(params)
+
+ const handleChange = (event) => {
+ const { options } = event.target
+ const newValues = Array.from(options)
+ .filter((option) => option.selected)
+ .map((option) => option.value)
+
+ if (!multiple) {
+ setSelectedValues([newValues[0] || ''])
+ onModelChange(
+ !newValues[0] || newValues[0] === '0'
+ ? null
+ : {
+ type: initialFilterType,
+ filter: newValues[0]
+ }
+ )
+ } else {
+ setSelectedValues(newValues)
+ onModelChange({
+ type: initialFilterType,
+ filter: newValues
+ })
+ }
+ }
+
+ const handleClear = (event) => {
+ event.stopPropagation()
+ setSelectedValues([])
+ onModelChange(null)
+ }
+
+ const renderSelectContent = useCallback(() => {
+ if (isLoading) {
+ return (
+
+ )
+ }
+
+ if (isError) {
+ return (
+
+ )
+ }
+
+ return (optionsData || []).map((option) => (
+
+ ))
+ }, [isLoading, isError, optionsData, error])
+
+ useEffect(() => {
+ if (!model) {
+ setSelectedValues(initialSelectedValues)
+ } else {
+ setSelectedValues([model?.filter])
+ }
+ }, [model, initialSelectedValues])
+
+ return (
+
+
0}
+ aria-controls="select-filter"
+ >
+
+ {selectedValues.length > 0 && (
+ event.stopPropagation()}
+ aria-label="Clear selection"
+ >
+
+
+ )}
+
+
+ )
+}
+
+BCSelectFloatingFilter.displayName = 'BCSelectFloatingFilter'
diff --git a/frontend/src/components/BCDataGrid/components/index.js b/frontend/src/components/BCDataGrid/components/index.js
index 14d4ca2be..16e855ef3 100644
--- a/frontend/src/components/BCDataGrid/components/index.js
+++ b/frontend/src/components/BCDataGrid/components/index.js
@@ -13,3 +13,5 @@ export { BCPagination } from './StatusBar/BCPagination'
export { LargeTextareaEditor } from './Editors/LargeTextareaEditor'
export { TextCellEditor } from './Editors/TextCellEditor'
export { NumberEditor } from './Editors/NumberEditor'
+export { BCDateFloatingFilter } from './Filters/BCDateFloatingFilter'
+export { BCSelectFloatingFilter } from './Filters/BCSelectFloatingFilter'
diff --git a/frontend/src/themes/base/globals.js b/frontend/src/themes/base/globals.js
index fe28c97c5..2eedaf4fc 100644
--- a/frontend/src/themes/base/globals.js
+++ b/frontend/src/themes/base/globals.js
@@ -114,6 +114,36 @@ const globals = {
fontWeight: 700,
color: grey[700]
},
+ '.select-container': {
+ fontFamily: "'BCSans', 'Noto Sans', 'Verdana', 'Arial', 'sans-serif'",
+ fontSize: '1.6rem',
+ width: '100%',
+ display: 'flex',
+ alignItems: 'center',
+ gap: '8px',
+ border: 'none',
+ borderBottom: '2px solid #495057',
+ borderRadius: '0px',
+ padding: '0px',
+ background: '#fff',
+ transition: 'border-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out'
+ },
+ '.select-container:focus-within': {
+ border: '2px solid #495057',
+ borderWidth: '0px 0.01rem'
+ },
+ '.select-container #select-filter': {
+ width: '100%',
+ padding: '11px',
+ border: 'none',
+ outline: 'none',
+ appearance: 'none',
+ background: 'transparent'
+ },
+ '.select-container option': {
+ fontSize: '1rem',
+ fontFamily: 'inherit'
+ },
// editor theme for ag-grid quertz theme
'.ag-theme-quartz': {
'--ag-borders': `0.5px solid ${grey[400]} !important`,
diff --git a/frontend/src/views/Admin/AdminMenu/components/Users.jsx b/frontend/src/views/Admin/AdminMenu/components/Users.jsx
index 28f2e021b..49921701b 100644
--- a/frontend/src/views/Admin/AdminMenu/components/Users.jsx
+++ b/frontend/src/views/Admin/AdminMenu/components/Users.jsx
@@ -43,7 +43,7 @@ export const Users = () => {
navigate(ROUTES.ADMIN_USERS_ADD)
}
const getRowId = useCallback((params) => {
- return params.data.userProfileId
+ return params.data.userProfileId.toString()
}, [])
const handleRowClicked = useCallback((params) => {
diff --git a/frontend/src/views/Admin/AdminMenu/components/_schema.js b/frontend/src/views/Admin/AdminMenu/components/_schema.js
index 70b652b71..7b46ba5bb 100644
--- a/frontend/src/views/Admin/AdminMenu/components/_schema.js
+++ b/frontend/src/views/Admin/AdminMenu/components/_schema.js
@@ -8,8 +8,11 @@ import {
RoleRenderer,
StatusRenderer
} from '@/utils/grid/cellRenderers'
-import { BCColumnSetFilter } from '@/components/BCDataGrid/components'
import { useRoleList } from '@/hooks/useRole'
+import {
+ BCSelectFloatingFilter,
+ BCDateFloatingFilter
+} from '@/components/BCDataGrid/components/index'
export const usersColumnDefs = (t) => [
{
@@ -44,14 +47,14 @@ export const usersColumnDefs = (t) => [
},
suppressFilterButton: true
},
- floatingFilterComponent: BCColumnSetFilter,
+ floatingFilterComponent: BCSelectFloatingFilter,
+ suppressFloatingFilterButton: true,
+ suppressHeaderFilterButton: true,
floatingFilterComponentParams: {
- apiQuery: useRoleList, // all data returned should be an array which includes an object of key 'name'
- // Eg: [{id: 1, name: 'EntryListItem' }] except name all others are optional
+ optionsQuery: useRoleList,
params: 'government_roles_only=true',
- key: 'admin-users',
- disableCloseOnSelect: false,
- multiple: false
+ valueKey: 'name',
+ labelKey: 'name'
},
cellRenderer: RoleRenderer,
cellClass: 'vertical-middle'
@@ -84,20 +87,21 @@ export const usersColumnDefs = (t) => [
},
cellRenderer: StatusRenderer,
cellClass: 'vertical-middle',
- floatingFilterComponent: BCColumnSetFilter,
+ floatingFilterComponent: BCSelectFloatingFilter,
floatingFilterComponentParams: {
- apiQuery: () => ({
+ optionsQuery: () => ({
data: [
{ id: 1, name: t('admin:userColLabels.active') },
{ id: 0, name: t('admin:userColLabels.inactive') }
],
isLoading: false
}),
- disableCloseOnSelect: false,
- multiple: false
+ valueKey: 'name',
+ labelKey: 'name'
},
minWidth: 120,
- suppressHeaderMenuButton: false
+ suppressFloatingFilterButton: true,
+ suppressHeaderFilterButton: true
},
{
colId: 'organizationId',
diff --git a/frontend/src/views/ComplianceReports/components/_schema.jsx b/frontend/src/views/ComplianceReports/components/_schema.jsx
index e7f1546fb..6c52b88b6 100644
--- a/frontend/src/views/ComplianceReports/components/_schema.jsx
+++ b/frontend/src/views/ComplianceReports/components/_schema.jsx
@@ -1,4 +1,7 @@
-import { BCColumnSetFilter } from '@/components/BCDataGrid/components'
+import {
+ BCDateFloatingFilter,
+ BCSelectFloatingFilter
+} from '@/components/BCDataGrid/components'
import { SUMMARY } from '@/constants/common'
import { ReportsStatusRenderer } from '@/utils/grid/cellRenderers'
import { timezoneFormatter } from '@/utils/formatters'
@@ -50,10 +53,10 @@ export const reportsColDefs = (t, bceidRole) => [
url: ({ data }) =>
`${data.compliancePeriod?.description}/${data.complianceReportId}`
},
- floatingFilterComponent: BCColumnSetFilter,
+ floatingFilterComponent: BCSelectFloatingFilter,
floatingFilterComponentParams: {
// TODO: change this to api Query later
- apiQuery: () => ({
+ optionsQuery: () => ({
data: bceidRole
? [
{ id: 1, name: 'Draft' },
@@ -70,17 +73,15 @@ export const reportsColDefs = (t, bceidRole) => [
],
isLoading: false
}),
- key: 'report-status',
- label: t('report:reportColLabels.status'),
- disableCloseOnSelect: false,
- multiple: false
+ valueKey: 'name',
+ labelKey: 'name'
}
},
{
field: 'updateDate',
cellDataType: 'dateString',
headerName: t('report:reportColLabels.lastUpdated'),
- flex: 1,
+ minWidth: '80',
valueGetter: ({ data }) => data.updateDate || '',
valueFormatter: timezoneFormatter,
filter: 'agDateColumnFilter',
@@ -89,7 +90,8 @@ export const reportsColDefs = (t, bceidRole) => [
suppressAndOrCondition: true,
buttons: ['clear'],
maxValidYear: 2400
- }
+ },
+ floatingFilterComponent: BCDateFloatingFilter
}
]
diff --git a/frontend/src/views/Organizations/ViewOrganization/_schema.js b/frontend/src/views/Organizations/ViewOrganization/_schema.js
index bc1a33fb8..8b78ce4d5 100644
--- a/frontend/src/views/Organizations/ViewOrganization/_schema.js
+++ b/frontend/src/views/Organizations/ViewOrganization/_schema.js
@@ -1,6 +1,6 @@
import { numberFormatter } from '@/utils/formatters'
import { LinkRenderer, OrgStatusRenderer } from '@/utils/grid/cellRenderers'
-import { BCColumnSetFilter } from '@/components/BCDataGrid/components'
+import { BCSelectFloatingFilter } from '@/components/BCDataGrid/components'
import { useOrganizationStatuses } from '@/hooks/useOrganizations'
import { usersColumnDefs } from '@/views/Admin/AdminMenu/components/_schema'
import { t } from 'i18next'
@@ -48,15 +48,14 @@ export const organizationsColDefs = (t) => [
valueGetter: (params) => params.data.orgStatus.status,
cellRenderer: OrgStatusRenderer,
cellClass: 'vertical-middle',
- floatingFilterComponent: BCColumnSetFilter,
+ floatingFilterComponent: BCSelectFloatingFilter,
floatingFilterComponentParams: {
- apiOptionField: 'status',
- apiQuery: useOrganizationStatuses,
- key: 'org-status',
- disableCloseOnSelect: false,
- multiple: false
+ valueKey: 'status',
+ labelKey: 'status',
+ optionsQuery: useOrganizationStatuses
},
- suppressHeaderMenuButton: true
+ suppressFloatingFilterButton: true,
+ suppressHeaderFilterButton: true
}
]
diff --git a/frontend/src/views/Transactions/_schema.js b/frontend/src/views/Transactions/_schema.js
index 46bbbc82c..50827ed38 100644
--- a/frontend/src/views/Transactions/_schema.js
+++ b/frontend/src/views/Transactions/_schema.js
@@ -5,7 +5,7 @@ import {
spacesFormatter
} from '@/utils/formatters'
import { TransactionStatusRenderer } from '@/utils/grid/cellRenderers'
-import { BCColumnSetFilter } from '@/components/BCDataGrid/components'
+import { BCSelectFloatingFilter } from '@/components/BCDataGrid/components'
import { useTransactionStatuses } from '@/hooks/useTransactions'
const prefixMap = {
@@ -102,14 +102,14 @@ export const transactionsColDefs = (t) => [
headerName: t('txn:txnColLabels.status'),
cellRenderer: TransactionStatusRenderer,
cellClass: 'vertical-middle',
- floatingFilterComponent: BCColumnSetFilter,
+ floatingFilterComponent: BCSelectFloatingFilter,
floatingFilterComponentParams: {
- apiOptionField: 'status',
- apiQuery: useTransactionStatuses,
- disableCloseOnSelect: false,
- multiple: false
+ valueKey: 'status',
+ labelKey: 'status',
+ optionsQuery: useTransactionStatuses
},
- suppressHeaderMenuButton: true,
+ suppressFloatingFilterButton: true,
+ suppressHeaderFilterButton: true,
minWidth: 180,
width: 250
},