diff --git a/Dockerfile b/Dockerfile index 10db9f3..f235c49 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,20 +7,20 @@ WORKDIR /app # Copy package files COPY package*.json ./ COPY frontend/package*.json ./frontend/ +COPY backend/package*.json ./backend/ # Install dependencies -RUN npm install -RUN cd frontend && npm install +RUN cd backend && npm install && \ + cd ../frontend && npm install # Copy source files COPY . . -COPY frontend ./frontend # Build frontend RUN cd frontend && npm run build # Build backend -RUN npm run build +RUN cd backend && npm run build # Create database file RUN touch database.sqlite @@ -32,13 +32,13 @@ FROM node:18-alpine WORKDIR /app # Copy package files -COPY package*.json ./ +COPY backend/package*.json ./ # Install production dependencies only RUN npm install --production # Copy built files from builder stage -COPY --from=builder /app/dist ./dist +COPY --from=builder /app/backend/dist ./dist COPY --from=builder /app/frontend/build ./frontend/build COPY --from=builder /app/database.sqlite ./database.sqlite diff --git a/backend/src/index.ts b/backend/src/index.ts index 7cdc0f9..550273b 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -34,6 +34,20 @@ app.get('/api/events', async (req, res) => { } }); +app.get('/api/events/:slug', async (req, res) => { + try { + const { slug } = req.params; + const [rows] = await pool.query('SELECT * FROM events WHERE id = ?', [slug]); + if (rows.length === 0) { + return res.status(404).json({ error: 'Event not found' }); + } + res.json(rows[0]); + } catch (error) { + console.error('Error fetching event:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + app.post('/api/events', async (req, res) => { try { const { title, description, date, location } = req.body; @@ -48,6 +62,45 @@ app.post('/api/events', async (req, res) => { } }); +// RSVP routes +app.get('/api/events/:slug/rsvps', async (req, res) => { + try { + const { slug } = req.params; + const [rows] = await pool.query('SELECT * FROM rsvps WHERE event_id = ?', [slug]); + res.json(rows); + } catch (error) { + console.error('Error fetching RSVPs:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +app.post('/api/events/:slug/rsvp', async (req, res) => { + try { + const { slug } = req.params; + const { name, attending, bringing_guests, guest_count, guest_names, items_bringing } = req.body; + + const [result] = await pool.query( + 'INSERT INTO rsvps (event_id, name, attending, bringing_guests, guest_count, guest_names, items_bringing) VALUES (?, ?, ?, ?, ?, ?, ?)', + [slug, name, attending, bringing_guests, guest_count, guest_names, items_bringing] + ); + res.status(201).json(result); + } catch (error) { + console.error('Error creating RSVP:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +app.delete('/api/events/:slug/rsvps/:id', async (req, res) => { + try { + const { id } = req.params; + await pool.query('DELETE FROM rsvps WHERE id = ?', [id]); + res.status(204).send(); + } catch (error) { + console.error('Error deleting RSVP:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + // Initialize database tables async function initializeDatabase() { try { @@ -61,6 +114,21 @@ async function initializeDatabase() { created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) `); + + await pool.query(` + CREATE TABLE IF NOT EXISTS rsvps ( + id INT AUTO_INCREMENT PRIMARY KEY, + event_id INT NOT NULL, + name VARCHAR(255) NOT NULL, + attending VARCHAR(10) NOT NULL, + bringing_guests VARCHAR(10) NOT NULL, + guest_count INT DEFAULT 0, + guest_names TEXT, + items_bringing TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE + ) + `); console.log('Database initialized successfully'); } catch (error) { console.error('Error initializing database:', error);