← back to Norma

components/drafts/DraftToolbar.tsx

142 lines

'use client';

import { useState } from 'react';
import { Save, Layers, History, Send, Check } from 'lucide-react';
import ExportMenu from '@/components/shared/ExportMenu';
import { useToast } from '@/components/ToastProvider';

interface DraftToolbarProps {
  draftId: string;
  isSaving: boolean;
  isDirty: boolean;
  onSave: () => void;
  onToggleBoilerplate: () => void;
  onToggleVersionHistory: () => void;
  showVersionHistory: boolean;
}

export default function DraftToolbar({
  draftId,
  isSaving,
  isDirty,
  onSave,
  onToggleBoilerplate,
  onToggleVersionHistory,
  showVersionHistory,
}: DraftToolbarProps) {
  const { addToast } = useToast();
  const [testSending, setTestSending] = useState(false);
  const [testSent, setTestSent] = useState(false);

  async function handleTestSend() {
    setTestSending(true);
    setTestSent(false);
    try {
      const res = await fetch(`/api/drafts/${draftId}/test-send`, { method: 'POST' });
      if (!res.ok) throw new Error('Test send failed');
      setTestSent(true);
      setTimeout(() => setTestSent(false), 3000);
    } catch {
      addToast('Test send failed. Check server logs.', 'error');
    } finally {
      setTestSending(false);
    }
  }

  return (
    <div
      className="flex items-center justify-between gap-2 px-3 py-2 flex-wrap"
      style={{
        borderTop: '1px solid var(--color-border)',
        backgroundColor: 'var(--color-surface)',
      }}
      role="toolbar"
      aria-label="Draft actions"
    >
      {/* Left group */}
      <div className="flex items-center gap-1.5 flex-wrap">
        {/* Save */}
        <button
          type="button"
          onClick={onSave}
          disabled={isSaving || !isDirty}
          className="btn btn-primary btn-sm"
          title={isSaving ? 'Saving...' : isDirty ? 'Save changes' : 'No unsaved changes'}
          aria-label={isSaving ? 'Saving' : 'Save'}
        >
          {isSaving ? (
            <span className="spinner" style={{ width: 12, height: 12, borderWidth: 1.5 }} />
          ) : (
            <Save size={13} aria-hidden="true" />
          )}
          <span className="hidden sm:inline">{isSaving ? 'Saving...' : 'Save'}</span>
        </button>

        {/* Boilerplate */}
        <button
          type="button"
          onClick={onToggleBoilerplate}
          className="btn btn-secondary btn-sm"
          title="Insert boilerplate block"
          aria-label="Boilerplate blocks"
        >
          <Layers size={13} aria-hidden="true" />
          <span className="hidden sm:inline">Boilerplate</span>
        </button>

        {/* Version History */}
        <button
          type="button"
          onClick={onToggleVersionHistory}
          className="btn btn-secondary btn-sm"
          aria-pressed={showVersionHistory}
          title="Version history"
          aria-label="Version history"
        >
          <History size={13} aria-hidden="true" />
          <span className="hidden sm:inline">History</span>
        </button>

        {/* Export */}
        <ExportMenu draftId={draftId} />
      </div>

      {/* Right group */}
      <div className="flex items-center gap-1.5">
        {isDirty && !isSaving && (
          <span className="text-xs" style={{ color: 'var(--color-warning)' }}>
            Unsaved changes
          </span>
        )}
        {!isDirty && !isSaving && (
          <span className="text-xs" style={{ color: 'var(--color-text-muted)' }}>
            All changes saved
          </span>
        )}

        {/* Test Send */}
        <button
          type="button"
          onClick={handleTestSend}
          disabled={testSending}
          className={`btn btn-sm ${testSent ? 'btn-secondary' : 'btn-secondary'}`}
          title="Send test email"
          aria-label="Send test email"
          style={testSent ? { color: 'var(--color-success)', borderColor: 'var(--color-success)' } : {}}
        >
          {testSending ? (
            <span className="spinner" style={{ width: 12, height: 12, borderWidth: 1.5 }} />
          ) : testSent ? (
            <Check size={13} aria-hidden="true" />
          ) : (
            <Send size={13} aria-hidden="true" />
          )}
          <span className="hidden sm:inline">
            {testSending ? 'Sending...' : testSent ? 'Sent!' : 'Test Send'}
          </span>
        </button>
      </div>
    </div>
  );
}