krz/brand-bench

A dynamic brand documentation generator with Ollama integration.

clone: git clone https://gitbay.org/krz/brand-bench.git

main: src/components/PreviewPanel.tsx · raw

  1import type { BrandInputs, BrandOutputs, LockedSections } from '../types';
  2import { BrandDoc } from './BrandDoc';
  3import { CopyButton } from './CopyButton';
  4import { toMarkdown, toJSON, toHTML, downloadFile } from '../lib/export';
  5
  6interface Props {
  7  inputs: BrandInputs;
  8  outputs: BrandOutputs | null;
  9  locked: LockedSections;
 10  onToggleLock: (section: keyof LockedSections) => void;
 11  onEdit: <K extends keyof BrandOutputs>(key: K, value: BrandOutputs[K]) => void;
 12  isGenerating: boolean;
 13  generateMode?: 'template' | string;
 14  generateError?: string | null;
 15  onGenerate?: () => void;
 16}
 17
 18export function PreviewPanel({ inputs, outputs, locked, onToggleLock, onEdit, isGenerating, generateMode, generateError, onGenerate }: Props) {
 19  const handleExportMd = () => {
 20    if (!outputs) return;
 21    downloadFile(toMarkdown(inputs, outputs), `${inputs.name || 'brand'}-package.md`, 'text/markdown');
 22  };
 23
 24  const handleExportJson = () => {
 25    if (!outputs) return;
 26    downloadFile(toJSON(inputs, outputs), `${inputs.name || 'brand'}-package.json`, 'application/json');
 27  };
 28
 29  const handleExportHtml = () => {
 30    if (!outputs) return;
 31    downloadFile(toHTML(inputs, outputs), `${inputs.name || 'brand'}-guidelines.html`, 'text/html');
 32  };
 33
 34  const fullMarkdown = outputs ? toMarkdown(inputs, outputs) : '';
 35
 36  return (
 37    <div className="preview-panel">
 38      <div className="preview-toolbar">
 39        <div className="preview-toolbar-left">
 40          <span className="preview-doc-label">
 41            {outputs ? 'Brand Package' : 'Preview'}
 42          </span>
 43          {outputs && (
 44            <span style={{ fontSize: 11, color: 'var(--text-4)' }}>
 45              · {new Date().toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })}
 46            </span>
 47          )}
 48        </div>
 49        {outputs && (
 50          <div className="preview-toolbar-right">
 51            <CopyButton text={fullMarkdown} label="Copy all" />
 52          </div>
 53        )}
 54      </div>
 55
 56      {generateError && (
 57        <div className="generate-error">
 58          <span className="generate-error-icon"></span>
 59          <span className="generate-error-msg">{generateError}</span>
 60          {onGenerate && (
 61            <button className="generate-error-retry btn btn-ghost" onClick={onGenerate}>
 62              Try template instead
 63            </button>
 64          )}
 65        </div>
 66      )}
 67
 68      <div className="preview-scroll">
 69        {isGenerating ? (
 70          <div className="empty-state">
 71            <div className="empty-state-title" style={{ color: 'var(--text-3)' }}>
 72              {generateMode && generateMode !== 'template'
 73                ? `Thinking with ${generateMode}`
 74                : 'Generating…'}
 75            </div>
 76            {generateMode && generateMode !== 'template' && (
 77              <div className="empty-state-sub">This may take 1560 seconds depending on your hardware</div>
 78            )}
 79          </div>
 80        ) : outputs ? (
 81          <BrandDoc
 82            inputs={inputs}
 83            outputs={outputs}
 84            locked={locked}
 85            onToggleLock={onToggleLock}
 86            onEdit={onEdit}
 87          />
 88        ) : (
 89          <div className="empty-state">
 90            <div className="empty-state-title">No package generated yet</div>
 91            <div className="empty-state-sub">Fill in the project details and click Generate</div>
 92          </div>
 93        )}
 94      </div>
 95
 96      {outputs && (
 97        <div className="export-bar">
 98          <span className="export-bar-left">
 99            Export
100          </span>
101          <div className="export-bar-right">
102            <button className="btn" onClick={handleExportMd}>
103              Export Markdown
104            </button>
105            <button className="btn" onClick={handleExportJson}>
106              Export JSON
107            </button>
108            <button className="btn" onClick={handleExportHtml}>
109              Export HTML
110            </button>
111          </div>
112        </div>
113      )}
114    </div>
115  );
116}