more predictable mocks for line

This commit is contained in:
Nate Kelley 2025-04-14 15:43:05 -06:00
parent 05a4a631c8
commit 2c240698c8
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
3 changed files with 175 additions and 73 deletions

View File

@ -20,8 +20,7 @@ import {
BubbleController, BubbleController,
PieController, PieController,
ScatterController, ScatterController,
DoughnutController, DoughnutController
scales
} from 'chart.js'; } from 'chart.js';
import { ChartMountedPlugin } from './core/plugins'; import { ChartMountedPlugin } from './core/plugins';
import ChartDeferred from 'chartjs-plugin-deferred'; import ChartDeferred from 'chartjs-plugin-deferred';

View File

@ -26,7 +26,7 @@ export const Default: Story = {
y: ['revenue', 'profit', 'customers'], y: ['revenue', 'profit', 'customers'],
category: [] category: []
}, },
className: 'w-[800px] h-[400px]', className: 'resize overflow-auto min-w-[250px] h-[400px]',
columnLabelFormats: { columnLabelFormats: {
date: { date: {
columnType: 'date', columnType: 'date',
@ -128,12 +128,12 @@ export const MultiYearDate: Story = {
y: ['value'], y: ['value'],
category: [] category: []
}, },
className: 'w-[800px] h-[400px]', className: 'w-[800px] h-[400px] resize overflow-auto',
columnLabelFormats: { columnLabelFormats: {
date: { date: {
columnType: 'date', columnType: 'date',
style: 'date', style: 'date',
dateFormat: 'YYYY' // Show only year for multi-year view dateFormat: 'auto' // Show only year for multi-year view
} satisfies IColumnLabelFormat, } satisfies IColumnLabelFormat,
value: { value: {
columnType: 'number', columnType: 'number',
@ -177,7 +177,7 @@ export const MultipleYAxes: Story = {
date: { date: {
columnType: 'date', columnType: 'date',
style: 'date', style: 'date',
dateFormat: 'MMM YYYY' dateFormat: 'auto'
} satisfies IColumnLabelFormat, } satisfies IColumnLabelFormat,
revenue: { revenue: {
columnType: 'number', columnType: 'number',
@ -203,30 +203,74 @@ export const UnevenlySpacedDates: Story = {
args: { args: {
selectedChartType: ChartType.Line, selectedChartType: ChartType.Line,
data: [ data: [
{ date: new Date('2024-01-05'), value: 120 }, { date: new Date('2024-01-05').toISOString(), value: 120 },
{ date: new Date('2024-01-28'), value: 145 }, { date: new Date('2024-01-28').toISOString(), value: 145 },
{ date: new Date('2024-02-15'), value: 160 }, { date: new Date('2024-02-15').toISOString(), value: 160 },
{ date: new Date('2024-03-02'), value: 155 }, { date: new Date('2024-03-02').toISOString(), value: 155 },
{ date: new Date('2024-04-18'), value: 180 }, { date: new Date('2024-04-18').toISOString(), value: 180 },
{ date: new Date('2024-05-30'), value: 210 }, { date: new Date('2024-05-30').toISOString(), value: 210 },
{ date: new Date('2024-07-12'), value: 195 }, { date: new Date('2024-07-12').toISOString(), value: 195 },
{ date: new Date('2024-08-03'), value: 225 }, { date: new Date('2024-08-03').toISOString(), value: 225 },
{ date: new Date('2024-09-22'), value: 240 }, { date: new Date('2024-09-22').toISOString(), value: 240 },
{ date: new Date('2024-11-15'), value: 260 }, { date: new Date('2024-11-15').toISOString(), value: 260 },
{ date: new Date('2024-12-28'), value: 280 }, { date: new Date('2024-12-28').toISOString(), value: 280 },
{ date: new Date('2025-04-08'), value: 310 } { date: new Date('2025-04-08').toISOString(), value: 310 }
], ],
barAndLineAxis: { barAndLineAxis: {
x: ['date'], x: ['date'],
y: ['value'], y: ['value'],
category: [] category: []
}, },
className: 'w-[800px] h-[400px]', className: 'w-[800px] h-[400px]',
columnSettings: {
value: {
lineSymbolSize: 5
}
},
columnLabelFormats: { columnLabelFormats: {
date: { date: {
columnType: 'date', columnType: 'date',
style: 'date', style: 'date',
dateFormat: 'll' // Full date format to show uneven spacing clearly dateFormat: 'auto' // Full date format to show uneven spacing clearly
} satisfies IColumnLabelFormat,
value: {
columnType: 'number',
style: 'number',
minimumFractionDigits: 0,
maximumFractionDigits: 0
} satisfies IColumnLabelFormat
}
}
};
// Closely spaced dates
export const CloselySpacedDates: Story = {
args: {
selectedChartType: ChartType.Line,
data: [
{ date: new Date('2024-01-01').toISOString(), value: 120 },
{ date: new Date('2024-01-03').toISOString(), value: 145 },
{ date: new Date('2024-01-05').toISOString(), value: 160 },
{ date: new Date('2024-01-07').toISOString(), value: 155 },
{ date: new Date('2024-01-12').toISOString(), value: 180 }
],
barAndLineAxis: {
x: ['date'],
y: ['value'],
category: []
},
className: 'w-[800px] h-[400px] resize overflow-auto',
columnSettings: {
value: {
lineSymbolSize: 5
}
},
columnLabelFormats: {
date: {
columnType: 'date',
style: 'date',
dateFormat: 'll' // Full date format to show spacing clearly
} satisfies IColumnLabelFormat, } satisfies IColumnLabelFormat,
value: { value: {
columnType: 'number', columnType: 'number',
@ -243,18 +287,18 @@ export const WithCategory: Story = {
args: { args: {
selectedChartType: ChartType.Line, selectedChartType: ChartType.Line,
data: [ data: [
{ month: new Date('2024-01-01'), sales: 1200, region: 'North' }, { month: new Date('2024-01-01').toISOString(), sales: 1200, region: 'North' },
{ month: new Date('2024-02-01'), sales: 1400, region: 'North' }, { month: new Date('2024-02-01').toISOString(), sales: 1400, region: 'North' },
{ month: new Date('2024-03-01'), sales: 1600, region: 'North' }, { month: new Date('2024-03-01').toISOString(), sales: 1600, region: 'North' },
{ month: new Date('2024-01-01'), sales: 800, region: 'South' }, { month: new Date('2024-01-01').toISOString(), sales: 800, region: 'South' },
{ month: new Date('2024-02-01'), sales: 900, region: 'South' }, { month: new Date('2024-02-01').toISOString(), sales: 900, region: 'South' },
{ month: new Date('2024-03-01'), sales: 1100, region: 'South' }, { month: new Date('2024-03-01').toISOString(), sales: 1100, region: 'South' },
{ month: new Date('2024-01-01'), sales: 1500, region: 'East' }, { month: new Date('2024-01-01').toISOString(), sales: 1500, region: 'East' },
{ month: new Date('2024-02-01'), sales: 1700, region: 'East' }, { month: new Date('2024-02-01').toISOString(), sales: 1700, region: 'East' },
{ month: new Date('2024-03-01'), sales: 1900, region: 'East' }, { month: new Date('2024-03-01').toISOString(), sales: 1900, region: 'East' },
{ month: new Date('2024-01-01'), sales: 1000, region: 'West' }, { month: new Date('2024-01-01').toISOString(), sales: 1000, region: 'West' },
{ month: new Date('2024-02-01'), sales: 1300, region: 'West' }, { month: new Date('2024-02-01').toISOString(), sales: 1300, region: 'West' },
{ month: new Date('2024-03-01'), sales: 1500, region: 'West' } { month: new Date('2024-03-01').toISOString(), sales: 1500, region: 'West' }
], ],
barAndLineAxis: { barAndLineAxis: {
x: ['month'], x: ['month'],
@ -266,7 +310,7 @@ export const WithCategory: Story = {
month: { month: {
columnType: 'date', columnType: 'date',
style: 'date', style: 'date',
dateFormat: 'MMM YYYY' dateFormat: 'auto'
} satisfies IColumnLabelFormat, } satisfies IColumnLabelFormat,
sales: { sales: {
columnType: 'number', columnType: 'number',
@ -286,15 +330,60 @@ export const MultipleYAxesWithCategory: Story = {
args: { args: {
selectedChartType: ChartType.Line, selectedChartType: ChartType.Line,
data: [ data: [
{ date: new Date('2024-01-01'), revenue: 1200, satisfaction: 4.2, product: 'Hardware' }, {
{ date: new Date('2024-02-01'), revenue: 1400, satisfaction: 4.3, product: 'Hardware' }, date: new Date('2024-01-01').toISOString(),
{ date: new Date('2024-03-01'), revenue: 1600, satisfaction: 4.4, product: 'Hardware' }, revenue: 1200,
{ date: new Date('2024-01-01'), revenue: 800, satisfaction: 4.7, product: 'Software' }, satisfaction: 4.2,
{ date: new Date('2024-02-01'), revenue: 1000, satisfaction: 4.8, product: 'Software' }, product: 'Hardware'
{ date: new Date('2024-03-01'), revenue: 1200, satisfaction: 4.9, product: 'Software' }, },
{ date: new Date('2024-01-01'), revenue: 2000, satisfaction: 4.0, product: 'Services' }, {
{ date: new Date('2024-02-01'), revenue: 2200, satisfaction: 4.1, product: 'Services' }, date: new Date('2024-02-01').toISOString(),
{ date: new Date('2024-03-01'), revenue: 2400, satisfaction: 4.2, product: 'Services' } revenue: 1400,
satisfaction: 4.3,
product: 'Hardware'
},
{
date: new Date('2024-03-01').toISOString(),
revenue: 1600,
satisfaction: 4.4,
product: 'Hardware'
},
{
date: new Date('2024-01-01').toISOString(),
revenue: 800,
satisfaction: 4.7,
product: 'Software'
},
{
date: new Date('2024-02-01').toISOString(),
revenue: 1000,
satisfaction: 4.8,
product: 'Software'
},
{
date: new Date('2024-03-01').toISOString(),
revenue: 1200,
satisfaction: 4.9,
product: 'Software'
},
{
date: new Date('2024-01-01').toISOString(),
revenue: 2000,
satisfaction: 4.0,
product: 'Services'
},
{
date: new Date('2024-02-01').toISOString(),
revenue: 2200,
satisfaction: 4.1,
product: 'Services'
},
{
date: new Date('2024-03-01').toISOString(),
revenue: 2400,
satisfaction: 4.2,
product: 'Services'
}
], ],
barAndLineAxis: { barAndLineAxis: {
x: ['date'], x: ['date'],
@ -306,7 +395,7 @@ export const MultipleYAxesWithCategory: Story = {
date: { date: {
columnType: 'date', columnType: 'date',
style: 'date', style: 'date',
dateFormat: 'MMM YYYY' dateFormat: 'auto'
} satisfies IColumnLabelFormat, } satisfies IColumnLabelFormat,
revenue: { revenue: {
columnType: 'number', columnType: 'number',
@ -356,7 +445,7 @@ export const NumericMonthX: Story = {
month: { month: {
columnType: 'number', columnType: 'number',
style: 'date', style: 'date',
dateFormat: 'MMM', dateFormat: 'auto',
minimumFractionDigits: 0, minimumFractionDigits: 0,
maximumFractionDigits: 0 maximumFractionDigits: 0
} satisfies IColumnLabelFormat, } satisfies IColumnLabelFormat,
@ -389,7 +478,7 @@ export const PercentageStackedLineSingle: Story = {
date: { date: {
columnType: 'number', columnType: 'number',
style: 'date', style: 'date',
dateFormat: 'LLL', dateFormat: 'auto',
minimumFractionDigits: 0, minimumFractionDigits: 0,
maximumFractionDigits: 0 maximumFractionDigits: 0
} satisfies IColumnLabelFormat, } satisfies IColumnLabelFormat,

View File

@ -1,55 +1,69 @@
import { IDataResult } from '@/api/asset_interfaces/metric/interfaces'; import { IDataResult } from '@/api/asset_interfaces/metric/interfaces';
import { faker } from '@faker-js/faker'; import dayjs from 'dayjs';
// Helper to generate dates for time series // Helper to generate dates for time series
const generateDates = (count: number) => { const generateDates = (count: number) => {
const dates: Date[] = []; const dates: Date[] = [];
const startDate = new Date(); const startDate = dayjs('April 1, 2025').toDate();
startDate.setDate(startDate.getDate() - count);
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const date = new Date(startDate); const date = dayjs(startDate).add(i, 'day').toDate();
date.setDate(date.getDate() + i);
dates.push(date); dates.push(date);
} }
return dates; return dates;
}; };
// Line chart mock data // Helper to add controlled noise to values
const addNoise = (value: number, variabilityPercent: number = 10): number => {
const maxNoise = value * (variabilityPercent / 100);
const noise = Math.sin(value) * maxNoise; // Using sin for pseudo-random but predictable noise
return Math.round(value + noise);
};
// Line chart mock data with predictable growth patterns and controlled variability
export const generateLineChartData = (pointCount = 10): IDataResult => { export const generateLineChartData = (pointCount = 10): IDataResult => {
const dates = generateDates(pointCount); const dates = generateDates(pointCount);
return dates.map((date) => ({ return dates.map((date, index) => {
date: date.toISOString(), const baseRevenue = 1000 + index * 500;
revenue: faker.number.int({ min: 1000, max: 10000 }), const baseProfit = 100 + index * 200;
profit: faker.number.int({ min: 100, max: 5000 }), const baseCustomers = 50 + index * 25;
customers: faker.number.int({ min: 50, max: 500 })
})); return {
date: date.toISOString(),
revenue: addNoise(baseRevenue, 15), // 15% variability
profit: addNoise(baseProfit, 20), // 20% variability
customers: addNoise(baseCustomers, 10) // 10% variability
};
});
}; };
// Bar chart mock data // Bar chart mock data with consistent categories
export const generateBarChartData = (categoryCount = 6): IDataResult => { export const generateBarChartData = (categoryCount = 6): IDataResult => {
return Array.from({ length: categoryCount }, () => ({ const categories = ['Electronics', 'Clothing', 'Food', 'Books', 'Sports', 'Home', 'Beauty'];
category: faker.commerce.department(), return Array.from({ length: categoryCount }, (_, index) => ({
sales: faker.number.int({ min: 1000, max: 10000 }), category: categories[index % categories.length],
units: faker.number.int({ min: 50, max: 500 }), sales: 1000 + index * 1000, // Increases by 1000 each category
returns: faker.number.int({ min: 100, max: 500 }) units: 50 + index * 50, // Increases by 50 each category
returns: 100 + index * 25 // Increases by 25 each category
})); }));
}; };
// Pie chart mock data // Pie chart mock data with fixed segments
export const generatePieChartData = (segmentCount = 5): IDataResult => { export const generatePieChartData = (segmentCount = 5): IDataResult => {
return Array.from({ length: segmentCount }, () => ({ const segments = ['Product A', 'Product B', 'Product C', 'Product D', 'Product E'];
segment: faker.commerce.product(), return Array.from({ length: segmentCount }, (_, index) => ({
value: faker.number.int({ min: 100, max: 1000 }) segment: segments[index % segments.length],
value: 100 + index * 200 // Increases by 200 each segment
})); }));
}; };
// Scatter chart mock data // Scatter chart mock data with predictable patterns
export const generateScatterChartData = (pointCount = 30): IDataResult => { export const generateScatterChartData = (pointCount = 30): IDataResult => {
return Array.from({ length: pointCount }, () => ({ const categories = ['Electronics', 'Clothing', 'Home Goods'];
x: faker.number.float({ min: 0, max: 100, fractionDigits: 1 }), return Array.from({ length: pointCount }, (_, index) => ({
y: faker.number.float({ min: 0, max: 100, fractionDigits: 1 }), x: (index % 10) * 10, // Values from 0-90 in steps of 10
size: faker.number.int({ min: 10, max: 50 }), y: Math.floor(index / 10) * 10, // Creates a grid pattern
category: faker.helpers.arrayElement(['Electronics', 'Clothing', 'Home Goods']) size: 10 + (index % 5) * 10, // Sizes cycle between 10-50 in steps of 10
category: categories[index % categories.length]
})); }));
}; };