Initial commit of Hearbit AI App
This commit is contained in:
121
src/App.tsx
Normal file
121
src/App.tsx
Normal file
@@ -0,0 +1,121 @@
|
||||
import { useState } from "react";
|
||||
import Settings from "./components/Settings";
|
||||
import Recorder from "./components/Recorder";
|
||||
|
||||
interface PromptTemplate {
|
||||
id: string;
|
||||
name: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
function App() {
|
||||
const [view, setView] = useState<'recorder' | 'settings'>('recorder');
|
||||
const [apiKey, setApiKey] = useState(localStorage.getItem('infomaniak_api_key') || '');
|
||||
const [productId, setProductId] = useState(localStorage.getItem('infomaniak_product_id') || '');
|
||||
|
||||
// Default prompts if none exist
|
||||
const defaultPrompts: PromptTemplate[] = [
|
||||
{ id: '1', name: 'General Summary', content: 'Summarize the following text into clear bullet points.' },
|
||||
{ id: '2', name: 'Action Items', content: 'Extract all action items and tasks from this text.' },
|
||||
{ id: '3', name: 'Email Draft', content: 'Draft a follow-up email based on this conversation.' }
|
||||
];
|
||||
|
||||
const [prompts, setPrompts] = useState<PromptTemplate[]>(() => {
|
||||
const saved = localStorage.getItem('infomaniak_prompts');
|
||||
return saved ? JSON.parse(saved) : defaultPrompts;
|
||||
});
|
||||
|
||||
const handleSaveSettings = (newApiKey: string, newProductId: string, newPrompts: PromptTemplate[]) => {
|
||||
setApiKey(newApiKey);
|
||||
setProductId(newProductId);
|
||||
setPrompts(newPrompts);
|
||||
localStorage.setItem('infomaniak_api_key', newApiKey);
|
||||
localStorage.setItem('infomaniak_product_id', newProductId);
|
||||
localStorage.setItem('infomaniak_prompts', JSON.stringify(newPrompts));
|
||||
setView('recorder');
|
||||
};
|
||||
|
||||
// State for Recorder (lifted to persist across view changes)
|
||||
const [transcription, setTranscription] = useState('');
|
||||
const [summary, setSummary] = useState('');
|
||||
|
||||
interface HistoryItem {
|
||||
id: string;
|
||||
date: string;
|
||||
transcription: string;
|
||||
summary: string;
|
||||
}
|
||||
|
||||
const [history, setHistory] = useState<HistoryItem[]>(() => {
|
||||
const saved = localStorage.getItem('infomaniak_history');
|
||||
return saved ? JSON.parse(saved) : [];
|
||||
});
|
||||
|
||||
const handleSaveToHistory = (t?: string, s?: string) => {
|
||||
const transToSave = t !== undefined ? t : transcription;
|
||||
const sumToSave = s !== undefined ? s : summary;
|
||||
|
||||
if (!transToSave && !sumToSave) return;
|
||||
const newItem: HistoryItem = {
|
||||
id: Date.now().toString(),
|
||||
date: new Date().toLocaleString(),
|
||||
transcription: transToSave,
|
||||
summary: sumToSave
|
||||
};
|
||||
const newHistory = [newItem, ...history];
|
||||
setHistory(newHistory);
|
||||
localStorage.setItem('infomaniak_history', JSON.stringify(newHistory));
|
||||
};
|
||||
|
||||
const handleDeleteHistory = (id: string) => {
|
||||
const newHistory = history.filter(item => item.id !== id);
|
||||
setHistory(newHistory);
|
||||
localStorage.setItem('infomaniak_history', JSON.stringify(newHistory));
|
||||
};
|
||||
|
||||
const handleLoadHistory = (item: HistoryItem) => {
|
||||
setTranscription(item.transcription);
|
||||
setSummary(item.summary);
|
||||
};
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background text-foreground flex flex-col select-none">
|
||||
<div className="flex-1 flex flex-col justify-center h-full">
|
||||
{view === 'recorder' ? (
|
||||
<Recorder
|
||||
apiKey={apiKey}
|
||||
productId={productId}
|
||||
prompts={prompts}
|
||||
onOpenSettings={() => setView('settings')}
|
||||
transcription={transcription}
|
||||
setTranscription={setTranscription}
|
||||
summary={summary}
|
||||
setSummary={setSummary}
|
||||
history={history}
|
||||
onSaveToHistory={handleSaveToHistory}
|
||||
onDeleteHistory={handleDeleteHistory}
|
||||
onLoadHistory={handleLoadHistory}
|
||||
/>
|
||||
) : (
|
||||
<Settings
|
||||
onSave={handleSaveSettings}
|
||||
onBack={() => setView('recorder')}
|
||||
initialApiKey={apiKey}
|
||||
initialProductId={productId}
|
||||
initialPrompts={prompts}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{view === 'settings' && (
|
||||
<div className="fixed top-4 right-4 z-50">
|
||||
{/* Close button handled inside Settings typically */}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
Reference in New Issue
Block a user