feat: add alert notification system for each eventcard#473
feat: add alert notification system for each eventcard#473HarshPatel5940 merged 8 commits intoFOSSUChennai:mainfrom
Conversation
- Add optional alert field to Event interface with message and type - Display alert icon next to community name badge when alert exists - Show alert tooltip on hover with formatted message - Support alert types: postponed, venue-change, cancelled, general - Apply alert functionality to both home events and archive pages
- Add alert field to event template - Document alert types: postponed, venue-change, cancelled, general - Include usage examples for different alert scenarios - Update validation section to include alert message requirements
|
Tagging: @nammahari @bupd @JustinBenito @Sarveshmrao for visibility. Thanks in advance. |
|
This is actually good |
- Remove Warning icon component from tooltip content in events.tsx - Remove Warning icon component from tooltip content in archive.tsx - Simplify tooltip structure by removing unnecessary flex wrapper
|
@Sarveshmrao Any inputs or blockers from your end? |
|
Hi @Som23Git amazing. As there are changes in UI, I'll just have @JustinBenito review this once and then we can proceed. |
@JustinBenito, any thoughts? |
|
@Som23Git can you resolve conflicts bro?, would like this feature to be merged. |
📝 WalkthroughWalkthroughAdds an optional per-event Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@src/components/pages/Archive/archive.tsx`:
- Around line 240-244: The JSX currently uses {!alert.type} to show the
"Important Notice" header, but alerts with type === 'general' are truthy so that
branch never renders; update the conditional to explicitly check for alert.type
=== 'general' (or use a default fallback like (alert.type === 'general' ||
!alert.type)) in the same JSX block where alert.type is inspected so the "⚠️
Important Notice" label renders for general alerts (refer to the alert variable
and the JSX lines that render {alert.type === 'postponed' ...}).
In `@src/components/pages/home/events.tsx`:
- Around line 211-243: The tooltip can overflow for right-edge cards; update the
component to compute placement at render/toggle and apply conditional classes
instead of always using left-0 w-64: add a ref to the event card container,
create a placement state (e.g., tooltipPlacement) and in the handler that
toggles setShowAlert (or a useEffect when showAlert becomes true) measure
containerRef.getBoundingClientRect().right vs window.innerWidth and set
tooltipPlacement to 'left' (use left-0), 'right' (use right-0 left-auto), or
'center' (use left-1/2 transform -translate-x-1/2) so the tooltip div (the
element that currently has className='absolute left-0 top-8 z-50 w-64 ...')
conditionally renders the appropriate Tailwind classes to keep it inside the
viewport; keep using showAlert/alert/Warning button handlers but swap the fixed
left-0 class for the placement-dependent class string.
- Around line 231-236: The alert header currently checks only for 'postponed',
'venue-change', 'cancelled' and a falsy type, so alert.type === 'general'
renders empty; update the conditional rendering inside the <p className='text-sm
font-semibold text-yellow-900'> to include alert.type === 'general' (or a final
fallback case for any unmatched truthy type) and render a default label like '⚠️
Important Notice' so that any non-empty alert.type (e.g., 'general') shows an
appropriate header; adjust the three explicit checks and the fallback around
alert.type to ensure a default branch covers all other string values.
🧹 Nitpick comments (3)
src/components/pages/home/events.tsx (2)
213-220: Conflicting click-toggle and hover interactions on the alert button.The button has both
onClick(togglesshowAlert) andonMouseEnter/onMouseLeave(setsshowAlertto true/false). On desktop, the click toggle is effectively overridden by hover events. On mobile (touch), hover events don't fire, so click-toggle works — but there's no way to dismiss the tooltip except tapping the button again (tapping elsewhere won't close it since there's no outside-click handler).Consider either:
- Hover-only on desktop + click-toggle with outside-click-to-dismiss on mobile, or
- Simplifying to hover-only (removing
onClick) if mobile isn't a primary concern.
9-38:EventandEventCardPropstypes are duplicated — consider importing fromevent.d.ts.The
Eventtype here (lines 9–22) duplicates the canonical definition insrc/types/event.d.ts. The alert shape{ message: string; type?: ... }is also repeated inEventCardProps. Consider importing theEventtype and extracting the alert type to avoid drift between files.src/components/pages/Archive/archive.tsx (1)
9-38: Massive duplication:EventCard,Tooltip, and types are nearly identical toevents.tsx.The
Eventtype,EventCardPropstype,EventCardcomponent (including all alert UI logic), andTooltipcomponent are copy-pasted betweenarchive.tsxandevents.tsx. This PR extends the duplicated surface area with the alert feature. Consider extracting into shared modules:
- A shared
EventCardcomponent (e.g.,src/components/EventCard.tsx)- A shared
Tooltipcomponent- Import the
Eventtype fromsrc/types/event.d.tsThis would make future alert changes (or any card changes) a single-file edit instead of two.
Also applies to: 121-312, 406-427
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@src/components/pages/home/events.tsx`:
- Line 266: The tooltip arrow div in events.tsx is hardcoded to 'left-4' which
breaks alignment when tooltipPlacement !== 'left'; update the arrow element that
currently uses class 'absolute -top-2 left-4 h-3 w-3 rotate-45 ...' to compute
its horizontal positioning from the tooltipPlacement prop/variable (e.g., when
tooltipPlacement === 'right' use 'right-4', when 'left' keep 'left-4', and when
centered placements like 'top'/'bottom' use 'left-1/2 transform
-translate-x-1/2'); implement this by building the arrow's className
conditionally based on tooltipPlacement so the arrow mirrors the tooltip
alignment.
- Around line 134-146: Replace the useEffect that computes tooltip placement
with useLayoutEffect so placement is computed synchronously to avoid the
one-frame flash; inside the effect (still reading alertContainerRef.current and
showAlert) compute tooltipWidth and setTooltipPlacement to 'right' when
rect.left + tooltipWidth > window.innerWidth, otherwise set it to 'left' (remove
the 'center' branch entirely because rect.left < tooltipWidth/2 should not map
to 'center'); keep using alertContainerRef and setTooltipPlacement exactly as
before but in useLayoutEffect and with the same dependency on showAlert.
🧹 Nitpick comments (3)
src/components/pages/home/events.tsx (3)
18-21: Extract thealertshape into a shared type to reduce duplication.The same
{ message: string; type?: 'postponed' | 'venue-change' | 'cancelled' | 'general' }literal is repeated inEvent,EventCardProps, and likely insrc/types/event.d.ts. Extract it once and reference it everywhere.♻️ Suggested shared type
+type EventAlert = { + message: string; + type?: 'postponed' | 'venue-change' | 'cancelled' | 'general'; +}; + type Event = { // ... - alert?: { - message: string; - type?: 'postponed' | 'venue-change' | 'cancelled' | 'general'; - }; + alert?: EventAlert; }; type EventCardProps = { // ... - alert?: { - message: string; - type?: 'postponed' | 'venue-change' | 'cancelled' | 'general'; - }; + alert?: EventAlert; };Also applies to: 34-37
229-236:onClicktoggle conflicts withonMouseEnter/onMouseLeaveon desktop.On desktop, hovering opens the tooltip via
onMouseEnter, but clicking while hovering togglesshowAlerttofalse, causing the tooltip to disappear while the cursor is still over the button. Consider removing theonClicktoggle (let hover drive desktop) and relying ononClickonly for touch devices, or use a single interaction model.
227-270: Alert tooltip lacks keyboard accessibility.The tooltip cannot be dismissed via
Escape, and the tooltip content isn't associated with the button viaaria-describedby(or similar). Screen-reader users won't know the tooltip content exists or be able to access it via keyboard alone. Consider:
- Adding an
onKeyDownhandler forEscapeto close the tooltip.- Linking the button to the tooltip panel with
aria-describedbyand anidon the tooltip<div>.- Adding
role="tooltip"to the popover.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/components/pages/home/events.tsx (2)
74-76:⚠️ Potential issue | 🟠 Major
Array.sort()mutateseventsstate in place — usetoSorted()or spread first.
events.sort(...)mutates the state array directly, which violates React's immutability contract for state. This can cause subtle rendering bugs.🐛 Proposed fix
- const sortedEvents = events.sort( + const sortedEvents = [...events].sort( (a, b) => new Date(a.eventDate).getTime() - new Date(b.eventDate).getTime() );
112-123:⚠️ Potential issue | 🟠 Major
EventCarddefined insideEventsis recreated every render — causes unmount/remount of all cards.Because
EventCardis declared inside the parent component body, React sees a new component type on every render. This means all cards unmount and remount on any parent state change (e.g., height recalculation), destroying local state likeshowAlertandmousePosition.Move
EventCardoutsideEventsand passmonthlyCardHeight/upcomingCardHeightas props (or via context).
🧹 Nitpick comments (4)
src/components/pages/home/events.tsx (4)
18-21: Extract a sharedAlertInfotype to avoid duplication.The alert shape is duplicated between
EventandEventCardProps. Consider extracting it:♻️ Suggested refactor
+type AlertInfo = { + message: string; + type?: 'postponed' | 'venue-change' | 'cancelled' | 'general'; +}; + type Event = { // ... - alert?: { - message: string; - type?: 'postponed' | 'venue-change' | 'cancelled' | 'general'; - }; + alert?: AlertInfo; }; type EventCardProps = { // ... - alert?: { - message: string; - type?: 'postponed' | 'venue-change' | 'cancelled' | 'general'; - }; + alert?: AlertInfo; };Also note that
src/types/event.d.tsdefines the canonicalEventtype — ideally both files should reference the same type rather than re-declaring it here.Also applies to: 34-37
229-241: MixedonClicktoggle +onMouseEnter/onMouseLeavecan feel inconsistent.On desktop, hover controls visibility completely, making the click toggle superfluous (mouse leave immediately closes after click). On touch devices,
onMouseLeavemay fire immediately after tap in some browsers, preventing the tooltip from staying open.Consider using only hover for desktop and only click (with outside-click-to-close) for touch, or pick one interaction model. This is minor and can be deferred.
255-263: Consider simplifying the alert header rendering with a map lookup.The current chain of
&&conditions works but is verbose and fragile if new types are added. A lookup map would be cleaner:♻️ Suggested refactor
+const ALERT_HEADERS: Record<string, string> = { + postponed: 'Event Postponed', + 'venue-change': 'Venue Changed', + cancelled: 'Event Cancelled', +}; <p className='text-sm font-semibold text-yellow-900'> - {alert.type === 'postponed' && 'Event Postponed'} - {alert.type === 'venue-change' && 'Venue Changed'} - {alert.type === 'cancelled' && 'Event Cancelled'} - {(!alert.type || - alert.type === 'general' || - !['postponed', 'venue-change', 'cancelled'].includes(alert.type)) && - 'Important Notice'} + {(alert.type && ALERT_HEADERS[alert.type]) || 'Important Notice'} </p>
107-110:useEffectdependenciesmonthlyEventsandupcomingEventsare new array references every render.Since
filter()creates a new array on every render, this effect fires every render cycle. It doesn't cause an infinite loop (React bails out on same-valuesetState), but it's wasteful. Consider memoizing the filtered arrays withuseMemo.
|
@HarshPatel5940, take a look. Let me know if you need any updates from my end. Thanks. |
|
@Som23Git thanks for the updates! will review shortly. |
HarshPatel5940
left a comment
There was a problem hiding this comment.
seems fine on an high level, will clone and check as well for any issues.
|
It will be in release soon. cc: @JustinBenito |

This PR adds an alert notification system to each event, allowing event organizers to display important notices (postponements, venue changes, cancellations, and important notice) directly on event cards.
Motivation & Inspiration
This feature was inspired by a real-world scenario where a community event had to be postponed due to a cyclone alert. Attendees were confused and asking questions like:
Without a clear way to communicate these changes directly on the event card, organizers had to rely on social media posts and external announcements, leading to confusion and missed updates.
Example scenario: A Build2Learn event in Chennai was postponed from
November 29thtoDecember 6thdue to a cyclone alert. While the organizer posted updates on LinkedIn, (assuming) attendees visiting theTamilNadu.techwebsite couldn't see this critical information directly on the event card.This feature solves this problem by allowing event organizers to add alerts directly to their event data, making important updates immediately visible to all new visitors.
What's Changed
Type Definition: Added optional
alertfield toEventinterface insrc/types/event.d.tsmessage(required) andtype(optional: 'postponed', 'venue-change', 'cancelled', 'general')EventCard Component: Updated both home events and archive pages
Backward Compatible: All existing events without alerts continue to work normally
Example screenshots:
Usage Example
(updated the CONTRIBUTING.md with clear examples)
To add an alert to an event in
events.json:I'm open to any suggestions, feedback, and improvements. Let me know. Thanks.
Summary by CodeRabbit
New Features
Documentation