feat(frontend): implement complete React/Vite frontend
## Features
- React 18 + TypeScript + Vite setup
- Tailwind CSS + shadcn/ui components
- Complete authentication flow (API Key)
- Dashboard with stats and recent documents
- Document upload (drag & drop) and management
- Chat interface with RAG support
- Settings page (theme, provider selection)
- Responsive design with mobile support
## Components
- Layout with sidebar navigation
- Button, Card, Input, Label, Separator (shadcn)
- Protected and public routes
## State Management
- Zustand stores: auth, chat, settings
- Persisted to localStorage
## API Integration
- Axios client with interceptors
- All API endpoints integrated
- Error handling and loading states
## Pages
- Login: API key authentication
- Dashboard: Overview and stats
- Documents: Upload, list, delete
- Chat: Conversational interface with sources
- Settings: Theme and provider config
🎨 Production-ready build (339KB gzipped)
This commit is contained in:
61
frontend/src/stores/settingsStore.ts
Normal file
61
frontend/src/stores/settingsStore.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
|
||||
interface SettingsState {
|
||||
// State
|
||||
theme: 'light' | 'dark' | 'system';
|
||||
defaultProvider: string;
|
||||
defaultModel: string;
|
||||
sidebarOpen: boolean;
|
||||
|
||||
// Actions
|
||||
setTheme: (theme: 'light' | 'dark' | 'system') => void;
|
||||
setDefaultProvider: (provider: string) => void;
|
||||
setDefaultModel: (model: string) => void;
|
||||
toggleSidebar: () => void;
|
||||
setSidebarOpen: (open: boolean) => void;
|
||||
}
|
||||
|
||||
export const useSettingsStore = create<SettingsState>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
theme: 'system',
|
||||
defaultProvider: 'openai',
|
||||
defaultModel: 'gpt-4o-mini',
|
||||
sidebarOpen: true,
|
||||
|
||||
setTheme: (theme) => {
|
||||
set({ theme });
|
||||
// Apply theme to document
|
||||
const root = window.document.documentElement;
|
||||
root.classList.remove('light', 'dark');
|
||||
|
||||
if (theme === 'system') {
|
||||
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
root.classList.add(systemTheme);
|
||||
} else {
|
||||
root.classList.add(theme);
|
||||
}
|
||||
},
|
||||
|
||||
setDefaultProvider: (provider) => {
|
||||
set({ defaultProvider: provider });
|
||||
},
|
||||
|
||||
setDefaultModel: (model) => {
|
||||
set({ defaultModel: model });
|
||||
},
|
||||
|
||||
toggleSidebar: () => {
|
||||
set((state) => ({ sidebarOpen: !state.sidebarOpen }));
|
||||
},
|
||||
|
||||
setSidebarOpen: (open) => {
|
||||
set({ sidebarOpen: open });
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: 'settings-storage',
|
||||
}
|
||||
)
|
||||
);
|
||||
Reference in New Issue
Block a user