From 72822aea2ba4360a7b783019e2ac8fe9575be00e Mon Sep 17 00:00:00 2001 From: Sasha Date: Thu, 16 Jan 2025 10:24:47 +0100 Subject: [PATCH] fix: UI fixes for statistics and merchant monitoring report pages (#2965) --- .../src/pages/Home/Home.page.tsx | 1 - .../MerchantMonitoringTable/columns.tsx | 67 ++++++++-------- .../src/pages/Statistics/Statistics.page.tsx | 1 + .../PortfolioRiskStatistics.tsx | 32 ++++---- .../usePortfolioRiskStatisticsLogic.tsx | 22 ++---- apps/kyb-app/CHANGELOG.md | 7 ++ apps/kyb-app/package.json | 4 +- packages/react-pdf-toolkit/CHANGELOG.md | 7 ++ packages/react-pdf-toolkit/package.json | 4 +- packages/ui/CHANGELOG.md | 6 ++ packages/ui/package.json | 2 +- .../ui/src/components/atoms/Chart/Chart.tsx | 18 +++-- .../molecules/ContentTooltip/index.ts | 1 + packages/ui/src/components/molecules/index.ts | 1 + .../WebsiteCredibility/WebsiteCredibility.tsx | 78 +++++++------------ pnpm-lock.yaml | 12 +-- 16 files changed, 131 insertions(+), 132 deletions(-) create mode 100644 packages/ui/src/components/molecules/ContentTooltip/index.ts diff --git a/apps/backoffice-v2/src/pages/Home/Home.page.tsx b/apps/backoffice-v2/src/pages/Home/Home.page.tsx index 1798043426..c4b6160ad3 100644 --- a/apps/backoffice-v2/src/pages/Home/Home.page.tsx +++ b/apps/backoffice-v2/src/pages/Home/Home.page.tsx @@ -53,7 +53,6 @@ export const Home: FunctionComponent = () => { {/* */} {/* */} {/* */} - {/* */} {/* */} {/**/} {(isDemo || isExample) && } diff --git a/apps/backoffice-v2/src/pages/MerchantMonitoring/components/MerchantMonitoringTable/columns.tsx b/apps/backoffice-v2/src/pages/MerchantMonitoring/components/MerchantMonitoringTable/columns.tsx index 9f5fa2d8e4..506e1ec834 100644 --- a/apps/backoffice-v2/src/pages/MerchantMonitoring/components/MerchantMonitoringTable/columns.tsx +++ b/apps/backoffice-v2/src/pages/MerchantMonitoring/components/MerchantMonitoringTable/columns.tsx @@ -1,34 +1,33 @@ import dayjs from 'dayjs'; -import utc from 'dayjs/plugin/utc'; import timezone from 'dayjs/plugin/timezone'; +import utc from 'dayjs/plugin/utc'; // Add these plugins to dayjs dayjs.extend(utc); dayjs.extend(timezone); -import { createColumnHelper } from '@tanstack/react-table'; 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 { + MERCHANT_REPORT_STATUSES_MAP, + MERCHANT_REPORT_TYPES_MAP, +} from '@/domains/business-reports/constants'; import { getSeverityFromRiskScore } from '@ballerine/common'; import { Badge, CheckCircle, + ContentTooltip, severityToClassName, TextWithNAFallback, WarningFilledSvg, } from '@ballerine/ui'; -import { useEllipsesWithTitle } from '@/common/hooks/useEllipsesWithTitle/useEllipsesWithTitle'; -import { CopyToClipboardButton } from '@/common/components/atoms/CopyToClipboardButton/CopyToClipboardButton'; import { Minus } from 'lucide-react'; -import { - MERCHANT_REPORT_STATUSES_MAP, - MERCHANT_REPORT_TYPES_MAP, -} from '@/domains/business-reports/constants'; -import React from 'react'; -import { IndicatorCircle } from '@/common/components/atoms/IndicatorCircle/IndicatorCircle'; -import { TooltipTrigger, TooltipContent, Tooltip } from '@ballerine/ui'; const columnHelper = createColumnHelper(); @@ -93,9 +92,19 @@ export const columns = [ }), columnHelper.accessor('monitoringStatus', { cell: ({ getValue }) => { - return getValue() ? ( - - + const value = getValue(); + + return ( + This merchant is {!value && 'not '}subscribed to recurring ongoing monitoring

+ } + props={{ + tooltipTrigger: { className: 'flex w-full justify-center' }, + tooltipContent: { align: 'center', side: 'top' }, + }} + > + {value ? ( -
- - This website is actively monitored for changes on a recurring basis - -
- ) : ( - - + ) : ( - - This website is not currently monitored for changes - + )} + ); }, header: () => ( - - - Monitored - - - Indicates whether this website is being monitored for changes - - + Indicates whether the merchant is subscribed to ongoing monitoring

} + props={{ + tooltipContent: { align: 'center', side: 'top' }, + }} + > + Monitored +
), }), columnHelper.accessor('reportType', { diff --git a/apps/backoffice-v2/src/pages/Statistics/Statistics.page.tsx b/apps/backoffice-v2/src/pages/Statistics/Statistics.page.tsx index eef3733fff..71360b469f 100644 --- a/apps/backoffice-v2/src/pages/Statistics/Statistics.page.tsx +++ b/apps/backoffice-v2/src/pages/Statistics/Statistics.page.tsx @@ -31,6 +31,7 @@ export const Statistics: FunctionComponent = () => { removedMerchantsCount={data.removedMerchantsCount} /> diff --git a/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/PortfolioRiskStatistics.tsx b/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/PortfolioRiskStatistics.tsx index 20e5a2d8ce..9720bd3c6e 100644 --- a/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/PortfolioRiskStatistics.tsx +++ b/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/PortfolioRiskStatistics.tsx @@ -1,9 +1,13 @@ +import { buttonVariants, WarningFilledSvg } from '@ballerine/ui'; import { FunctionComponent } from 'react'; +import { Link } from 'react-router-dom'; +import { Cell, Pie, PieChart } from 'recharts'; +import { titleCase } from 'string-ts'; +import { z } from 'zod'; + import { Card } from '@/common/components/atoms/Card/Card'; -import { CardHeader } from '@/common/components/atoms/Card/Card.Header'; import { CardContent } from '@/common/components/atoms/Card/Card.Content'; -import { Cell, Pie, PieChart } from 'recharts'; -import { ctw } from '@/common/utils/ctw/ctw'; +import { CardHeader } from '@/common/components/atoms/Card/Card.Header'; import { Table, TableBody, @@ -12,16 +16,15 @@ import { TableHeader, TableRow, } from '@/common/components/atoms/Table'; -import { titleCase } from 'string-ts'; -import { usePortfolioRiskStatisticsLogic } from '@/pages/Statistics/components/PortfolioRiskStatistics/hooks/usePortfolioRiskStatisticsLogic/usePortfolioRiskStatisticsLogic'; -import { z } from 'zod'; +import { ctw } from '@/common/utils/ctw/ctw'; import { MetricsResponseSchema } from '@/domains/business-reports/hooks/queries/useBusinessReportMetricsQuery/useBusinessReportMetricsQuery'; -import { Link } from 'react-router-dom'; -import { buttonVariants, WarningFilledSvg } from '@ballerine/ui'; +import { usePortfolioRiskStatisticsLogic } from '@/pages/Statistics/components/PortfolioRiskStatistics/hooks/usePortfolioRiskStatisticsLogic/usePortfolioRiskStatisticsLogic'; export const PortfolioRiskStatistics: FunctionComponent< - Pick, 'riskLevelCounts' | 'violationCounts'> -> = ({ riskLevelCounts, violationCounts }) => { + Pick, 'riskLevelCounts' | 'violationCounts'> & { + userSelectedDate: Date; + } +> = ({ riskLevelCounts, violationCounts, userSelectedDate }) => { const { riskLevelToFillColor, parent, @@ -30,10 +33,11 @@ export const PortfolioRiskStatistics: FunctionComponent< filteredRiskIndicators, locale, navigate, + alertedReports, from, to, - alertedReports, } = usePortfolioRiskStatisticsLogic({ + userSelectedDate, violationCounts, }); @@ -84,7 +88,9 @@ export const PortfolioRiskStatistics: FunctionComponent< 'cursor-pointer outline-none', )} onClick={() => - navigate(`/${locale}/merchant-monitoring?riskLevels[0]=${riskLevel}`) + navigate( + `/${locale}/merchant-monitoring?riskLevels[0]=${riskLevel}&from=${from}&to=${to}`, + ) } /> ))} @@ -135,7 +141,7 @@ export const PortfolioRiskStatistics: FunctionComponent< diff --git a/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/hooks/usePortfolioRiskStatisticsLogic/usePortfolioRiskStatisticsLogic.tsx b/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/hooks/usePortfolioRiskStatisticsLogic/usePortfolioRiskStatisticsLogic.tsx index 2689c99a4e..ce870cf7b5 100644 --- a/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/hooks/usePortfolioRiskStatisticsLogic/usePortfolioRiskStatisticsLogic.tsx +++ b/apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/hooks/usePortfolioRiskStatisticsLogic/usePortfolioRiskStatisticsLogic.tsx @@ -16,7 +16,8 @@ import { useBusinessReportsQuery } from '@/domains/business-reports/hooks/querie export const usePortfolioRiskStatisticsLogic = ({ violationCounts, -}: Pick, 'violationCounts'>) => { + userSelectedDate, +}: Pick, 'violationCounts'> & { userSelectedDate: Date }) => { const [parent] = useAutoAnimate(); const [riskIndicatorsSorting, setRiskIndicatorsSorting] = useState('desc'); const onSortRiskIndicators = useCallback( @@ -48,23 +49,14 @@ export const usePortfolioRiskStatisticsLogic = ({ ); const locale = useLocale(); const navigate = useNavigate(); - const getLast30DaysDateRange = () => { - const today = dayjs(); - const thirtyDaysAgo = today.subtract(30, 'day'); - return { - from: thirtyDaysAgo.format('YYYY-MM-DD'), - to: today.format('YYYY-MM-DD'), - }; - }; - - const last30DaysDateRange = getLast30DaysDateRange(); - const [{ from }] = useZodSearchParams(StatisticsSearchSchema); + const from = dayjs(userSelectedDate).format('YYYY-MM-DD'); + const to = dayjs(userSelectedDate).add(1, 'month').format('YYYY-MM-DD'); const { data: businessReports } = useBusinessReportsQuery({ isAlert: true, from, - to: dayjs(from).add(1, 'month').format('YYYY-MM-DD'), + to, }); const alertedReports = businessReports?.totalItems ?? 0; @@ -79,8 +71,8 @@ export const usePortfolioRiskStatisticsLogic = ({ filteredRiskIndicators, locale, navigate, - from: last30DaysDateRange.from, - to: last30DaysDateRange.to, + from, + to, alertedReports, }; }; diff --git a/apps/kyb-app/CHANGELOG.md b/apps/kyb-app/CHANGELOG.md index 4725d46091..3ce302e21d 100644 --- a/apps/kyb-app/CHANGELOG.md +++ b/apps/kyb-app/CHANGELOG.md @@ -1,5 +1,12 @@ # kyb-app +## 0.3.110 + +### Patch Changes + +- Updated dependencies + - @ballerine/ui@0.5.63 + ## 0.3.109 ### Patch Changes diff --git a/apps/kyb-app/package.json b/apps/kyb-app/package.json index 1d3c40e3d8..4e4d538006 100644 --- a/apps/kyb-app/package.json +++ b/apps/kyb-app/package.json @@ -1,7 +1,7 @@ { "name": "@ballerine/kyb-app", "private": true, - "version": "0.3.109", + "version": "0.3.110", "type": "module", "scripts": { "dev": "vite", @@ -19,7 +19,7 @@ "@ballerine/blocks": "0.2.32", "@ballerine/common": "^0.9.66", "@ballerine/workflow-browser-sdk": "0.6.85", - "@ballerine/ui": "0.5.62", + "@ballerine/ui": "0.5.63", "@lukemorales/query-key-factory": "^1.0.3", "@radix-ui/react-icons": "^1.3.0", "@rjsf/core": "^5.9.0", diff --git a/packages/react-pdf-toolkit/CHANGELOG.md b/packages/react-pdf-toolkit/CHANGELOG.md index 0256f35422..ee9f9a4456 100644 --- a/packages/react-pdf-toolkit/CHANGELOG.md +++ b/packages/react-pdf-toolkit/CHANGELOG.md @@ -1,5 +1,12 @@ # @ballerine/react-pdf-toolkit +## 1.2.63 + +### Patch Changes + +- Updated dependencies + - @ballerine/ui@0.5.63 + ## 1.2.62 ### Patch Changes diff --git a/packages/react-pdf-toolkit/package.json b/packages/react-pdf-toolkit/package.json index ef1f896b28..39661eb59a 100644 --- a/packages/react-pdf-toolkit/package.json +++ b/packages/react-pdf-toolkit/package.json @@ -1,7 +1,7 @@ { "name": "@ballerine/react-pdf-toolkit", "private": false, - "version": "1.2.62", + "version": "1.2.63", "types": "./dist/build.d.ts", "main": "./dist/react-pdf-toolkit.js", "module": "./dist/react-pdf-toolkit.mjs", @@ -27,7 +27,7 @@ }, "dependencies": { "@ballerine/config": "^1.1.30", - "@ballerine/ui": "0.5.62", + "@ballerine/ui": "0.5.63", "@react-pdf/renderer": "^3.1.14", "@sinclair/typebox": "^0.31.7", "ajv": "^8.12.0", diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md index a99bd0b47a..e93634bd7e 100644 --- a/packages/ui/CHANGELOG.md +++ b/packages/ui/CHANGELOG.md @@ -1,5 +1,11 @@ # @ballerine/ui +## 0.5.63 + +### Patch Changes + +- Export ContentTooltip component + ## 0.5.62 ### Patch Changes diff --git a/packages/ui/package.json b/packages/ui/package.json index 2bd8265e07..ae8b3c0e27 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,7 +1,7 @@ { "name": "@ballerine/ui", "private": false, - "version": "0.5.62", + "version": "0.5.63", "type": "module", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/ui/src/components/atoms/Chart/Chart.tsx b/packages/ui/src/components/atoms/Chart/Chart.tsx index b3e74fb40b..f82e968c2c 100644 --- a/packages/ui/src/components/atoms/Chart/Chart.tsx +++ b/packages/ui/src/components/atoms/Chart/Chart.tsx @@ -1,6 +1,7 @@ import { ctw } from '@/common/utils/ctw'; import * as React from 'react'; import * as RechartsPrimitive from 'recharts'; +import { ValueType } from 'recharts/types/component/DefaultTooltipContent'; // Format: { THEME_NAME: CSS_SELECTOR } const THEMES = { light: '', dark: '.dark' } as const; @@ -100,6 +101,7 @@ const ChartTooltipContent = React.forwardRef< indicator?: 'line' | 'dot' | 'dashed'; nameKey?: string; labelKey?: string; + valueRender?: (value: ValueType) => React.ReactNode; } >( ( @@ -110,6 +112,7 @@ const ChartTooltipContent = React.forwardRef< indicator = 'dot', hideLabel = false, hideIndicator = false, + valueRender, label, labelFormatter, labelClassName, @@ -217,11 +220,12 @@ const ChartTooltipContent = React.forwardRef< {itemConfig?.label || item.name} - {item.value && ( - - {item.value.toLocaleString()} - - )} + {item.value && + (valueRender?.(item.value) ?? ( + + {item.value.toLocaleString()} + + ))} )} @@ -291,7 +295,7 @@ const ChartLegendContent = React.forwardRef< ChartLegendContent.displayName = 'ChartLegend'; // Helper to extract item config from a payload. -function getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key: string) { +const getPayloadConfigFromPayload = (config: ChartConfig, payload: unknown, key: string) => { if (typeof payload !== 'object' || payload === null) { return undefined; } @@ -314,7 +318,7 @@ function getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key: } return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config]; -} +}; export { ChartContainer, diff --git a/packages/ui/src/components/molecules/ContentTooltip/index.ts b/packages/ui/src/components/molecules/ContentTooltip/index.ts new file mode 100644 index 0000000000..086008aab9 --- /dev/null +++ b/packages/ui/src/components/molecules/ContentTooltip/index.ts @@ -0,0 +1 @@ +export * from './ContentTooltip'; diff --git a/packages/ui/src/components/molecules/index.ts b/packages/ui/src/components/molecules/index.ts index 1841c425ea..7a5ca9100b 100644 --- a/packages/ui/src/components/molecules/index.ts +++ b/packages/ui/src/components/molecules/index.ts @@ -1,3 +1,4 @@ +export * from './ContentTooltip'; export * from './JsonDialog'; export * from './inputs'; export * from './ErrorsList'; diff --git a/packages/ui/src/components/templates/report/components/WebsiteCredibility/WebsiteCredibility.tsx b/packages/ui/src/components/templates/report/components/WebsiteCredibility/WebsiteCredibility.tsx index f011a255fa..546d0f2628 100644 --- a/packages/ui/src/components/templates/report/components/WebsiteCredibility/WebsiteCredibility.tsx +++ b/packages/ui/src/components/templates/report/components/WebsiteCredibility/WebsiteCredibility.tsx @@ -1,13 +1,24 @@ +import { ctw } from '@/common'; import { Card, CardContent, CardHeader } from '@/components'; -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/atoms'; +import { + CardDescription, + ChartContainer, + ChartTooltip, + ChartTooltipContent, + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from '@/components/atoms'; import { BallerineLink } from '@/components/atoms/BallerineLink/BallerineLink'; -import { ctw } from '@/common'; import { ContentTooltip } from '@/components/molecules/ContentTooltip/ContentTooltip'; import { RiskIndicators } from '@/components/molecules/RiskIndicators/RiskIndicators'; import dayjs from 'dayjs'; -import { InfoIcon, TrendingDown } from 'lucide-react'; +import { InfoIcon } from 'lucide-react'; import { FunctionComponent, useMemo } from 'react'; import { + Area, + AreaChart, CartesianGrid, Cell, Legend, @@ -18,10 +29,6 @@ import { YAxis, } from 'recharts'; import { capitalize } from 'string-ts'; -import { TrendingUp } from 'lucide-react'; -import { Area, AreaChart } from 'recharts'; -import { CardDescription, CardFooter } from '@/components/atoms'; -import { ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/atoms'; const engagementMetricsMapper = { 'Time on site': { @@ -81,23 +88,6 @@ export const WebsiteCredibility: FunctionComponent<{ .map(({ label, value }) => ({ label, value: parseFloat(value.toFixed(2)) })); }, [trafficAnalysis.trafficSources]); - const calculateTrend = (data: Array<{ label: string; value: string }>) => { - if (data.length < 2) { - return { direction: 'No trend data', percentage: 0 }; - } - - const lastMonthValue = parseInt(data[data.length - 1]?.value ?? '0'); - const previousMonthValue = parseInt(data[data.length - 2]?.value ?? '0'); - const percentageChange = ((lastMonthValue - previousMonthValue) / previousMonthValue) * 100; - const direction = lastMonthValue > previousMonthValue ? 'up' : 'down'; - - return { direction, percentage: Math.abs(percentageChange) }; - }; - - const trend = calculateTrend( - trafficAnalysis.montlyVisitsIndicators.map(({ label, value }) => ({ label, value })), - ); - return (
@@ -194,8 +184,8 @@ export const WebsiteCredibility: FunctionComponent<{ } + content={ + ( + + {Intl.NumberFormat('en').format(Number(value))} + + )} + /> + } /> )} - -
-
-
- {trend.direction !== 'No trend data' && ( - <> - {trend.direction === 'up' ? ( - - ) : ( - - )} - {`Trending ${trend.direction} by ${trend.percentage.toFixed( - 1, - )}% this month`} - - )} -
-
-
-
- {/*
-
*/}
Traffic Sources @@ -468,9 +445,6 @@ export const WebsiteCredibility: FunctionComponent<{ - - {/*
-
*/}
); }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9de65bc44b..86f7dda3fa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -536,7 +536,7 @@ importers: specifier: ^0.9.66 version: link:../../packages/common '@ballerine/ui': - specifier: 0.5.62 + specifier: 0.5.63 version: link:../../packages/ui '@ballerine/workflow-browser-sdk': specifier: 0.6.85 @@ -1516,7 +1516,7 @@ importers: specifier: ^1.1.30 version: link:../config '@ballerine/ui': - specifier: 0.5.62 + specifier: 0.5.63 version: link:../ui '@react-pdf/renderer': specifier: ^3.1.14 @@ -20306,7 +20306,7 @@ packages: '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.3) '@types/babel__core': 7.20.4 react-refresh: 0.14.0 - vite: 4.5.3(@types/node@18.17.19) + vite: 4.5.3(@types/node@20.9.2) transitivePeerDependencies: - supports-color dev: true @@ -38536,7 +38536,7 @@ packages: strip-ansi: 6.0.1 tiny-invariant: 1.3.1 typescript: 5.1.6 - vite: 4.5.3(@types/node@18.17.19) + vite: 4.5.3(@types/node@20.9.2) vscode-languageclient: 7.0.0 vscode-languageserver: 7.0.0 vscode-languageserver-textdocument: 1.0.11 @@ -38667,7 +38667,7 @@ packages: kolorist: 1.8.0 sirv: 2.0.3 ufo: 1.3.2 - vite: 4.5.3(@types/node@18.17.19) + vite: 4.5.3(@types/node@20.9.2) transitivePeerDependencies: - rollup - supports-color @@ -38746,7 +38746,7 @@ packages: debug: 4.3.4(supports-color@8.1.1) globrex: 0.1.2 tsconfck: 2.1.2(typescript@5.1.6) - vite: 4.5.3(@types/node@18.17.19) + vite: 4.5.3(@types/node@20.9.2) transitivePeerDependencies: - supports-color - typescript