114 lines
3.4 KiB
TypeScript
114 lines
3.4 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect } from 'react';
|
|
import { useStore } from '@/lib/store';
|
|
import { api } from '@/lib/api';
|
|
import Sidebar from '@/components/Sidebar';
|
|
import MessageList from '@/components/MessageList';
|
|
import MessageInput from '@/components/MessageInput';
|
|
import SettingsPanel from '@/components/SettingsPanel';
|
|
|
|
export default function Home() {
|
|
const {
|
|
settings,
|
|
setSettings,
|
|
setConversations,
|
|
setCurrentId,
|
|
setMessages,
|
|
currentId,
|
|
settingsOpen,
|
|
sidebarOpen,
|
|
setSidebarOpen,
|
|
} = useStore();
|
|
|
|
useEffect(() => {
|
|
// Load settings from server
|
|
api.getSettings().then(setSettings).catch(console.error);
|
|
// Load conversations
|
|
api.getConversations().then(setConversations).catch(console.error);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
// Load messages when conversation changes
|
|
if (currentId) {
|
|
api.getMessages(currentId).then(setMessages).catch(console.error);
|
|
} else {
|
|
setMessages([]);
|
|
}
|
|
}, [currentId]);
|
|
|
|
return (
|
|
<div
|
|
className="flex h-dvh overflow-hidden"
|
|
style={{ background: 'var(--bg)' }}
|
|
data-theme={settings.theme}
|
|
data-font={settings.font_size}
|
|
>
|
|
{/* Mobile sidebar overlay */}
|
|
{sidebarOpen && (
|
|
<div
|
|
className="fixed inset-0 z-20 bg-black/40 md:hidden"
|
|
onClick={() => setSidebarOpen(false)}
|
|
/>
|
|
)}
|
|
|
|
{/* Sidebar */}
|
|
<div
|
|
className={`
|
|
fixed inset-y-0 left-0 z-30 w-72 transform transition-transform duration-200
|
|
md:relative md:translate-x-0 md:w-64 md:flex-shrink-0
|
|
${sidebarOpen ? 'translate-x-0' : '-translate-x-full'}
|
|
`}
|
|
style={{ background: 'var(--sidebar-bg)', borderRight: '1px solid var(--border)' }}
|
|
>
|
|
<Sidebar />
|
|
</div>
|
|
|
|
{/* Main */}
|
|
<div className="flex flex-col flex-1 min-w-0">
|
|
{/* Topbar */}
|
|
<div
|
|
className="flex items-center justify-between px-4 py-3 flex-shrink-0"
|
|
style={{ borderBottom: '1px solid var(--border)' }}
|
|
>
|
|
<div className="flex items-center gap-3">
|
|
{/* Hamburger — mobile only */}
|
|
<button
|
|
className="md:hidden p-1 rounded"
|
|
style={{ color: 'var(--text3)' }}
|
|
onClick={() => setSidebarOpen(!sidebarOpen)}
|
|
aria-label="Toggle sidebar"
|
|
>
|
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
|
|
<rect y="3" width="20" height="2" rx="1"/>
|
|
<rect y="9" width="20" height="2" rx="1"/>
|
|
<rect y="15" width="20" height="2" rx="1"/>
|
|
</svg>
|
|
</button>
|
|
<span style={{ fontSize: '13px', color: 'var(--text3)' }}>
|
|
<strong style={{ color: 'var(--text)', fontWeight: 500 }}>Aaron AI</strong>
|
|
{' '}— personal knowledge assistant
|
|
</span>
|
|
</div>
|
|
<button
|
|
onClick={() => useStore.getState().setSettingsOpen(!settingsOpen)}
|
|
style={{ color: 'var(--text3)', background: 'none', border: 'none', cursor: 'pointer', padding: '4px', borderRadius: '6px', fontSize: '18px' }}
|
|
aria-label="Settings"
|
|
>
|
|
⚙
|
|
</button>
|
|
</div>
|
|
|
|
{/* Messages */}
|
|
<MessageList />
|
|
|
|
{/* Input */}
|
|
<MessageInput />
|
|
</div>
|
|
|
|
{/* Settings panel */}
|
|
<SettingsPanel />
|
|
</div>
|
|
);
|
|
}
|