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

ongoing monitoring turning on and off #2941

Merged
merged 3 commits into from
Jan 8, 2025

Conversation

tomer-shvadron
Copy link
Collaborator

@tomer-shvadron tomer-shvadron commented Jan 7, 2025

Summary by CodeRabbit

Release Notes

  • New Features

    • Added business monitoring functionality with the ability to turn monitoring on and off for merchants
    • Introduced portfolio analytics and risk statistics in the statistics page
    • Enhanced merchant monitoring table with new columns and monitoring status display
  • Improvements

    • Updated localization for toast messages related to business monitoring
    • Improved date selection and metrics filtering in statistics
    • Enhanced user registration and activity tracking
  • Bug Fixes

    • Refined portfolio risk statistics display
    • Improved error handling for monitoring state changes
  • Documentation

    • Updated API schemas to support new monitoring and metrics features

- Add success and error messages for turning monitoring on/off
- Update API endpoints to manage ongoing monitoring status
- Integrate tooltip UI for monitoring status display

(Your code is so reactive that I'm surprised it doesn't require a safe word)
Copy link

changeset-bot bot commented Jan 7, 2025

⚠️ No Changeset found

Latest commit: 652ab0e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

coderabbitai bot commented Jan 7, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This pull request introduces comprehensive enhancements to the business monitoring functionality across multiple applications and services. The changes span from frontend components to backend services, adding new features for managing merchant monitoring, updating user interfaces, and improving metrics tracking. Key additions include a new monitoring status feature, enhanced portfolio analytics, and more detailed business report metrics with date range filtering capabilities.

Changes

