import { X, CheckCircle, XCircle, Calculator } from 'lucide-react'; import { createPortal } from 'react-dom'; import type { ReturnBreakdown } from '../types'; interface ReturnExplainModalProps { isOpen: boolean; onClose: () => void; breakdown: ReturnBreakdown | null; date: string; } export default function ReturnExplainModal({ isOpen, onClose, breakdown, date }: ReturnExplainModalProps) { if (!isOpen || !breakdown) return null; const formattedDate = new Date(date).toLocaleDateString('en-IN', { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric', }); return createPortal(
{/* Backdrop */}
{/* Modal */}
{/* Header */}

Return Calculation

{/* Content */}
{/* Date & Result */}
{formattedDate}
= 0 ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'}`}> {breakdown.weightedReturn >= 0 ? '+' : ''}{breakdown.weightedReturn.toFixed(1)}%

Weighted Average Return

{/* Method Explanation */}

Calculation Method

1. Correct Predictions → Contribute positively

  • • BUY that went up → add the gain
  • • SELL that went down → add the avoided loss
  • • HOLD that stayed flat → small positive

2. Incorrect Predictions → Contribute negatively

  • • BUY that went down → subtract the loss
  • • SELL that went up → subtract missed gain
  • • HOLD that moved → subtract missed opportunity

3. Weighted Average

(Correct Avg × Correct Weight) + (Incorrect Avg × Incorrect Weight)
{/* Correct Predictions Breakdown */}

Correct Predictions

({breakdown.correctPredictions.count} stocks)
Average Return
+{breakdown.correctPredictions.avgReturn.toFixed(1)}%
Weight
{breakdown.correctPredictions.count}/{breakdown.correctPredictions.count + breakdown.incorrectPredictions.count}
{breakdown.correctPredictions.stocks.length > 0 && (
Top performers:
{breakdown.correctPredictions.stocks.map((stock: { symbol: string; decision: string; return1d: number }) => (
{stock.symbol} ({stock.decision}) +{stock.return1d.toFixed(1)}%
))}
)}
{/* Incorrect Predictions Breakdown */}

Incorrect Predictions

({breakdown.incorrectPredictions.count} stocks)
Average Return
{breakdown.incorrectPredictions.avgReturn.toFixed(1)}%
Weight
{breakdown.incorrectPredictions.count}/{breakdown.correctPredictions.count + breakdown.incorrectPredictions.count}
{breakdown.incorrectPredictions.stocks.length > 0 && (
Worst performers:
{breakdown.incorrectPredictions.stocks.map((stock: { symbol: string; decision: string; return1d: number }) => (
{stock.symbol} ({stock.decision}) {stock.return1d.toFixed(1)}%
))}
)}
{/* Final Calculation */}

Final Calculation

{breakdown.formula}
{/* Disclaimer */}

Note: This weighted return represents the theoretical gain/loss if you followed all predictions for the day. Actual results may vary based on execution timing, transaction costs, and market conditions.

{/* Footer */}
, document.body ); }