Polish social milestone chart curves
This commit is contained in:
@@ -7,6 +7,7 @@ import { Button } from '@/components/ui/Button';
|
||||
import { useCsrf } from '@/hooks/useCsrf';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { showToast } from '@/components/ui/Toast';
|
||||
import { roundedChartPath } from '@/lib/rounded-chart-path';
|
||||
|
||||
type Channel = 'x' | 'instagram';
|
||||
type Card = { language: 'en' | 'de'; qrTitle: string; label: string; title: string; totalScans?: number; totalUniqueScans: number; milestoneThreshold: number; trend: { points: Array<{ at: string; total: number }>; startLabel: string; endLabel: string; target: number; ceiling: number } | null };
|
||||
@@ -24,20 +25,21 @@ function Trend({ trend, locale }: { trend: NonNullable<Card['trend']>; locale: '
|
||||
: Array.from({ length: 5 }, (_, index) => trend.target * (index + 1) / 4);
|
||||
const first = new Date(trend.points[0].at).getTime();
|
||||
const last = Math.max(new Date(trend.points[trend.points.length - 1].at).getTime(), first + 1);
|
||||
const points = trend.points.map(point => {
|
||||
const chartPoints = trend.points.map(point => {
|
||||
const x = 60 + ((new Date(point.at).getTime() - first) / (last - first)) * 410;
|
||||
const y = 142 - (point.total / ceiling) * 126;
|
||||
return `${x},${y}`;
|
||||
}).join(' ');
|
||||
const targetY = 142 - (trend.target / ceiling) * 126;
|
||||
return { x, y };
|
||||
});
|
||||
const path = roundedChartPath(chartPoints, 18);
|
||||
const endPoint = chartPoints[chartPoints.length - 1] || { x: 470, y: 142 };
|
||||
const number = new Intl.NumberFormat(locale === 'de' ? 'de-DE' : 'en-US', { maximumFractionDigits: 2 });
|
||||
return <svg viewBox="0 0 480 184" className="w-full" role="img" aria-label="Cumulative unique scan trend">
|
||||
{ticks.map(tick => {
|
||||
const y = 142 - (tick / ceiling) * 126;
|
||||
return <g key={tick}><text x="48" y={y + 4} textAnchor="end" fontSize="11" fontWeight={tick === trend.target ? 700 : 500} fill={tick === trend.target ? '#0256ff' : '#64748b'}>{number.format(tick)}</text><line x1="60" x2="470" y1={y} y2={y} stroke={tick === trend.target ? '#bfdbfe' : '#e2e8f0'} strokeWidth={tick === trend.target ? 1.6 : 1} /></g>;
|
||||
})}
|
||||
<polyline points={points} fill="none" stroke="#0256ff" strokeWidth="3.5" strokeLinejoin="round" strokeLinecap="round" />
|
||||
<circle cx="470" cy={targetY} r="4.5" fill="#ffffff" stroke="#0256ff" strokeWidth="3" />
|
||||
<path d={path} fill="none" stroke="#0256ff" strokeWidth="3.5" strokeLinejoin="round" strokeLinecap="round" />
|
||||
<circle cx={endPoint.x} cy={endPoint.y} r="4.5" fill="#ffffff" stroke="#0256ff" strokeWidth="3" />
|
||||
<text x="60" y="176" fontSize="11" fontWeight="600" fill="#45617f">{trend.startLabel}</text>
|
||||
<text x="470" y="176" textAnchor="end" fontSize="11" fontWeight="600" fill="#45617f">{trend.endLabel}</text>
|
||||
</svg>;
|
||||
|
||||
Reference in New Issue
Block a user