improvement: some files replaced, lots of them i shall say. AGENT.MD file created. some rules and skills added for cursor agent.

This commit is contained in:
2026-07-12 21:08:29 +03:30
parent 1cdf853d32
commit 0d3fb0a51d
86 changed files with 4758 additions and 4260 deletions

View File

@@ -0,0 +1,168 @@
'use client';
import type { CSSProperties } from 'react';
import { Cell, Pie, PieChart, ResponsiveContainer, Tooltip } from 'recharts';
import type { TodayChartBucket } from '@/types/today';
import { TodayChartFrame } from '@/components/ui/today/TodayChartFrame';
import {
chartRankColor,
TODAY_CHART_TOOLTIP_STYLE,
} from '@/components/today/chart-theme';
interface TodayDonutChartBaseProps {
data: TodayChartBucket[];
labelForCode: (code: string) => string;
colorForCode?: (code: string, index: number) => string;
swatchStyleForCode?: (code: string, index: number) => CSSProperties;
}
interface TodayDonutChartProps extends TodayDonutChartBaseProps {
variant?: 'donut' | 'pie';
/** Inline legend + chart row (legacy). Prefer TodayDonutChartLegend + sidePanelLayout. */
sideLegend?: boolean;
}
function useDonutChartModel({
data,
labelForCode,
colorForCode,
swatchStyleForCode,
}: TodayDonutChartBaseProps) {
const chartData = data.map((item) => ({
...item,
displayLabel: labelForCode(item.code),
}));
const resolveColor = (code: string, index: number) =>
colorForCode?.(code, index) ?? chartRankColor(index);
const resolveSwatchStyle = (code: string, index: number): CSSProperties =>
swatchStyleForCode?.(code, index) ?? {
backgroundColor: resolveColor(code, index),
borderColor: 'rgba(0, 0, 0, 0.18)',
};
return { chartData, resolveColor, resolveSwatchStyle };
}
export function TodayDonutChartLegend({
data,
labelForCode,
colorForCode,
swatchStyleForCode,
}: TodayDonutChartBaseProps) {
const { chartData, resolveSwatchStyle } = useDonutChartModel({
data,
labelForCode,
colorForCode,
swatchStyleForCode,
});
const rowClass = 'flex h-4 items-center text-xs leading-none';
return (
<div className="flex min-w-0 items-start overflow-hidden">
<div className="flex max-h-full min-w-0 flex-col items-start gap-1.5 overflow-y-auto">
{chartData.map((entry, index) => (
<span key={entry.code} className={rowClass}>
<span
className="inline-block h-3 w-3 rounded-sm border"
style={resolveSwatchStyle(entry.code, index)}
aria-hidden
/>
</span>
))}
</div>
<div className="ml-2 flex min-w-0 flex-col items-start gap-1.5 overflow-hidden">
{chartData.map((entry) => (
<span
key={entry.code}
className={`${rowClass} max-w-full truncate text-left text-text-primary`}
>
{entry.displayLabel}
</span>
))}
</div>
<div className="ml-3 flex shrink-0 flex-col items-end gap-1.5">
{chartData.map((entry) => (
<span
key={entry.code}
className={`${rowClass} tabular-nums text-right text-text-muted`}
>
{entry.count}
</span>
))}
</div>
</div>
);
}
export function TodayDonutChart({
data,
labelForCode,
colorForCode,
swatchStyleForCode,
variant = 'donut',
sideLegend = false,
}: TodayDonutChartProps) {
const { chartData, resolveColor } = useDonutChartModel({
data,
labelForCode,
colorForCode,
swatchStyleForCode,
});
const innerRadius = variant === 'pie' ? 0 : '62%';
const outerRadius = variant === 'pie' ? '88%' : 92;
const pieChart = (
<ResponsiveContainer width="100%" height="100%">
<PieChart margin={{ top: 0, right: 0, bottom: 0, left: 0 }}>
<Pie
data={chartData}
dataKey="count"
nameKey="displayLabel"
cx="50%"
cy="50%"
innerRadius={innerRadius}
outerRadius={outerRadius}
paddingAngle={variant === 'pie' ? 1 : 2}
stroke="transparent"
>
{chartData.map((entry, index) => (
<Cell key={entry.code} fill={resolveColor(entry.code, index)} />
))}
</Pie>
<Tooltip
contentStyle={TODAY_CHART_TOOLTIP_STYLE}
formatter={(value, _name, item) => {
const row = item?.payload as TodayChartBucket | undefined;
return [value, row ? labelForCode(row.code) : ''];
}}
/>
</PieChart>
</ResponsiveContainer>
);
if (sideLegend) {
return (
<div className="flex h-full min-h-0 w-full items-center gap-3 overflow-hidden sm:gap-4">
<div className="flex min-h-0 min-w-0 flex-1 items-center overflow-hidden">
<TodayDonutChartLegend
data={data}
labelForCode={labelForCode}
colorForCode={colorForCode}
swatchStyleForCode={swatchStyleForCode}
/>
</div>
<div className="aspect-square h-[min(100%,9.5rem)] w-[min(100%,9.5rem)] shrink-0">
{pieChart}
</div>
</div>
);
}
return <TodayChartFrame>{pieChart}</TodayChartFrame>;
}