DevByte-Community / DevByte-Community/Community-API-Backend
Implement Simplified Events Management System
- Langage dominant
- JavaScript
- Étoiles
- 2
- Forks
- 11
- Métriques de merge des PR
- Aucune PR mergée en 30 j
Description
Ticket ID: EVENTS-SIMPLE-001
Priority: High
**Feature Description**
Implement a simplified events system for community gatherings. Users can create events and register/unregister with a single click. No calendar integration, no statistics, no complex registration tracking.
**Acceptance Criteria**
1. Database Schema
```
sql
CREATE TABLE events (
id UUID PRIMARY KEY DEFAULT uuid_generate_v7(),
title VARCHAR(200) NOT NULL,
description TEXT NOT NULL,
body TEXT, -- Detailed event description
techs UUID[] DEFAULT ARRAY[]::UUID[], -- Related technologies
partners UUID[] DEFAULT ARRAY[]::UUID[], -- Partner organizations
created_by UUID REFERENCES users(id) ON DELETE SET NULL,
cover_image VARCHAR(500),
start_at TIMESTAMP NOT NULL,
ends_at TIMESTAMP NOT NULL,
registration_link VARCHAR(500), -- External registration (optional)
external_link VARCHAR(500), -- Additional event link
location VARCHAR(200) NOT NULL,
venue_details TEXT, -- Specific venue info
topic VARCHAR(100),
type VARCHAR(50) DEFAULT 'WORKSHOP' CHECK (type IN ('WORKSHOP', 'MEETUP', 'HACKATHON', 'CONFERENCE', 'NETWORKING', 'WEBINAR', 'TRAINING')),
participants UUID[] DEFAULT ARRAY[]::UUID[], -- Simple array of user IDs
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Indexes for performance
CREATE INDEX idx_events_start_at ON events(start_at);
CREATE INDEX idx_events_type ON events(type);
CREATE INDEX idx_events_created_by ON events(created_by);
CREATE INDEX idx_events_participants ON events USING gin(participants);
```
2. Core Endpoints
- Public Endpoints (No Auth Required):
```
text
GET /api/v1/events # List events with filters & pagination
GET /api/v1/events/:id # Get event details
```
- Authenticated User Endpoints:
```
text
POST /api/v1/events # Create event
PUT /api/v1/events/:id # Update event (creator only)
DELETE /api/v1/events/:id # Delete event (creator or admin)
POST /api/v1/events/:id/register # Register for event (adds user to participants)
DELETE /api/v1/events/:id/register # Unregister from event (removes user from participants)
GET /api/v1/events/my-events # Get user's created events
GET /api/v1/events/my-registrations # Get events user is registered for
```
- Admin Endpoints:
```
text
DELETE /api/v1/admin/events/:id # Force delete any event
```
3. Filtering & Search
Query Parameters for `/api/v1/events`:
- type: WORKSHOP, MEETUP, HACKATHON, etc.
- topic: React, JavaScript, Open Source, etc.
- techs: Technology IDs (comma-separated)
- date: upcoming, past, all
- location: City, country
- search: Keyword search in title/description
- page, pageSize: Pagination
4. Caching Strategy
- Redis Cache Implementation:
```
javascript
const CACHE_KEYS = {
EVENTS_LIST: 'events:list:v1:', // + filters hash
EVENT_DETAIL: 'event:detail:', // + eventId
USER_EVENTS: 'events:user:', // + userId
};
const CACHE_TTL = {
EVENTS_LIST: 300, // 5 minutes
EVENT_DETAIL: 600, // 10 minutes
USER_EVENTS: 300 // 5 minutes
};
// Cache invalidation triggers:
// - New event created/updated/deleted
// - User registers/unregisters for event
```
5. Response Formats
Event Listing Response:
```
json
{
"success": true,
"data": [
{
"id": "uuid",
"title": "Introduction to React Hooks Workshop",
"description": "A hands-on session covering useState, useEffect, and custom hooks...",
"coverImage": "url",
"startAt": "2025-01-10T13:00:00Z",
"endsAt": "2025-01-10T16:00:00Z",
"location": "DevByte HQ, Lagos",
"type": "WORKSHOP",
"topic": "React",
"techs": [
{ "id": "react-uuid", "name": "React", "icon": "url" },
{ "id": "js-uuid", "name": "JavaScript", "icon": "url" }
],
"participants": ["user1-uuid", "user2-uuid", "user3-uuid"],
"participantCount": 3,
"registrationLink": "https://external-registration.com",
"formattedDate": "01-10-2025 (01:00pm - 04:00pm)",
"createdBy": {
"id": "user-uuid",
"fullName": "Event Organizer",
"profilePicture": "url"
},
"hasRegistered": false, // For authenticated users
"isCreator": false // For authenticated users
}
]
}
```
6. Registration Logic ✅
- Simple array operations:
```
javascript
// Register user
const event = await Event.findByPk(eventId);
if (!event.participants.includes(userId)) {
event.participants = [...event.participants, userId];
await event.save();
}
// Unregister user
event.participants = event.participants.filter(id => id !== userId);
await event.save();
```
- Rules:
- No duplicate registrations
- Users can register/unregister anytime
- No registration limits
- No waitlists
- No approval process
7. Validation Rules ✅
- [ ] Title: Required, 5-200 characters(no special characters to prevent sql injection attacks)
- [ ] Description: Required, 50-500 characters(no special characters to prevent sql injection attacks)
- [ ] Start/End Time: Required
- [ ] Location: Required, 2-200 characters(no special characters to prevent sql injection attacks)
- [ ] Type: Required, from enum values
- [ ] Registration Link: Optional, valid URL
- [ ] Cover Image: Optional, valid URL
- [ ] Techs/Partners: Optional, arrays of valid IDs
9. Testing ✅
- [ ] Unit tests for event creation/validation
- [ ] Integration tests for registration/unregistration
- [ ] Authorization tests (creator vs non-creator)
10. Documentation ✅
- [ ] Complete Swagger/OpenAPI documentation
- [ ] Simple registration flow documentation
- [ ] Cache behavior documentation
Guide de contribution
Ouvrir le guide de contribution
Évaluation
Cette issue n'a pas encore été évaluée.