event.stopPropagation()}
aria-label="Clear selection"
+ tabIndex={-1}
>
diff --git a/frontend/src/components/BCDataGrid/components/Renderers/AccessibleHeader.jsx b/frontend/src/components/BCDataGrid/components/Renderers/AccessibleHeader.jsx
new file mode 100644
index 000000000..af0cdaf56
--- /dev/null
+++ b/frontend/src/components/BCDataGrid/components/Renderers/AccessibleHeader.jsx
@@ -0,0 +1,7 @@
+export const AccessibleHeader = (props) => {
+ return (
+
+ {props.column.colDef.headerName}
+
+ )
+}
diff --git a/frontend/src/components/BCDataGrid/components/Renderers/RequiredHeader.jsx b/frontend/src/components/BCDataGrid/components/Renderers/RequiredHeader.jsx
index 1e8ddfbfb..8a6b9174f 100644
--- a/frontend/src/components/BCDataGrid/components/Renderers/RequiredHeader.jsx
+++ b/frontend/src/components/BCDataGrid/components/Renderers/RequiredHeader.jsx
@@ -1,8 +1,8 @@
export const RequiredHeader = (props) => {
return (
-
+
*
- {props.column.colDef.headerName}
+ {props.column.colDef.headerName}
)
}
diff --git a/frontend/src/components/BCDataGrid/components/index.js b/frontend/src/components/BCDataGrid/components/index.js
index 16e855ef3..56eb9135a 100644
--- a/frontend/src/components/BCDataGrid/components/index.js
+++ b/frontend/src/components/BCDataGrid/components/index.js
@@ -6,6 +6,7 @@ export { DateRangeCellEditor } from './Editors/DateRangeCellEditor'
export { ActionsRenderer } from './Renderers/ActionsRenderer'
export { ActionsRenderer2 } from './Renderers/ActionsRenderer2'
export { RequiredHeader } from './Renderers/RequiredHeader'
+export { AccessibleHeader } from './Renderers/AccessibleHeader'
export { ValidationRenderer } from './Renderers/ValidationRenderer'
export { ValidationRenderer2 } from './Renderers/ValidationRenderer2'
export { BCColumnSetFilter } from './Filters/BCColumnSetFilter'
diff --git a/frontend/src/components/Footer.jsx b/frontend/src/components/Footer.jsx
index 0af3801f8..c62993d5b 100644
--- a/frontend/src/components/Footer.jsx
+++ b/frontend/src/components/Footer.jsx
@@ -19,25 +19,25 @@ const Footer = (props) => {
label: 'About this site'
},
{
- href: 'http://gov.bc.ca/disclaimer/',
+ href: 'https://gov.bc.ca/disclaimer/',
name: 'Disclaimer',
id: 'footer-disclaimer',
label: 'BC gov disclaimer information'
},
{
- href: 'http://gov.bc.ca/privacy/',
+ href: 'https://gov.bc.ca/privacy/',
name: 'Privacy',
id: 'footer-privacy',
label: 'BC gov privacy information'
},
{
- href: 'http://gov.bc.ca/webaccessibility/',
+ href: 'https://gov.bc.ca/webaccessibility/',
name: 'Accessibility',
id: 'footer-accessibility',
label: 'BC gov accessibility information'
},
{
- href: 'http://gov.bc.ca/copyright',
+ href: 'https://gov.bc.ca/copyright',
name: 'Copyright',
id: 'footer-copyright',
label: 'BC gov copyright information'
diff --git a/frontend/src/constants/routes/apiRoutes.js b/frontend/src/constants/routes/apiRoutes.js
index d79d25464..b8f7a1af5 100644
--- a/frontend/src/constants/routes/apiRoutes.js
+++ b/frontend/src/constants/routes/apiRoutes.js
@@ -34,7 +34,7 @@ export const apiRoutes = {
saveOtherUses: '/other-uses/save',
getOtherUses: '/other-uses/list',
getAllOtherUses: '/other-uses/list-all',
- otherUsesOptions: '/other-uses/table-options',
+ otherUsesOptions: '/other-uses/table-options?',
getComplianceReport: '/reports/:reportID',
updateComplianceReport: '/reports/:reportID',
getComplianceReportSummary: '/reports/:reportID/summary',
diff --git a/frontend/src/constants/statuses.js b/frontend/src/constants/statuses.js
index 91c7d3662..36844092a 100644
--- a/frontend/src/constants/statuses.js
+++ b/frontend/src/constants/statuses.js
@@ -66,3 +66,10 @@ export const FUEL_CODE_STATUSES = {
export function getAllFuelCodeStatuses() {
return Object.values(FUEL_CODE_STATUSES)
}
+
+export const TRANSACTION_TYPES = {
+ TRANSFER: 'Transfer',
+ INITIATIVE_AGREEMENT: 'InitiativeAgreement',
+ COMPLIANCE_REPORT: 'ComplianceReport',
+ ADMINISTRATIVE_ADJUSTMENT: 'AdminAdjustment'
+}
\ No newline at end of file
diff --git a/frontend/src/hooks/useFuelSupply.js b/frontend/src/hooks/useFuelSupply.js
index 33c059847..86606e630 100644
--- a/frontend/src/hooks/useFuelSupply.js
+++ b/frontend/src/hooks/useFuelSupply.js
@@ -8,7 +8,7 @@ export const useFuelSupplyOptions = (params, options) => {
const path =
apiRoutes.fuelSupplyOptions + 'compliancePeriod=' + params.compliancePeriod
return useQuery({
- queryKey: ['fuel-supply-options'],
+ queryKey: ['fuel-supply-options', params.compliancePeriod],
queryFn: async () => (await client.get(path)).data,
...options
})
diff --git a/frontend/src/hooks/useOtherUses.js b/frontend/src/hooks/useOtherUses.js
index 49ad999ee..3ff5481ef 100644
--- a/frontend/src/hooks/useOtherUses.js
+++ b/frontend/src/hooks/useOtherUses.js
@@ -4,9 +4,10 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
export const useOtherUsesOptions = (params, options) => {
const client = useApiService()
- const path = apiRoutes.otherUsesOptions
+ const path =
+ apiRoutes.otherUsesOptions + 'compliancePeriod=' + params.compliancePeriod
return useQuery({
- queryKey: ['other-uses-options'],
+ queryKey: ['other-uses-options', params.compliancePeriod],
queryFn: async () => (await client.get(path)).data,
...options
})
diff --git a/frontend/src/utils/grid/cellRenderers.jsx b/frontend/src/utils/grid/cellRenderers.jsx
index 642ba9fed..37917345a 100644
--- a/frontend/src/utils/grid/cellRenderers.jsx
+++ b/frontend/src/utils/grid/cellRenderers.jsx
@@ -1,4 +1,3 @@
-/* eslint-disable react-hooks/exhaustive-deps */
import BCBadge from '@/components/BCBadge'
import BCBox from '@/components/BCBox'
import { roles } from '@/constants/roles'
@@ -7,7 +6,7 @@ import {
getAllOrganizationStatuses
} from '@/constants/statuses'
import { Link, useLocation } from 'react-router-dom'
-import { useState, useRef, useEffect, useCallback } from 'react'
+import { useCallback, useEffect, useRef, useState } from 'react'
import colors from '@/themes/base/colors'
export const TextRenderer = (props) => {
@@ -20,80 +19,84 @@ export const TextRenderer = (props) => {
export const LinkRenderer = (props) => {
const location = useLocation()
+
+ const baseUrl = props.isAbsolute ? '' : `${location.pathname}/`
+ const targetUrl =
+ baseUrl +
+ ((props.url && props.url({ data: props.data })) || props?.node?.id)
return (
-
+
{props.valueFormatted || props.value}
)
}
+const BaseStatusRenderer = ({
+ isView = false,
+ value = false,
+ successText = 'Active',
+ failureText = 'Inactive',
+ successColor = 'success',
+ failureColor = 'smoky'
+}) => {
+ const badgeStyles = {
+ ...(!isView ? { display: 'flex', justifyContent: 'center' } : {}),
+ '& .MuiBadge-badge': {
+ minWidth: '120px',
+ fontWeight: 'regular',
+ textTransform: 'capitalize',
+ fontSize: '0.875rem',
+ padding: '0.4em 0.6em'
+ }
+ }
-export const StatusRenderer = (props) => {
return (
)
-}
-export const LoginStatusRenderer = (props) => {
- return (
-
-
-
- )
+ if (props.url) {
+ const baseUrl = props.isAbsolute ? '' : `${location.pathname}/`
+ const targetUrl =
+ baseUrl +
+ ((props.url && props.url({ data: props.data })) || props?.node?.id)
+
+ return (
+
+ {component}
+
+ )
+ } else {
+ return component
+ }
}
+export const StatusRenderer = (props) => (
+
+)
+
+export const LoginStatusRenderer = (props) => (
+
+)
+
export const OrgStatusRenderer = (props) => {
const location = useLocation()
const statusArr = getAllOrganizationStatuses()
@@ -170,38 +173,6 @@ export const FuelCodeStatusRenderer = (props) => {
)
}
-export const FuelCodeStatusTextRenderer = (props) => {
- const statusArr = getAllFuelCodeStatuses()
- const statusColorArr = ['info', 'success', 'error']
- const statusIndex = statusArr.indexOf(props.data.fuelCodeStatus.status)
- return (
-
-
-
-
-
- )
-}
export const TransactionStatusRenderer = (props) => {
const statusArr = [
@@ -229,7 +200,7 @@ export const TransactionStatusRenderer = (props) => {
'error'
]
const statusIndex = statusArr.indexOf(props.data.status)
- return (
+ const component = (
{
/>
)
+ if (props.url) {
+ const baseUrl = props.isAbsolute ? '' : `${location.pathname}/`
+ const targetUrl =
+ baseUrl +
+ ((props.url && props.url({ data: props.data })) || props?.node?.id)
+
+ return (
+
+ {component}
+
+ )
+ } else {
+ return component
+ }
}
export const ReportsStatusRenderer = (props) => {
const statusArr = [
@@ -437,16 +422,16 @@ const GenericChipRenderer = ({
{renderOverflowChip(hiddenChipsCount)}
)
-
+ const baseUrl = props.isAbsolute ? '' : `${location.pathname}/`
+ const targetUrl =
+ baseUrl +
+ ((props.url && props.url({ data: props.data })) || props?.node?.id)
return disableLink ? (
chipContent
) : (
-
+
{chipContent}
-
+
)
}
diff --git a/frontend/src/views/Admin/AdminMenu/components/AuditLog.jsx b/frontend/src/views/Admin/AdminMenu/components/AuditLog.jsx
index a6f994c90..d6dad401c 100644
--- a/frontend/src/views/Admin/AdminMenu/components/AuditLog.jsx
+++ b/frontend/src/views/Admin/AdminMenu/components/AuditLog.jsx
@@ -1,16 +1,15 @@
-import { useRef, useCallback } from 'react'
+import { useCallback, useMemo, useRef } from 'react'
import BCBox from '@/components/BCBox'
import BCDataGridServer from '@/components/BCDataGrid/BCDataGridServer'
import BCTypography from '@/components/BCTypography'
import { useTranslation } from 'react-i18next'
import { auditLogColDefs, defaultAuditLogSortModel } from './_schema'
-import { apiRoutes, ROUTES } from '@/constants/routes'
-import { useNavigate } from 'react-router-dom'
+import { apiRoutes } from '@/constants/routes'
+import { LinkRenderer } from '@/utils/grid/cellRenderers.jsx'
export const AuditLog = () => {
const { t } = useTranslation(['common', 'admin'])
const gridRef = useRef()
- const navigate = useNavigate()
const gridOptions = {
overlayNoRowsTemplate: t('admin:auditLogsNotFound'),
@@ -24,16 +23,14 @@ export const AuditLog = () => {
const apiEndpoint = apiRoutes.getAuditLogs
- const handleRowClicked = useCallback(
- (params) => {
- const { auditLogId } = params.data
- const path = ROUTES.ADMIN_AUDIT_LOG_VIEW.replace(
- ':auditLogId',
- auditLogId
- )
- navigate(path)
- },
- [navigate]
+ const defaultColDef = useMemo(
+ () => ({
+ cellRenderer: LinkRenderer,
+ cellRendererParams: {
+ url: (data) => data.data.auditLogId
+ }
+ }),
+ []
)
return (
@@ -54,7 +51,7 @@ export const AuditLog = () => {
enableCopyButton={false}
enableExportButton={true}
exportName="AuditLog"
- handleRowClicked={handleRowClicked}
+ defaultColDef={defaultColDef}
/>
)
diff --git a/frontend/src/views/Admin/AdminMenu/components/UserActivity.jsx b/frontend/src/views/Admin/AdminMenu/components/UserActivity.jsx
index 532214e8e..ca8e57582 100644
--- a/frontend/src/views/Admin/AdminMenu/components/UserActivity.jsx
+++ b/frontend/src/views/Admin/AdminMenu/components/UserActivity.jsx
@@ -1,48 +1,47 @@
import BCBox from '@/components/BCBox'
import BCTypography from '@/components/BCTypography'
import { useTranslation } from 'react-i18next'
-import { useCallback } from 'react'
-import { useNavigate } from 'react-router-dom'
+import { useCallback, useMemo } from 'react'
import { userActivityColDefs } from '@/views/Admin/AdminMenu/components/_schema'
import { ROUTES } from '@/constants/routes'
import { BCGridViewer } from '@/components/BCDataGrid/BCGridViewer'
import { useGetUserActivities } from '@/hooks/useUser'
+import { LinkRenderer } from '@/utils/grid/cellRenderers.jsx'
export const UserActivity = () => {
const { t } = useTranslation(['common', 'admin'])
- const navigate = useNavigate()
const getRowId = useCallback((params) => {
- return `${params.data.transactionType.toLowerCase()}-${
- params.data.transactionId
- }`
+ return `${
+ params.data.actionTaken
+ }-${params.data.transactionType}-${params.data.transactionId}`
}, [])
- const handleRowClicked = useCallback(
- (params) => {
- const { transactionType, transactionId } = params.data
-
- let route
- switch (transactionType) {
- case 'Transfer':
- route = ROUTES.TRANSFERS_VIEW.replace(':transferId', transactionId)
- break
- case 'AdminAdjustment':
- route = ROUTES.ADMIN_ADJUSTMENT_VIEW.replace(
- ':transactionId',
- transactionId
- )
- break
- case 'InitiativeAgreement':
- route = ROUTES.INITIATIVE_AGREEMENT_VIEW.replace(
- ':transactionId',
- transactionId
- )
+ const defaultColDef = useMemo(
+ () => ({
+ cellRenderer: LinkRenderer,
+ cellRendererParams: {
+ isAbsolute: true,
+ url: (data) => {
+ const { transactionType, transactionId } = data.data
+ switch (transactionType) {
+ case 'Transfer':
+ return ROUTES.TRANSFERS_VIEW.replace(':transferId', transactionId)
+ case 'AdminAdjustment':
+ return ROUTES.ADMIN_ADJUSTMENT_VIEW.replace(
+ ':transactionId',
+ transactionId
+ )
+ case 'InitiativeAgreement':
+ return ROUTES.INITIATIVE_AGREEMENT_VIEW.replace(
+ ':transactionId',
+ transactionId
+ )
+ }
+ }
}
-
- navigate(route)
- },
- [navigate]
+ }),
+ []
)
return (
@@ -64,8 +63,7 @@ export const UserActivity = () => {
defaultMinWidth: 50,
defaultMaxWidth: 600
}}
- rowSelection={{ isRowSelectable: false }}
- onRowClicked={handleRowClicked}
+ defaultColDef={defaultColDef}
/>
diff --git a/frontend/src/views/Admin/AdminMenu/components/Users.jsx b/frontend/src/views/Admin/AdminMenu/components/Users.jsx
index 49921701b..65de1813f 100644
--- a/frontend/src/views/Admin/AdminMenu/components/Users.jsx
+++ b/frontend/src/views/Admin/AdminMenu/components/Users.jsx
@@ -1,21 +1,16 @@
-/* eslint-disable react-hooks/exhaustive-deps */
-// @mui component
import BCTypography from '@/components/BCTypography'
import BCButton from '@/components/BCButton'
import BCBox from '@/components/BCBox'
import BCAlert from '@/components/BCAlert'
import BCDataGridServer from '@/components/BCDataGrid/BCDataGridServer'
-// icons
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faCirclePlus } from '@fortawesome/free-solid-svg-icons'
-// hooks
import { useLocation, useNavigate } from 'react-router-dom'
-import { useCallback, useRef, useState, useEffect } from 'react'
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-
-import { ROUTES, apiRoutes } from '@/constants/routes'
-import { usersColumnDefs, idirUserDefaultFilter } from './_schema'
-import { calculateRowHeight } from '@/utils/formatters'
+import { apiRoutes, ROUTES } from '@/constants/routes'
+import { idirUserDefaultFilter, usersColumnDefs } from './_schema'
+import { LinkRenderer } from '@/utils/grid/cellRenderers.jsx'
export const Users = () => {
const { t } = useTranslation(['common', 'admin'])
@@ -46,9 +41,15 @@ export const Users = () => {
return params.data.userProfileId.toString()
}, [])
- const handleRowClicked = useCallback((params) => {
- navigate(`${ROUTES.ADMIN_USERS}/${params.data.userProfileId}`)
- })
+ const defaultColDef = useMemo(
+ () => ({
+ cellRenderer: LinkRenderer,
+ cellRendererParams: {
+ url: (data) => data.data.userProfileId
+ }
+ }),
+ []
+ )
const gridRef = useRef()
useEffect(() => {
@@ -99,9 +100,9 @@ export const Users = () => {
defaultSortModel={defaultSortModel}
defaultFilterModel={idirUserDefaultFilter}
handleGridKey={handleGridKey}
- handleRowClicked={handleRowClicked}
enableResetButton={false}
enableCopyButton={false}
+ defaultColDef={defaultColDef}
/>
diff --git a/frontend/src/views/Admin/AdminMenu/components/ViewUser.jsx b/frontend/src/views/Admin/AdminMenu/components/ViewUser.jsx
index 6ad30a1b6..833dfc3ec 100644
--- a/frontend/src/views/Admin/AdminMenu/components/ViewUser.jsx
+++ b/frontend/src/views/Admin/AdminMenu/components/ViewUser.jsx
@@ -1,19 +1,23 @@
import Loading from '@/components/Loading'
import BCTypography from '@/components/BCTypography'
-import { FloatingAlert, BCAlert2 } from '@/components/BCAlert'
+import { BCAlert2, FloatingAlert } from '@/components/BCAlert'
import BCDataGridServer from '@/components/BCDataGrid/BCDataGridServer'
-import { useRef, useCallback, useEffect, useState } from 'react'
-import { useNavigate, useParams } from 'react-router-dom'
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import { useParams } from 'react-router-dom'
import { useUser } from '@/hooks/useUser'
import { useCurrentUser } from '@/hooks/useCurrentUser'
import { useTranslation } from 'react-i18next'
import { phoneNumberFormatter } from '@/utils/formatters'
-import { RoleSpanRenderer, StatusRenderer } from '@/utils/grid/cellRenderers'
import {
- userActivityColDefs,
- defaultSortModel
+ LinkRenderer,
+ RoleSpanRenderer,
+ StatusRenderer
+} from '@/utils/grid/cellRenderers'
+import {
+ defaultSortModel,
+ userActivityColDefs
} from '@/views/Admin/AdminMenu/components/_schema'
-import { ROUTES, apiRoutes } from '@/constants/routes'
+import { apiRoutes, ROUTES } from '@/constants/routes'
import { roles } from '@/constants/roles'
import { useOrganizationUser } from '@/hooks/useOrganization'
import { Role } from '@/components/Role'
@@ -33,7 +37,6 @@ export const ViewUser = () => {
const { userID, orgID } = useParams()
const { data: currentUser, hasRoles } = useCurrentUser()
- const navigate = useNavigate()
const [editButtonRoute, setEditButtonRoute] = useState(null)
const { data, isLoading, isLoadingError, isError, error } = hasRoles(
@@ -73,35 +76,31 @@ export const ViewUser = () => {
}`
}, [])
- const handleRowClicked = useCallback(
- (params) => {
- const { transactionType, transactionId } = params.data
- let route
- switch (transactionType) {
- case 'Transfer':
- route = ROUTES.TRANSFERS_VIEW.replace(':transferId', transactionId)
- break
- case 'AdminAdjustment':
- route = ROUTES.ADMIN_ADJUSTMENT_VIEW.replace(
- ':transactionId',
- transactionId
- )
- break
- case 'InitiativeAgreement':
- route = ROUTES.INITIATIVE_AGREEMENT_VIEW.replace(
- ':transactionId',
- transactionId
- )
- break
- default:
- route = null
- }
-
- if (route) {
- navigate(route)
+ const defaultColDef = useMemo(
+ () => ({
+ cellRenderer: LinkRenderer,
+ cellRendererParams: {
+ isAbsolute: true,
+ url: (data) => {
+ const { transactionType, transactionId } = data.data
+ switch (transactionType) {
+ case 'Transfer':
+ return ROUTES.TRANSFERS_VIEW.replace(':transferId', transactionId)
+ case 'AdminAdjustment':
+ return ROUTES.ADMIN_ADJUSTMENT_VIEW.replace(
+ ':transactionId',
+ transactionId
+ )
+ case 'InitiativeAgreement':
+ return ROUTES.INITIATIVE_AGREEMENT_VIEW.replace(
+ ':transactionId',
+ transactionId
+ )
+ }
+ }
}
- },
- [navigate]
+ }),
+ []
)
useEffect(() => {
@@ -208,7 +207,7 @@ export const ViewUser = () => {
gridOptions={gridOptions}
defaultSortModel={defaultSortModel}
enableCopyButton={false}
- handleRowClicked={handleRowClicked}
+ defaultColDef={defaultColDef}
/>
>
diff --git a/frontend/src/views/Admin/__tests__/AdminTabPanel.test.jsx b/frontend/src/views/Admin/AdminMenu/components/__tests__/AdminTabPanel.test.jsx
similarity index 92%
rename from frontend/src/views/Admin/__tests__/AdminTabPanel.test.jsx
rename to frontend/src/views/Admin/AdminMenu/components/__tests__/AdminTabPanel.test.jsx
index 42affc7d2..bde91178e 100644
--- a/frontend/src/views/Admin/__tests__/AdminTabPanel.test.jsx
+++ b/frontend/src/views/Admin/AdminMenu/components/__tests__/AdminTabPanel.test.jsx
@@ -2,8 +2,8 @@ import { describe, it, expect } from 'vitest'
import { render, screen } from '@testing-library/react'
import { ThemeProvider } from '@mui/material/styles'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
-import theme from '@/themes' // Make sure this path is correct
-import { AdminTabPanel } from '../AdminMenu/components/AdminTabPanel'
+import theme from '@/themes/index.js' // Make sure this path is correct
+import { AdminTabPanel } from '../AdminTabPanel.jsx'
// Custom render function with all necessary providers
const customRender = (ui, options = {}) => {
diff --git a/frontend/src/views/Admin/AdminMenu/components/__tests__/AuditLog.test.jsx b/frontend/src/views/Admin/AdminMenu/components/__tests__/AuditLog.test.jsx
index 8cef96958..f62a29394 100644
--- a/frontend/src/views/Admin/AdminMenu/components/__tests__/AuditLog.test.jsx
+++ b/frontend/src/views/Admin/AdminMenu/components/__tests__/AuditLog.test.jsx
@@ -1,51 +1,61 @@
-import { render, screen, fireEvent } from '@testing-library/react'
-import { AuditLog } from '../AuditLog'
-import { useNavigate } from 'react-router-dom'
-import { vi } from 'vitest'
+import React from 'react'
+import { fireEvent, render, screen } from '@testing-library/react'
+import { beforeEach, describe, expect, it, vi } from 'vitest'
+import { AuditLog } from '@/views/Admin/AdminMenu/index.js'
+import { wrapper } from '@/tests/utils/wrapper.jsx'
-// Mock necessary modules
+// Mock i18n
vi.mock('react-i18next', () => ({
useTranslation: () => ({ t: (key) => key })
}))
-vi.mock('react-router-dom', () => ({
- ...vi.importActual('react-router-dom'),
- useNavigate: vi.fn()
-}))
-
-// Mock the BCBox component
-vi.mock('@/components/BCBox', () => ({
- default: ({ children }) =>
{children}
-}))
+// Mock react-router-dom
+const navigateMock = vi.fn()
+vi.mock('react-router-dom', async () => {
+ const actual = await vi.importActual('react-router-dom')
+ return {
+ ...actual,
+ useNavigate: () => navigateMock
+ }
+})
-// Mock the BCDataGridServer component
+// Mock BCDataGridServer so we can inspect props & simulate row clicks
vi.mock('@/components/BCDataGrid/BCDataGridServer', () => ({
- default: ({ handleRowClicked }) => (
-
-
-
- )
+ default: ({ handleRowClicked, ...props }) => {
+ // We'll return some basic UI with a button to simulate a row-click.
+ return (
+
+
+
+ )
+ }
}))
describe('AuditLog Component', () => {
- const navigateMock = vi.fn()
-
beforeEach(() => {
vi.clearAllMocks()
- useNavigate.mockReturnValue(navigateMock)
})
it('renders correctly', () => {
- render(
)
+ render(
, { wrapper })
expect(screen.getByText('admin:AuditLog')).toBeInTheDocument()
+ expect(screen.getByTestId('bc-datagrid-server')).toBeInTheDocument()
+ })
+
+ it('passes the correct props to BCDataGridServer', () => {
+ render(
, { wrapper })
+ expect(screen.getByText('Mock Row')).toBeInTheDocument()
})
- it('navigates to the correct path when a row is clicked', () => {
- render(
)
- const mockRowButton = screen.getByText('Mock Row')
- fireEvent.click(mockRowButton)
- expect(navigateMock).toHaveBeenCalledWith('/admin/audit-log/123')
+ it('uses getRowId to return auditLogId', () => {
+ const params = { data: { auditLogId: 'TEST_ID' } }
+ const rowId = params.data.auditLogId // or call the function directly
+ expect(rowId).toBe('TEST_ID')
})
})
diff --git a/frontend/src/views/Admin/AdminMenu/components/__tests__/UserActivity.test.jsx b/frontend/src/views/Admin/AdminMenu/components/__tests__/UserActivity.test.jsx
index fa3b92cc5..e07f424bc 100644
--- a/frontend/src/views/Admin/AdminMenu/components/__tests__/UserActivity.test.jsx
+++ b/frontend/src/views/Admin/AdminMenu/components/__tests__/UserActivity.test.jsx
@@ -1,83 +1,136 @@
import React from 'react'
import { render, screen } from '@testing-library/react'
-import { vi, describe, it, expect, beforeEach } from 'vitest'
+import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest'
import { UserActivity } from '../UserActivity'
import { wrapper } from '@/tests/utils/wrapper'
+import { BCGridViewer } from '@/components/BCDataGrid/BCGridViewer'
-// Mock react-i18next
vi.mock('react-i18next', () => ({
useTranslation: () => ({
t: (key) => key
})
}))
-// Mock react-router-dom
const mockUseNavigate = vi.fn()
-vi.mock('react-router-dom', () => ({
- ...vi.importActual('react-router-dom'),
- useNavigate: () => mockUseNavigate
-}))
-
-// Mock constants
-vi.mock('@/constants/routes', () => ({
- ROUTES: {
- TRANSFERS_VIEW: '/transfers/:transferId',
- ADMIN_ADJUSTMENT_VIEW: '/admin-adjustment/:transactionId',
- INITIATIVE_AGREEMENT_VIEW: '/initiative-agreement/:transactionId'
+vi.mock('react-router-dom', async () => {
+ const actual = await vi.importActual('react-router-dom')
+ return {
+ ...actual,
+ useNavigate: () => mockUseNavigate
}
-}))
+})
-// Mock userActivityColDefs
vi.mock('@/views/Admin/AdminMenu/components/_schema', () => ({
- userActivityColDefs: () => [
+ userActivityColDefs: [
{ headerName: 'Column 1', field: 'col1' },
{ headerName: 'Column 2', field: 'col2' }
]
}))
-// Variable to hold the onRowClicked function
-let onRowClickedMock
-
-// Mock BCGridViewer
+// -- Mock BCGridViewer so we can inspect its props --
vi.mock('@/components/BCDataGrid/BCGridViewer', () => ({
- BCGridViewer: (props) => {
- onRowClickedMock = props.onRowClicked
- return
BCGridViewer
- }
+ BCGridViewer: vi.fn(() =>
BCGridViewer
)
+}))
+
+vi.mock('@/hooks/useUser', () => ({
+ useGetUserActivities: () => ({
+ data: { activities: [] }, // or mock real data if needed
+ isLoading: false,
+ isError: false
+ })
}))
describe('UserActivity', () => {
beforeEach(() => {
- vi.resetAllMocks()
+ vi.clearAllMocks()
+ })
+
+ afterEach(() => {
+ vi.restoreAllMocks()
})
- it('renders the component', () => {
+ it('renders the heading and the grid', () => {
render(
, { wrapper })
+
+ // 1. Heading check
expect(screen.getByText('admin:UserActivity')).toBeInTheDocument()
+
+ // 2. BCGridViewer check
expect(screen.getByTestId('bc-grid-viewer')).toBeInTheDocument()
})
- it('navigates to the correct route when transactionType is Transfer', () => {
+ it('passes the correct props to BCGridViewer', () => {
render(
, { wrapper })
- onRowClickedMock({
- data: { transactionType: 'Transfer', transactionId: '123' }
- })
- expect(mockUseNavigate).toHaveBeenCalledWith('/transfers/123')
+
+ // BCGridViewer has been mocked, so we can inspect its calls
+ expect(BCGridViewer).toHaveBeenCalledTimes(1)
+ const gridProps = BCGridViewer.mock.calls[0][0]
+
+ // 1) gridKey
+ expect(gridProps.gridKey).toBe('all-user-activities-grid')
+
+ // 2) columnDefs
+ expect(gridProps.columnDefs).toEqual([
+ { headerName: 'Column 1', field: 'col1' },
+ { headerName: 'Column 2', field: 'col2' }
+ ])
+
+ // 3) dataKey
+ expect(gridProps.dataKey).toBe('activities')
+
+ // 4) getRowId
+ expect(gridProps.getRowId).toBeDefined()
+ // Optionally check the logic of getRowId
+ // This is a unit-style check; you can do something like:
+ const mockParams = {
+ data: {
+ transactionType: 'AdminAdjustment',
+ transactionId: '123',
+ actionTaken: 'CREATE'
+ }
+ }
+ expect(gridProps.getRowId(mockParams)).toBe('CREATE-AdminAdjustment-123')
+
+ // 5) defaultColDef
+ expect(gridProps.defaultColDef).toBeDefined()
+ expect(typeof gridProps.defaultColDef.cellRendererParams.url).toBe(
+ 'function'
+ )
})
- it('navigates to the correct route when transactionType is AdminAdjustment', () => {
+ it('generates correct URLs for each transaction type', () => {
render(
, { wrapper })
- onRowClickedMock({
- data: { transactionType: 'AdminAdjustment', transactionId: '456' }
+
+ // Extract the defaultColDef from BCGridViewer props
+ const gridProps = BCGridViewer.mock.calls[0][0]
+ const { url } = gridProps.defaultColDef.cellRendererParams
+
+ // Test different transaction types
+ const mockData = (transactionType, transactionId) => ({
+ data: { transactionType, transactionId }
})
- expect(mockUseNavigate).toHaveBeenCalledWith('/admin-adjustment/456')
+
+ // Transfer
+ expect(url(mockData('Transfer', 'ABC123'))).toBe('/transfers/ABC123')
+
+ // AdminAdjustment
+ expect(url(mockData('AdminAdjustment', 'XYZ789'))).toBe(
+ '/admin-adjustment/XYZ789'
+ )
+
+ // InitiativeAgreement
+ expect(url(mockData('InitiativeAgreement', 'IA555'))).toBe(
+ '/initiative-agreement/IA555'
+ )
})
- it('navigates to the correct route when transactionType is InitiativeAgreement', () => {
+ // If you want to verify that no rows found message is shown if data is empty
+ it('shows the overlayNoRowsTemplate when there are no activities', () => {
render(
, { wrapper })
- onRowClickedMock({
- data: { transactionType: 'InitiativeAgreement', transactionId: '789' }
- })
- expect(mockUseNavigate).toHaveBeenCalledWith('/initiative-agreement/789')
+
+ // BCGridViewer props
+ const gridProps = BCGridViewer.mock.calls[0][0]
+ // Because data is mocked to []
+ expect(gridProps.overlayNoRowsTemplate).toBe('admin:activitiesNotFound')
})
})
diff --git a/frontend/src/views/Admin/AdminMenu/components/__tests__/Users.test.jsx b/frontend/src/views/Admin/AdminMenu/components/__tests__/Users.test.jsx
new file mode 100644
index 000000000..6373303a5
--- /dev/null
+++ b/frontend/src/views/Admin/AdminMenu/components/__tests__/Users.test.jsx
@@ -0,0 +1,49 @@
+import { vi, describe, it, expect, beforeEach } from 'vitest'
+import { render, screen, fireEvent, waitFor } from '@testing-library/react'
+import { Users } from '../Users.jsx'
+import { wrapper } from '@/tests/utils/wrapper.jsx'
+
+// Mock dependencies
+vi.mock('react-i18next', () => ({
+ useTranslation: () => ({
+ t: (key) => key
+ })
+}))
+
+// Mock BCDataGridServer component
+vi.mock('@/components/BCDataGrid/BCDataGridServer', () => ({
+ default: () =>
Mocked DataGrid
+}))
+
+describe('Users Component', () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ })
+
+ it('renders without crashing', () => {
+ render(
, { wrapper })
+ expect(screen.getByText('admin:Users')).toBeInTheDocument()
+ })
+
+ it('displays the New User button', () => {
+ render(
, { wrapper })
+ const newUserButton = screen.getByText('admin:newUserBtn')
+ expect(newUserButton).toBeInTheDocument()
+ })
+
+ it('navigates to add user page when New User button is clicked', async () => {
+ render(
, { wrapper })
+ const newUserButton = screen.getByText('admin:newUserBtn')
+ fireEvent.click(newUserButton)
+
+ // Check if the navigation occurred
+ await waitFor(() => {
+ expect(window.location.href).toContain('/admin/users/add')
+ })
+ })
+
+ it('renders BCDataGridServer with correct props', () => {
+ render(
, { wrapper })
+ expect(screen.getByTestId('mocked-data-grid')).toBeInTheDocument()
+ })
+})
diff --git a/frontend/src/views/Admin/__tests__/ViewUser.test.jsx b/frontend/src/views/Admin/AdminMenu/components/__tests__/ViewUser.test.jsx
similarity index 93%
rename from frontend/src/views/Admin/__tests__/ViewUser.test.jsx
rename to frontend/src/views/Admin/AdminMenu/components/__tests__/ViewUser.test.jsx
index 6968208fa..e5055cbb2 100644
--- a/frontend/src/views/Admin/__tests__/ViewUser.test.jsx
+++ b/frontend/src/views/Admin/AdminMenu/components/__tests__/ViewUser.test.jsx
@@ -2,12 +2,12 @@ import React from 'react'
import { vi, describe, it, expect, beforeEach } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { useLocation } from 'react-router-dom'
-import * as useUserHook from '@/hooks/useUser'
-import * as useCurrentUserHook from '@/hooks/useCurrentUser'
-import * as useOrganizationHook from '@/hooks/useOrganization'
-import * as formatters from '@/utils/formatters'
-import { wrapper } from '@/tests/utils/wrapper'
-import { ViewUser } from '../AdminMenu/components/ViewUser'
+import * as useUserHook from '@/hooks/useUser.js'
+import * as useCurrentUserHook from '@/hooks/useCurrentUser.js'
+import * as useOrganizationHook from '@/hooks/useOrganization.js'
+import * as formatters from '@/utils/formatters.js'
+import { wrapper } from '@/tests/utils/wrapper.jsx'
+import { ViewUser } from '../ViewUser.jsx'
// Mocks
vi.mock('@react-keycloak/web', () => ({
@@ -153,7 +153,7 @@ describe('ViewUser Component', () => {
wrapper({ children, initialEntries: ['/admin/users/1'] })
}
)
-
+
const editButton = screen.getByRole('button', { name: /admin:editBtn/i })
fireEvent.click(editButton)
diff --git a/frontend/src/views/Admin/AdminMenu/components/_schema.js b/frontend/src/views/Admin/AdminMenu/components/_schema.js
index 1c8093fe5..235c31187 100644
--- a/frontend/src/views/Admin/AdminMenu/components/_schema.js
+++ b/frontend/src/views/Admin/AdminMenu/components/_schema.js
@@ -1,6 +1,6 @@
import {
- phoneNumberFormatter,
dateFormatter,
+ phoneNumberFormatter,
timezoneFormatter
} from '@/utils/formatters'
import {
@@ -14,6 +14,11 @@ import {
BCSelectFloatingFilter,
BCDateFloatingFilter
} from '@/components/BCDataGrid/components/index'
+import {
+ COMPLIANCE_REPORT_STATUSES,
+ TRANSACTION_TYPES,
+ TRANSFER_STATUSES
+} from '@/constants/statuses'
export const usersColumnDefs = (t) => [
{
@@ -21,7 +26,6 @@ export const usersColumnDefs = (t) => [
field: 'firstName',
minWidth: 250,
headerName: t('admin:userColLabels.userName'),
- cellRenderer: LinkRenderer,
valueGetter: (params) => params.data.firstName + ' ' + params.data.lastName
},
{
@@ -50,7 +54,6 @@ export const usersColumnDefs = (t) => [
},
floatingFilterComponent: BCSelectFloatingFilter,
suppressFloatingFilterButton: true,
- suppressHeaderFilterButton: true,
floatingFilterComponentParams: {
optionsQuery: useRoleList,
params: 'government_roles_only=true',
@@ -64,14 +67,12 @@ export const usersColumnDefs = (t) => [
colId: 'email',
field: 'keycloakEmail',
headerName: t('admin:userColLabels.email'),
- cellRenderer: LinkRenderer,
minWidth: 300
},
{
colId: 'phone',
field: 'phone',
headerName: t('admin:userColLabels.phone'),
- cellRenderer: LinkRenderer,
valueFormatter: phoneNumberFormatter,
filter: 'agTextColumnFilter',
minWidth: 120
@@ -101,8 +102,7 @@ export const usersColumnDefs = (t) => [
labelKey: 'name'
},
minWidth: 120,
- suppressFloatingFilterButton: true,
- suppressHeaderFilterButton: true
+ suppressFloatingFilterButton: true
},
{
colId: 'organizationId',
@@ -128,12 +128,52 @@ export const userActivityColDefs = [
{
colId: 'actionTaken',
field: 'actionTaken',
- headerName: 'Action Taken'
+ headerName: 'Action Taken',
+ floatingFilterComponent: BCSelectFloatingFilter,
+ floatingFilterComponentParams: {
+ valueKey: 'action',
+ labelKey: 'action',
+ optionsQuery: () => {
+ const allStatuses = [
+ ...Object.values(TRANSFER_STATUSES).map((value) => ({
+ action: value
+ }))
+ // ...Object.values(COMPLIANCE_REPORT_STATUSES).map((value) => ({
+ // action: value
+ // }))
+ ]
+
+ const deduplicatedStatuses = Array.from(
+ new Set(allStatuses.map((item) => item.action))
+ ).map((action) => ({ action }))
+
+ return {
+ data: deduplicatedStatuses,
+ isLoading: false
+ }
+ }
+ },
+ suppressFloatingFilterButton: true
},
{
colId: 'transactionType',
field: 'transactionType',
- headerName: 'Transaction Type'
+ headerName: 'Transaction Type',
+ floatingFilterComponent: BCSelectFloatingFilter,
+ floatingFilterComponentParams: {
+ valueKey: 'value',
+ labelKey: 'label',
+ optionsQuery: () => ({
+ data: [
+ ...Object.values(TRANSACTION_TYPES).map((value) => ({
+ label: value.replace(/([A-Z])/g, ' $1').trim(),
+ value
+ }))
+ ],
+ isLoading: false
+ })
+ },
+ suppressFloatingFilterButton: true
},
{
colId: 'transactionId',
@@ -150,7 +190,8 @@ export const userActivityColDefs = [
field: 'createDate',
headerName: 'Date',
valueFormatter: dateFormatter,
- filter: false
+ floatingFilterComponent: BCDateFloatingFilter,
+ suppressFloatingFilterButton: true
}
]
@@ -180,7 +221,26 @@ export const userLoginHistoryColDefs = (t) => [
{
field: 'isLoginSuccessful',
headerName: t('admin:userLoginHistoryColLabels.isLoginSuccessful'),
- cellRenderer: LoginStatusRenderer
+ cellRenderer: LoginStatusRenderer,
+ valueGetter: (params) => params.data.isLoginSuccessful,
+ filterParams: {
+ textMatcher: (filter) => {
+ return true
+ }
+ },
+ floatingFilterComponent: BCSelectFloatingFilter,
+ floatingFilterComponentParams: {
+ optionsQuery: () => ({
+ data: [
+ { id: 1, name: 'Success' },
+ { id: 0, name: 'Failed' }
+ ],
+ isLoading: false
+ }),
+ valueKey: 'name',
+ labelKey: 'name'
+ },
+ suppressFloatingFilterButton: true
},
{
field: 'loginErrorMessage',
@@ -190,7 +250,9 @@ export const userLoginHistoryColDefs = (t) => [
field: 'createDate',
headerName: t('admin:userLoginHistoryColLabels.createDate'),
cellDataType: 'dateString',
- valueFormatter: timezoneFormatter
+ valueFormatter: timezoneFormatter,
+ floatingFilterComponent: BCDateFloatingFilter,
+ suppressFloatingFilterButton: true
}
]
@@ -255,7 +317,9 @@ export const auditLogColDefs = (t) => [
filterOptions: ['equals', 'lessThan', 'greaterThan', 'inRange'],
suppressAndOrCondition: true,
buttons: ['clear']
- }
+ },
+ floatingFilterComponent: BCDateFloatingFilter,
+ suppressFloatingFilterButton: true
}
]
diff --git a/frontend/src/views/Admin/__tests__/Users.test.jsx b/frontend/src/views/Admin/__tests__/Users.test.jsx
deleted file mode 100644
index 166b59d24..000000000
--- a/frontend/src/views/Admin/__tests__/Users.test.jsx
+++ /dev/null
@@ -1,158 +0,0 @@
-import { vi, describe, it, expect, beforeEach } from 'vitest'
-import { render, screen, fireEvent, waitFor } from '@testing-library/react'
-import { MemoryRouter, Route, Routes, useLocation } from 'react-router-dom'
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
-import { Users } from '../AdminMenu/components/Users'
-import { ThemeProvider } from '@mui/material'
-import theme from '@/themes'
-
-// Mock dependencies
-vi.mock('react-i18next', () => ({
- useTranslation: () => ({
- t: (key) => key
- })
-}))
-
-vi.mock('@/constants/routes', () => ({
- ROUTES: {
- ADMIN_USERS_ADD: '/admin/users/add',
- ADMIN_USERS: '/admin/users'
- },
- apiRoutes: {
- listUsers: '/api/users'
- }
-}))
-
-vi.mock('../AdminMenu/components/_schema', () => ({
- usersColumnDefs: vi.fn(() => []),
- idirUserDefaultFilter: []
-}))
-
-vi.mock('@/utils/formatters', () => ({
- calculateRowHeight: vi.fn(() => 50)
-}))
-
-// Mock BCDataGridServer component
-vi.mock('@/components/BCDataGrid/BCDataGridServer', () => ({
- default: ({ handleRowClicked }) => (
-
handleRowClicked({ data: { userProfileId: '123' } })}
- >
- Mocked DataGrid
-
- )
-}))
-
-// Helper component to access current location
-const LocationDisplay = () => {
- const location = useLocation()
- return
{location.pathname}
-}
-
-const WrapperComponent = ({ children, initialEntries = ['/'] }) => {
- const queryClient = new QueryClient()
- return (
-
-
-
-
-
- {children}
-
- >
- }
- />
-
-
-
-
- )
-}
-
-describe('Users Component', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- })
-
- it('renders without crashing', () => {
- render(
-
-
-
- )
- expect(screen.getByText('admin:Users')).toBeInTheDocument()
- })
-
- it('displays the New User button', () => {
- render(
-
-
-
- )
- const newUserButton = screen.getByText('admin:newUserBtn')
- expect(newUserButton).toBeInTheDocument()
- })
-
- it('navigates to add user page when New User button is clicked', async () => {
- render(
-
-
-
- )
- const newUserButton = screen.getByText('admin:newUserBtn')
- fireEvent.click(newUserButton)
-
- // Check if the navigation occurred
- await waitFor(() => {
- expect(screen.getByTestId('location-display')).toHaveTextContent(
- '/admin/users/add'
- )
- })
- })
-
- it('renders BCDataGridServer with correct props', () => {
- render(
-
-
-
- )
- expect(screen.getByTestId('mocked-data-grid')).toBeInTheDocument()
- })
-
- it('displays alert message when location state has a message', () => {
- const initialEntries = [
- {
- pathname: '/admin/users',
- state: { message: 'Test alert message', severity: 'success' }
- }
- ]
- render(
-
-
-
- )
- expect(screen.getByText('Test alert message')).toBeInTheDocument()
- })
-
- it('handles row click correctly', async () => {
- render(
-
-
-
- )
-
- // Simulate a row click
- const mockedDataGrid = screen.getByTestId('mocked-data-grid')
- fireEvent.click(mockedDataGrid)
-
- // Check if the navigation occurred
- await waitFor(() => {
- const locationDisplay = screen.getByTestId('location-display')
- expect(locationDisplay.textContent).toBe('/admin/users/123')
- })
- })
-})
diff --git a/frontend/src/views/AllocationAgreements/AllocationAgreementSummary.jsx b/frontend/src/views/AllocationAgreements/AllocationAgreementSummary.jsx
index 70a536d18..3ecf13546 100644
--- a/frontend/src/views/AllocationAgreements/AllocationAgreementSummary.jsx
+++ b/frontend/src/views/AllocationAgreements/AllocationAgreementSummary.jsx
@@ -9,6 +9,7 @@ import { useTranslation } from 'react-i18next'
import { useLocation, useParams, useNavigate } from 'react-router-dom'
import { v4 as uuid } from 'uuid'
import { COMPLIANCE_REPORT_STATUSES } from '@/constants/statuses.js'
+import { LinkRenderer } from '@/utils/grid/cellRenderers.jsx'
export const AllocationAgreementSummary = ({ data, status }) => {
const [alertMessage, setAlertMessage] = useState('')
@@ -47,9 +48,14 @@ export const AllocationAgreementSummary = ({ data, status }) => {
const defaultColDef = useMemo(
() => ({
floatingFilter: false,
- filter: false
+ filter: false,
+ cellRenderer:
+ status === COMPLIANCE_REPORT_STATUSES.DRAFT ? LinkRenderer : undefined,
+ cellRendererParams: {
+ url: () => 'allocation-agreements'
+ }
}),
- []
+ [status]
)
const columns = useMemo(
@@ -137,17 +143,6 @@ export const AllocationAgreementSummary = ({ data, status }) => {
setGridKey(`allocation-agreements-grid-${uuid()}`)
}
- const handleRowClicked = (params) => {
- if (status === COMPLIANCE_REPORT_STATUSES.DRAFT) {
- navigate(
- ROUTES.REPORTS_ADD_ALLOCATION_AGREEMENTS.replace(
- ':compliancePeriod',
- compliancePeriod
- ).replace(':complianceReportId', complianceReportId)
- )
- }
- }
-
return (
@@ -172,7 +167,6 @@ export const AllocationAgreementSummary = ({ data, status }) => {
enableCopyButton={false}
defaultColDef={defaultColDef}
suppressPagination={data.allocationAgreements.length <= 10}
- handleRowClicked={handleRowClicked}
/>
diff --git a/frontend/src/views/AllocationAgreements/_schema.jsx b/frontend/src/views/AllocationAgreements/_schema.jsx
index 26ef36700..1d275cd06 100644
--- a/frontend/src/views/AllocationAgreements/_schema.jsx
+++ b/frontend/src/views/AllocationAgreements/_schema.jsx
@@ -55,7 +55,7 @@ export const allocationAgreementColDefs = (optionsData, errors, currentUser) =>
field: 'allocationTransactionType',
headerComponent: RequiredHeader,
headerName: i18n.t(
- 'allocationAgreement:allocationAgreementColLabels.transaction'
+ 'allocationAgreement:allocationAgreementColLabels.allocationTransactionType'
),
cellEditor: AutocompleteCellEditor,
cellEditorParams: {
diff --git a/frontend/src/views/ComplianceReports/ComplianceReports.jsx b/frontend/src/views/ComplianceReports/ComplianceReports.jsx
index 504d42990..948742536 100644
--- a/frontend/src/views/ComplianceReports/ComplianceReports.jsx
+++ b/frontend/src/views/ComplianceReports/ComplianceReports.jsx
@@ -1,25 +1,20 @@
-// mui components
import { Stack } from '@mui/material'
import BCBox from '@/components/BCBox'
import BCAlert from '@/components/BCAlert'
import BCDataGridServer from '@/components/BCDataGrid/BCDataGridServer'
-// react components
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useLocation, useNavigate } from 'react-router-dom'
-// Services
import { Role } from '@/components/Role'
-// constants
import { roles } from '@/constants/roles'
import { apiRoutes, ROUTES } from '@/constants/routes'
import { COMPLIANCE_REPORT_STATUSES } from '@/constants/statuses'
-// hooks
import { useCurrentUser } from '@/hooks/useCurrentUser'
import { useCreateComplianceReport } from '@/hooks/useComplianceReports'
-// internal components
import { defaultSortModel, reportsColDefs } from './components/_schema'
import { NewComplianceReportButton } from './components/NewComplianceReportButton'
import BCTypography from '@/components/BCTypography'
+import { LinkRenderer } from '@/utils/grid/cellRenderers.jsx'
export const ComplianceReports = () => {
const { t } = useTranslation(['common', 'report'])
@@ -44,19 +39,9 @@ export const ComplianceReports = () => {
(params) => params.data.complianceReportId.toString(),
[]
)
- const handleRowClicked = useCallback(
- ({ data }) => {
- const mappedRoute = ROUTES.REPORTS_VIEW.replace(
- ':compliancePeriod',
- data.compliancePeriod.description
- ).replace(':complianceReportId', data.complianceReportId)
- navigate(mappedRoute)
- },
- [navigate]
- )
const handleGridKey = useCallback(() => {
- setGridKey(`reports-grid`)
+ setGridKey('reports-grid')
}, [])
useEffect(() => {
@@ -66,42 +51,51 @@ export const ComplianceReports = () => {
}
}, [location.state])
- const {
- mutate: createComplianceReport,
- isLoading: isCreating,
- isError
- } = useCreateComplianceReport(currentUser?.organization?.organizationId, {
- onSuccess: (response, variables) => {
- setAlertMessage(
- t('report:actionMsgs.successText', {
- status: 'created'
- })
- )
- setIsButtonLoading(false)
- setAlertSeverity('success')
- navigate(
- ROUTES.REPORTS_VIEW.replace(
- ':compliancePeriod',
- response.data.compliancePeriod.description
- ).replace(':complianceReportId', response.data.complianceReportId),
- { state: { data: response.data, newReport: true } }
- )
- alertRef.current.triggerAlert()
- },
- onError: (_error, _variables) => {
- setIsButtonLoading(false)
- const errorMsg = _error.response.data?.detail
- setAlertMessage(errorMsg)
- setAlertSeverity('error')
- alertRef.current.triggerAlert()
- }
- })
+ const { mutate: createComplianceReport, isLoading: isCreating } =
+ useCreateComplianceReport(currentUser?.organization?.organizationId, {
+ onSuccess: (response, variables) => {
+ setAlertMessage(
+ t('report:actionMsgs.successText', {
+ status: 'created'
+ })
+ )
+ setIsButtonLoading(false)
+ setAlertSeverity('success')
+ navigate(
+ ROUTES.REPORTS_VIEW.replace(
+ ':compliancePeriod',
+ response.data.compliancePeriod.description
+ ).replace(':complianceReportId', response.data.complianceReportId),
+ { state: { data: response.data, newReport: true } }
+ )
+ alertRef.current.triggerAlert()
+ },
+ onError: (_error, _variables) => {
+ setIsButtonLoading(false)
+ const errorMsg = _error.response.data?.detail
+ setAlertMessage(errorMsg)
+ setAlertSeverity('error')
+ alertRef.current.triggerAlert()
+ }
+ })
useEffect(() => {
if (isCreating) {
setIsButtonLoading(true)
}
}, [isCreating])
+
+ const defaultColDef = useMemo(
+ () => ({
+ cellRenderer: LinkRenderer,
+ cellRendererParams: {
+ url: (data) =>
+ `${data.data.compliancePeriod.description}/${data.data.complianceReportId}`
+ }
+ }),
+ []
+ )
+
return (
<>
@@ -159,8 +153,8 @@ export const ComplianceReports = () => {
defaultFilterModel={location.state?.filters}
gridOptions={gridOptions}
handleGridKey={handleGridKey}
- handleRowClicked={handleRowClicked}
enableCopyButton={false}
+ defaultColDef={defaultColDef}
/>
diff --git a/frontend/src/views/ComplianceReports/components/_schema.jsx b/frontend/src/views/ComplianceReports/components/_schema.jsx
index 6c52b88b6..e2e9ba6a4 100644
--- a/frontend/src/views/ComplianceReports/components/_schema.jsx
+++ b/frontend/src/views/ComplianceReports/components/_schema.jsx
@@ -75,7 +75,8 @@ export const reportsColDefs = (t, bceidRole) => [
}),
valueKey: 'name',
labelKey: 'name'
- }
+ },
+ suppressFloatingFilterButton: true
},
{
field: 'updateDate',
@@ -91,7 +92,8 @@ export const reportsColDefs = (t, bceidRole) => [
buttons: ['clear'],
maxValidYear: 2400
},
- floatingFilterComponent: BCDateFloatingFilter
+ floatingFilterComponent: BCDateFloatingFilter,
+ suppressFloatingFilterButton: true
}
]
diff --git a/frontend/src/views/FinalSupplyEquipments/FinalSupplyEquipmentSummary.jsx b/frontend/src/views/FinalSupplyEquipments/FinalSupplyEquipmentSummary.jsx
index a8c7935a1..699ef8c97 100644
--- a/frontend/src/views/FinalSupplyEquipments/FinalSupplyEquipmentSummary.jsx
+++ b/frontend/src/views/FinalSupplyEquipments/FinalSupplyEquipmentSummary.jsx
@@ -1,12 +1,12 @@
import BCAlert from '@/components/BCAlert'
import BCBox from '@/components/BCBox'
import BCDataGridServer from '@/components/BCDataGrid/BCDataGridServer'
-import { apiRoutes, ROUTES } from '@/constants/routes'
-import { CommonArrayRenderer } from '@/utils/grid/cellRenderers'
+import { apiRoutes } from '@/constants/routes'
+import { CommonArrayRenderer, LinkRenderer } from '@/utils/grid/cellRenderers'
import Grid2 from '@mui/material/Unstable_Grid2/Grid2'
import { useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useLocation, useParams, useNavigate } from 'react-router-dom'
+import { useLocation, useParams } from 'react-router-dom'
import { v4 as uuid } from 'uuid'
import { numberFormatter } from '@/utils/formatters.js'
import { COMPLIANCE_REPORT_STATUSES } from '@/constants/statuses.js'
@@ -15,12 +15,11 @@ export const FinalSupplyEquipmentSummary = ({ data, status }) => {
const [alertMessage, setAlertMessage] = useState('')
const [alertSeverity, setAlertSeverity] = useState('info')
const [gridKey, setGridKey] = useState('final-supply-equipments-grid')
- const { complianceReportId, compliancePeriod } = useParams()
+ const { complianceReportId } = useParams()
const gridRef = useRef()
const { t } = useTranslation(['common', 'finalSupplyEquipments'])
const location = useLocation()
- const navigate = useNavigate()
useEffect(() => {
if (location.state?.message) {
@@ -45,10 +44,16 @@ export const FinalSupplyEquipmentSummary = ({ data, status }) => {
const defaultColDef = useMemo(
() => ({
floatingFilter: false,
- filter: false
+ filter: false,
+ cellRenderer:
+ status === COMPLIANCE_REPORT_STATUSES.DRAFT ? LinkRenderer : undefined,
+ cellRendererParams: {
+ url: () => 'final-supply-equipments'
+ }
}),
- []
+ [status]
)
+
const columns = useMemo(
() => [
{
@@ -188,17 +193,6 @@ export const FinalSupplyEquipmentSummary = ({ data, status }) => {
setGridKey(`final-supply-equipments-grid-${uuid()}`)
}
- const handleRowClicked = () => {
- if (status === COMPLIANCE_REPORT_STATUSES.DRAFT) {
- navigate(
- ROUTES.REPORTS_ADD_FINAL_SUPPLY_EQUIPMENTS.replace(
- ':compliancePeriod',
- compliancePeriod
- ).replace(':complianceReportId', complianceReportId)
- )
- }
- }
-
return (
@@ -223,7 +217,6 @@ export const FinalSupplyEquipmentSummary = ({ data, status }) => {
enableCopyButton={false}
defaultColDef={defaultColDef}
suppressPagination={data.finalSupplyEquipments.length <= 10}
- handleRowClicked={handleRowClicked}
/>
diff --git a/frontend/src/views/FuelCodes/FuelCodes.jsx b/frontend/src/views/FuelCodes/FuelCodes.jsx
index fba322f9a..a19fd7a7f 100644
--- a/frontend/src/views/FuelCodes/FuelCodes.jsx
+++ b/frontend/src/views/FuelCodes/FuelCodes.jsx
@@ -14,10 +14,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { Stack } from '@mui/material'
import BCTypography from '@/components/BCTypography'
import Grid2 from '@mui/material/Unstable_Grid2/Grid2'
-import { useEffect, useState } from 'react'
+import { useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useLocation, useNavigate } from 'react-router-dom'
import { fuelCodeColDefs } from './_schema'
+import { LinkRenderer } from '@/utils/grid/cellRenderers.jsx'
const FuelCodesBase = () => {
const [isDownloadingFuelCodes, setIsDownloadingFuelCodes] = useState(false)
@@ -40,11 +41,15 @@ const FuelCodesBase = () => {
return params.data.fuelCodeId.toString()
}
- const handleRowClicked = (params) => {
- navigate(
- ROUTES.FUELCODES_EDIT.replace(':fuelCodeID', params.data.fuelCodeId)
- )
- }
+ const defaultColDef = useMemo(
+ () => ({
+ cellRenderer: LinkRenderer,
+ cellRendererParams: {
+ url: (data) => data.data.fuelCodeId
+ }
+ }),
+ []
+ )
const handleDownloadFuelCodes = async () => {
setIsDownloadingFuelCodes(true)
@@ -110,14 +115,10 @@ const FuelCodesBase = () => {
columnDefs={fuelCodeColDefs(t)}
query={useGetFuelCodes}
queryParams={{ cacheTime: 0, staleTime: 0 }}
- dataKey={'fuelCodes'}
+ dataKey="fuelCodes"
getRowId={getRowId}
- onRowClicked={handleRowClicked}
overlayNoRowsTemplate={t('fuelCode:noFuelCodesFound')}
- autoSizeStrategy={{
- defaultMinWidth: 50,
- defaultMaxWidth: 600
- }}
+ defaultColDef={defaultColDef}
/>
diff --git a/frontend/src/views/FuelCodes/_schema.jsx b/frontend/src/views/FuelCodes/_schema.jsx
index cb93d7617..d2eade3b5 100644
--- a/frontend/src/views/FuelCodes/_schema.jsx
+++ b/frontend/src/views/FuelCodes/_schema.jsx
@@ -1,39 +1,42 @@
import {
CommonArrayRenderer,
- FuelCodeStatusTextRenderer,
+ FuelCodeStatusRenderer,
TextRenderer
} from '@/utils/grid/cellRenderers'
import { numberFormatter, timezoneFormatter } from '@/utils/formatters'
import BCTypography from '@/components/BCTypography'
-import { BCColumnSetFilter } from '@/components/BCDataGrid/components'
+import {
+ BCSelectFloatingFilter,
+ BCDateFloatingFilter
+} from '@/components/BCDataGrid/components'
import { useFuelCodeStatuses, useTransportModes } from '@/hooks/useFuelCode'
export const fuelCodeColDefs = (t) => [
{
field: 'status',
headerName: t('fuelCode:fuelCodeColLabels.status'),
- floatingFilterComponent: BCColumnSetFilter,
+ floatingFilterComponent: BCSelectFloatingFilter,
floatingFilterComponentParams: {
- apiOptionField: 'status',
- apiQuery: useFuelCodeStatuses,
- disableCloseOnSelect: false,
- multiple: false
+ valueKey: 'status',
+ labelKey: 'status',
+ optionsQuery: useFuelCodeStatuses
},
+ suppressFloatingFilterButton: true,
valueGetter: (params) => params.data.fuelCodeStatus.status,
- cellRenderer: FuelCodeStatusTextRenderer
+ cellRenderer: FuelCodeStatusRenderer
},
{
field: 'prefix',
headerName: t('fuelCode:fuelCodeColLabels.prefix'),
- valueGetter: (params) => params.data.fuelCodePrefix.prefix,
- cellRenderer: TextRenderer
+ suppressFloatingFilterButton: true,
+ valueGetter: (params) => params.data.fuelCodePrefix.prefix
},
{
field: 'fuelSuffix',
headerName: t('fuelCode:fuelCodeColLabels.fuelSuffix'),
- cellRenderer: TextRenderer,
type: 'numericColumn',
filter: 'agNumberColumnFilter',
+ suppressFloatingFilterButton: true,
filterParams: {
filterOptions: ['startsWith'],
buttons: ['clear']
@@ -42,7 +45,6 @@ export const fuelCodeColDefs = (t) => [
{
field: 'carbonIntensity',
headerName: t('fuelCode:fuelCodeColLabels.carbonIntensity'),
- cellRenderer: TextRenderer,
type: 'numericColumn',
filter: 'agNumberColumnFilter',
filterParams: {
@@ -52,78 +54,65 @@ export const fuelCodeColDefs = (t) => [
},
{
field: 'edrms',
- headerName: t('fuelCode:fuelCodeColLabels.edrms'),
- cellRenderer: TextRenderer
+ headerName: t('fuelCode:fuelCodeColLabels.edrms')
},
{
field: 'company',
headerName: t('fuelCode:fuelCodeColLabels.company'),
- cellRenderer: TextRenderer,
minWidth: 300
},
{
field: 'contactName',
headerName: t('fuelCode:fuelCodeColLabels.contactName'),
- cellRenderer: TextRenderer,
minWidth: 300
},
{
field: 'contactEmail',
headerName: t('fuelCode:fuelCodeColLabels.contactEmail'),
- cellRenderer: TextRenderer,
minWidth: 300
},
{
field: 'applicationDate',
headerName: t('fuelCode:fuelCodeColLabels.applicationDate'),
- filter: false,
- cellRenderer: TextRenderer
+ filter: false
},
{
field: 'approvalDate',
headerName: t('fuelCode:fuelCodeColLabels.approvalDate'),
- filter: false,
- cellRenderer: TextRenderer
+ filter: false
},
{
field: 'effectiveDate',
headerName: t('fuelCode:fuelCodeColLabels.effectiveDate'),
- filter: false,
- cellRenderer: TextRenderer
+ filter: false
},
{
field: 'expirationDate',
headerName: t('fuelCode:fuelCodeColLabels.expirationDate'),
- filter: false,
- cellRenderer: TextRenderer
+ filter: false
},
{
field: 'fuelType',
headerName: t('fuelCode:fuelCodeColLabels.fuelType'),
- cellRenderer: TextRenderer,
valueGetter: (params) => params.data.fuelType.fuelType
},
{
field: 'feedstock',
- headerName: t('fuelCode:fuelCodeColLabels.feedstock'),
- cellRenderer: TextRenderer
+ headerName: t('fuelCode:fuelCodeColLabels.feedstock')
},
{
field: 'feedstockLocation',
headerName: t('fuelCode:fuelCodeColLabels.feedstockLocation'),
- cellRenderer: TextRenderer,
minWidth: 300
},
{
field: 'feedstockMisc',
headerName: t('fuelCode:fuelCodeColLabels.misc'),
- cellRenderer: TextRenderer,
minWidth: 495
},
{
field: 'fuelProductionFacilityCity',
headerName: t('fuelCode:fuelCodeColLabels.fuelProductionFacilityCity'),
- cellRenderer: TextRenderer,
minWidth: 325
},
{
@@ -131,69 +120,64 @@ export const fuelCodeColDefs = (t) => [
headerName: t(
'fuelCode:fuelCodeColLabels.fuelProductionFacilityProvinceState'
),
- cellRenderer: TextRenderer,
minWidth: 325
},
{
field: 'fuelProductionFacilityCountry',
headerName: t('fuelCode:fuelCodeColLabels.fuelProductionFacilityCountry'),
- cellRenderer: TextRenderer,
minWidth: 325
},
{
field: 'facilityNameplateCapacity',
headerName: t('fuelCode:fuelCodeColLabels.facilityNameplateCapacity'),
valueFormatter: numberFormatter,
- cellRenderer: TextRenderer,
minWidth: 290,
type: 'numericColumn'
},
{
field: 'facilityNameplateCapacityUnit',
headerName: t('fuelCode:fuelCodeColLabels.facilityNameplateCapacityUnit'),
- cellRenderer: TextRenderer,
minWidth: 290
},
{
field: 'feedstockFuelTransportMode',
headerName: t('fuelCode:fuelCodeColLabels.feedstockFuelTransportMode'),
sortable: false,
- floatingFilterComponent: BCColumnSetFilter,
+ floatingFilterComponent: BCSelectFloatingFilter,
floatingFilterComponentParams: {
- apiOptionField: 'transportMode',
- apiQuery: useTransportModes,
- disableCloseOnSelect: false,
- multiple: false
+ valueKey: 'transportMode',
+ labelKey: 'transportMode',
+ optionsQuery: useTransportModes
},
+ suppressFloatingFilterButton: true,
minWidth: 335,
valueGetter: (params) =>
params.data.feedstockFuelTransportModes.map(
(item) => item.feedstockFuelTransportMode.transportMode
),
- cellRenderer: (props) =>
+ cellRenderer: (props) =>
},
{
field: 'finishedFuelTransportMode',
headerName: t('fuelCode:fuelCodeColLabels.finishedFuelTransportMode'),
sortable: false,
- floatingFilterComponent: BCColumnSetFilter,
+ floatingFilterComponent: BCSelectFloatingFilter,
floatingFilterComponentParams: {
- apiOptionField: 'transportMode',
- apiQuery: useTransportModes,
- disableCloseOnSelect: false,
- multiple: false
+ valueKey: 'transportMode',
+ labelKey: 'transportMode',
+ optionsQuery: useTransportModes
},
+ suppressFloatingFilterButton: true,
minWidth: 335,
valueGetter: (params) =>
params.data.finishedFuelTransportModes.map(
(item) => item.finishedFuelTransportMode.transportMode
),
- cellRenderer: (props) =>
+ cellRenderer: (props) =>
},
{
field: 'formerCompany',
headerName: t('fuelCode:fuelCodeColLabels.formerCompany'),
- cellRenderer: TextRenderer,
minWidth: 300
},
{
@@ -212,7 +196,6 @@ export const fuelCodeColDefs = (t) => [
{
field: 'notes',
headerName: t('fuelCode:fuelCodeColLabels.notes'),
- cellRenderer: TextRenderer,
minWidth: 600
}
]
diff --git a/frontend/src/views/FuelExports/FuelExportSummary.jsx b/frontend/src/views/FuelExports/FuelExportSummary.jsx
index 76898317f..ef9cbd5b0 100644
--- a/frontend/src/views/FuelExports/FuelExportSummary.jsx
+++ b/frontend/src/views/FuelExports/FuelExportSummary.jsx
@@ -6,20 +6,19 @@ import { formatNumberWithCommas as valueFormatter } from '@/utils/formatters'
import Grid2 from '@mui/material/Unstable_Grid2/Grid2'
import { useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useLocation, useParams, useNavigate } from 'react-router-dom'
+import { useLocation, useParams } from 'react-router-dom'
import i18n from '@/i18n'
-import { ROUTES } from '@/constants/routes'
import { COMPLIANCE_REPORT_STATUSES } from '@/constants/statuses.js'
+import { LinkRenderer } from '@/utils/grid/cellRenderers.jsx'
export const FuelExportSummary = ({ data, status }) => {
const [alertMessage, setAlertMessage] = useState('')
const [alertSeverity, setAlertSeverity] = useState('info')
- const { complianceReportId, compliancePeriod } = useParams()
+ const { complianceReportId } = useParams()
const gridRef = useRef()
const { t } = useTranslation(['common', 'fuelExport'])
const location = useLocation()
- const navigate = useNavigate()
useEffect(() => {
if (location.state?.message) {
@@ -45,9 +44,14 @@ export const FuelExportSummary = ({ data, status }) => {
const defaultColDef = useMemo(
() => ({
floatingFilter: false,
- filter: false
+ filter: false,
+ cellRenderer:
+ status === COMPLIANCE_REPORT_STATUSES.DRAFT ? LinkRenderer : undefined,
+ cellRendererParams: {
+ url: () => 'fuel-exports'
+ }
}),
- []
+ [status]
)
// TODO: The values for the following columns must be determined
@@ -125,17 +129,6 @@ export const FuelExportSummary = ({ data, status }) => {
return params.data.fuelExportId.toString()
}
- const handleRowClicked = () => {
- if (status === COMPLIANCE_REPORT_STATUSES.DRAFT) {
- navigate(
- ROUTES.REPORTS_ADD_FUEL_EXPORTS.replace(
- ':compliancePeriod',
- compliancePeriod
- ).replace(':complianceReportId', complianceReportId)
- )
- }
- }
-
return (
@@ -158,7 +151,6 @@ export const FuelExportSummary = ({ data, status }) => {
enableCopyButton={false}
defaultColDef={defaultColDef}
suppressPagination={data.fuelExports.length <= 10}
- onRowClicked={handleRowClicked}
/>
diff --git a/frontend/src/views/FuelSupplies/AddEditFuelSupplies.jsx b/frontend/src/views/FuelSupplies/AddEditFuelSupplies.jsx
index 735f09eee..f76063182 100644
--- a/frontend/src/views/FuelSupplies/AddEditFuelSupplies.jsx
+++ b/frontend/src/views/FuelSupplies/AddEditFuelSupplies.jsx
@@ -103,7 +103,7 @@ export const AddEditFuelSupplies = () => {
item.fuelType?.fuelType === 'Other' ? item.fuelTypeOther : null,
provisionOfTheAct: item.provisionOfTheAct?.name,
fuelCode: item.fuelCode?.fuelCode,
- endUse: item.endUse?.type || 'Any',
+ endUse: item.endUse?.type,
id: uuid()
}))
setRowData([...updatedRowData, { id: uuid() }])
@@ -140,7 +140,7 @@ export const AddEditFuelSupplies = () => {
item.fuelType?.fuelType === 'Other' ? item.fuelTypeOther : null,
provisionOfTheAct: item.provisionOfTheAct?.name,
fuelCode: item.fuelCode?.fuelCode,
- endUse: item.endUse?.type || 'Any',
+ endUse: item.endUse?.type,
id: uuid()
}))
setRowData(updatedRowData)
@@ -161,11 +161,39 @@ export const AddEditFuelSupplies = () => {
(item) => item.fuelCategory
)
+ const endUseTypes = selectedFuelType.eerRatios.map(
+ (item) => item.endUseType
+ )
+
// Set to null if multiple options, otherwise use first item
const categoryValue =
fuelCategoryOptions.length === 1 ? fuelCategoryOptions[0] : null
+ const endUseValue =
+ endUseTypes.length === 1 ? endUseTypes[0].type : null
params.node.setDataValue('fuelCategory', categoryValue)
+ params.node.setDataValue('endUseType', endUseValue)
+ }
+ }
+
+ if (params.column.colId === 'fuelCategory') {
+ const selectedFuelType = optionsData?.fuelTypes?.find(
+ (obj) => params.node.data.fuelType === obj.fuelType
+ )
+
+ if (selectedFuelType) {
+ const endUseTypes = selectedFuelType.eerRatios
+ .filter(
+ (item) =>
+ item.fuelCategory.fuelCategory === params.data.fuelCategory
+ )
+ .map((item) => item.endUseType)
+
+ // Set to null if multiple options, otherwise use first item
+ const endUseValue =
+ endUseTypes.length === 1 ? endUseTypes[0].type : null
+
+ params.node.setDataValue('endUseType', endUseValue)
}
}
},
diff --git a/frontend/src/views/FuelSupplies/FuelSupplySummary.jsx b/frontend/src/views/FuelSupplies/FuelSupplySummary.jsx
index b9808f1ad..af7843444 100644
--- a/frontend/src/views/FuelSupplies/FuelSupplySummary.jsx
+++ b/frontend/src/views/FuelSupplies/FuelSupplySummary.jsx
@@ -1,27 +1,26 @@
import BCAlert from '@/components/BCAlert'
import BCBox from '@/components/BCBox'
import BCDataGridServer from '@/components/BCDataGrid/BCDataGridServer'
-import { apiRoutes, ROUTES } from '@/constants/routes'
+import { apiRoutes } from '@/constants/routes'
import { formatNumberWithCommas as valueFormatter } from '@/utils/formatters'
import Grid2 from '@mui/material/Unstable_Grid2/Grid2'
import { useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useLocation, useNavigate, useParams } from 'react-router-dom'
+import { useLocation, useParams } from 'react-router-dom'
import { v4 as uuid } from 'uuid'
import i18n from '@/i18n'
-import { StandardCellWarningAndErrors } from '@/utils/grid/errorRenderers'
import { COMPLIANCE_REPORT_STATUSES } from '@/constants/statuses.js'
+import { LinkRenderer } from '@/utils/grid/cellRenderers.jsx'
export const FuelSupplySummary = ({ data, status }) => {
const [alertMessage, setAlertMessage] = useState('')
const [alertSeverity, setAlertSeverity] = useState('info')
const [gridKey, setGridKey] = useState(`fuel-supplies-grid`)
- const { complianceReportId, compliancePeriod } = useParams()
+ const { complianceReportId } = useParams()
const gridRef = useRef()
const { t } = useTranslation(['common', 'fuelSupply'])
const location = useLocation()
- const navigate = useNavigate()
useEffect(() => {
if (location.state?.message) {
@@ -47,12 +46,16 @@ export const FuelSupplySummary = ({ data, status }) => {
const defaultColDef = useMemo(
() => ({
floatingFilter: false,
- filter: false
+ filter: false,
+ cellRenderer:
+ status === COMPLIANCE_REPORT_STATUSES.DRAFT ? LinkRenderer : undefined,
+ cellRendererParams: {
+ url: () => 'supply-of-fuel'
+ }
}),
- []
+ [status]
)
- // TODO: The values for the following columns must be determined
const columns = useMemo(
() => [
{
@@ -127,17 +130,6 @@ export const FuelSupplySummary = ({ data, status }) => {
setGridKey(`fuel-supplies-grid-${uuid()}`)
}
- const handleRowClicked = () => {
- if (status === COMPLIANCE_REPORT_STATUSES.DRAFT) {
- navigate(
- ROUTES.REPORTS_ADD_SUPPLY_OF_FUEL.replace(
- ':compliancePeriod',
- compliancePeriod
- ).replace(':complianceReportId', complianceReportId)
- )
- }
- }
-
return (
@@ -162,7 +154,6 @@ export const FuelSupplySummary = ({ data, status }) => {
enableCopyButton={false}
defaultColDef={defaultColDef}
suppressPagination={data.fuelSupplies.length <= 10}
- handleRowClicked={handleRowClicked}
/>
diff --git a/frontend/src/views/FuelSupplies/_schema.jsx b/frontend/src/views/FuelSupplies/_schema.jsx
index ba1b52df9..9cbe65cbe 100644
--- a/frontend/src/views/FuelSupplies/_schema.jsx
+++ b/frontend/src/views/FuelSupplies/_schema.jsx
@@ -193,7 +193,7 @@ export const fuelSupplyColDefs = (optionsData, errors, warnings) => [
{
field: 'endUseType',
headerComponent: RequiredHeader,
- headerName: i18n.t('fuelSupply:fuelSupplyColLabels.endUse'),
+ headerName: i18n.t('fuelSupply:fuelSupplyColLabels.endUseId'),
cellEditorParams: (params) => ({
options: [
...new Set(
@@ -206,7 +206,7 @@ export const fuelSupplyColDefs = (optionsData, errors, warnings) => [
?.map((item) => item.endUseType?.type)
.sort()
)
- ].filter((item) => item != null) || ['Any'],
+ ].filter((item) => item != null),
multiple: false,
disableCloseOnSelect: false,
freeSolo: false,
@@ -219,14 +219,10 @@ export const fuelSupplyColDefs = (optionsData, errors, warnings) => [
cellStyle: (params) =>
StandardCellWarningAndErrors(params, errors, warnings),
suppressKeyboardEvent,
- valueGetter: (params) => {
- return params.colDef?.cellEditorParams(params).options.length < 1
- ? 'Any'
- : params.data?.endUseType?.type
- },
+ valueGetter: (params) => params.data.endUseType?.type,
editable: (params) => {
const cellParams = params.colDef?.cellEditorParams(params)
- return cellParams.options.length > 0
+ return cellParams.options.length > 1
},
valueSetter: (params) => {
if (params.newValue) {
diff --git a/frontend/src/views/Notifications/NotificationMenu/components/_schema.jsx b/frontend/src/views/Notifications/NotificationMenu/components/_schema.jsx
index 601fb29c6..235eccc50 100644
--- a/frontend/src/views/Notifications/NotificationMenu/components/_schema.jsx
+++ b/frontend/src/views/Notifications/NotificationMenu/components/_schema.jsx
@@ -1,6 +1,7 @@
import { dateFormatter } from '@/utils/formatters'
import { actions } from '@/components/BCDataGrid/columns'
import { ROUTES } from '@/constants/routes'
+import { BCDateFloatingFilter } from '@/components/BCDataGrid/components'
export const columnDefs = (t, currentUser) => [
{
@@ -16,7 +17,8 @@ export const columnDefs = (t, currentUser) => [
{
colId: 'date',
field: 'date',
- cellDataType: 'date',
+ floatingFilterComponent: BCDateFloatingFilter,
+ suppressFloatingFilterButton: true,
headerName: t('notifications:notificationColLabels.date'),
valueGetter: (params) => params.data.createDate,
valueFormatter: dateFormatter
diff --git a/frontend/src/views/NotionalTransfers/AddEditNotionalTransfers.jsx b/frontend/src/views/NotionalTransfers/AddEditNotionalTransfers.jsx
index 812192fa9..00a633f7d 100644
--- a/frontend/src/views/NotionalTransfers/AddEditNotionalTransfers.jsx
+++ b/frontend/src/views/NotionalTransfers/AddEditNotionalTransfers.jsx
@@ -1,9 +1,8 @@
-import { useState, useEffect, useMemo, useRef, useCallback } from 'react'
+import { useState, useEffect, useRef, useCallback } from 'react'
import BCTypography from '@/components/BCTypography'
import Grid2 from '@mui/material/Unstable_Grid2/Grid2'
import { useTranslation } from 'react-i18next'
import { useLocation, useNavigate, useParams } from 'react-router-dom'
-import { BCAlert2 } from '@/components/BCAlert'
import BCBox from '@/components/BCBox'
import Loading from '@/components/Loading'
import { defaultColDef, notionalTransferColDefs } from './_schema'
@@ -15,7 +14,6 @@ import {
import { useCurrentUser } from '@/hooks/useCurrentUser'
import { v4 as uuid } from 'uuid'
import { BCGridEditor } from '@/components/BCDataGrid/BCGridEditor'
-import { useApiService } from '@/services/useApiService'
import * as ROUTES from '@/constants/routes/routes.js'
export const AddEditNotionalTransfers = () => {
@@ -26,7 +24,6 @@ export const AddEditNotionalTransfers = () => {
const gridRef = useRef(null)
const alertRef = useRef()
const location = useLocation()
- const apiService = useApiService()
const { t } = useTranslation(['common', 'notionalTransfer', 'reports'])
const { complianceReportId, compliancePeriod } = useParams()
const {
diff --git a/frontend/src/views/NotionalTransfers/NotionalTransferSummary.jsx b/frontend/src/views/NotionalTransfers/NotionalTransferSummary.jsx
index daa71fae1..282e72164 100644
--- a/frontend/src/views/NotionalTransfers/NotionalTransferSummary.jsx
+++ b/frontend/src/views/NotionalTransfers/NotionalTransferSummary.jsx
@@ -3,21 +3,20 @@ import BCBox from '@/components/BCBox'
import { BCGridViewer } from '@/components/BCDataGrid/BCGridViewer'
import { useGetNotionalTransfers } from '@/hooks/useNotionalTransfer'
import Grid2 from '@mui/material/Unstable_Grid2/Grid2'
-import { useEffect, useState, useMemo } from 'react'
+import { useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { useLocation, useParams, useNavigate } from 'react-router-dom'
+import { useLocation, useParams } from 'react-router-dom'
import { formatNumberWithCommas as valueFormatter } from '@/utils/formatters'
-import { ROUTES } from '@/constants/routes'
import { COMPLIANCE_REPORT_STATUSES } from '@/constants/statuses.js'
+import { LinkRenderer } from '@/utils/grid/cellRenderers.jsx'
export const NotionalTransferSummary = ({ data, status }) => {
const [alertMessage, setAlertMessage] = useState('')
const [alertSeverity, setAlertSeverity] = useState('info')
- const { complianceReportId, compliancePeriod } = useParams()
+ const { complianceReportId } = useParams()
const { t } = useTranslation(['common', 'notionalTransfers'])
const location = useLocation()
- const navigate = useNavigate()
useEffect(() => {
if (location.state?.message) {
@@ -30,22 +29,16 @@ export const NotionalTransferSummary = ({ data, status }) => {
const defaultColDef = useMemo(
() => ({
floatingFilter: false,
- filter: false
+ filter: false,
+ cellRenderer:
+ status === COMPLIANCE_REPORT_STATUSES.DRAFT ? LinkRenderer : undefined,
+ cellRendererParams: {
+ url: () => 'notional-transfers'
+ }
}),
- []
+ [status]
)
- const handleRowClicked = () => {
- if (status === COMPLIANCE_REPORT_STATUSES.DRAFT) {
- navigate(
- ROUTES.REPORTS_ADD_NOTIONAL_TRANSFERS.replace(
- ':compliancePeriod',
- compliancePeriod
- ).replace(':complianceReportId', complianceReportId)
- )
- }
- }
-
const columns = [
{
headerName: t('notionalTransfer:notionalTransferColLabels.legalName'),
@@ -95,7 +88,7 @@ export const NotionalTransferSummary = ({ data, status }) => {
defaultColDef={defaultColDef}
query={useGetNotionalTransfers}
queryParams={{ complianceReportId }}
- dataKey={'notionalTransfers'}
+ dataKey="notionalTransfers"
suppressPagination={data?.length <= 10}
autoSizeStrategy={{
type: 'fitCellContents',
@@ -105,7 +98,6 @@ export const NotionalTransferSummary = ({ data, status }) => {
enableCellTextSelection
ensureDomOrder
handleRo
- onRowClicked={handleRowClicked}
/>
diff --git a/frontend/src/views/Organizations/Organizations.jsx b/frontend/src/views/Organizations/Organizations.jsx
index aad8c2aa7..bca77d4fa 100644
--- a/frontend/src/views/Organizations/Organizations.jsx
+++ b/frontend/src/views/Organizations/Organizations.jsx
@@ -12,7 +12,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { organizationsColDefs } from './ViewOrganization/_schema'
// react components
import { ROUTES, apiRoutes } from '@/constants/routes'
-import { useCallback, useEffect, useRef, useState } from 'react'
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useLocation, useNavigate } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
// Services
@@ -20,6 +20,7 @@ import { DownloadButton } from '@/components/DownloadButton'
import { useApiService } from '@/services/useApiService'
import { roles } from '@/constants/roles'
import { Role } from '@/components/Role'
+import { LinkRenderer } from '@/utils/grid/cellRenderers.jsx'
export const Organizations = () => {
const { t } = useTranslation(['common', 'org'])
@@ -39,12 +40,7 @@ export const Organizations = () => {
const location = useLocation()
const defaultSortModel = [{ field: 'name', direction: 'asc' }]
- // eslint-disable-next-line react-hooks/exhaustive-deps
- const handleRowClicked = useCallback((params) => {
- navigate(
- ROUTES.ORGANIZATIONS_VIEW.replace(':orgID', params.data.organizationId)
- )
- })
+
const apiService = useApiService()
const [isDownloadingOrgs, setIsDownloadingOrgs] = useState(false)
const [isDownloadingUsers, setIsDownloadingUsers] = useState(false)
@@ -85,6 +81,16 @@ export const Organizations = () => {
}
}
+ const defaultColDef = useMemo(
+ () => ({
+ cellRenderer: LinkRenderer,
+ cellRendererParams: {
+ url: (data) => data.data.organizationId
+ }
+ }),
+ []
+ )
+
return (
<>
@@ -137,16 +143,16 @@ export const Organizations = () => {
>
diff --git a/frontend/src/views/Organizations/ViewOrganization/ViewOrganization.jsx b/frontend/src/views/Organizations/ViewOrganization/ViewOrganization.jsx
index d3c8dcf40..05fc5fbb6 100644
--- a/frontend/src/views/Organizations/ViewOrganization/ViewOrganization.jsx
+++ b/frontend/src/views/Organizations/ViewOrganization/ViewOrganization.jsx
@@ -5,24 +5,24 @@ import BCAlert from '@/components/BCAlert'
import BCDataGridServer from '@/components/BCDataGrid/BCDataGridServer'
import Loading from '@/components/Loading'
import BCWidgetCard from '@/components/BCWidgetCard/BCWidgetCard'
-import colors from '@/themes/base/colors.js'
import { faCirclePlus } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { useCallback, useEffect, useRef, useState } from 'react'
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { ROUTES, apiRoutes } from '@/constants/routes'
+import { apiRoutes, ROUTES } from '@/constants/routes'
import { useCurrentUser } from '@/hooks/useCurrentUser'
import {
useOrganization,
useOrganizationBalance
} from '@/hooks/useOrganization'
import { constructAddress } from '@/utils/constructAddress'
-import { calculateRowHeight, phoneNumberFormatter } from '@/utils/formatters'
+import { phoneNumberFormatter } from '@/utils/formatters'
import { useLocation, useNavigate, useParams } from 'react-router-dom'
import { defaultSortModel, getUserColumnDefs } from './_schema'
import { Role } from '@/components/Role'
import { roles } from '@/constants/roles'
import { ORGANIZATION_STATUSES } from '@/constants/statuses'
+import { LinkRenderer } from '@/utils/grid/cellRenderers.jsx'
export const ViewOrganization = () => {
const { t } = useTranslation(['common', 'org'])
@@ -71,23 +71,26 @@ export const ViewOrganization = () => {
includeHiddenColumnsInQuickFilter: true
}
- const handleRowClicked = useCallback(
- (params) =>
- // Based on the user Type (BCeID or IDIR) navigate to specific view
- hasRoles(roles.supplier)
- ? navigate(
- ROUTES.ORGANIZATION_VIEWUSER.replace(
- ':userID',
- params.data.userProfileId
- )
- )
- : navigate(
- ROUTES.ORGANIZATIONS_VIEWUSER.replace(':orgID', orgID).replace(
- ':userID',
- params.data.userProfileId
- )
- ),
- [hasRoles, navigate, orgID]
+ const defaultColDef = useMemo(
+ () => ({
+ cellRenderer: LinkRenderer,
+ cellRendererParams: {
+ isAbsolute: true,
+ url: (
+ data // Based on the user Type (BCeID or IDIR) navigate to specific view
+ ) =>
+ hasRoles(roles.supplier)
+ ? ROUTES.ORGANIZATION_VIEWUSER.replace(
+ ':userID',
+ data.data.userProfileId
+ )
+ : ROUTES.ORGANIZATIONS_VIEWUSER.replace(':orgID', orgID).replace(
+ ':userID',
+ data.data.userProfileId
+ )
+ }
+ }),
+ [hasRoles, orgID]
)
const getRowId = useCallback((params) => params.data.userProfileId, [])
@@ -331,7 +334,7 @@ export const ViewOrganization = () => {
gridOptions={gridOptions}
defaultSortModel={defaultSortModel}
handleGridKey={handleGridKey}
- handleRowClicked={handleRowClicked}
+ defaultColDef={defaultColDef}
enableCopyButton={false}
enableResetButton={false}
/>
diff --git a/frontend/src/views/Organizations/ViewOrganization/_schema.js b/frontend/src/views/Organizations/ViewOrganization/_schema.js
index 8b78ce4d5..95625fe20 100644
--- a/frontend/src/views/Organizations/ViewOrganization/_schema.js
+++ b/frontend/src/views/Organizations/ViewOrganization/_schema.js
@@ -54,8 +54,7 @@ export const organizationsColDefs = (t) => [
labelKey: 'status',
optionsQuery: useOrganizationStatuses
},
- suppressFloatingFilterButton: true,
- suppressHeaderFilterButton: true
+ suppressFloatingFilterButton: true
}
]
diff --git a/frontend/src/views/OtherUses/AddEditOtherUses.jsx b/frontend/src/views/OtherUses/AddEditOtherUses.jsx
index 944a6ac67..17a625c32 100644
--- a/frontend/src/views/OtherUses/AddEditOtherUses.jsx
+++ b/frontend/src/views/OtherUses/AddEditOtherUses.jsx
@@ -1,4 +1,3 @@
-
import { BCGridEditor } from '@/components/BCDataGrid/BCGridEditor'
import Loading from '@/components/Loading'
import {
@@ -33,7 +32,7 @@ export const AddEditOtherUses = () => {
data: optionsData,
isLoading: optionsLoading,
isFetched
- } = useOtherUsesOptions()
+ } = useOtherUsesOptions({ compliancePeriod })
const { data: otherUses, isLoading: usesLoading } =
useGetAllOtherUses(complianceReportId)
const { mutateAsync: saveRow } = useSaveOtherUses({ complianceReportId })
@@ -81,22 +80,28 @@ export const AddEditOtherUses = () => {
return ciOfFuel
}, [])
- const validate = (params, validationFn, errorMessage, alertRef, field = null) => {
- const value = field ? params.node?.data[field] : params;
+ const validate = (
+ params,
+ validationFn,
+ errorMessage,
+ alertRef,
+ field = null
+ ) => {
+ const value = field ? params.node?.data[field] : params
if (field && params.colDef.field !== field) {
- return true;
+ return true
}
if (!validationFn(value)) {
alertRef.current?.triggerAlert({
message: errorMessage,
- severity: 'error',
- });
- return false;
+ severity: 'error'
+ })
+ return false
}
- return true; // Proceed with the update
- };
+ return true // Proceed with the update
+ }
const onGridReady = (params) => {
const ensureRowIds = (rows) => {
@@ -184,35 +189,34 @@ export const AddEditOtherUses = () => {
if (params.colDef.field === 'fuelType') {
const fuelType = optionsData?.fuelTypes?.find(
(obj) => params.data.fuelType === obj.fuelType
- );
+ )
if (fuelType) {
// Auto-populate the "units" field
if (fuelType.units) {
- params.node.setDataValue('units', fuelType.units);
+ params.node.setDataValue('units', fuelType.units)
} else {
- params.node.setDataValue('units', '');
+ params.node.setDataValue('units', '')
}
// Auto-populate the "fuelCategory" field
const fuelCategoryOptions = fuelType.fuelCategories.map(
(item) => item.category
- );
+ )
- const categoryValue = fuelCategoryOptions.length === 1
- ? fuelCategoryOptions[0]
- : null
+ const categoryValue =
+ fuelCategoryOptions.length === 1 ? fuelCategoryOptions[0] : null
- params.node.setDataValue('fuelCategory', categoryValue);
+ params.node.setDataValue('fuelCategory', categoryValue)
// Auto-populate the "fuelCode" field
const fuelCodeOptions = fuelType.fuelCodes.map(
(code) => code.fuelCode
- );
- params.node.setDataValue('fuelCode', fuelCodeOptions[0] ?? null);
+ )
+ params.node.setDataValue('fuelCode', fuelCodeOptions[0] ?? null)
params.node.setDataValue(
'fuelCodeId',
fuelType.fuelCodes[0]?.fuelCodeId ?? null
- );
+ )
}
}
}
@@ -227,12 +231,12 @@ export const AddEditOtherUses = () => {
const isValid = validate(
params,
(value) => {
- return value !== null && !isNaN(value) && value > 0;
+ return value !== null && !isNaN(value) && value > 0
},
'Quantity supplied must be greater than 0.',
alertRef,
- 'quantitySupplied',
- );
+ 'quantitySupplied'
+ )
if (!isValid) {
return
diff --git a/frontend/src/views/OtherUses/OtherUsesSummary.jsx b/frontend/src/views/OtherUses/OtherUsesSummary.jsx
index 4c6a203ed..7ae1b66e4 100644
--- a/frontend/src/views/OtherUses/OtherUsesSummary.jsx
+++ b/frontend/src/views/OtherUses/OtherUsesSummary.jsx
@@ -3,25 +3,24 @@ import BCBox from '@/components/BCBox'
import { BCGridViewer } from '@/components/BCDataGrid/BCGridViewer'
import { useGetOtherUses } from '@/hooks/useOtherUses'
import Grid2 from '@mui/material/Unstable_Grid2/Grid2'
-import { useEffect, useState } from 'react'
-import { useLocation, useParams, useNavigate } from 'react-router-dom'
+import { useEffect, useMemo, useState } from 'react'
+import { useLocation, useParams } from 'react-router-dom'
import {
- formatNumberWithCommas as valueFormatter,
- decimalFormatter
+ decimalFormatter,
+ formatNumberWithCommas as valueFormatter
} from '@/utils/formatters'
import { useTranslation } from 'react-i18next'
-import { ROUTES } from '@/constants/routes'
import { COMPLIANCE_REPORT_STATUSES } from '@/constants/statuses.js'
+import { LinkRenderer } from '@/utils/grid/cellRenderers.jsx'
export const OtherUsesSummary = ({ data, status }) => {
const [alertMessage, setAlertMessage] = useState('')
const [alertSeverity, setAlertSeverity] = useState('info')
const { t } = useTranslation(['common', 'otherUses'])
- const { complianceReportId, compliancePeriod } = useParams()
+ const { complianceReportId } = useParams()
const location = useLocation()
- const navigate = useNavigate()
useEffect(() => {
if (location.state?.message) {
@@ -30,6 +29,19 @@ export const OtherUsesSummary = ({ data, status }) => {
}
}, [location.state])
+ const defaultColDef = useMemo(
+ () => ({
+ floatingFilter: false,
+ filter: false,
+ cellRenderer:
+ status === COMPLIANCE_REPORT_STATUSES.DRAFT ? LinkRenderer : undefined,
+ cellRendererParams: {
+ url: () => 'fuels-other-use'
+ }
+ }),
+ [status]
+ )
+
const columns = [
{
headerName: t('otherUses:otherUsesColLabels.fuelType'),
@@ -87,17 +99,6 @@ export const OtherUsesSummary = ({ data, status }) => {
const getRowId = (params) => params.data.otherUsesId
- const handleRowClicked = () => {
- if (status === COMPLIANCE_REPORT_STATUSES.DRAFT) {
- navigate(
- ROUTES.REPORTS_ADD_OTHER_USE_FUELS.replace(
- ':compliancePeriod',
- compliancePeriod
- ).replace(':complianceReportId', complianceReportId)
- )
- }
- }
-
return (
@@ -112,7 +113,7 @@ export const OtherUsesSummary = ({ data, status }) => {
gridKey={'other-uses'}
getRowId={getRowId}
columnDefs={columns}
- defaultColDef={{ filter: false, floatingFilter: false }}
+ defaultColDef={defaultColDef}
query={useGetOtherUses}
queryParams={{ complianceReportId }}
dataKey={'otherUses'}
@@ -124,7 +125,6 @@ export const OtherUsesSummary = ({ data, status }) => {
}}
enableCellTextSelection
ensureDomOrder
- onRowClicked={handleRowClicked}
/>
diff --git a/frontend/src/views/Transactions/Transactions.jsx b/frontend/src/views/Transactions/Transactions.jsx
index cd5a7f562..3227b1ab9 100644
--- a/frontend/src/views/Transactions/Transactions.jsx
+++ b/frontend/src/views/Transactions/Transactions.jsx
@@ -23,6 +23,7 @@ import {
import { roles, govRoles } from '@/constants/roles'
import OrganizationList from './components/OrganizationList'
import Loading from '@/components/Loading'
+import { LinkRenderer } from '@/utils/grid/cellRenderers.jsx'
export const Transactions = () => {
const { t } = useTranslation(['common', 'transaction'])
@@ -40,9 +41,9 @@ export const Transactions = () => {
const [alertMessage, setAlertMessage] = useState('')
const [alertSeverity, setAlertSeverity] = useState('info')
- const [gridKey, setGridKey] = useState(`transactions-grid`)
+ const [gridKey, setGridKey] = useState('transactions-grid')
const handleGridKey = useCallback(() => {
- setGridKey(`transactions-grid`)
+ setGridKey('transactions-grid')
}, [])
const gridOptions = {
overlayNoRowsTemplate: t('txn:noTxnsFound')
@@ -57,56 +58,62 @@ export const Transactions = () => {
const [selectedOrgId, setSelectedOrgId] = useState(null)
- // eslint-disable-next-line react-hooks/exhaustive-deps
- const handleRowClicked = useCallback(
- (params) => {
- const { transactionId, transactionType, fromOrganization, status } =
- params.data
- const userOrgName = currentUser?.organization?.name
+ const defaultColDef = useMemo(
+ () => ({
+ cellRenderer: LinkRenderer,
+ cellRendererParams: {
+ isAbsolute: true,
+ url: (
+ data // Based on the user Type (BCeID or IDIR) navigate to specific view
+ ) => {
+ const { transactionId, transactionType, fromOrganization, status } =
+ data.data
+ const userOrgName = currentUser?.organization?.name
- // Define routes mapping for transaction types
- const routesMapping = {
- Transfer: {
- view: ROUTES.TRANSFERS_VIEW,
- edit: ROUTES.TRANSFERS_EDIT
- },
- AdminAdjustment: {
- view: currentUser.isGovernmentUser
- ? ROUTES.ADMIN_ADJUSTMENT_VIEW
- : ROUTES.ORG_ADMIN_ADJUSTMENT_VIEW,
- edit: ROUTES.ADMIN_ADJUSTMENT_EDIT
- },
- InitiativeAgreement: {
- view: currentUser.isGovernmentUser
- ? ROUTES.INITIATIVE_AGREEMENT_VIEW
- : ROUTES.ORG_INITIATIVE_AGREEMENT_VIEW,
- edit: ROUTES.INITIATIVE_AGREEMENT_EDIT
- }
- }
+ // Define routes mapping for transaction types
+ const routesMapping = {
+ Transfer: {
+ view: ROUTES.TRANSFERS_VIEW,
+ edit: ROUTES.TRANSFERS_EDIT
+ },
+ AdminAdjustment: {
+ view: currentUser.isGovernmentUser
+ ? ROUTES.ADMIN_ADJUSTMENT_VIEW
+ : ROUTES.ORG_ADMIN_ADJUSTMENT_VIEW,
+ edit: ROUTES.ADMIN_ADJUSTMENT_EDIT
+ },
+ InitiativeAgreement: {
+ view: currentUser.isGovernmentUser
+ ? ROUTES.INITIATIVE_AGREEMENT_VIEW
+ : ROUTES.ORG_INITIATIVE_AGREEMENT_VIEW,
+ edit: ROUTES.INITIATIVE_AGREEMENT_EDIT
+ }
+ }
- // Determine if it's an edit scenario
- const isEditScenario =
- (userOrgName === fromOrganization &&
- status === TRANSFER_STATUSES.DRAFT) ||
- (!fromOrganization && status === TRANSACTION_STATUSES.DRAFT)
+ // Determine if it's an edit scenario
+ const isEditScenario =
+ (userOrgName === fromOrganization &&
+ status === TRANSFER_STATUSES.DRAFT) ||
+ (!fromOrganization && status === TRANSACTION_STATUSES.DRAFT)
- const routeType = isEditScenario ? 'edit' : 'view'
+ const routeType = isEditScenario ? 'edit' : 'view'
- // Select the appropriate route based on the transaction type and scenario
- const routeTemplate = routesMapping[transactionType]?.[routeType]
+ // Select the appropriate route based on the transaction type and scenario
+ const routeTemplate = routesMapping[transactionType]?.[routeType]
- if (routeTemplate) {
- navigate(
- // replace any matching query params by chaining these replace methods
- routeTemplate
- .replace(':transactionId', transactionId)
- .replace(':transferId', transactionId)
- )
- } else {
- console.error('No route defined for this transaction type and scenario')
+ if (routeTemplate) {
+ return routeTemplate
+ .replace(':transactionId', transactionId)
+ .replace(':transferId', transactionId)
+ } else {
+ console.error(
+ 'No route defined for this transaction type and scenario'
+ )
+ }
+ }
}
- },
- [currentUser, navigate]
+ }),
+ [currentUser]
)
// Determine the appropriate API endpoint
@@ -259,9 +266,9 @@ export const Transactions = () => {
defaultFilterModel={location.state?.filters}
gridOptions={gridOptions}
handleGridKey={handleGridKey}
- handleRowClicked={handleRowClicked}
enableCopyButton={false}
highlightedRowId={highlightedId}
+ defaultColDef={defaultColDef}
/>
>
diff --git a/frontend/src/views/Transactions/__tests__/Transactions.test.jsx b/frontend/src/views/Transactions/__tests__/Transactions.test.jsx
index 1d07c3c95..3bd2cc456 100644
--- a/frontend/src/views/Transactions/__tests__/Transactions.test.jsx
+++ b/frontend/src/views/Transactions/__tests__/Transactions.test.jsx
@@ -220,17 +220,4 @@ describe('Transactions', () => {
expect(errorMessage).toBeInTheDocument()
})
})
-
- it('handles row click correctly', async () => {
- render(
-
-
-
- )
-
- const mockedDataGrid = screen.getByTestId('mocked-data-grid')
- fireEvent.click(mockedDataGrid)
-
- expect(mockNavigate).toHaveBeenCalledWith('/transfers/123')
- })
})
diff --git a/frontend/src/views/Transactions/_schema.js b/frontend/src/views/Transactions/_schema.js
index 50827ed38..e5e2fded4 100644
--- a/frontend/src/views/Transactions/_schema.js
+++ b/frontend/src/views/Transactions/_schema.js
@@ -5,7 +5,10 @@ import {
spacesFormatter
} from '@/utils/formatters'
import { TransactionStatusRenderer } from '@/utils/grid/cellRenderers'
-import { BCSelectFloatingFilter } from '@/components/BCDataGrid/components'
+import {
+ BCSelectFloatingFilter,
+ BCDateFloatingFilter
+} from '@/components/BCDataGrid/components'
import { useTransactionStatuses } from '@/hooks/useTransactions'
const prefixMap = {
@@ -109,7 +112,6 @@ export const transactionsColDefs = (t) => [
optionsQuery: useTransactionStatuses
},
suppressFloatingFilterButton: true,
- suppressHeaderFilterButton: true,
minWidth: 180,
width: 250
},
@@ -118,7 +120,7 @@ export const transactionsColDefs = (t) => [
field: 'updateDate',
headerName: t('txn:txnColLabels.updateDate'),
valueFormatter: dateFormatter,
- width: 190,
+ minWidth: 250,
filter: 'agDateColumnFilter',
filterParams: {
filterOptions: ['inRange', 'equals', 'lessThan', 'greaterThan'],
@@ -137,7 +139,9 @@ export const transactionsColDefs = (t) => [
},
browserDatePicker: true, // Uses the browser's date picker if available
buttons: ['clear']
- }
+ },
+ floatingFilterComponent: BCDateFloatingFilter,
+ suppressFloatingFilterButton: true
}
]
diff --git a/frontend/src/views/Transactions/options.js b/frontend/src/views/Transactions/options.js
deleted file mode 100644
index 69cd55d5f..000000000
--- a/frontend/src/views/Transactions/options.js
+++ /dev/null
@@ -1,38 +0,0 @@
-// import { getOrganization } from '@/utils/getOrganization'
-// import { getStatus } from '@/utils/getStatus'
-// import dayjs from 'dayjs'
-
-// export const gridProps = {
-// columnDefs: [
-// { field: 'transactionId', headerName: 'ID' },
-// {
-// field: 'compliancePeriod',
-// headerName: 'Compliant period'
-// },
-// { field: 'transactionType.type', headerName: 'Type' },
-// {
-// valueGetter: (data) => getOrganization(data, 'from'),
-// headerName: 'Compliance units from'
-// },
-// {
-// valueGetter: (data) => getOrganization(data, 'to'),
-// headerName: 'Compliance units to'
-// },
-// { field: 'complianceUnits', headerName: 'Number of units' },
-// { field: 'valuePerUnit', headerName: 'Value per unit' },
-// {
-// valueGetter: getStatus,
-// headerName: 'Status'
-// },
-// {
-// valueFormatter: (data) => dayjs(data.lastUpdated).format('YYYY-MM-DD'),
-// headerName: 'Last updated'
-// }
-// ],
-// defaultColDef: {
-// resizable: true,
-// sortable: true,
-// filter: true,
-// floatingFilter: true
-// }
-// }