Backend: - POST /api/events — create event, validates title/date/venue required, rejects past dates (Asia/Jerusalem aware), returns compliance_checklist flag when max_guests >= 100 - GET /api/events — list organizer events (scoped by JWT), paginated (limit 20), enriched with rsvp_confirmed/pending/total + vendors_confirmed counts, sorted by event_date ASC - GET /api/events/:id — single event with RSVP + vendor counts - PUT /api/events/:id — COALESCE update, validated status transitions (draft→published/cancelled, published→cancelled/completed), ownership enforced; returns compliance_checklist flag when crossing 100 guests - DELETE /api/events/:id — soft delete (deleted_at + status=cancelled), 204 Frontend: - DashboardPage — real event list, EventCard grid, pagination, prominent empty state with "צור אירוע ראשון" CTA - EventCard — title, date, venue, RSVP confirmed/total/vendors stats, progress bar (orange at 90%), days-until countdown, publish/edit/cancel actions - CreateEventPage — full form: title, date+time picker (min=today), venue, kashrut, budget, guest count; compliance checklist appears when max_guests >= 100, dismissible; Hebrew validation errors - EventDetailPage — full event detail with stat cards, days-until, read-only compliance checklist for 100+ events, quick-action links - ComplianceChecklist — reusable: interactive (create/edit) or read-only (detail page); 4 Israeli compliance items, dismissible banner - Button component: added asChild support via @radix-ui/react-slot - App.tsx: routes for /events/new, /events/:id, /events/:id/edit Build: 0 TS errors, 68 modules Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
50 lines
1.4 KiB
JavaScript
50 lines
1.4 KiB
JavaScript
require('dotenv').config();
|
|
const express = require('express');
|
|
const cookieParser = require('cookie-parser');
|
|
const cors = require('cors');
|
|
const path = require('path');
|
|
|
|
const authRoutes = require('./routes/auth');
|
|
const eventRoutes = require('./routes/events');
|
|
const guestRoutes = require('./routes/guests');
|
|
const rsvpRoutes = require('./routes/rsvp');
|
|
const { authMiddleware } = require('./middleware/auth');
|
|
const { startReminderCron } = require('./jobs/reminderCron');
|
|
|
|
const app = express();
|
|
const PORT = process.env.PORT || 3000;
|
|
|
|
app.use(cors({
|
|
origin: process.env.CLIENT_ORIGIN || true,
|
|
credentials: true,
|
|
}));
|
|
app.use(express.json());
|
|
app.use(cookieParser());
|
|
|
|
// Health check — no auth required
|
|
app.get('/health', (req, res) => res.json({ status: 'ok' }));
|
|
|
|
// Auth routes — no middleware (register/login are public)
|
|
app.use('/api/auth', authRoutes);
|
|
|
|
// Public RSVP routes — no auth required
|
|
app.use('/api/rsvp', rsvpRoutes);
|
|
|
|
// All routes below require valid JWT
|
|
app.use('/api', authMiddleware);
|
|
|
|
// Event + Guest management routes (auth enforced above)
|
|
app.use('/api/events', eventRoutes);
|
|
app.use('/api', guestRoutes);
|
|
|
|
// Serve React frontend in production
|
|
app.use(express.static(path.join(__dirname, 'client', 'dist')));
|
|
app.get('*', (req, res) => {
|
|
res.sendFile(path.join(__dirname, 'client', 'dist', 'index.html'));
|
|
});
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`אירועית server running on port ${PORT}`);
|
|
startReminderCron();
|
|
});
|