diff --git a/apps/backoffice-v2/src/common/components/atoms/MultiSelect/MultiSelect.tsx b/apps/backoffice-v2/src/common/components/atoms/MultiSelect/MultiSelect.tsx index 02c64a0242..78d5bdbaac 100644 --- a/apps/backoffice-v2/src/common/components/atoms/MultiSelect/MultiSelect.tsx +++ b/apps/backoffice-v2/src/common/components/atoms/MultiSelect/MultiSelect.tsx @@ -39,13 +39,11 @@ export const MultiSelect = < }, >({ title, - selectedValues, + selectedValues: selected, onSelect, onClearSelect, options, }: IMultiSelectProps) => { - const [selected, setSelected] = useState(selectedValues); - const onSelectChange = useCallback( (value: TOption['value']) => { const isSelected = selected.some(selectedValue => selectedValue === value); @@ -53,7 +51,6 @@ export const MultiSelect = < ? selected.filter(selectedValue => selectedValue !== value) : [...selected, value]; - setSelected(nextSelected); onSelect(nextSelected); }, [onSelect, selected], @@ -125,13 +122,7 @@ export const MultiSelect = < <> - { - onClearSelect(); - setSelected([]); - }} - className="justify-center text-center" - > + Clear filters diff --git a/apps/backoffice-v2/src/domains/business-reports/fetchers.ts b/apps/backoffice-v2/src/domains/business-reports/fetchers.ts index 9d82771336..eb923fe846 100644 --- a/apps/backoffice-v2/src/domains/business-reports/fetchers.ts +++ b/apps/backoffice-v2/src/domains/business-reports/fetchers.ts @@ -14,7 +14,10 @@ import { MerchantReportVersion, } from '@/domains/business-reports/constants'; import { UnknownRecord } from 'type-fest'; -import { RISK_LEVELS } from '@/pages/MerchantMonitoring/hooks/useMerchantMonitoringLogic/useMerchantMonitoringLogic'; +import { + RISK_LEVELS, + STATUS_OPTIONS, +} from '@/pages/MerchantMonitoring/hooks/useMerchantMonitoringLogic/useMerchantMonitoringLogic'; export const BusinessReportSchema = z .object({ @@ -88,10 +91,12 @@ export const fetchLatestBusinessReport = async ({ export const fetchBusinessReports = async ({ reportType, riskLevel, + status, ...params }: { reportType: MerchantReportType | 'All'; riskLevel: Array<(typeof RISK_LEVELS)[number]>; + status: Array<(typeof STATUS_OPTIONS)[number]>; page: { number: number; size: number; @@ -102,7 +107,8 @@ export const fetchBusinessReports = async ({ { ...params, ...(reportType !== 'All' && { type: reportType }), - riskLevel: riskLevel, + riskLevel, + status, }, { encode: false }, ); diff --git a/apps/backoffice-v2/src/domains/business-reports/hooks/queries/useBusinessReportsQuery/useBusinessReportsQuery.tsx b/apps/backoffice-v2/src/domains/business-reports/hooks/queries/useBusinessReportsQuery/useBusinessReportsQuery.tsx index 57de088021..0f0cbd232d 100644 --- a/apps/backoffice-v2/src/domains/business-reports/hooks/queries/useBusinessReportsQuery/useBusinessReportsQuery.tsx +++ b/apps/backoffice-v2/src/domains/business-reports/hooks/queries/useBusinessReportsQuery/useBusinessReportsQuery.tsx @@ -3,7 +3,10 @@ import { useQuery } from '@tanstack/react-query'; import { businessReportsQueryKey } from '@/domains/business-reports/query-keys'; import { isString } from '@/common/utils/is-string/is-string'; import { MerchantReportType } from '@/domains/business-reports/constants'; -import { RISK_LEVELS } from '@/pages/MerchantMonitoring/hooks/useMerchantMonitoringLogic/useMerchantMonitoringLogic'; +import { + RISK_LEVELS, + STATUS_OPTIONS, +} from '@/pages/MerchantMonitoring/hooks/useMerchantMonitoringLogic/useMerchantMonitoringLogic'; export const useBusinessReportsQuery = ({ reportType, @@ -13,6 +16,7 @@ export const useBusinessReportsQuery = ({ sortBy, sortDir, riskLevel, + status, }: { reportType: MerchantReportType | 'All'; search: string; @@ -21,6 +25,7 @@ export const useBusinessReportsQuery = ({ sortBy: string; sortDir: string; riskLevel: Array<(typeof RISK_LEVELS)[number]>; + status: Array<(typeof STATUS_OPTIONS)[number]>; }) => { const isAuthenticated = useIsAuthenticated(); @@ -33,6 +38,7 @@ export const useBusinessReportsQuery = ({ sortBy, sortDir, riskLevel, + status, }), enabled: isAuthenticated && diff --git a/apps/backoffice-v2/src/domains/business-reports/query-keys.ts b/apps/backoffice-v2/src/domains/business-reports/query-keys.ts index 07f4a2c8fa..6b192ad952 100644 --- a/apps/backoffice-v2/src/domains/business-reports/query-keys.ts +++ b/apps/backoffice-v2/src/domains/business-reports/query-keys.ts @@ -6,7 +6,10 @@ import { fetchLatestBusinessReport, } from '@/domains/business-reports/fetchers'; import { MerchantReportType } from '@/domains/business-reports/constants'; -import { RISK_LEVELS } from '@/pages/MerchantMonitoring/hooks/useMerchantMonitoringLogic/useMerchantMonitoringLogic'; +import { + RISK_LEVELS, + STATUS_OPTIONS, +} from '@/pages/MerchantMonitoring/hooks/useMerchantMonitoringLogic/useMerchantMonitoringLogic'; export const businessReportsQueryKey = createQueryKeys('business-reports', { list: ({ @@ -23,6 +26,7 @@ export const businessReportsQueryKey = createQueryKeys('business-reports', { sortBy: string; sortDir: string; riskLevel: Array<(typeof RISK_LEVELS)[number]>; + status: Array<(typeof STATUS_OPTIONS)[number]>; }) => ({ queryKey: [{ page, pageSize, sortBy, sortDir, ...params }], queryFn: () => { diff --git a/apps/backoffice-v2/src/pages/MerchantMonitoring/MerchantMonitoring.page.tsx b/apps/backoffice-v2/src/pages/MerchantMonitoring/MerchantMonitoring.page.tsx index dc20d50899..fdc2691786 100644 --- a/apps/backoffice-v2/src/pages/MerchantMonitoring/MerchantMonitoring.page.tsx +++ b/apps/backoffice-v2/src/pages/MerchantMonitoring/MerchantMonitoring.page.tsx @@ -43,8 +43,11 @@ export const MerchantMonitoring: FunctionComponent = () => { onReportTypeChange, REPORT_TYPE_TO_DISPLAY_TEXT, RISK_LEVEL_FILTERS, - onRiskLevelChange, - onClearSelect, + STATUS_LEVEL_FILTERS, + handleFilterChange, + handleFilterClear, + riskLevel, + status, } = useMerchantMonitoringLogic(); return ( @@ -127,18 +130,26 @@ export const MerchantMonitoring: FunctionComponent = () => { -
- {RISK_LEVEL_FILTERS.map(({ title, options }) => ( - - ))} -
+ {RISK_LEVEL_FILTERS.map(({ title, accessor, options }) => ( + + ))} + {STATUS_LEVEL_FILTERS.map(({ title, accessor, options }) => ( + + ))}
{isNonEmptyArray(businessReports) && } diff --git a/apps/backoffice-v2/src/pages/MerchantMonitoring/get-merchant-monitoring-search-schema.ts b/apps/backoffice-v2/src/pages/MerchantMonitoring/get-merchant-monitoring-search-schema.ts index 39dc8dea04..ea1453a6c9 100644 --- a/apps/backoffice-v2/src/pages/MerchantMonitoring/get-merchant-monitoring-search-schema.ts +++ b/apps/backoffice-v2/src/pages/MerchantMonitoring/get-merchant-monitoring-search-schema.ts @@ -5,6 +5,7 @@ import { BooleanishRecordSchema } from '@ballerine/ui'; import { REPORT_TYPE_TO_DISPLAY_TEXT, RISK_LEVELS, + STATUS_OPTIONS, } from './hooks/useMerchantMonitoringLogic/useMerchantMonitoringLogic'; export const getMerchantMonitoringSearchSchema = () => @@ -47,5 +48,15 @@ export const getMerchantMonitoringSearchSchema = () => ], ), ) - .optional(), + .catch([]), + status: z + .array( + z.enum( + STATUS_OPTIONS.map(status => status.toLowerCase()) as [ + (typeof STATUS_OPTIONS)[number], + ...Array<(typeof STATUS_OPTIONS)[number]>, + ], + ), + ) + .catch([]), }); diff --git a/apps/backoffice-v2/src/pages/MerchantMonitoring/hooks/useMerchantMonitoringLogic/useMerchantMonitoringLogic.tsx b/apps/backoffice-v2/src/pages/MerchantMonitoring/hooks/useMerchantMonitoringLogic/useMerchantMonitoringLogic.tsx index 92eeb6fd03..53c85af6de 100644 --- a/apps/backoffice-v2/src/pages/MerchantMonitoring/hooks/useMerchantMonitoringLogic/useMerchantMonitoringLogic.tsx +++ b/apps/backoffice-v2/src/pages/MerchantMonitoring/hooks/useMerchantMonitoringLogic/useMerchantMonitoringLogic.tsx @@ -24,6 +24,7 @@ export const RISK_LEVELS = ['Critical', 'High', 'Medium', 'Low'] as const; const RISK_LEVEL_FILTERS = [ { title: 'Risk Level', + accessor: 'riskLevel', options: RISK_LEVELS.map(riskLevel => ({ label: riskLevel, value: riskLevel.toLowerCase(), @@ -31,6 +32,19 @@ const RISK_LEVEL_FILTERS = [ }, ]; +export const STATUS_OPTIONS = ['In Progress', 'Quality Control', 'Manual Review'] as const; + +const STATUS_LEVEL_FILTERS = [ + { + title: 'Status', + accessor: 'status', + options: STATUS_OPTIONS.map(status => ({ + label: status, + value: status.toLowerCase(), + })), + }, +]; + export const useMerchantMonitoringLogic = () => { const locale = useLocale(); const { data: customer } = useCustomerQuery(); @@ -38,7 +52,7 @@ export const useMerchantMonitoringLogic = () => { const MerchantMonitoringSearchSchema = getMerchantMonitoringSearchSchema(); const [ - { page, pageSize, sortBy, sortDir, search: searchParamValue, reportType, riskLevel }, + { page, pageSize, sortBy, sortDir, search: searchParamValue, reportType, riskLevel, status }, setSearchParams, ] = useZodSearchParams(MerchantMonitoringSearchSchema); @@ -59,26 +73,32 @@ export const useMerchantMonitoringLogic = () => { sortBy, sortDir, riskLevel: riskLevel ?? [], + status: status ?? [], }); const onReportTypeChange = (reportType: keyof typeof REPORT_TYPE_TO_DISPLAY_TEXT) => { setSearchParams({ reportType: REPORT_TYPE_TO_DISPLAY_TEXT[reportType] }); }; - const onRiskLevelChange = useCallback( - (selected: unknown[]) => { - const selectedRiskLevels = selected as Array<(typeof RISK_LEVELS)[number]>; - + const handleFilterChange = useCallback( + (filterKey: string) => (selected: unknown) => { setSearchParams({ - riskLevel: selectedRiskLevels, + [filterKey]: Array.isArray(selected) ? selected : [selected], + page: '1', }); }, [setSearchParams], ); - const onClearSelect = useCallback(() => { - setSearchParams({ riskLevel: [] }); - }, [setSearchParams]); + const handleFilterClear = useCallback( + (filterKey: string) => () => { + setSearchParams({ + [filterKey]: [], + page: '1', + }); + }, + [setSearchParams], + ); const { onPaginate, onPrevPage, onNextPage, onLastPage, isLastPage } = usePagination({ totalPages: data?.totalPages ?? 0, @@ -104,7 +124,10 @@ export const useMerchantMonitoringLogic = () => { onReportTypeChange, REPORT_TYPE_TO_DISPLAY_TEXT, RISK_LEVEL_FILTERS, - onRiskLevelChange, - onClearSelect, + STATUS_LEVEL_FILTERS, + handleFilterChange, + handleFilterClear, + riskLevel, + status, }; }; diff --git a/apps/backoffice-v2/src/pages/TransactionMonitoringAlerts/components/AlertsFilters/AlertsFilters.tsx b/apps/backoffice-v2/src/pages/TransactionMonitoringAlerts/components/AlertsFilters/AlertsFilters.tsx index 9258e26d9d..d01798d4f6 100644 --- a/apps/backoffice-v2/src/pages/TransactionMonitoringAlerts/components/AlertsFilters/AlertsFilters.tsx +++ b/apps/backoffice-v2/src/pages/TransactionMonitoringAlerts/components/AlertsFilters/AlertsFilters.tsx @@ -4,7 +4,6 @@ import { MultiSelect } from '@/common/components/atoms/MultiSelect/MultiSelect'; import { useFilter } from '@/common/hooks/useFilter/useFilter'; import { AlertStatuses } from '@/domains/alerts/fetchers'; import { titleCase } from 'string-ts'; -import { keyFactory } from '@/common/utils/key-factory/key-factory'; export const AlertsFilters: FunctionComponent<{ assignees: TUsers; @@ -79,7 +78,7 @@ export const AlertsFilters: FunctionComponent<{
{filters.map(({ title, accessor, options }) => (