Skip to content

Conversation

@devksingh4
Copy link
Member

@devksingh4 devksingh4 commented Nov 13, 2025

Summary by CodeRabbit

  • New Features
    • Added purchase date display for tickets showing when checkout was completed
    • Tickets now sorted by validity status and purchase date in descending order
    • Email cells are now clickable with a tooltip to copy ticket ID to clipboard

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 13, 2025

Walkthrough

The changes introduce a new optional purchasedAt field to track checkout session completion times (in seconds since Epoch). The field is added to the ticket entry data model, incorporated into API route responses with multi-criteria sorting (by validity, purchasedAt presence, then descending purchase time), and displayed in the UI with a human-readable timestamp replacing the Ticket ID column. Email cells now include a tooltip and copy-to-clipboard functionality for the ticket ID.

Changes

Cohort / File(s) Summary
Ticket Data Model
src/api/functions/tickets.ts
Added optional purchased_at?: number field to RawMerchEntry and propagated the value as purchasedAt in emitted merch ticket objects.
API Route Handler
src/api/routes/tickets.ts
Added optional purchasedAt: number field to ticketEntryZod schema with description. Implemented multi-criteria sorting in GET /event/:eventId response: prioritizes valid tickets, then entries with defined purchasedAt, then descending purchasedAt value.
UI Display
src/ui/pages/tickets/ViewTickets.page.tsx
Added optional purchasedAt to purchaseSchema type; introduced formatPurchaseTime() helper for human-readable rendering (or "N/A" if absent). Replaced Ticket ID column with Purchased At column. Enhanced email cell with Mantine Tooltip and clickable copy-to-clipboard functionality for ticket IDs via new copyTicketId() function.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Notable areas:
    • Verify the sorting comparator logic in src/api/routes/tickets.ts correctly prioritizes validity and purchasedAt values as intended
    • Confirm formatPurchaseTime() properly handles undefined/missing purchasedAt values in the UI
    • Check that the clipboard copy notification integrates well with the existing notification system

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'Display purchased at data when available' directly summarizes the main change: adding and displaying a new purchasedAt field across the ticket system's API and UI layers.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dsingh14/return-purchased-at

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

💰 Infracost report

Monthly estimate generated

This comment will be updated when code changes.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/api/routes/tickets.ts (1)

283-296: Critical: Missing purchasedAt field in response object.

The response object being pushed to issuedTickets is missing the purchasedAt field, even though:

  1. The schema defines it (lines 73-76)
  2. The sorting logic uses it (lines 311-320)
  3. The UI displays it (src/ui/pages/tickets/ViewTickets.page.tsx, lines 384-386)
  4. The database record should contain purchased_at (unmarshalled from line 282)

This will cause the UI to always display "N/A" for purchase times, and the sorting won't work as intended. For comparison, getUserMerchPurchases in src/api/functions/tickets.ts correctly includes this field at line 139.

Apply this diff to add the missing field:

           issuedTickets.push({
             type: "merch",
             valid: true,
             ticketId: unmarshalled.stripe_pi,
             refunded: unmarshalled.refunded,
             fulfilled: unmarshalled.fulfilled,
             purchaserData: {
               email: unmarshalled.email,
               productId: eventId,
               quantity: unmarshalled.quantity,
               size: unmarshalled.size,
             },
             totalPaid: unmarshalled.total_paid,
+            purchasedAt: unmarshalled.purchased_at,
           });
🧹 Nitpick comments (2)
src/ui/pages/tickets/ViewTickets.page.tsx (2)

270-275: Function is correct, but consider adding error handling.

The implementation works, though clipboard operations can fail. Consider wrapping in try-catch similar to the copyEmails function for consistency.

Apply this diff to add error handling:

 const copyTicketId = (ticketId: string) => {
-  navigator.clipboard.writeText(ticketId);
-  notifications.show({
-    message: "Ticket ID copied to clipboard!",
-  });
+  try {
+    navigator.clipboard.writeText(ticketId);
+    notifications.show({
+      message: "Ticket ID copied to clipboard!",
+    });
+  } catch (e) {
+    notifications.show({
+      title: "Failed to copy ticket ID",
+      message: "Please try again or contact support.",
+      color: "red",
+    });
+  }
 };

364-378: Consider UX: clicking email text copies ticket ID.

The tooltip helps clarify the behavior, but users may find it unexpected that clicking email text copies the ticket ID rather than the email itself. Consider alternatives:

  • Add a separate copy icon next to the email
  • Make the ticket ID visible somewhere in the row with its own copy button
  • Display ticket ID in the tooltip itself

This is not a functional issue, just a UX consideration for user expectations.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between f076739 and 20e9bf6.

📒 Files selected for processing (3)
  • src/api/functions/tickets.ts (2 hunks)
  • src/api/routes/tickets.ts (2 hunks)
  • src/ui/pages/tickets/ViewTickets.page.tsx (6 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run Unit Tests
  • GitHub Check: Build Application
🔇 Additional comments (8)
src/api/functions/tickets.ts (2)

35-35: LGTM! Optional field correctly added.

The purchased_at field is appropriately typed as optional since historical records may not have this field.


139-139: LGTM! Field correctly propagated.

The purchasedAt field is properly propagated from the database result to the API response with appropriate naming convention conversion.

src/ui/pages/tickets/ViewTickets.page.tsx (4)

14-14: LGTM!


34-34: LGTM! Schema correctly aligned with backend.


64-69: LGTM! Timestamp formatting is correct.

The function properly handles undefined values and correctly converts epoch seconds to milliseconds for JavaScript Date constructor.


384-386: LGTM! Purchase time correctly displayed.

src/api/routes/tickets.ts (2)

73-76: LGTM! Schema definition is clear and correct.


304-322: LGTM! Sorting logic is well-structured.

The multi-criteria sorting correctly prioritizes valid tickets, then tickets with purchase timestamps, then sorts by most recent first. The logic properly handles all undefined cases.

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