Skip to content

✨ Finish event creation and editing flow - #952

Open
Justber79 wants to merge 3 commits into
need4deed-org:developfrom
Justber79:justyna-945-event-flow
Open

✨ Finish event creation and editing flow#952
Justber79 wants to merge 3 commits into
need4deed-org:developfrom
Justber79:justyna-945-event-flow

Conversation

@Justber79

Copy link
Copy Markdown
Collaborator

Description

Finishes the dashboard event-management flow so coordinators can create, view, edit, and delete persisted events.
The calendar now displays real event data and provides a clearer overview of upcoming and past events. The existing three-step creation design is preserved while adding the missing event fields and backend integration.

Related Issues

Closes #945

Changes

  • Connect the event flow to the real GET, POST, PATCH, and DELETE event endpoints.
  • Display upcoming and past events fetched from the backend.
  • Add event markers to the calendar.
  • Allow selecting a calendar date to prefill the creation form.
  • Add start date, end date, start time, and end time fields.
  • Add the registration-link field.
  • Add required address-field validation.
  • Add a 512-character description limit matching the backend constraint.
  • Add an edit route and prefill the form with the selected event’s saved values.
  • Add event deletion with a confirmation dialog.
  • Add English and German translations for the new UI.
  • Update the event API types through the published need4deed-sdk package.

Screenshots / Demos

Before

Calendar before implementation

After

Events dashboard — German Events dashboard in German
Events dashboard and event flow — English Events dashboard in English Create event location step Create event date and time step Edit event flow Delete event confirmation

Testing

  • yarn typecheck — passed
  • yarn lint — passed with four pre-existing, unrelated React Hook warnings
  • git diff --check — passed
  • Manually tested creating, displaying, editing, and deleting events.
  • Manually tested calendar navigation and event date markers.
  • Manually checked the English and German versions.

Checklist

  • WITHIN THE SCOPE OF AN ISSUE; No unnecessary files included
  • Tests added/updated — no automated tests added; flow tested manually
  • Documentation updated — not required
  • CI passes — pending PR checks

@arturasmckwcz

Copy link
Copy Markdown
Collaborator

Follow-up on #945: instructions for making the calendar reusable

Functionally this PR already covers the ask (fetch/create/edit/delete events, month grid, upcoming/past lists). What's still needed is a refactor so CalendarContent.tsx (currently ~480 lines, everything inline) stops being a monolith. Whoever picks this up (including a coding assistant) should treat it as a follow-up to this PR, working from what's already merged/open here.

The page (CalendarContent.tsx) should end up doing only 3 things:

  1. Call a hook that returns the events for the given month.
  2. Render the "Create an event" CTA.
  3. Render a reusable Calendar component.

1. Consolidate the data logic into a hook

src/hooks/useEvents.ts already has useEvents, useCreateEvent, useUpdateEvent(id), useDeleteEvent. Build on top of these rather than replacing them:

  • Add useEvent(id) for single-event fetch. CreateEvent.tsx currently derives the editing event by events.find(e => e.id === eventId) off the full useEvents() list (see src/components/Dashboard/Calendar/CreateEvent/CreateEvent.tsx) — formalize that into its own hook so it's not duplicated wherever a single event is needed. Reusing the cached list via select is fine; it doesn't need a dedicated network call unless we want to avoid loading the whole list just to open one event.
  • Add an orchestration hook (e.g. useCalendar() in src/hooks/useCalendar.ts) that wraps the above and owns everything CalendarContent.tsx currently hand-rolls inline:
    • month state (monthDate, setMonthDate, prev/next)
    • upcoming / past derivation (currently the events.filter(...) / .reverse() lines directly in the component)
    • the day-click handler (currently clickDay) — on click, decide "scroll to that day's items" vs. "fire the empty-date callback"
    • edit/delete trigger functions and the delete-confirmation dialog state (currently local useState<ApiEventN4DGetList | null> for deleting)
  • The events fetch itself doesn't need real month filtering on this pass — apiPathEvent returns the full list and the dataset is small; keep loading everything once and filter by month client-side inside the hook. Don't add a backend query param for this unless it's already in the SDK contract.

2. Split into components

Two new pieces, both currently inlined in CalendarContent.tsx:

(a) Reusable Calendar component — new folder, e.g. src/components/Dashboard/Calendar/Calendar/, composed of 3 widgets:

  • CalendarGrid — the month grid (currently the cells() helper + Days/Day/Dot styled components)
  • UpcomingEvents — the upcoming list (currently the upcoming.map(EventCard...) block)
  • PastEvents — the collapsible past list (currently the Past/PastToggle/PastRow block)

The EventCard component (currently defined inline in CalendarContent.tsx) should move into this folder too and support both a "card" and a "bar" rendering variant, since past events currently render as a plain PastRow bar while upcoming events render as a full Card — make that an explicit prop rather than two separate hand-written layouts.

