Skip to content

Conversation

@HJyup
Copy link
Collaborator

@HJyup HJyup commented Jan 7, 2026

No description provided.

Copilot AI review requested due to automatic review settings January 7, 2026 00:03
@vercel
Copy link

vercel bot commented Jan 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
events-comp-soc-com-web Ready Ready Preview, Comment Jan 7, 2026 0:04am

@HJyup HJyup merged commit a7de64c into main Jan 7, 2026
8 checks passed
@HJyup HJyup deleted the user-registrations-list branch January 7, 2026 00:04
Copy link

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 PR adds comprehensive registration UI functionality, enabling users to view, create, and manage their event registrations. The implementation spans both frontend and backend, introducing new API endpoints for fetching user registrations and displaying them in a dedicated user dashboard.

Key changes include:

  • New /me route displaying user's event registrations with status badges
  • Registration creation flow with form submission on event detail pages
  • Backend endpoints for fetching user registrations and individual registration status
  • Schema updates to include event metadata in registration responses

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
apps/web/src/routes/me/index.tsx Implements user dashboard showing all registrations with status indicators
apps/web/src/routes/events/$eventId/index.tsx Adds registration status display and disables registration button for already-registered users
apps/web/src/lib/hooks/use-create-registration.tsx New hook for handling registration creation with query invalidation
apps/web/src/lib/data/users.ts Adds server function to fetch all registrations for authenticated user
apps/web/src/lib/data/registration.ts Implements registration fetch and creation server functions
apps/web/src/lib/data/event.ts Minor whitespace formatting improvements for consistency
apps/web/src/components/ui/dialog.tsx Removes unused DialogClose export and adjusts overlay opacity
apps/web/src/components/registration-status-badge.tsx New badge component for displaying registration status with color coding
apps/web/src/components/registration-card.tsx Card component for displaying registration summary on user dashboard
apps/web/src/components/registration-block.tsx Block component showing registration details on event pages
apps/web/src/components/controlls/register-event-button.tsx Updates registration button to handle form submission and disabled state
apps/shared/src/registrations/schemas.ts Extends registration schema with event metadata fields
apps/api/src/modules/users/store.ts Adds query to fetch user registrations with joined event data
apps/api/src/modules/users/service.ts Exposes getUserRegistrations service method
apps/api/src/modules/users/route.ts Implements GET /registrations endpoint for authenticated users
apps/api/src/modules/users/route.test.ts Adds comprehensive test coverage for user registrations endpoint
apps/api/src/modules/registration/store.ts Refactors to use shared selection object and adds filtering/pagination support
apps/api/src/modules/registration/service.ts Implements getRegistrationByUser and getRegistrations service methods
apps/api/src/modules/registration/schema.ts Adds query filter schema for paginated registration retrieval
apps/api/src/modules/registration/route.ts Implements GET / and GET /me endpoints for fetching registrations
apps/api/src/modules/registration/route.test.ts Adds test coverage for new registration query endpoints
Comments suppressed due to low confidence (1)

apps/shared/src/registrations/schemas.ts:22

  • The RegistrationResponseSchema is missing the userId field, but the API returns it (as seen in the registrationSelection object in the store). This will cause schema validation to fail when parsing API responses. Add userId: z.string() to the schema.
export const RegistrationResponseSchema = RegistrationContractSchema.extend({
  eventId: z.string(),
  eventTitle: z.string().optional(),
  eventDate: z.iso.datetime(),
  eventLocation: z.string().nullable(),
  status: z.enum(RegistrationStatus),
  createdAt: z.iso.datetime(),
  updatedAt: z.iso.datetime(),
});

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

Comment on lines +43 to +60
server.get("/", async (request, reply) => {
const { sessionClaims } = getAuth(request);
const role = sessionClaims?.metadata?.role;

const params = RegistrationEventIdSchema.parse(request.params);
const filters = RegistrationsQueryFilterSchema.parse(request.query);

const events = await registrationService.getRegistrations({
db: server.db,
filters: {
id: params.eventId,
...filters,
},
role: role ?? null,
});

return reply.status(200).send(events);
});
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

Missing test coverage for the authorization check when a non-committee user tries to access GET /v1/events/:eventId/registrations. This should return 401 Unauthorized but there's no test verifying this behavior.