File Change Summary
apps/backoffice-v2/public/locales/en/toast.json Added localization entries for business monitoring activation and deactivation
apps/backoffice-v2/src/common/components/templates/Providers/Providers.tsx Added TooltipProvider to component hierarchy
apps/backoffice-v2/src/domains/auth/validation-schemas.ts Added lastActiveAt and registrationDate to AuthenticatedUserSchema
apps/backoffice-v2/src/pages/Statistics/* Introduced new components for portfolio analytics and risk statistics
services/workflows-service/src/business-report/* Added monitoring status, new DTOs, and metrics retrieval methods
services/workflows-service/src/business/business.controller.external.ts Added method to update ongoing monitoring state

Sequence Diagram

sequenceDiagram
    participant User
    participant Frontend
    participant BackendController
    participant BusinessService
    participant MonitoringClient

    User->>Frontend: Toggle Monitoring Status
    Frontend->>BackendController: Update Monitoring State
    BackendController->>BusinessService: Update Business Metadata
    BusinessService->>MonitoringClient: Retrieve/Update Metrics
    MonitoringClient-->>BusinessService: Return Monitoring Data
    BusinessService-->>BackendController: Confirm Update
    BackendController-->>Frontend: Return Updated Status
    Frontend->>User: Display Success/Error Toast
Loading

Possibly related PRs

Suggested Reviewers

  • Omri-Levy
  • MatanYadaev
  • alonp99

Poem

🐰 Merchant Monitoring Magic

With metrics sharp and status bright,
Our rabbit hops through data's might.
Monitoring on, monitoring off,
Watch businesses take flight and aloft!

Code leaps and bounds with rabbit glee! 🚀


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@tomer-shvadron tomer-shvadron changed the base branch from dev to mm-ui-ux-hackathon-jan-2025 January 7, 2025 12:19
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

Actionable comments posted: 8

🧹 Nitpick comments (25)
apps/backoffice-v2/src/pages/Statistics/Statistics.page.tsx (2)

12-17: Consider improving error handling UX

Instead of throwing the error directly, consider implementing a user-friendly error state component that:

  • Displays the error message in a readable format
  • Provides retry functionality
  • Logs the error for monitoring
  if (error) {
-   throw error;
+   return (
+     <div className="flex flex-col items-center justify-center space-y-4">
+       <p className="text-red-500">Failed to load statistics</p>
+       <button
+         onClick={() => window.location.reload()}
+         className="rounded bg-primary px-4 py-2 text-white"
+       >
+         Retry
+       </button>
+     </div>
+   );
  }

32-32: Clean up commented code

There are commented-out components (UserStatistics and WorkflowStatistics) in the code. If these components are no longer needed, consider removing them completely. If they are planned for future use, document the reason for keeping them commented.

Also applies to: 37-37

services/workflows-service/src/business-report/business-report.controller.external.ts (1)

119-143: Optimize Database Calls in Reports Mapping to Improve Performance

In the listBusinessReports method, you are fetching business metadata for each report individually within the map function:

const business = await this.businessService.getById(
  report.merchantId,
  { select: { metadata: true } },
  [currentProjectId],
);

This can lead to performance issues due to multiple sequential database calls, especially when processing a large number of reports. Consider optimizing this by fetching all required business metadata in a single query before mapping over the reports. You can retrieve all relevant businesses at once and then associate them with the reports within the mapping.

services/workflows-service/src/business-report/dtos/business-report-metrics.dto.ts (2)

5-15: Add Date Format Validation to 'from' and 'to' Parameters in DTO

In the BusinessReportMetricsRequestQueryDto, the from and to parameters are currently validated as optional strings. To ensure they represent valid dates, consider adding the @IsISO8601() decorator from class-validator:

import { IsOptional, IsString } from 'class-validator';
+import { IsISO8601 } from 'class-validator';

export class BusinessReportMetricsRequestQueryDto {
  @IsOptional()
+ @IsISO8601()
  @IsString()
  @ApiProperty({ type: String, required: false })
  from?: string;

  @IsOptional()
+ @IsISO8601()
  @IsString()
  @ApiProperty({ type: String, required: false })
  to?: string;
}

This ensures that any provided from and to values are valid ISO 8601 date strings.


17-20: Enhance Date Validation in Zod Schema for 'from' and 'to'

In the BusinessReportsMetricsQuerySchema, the from and to fields are defined as optional strings:

from: z.string().optional(),
to: z.string().optional(),

To ensure they are valid date-time strings, consider adding .datetime():

export const BusinessReportsMetricsQuerySchema = z.object({
-  from: z.string().optional(),
-  to: z.string().optional(),
+  from: z.string().datetime().optional(),
+  to: z.string().datetime().optional(),
});

This adds an extra layer of validation for incoming query parameters.

apps/backoffice-v2/src/pages/MerchantMonitoringBusinessReport/fetchers.ts (1)

14-19: Consider reducing the timeout duration.

The current timeout of 300,000ms (5 minutes) seems excessive for a monitoring state toggle operation. Consider reducing it to a more reasonable duration (e.g., 30-60 seconds) unless there's a specific requirement for such a long timeout.

apps/backoffice-v2/src/pages/Statistics/components/PortfolioAnalytics/hooks/usePortfolioAnalyticsLogic.tsx (2)

31-42: Consider extracting width calculation logic.

The width calculation logic could be simplified and made more reusable.

Consider extracting it into a utility function:

const calculateRelativeWidths = (items: Array<{count: number}>, minWidth = 2) => {
  const maxCount = Math.max(...items.map(item => item.count), 0);
  return items.map(item => 
    item.count > 0 ? Math.max((item.count / maxCount) * 100, minWidth) : 0
  );
};

17-22: Consider using a more reusable sorting callback.

The sorting callback could be made more reusable by accepting the current sort direction.

Consider this approach:

const onSortRiskIndicators = useCallback(() => {
  setRiskIndicatorsSorting(current => current === 'asc' ? 'desc' : 'asc');
}, []);
apps/backoffice-v2/src/pages/Statistics/hooks/useStatisticsLogic.tsx (1)

13-22: Improve date validation readability.

The date validation logic is complex and could benefit from being broken down into named functions for better readability and maintainability.

-    from: z.string().transform(data => {
-      const dayjsDate = dayjs(data, 'YYYY-MM-DD', true);
-
-      return dayjsDate.isValid() &&
-        dayjsDate.isBefore(dayjs()) &&
-        dayjsDate.date() === 1 &&
-        dayjsDate.add(1, 'day').isAfter(dayjs(registrationDate).startOf('month'))
-        ? data
-        : dayjs().startOf('month').format('YYYY-MM-DD');
-    }),
+    from: z.string().transform(data => {
+      const dayjsDate = dayjs(data, 'YYYY-MM-DD', true);
+      
+      const isValidDate = dayjsDate.isValid();
+      const isBeforeToday = dayjsDate.isBefore(dayjs());
+      const isFirstOfMonth = dayjsDate.date() === 1;
+      const isAfterRegistration = dayjsDate
+        .add(1, 'day')
+        .isAfter(dayjs(registrationDate).startOf('month'));
+      
+      return (isValidDate && isBeforeToday && isFirstOfMonth && isAfterRegistration)
+        ? data
+        : dayjs().startOf('month').format('YYYY-MM-DD');
+    }),
services/workflows-service/src/auth/session-serializer.ts (1)

49-51: Consider adding index for frequently accessed fields.

Since createdAt and lastActiveAt are now being queried alongside other user data, consider adding an index to optimize these frequent lookups.

apps/backoffice-v2/src/pages/Statistics/components/PortfolioAnalytics/PortfolioAnalytics.tsx (1)

21-25: Add ARIA labels for better accessibility.

The icons and statistics should have proper ARIA labels for screen readers.

-          <Users className="h-4 w-4 text-muted-foreground" />
+          <Users className="h-4 w-4 text-muted-foreground" aria-hidden="true" />
           <p>
-            Total Active Merchants: <span className="font-semibold">{totalActiveMerchants}</span>
+            <span aria-label="Total Active Merchants">Total Active Merchants: </span>
+            <span className="font-semibold" aria-label={`${totalActiveMerchants} merchants`}>
+              {totalActiveMerchants}
+            </span>
           </p>
apps/backoffice-v2/src/pages/Statistics/components/MonthPicker/MonthPicker.tsx (2)

6-7: Memoize static values.

Consider memoizing the static today value and months array to prevent unnecessary re-renders.

-const today = dayjs();
-const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+const today = dayjs();
+const months = Object.freeze(['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);

80-99: Optimize month button rendering.

Consider memoizing the month buttons to prevent unnecessary re-renders.

+const MonthButton = memo(({ month, index, ...props }) => (
+  <Button
+    key={month}
+    {...props}
+  >
+    {month}
+  </Button>
+));

-          {months.map((month, index) => (
+          {useMemo(() => months.map((month, index) => (
             <MonthButton
               key={month}
+              month={month}
+              index={index}
               onClick={() => handleMonthSelect(index)}
               disabled={
                 isMonthDisabled(index) ||
                 (dayjsMinDate &&
                   currentYear === dayjsMinDate.year() &&
                   index < dayjsMinDate.month())
               }
               variant="ghost"
               className={ctw(
                 'h-9 w-full',
                 isSameMonth(dayjsDate, dayjs().year(currentYear).month(index)) &&
                   'bg-primary text-primary-foreground',
               )}
-            >
-              {month}
-            </Button>
+            />
-          ))}
+          )), [currentYear, dayjsDate, dayjsMinDate])}
apps/backoffice-v2/src/pages/MerchantMonitoringBusinessReport/hooks/useMerchantMonitoringBusinessReportLogic/useMerchantMonitoringBusinessReportLogic.tsx (1)

80-96: Consider adding error handling and loading states.

While the monitoring toggle functions are properly memoized, they could benefit from error handling and loading state management.

 const turnOngoingMonitoringOn = useCallback(
   (merchantId: string | undefined) => {
     if (merchantId) {
-      turnMonitoringOnMutation.mutate(merchantId);
+      try {
+        turnMonitoringOnMutation.mutate(merchantId, {
+          onError: (error) => {
+            toast.error('Failed to enable monitoring');
+          },
+        });
+      } catch (error) {
+        console.error('Error enabling monitoring:', error);
+      }
     }
   },
   [turnMonitoringOnMutation],
 );
apps/backoffice-v2/src/domains/business-reports/fetchers.ts (1)

33-33: Consider adding a default value for monitoringStatus.

While the boolean type is correct, consider providing a default value to handle cases where the status might not be set.

-    monitoringStatus: z.boolean(),
+    monitoringStatus: z.boolean().default(false),
packages/ui/src/components/templates/report/hooks/useReportTabs/useReportTabs.tsx (1)

Line range hint 89-96: Update type definition to document null values.

The type definition should be more explicit about the possibility of null values.

   } as const satisfies ReadonlyArray<{
     title: string;
     search: string;
-    violations: Array<{
+    violations: Array<{
       label: string;
       severity: string;
-    }> | null;
+    }> | null; // null indicates no violations present
   }>;
apps/backoffice-v2/src/pages/MerchantMonitoringBusinessReport/MerchantMonitoringBusinessReport.page.tsx (1)

117-127: Add accessibility attributes to the status indicator.

While the visual implementation is good, consider adding ARIA attributes for better accessibility.

 <span
   className={ctw('select-none rounded-full d-3', {
     'bg-success': businessReport?.monitoringStatus,
     'bg-slate-400': !businessReport?.monitoringStatus,
   })}
+  role="status"
+  aria-label={`Monitoring ${businessReport?.monitoringStatus ? 'active' : 'inactive'}`}
 >
   &nbsp;
 </span>
services/workflows-service/src/business-report/merchant-monitoring-client.ts (1)

279-292: Consider adding date format validation.

While the implementation is good, consider validating the date format to prevent potential issues.

 public async getMetrics({
   customerId,
   from,
   to,
 }: {
   customerId: string;
-  from?: string;
-  to?: string;
+  from?: string & { _brand?: 'ISO8601' };
+  to?: string & { _brand?: 'ISO8601' };
 }) {
+  if (from && !from.match(/^\d{4}-\d{2}-\d{2}$/)) {
+    throw new Error('Invalid from date format. Expected YYYY-MM-DD');
+  }
+  if (to && !to.match(/^\d{4}-\d{2}-\d{2}$/)) {
+    throw new Error('Invalid to date format. Expected YYYY-MM-DD');
+  }
   const response = await this.axios.get('merchants/analysis/metrics', {
services/workflows-service/src/workflow/cron/ongoing-monitoring.cron.ts (1)

73-82: Enhance type safety for metadata access.

While the refactoring improves readability, consider adding type safety for the metadata structure.

+interface BusinessMetadata {
+  featureConfig?: {
+    [key: string]: {
+      enabled?: boolean;
+    };
+  };
+}

 const isOngoingEnabledForBusiness =
-  business.metadata?.featureConfig?.[this.processFeatureName]?.enabled;
+  (business.metadata as BusinessMetadata | undefined)?.featureConfig?.[this.processFeatureName]?.enabled;
apps/backoffice-v2/src/pages/MerchantMonitoring/components/MerchantMonitoringTable/columns.tsx (2)

98-139: Consider adding ARIA labels for better accessibility.

The column accessor is well-implemented with clear visual indicators and helpful tooltips. However, consider adding ARIA labels to improve accessibility.

Apply this diff to add ARIA labels:

-            <CheckCircle
+            <CheckCircle
+              aria-label="Active monitoring"
               size={18}
               className={`stroke-background`}
               containerProps={{
                 className: 'me-3 bg-success mt-px',
               }}
             />
-            <IndicatorCircle
+            <IndicatorCircle
+              aria-label="Inactive monitoring"
               size={18}
               className={`stroke-transparent`}
               containerProps={{
                 className: 'bg-slate-500/20',
               }}
             />

149-158: Consider adding ARIA labels and tooltip for better accessibility and UX.

The column accessor is well-implemented with clear visual indicators. However, consider adding ARIA labels and tooltips to improve accessibility and user experience.

Apply this diff to add ARIA labels and tooltips:

+import { Tooltip, TooltipContent, TooltipTrigger } from '@ballerine/ui';

 columnHelper.accessor('isAlert', {
   cell: ({ getValue }) => {
     return getValue() ? (
-      <WarningFilledSvg className={`d-6`} />
+      <Tooltip>
+        <TooltipTrigger>
+          <WarningFilledSvg className={`d-6`} aria-label="Alert detected" />
+        </TooltipTrigger>
+        <TooltipContent>Alert detected for this merchant</TooltipContent>
+      </Tooltip>
     ) : (
-      <Minus className={`text-[#D9D9D9] d-6`} />
+      <Tooltip>
+        <TooltipTrigger>
+          <Minus className={`text-[#D9D9D9] d-6`} aria-label="No alerts" />
+        </TooltipTrigger>
+        <TooltipContent>No alerts detected for this merchant</TooltipContent>
+      </Tooltip>
     );
   },
   header: 'Alert',
 }),
apps/backoffice-v2/src/pages/MerchantMonitoring/MerchantMonitoring.page.tsx (1)

205-214: Consider adding ARIA live region for dynamic content.

The badge component is well-implemented with clear styling and conditional rendering. However, consider adding an ARIA live region to announce updates to screen readers.

Apply this diff to add ARIA live region:

-      <div>
+      <div role="status" aria-live="polite">
         {!isLoadingBusinessReports && (
           <Badge
             variant="secondary"
             className="rounded-full px-3 py-1 text-sm font-semibold text-gray-700"
           >
             {totalItems} results
           </Badge>
         )}
       </div>
services/workflows-service/src/business/business.controller.external.ts (1)

136-190: Add error handling and input validation.

The method is well-implemented with proper transaction handling and safe JSON merging. However, consider adding error handling and input validation.

Apply this diff to add error handling and input validation:

 @common.Patch('/:id/monitoring/:state')
 @swagger.ApiForbiddenResponse()
 @swagger.ApiOkResponse({ type: BusinessDto })
 @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
 async updateOngoingMonitoringState(
   @common.Param('id') businessId: string,
   @common.Param('state') state: 'on' | 'off',
   @CurrentProject() currentProjectId: TProjectId,
 ) {
+  if (!businessId) {
+    throw new common.BadRequestException('Business ID is required');
+  }
+
+  try {
     const business = await this.businessService.getById(
       businessId,
       { select: { metadata: true } },
       [currentProjectId],
     );
+
+    if (!business) {
+      throw new errors.NotFoundException(`No business was found for id "${businessId}"`);
+    }

     const metadata = business?.metadata as {
       featureConfig?: TCustomerWithFeatures['features'];
     };

     const enabled = state === 'on';

     const updatedMetadata = !metadata
       ? {
           featureConfig: {
             [FEATURE_LIST.ONGOING_MERCHANT_REPORT]: {
               enabled,
             },
           },
         }
       : {
           ...metadata,
           featureConfig: {
             ...metadata.featureConfig,
             [FEATURE_LIST.ONGOING_MERCHANT_REPORT]: {
               ...metadata.featureConfig?.[FEATURE_LIST.ONGOING_MERCHANT_REPORT],
               enabled,
             },
           },
         };

     await this.prismaService.$transaction(async transaction => {
       const stringifiedMetadata = JSON.stringify(updatedMetadata);

       await transaction.$executeRaw`
         UPDATE "Business"
         SET "metadata" = jsonb_deep_merge_with_options(
           COALESCE("metadata", '{}'::jsonb),
           ${stringifiedMetadata}::jsonb,
           ${ARRAY_MERGE_OPTION.BY_INDEX}
         )
         WHERE "id" = ${businessId}
           AND "projectId" = ${currentProjectId};
       `;
     });
+
+    return { success: true };
+  } catch (error) {
+    if (error instanceof errors.NotFoundException) {
+      throw error;
+    }
+
+    throw new common.InternalServerErrorException(
+      'Failed to update ongoing monitoring state',
+    );
+  }
 }
apps/backoffice-v2/src/pages/Statistics/components/PortfolioRiskStatistics/hooks/usePortfolioRiskStatisticsLogic/usePortfolioRiskStatisticsLogic.tsx (1)

28-28: Consider performance implications of increased list size.

Increasing the list from 5 to 10 items could impact rendering performance with large datasets. Consider implementing:

  1. Virtualization for large lists
  2. Pagination controls
  3. Lazy loading mechanism
apps/backoffice-v2/public/locales/en/toast.json (1)

93-96: Consider adding support for dynamic content.

The success/error messages could benefit from placeholder support (like {{merchantName}}) to provide more context-specific feedback.

Example enhancement:

-    "success": "Merchant monitoring has been turned on successfully.",
+    "success": "Merchant monitoring for {{merchantName}} has been turned on successfully.",
🛑 Comments failed to post (8)
services/workflows-service/src/business-report/business-report.controller.external.ts (2)

41-46: ⚠️ Potential issue

Duplicate Import of 'BusinessReportMetricsDto'

The BusinessReportMetricsDto is imported twice from different paths:

  • Line 41: import { BusinessReportMetricsDto } from '@/business-report/dtos/business-report-metrics-dto';
  • Line 46: import { BusinessReportMetricsDto } from './dtos/business-report-metrics-dto';

This redeclaration can lead to conflicts and confusion. Please remove one of the imports to resolve this issue.

Apply this diff to fix the problem:

- import { BusinessReportMetricsDto } from './dtos/business-report-metrics-dto';
📝 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.

import { BusinessReportMetricsDto } from '@/business-report/dtos/business-report-metrics-dto';
import {
  BusinessReportMetricsRequestQueryDto,
  BusinessReportsMetricsQuerySchema,
} from '@/business-report/dtos/business-report-metrics.dto';
🧰 Tools
🪛 Biome (1.9.4)

[error] 46-46: Shouldn't redeclare 'BusinessReportMetricsDto'. Consider to delete it or rename it.

'BusinessReportMetricsDto' is defined here:

(lint/suspicious/noRedeclare)


163-169: 💡 Codebase verification

Add Date Format Validation and Parsing to Metrics Query Parameters

The current validation only ensures that from and to are strings, without validating the date format or parsing them. This could lead to runtime errors or incorrect metrics. Consider:

  • Adding date format validation using Zod's datetime() or class validator's @IsISO8601()
  • Ensuring 'from' date is not after 'to' date
  • Parsing strings into Date objects before passing to merchantMonitoringClient
🔗 Analysis chain

Ensure Proper Date Validation and Parsing for 'from' and 'to' Parameters

In the getMetrics method, the from and to query parameters are accepted as optional strings:

@Query() { from, to }: BusinessReportMetricsRequestQueryDto,

Ensure that these date strings are properly validated and parsed into date objects before being used in the merchantMonitoringClient.getMetrics call. Invalid or incorrectly formatted dates might lead to errors or incorrect metrics retrieval.

🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Find the DTO definition
ast-grep --pattern 'class BusinessReportMetricsRequestQueryDto {
  $$$
}'

# Also search for any imports or usage of validation decorators
rg "BusinessReportMetricsRequestQueryDto" -B 2 -A 10

Length of output: 5940


Script:

#!/bin/bash
# Find the Zod schema definition
rg "BusinessReportsMetricsQuerySchema" -B 2 -A 10

# Look for merchantMonitoringClient implementation
ast-grep --pattern 'class $_ implements MerchantMonitoringClient {
  $$$
  getMetrics($_) {
    $$$
  }
  $$$
}'

# Also search for any interface definition
ast-grep --pattern 'interface MerchantMonitoringClient {
  $$$
}'

Length of output: 4191

apps/backoffice-v2/src/pages/MerchantMonitoringBusinessReport/mutations/useTurnMonitoringOnMutation/useTurnMonitoringOnMutation.tsx (1)

24-24: 🛠️ Refactor suggestion

Optimize query invalidation.

Using invalidateQueries() without specific query keys will invalidate all queries in the cache, potentially causing unnecessary re-fetches across the application.

Consider targeting specific queries:

-      void queryClient.invalidateQueries();
+      void queryClient.invalidateQueries({ queryKey: ['merchantMonitoring', merchantId] });

Committable suggestion skipped: line range outside the PR's diff.

apps/backoffice-v2/src/pages/MerchantMonitoringBusinessReport/mutations/useTurnMonitoringOffMutation/useTurnMonitoringOffMutation.tsx (1)

9-44: 🛠️ Refactor suggestion

Consider consolidating duplicate mutation logic.

This hook largely duplicates the logic from useTurnMonitoringOnMutation. Consider creating a shared factory function to reduce duplication:

const createMonitoringMutation = (state: 'on' | 'off') => 
  ({ onSuccess }: { onSuccess?: <TData>(data: TData) => void }) => {
    const queryClient = useQueryClient();
    
    return useMutation({
      mutationFn: (merchantId: string) => 
        turnOngoingMonitoring({ merchantId, state }),
      onSuccess: data => {
        void queryClient.invalidateQueries({ 
          queryKey: ['merchantMonitoring', merchantId] 
        });
        toast.success(t(`toast:business_monitoring_${state}.success`));
        onSuccess?.(data);
      },
      onError: (error: unknown) => {
        if (error instanceof HttpError && error.code === 400) {
          toast.error(error.message);
          return;
        }
        toast.error(t(`toast:business_monitoring_${state}.error`, {
          errorMessage: isObject(error) && 'message' in error 
            ? error.message 
            : error,
        }));
      },
    });
  };

export const useTurnMonitoringOnMutation = createMonitoringMutation('on');
export const useTurnMonitoringOffMutation = createMonitoringMutation('off');
apps/backoffice-v2/src/domains/business-reports/hooks/queries/useBusinessReportMetricsQuery/useBusinessReportMetricsQuery.ts (1)

27-29: 🛠️ Refactor suggestion

Consider handling undefined date parameters in URL construction.

The URL construction might include 'undefined' as string values when from or to parameters are not provided.

Consider this safer approach:

-    endpoint: `../external/business-reports/metrics?from=${from}&to=${to}`,
+    endpoint: `../external/business-reports/metrics${
+      from || to ? `?${[
+        from && `from=${from}`,
+        to && `to=${to}`,
+      ].filter(Boolean).join('&')}` : ''
+    }`,
📝 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.

export const fetchBusinessReportMetrics = async ({ from, to }: { from?: string; to?: string }) => {
  const [businessReportMetrics, error] = await apiClient({
    endpoint: `../external/business-reports/metrics${
      from || to ? `?${[
        from && `from=${from}`,
        to && `to=${to}`,
      ].filter(Boolean).join('&')}` : ''
    }`,
apps/backoffice-v2/src/pages/Statistics/components/PortfolioAnalytics/PortfolioAnalytics.tsx (1)

35-37: 🛠️ Refactor suggestion

Add loading and error states for metrics.

Consider adding loading states and error handling for when the metrics are undefined or loading.

            <div className="text-2xl font-bold">
-              {addedMerchantsCount > 0 ? `+${addedMerchantsCount}` : `0`}
+              {addedMerchantsCount === undefined ? '-' : 
+                (addedMerchantsCount > 0 ? `+${addedMerchantsCount}` : `0`)}
            </div>

Also applies to: 47-49

apps/backoffice-v2/src/pages/Statistics/components/MonthPicker/MonthPicker.tsx (1)

22-29: 🛠️ Refactor suggestion

Add error handling for date manipulation.

The handleMonthSelect function should handle potential invalid dates and provide feedback to the user.

   const handleMonthSelect = (monthIndex: number) => {
+    try {
       const newDate = dayjs(date).year(currentYear).month(monthIndex);
 
       if (newDate.isSame(today, 'month') || newDate.isBefore(today, 'month')) {
         setDate(newDate.toDate());
         setOpen(false);
       }
+    } catch (error) {
+      console.error('Error selecting month:', error);
+      // Consider adding user feedback here
+    }
   };
📝 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.

  const handleMonthSelect = (monthIndex: number) => {
    try {
      const newDate = dayjs(date).year(currentYear).month(monthIndex);

      if (newDate.isSame(today, 'month') || newDate.isBefore(today, 'month')) {
        setDate(newDate.toDate());
        setOpen(false);
      }
    } catch (error) {
      console.error('Error selecting month:', error);
      // Consider adding user feedback here
    }
  };
apps/backoffice-v2/src/pages/MerchantMonitoring/components/MerchantMonitoringTable/columns.tsx (1)

182-200: 💡 Codebase verification

Remove the commented-out merchantId column accessor

The merchantId column has been replaced by the 'id' column (Report ID) which uses the same implementation pattern. The commented code can be safely removed to improve code maintainability.

🔗 Analysis chain

Verify if the commented-out code should be removed.

The merchantId column accessor is commented out but contains a complete implementation. If this code is no longer needed, consider removing it to maintain code cleanliness.

Run the following script to verify if the merchantId column is used elsewhere:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for references to the merchantId column.

# Test: Search for merchantId column usage
rg -A 5 'merchantId.*column'

Length of output: 30


Script:

#!/bin/bash
# Search for merchantId usage in the table component and column definitions
echo "=== Searching for merchantId in the table component ==="
rg -l "merchantId" "apps/backoffice-v2/src/pages/MerchantMonitoring/"

echo -e "\n=== Checking column definitions pattern ==="
ast-grep --pattern 'columnHelper.accessor($_, {
  $$$
})'  "apps/backoffice-v2/src/pages/MerchantMonitoring/components/MerchantMonitoringTable/columns.tsx"

echo -e "\n=== Looking for any merchantId references ==="
rg "merchantId" "apps/backoffice-v2/src/pages/MerchantMonitoring/components/MerchantMonitoringTable/columns.tsx" -A 2 -B 2

Length of output: 22614

…sDto

- Eliminate unnecessary import to clean up the code
- Reduces clutter and potential confusion in the module

(your code is so tidy now, it could be a minimalist's dream home)
- Simplify monitoring mutation definitions
- Consolidate business fetching to reduce database calls

(Your database queries are so chatty, they could use a good night's sleep)
@tomer-shvadron tomer-shvadron merged commit 8b6eb3f into mm-ui-ux-hackathon-jan-2025 Jan 8, 2025
16 checks passed
@tomer-shvadron tomer-shvadron deleted the bal-2824 branch January 8, 2025 09:09
tomer-shvadron added a commit that referenced this pull request Jan 14, 2025
* Bal 3305 - improve UI messages for no indications detected (#2936)

* feat(ui): improve UI messages for no indications detected

- Provide more detailed messages for indications of website reputation
- Specify lack of issues in pricing and structural evaluation

(Your code comments speak less clearly than a cryptic crossword in a dark room)

* chore(deps): update @ballerine/ui to version 0.5.60

- Bump version of @ballerine/ui to 0.5.60 across multiple packages
- Update package.json and changelog for @ballerine/react-pdf-toolkit and kyb-app

(the dependencies are getting updated faster than my social life)

---------

Co-authored-by: Omri Levy <[email protected]>

* fix(report-tabs): hide violations for ads and social media tab (#2937)

- Update logic to return null for ad and social media violations

* feat(merchant-monitoring): display total items in results badge (#2938)

* feat(merchant-monitoring): display total items in results badge

- Add a badge to show total number of results
- Improve layout by adjusting heading structure

(Your layout is so crowded, it could use a personal space policy)

* fix(merchantMonitoring): format totalItems for improved readability

- Update totalItems to format with Intl.NumberFormat
- Enhance the display of item counts for user experience

(your number formatting was so plain, it looked like a binary tree without leaves)

---------

Co-authored-by: Omri Levy <[email protected]>

* refactor(backoffice-v2): changed home statistics (#2935)

* feat: monthly filter on statistics page and additional merchant related data (BAL-3302, BAL-3303) (#2940)

* feat: monthly filter on statistics page and additional merchant related data

* fix: revert conditional statement

* fix: rewrite month picker to dayjs

* fix: CodeRabbit comments

* fix: minor code style correction

* refactor(statistics): simplify date transformation logic

- Make the 'from' field optional in the statistics search schema
- Clean up date transformation for better readability

(your code's so tangled, it could be the plot of a soap opera)

* ongoing monitoring turning on and off (#2941)

* feat(monitoring): implement business monitoring feature

- Add success and error messages for turning monitoring on/off
- Update API endpoints to manage ongoing monitoring status
- Integrate tooltip UI for monitoring status display

(Your code is so reactive that I'm surprised it doesn't require a safe word)

* chore(business-report): remove unused import for BusinessReportMetricsDto

- Eliminate unnecessary import to clean up the code
- Reduces clutter and potential confusion in the module

(your code is so tidy now, it could be a minimalist's dream home)

* fix(report): optimize business report fetching logic

- Simplify monitoring mutation definitions
- Consolidate business fetching to reduce database calls

(Your database queries are so chatty, they could use a good night's sleep)

* feat(ui): integrate ContentTooltip for enhanced user guidance

- Implement ContentTooltip component across multiple report templates
- Update Providers to include TooltipProvider from Ballerine UI
- Refactor headings with tooltips for additional information

(your tooltips are so informative, they should come with a user manual)

* Added filter for isAlert (#2943)

* refactor(backoffice-v2): changed home statistics

* feat(backoffice-v3): added filter for isAlert

* refactor(backoffice-v2): updated alert filter copy

* refactor(ui): simplify tooltip imports and update section titles

- Consolidate tooltip component imports from '@ballerine/ui'
- Change section titles from "Ads and Social Media" to "Social Media"

(With these changes, we're one step closer to rebranding you as a minimalism guru)

* fix: portfolio analytics design (#2945)

* Alerts graph (#2946)

* refactor(backoffice-v2): changed home statistics

* feat(backoffice-v3): added filter for isAlert

* refactor(backoffice-v2): updated alert filter copy

* feat(backoffice-v2): added alerts graph to home page

* refactor(backoffice-v2): now using dayjs for last 30 days date

* refactor(backoffice-v2): added from and to to alerts count

* feat(chart): introduce ChartContainer and tooltip components

- Add ChartContainer component for chart rendering
- Implement ChartTooltip and ChartTooltipContent components
- Enhance the WebsiteCredibility component to use the new Chart components

(your JSX structure is more nested than a Russian doll collection)

* fix(WebsiteCredibility): improve trend calculation readability

- Refactor conditional return for better clarity
- Enhance code structure for maintainability

(your code's readability is like a secret menu, good luck figuring it out)

* Default filter for merchant reports (#2947)

* feat(backoffice-v2): added default filter for merchant reports view

* fix(backoffice-v2): now clear all clears isAlert filter

* feat(auth): update user validation schemas (#2954)

- Remove registrationDate from AuthenticatedUserSchema
- Update isAlert field in BusinessReportSchema to be optional
- Add BusinessReportsCountSchema for report counting functionality

(Your schema changes are so dramatic, they should come with a Netflix subscription)

* refactor(components): simplify JSX structure in MerchantMonitoringTable

- Merge nested span into TextWithNAFallback for better clarity
- Remove unused import of CardTitle in WebsiteCredibility component

(your code's like a good magician—just when I think I see the trick, it disappears)

---------

Co-authored-by: Shane <[email protected]>
Co-authored-by: Omri Levy <[email protected]>
Co-authored-by: Sasha <[email protected]>
r4zendev pushed a commit that referenced this pull request Jan 14, 2025
* feat(monitoring): implement business monitoring feature

- Add success and error messages for turning monitoring on/off
- Update API endpoints to manage ongoing monitoring status
- Integrate tooltip UI for monitoring status display

(Your code is so reactive that I'm surprised it doesn't require a safe word)

* chore(business-report): remove unused import for BusinessReportMetricsDto

- Eliminate unnecessary import to clean up the code
- Reduces clutter and potential confusion in the module

(your code is so tidy now, it could be a minimalist's dream home)

* fix(report): optimize business report fetching logic

- Simplify monitoring mutation definitions
- Consolidate business fetching to reduce database calls

(Your database queries are so chatty, they could use a good night's sleep)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants