Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui): enhance merchant monitoring report status component #3061

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const buttonVariants = cva(
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'underline-offset-4 hover:underline text-primary',
status: 'focus-visible:ring-0 focus-visible:ring-offset-0 focus:!bg-[#F4F6FD] bg-[#F4F6FD]',
},
size: {
default: 'h-10 py-2 px-4',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { t } from 'i18next';
import { toast } from 'sonner';
import { isObject, MerchantReportType } from '@ballerine/common';
import { useMutation, useQueryClient } from '@tanstack/react-query';

import { HttpError } from '@/common/errors/http-error';
import { createBusinessReportBatch } from '@/domains/business-reports/fetchers';
import { useCustomerQuery } from '@/domains/customer/hooks/queries/useCustomerQuery/useCustomerQuery';
import { isObject } from '@ballerine/common';
import { MerchantReportType } from '@/domains/business-reports/constants';

export const useCreateBusinessReportBatchMutation = ({
reportType,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useQuery } from '@tanstack/react-query';
import { MerchantReportType } from '@ballerine/common';

import { MerchantReportType } from '@/domains/business-reports/constants';
import { businessReportsQueryKey } from '@/domains/business-reports/query-keys';
import { TReportStatusValue, TRiskLevel } from '@/pages/MerchantMonitoring/schemas';
import { useIsAuthenticated } from '@/domains/auth/context/AuthProvider/hooks/useIsAuthenticated/useIsAuthenticated';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useIsAuthenticated } from '@/domains/auth/context/AuthProvider/hooks/useIsAuthenticated/useIsAuthenticated';
import { useQuery } from '@tanstack/react-query';
import { MerchantReportType } from '@ballerine/common';

import { isString } from '@/common/utils/is-string/is-string';
import { businessReportsQueryKey } from '@/domains/business-reports/query-keys';
import { MerchantReportType } from '@/domains/business-reports/constants';
import { useIsAuthenticated } from '@/domains/auth/context/AuthProvider/hooks/useIsAuthenticated/useIsAuthenticated';

export const useLatestBusinessReportQuery = ({
businessId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { MerchantReportType } from '@ballerine/common';
import { createQueryKeys } from '@lukemorales/query-key-factory';

import {
fetchBusinessReportById,
fetchBusinessReports,
fetchLatestBusinessReport,
} from '@/domains/business-reports/fetchers';
import { MerchantReportType } from '@/domains/business-reports/constants';
import { TReportStatusValue, TRiskLevel } from '@/pages/MerchantMonitoring/schemas';

export const businessReportsQueryKey = createQueryKeys('business-reports', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export const useDefaultBlocksLogic = () => {
omitPropsFromObjectWhitelist({
object: workflow?.context?.pluginsOutput,
whitelist: registryInfoWhitelist,
}),
}) ?? {},
[workflow?.context?.pluginsOutput],
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { titleCase } from 'string-ts';
import React, { ElementRef, forwardRef } from 'react';
import { MERCHANT_REPORT_STATUSES_MAP } from '@ballerine/common';
import {
Badge,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@ballerine/ui';

import { ctw } from '@/common/utils/ctw/ctw';
import { Button } from '@/common/components/atoms/Button/Button';

const reportInProgressData = {
variant: 'gray',
title: 'Scan in progress',
text: '',
};

const statusToData = {
[MERCHANT_REPORT_STATUSES_MAP['in-progress']]: reportInProgressData,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add failed as well?

[MERCHANT_REPORT_STATUSES_MAP['quality-control']]: reportInProgressData,
[MERCHANT_REPORT_STATUSES_MAP['pending-review']]: {
variant: 'gray',
title: 'Pending Review',
text: 'The review process has not yet started',
},
[MERCHANT_REPORT_STATUSES_MAP['under-review']]: {
variant: 'info',
title: 'Under Review',
text: 'The merchant is currently being assessed',
},
[MERCHANT_REPORT_STATUSES_MAP.completed]: {
variant: 'success',
title: 'Review Completed',
text: 'The assessment of this merchant is finalized',
},
} as const;

const statusesToSelect = [
MERCHANT_REPORT_STATUSES_MAP['pending-review'],
MERCHANT_REPORT_STATUSES_MAP['under-review'],
MERCHANT_REPORT_STATUSES_MAP.completed,
];

const BadgeElement = forwardRef<ElementRef<typeof Badge>, { status: keyof typeof statusToData }>(
({ status, ...props }, ref) => {
const reportIsInProgress = [
MERCHANT_REPORT_STATUSES_MAP['in-progress'],
MERCHANT_REPORT_STATUSES_MAP['quality-control'],
].includes(status);

return (
<Badge
{...props}
ref={ref}
variant={statusToData[status].variant}
className={ctw(`h-6 space-x-1 text-sm font-medium hover:shadow-[0_0_2px_rgba(0,0,0,0.3)]`, {
'cursor-pointer': !reportIsInProgress,
'cursor-not-allowed bg-[#E3E2E0] text-[#32302C]/60 ': reportIsInProgress,
'bg-[#D3E5EF] text-[#183347]': status === MERCHANT_REPORT_STATUSES_MAP['under-review'],
'bg-[#DBEDDB] text-[#1C3829]': status === MERCHANT_REPORT_STATUSES_MAP['completed'],
})}
>
<span
className={ctw(`rounded-full d-2`, {
'bg-[#91918E]': reportIsInProgress,
'bg-[#5B97BD]': status === MERCHANT_REPORT_STATUSES_MAP['under-review'],
'bg-[#6C9B7D]': status === MERCHANT_REPORT_STATUSES_MAP['completed'],
})}
>
&nbsp;
</span>
<span>{statusToData[status].title ?? titleCase(status ?? '')}</span>
</Badge>
);
},
);

BadgeElement.displayName = 'BadgeElement';

export const MerchantMonitoringReportStatus = ({
status,
}: {
status?: keyof typeof statusToData;
}) => {
if (!status) {
return null;
}

return (
<DropdownMenu>
<DropdownMenuTrigger
className={`flex items-center`}
disabled={[
MERCHANT_REPORT_STATUSES_MAP['in-progress'],
MERCHANT_REPORT_STATUSES_MAP['quality-control'],
].includes(status)}
>
<BadgeElement status={status} />
</DropdownMenuTrigger>
<DropdownMenuContent align="center" className={`space-y-2 p-4`}>
{statusesToSelect.map(status => (
<DropdownMenuItem
key={status}
className="flex w-full cursor-pointer items-center px-8 py-1"
asChild
>
<Button
variant={'status'}
className="flex h-16 w-80 flex-col items-start justify-center space-y-1 px-4 py-2"
onClick={() => {
console.log(status);
}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove console.log from production code.

The onClick handler contains a console.log statement which should not be in production code.

Apply this diff to handle the status change properly:

-              onClick={() => {
-                console.log(status);
-              }}
+              onClick={() => {
+                // TODO: Implement status change handler
+                onStatusChange?.(status);
+              }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onClick={() => {
console.log(status);
}}
onClick={() => {
// TODO: Implement status change handler
onStatusChange?.(status);
}}

>
<BadgeElement status={status} />
<span className={`text-xs font-semibold leading-5 text-[#94A3B8]`}>
{statusToData[status].text}
</span>
</Button>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
);
};
Original file line number Diff line number Diff line change
@@ -1,33 +1,30 @@
import {
Badge,
CheckCircle,
ContentTooltip,
severityToClassName,
TextWithNAFallback,
WarningFilledSvg,
} from '@ballerine/ui';
import React from 'react';
import dayjs from 'dayjs';
import timezone from 'dayjs/plugin/timezone';
import utc from 'dayjs/plugin/utc';
import { Minus } from 'lucide-react';
import { titleCase } from 'string-ts';
import timezone from 'dayjs/plugin/timezone';
import { createColumnHelper } from '@tanstack/react-table';
import { MERCHANT_REPORT_TYPES_MAP } from '@ballerine/common';

// Add these plugins to dayjs
dayjs.extend(utc);
dayjs.extend(timezone);

import { ctw } from '@/common/utils/ctw/ctw';
import { TBusinessReport } from '@/domains/business-reports/fetchers';
import { createColumnHelper } from '@tanstack/react-table';
import { titleCase } from 'string-ts';

import { CopyToClipboardButton } from '@/common/components/atoms/CopyToClipboardButton/CopyToClipboardButton';
import { IndicatorCircle } from '@/common/components/atoms/IndicatorCircle/IndicatorCircle';
import { useEllipsesWithTitle } from '@/common/hooks/useEllipsesWithTitle/useEllipsesWithTitle';
import { ctw } from '@/common/utils/ctw/ctw';
import {
getSeverityFromRiskScore,
MERCHANT_REPORT_STATUSES_MAP,
MERCHANT_REPORT_TYPES_MAP,
} from '@ballerine/common';
import {
Badge,
CheckCircle,
ContentTooltip,
severityToClassName,
TextWithNAFallback,
WarningFilledSvg,
} from '@ballerine/ui';
import { Minus } from 'lucide-react';
import { CopyToClipboardButton } from '@/common/components/atoms/CopyToClipboardButton/CopyToClipboardButton';
import { MerchantMonitoringReportStatus } from '@/pages/MerchantMonitoring/components/MerchantMonitoringReportStatus/MerchantMonitoringReportStatus';

const columnHelper = createColumnHelper<TBusinessReport>();

Expand All @@ -36,11 +33,6 @@ const SCAN_TYPES = {
MONITORING: 'Monitoring',
} as const;

const REPORT_STATUS_TO_DISPLAY_STATUS = {
[MERCHANT_REPORT_STATUSES_MAP.completed]: 'Ready for Review',
[MERCHANT_REPORT_STATUSES_MAP['quality-control']]: 'Quality Control',
} as const;

const REPORT_TYPE_TO_SCAN_TYPE = {
[MERCHANT_REPORT_TYPES_MAP.MERCHANT_REPORT_T1]: SCAN_TYPES.ONBOARDING,
[MERCHANT_REPORT_TYPES_MAP.ONGOING_MERCHANT_REPORT_T1]: SCAN_TYPES.MONITORING,
Expand Down Expand Up @@ -93,7 +85,7 @@ export const columns = [
<p>This merchant is {!value && 'not '}subscribed to recurring ongoing monitoring</p>
}
props={{
tooltipTrigger: { className: 'flex w-full justify-center' },
tooltipTrigger: { className: 'flex w-full justify-start' },
tooltipContent: { align: 'center', side: 'top' },
}}
>
Expand Down Expand Up @@ -207,20 +199,7 @@ export const columns = [
cell: info => {
const status = info.getValue();

return (
<TextWithNAFallback
className={ctw('font-semibold', {
'text-slate-400': status === MERCHANT_REPORT_STATUSES_MAP.completed,
'text-destructive': status === MERCHANT_REPORT_STATUSES_MAP.failed,
})}
>
{titleCase(
REPORT_STATUS_TO_DISPLAY_STATUS[
status as keyof typeof REPORT_STATUS_TO_DISPLAY_STATUS
] ?? status,
)}
</TextWithNAFallback>
);
return <MerchantMonitoringReportStatus status={status} />;
},
header: 'Status',
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ export const useMerchantMonitoringTableLogic = () => {
cell,
children,
}) => {
if (cell.row.original.status === MERCHANT_REPORT_STATUSES_MAP.completed) {
if (
[
MERCHANT_REPORT_STATUSES_MAP['pending-review'],
MERCHANT_REPORT_STATUSES_MAP['under-review'],
MERCHANT_REPORT_STATUSES_MAP.completed,
].includes(cell.row.original.status)
) {
return (
<Link
to={`/${locale}/merchant-monitoring/${cell.row.id}`}
Expand Down
Loading