feat: structure

This commit is contained in:
2026-04-06 23:30:19 +02:00
commit 46a0d7aba8
41 changed files with 3480 additions and 0 deletions

59
frontend/src/App.tsx Normal file
View File

@@ -0,0 +1,59 @@
import { useState } from 'react'
import { Timeline } from './components/timeline/Timeline'
import { LeftSidebar } from './components/layout/LeftSidebar'
import { RightSidebar } from './components/layout/RightSidebar'
import { TopBar } from './components/layout/TopBar'
import { usePhotoStore } from './store/photoStore'
import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts'
function App() {
const [leftSidebarOpen, setLeftSidebarOpen] = useState(true)
const [rightSidebarOpen, setRightSidebarOpen] = useState(false)
const selectedPhotos = usePhotoStore((state) => state.selectedPhotos)
// Set up global keyboard shortcuts
useKeyboardShortcuts({
onToggleLeftSidebar: () => setLeftSidebarOpen(!leftSidebarOpen),
onToggleRightSidebar: () => setRightSidebarOpen(!rightSidebarOpen),
})
// Show right sidebar when photos are selected
if (selectedPhotos.length > 0 && !rightSidebarOpen) {
setRightSidebarOpen(true)
} else if (selectedPhotos.length === 0 && rightSidebarOpen) {
setRightSidebarOpen(false)
}
return (
<div className="flex flex-col h-screen bg-bg text-text">
<TopBar />
<div className="flex flex-1 overflow-hidden">
{/* Left Sidebar */}
<div
className={`transition-all duration-200 ${
leftSidebarOpen ? 'w-64' : 'w-0'
} overflow-hidden border-r border-border bg-surface`}
>
<LeftSidebar />
</div>
{/* Main Content - Timeline */}
<div className="flex-1 overflow-auto">
<Timeline />
</div>
{/* Right Sidebar */}
<div
className={`transition-all duration-200 ${
rightSidebarOpen ? 'w-80' : 'w-0'
} overflow-hidden border-l border-border bg-surface`}
>
<RightSidebar />
</div>
</div>
</div>
)
}
export default App

43
frontend/src/index.css Normal file
View File

@@ -0,0 +1,43 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--color-bg: #111110;
--color-surface: #161615;
--color-surface-2: #1c1c1a;
--color-surface-offset: #222220;
--color-border: rgba(255, 255, 255, 0.08);
--color-text: #e8e6e0;
--color-text-muted: #878580;
--color-text-faint: #4a4845;
--color-primary: #4f98a3;
--color-pick: #4f9e5c;
--color-reject: #c25a5a;
--color-star: #d4a340;
}
body {
@apply bg-bg text-text;
font-family: 'Geist', system-ui, sans-serif;
}
}
/* Custom scrollbar styles */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
@apply bg-surface;
}
::-webkit-scrollbar-thumb {
@apply bg-surface-offset rounded;
}
::-webkit-scrollbar-thumb:hover {
@apply bg-text-faint;
}

24
frontend/src/main.tsx Normal file
View File

@@ -0,0 +1,24 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import App from './App'
import './index.css'
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 60 * 1000, // 5 minutes
retry: 2,
},
},
})
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<App />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
</React.StrictMode>,
)