feat: add notifications and project shares features

- Backend: notifications + shares routes, DB tables, SqliteAdapter methods
- Frontend: NotificationPanel (bell icon + dropdown), ShareDialog, Dashboard integration
- Styles: notification + share dialog CSS
This commit is contained in:
2026-06-28 13:52:54 +02:00
parent a4371ca3ce
commit 20432f4b47
11 changed files with 655 additions and 7 deletions
+28 -7
View File
@@ -3,6 +3,8 @@
*/
import { useState, useEffect, useCallback } from 'react';
import { useAuth } from '../contexts/AuthContext';
import { NotificationPanel } from '../components/NotificationPanel';
import { ShareDialog } from '../components/ShareDialog';
const API_BASE = import.meta.env.VITE_API_BASE || '';
@@ -25,6 +27,7 @@ export function Dashboard({ onOpenProject }: DashboardProps) {
const [showCreate, setShowCreate] = useState(false);
const [newName, setNewName] = useState('');
const [newDesc, setNewDesc] = useState('');
const [shareProjectId, setShareProjectId] = useState<string | null>(null);
const fetchProjects = useCallback(async () => {
setLoading(true);
@@ -86,7 +89,10 @@ export function Dashboard({ onOpenProject }: DashboardProps) {
<h1>Web CAD</h1>
<span className="dashboard-user">{user?.name} ({user?.role})</span>
</div>
<button className="dashboard-logout" onClick={logout}>Abmelden</button>
<div className="dashboard-header-actions">
<NotificationPanel token={token!} />
<button className="dashboard-logout" onClick={logout}>Abmelden</button>
</div>
</header>
<div className="dashboard-content">
@@ -133,18 +139,33 @@ export function Dashboard({ onOpenProject }: DashboardProps) {
{project.description && <p>{project.description}</p>}
<div className="dashboard-project-meta">
<span>Erstellt: {new Date(project.created_at).toLocaleDateString('de-DE')}</span>
<button
className="dashboard-delete-btn"
onClick={(e) => handleDelete(project.id, e)}
>
Löschen
</button>
<div className="dashboard-project-actions">
<button
className="dashboard-share-btn"
onClick={(e) => { e.stopPropagation(); setShareProjectId(project.id); }}
>
Teilen
</button>
<button
className="dashboard-delete-btn"
onClick={(e) => handleDelete(project.id, e)}
>
Löschen
</button>
</div>
</div>
</div>
))}
</div>
)}
</div>
<ShareDialog
token={token!}
projectId={shareProjectId ?? ''}
open={!!shareProjectId}
onClose={() => setShareProjectId(null)}
/>
</div>
);
}