Lead volume widget
ui/src/components/adminDashboard/widgets/LeadVolumeWidget
The main widget of the page is LeadVolumeWidget. Widget written with usage of LineChart component. Each line has its own linear gradient which is made with function createGradient
:
The widget also has a comparison mode, which can be activated by clicking on the switch. In comparison mode, we can compare two ranges for the selected businesses. When in comparison mode, the page's RangePicker will not function unless both ranges are selected in the LeadVolumeWidget. To compare 2 ranges widget will send request for each range and then combine results in one array but with different styles. Code example:
In the LineChart component, we have specific logic that ensures the correct display of the tooltip, axis steps, and date formatting in the tooltip. Let's see how calculateOptimalStepSize
works:
For the optimal layout according to the design, the chart should have exactly 6 steps. To achieve this, we need to find the optimal step size. In the function, we have an array of available steps. To find the optimal size, we divide the maximum data value on the chart by the step size, and the result should be equal to or less than the target step size.
To create a custom tooltip, use the getOrCreateTooltip
function. If the tooltip element already exists, it will return it; if not, it will create the element with specified styles using vanilla JS methods. Code example:
externalTooltipHandlerComparison
externalTooltipHandlerComparison
The externalTooltipHandlerComparison
function is a custom tooltip handler that manages the display and formatting of an external tooltip element for a chart in comparison mode. It retrieves or creates a tooltip element, formats its contents, and styles it for visual clarity, particularly when comparing two data points or time periods.
Parameters
context: Contains information about the chart and the tooltip, including chart data, tooltip position, and tooltip content.
Function Overview
Retrieve Tooltip Element: Uses
getOrCreateTooltip(chart)
to fetch an existing tooltip element or create a new one if none exists.Tooltip Visibility:
Sets the tooltip’s opacity to
0
if there’s no tooltip data to display, effectively hiding it.If there is data, continues with formatting.
Tooltip Content Setup:
Extracts the
title
andbody
content from the tooltip.Titles are split and formatted with
dayjs
for dates, if applicable, and displayed with appropriate month formatting.Creates two title elements,
firstTitleWrapper
andsecondTitleWrapper
, representing the two comparison data points or time periods.
Tooltip Body Formatting:
The tooltip body content (
bodyLines
) is sorted alphabetically.For each line of content, a wrapper element is created and styled, displaying a colored span for visual distinction.
Alternates between adding text to the left or right wrapper to organize comparison values.
Content Wrapping:
Clears any existing content in
tableRoot
to ensure fresh data is displayed.Appends newly created elements (
leftWrapper
andrightWrapper
) to thetableRoot
.
Tooltip Positioning:
Positions the tooltip relative to the chart's
offsetLeft
andoffsetTop
, ensuring it follows the tooltip caret's location accurately on the chart.
Styling Notes
The function uses classes (e.g., tooltip-title-wrapper
, tooltip-fit-content
, tooltip-text-wrapper
) for custom styling, ensuring that elements such as colored lines and text are properly formatted. The createSpan
helper function is used to apply colors from chartColors
.
Example Usage
This function is called automatically by the chart’s event system when a tooltip event is triggered, e.g., hovering over chart points in comparison mode.
Code example:
It is also fucntion for generating tooltip for default mode but it is almost same but with different layout for one dataset.
formatDateToNumber
formatDateToNumber
The formatDateToNumber
function formats date labels based on the input date granularity (month, day, or week) and chart data label length.
Parameters:
label
: A date string, either in "YYYY-MM" (month), "DD-MM-YYYY" (day), or "DD/MM" (week) format.
Function Logic:
Monthly Format (YYYY-MM):
For labels with a monthly format and up to 9 items, returns the month abbreviation (e.g., "May").
For over 9 labels, returns the quarter and year (e.g., "Q2/2024") based on the month. The label is stored in
quartalsLabels
to prevent duplicates.
Daily Format (DD-MM-YYYY):
Extracts and returns the day as a string (e.g., "19").
Default:
Returns the original label (e.g., for weekly formats).
This function optimizes labels for various chart views, ensuring a simplified display depending on the date range.
Example Usage
Pass that function as a callback to your scales.ticks
key in chartOptions
:
Plugin for drawing vertical line on mouse enter to any point
The provided plugin is a custom plugin for a Chart.js Line chart that draws a vertical dashed line across the chart whenever a tooltip is active.
Implementation
Location: This plugin is added to the
plugins
array of the<Line />
component.
Plugin Functionality
Lifecycle Method:
afterDraw
Executes after the chart is drawn, allowing for modifications to the canvas based on the current chart state.
Parameters
chart
: The chart instance, providing access to its properties and methods.
Logic
Check Active Tooltip:
If there is an active tooltip (i.e.,
chart.tooltip?._active?.length
), the plugin retrieves the x-coordinate of the active tooltip's element.
Draw Dashed Line:
It obtains the y-axis scale (
yAxis
) and the rendering context (ctx
) from the chart.The following drawing operations are performed:
Save Context: Saves the current canvas state.
Set Line Dash: Configures the line style to dashed with a pattern of 8 pixels on and 7 pixels off.
Begin Path: Starts a new path for drawing.
Move To: Moves the drawing cursor to the active tooltip's x-coordinate at the top of the y-axis.
Line To: Draws a line down to the bottom of the y-axis.
Set Line Width: Defines the line width to 1 pixel.
Set Stroke Style: Sets the stroke color to
primitiveColors.gray100
.Stroke: Renders the line onto the canvas.
Restore Context: Restores the previous canvas state.
Backend
getLeadsPerBusinessesPerDay
is responsible for getting datasets for LeadVolumeWidget.
The function will return different results based on the specified period:
For a period of less than 2 months: Labels will be daily dates, and the values will represent the leads created on those dates for each business.
For a period of more than 2 months and less than 4 months: Labels will be the starting days of the week (with the week beginning on Saturday) along with the month number, for example, 20/07. The values will represent the leads created during that week for each business.
For a period of more than 4 months: Labels will be the names of the months, and the values will represent the leads created during each month for each business.
(On the frontend, we also have a quarterly display that shows data by month but generates custom labels with quarters and years.)
The getLeadsPerBusinessesPerDay
function retrieves the number of leads created per business over a specified date range. It organizes the data for visualization in a chart format, accounting for various conditions such as time periods and chart modes.
Parameters
mode
(ChartMode): Determines the mode of the chart (e.g., analysis or comparison).startDate
(string): The start date of the period to analyze, formatted as a string.endDate
(string): The end date of the period to analyze, formatted as a string.businessIds
(number[]): An array of business IDs to filter the leads.teamId
(string): The ID of the team associated with the leads.
Returns
Promise<{ labels: string[], data: object, totalLeadsAmount: number, percentageChange: number }>
:labels
: An array of date labels.data
: An object containing the lead counts for each business by date.totalLeadsAmount
: The total number of leads generated in the specified period.percentageChange
: The percentage change in leads compared to the previous period.
Description
Date Validation:
The function checks if the provided start and end dates are valid. If not, it throws a
BadRequestException
.
Date Range Calculation:
It calculates the duration of the period in days and prepares for querying data for the current and previous periods.
Leads Query:
It retrieves leads data by joining the leads with businesses, grouping by business name and creation date, and counting the number of leads created.
Business Names Retrieval:
Fetches the names of the businesses corresponding to the provided IDs for later reference.
Data Structuring:
Organizes the leads data into a result object, formatted by business names and dates.
Final Data Processing:
Handles different scenarios based on the duration of the date range:
If the range is less than two months, it fills in any missing dates with lead counts of zero.
If the range is two months or longer, it groups data by week or month.
Comparison Mode Handling:
In comparison mode, it ensures that every business has a corresponding entry in the result, filling in zeros where necessary.
Previous Period Calculation:
Calls a helper function to calculate the total number of leads for the previous period.
Percentage Change Calculation:
Computes the percentage change in leads compared to the previous period, handling edge cases where the previous period's total may be zero.
Final Sorting:
Sorts the final result by business name for better readability.
Error Handling
Throws a
BadRequestException
for invalid date formats and can impose business count limits if uncommented.
This function is essential for generating lead analytics, enabling teams to visualize their performance and track changes over time.
If there is no data for a specific date, we should manually set the lead count for that date key; otherwise, it will not appear in the result array and will cause incorrect chart display. Additionally, we should always sort the dates to ensure they appear in the correct order, and at the end, sort by business name to maintain consistent colors and order for the same businesses.
If it is a call for comparison mode, there is one additional cycle that handles the case when there is no data for a business and fills the array with zeroes for correct display on the chart.
Last updated