UNPKG

@pagamio/frontend-commons-lib

Version:

Pagamio library for Frontend reusable components like the form engine and table container

181 lines (180 loc) 7.57 kB
import dayjs from 'dayjs'; import { formatPrice } from '../../helpers'; const createTooltipContainer = () => ` <div style="margin-top: 5px; border-top: 1px solid #eee; padding-top: 5px;"> `; const isDateString = (value) => { // Check if the string is a valid date format return dayjs(value).isValid() && !Number.isNaN(Date.parse(value)); }; const formatDisplayName = (name) => { if (isDateString(name)) { return dayjs(name).format('MMM DD HH:mm'); } return name; }; const formatTooltipValue = (value, format, currency, displaySymbol) => { if (format === 'number') { return value.toLocaleString(); } const numericValue = Number(value); return currency ? formatPrice(numericValue, currency, 2, undefined, displaySymbol) : formatPrice(numericValue); }; const createTooltipRow = (label, value, suffix = '', format = 'number', currency, displaySymbol) => { return ` <div style="font-size: 12px; color: #666; margin-bottom: 3px;"> <span style="font-weight: 500;">${label}:</span> ${formatTooltipValue(value, format, currency, displaySymbol)}${suffix} </div> `; }; export const processTooltipFields = (tooltipAdditionalFields) => { return tooltipAdditionalFields.map((field) => { if (typeof field === 'string') { return { toolTipkey: field, valueKey: field, nameKey: field, label: field.replace(/([A-Z])/g, ' $1').trim(), suffix: '', format: 'number', formatter: (value, currency) => { if (typeof value === 'number') { return value.toLocaleString(); } return String(value); }, }; } return { toolTipkey: field.toolTipkey, valueKey: field.valueKey, nameKey: field.nameKey, label: field.label ?? field.toolTipkey.replace(/([A-Z])/g, ' $1').trim(), suffix: field.suffix ?? '', format: field.format ?? 'number', formatter: field.formatter ?? ((value, currency, displaySymbol) => { if (field.format === 'currency') { return formatPrice(Number(value), currency, 2, undefined, displaySymbol); } if (typeof value === 'number') { return value.toLocaleString(); } return String(value); }), }; }); }; const processAdditionalFields = (data, processedTooltipFields, currency, displaySymbol) => { let content = createTooltipContainer(); processedTooltipFields.forEach((field) => { if (data[field.toolTipkey] !== undefined) { const rawValue = data[field.toolTipkey]; if (field.formatter) { // If there's a custom formatter const formattedValue = field.formatter(rawValue, currency, displaySymbol); content += ` <div style="font-size: 12px; color: #666; margin-bottom: 3px;"> <span style="font-weight: 500;">${field.label}:</span> ${formattedValue}${field.suffix} </div> `; } else { // No custom formatter, let createTooltipRow handle it content += createTooltipRow(field.label, rawValue, field.suffix, field.format, currency, displaySymbol); } } }); return content + '</div>'; }; const processLineGraphData = (date) => { return createTooltipContainer() + createTooltipRow('Date', date) + '</div>'; }; const processMetricData = (processedTooltipFields, metricData, seriesValue, name, currency, displaySymbol) => { let content = ''; processedTooltipFields.forEach((field) => { const filteredValue = metricData.find((item) => item[field.valueKey] === seriesValue && item[field.nameKey] === name); if (filteredValue) { if (!content) { content = createTooltipContainer(); } const rawValue = filteredValue[field.toolTipkey]; if (field.formatter) { // If there's a custom formatter, const formattedValue = field.formatter(rawValue, currency, displaySymbol); content += ` <div style="font-size: 12px; color: #666; margin-bottom: 3px;"> <span style="font-weight: 500;">${field.label}:</span> ${formattedValue}${field.suffix} </div> `; } else { // No custom formatter, let createTooltipRow handle it content += createTooltipRow(field.label, rawValue, field.suffix, field.format, currency, displaySymbol); } } }); return content ? content + '</div>' : ''; }; export const createTooltipFormatter = (format, tooltipTitle, tooltipUnit, processedTooltipFields, metricData, currency, displaySymbol) => { return (params) => { let seriesColor = '#5470c6'; let seriesValue = 0; let isLineGraph = false; let date = ''; const { name, value, color, data, seriesName } = Array.isArray(params) ? params[0] : params; if (typeof color === 'string') { seriesColor = color; } else if (color?.colorStops?.[0]?.color) { seriesColor = color.colorStops[0].color; } if (Array.isArray(value)) { seriesValue = value[1]; date = value[0]; isLineGraph = true; } else { seriesValue = value; } // Format the main value let mainValueFormatted; if (format === 'number') { mainValueFormatted = `${seriesValue.toLocaleString()} ${tooltipUnit}`; } else if (displaySymbol) { // Use display symbol with explicit currency fallback const currencyToUse = currency || 'ZAR'; mainValueFormatted = formatPrice(seriesValue, currencyToUse, 2, undefined, displaySymbol); } else if (currency) { mainValueFormatted = formatPrice(seriesValue, currency); } else { mainValueFormatted = formatPrice(seriesValue); } let tooltipContent = ` <div> <div style="font-size: 14px; font-weight: 500; margin-bottom: 8px;"><b>${tooltipTitle}</b></div> <div style="display: flex; align-items: center; margin-bottom: 5px;"> <span style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background-color: ${seriesColor}; margin-right: 8px;"></span> <span style="font-weight: 500;">${formatDisplayName(name === '' ? seriesName : name)}:</span> <span style="margin-left: 5px;">${mainValueFormatted}</span> </div> `; // Add additional fields if available if (processedTooltipFields.length > 0) { const hasAdditionalData = processedTooltipFields.some((field) => data[field.toolTipkey] !== undefined); if (hasAdditionalData) { tooltipContent += processAdditionalFields(data, processedTooltipFields, currency, displaySymbol); } else { tooltipContent += isLineGraph ? processLineGraphData(date) : processMetricData(processedTooltipFields, metricData, seriesValue, name, currency, displaySymbol); } } tooltipContent += '</div>'; return tooltipContent; }; };