← back to Norma

components/email-analyzer/GeneratedVersionCard.tsx

106 lines

'use client';

import { Mail } from 'lucide-react';
import type { VersionEntry } from './VersionTimeline';
import { sanitizeHtml } from './sanitize';

/* ─── Helpers ────────────────────────────────────────────────────────────── */

function countWords(html: string): number {
  const plain = html.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
  return plain.split(/\s+/).filter(Boolean).length;
}

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

interface GeneratedVersionCardProps {
  currentVersion: string;
  activeVersionId: string | null;
  versions: VersionEntry[];
}

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

/**
 * Renders the current email version preview with sanitized HTML content.
 * Content is sanitized via sanitizeHtml() which strips script tags,
 * event handlers, iframes, and other dangerous elements before rendering.
 */
export default function GeneratedVersionCard({
  currentVersion,
  activeVersionId,
  versions,
}: GeneratedVersionCardProps) {
  const activeVersion = versions.find((v) => v.id === activeVersionId);
  const sanitized = sanitizeHtml(currentVersion);

  return (
    <div
      className="card"
      style={{
        padding: 0,
        display: 'flex',
        flexDirection: 'column',
        overflow: 'hidden',
      }}
    >
      <div
        style={{
          padding: '10px 16px',
          borderBottom: '1px solid var(--color-border)',
          display: 'flex',
          alignItems: 'center',
          gap: 8,
        }}
      >
        <Mail size={14} style={{ color: 'var(--color-primary)' }} />
        <span
          style={{
            fontSize: 13,
            fontWeight: 600,
            color: 'var(--color-text)',
          }}
        >
          Generated Version
        </span>
        {activeVersionId && (
          <span
            className="badge"
            style={{
              fontSize: 10,
              padding: '1px 6px',
              backgroundColor: 'var(--color-primary-dim)',
              color: 'var(--color-primary)',
              border: '1px solid rgba(10,124,89,0.2)',
            }}
          >
            v{activeVersion?.versionNumber || '?'}
          </span>
        )}
        <span
          style={{
            fontSize: 12,
            color: 'var(--color-text-muted)',
            marginLeft: 'auto',
          }}
        >
          {countWords(currentVersion)} words
        </span>
      </div>
      <div
        style={{
          flex: 1,
          padding: 20,
          overflowY: 'auto',
          fontSize: 14,
          lineHeight: 1.8,
          color: 'var(--color-text)',
          maxHeight: 450,
        }}
        className="email-preview-content"
        dangerouslySetInnerHTML={{ __html: sanitized }}
      />
    </div>
  );
}