NeonClary
Initial commit: LLMChats3 - LLM conversation app with React + FastAPI, persona config, orchestrated conversation lifecycle, collapsible sidebar accordions, stop button, and export capabilities
085db90
import React, { useState, useRef, useEffect } from 'react';
import { Download, Settings } from 'lucide-react';
import { exportChat, exportApiLog } from '../utils/api';
export default function ExportBar({ sessionId }) {
const [devOpen, setDevOpen] = useState(false);
const dropdownRef = useRef(null);
useEffect(() => {
const handleClickOutside = (e) => {
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
setDevOpen(false);
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, []);
const downloadFile = (filename, content) => {
const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
};
const handleExport = async (fmt) => {
try {
const result = await exportChat(sessionId, fmt);
downloadFile(result.filename, result.content);
} catch (err) {
console.error('Export failed:', err);
}
};
const handleApiLogExport = async () => {
try {
const result = await exportApiLog(sessionId);
downloadFile('api_log.json', JSON.stringify(result, null, 2));
setDevOpen(false);
} catch (err) {
console.error('API log export failed:', err);
}
};
if (!sessionId) return null;
return (
<div className="export-bar">
<button className="btn-secondary" onClick={() => handleExport('txt')}>
<Download size={14} style={{ verticalAlign: 'middle', marginRight: 4 }} />
Download .txt
</button>
<button className="btn-secondary" onClick={() => handleExport('md')}>
<Download size={14} style={{ verticalAlign: 'middle', marginRight: 4 }} />
Download .md
</button>
<div className="dev-dropdown" ref={dropdownRef}>
<button
className="icon-btn"
onClick={() => setDevOpen(o => !o)}
title="Developer Options"
>
<Settings size={16} />
</button>
{devOpen && (
<div className="dev-dropdown-menu">
<button onClick={handleApiLogExport}>
Download Full API Log
</button>
</div>
)}
</div>
</div>
);
}