diff --git a/backend/server.js b/backend/server.js index 8c2aa87..7117beb 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1,3 +1,4 @@ +require('dotenv').config(); const express = require('express'); const cors = require('cors'); const bcrypt = require('bcrypt'); @@ -8,6 +9,7 @@ const path = require('path'); const fs = require('fs'); const { db, run, get, all } = require('./database'); +const { sendMail } = require('./mail'); const app = express(); app.use(cors()); @@ -156,6 +158,21 @@ app.post('/api/projects', authenticate, async (req, res) => { } }); +app.delete('/api/projects/:id', authenticate, async (req, res) => { + const { id } = req.params; + try { + const existing = await get('SELECT * FROM projects WHERE id = ?', [id]); + if (!existing) return res.status(404).json({ error: 'Not found' }); + if (existing.user_id !== req.user.id && req.user.role !== 'admin') { + return res.status(403).json({ error: 'Forbidden' }); + } + await run('DELETE FROM projects WHERE id = ?', [id]); + res.json({ success: true }); + } catch (err) { + res.status(500).json({ error: err.message }); + } +}); + // 7. Get users (Admin only) app.get('/api/users', authenticate, async (req, res) => { if (req.user.role !== 'admin') return res.status(403).json({ error: 'Forbidden' }); diff --git a/src/lib/api.ts b/src/lib/api.ts index 5f0eb54..f65109a 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -70,6 +70,15 @@ export const api = { if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`); return data; }, + + deleteProject: async (id) => { + const res = await fetch(`${API_URL}/projects/${id}`, { + method: 'DELETE', + headers: getHeaders(), + }); + if (!res.ok) throw new Error('Failed to delete project'); + return res.json(); + }, // Admin getUsers: async () => { diff --git a/src/pages/Dashboard.tsx b/src/pages/Dashboard.tsx index 468cf09..82542cc 100644 --- a/src/pages/Dashboard.tsx +++ b/src/pages/Dashboard.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react'; import { useAuthStore } from '../store/authStore'; import { useNavigate, Link } from 'react-router-dom'; -import { LogOut, Plus, Folder, Loader2 } from 'lucide-react'; +import { LogOut, Plus, Folder, Loader2, Trash2 } from 'lucide-react'; import { api } from '../lib/api'; interface Project { @@ -31,6 +31,18 @@ export default function Dashboard() { fetchProjects(); }, [user]); + const handleDeleteProject = async (e: React.MouseEvent, id: string) => { + e.stopPropagation(); // prevent navigating to editor + if (!confirm('Are you sure you want to delete this project?')) return; + try { + await api.deleteProject(id); + setProjects(projects.filter(p => p.id !== id)); + } catch (err) { + console.error('Error deleting project:', err); + alert('Failed to delete project'); + } + }; + const handleSignOut = async () => { await signOut(); navigate('/'); @@ -108,6 +120,13 @@ export default function Dashboard() {

{project.name}

{new Date(project.created_at).toLocaleDateString()}

+ ))}