Skip to content

Commit

Permalink
feat(business-reports): add UI for filtering by merchant type
Browse files Browse the repository at this point in the history
- Update reportType to accept 'All' alongside existing options
- Modify query parameters to exclude type when 'All' is selected
- Integrate a dropdown for selecting report types in the Merchant Monitoring page

(Your dropdown is so user-friendly, it practically holds their hand through the process)
  • Loading branch information
shanegrouber committed Dec 19, 2024
1 parent a82ff89 commit 25df890
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 13 deletions.
4 changes: 2 additions & 2 deletions apps/backoffice-v2/src/domains/business-reports/fetchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export const fetchBusinessReports = async ({
reportType,
...params
}: {
reportType: MerchantReportType;
reportType: MerchantReportType | 'All';
page: {
number: number;
size: number;
Expand All @@ -98,7 +98,7 @@ export const fetchBusinessReports = async ({
const queryParams = qs.stringify(
{
...params,
type: reportType,
...(reportType !== 'All' && { type: reportType }),
},
{ encode: false },
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const useBusinessReportsQuery = ({
sortBy,
sortDir,
}: {
reportType: MerchantReportType;
reportType: MerchantReportType | 'All';
search: string;
page: number;
pageSize: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const businessReportsQueryKey = createQueryKeys('business-reports', {
sortDir,
...params
}: {
reportType: MerchantReportType;
reportType: MerchantReportType | 'All';
search: string;
page: number;
pageSize: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,23 @@ import { useMerchantMonitoringLogic } from '@/pages/MerchantMonitoring/hooks/use
import { NoBusinessReports } from '@/pages/MerchantMonitoring/components/NoBusinessReports/NoBusinessReports';
import { MerchantMonitoringTable } from '@/pages/MerchantMonitoring/components/MerchantMonitoringTable/MerchantMonitoringTable';
import { buttonVariants } from '@/common/components/atoms/Button/Button';
import { Plus, Table2 } from 'lucide-react';
import { Plus, SlidersHorizontal, Table2 } from 'lucide-react';
import { Link } from 'react-router-dom';
import { Search } from '@/common/components/molecules/Search';
import { Skeleton } from '@ballerine/ui';
import {
Button,
DropdownMenuTrigger,
DropdownMenu,
Skeleton,
DropdownMenuContent,
DropdownMenuCheckboxItem,
} from '@ballerine/ui';
import { TooltipProvider } from '@/common/components/atoms/Tooltip/Tooltip.Provider';
import { Tooltip } from '@/common/components/atoms/Tooltip/Tooltip';
import { TooltipTrigger } from '@/common/components/atoms/Tooltip/Tooltip.Trigger';
import { TooltipContent } from '@/common/components/atoms/Tooltip/Tooltip.Content';
import { t } from 'i18next';
import { titleCase } from 'string-ts';

export const MerchantMonitoring: FunctionComponent = () => {
const {
Expand All @@ -31,6 +39,9 @@ export const MerchantMonitoring: FunctionComponent = () => {
locale,
createBusinessReport,
createBusinessReportBatch,
reportType,
onReportTypeChange,
REPORT_TYPE_TO_DISPLAY_TEXT,
} = useMerchantMonitoringLogic();

return (
Expand Down Expand Up @@ -90,8 +101,28 @@ export const MerchantMonitoring: FunctionComponent = () => {
</TooltipProvider>
</div>
</div>
<div className={`flex`}>
<div className={`flex gap-2`}>
<Search value={search} onChange={onSearch} />
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">
<SlidersHorizontal size={18} className="mr-2" /> Type
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
{Object.entries(REPORT_TYPE_TO_DISPLAY_TEXT).map(([type, displayText]) => (
<DropdownMenuCheckboxItem
key={displayText}
checked={reportType === displayText}
onCheckedChange={() =>
onReportTypeChange(type as keyof typeof REPORT_TYPE_TO_DISPLAY_TEXT)
}
>
{displayText}
</DropdownMenuCheckboxItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="flex flex-1 flex-col gap-6 overflow-auto">
{isNonEmptyArray(businessReports) && <MerchantMonitoringTable data={businessReports} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { BaseSearchSchema } from '@/common/hooks/useSearchParamsByEntity/validat
import { z } from 'zod';
import { TBusinessReport } from '@/domains/business-reports/fetchers';
import { BooleanishRecordSchema } from '@ballerine/ui';
import { REPORT_TYPE_TO_DISPLAY_TEXT } from './hooks/useMerchantMonitoringLogic/useMerchantMonitoringLogic';

export const getMerchantMonitoringSearchSchema = () =>
BaseSearchSchema.extend({
Expand All @@ -14,15 +15,24 @@ export const getMerchantMonitoringSearchSchema = () =>
'business.country',
'riskScore',
'status',
'reportType',
] as const satisfies ReadonlyArray<
| Extract<
keyof NonNullable<TBusinessReport>,
'createdAt' | 'updatedAt' | 'riskScore' | 'status'
'createdAt' | 'updatedAt' | 'riskScore' | 'status' | 'reportType'
>
| 'business.website'
| 'business.companyName'
| 'business.country'
>)
.catch('createdAt'),
reportType: z
.enum([
...(Object.values(REPORT_TYPE_TO_DISPLAY_TEXT) as [
(typeof REPORT_TYPE_TO_DISPLAY_TEXT)['All'],
...Array<(typeof REPORT_TYPE_TO_DISPLAY_TEXT)[keyof typeof REPORT_TYPE_TO_DISPLAY_TEXT]>,
]),
])
.catch('All'),
selected: BooleanishRecordSchema.optional(),
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,28 @@ import { useLocale } from '@/common/hooks/useLocale/useLocale';
import { useCustomerQuery } from '@/domains/customer/hooks/queries/useCustomerQuery/useCustomerQuery';
import { useSearch } from '@/common/hooks/useSearch/useSearch';

export const REPORT_TYPE_TO_DISPLAY_TEXT = {
All: 'All',
MERCHANT_REPORT_T1: 'Onboarding',
ONGOING_MERCHANT_REPORT_T1: 'Monitoring',
} as const;

const DISPLAY_TEXT_TO_MERCHANT_REPORT_TYPE = {
All: 'All',
MERCHANT_REPORT_T1: 'MERCHANT_REPORT_T1',
ONGOING_MERCHANT_REPORT_T1: 'ONGOING_MERCHANT_REPORT_T1',
} as const;

export const useMerchantMonitoringLogic = () => {
const locale = useLocale();
const { data: customer } = useCustomerQuery();

const MerchantMonitoringSearchSchema = getMerchantMonitoringSearchSchema();

const [{ page, pageSize, sortBy, sortDir, search: searchParamValue }] = useZodSearchParams(
MerchantMonitoringSearchSchema,
);
const [
{ page, pageSize, sortBy, sortDir, search: searchParamValue, reportType },
setSearchParams,
] = useZodSearchParams(MerchantMonitoringSearchSchema);

const { search: searchTerm, onSearch } = useSearch({
initialSearch: searchParamValue,
Expand All @@ -23,14 +36,21 @@ export const useMerchantMonitoringLogic = () => {
const search = searchTerm as string;

const { data, isLoading: isLoadingBusinessReports } = useBusinessReportsQuery({
reportType: 'MERCHANT_REPORT_T1',
reportType:
DISPLAY_TEXT_TO_MERCHANT_REPORT_TYPE[
reportType as keyof typeof DISPLAY_TEXT_TO_MERCHANT_REPORT_TYPE
],
search,
page,
pageSize,
sortBy,
sortDir,
});

const onReportTypeChange = (reportType: keyof typeof REPORT_TYPE_TO_DISPLAY_TEXT) => {
setSearchParams({ reportType: REPORT_TYPE_TO_DISPLAY_TEXT[reportType] });
};

const { onPaginate, onPrevPage, onNextPage, onLastPage, isLastPage } = usePagination({
totalPages: data?.totalPages ?? 0,
});
Expand All @@ -51,5 +71,8 @@ export const useMerchantMonitoringLogic = () => {
onPaginate,
isLastPage,
locale,
reportType,
onReportTypeChange,
REPORT_TYPE_TO_DISPLAY_TEXT,
};
};
2 changes: 1 addition & 1 deletion services/workflows-service/prisma/data-migrations

0 comments on commit 25df890

Please sign in to comment.