import type { IVChartOption } from '@visactor/vchart';
import type { TikTokVideoData } from '../index';
import { TIKTOK_COLORS } from '../index';
/**
* Create a line chart spec for views over time trend
*/
export function createLineChartSpec(data: TikTokVideoData[]): IVChartOption {
// Sort data by date
const sortedData = [...data].sort((a, b) =>
new Date(a.datePublished).getTime() - new Date(b.datePublished).getTime()
);
// Prepare data for line chart
const chartData = sortedData.map(item => ({
date: new Date(item.datePublished).toLocaleDateString('en-US', {
month: 'short',
day: 'numeric'
}),
views: item.views,
likes: item.likes,
comments: item.comments,
shares: item.shares,
timestamp: new Date(item.datePublished).getTime()
}));
return {
type: 'line',
data: {
values: chartData
},
title: {
visible: true,
text: 'Views Over Time',
textStyle: {
fontSize: 20,
fontWeight: 'bold'
}
},
xField: 'date',
yField: 'views',
seriesField: 'type',
point: {
visible: true,
style: {
size: 6,
fill: TIKTOK_COLORS.primary,
stroke: '#fff',
lineWidth: 2
}
},
line: {
style: {
stroke: TIKTOK_COLORS.primary,
lineWidth: 3,
lineDash: [0]
}
},
axes: [
{
orient: 'left',
title: {
visible: true,
text: 'Views',
style: {
fontSize: 14,
fontWeight: 'bold'
}
},
label: {
formatMethod: (val: number) => {
if (val >= 1000000) return (val / 1000000).toFixed(1) + 'M';
if (val >= 1000) return (val / 1000).toFixed(1) + 'K';
return val.toString();
}
},
grid: {
visible: true,
style: {
lineDash: [4, 4],
stroke: '#e8e8e8'
}
}
},
{
orient: 'bottom',
title: {
visible: true,
text: 'Date Published',
style: {
fontSize: 14,
fontWeight: 'bold'
}
},
label: {
autoRotate: true,
autoRotateAngle: [0, 45],
style: {
fontSize: 12
}
}
}
],
tooltip: {
visible: true,
mark: {
content: [
{
key: 'date',
value: (datum: any) => datum.date
},
{
key: 'views',
value: (datum: any) => datum.views.toLocaleString()
}
]
}
},
crosshair: {
xField: {
visible: true,
line: {
type: 'line',
style: {
stroke: TIKTOK_COLORS.primary,
lineWidth: 1,
opacity: 0.3
}
}
}
},
hover: {
enable: true
},
animation: {
appear: {
duration: 1000,
easing: 'cubicOut'
}
}
};
}