Skip to content

feat: Phase 4 — Footfall Dashboard (slot-based bookings + trainer attendance)#6

Closed
maragakn wants to merge 4 commits intomainfrom
feat/footfall-dashboard
Closed

feat: Phase 4 — Footfall Dashboard (slot-based bookings + trainer attendance)#6
maragakn wants to merge 4 commits intomainfrom
feat/footfall-dashboard

Conversation

@maragakn
Copy link
Copy Markdown
Collaborator

@maragakn maragakn commented Apr 9, 2026

Summary

  • AmenityBooking model replaces FootfallEvent — a gym slot booking (e.g. 7am–8am) IS the footfall record. No scanner device required at the gym.
  • Trainer attendance shown as gate check-ins via MyGate staff entry — TrainerAttendance.checkIn/checkOut already tracked this correctly.
  • 687 amenity bookings seeded across 7 days with realistic peak-hour distribution (5am–10am morning rush, 6pm–9pm evening rush) for 2 active centers.

What's new

Data

  • New AmenityBooking model: centerId, memberName, memberFlat, slotDate, slotHour (int), status
  • FootfallEvent model removed (booking = footfall, no raw events needed)
  • Seed: 687 bookings with member names, flat numbers, and realistic hourly spread

API routes

  • GET /api/footfall?centerId=&date= → total bookings, by-hour array (5am–9pm), recent 10 bookings
  • GET /api/attendance/trainer?centerId=&date= → present/absent/late summary + per-trainer check-in times and hours worked

RWA Admin Dashboard (/rwa)

  • Footfall card — today's count, delta vs yesterday, hourly bar chart (current hour highlighted in orange)
  • Booking feed — recent bookings with member name, flat number, and slot badge
  • Trainer attendance card — present/late/absent pill summary + per-trainer rows with check-in time and source (MYGATE/OTP/MANUAL)

Test plan

  • Navigate to /rwa — footfall card shows today's booking count with hourly chart
  • Hover over bars in chart — tooltip shows count per slot
  • Booking feed shows member names and flat numbers with slot times
  • Trainer attendance shows correct present/absent split with check-in times
  • GET /api/footfall?centerId=[id] returns { totalBookings, byHour, recentBookings }
  • GET /api/attendance/trainer?centerId=[id] returns { summary, trainers }

Made with Cursor

Copilot AI review requested due to automatic review settings April 9, 2026 11:02
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request implements Phase 4 of the footfall dashboard, transitioning from raw footfall events to slot-based amenity bookings. The core change replaces the FootfallEvent model with a new AmenityBooking model, where gym bookings serve as the authoritative footfall records. The PR includes new dashboard components, API endpoints for footfall and trainer attendance data, and 687 seeded amenity bookings across 7 days with realistic peak-hour distribution.

Changes:

  • Replaced FootfallEvent model with AmenityBooking (centerId, memberName, memberFlat, slotDate, slotHour, status) for slot-based footfall tracking
  • Seeded 687 amenity bookings across 7 days with peak-hour distribution (5am-10am and 6pm-9pm) for 2 active centers
  • Added new dashboard components: FootfallCard (today's count with hourly bar chart), BookingFeed (recent bookings), and TrainerAttendanceCard (trainer attendance summary)
  • Created new API routes: GET /api/footfall and GET /api/attendance/trainer for data retrieval
  • Implemented new RWA resident dashboard at /rwa with footfall, bookings, and trainer attendance data

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
prisma/schema.prisma Replaced FootfallEvent model with AmenityBooking, updated Center relations
prisma/seed.ts Updated seeding logic to generate realistic 687 amenity bookings with peak-hour distribution across two centers
prisma/migrations/20260409103000_replace_footfall_with_amenity_bookings/migration.sql Database migration to drop FootfallEvent table and create AmenityBooking table
components/dashboard/FootfallCard.tsx New component displaying today's booking count with delta vs yesterday and hourly bar chart
components/dashboard/BookingFeed.tsx New component showing recent 12 bookings with member names and flat numbers
components/dashboard/TrainerAttendanceCard.tsx New component displaying trainer attendance summary (present/absent/late) with check-in times
app/rwa/page.tsx New RWA resident dashboard page combining footfall, bookings, and trainer attendance cards
app/rwa-admin/page.tsx Updated stats calculation to use amenity bookings instead of footfall events
app/api/footfall/route.ts New API endpoint for footfall data with hourly breakdown and recent bookings
app/api/attendance/trainer/route.ts New API endpoint for trainer attendance with summary and per-trainer details

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/api/footfall/route.ts
Comment on lines +34 to +38
const hourLabel = (h: number) => {
const suffix = h >= 12 ? "pm" : "am"
const display = h > 12 ? h - 12 : h
return `${display}${suffix}`
}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

The hourLabel function is missing the h === 0 ? 12 : h check when calculating the display hour. This will produce incorrect labels like "0am" instead of "12am" for midnight hour bookings (when h is 0). While this particular bug won't affect the current feature since bookings are only for hours 5-21, the inconsistency with other implementations of hourLabel in FootfallCard.tsx and BookingFeed.tsx makes it a bug that should be fixed for consistency and future-proofing.

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +26
const hourLabel = (h: number) => {
const suffix = h >= 12 ? "pm" : "am"
const display = h > 12 ? h - 12 : h === 0 ? 12 : h
const nextH = h + 1
const nextDisplay = nextH > 12 ? nextH - 12 : nextH === 0 ? 12 : nextH
const nextSuffix = nextH >= 12 ? "pm" : "am"
return `${display}${suffix}–${nextDisplay}${nextSuffix}`
}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

The hourLabel function in BookingFeed has a logic error for the suffix calculation when the next hour crosses the am/pm boundary at midnight (hour 24). When h=23, nextH becomes 24, and nextSuffix becomes "pm" (since 24 >= 12), but hour 24 represents midnight (hour 0) and should be "am". The correct logic should be nextSuffix = nextH > 24 || nextH < 12 ? "am" : "pm" or handle the 24-hour case explicitly. While this won't affect current bookings (limited to 5-21), it's a latent bug that could cause incorrect labels if booking hours are extended in the future.

Copilot uses AI. Check for mistakes.
Integrates FootfallCard, TrainerAttendanceCard, and BookingFeed into
the proper /rwa-admin page (with sidebar) replacing the placeholder.
Scopes stat queries to the active center. Removes the orphaned /rwa
standalone page that had no layout or navigation.

Made-with: Cursor
@maragakn
Copy link
Copy Markdown
Collaborator Author

maragakn commented Apr 9, 2026

Superseded by #9 — rebased cleanly on latest main (post PR #8 merge). Closing in favour of the cleaner branch.

@maragakn maragakn closed this Apr 9, 2026
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.

2 participants