← back to Norma

components/email-analyzer/CompareModal.tsx

146 lines

'use client';

import type { VersionEntry } from './VersionTimeline';
import ProsConsPanel, { type ProsConsData } from './ProsConsPanel';
import { sanitizeHtml } from './sanitize';
import ScorePanel from './ScorePanel';
import ResizableModal from '../shared/ResizableModal';

/* ─── Types ──────────────────────────────────────────────────────────────── */

interface CompareModalProps {
  compareA: VersionEntry;
  compareB: VersionEntry;
  prosConsData: ProsConsData | null;
  prosConsLoading: boolean;
  onClose: () => void;
  /** When a suggestion is clicked, modal closes and this fires with the chat instruction. */
  onApplySuggestion?: (suggestion: string, label: string) => void;
}

/* ─── Component ──────────────────────────────────────────────────────────── */

export default function CompareModal({
  compareA,
  compareB,
  prosConsData,
  prosConsLoading,
  onClose,
  onApplySuggestion,
}: CompareModalProps) {
  return (
    <ResizableModal
      modalId="email-analyzer-compare-versions"
      title={`Compare: v${compareA.versionNumber} vs v${compareB.versionNumber}`}
      onClose={onClose}
      defaultWidth={1000}
    >
      <div style={{ margin: '-16px -20px' }}>
        {/* Side-by-side content */}
        <div style={{ display: 'flex', minHeight: 300 }}>
          <div
            style={{
              flex: 1,
              padding: 16,
              borderRight: '1px solid var(--color-border)',
            }}
          >
            <div
              style={{
                fontSize: 12,
                fontWeight: 600,
                color: 'var(--color-text-muted)',
                marginBottom: 8,
                textTransform: 'uppercase',
                letterSpacing: '0.06em',
              }}
            >
              v{compareA.versionNumber}: {compareA.label}
            </div>
            <div
              style={{
                fontSize: 13,
                lineHeight: 1.7,
                color: 'var(--color-text)',
              }}
              dangerouslySetInnerHTML={{
                __html: sanitizeHtml(compareA.content),
              }}
            />
          </div>
          <div style={{ flex: 1, padding: 16 }}>
            <div
              style={{
                fontSize: 12,
                fontWeight: 600,
                color: 'var(--color-text-muted)',
                marginBottom: 8,
                textTransform: 'uppercase',
                letterSpacing: '0.06em',
              }}
            >
              v{compareB.versionNumber}: {compareB.label}
            </div>
            <div
              style={{
                fontSize: 13,
                lineHeight: 1.7,
                color: 'var(--color-text)',
              }}
              dangerouslySetInnerHTML={{
                __html: sanitizeHtml(compareB.content),
              }}
            />
          </div>
        </div>

        {/* Pros/Cons analysis */}
        <div
          style={{
            borderTop: '1px solid var(--color-border)',
            padding: '14px 20px',
          }}
        >
          <ProsConsPanel
            data={prosConsData}
            loading={prosConsLoading}
            prosLabel={`v${compareB.versionNumber} does better`}
            consLabel={`v${compareA.versionNumber} did better`}
            compact
          />
        </div>

        {/* Live score + suggestions to improve v B */}
        <div
          style={{
            borderTop: '1px solid var(--color-border)',
            padding: '14px 20px',
            background: 'var(--color-surface-el)',
          }}
        >
          <div
            style={{
              fontSize: 12,
              fontWeight: 700,
              color: 'var(--color-text-muted)',
              marginBottom: 10,
              textTransform: 'uppercase',
              letterSpacing: '0.06em',
            }}
          >
            Score v{compareB.versionNumber} + live improvement suggestions
          </div>
          <ScorePanel
            email={compareB.content}
            autoRunKey={compareB.id}
            onApplySuggestion={(suggestion, label) => {
              onApplySuggestion?.(suggestion, label);
              onClose();
            }}
          />
        </div>
      </div>
    </ResizableModal>
  );
}