(b) "Create an event" CTA — extract the Button + create() navigation call into its own small component (e.g. CreateEventCta.tsx) so it's not tangled with the rest of the page.

3. Calendar component contract

  • Props: the month's events, the current month/navigation state, and a callback — something like onEmptyDateClick(date: Date) — for what to do when an empty grid date is clicked.
  • Default behavior (no override needed for the dashboard use case):
    • List all of the month's events across the two widgets: upcoming and past.
    • Each list item can render as a card or a bar (see variant note above).
    • Clicking a grid date with events scrolls to that day's items; clicking an empty date fires onEmptyDateClick. Note: the current clickDay implementation only scrolls to the first event matching that date (events.find(...) + getElementById('event-${event.id}')) — since a day can have multiple events, this should scroll to/highlight the whole group for that day, not just one.
    • The grid should stay visible at all times when there's enough room — it's currently in a Grid/aside layout that already keeps it beside the list, but check that behavior holds (e.g. position: sticky on the aside) once the list is long enough to scroll.

No SDK or backend changes needed for this pass — it's a pure frontend refactor of code that's already functionally complete in this PR.

@nadavosa nadavosa left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the diff and checked it out locally. tsc --noEmit and yarn lint both pass clean on this branch (only the same 4 pre-existing, unrelated hook warnings you already called out). Note GitHub hasn't actually run CI on this PR yet, it's a fork PR and no check runs exist for the head commit yet (probably needs a maintainer to approve the workflow run), so "CI passes" isn't confirmed from GitHub's side yet, just from my local run.

Found a few real issues worth addressing before merge:

1. Event type is hardcoded to WORKSHOP for every event. toPayload() in CreateEvent.tsx always sets type: EventN4DType.WORKSHOP, but the SDK enum has two values (PARTY, WORKSHOP) and there's no UI to choose. Every event a coordinator creates through this flow, including a purely social one, gets tagged as a workshop. Was this intentional (e.g. "party" isn't used yet), or should there be a type selector in the form?

2. Events only get a translation in the coordinator's current UI language. toPayload() submits a single-element translations array using i18n.language. Since the public site is bilingual and translations is a required array (per ApiEventN4DCreate), an event created by a German-speaking coordinator has no English translation record at all, and vice versa. Non-matching-locale visitors to the public event page would presumably see nothing (or a broken fallback) for that event. This seems like a real gap for a bilingual site rather than an edge case.

3. Multi-day events aren't reflected on the calendar past their start day. eventDays (for the dot markers) and clickDay (click-to-scroll-to-event) in CalendarContent.tsx both key only on event.date, never event.dateEnd. Since the date/time step explicitly supports a different end date (with end > start validation), a coordinator can create a multi-day event, but the calendar only marks its first day. Clicking the event's other days (including its own end day) shows no marker and offers "create event" there instead, since nothing flags that day as occupied.

4. Multi-day event card display reads as a same-day range. EventCard's range() helper builds the date from event.date but appends endTime from event.dateEnd regardless of whether they're the same calendar day, e.g. a Friday 18:00 → Saturday 09:00 event renders as "Friday, ... · 18:00–09:00", which reads like an invalid same-day range rather than a two-day span.

5. Minor: /dashboard/calendar/[id]/edit/page.tsx does Number(id), if the id in the URL isn't numeric this becomes NaN, which is falsy, so CreateEvent silently falls into "create new event" mode instead of showing an error for a malformed edit URL. Low severity, just flagging.

None of these are typos or crashes, the flow works for the straightforward same-day, single-language case shown in the screenshots, but 1-3 look like they'd affect real usage once coordinators create multi-day or non-English-only events.

@Justber79

Justber79 commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator Author

@arturasmckwcz @nadavosa Thank you both for reviewing the PR and for the detailed feedback. I’ve pushed commit daec62e5 addressing your comments.

For Arturas’s refactor request:

  • CalendarContent.tsx now only calls useCalendar(), renders CreateEventCta, and renders the reusable Calendar.
  • The calendar is split into CalendarGrid, UpcomingEvents, PastEvents, and EventCard with card/bar variants.
  • useEvent(id) and useCalendar() now own the relevant data and orchestration logic.
  • Occupied dates scroll to and highlight the complete date group; empty dates open the creation flow with the date prefilled.
  • The calendar remains sticky on desktop.

For Nadav’s findings:

  • Multi-day events mark every covered day, including across months.
  • Multi-day ranges display both dates correctly.
  • Malformed edit URLs show Not Found.
  • Event type is now selectable using the existing SDK EventN4DType values: WORKSHOP and PARTY. The selected type is saved and restored during editing.

One question remains about translations: should coordinators enter both English and German title/description, or should the public event pages rely on the backend fallback when only one translation exists?

Updated calendar

Updated calendar page

Event type selector

Create event form with event type selector

Please let me know if I should make any further changes to PR #952.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: finish the Calendar event creation/edit flow — missing fields, no backend wiring, no edit view

3 participants