← back to Norma

components/email-analyzer/OriginalEmailCard.tsx

270 lines

'use client';

import { useRef } from 'react';
import {
  ClipboardPaste,
  ChevronDown,
  BarChart3,
  Loader2,
  X,
} from 'lucide-react';

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

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

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

interface OriginalEmailCardProps {
  pastedEmail: string;
  onPastedEmailChange: (value: string) => void;
  showOriginal: boolean;
  onToggleOriginal: () => void;
  hasVersions: boolean;
  isAnalyzing: boolean;
  onAnalyze: () => void;
  /** Ref forwarded to the textarea for external focus management */
  pasteRef?: React.RefObject<HTMLTextAreaElement | null>;
}

interface AddOriginalSectionProps {
  show: boolean;
  onShow: () => void;
  onHide: () => void;
  originalCount: number;
  newOriginalText: string;
  onNewOriginalTextChange: (value: string) => void;
  onSave: () => void;
}

/* ─── Original Email Card ────────────────────────────────────────────────── */

export default function OriginalEmailCard({
  pastedEmail,
  onPastedEmailChange,
  showOriginal,
  onToggleOriginal,
  hasVersions,
  isAnalyzing,
  onAnalyze,
  pasteRef,
}: OriginalEmailCardProps) {
  const localRef = useRef<HTMLTextAreaElement>(null);
  const textareaRef = pasteRef ?? localRef;

  return (
    <div
      className="card"
      style={{ padding: 0, overflow: 'hidden' }}
    >
      <div
        style={{
          padding: '12px 16px',
          borderBottom: '1px solid var(--color-border)',
          display: 'flex',
          alignItems: 'center',
          gap: 8,
          cursor: hasVersions ? 'pointer' : 'default',
        }}
        onClick={() => hasVersions && onToggleOriginal()}
      >
        <ClipboardPaste
          size={16}
          style={{ color: 'var(--color-primary)' }}
        />
        <span
          style={{
            fontSize: 13,
            fontWeight: 600,
            color: 'var(--color-text)',
            flex: 1,
          }}
        >
          Original Email
        </span>
        {pastedEmail.trim() && (
          <span style={{ fontSize: 12, color: 'var(--color-text-muted)' }}>
            {countWords(pastedEmail)} words
          </span>
        )}
        {hasVersions && (
          <ChevronDown
            size={14}
            style={{
              color: 'var(--color-text-muted)',
              transform: showOriginal ? 'rotate(0deg)' : 'rotate(-90deg)',
              transition: 'transform 0.15s',
            }}
          />
        )}
      </div>
      {(showOriginal || !hasVersions) && (
        <>
          <textarea
            ref={textareaRef}
            className="input"
            style={{
              width: '100%',
              minHeight: hasVersions ? 100 : 200,
              maxHeight: hasVersions ? 150 : 400,
              fontSize: 14,
              lineHeight: 1.7,
              resize: 'vertical',
              border: 'none',
              borderRadius: 0,
              padding: 16,
              backgroundColor: 'var(--color-surface)',
            }}
            placeholder={
              'Paste an email here to analyze and rewrite...\n\nYou can paste plain text or HTML email content. The AI will help you refine the tone, length, and messaging.'
            }
            value={pastedEmail}
            onChange={(e) => onPastedEmailChange(e.target.value)}
            readOnly={hasVersions}
          />
          {!hasVersions && (
            <div
              style={{
                padding: '10px 16px',
                borderTop: '1px solid var(--color-border)',
                display: 'flex',
                alignItems: 'center',
                gap: 8,
              }}
            >
              <button
                type="button"
                className="btn btn-primary btn-sm"
                disabled={!pastedEmail.trim() || isAnalyzing}
                onClick={onAnalyze}
                style={{ display: 'flex', alignItems: 'center', gap: 6 }}
              >
                {isAnalyzing ? (
                  <>
                    <Loader2 size={14} className="spinner" /> Analyzing...
                  </>
                ) : (
                  <>
                    <BarChart3 size={14} /> Analyze
                  </>
                )}
              </button>
            </div>
          )}
        </>
      )}
    </div>
  );
}

/* ─── Add Another Original Section ───────────────────────────────────────── */

export function AddOriginalSection({
  show,
  onShow,
  onHide,
  originalCount,
  newOriginalText,
  onNewOriginalTextChange,
  onSave,
}: AddOriginalSectionProps) {
  if (!show) {
    return (
      <button
        type="button"
        className="btn btn-ghost btn-sm"
        style={{ fontSize: 12, gap: 4, color: 'var(--color-text-muted)' }}
        onClick={onShow}
      >
        <ClipboardPaste size={12} /> Add another original (v0.{originalCount + 1})
      </button>
    );
  }

  return (
    <div
      className="card"
      style={{ padding: 0, overflow: 'hidden' }}
    >
      <div
        style={{
          padding: '10px 16px',
          borderBottom: '1px solid var(--color-border)',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'space-between',
        }}
      >
        <span
          style={{
            fontSize: 13,
            fontWeight: 600,
            color: 'var(--color-text)',
          }}
        >
          Paste another version (v0.{originalCount + 1})
        </span>
        <button
          type="button"
          onClick={onHide}
          style={{
            background: 'none',
            border: 'none',
            cursor: 'pointer',
            color: 'var(--color-text-muted)',
            padding: 2,
            display: 'flex',
          }}
        >
          <X size={14} />
        </button>
      </div>
      <textarea
        className="input"
        style={{
          width: '100%',
          minHeight: 120,
          fontSize: 14,
          lineHeight: 1.7,
          resize: 'vertical',
          border: 'none',
          borderRadius: 0,
          padding: 16,
          backgroundColor: 'var(--color-surface)',
        }}
        placeholder="Paste a different version of this email..."
        value={newOriginalText}
        onChange={(e) => onNewOriginalTextChange(e.target.value)}
        autoFocus
      />
      <div
        style={{
          padding: '8px 16px',
          borderTop: '1px solid var(--color-border)',
          display: 'flex',
          alignItems: 'center',
          gap: 8,
        }}
      >
        <button
          type="button"
          className="btn btn-primary btn-sm"
          disabled={!newOriginalText.trim()}
          onClick={onSave}
          style={{ fontSize: 12 }}
        >
          Save as v0.{originalCount + 1}
        </button>
        {newOriginalText.trim() && (
          <span style={{ fontSize: 11, color: 'var(--color-text-muted)' }}>
            {countWords(newOriginalText)} words
          </span>
        )}
      </div>
    </div>
  );
}