'use client'; import { Target, Zap, Clock, LayoutGrid } from 'lucide-react'; import type { OpportunityMatrix as OpportunityMatrixType, OpportunityItem } from '../types'; interface OpportunityMatrixProps { matrix: OpportunityMatrixType | null; onSubcodeClick?: (subcode: string) => void; } interface QuadrantProps { title: string; icon: React.ReactNode; items: OpportunityItem[]; bgColor: string; borderColor: string; textColor: string; iconBg: string; onItemClick?: (subcode: string) => void; } function Quadrant({ title, icon, items, bgColor, borderColor, textColor, iconBg, onItemClick, }: QuadrantProps) { return (
{/* Header */}
{icon}
{title} {items.length}
{/* Positioned items with dots and offset labels */} {items.length === 0 ? (
None
) : ( {items.map((item, index) => { // Constrain coordinates to safe zone const safeX = 15 + item.x * 70; const safeY = 30 + item.y * 55; // Offset label based on position to avoid clustering // Items on left half get labels to the right, vice versa const labelOffsetX = safeX < 50 ? 12 : -12; const labelOffsetY = (index % 3 - 1) * 8; // Stagger vertically return ( {/* Leader line */} {/* Dot at exact position */} ); })} )} {/* Clickable labels */} {items.length > 0 && items.map((item, index) => { const safeX = 15 + item.x * 70; const safeY = 30 + item.y * 55; const labelOffsetX = safeX < 50 ? 8 : -8; const labelOffsetY = (index % 3 - 1) * 6; const anchorX = safeX < 50 ? 'left-0' : 'right-0'; return ( ); })}
); } /** * 2x2 Opportunity Matrix visualization. * Shows issues categorized by frequency vs complexity with coordinate positioning. */ export function OpportunityMatrix({ matrix, onSubcodeClick }: OpportunityMatrixProps) { if (!matrix) { return null; } const totalItems = matrix.quick_wins.length + matrix.critical.length + matrix.nice_to_have.length + matrix.strategic.length; if (totalItems === 0) { return null; } return (

Opportunity Matrix

{totalItems} opportunities
{/* Matrix with L-shaped label area */}
{/* Y-axis label column */}
Effort →
{/* Main matrix area */}
{/* Matrix with arrows */}
{/* Coordinate axes - L-shaped from bottom-left origin */} {/* Horizontal arrowhead - points right */} {/* Vertical arrowhead - points up (pre-rotated triangle) */} {/* X-axis (horizontal - frequency increases right) */} {/* Y-axis (vertical - effort increases up) */}
{/* Unified coordinate grid overlay */} {/* Vertical grid lines */} {[12.5, 25, 37.5, 50, 62.5, 75, 87.5].map((x) => ( ))} {/* Horizontal grid lines */} {[12.5, 25, 37.5, 50, 62.5, 75, 87.5].map((y) => ( ))}
{/* Top Row: Simple solutions */} } items={matrix.nice_to_have} bgColor="bg-gray-50" borderColor="border-gray-200" textColor="text-gray-700" iconBg="bg-gray-200" onItemClick={onSubcodeClick} /> } items={matrix.quick_wins} bgColor="bg-green-50" borderColor="border-green-200" textColor="text-green-700" iconBg="bg-green-200" onItemClick={onSubcodeClick} /> {/* Bottom Row: Complex solutions */} } items={matrix.strategic} bgColor="bg-purple-50" borderColor="border-purple-200" textColor="text-purple-700" iconBg="bg-purple-200" onItemClick={onSubcodeClick} /> } items={matrix.critical} bgColor="bg-red-50" borderColor="border-red-200" textColor="text-red-700" iconBg="bg-red-200" onItemClick={onSubcodeClick} />
{/* X-axis label row */}
Frequency →
{/* Legend */}
Quick Wins: Fix first
Critical: High impact
Strategic: Plan ahead
Nice to Have: Low priority
); }