86 lines
3.2 KiB
TypeScript
86 lines
3.2 KiB
TypeScript
import { MessageSquareWarning } from 'lucide-react';
|
|
|
|
import { ReportSection } from '../ReportSection';
|
|
|
|
import type { ReportFrictionSignals, ReportThrashingSignals } from '@renderer/types/sessionReport';
|
|
|
|
const frictionColor = (rate: number): string => {
|
|
if (rate <= 0.1) return '#4ade80';
|
|
if (rate <= 0.25) return '#fbbf24';
|
|
return '#f87171';
|
|
};
|
|
|
|
interface FrictionSectionProps {
|
|
data: ReportFrictionSignals;
|
|
thrashing: ReportThrashingSignals;
|
|
}
|
|
|
|
export const FrictionSection = ({ data, thrashing }: FrictionSectionProps) => {
|
|
return (
|
|
<ReportSection title="Friction Signals" icon={MessageSquareWarning}>
|
|
<div className="mb-4 flex items-center gap-3">
|
|
<span
|
|
className="rounded px-2 py-0.5 text-xs font-medium"
|
|
style={{
|
|
backgroundColor: `${frictionColor(data.frictionRate)}20`,
|
|
color: frictionColor(data.frictionRate),
|
|
}}
|
|
>
|
|
Friction Rate: {(data.frictionRate * 100).toFixed(1)}%
|
|
</span>
|
|
<span className="text-xs text-text-muted">
|
|
{data.correctionCount} correction{data.correctionCount !== 1 ? 's' : ''}
|
|
</span>
|
|
</div>
|
|
|
|
{data.corrections.length > 0 && (
|
|
<div className="mb-4">
|
|
<div className="mb-2 text-xs font-medium text-text-muted">Corrections</div>
|
|
<div className="flex flex-col gap-1">
|
|
{data.corrections.map((corr, idx) => (
|
|
<div key={idx} className="flex items-start gap-2 rounded px-2 py-1 text-xs">
|
|
<span
|
|
className="shrink-0 rounded px-1.5 py-0.5 font-mono text-[10px]"
|
|
style={{ backgroundColor: 'rgba(251, 191, 36, 0.15)', color: '#fbbf24' }}
|
|
>
|
|
{corr.keyword}
|
|
</span>
|
|
<span className="truncate text-text-secondary">{corr.preview}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{(thrashing.bashNearDuplicates.length > 0 || thrashing.editReworkFiles.length > 0) && (
|
|
<div>
|
|
<div className="mb-2 text-xs font-medium text-text-muted">Thrashing Signals</div>
|
|
|
|
{thrashing.bashNearDuplicates.length > 0 && (
|
|
<div className="mb-2">
|
|
<div className="mb-1 text-xs text-text-muted">Repeated Bash Commands</div>
|
|
{thrashing.bashNearDuplicates.map((dup, idx) => (
|
|
<div key={idx} className="flex items-center gap-2 px-2 py-0.5 text-xs">
|
|
<span className="text-text-muted">{dup.count}x</span>
|
|
<code className="truncate text-text-secondary">{dup.prefix}</code>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
|
|
{thrashing.editReworkFiles.length > 0 && (
|
|
<div>
|
|
<div className="mb-1 text-xs text-text-muted">Reworked Files (3+ edits)</div>
|
|
{thrashing.editReworkFiles.map((file, idx) => (
|
|
<div key={idx} className="flex items-center gap-2 px-2 py-0.5 text-xs">
|
|
<span className="text-text-muted">{file.editIndices.length}x</span>
|
|
<span className="truncate text-text-secondary">{file.filePath}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
</ReportSection>
|
|
);
|
|
};
|