Copilot uses AI. Check for mistakes.
} catch (err) {
console.error(err)

throw new Error('Failed to load an event')
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The error message "Failed to load an event" is incorrect for a registration creation operation. This should say "Failed to create registration" or similar.

Suggested change
throw new Error('Failed to load an event')
throw new Error('Failed to create registration')

Copilot uses AI. Check for mistakes.
Comment on lines 14 to 21
export const RegistrationResponseSchema = RegistrationContractSchema.extend({
id: z.string(),
eventId: z.string(),
eventTitle: z.string().optional(),
eventDate: z.iso.datetime(),
eventLocation: z.string().nullable(),
status: z.enum(RegistrationStatus),
createdAt: z.iso.datetime(),
updatedAt: z.iso.datetime(),
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The RegistrationResponseSchema is missing the 'id' field that was removed. Registration records should have a unique identifier. If the composite key (userId, eventId) is intended as the identifier, this should be documented, but typically response schemas include an explicit id field for consistency.

Copilot uses AI. Check for mistakes.
})
void queryClient.invalidateQueries({
queryKey: ['registrations'],
})
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

After creating a registration, only queries with the key ['registrations'] are invalidated, but the specific registration query uses ['registrations', eventId]. Consider also invalidating the user registrations query with key ['users', 'registrations'] to ensure the /me page updates correctly after registration.

Suggested change
})
})
void queryClient.invalidateQueries({
queryKey: ['registrations', eventId],
})
void queryClient.invalidateQueries({
queryKey: ['users', 'registrations'],
})

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +26
description: 'Event has been created',
})
void queryClient.invalidateQueries({
queryKey: ['registrations'],
})
},
onError: (error) => {
toast.error('Failed to create event', {
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The error message "Failed to create event" is incorrect for a registration operation. This should say "Failed to create registration" or "Failed to register for event".

Suggested change
description: 'Event has been created',
})
void queryClient.invalidateQueries({
queryKey: ['registrations'],
})
},
onError: (error) => {
toast.error('Failed to create event', {
description: 'Registration has been created',
})
void queryClient.invalidateQueries({
queryKey: ['registrations'],
})
},
onError: (error) => {
toast.error('Failed to create registration', {

Copilot uses AI. Check for mistakes.
} catch (err) {
console.error(err)

throw new Error('Failed to load an event')
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The error message "Failed to load an event" is incorrect for a registration operation. This should say "Failed to load registration" or "Failed to fetch registration".

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +47
.select({
userId: registrationsTable.userId,
eventId: registrationsTable.eventId,
status: registrationsTable.status,
createdAt: registrationsTable.createdAt,
updatedAt: registrationsTable.updatedAt,
eventTitle: eventsTable.title,
eventDate: eventsTable.date,
eventLocation: eventsTable.location,
})
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The selection object for user registrations is duplicated from the registrationSelection object defined in registration/store.ts. Consider importing and reusing the registrationSelection to maintain consistency and avoid duplication.

Copilot uses AI. Check for mistakes.
Comment on lines +62 to +80
server.get("/me", async (request, reply) => {
const { userId, sessionClaims } = getAuth(request);
const role = sessionClaims?.metadata?.role;

if (!userId || !role) {
return reply.status(401).send({ message: "Unauthorised" });
}

const data = RegistrationEventIdSchema.parse(request.params);
const registration = await registrationService.getRegistrationByUser({
db: server.db,
data: {
...data,
userId,
},
});

return registration ? reply.status(200).send(registration) : reply.status(204).send();
});
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

Missing test coverage for the case where a user fetches their own registration but no registration exists (should return 204). Consider adding a test case to verify this behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +21
export const registrationSelection = {
userId: registrationsTable.userId,
eventId: registrationsTable.eventId,
status: registrationsTable.status,
createdAt: registrationsTable.createdAt,
updatedAt: registrationsTable.updatedAt,
eventTitle: eventsTable.title,
eventDate: eventsTable.date,
eventLocation: eventsTable.location,
};
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The registrationSelection object is missing the 'answers' field from RegistrationContractSchema. Registration answers are not being returned in API responses, which means users won't be able to see their submitted form answers. Add answers: registrationsTable.answers to the selection object.

Copilot uses AI. Check for mistakes.

const sizeClasses = {
sm: 'text-[10px] px-2 py-0.5 rounded-sm uppercase tracking-wider',
md: 'text-sm md:text-base px-6.5 py-2 rounded-md',
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

The className 'px-6.5' is not a valid Tailwind CSS class. Standard Tailwind spacing uses integers or fractions (e.g., px-6, px-7, or px-6.5 would need to be defined in the Tailwind config). Consider using px-6 or px-7 instead.

Suggested change
md: 'text-sm md:text-base px-6.5 py-2 rounded-md',
md: 'text-sm md:text-base px-6 py-2 rounded-md',

Copilot uses AI. Check for mistakes.
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