96 lines
2.3 KiB
TypeScript
96 lines
2.3 KiB
TypeScript
import { useMemo } from "react";
|
|
import {
|
|
CartesianGrid,
|
|
Line,
|
|
LineChart,
|
|
ResponsiveContainer,
|
|
Tooltip,
|
|
XAxis,
|
|
YAxis,
|
|
} from "recharts";
|
|
import { formatCount } from "@/client/features/ai-search/platformLabels";
|
|
import type { BrandLookupResult } from "@/types/schemas/ai-search";
|
|
|
|
type Props = {
|
|
result: BrandLookupResult;
|
|
};
|
|
|
|
export function BrandLookupMentionTrendCard({ result }: Props) {
|
|
const chartData = useMemo(
|
|
() =>
|
|
result.monthlyVolume.map((entry) => ({
|
|
label: `${entry.year}-${String(entry.month).padStart(2, "0")}`,
|
|
volume: entry.volume ?? 0,
|
|
})),
|
|
[result.monthlyVolume],
|
|
);
|
|
|
|
if (chartData.length === 0) {
|
|
return (
|
|
<div className="flex h-56 items-center justify-center text-sm text-base-content/60">
|
|
Not enough historical data yet.
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="h-56">
|
|
<ResponsiveContainer width="100%" height="100%">
|
|
<LineChart
|
|
data={chartData}
|
|
margin={{ top: 12, right: 12, bottom: 4, left: 0 }}
|
|
>
|
|
<CartesianGrid
|
|
strokeDasharray="3 3"
|
|
stroke="currentColor"
|
|
opacity={0.12}
|
|
/>
|
|
<XAxis
|
|
dataKey="label"
|
|
tick={{ fontSize: 11, fill: "#888" }}
|
|
tickLine={false}
|
|
axisLine={false}
|
|
/>
|
|
<YAxis
|
|
tick={{ fontSize: 11, fill: "#888" }}
|
|
tickLine={false}
|
|
axisLine={false}
|
|
allowDecimals={false}
|
|
/>
|
|
<Tooltip
|
|
content={<MentionTooltip />}
|
|
cursor={{ stroke: "currentColor", strokeOpacity: 0.2 }}
|
|
/>
|
|
<Line
|
|
type="monotone"
|
|
dataKey="volume"
|
|
stroke="hsl(220 70% 50%)"
|
|
strokeWidth={2}
|
|
dot={false}
|
|
/>
|
|
</LineChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function MentionTooltip({
|
|
active,
|
|
payload,
|
|
label,
|
|
}: {
|
|
active?: boolean;
|
|
payload?: Array<{ value: number }>;
|
|
label?: string;
|
|
}) {
|
|
if (!active || !payload?.length) return null;
|
|
return (
|
|
<div className="rounded-md border border-base-300 bg-base-100 px-3 py-2 shadow-sm">
|
|
<p className="text-xs text-base-content/60">{label}</p>
|
|
<p className="text-sm font-medium tabular-nums">
|
|
{formatCount(payload[0].value)} mentions
|
|
</p>
|
|
</div>
|
|
);
|
|
}
|