Skip to content

feat: EventRegistration entity + public signup endpoint + coordinator view + CSV export #682

@nadavosa

Description

@nadavosa

Context

Linked to need4deed-org/fe#647 — in-house event registration replacing Google Forms.

New entity: EventRegistration

Field Type Notes
id number PK
opportunityId number FK → opportunity (must be dated + non-accompanying)
fullName string
email string
phone string | null
numberOfPeople number default 1
languagePreference string | null
message string | null max 500 chars
createdAt timestamp

Endpoints

POST /event-registration (public, no auth)

Anyone can submit. Validate that the opportunity exists, has an appointmentDate, and is not past.

Body:
```json
{
"opportunityId": 5,
"fullName": "Ali K.",
"email": "ali@example.com",
"phone": "+49123456",
"numberOfPeople": 2,
"languagePreference": "Arabic",
"message": "Looking forward to it"
}
```

Response: `201 { message: "Registration submitted." }`

Errors:

  • `404` — opportunity not found
  • `400` — opportunity is not an event (no date, or accompanying type)
  • `400` — event date is in the past

GET /opportunity/:id/registrations (COORDINATOR, NGO, ADMIN only)

Returns all registrations for a given event opportunity, ordered by `createdAt DESC`.

Response:
```json
{
"data": [
{
"id": 1,
"fullName": "Ali K.",
"email": "ali@example.com",
"phone": "+49123456",
"numberOfPeople": 2,
"languagePreference": "Arabic",
"message": "...",
"createdAt": "2026-06-13T10:00:00Z"
}
],
"count": 1,
"totalPeople": 2
}
```

Include `totalPeople` (sum of numberOfPeople across all registrations).

GET /opportunity/:id/registrations/export (COORDINATOR, NGO, ADMIN only)

Returns a CSV file download.

Headers: `Content-Type: text/csv`, `Content-Disposition: attachment; filename="registrations-{id}.csv"`

Columns: Name, Email, Phone, People, Language, Message, Registered at

SDK types

Add to need4deed-sdk:

  • `ApiEventRegistrationPost`
  • `ApiEventRegistrationGet`

Tasks

  • `EventRegistration` entity (TypeORM)
  • Repository
  • `POST /event-registration` (public route, no auth hook)
  • `GET /opportunity/:id/registrations` (auth: COORDINATOR, NGO, ADMIN)
  • `GET /opportunity/:id/registrations/export` — CSV
  • Validation: opportunity must be a dated non-accompanying event, not in the past
  • SDK types

Metadata

Metadata

Assignees

No one assigned

    Labels

    biggycontains sub-issues, won't get dev branch

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions