Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backend create endpoint for admin to create event and also to fetch all events #785

Merged
101 changes: 101 additions & 0 deletions client/src/models/__generated__/schema.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions server/src/data-layer/models/firebase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,26 @@ export interface Event {
* Use the same start and end date to indicate a 1 day signup period.
*/
start_date: Timestamp

/**
* The signup period end date.
* Note that this date is in UTC time.
*/
end_date: Timestamp

/**
* Event start date for the event i.e the day members should meet at shads,
* **NOT** the signups, refer to {@link start_date} for signup start
*/
physical_start_date: Timestamp

/**
* Event end time for the event i.e the last day members will be at the lodge,
* is optionial in case of one day events. **NOT** the signups, refer to
* {@link end_date} for signup end date
*/
physical_end_date?: Timestamp

/**
* Max number of attendees at this event, left as optional for uncapped
* @example 30
Expand Down
1 change: 1 addition & 0 deletions server/src/data-layer/services/BookingHistoryService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class BookingHistoryService {
PaginatedFirebaseResponse<DocumentDataWithUid<BookingHistoryEvent>>
> {
const res = await db.bookingHistory
// TODO: properly make this descending
.orderBy("timestamp")
.startAfter(startAfter || 0)
.limit(limit)
Expand Down
34 changes: 34 additions & 0 deletions server/src/data-layer/services/EventService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,31 @@ const endDate = new Date(2024, 1, 2)
const startTimestamp = dateToFirestoreTimeStamp(startDate)
const endTimestamp = dateToFirestoreTimeStamp(endDate)

const laterStartDate = dateToFirestoreTimeStamp(new Date(2024, 2, 2))

const event1: Event = {
title: "UASC new event",
description: "Grand opening of the website.",
location: "Virtual pizza event",
physical_start_date: startTimestamp,
start_date: startTimestamp,
end_date: endTimestamp
}
const event2: Event = {
title: "Snowboard racing",
description: "Race and see who's the fastest!",
location: "Snowsport club",
physical_start_date: startTimestamp,
start_date: startTimestamp,
end_date: endTimestamp
}
const now = new Date(Date.now())
const futureEvent: Event = {
title: "Scheduled event",
location: "Future event",
physical_start_date: Timestamp.fromDate(
new Date(now.getUTCFullYear() + 1, 1, 1)
),
start_date: Timestamp.fromDate(new Date(now.getUTCFullYear() + 1, 1, 1)),
end_date: Timestamp.fromDate(new Date(now.getUTCFullYear() + 1, 1, 1))
}
Expand All @@ -57,6 +64,33 @@ describe("EventService integration tests", () => {
await cleanFirestore()
})

it("Should be able to fetch the latest X events (based on when the event actually starts), descending", async () => {
const { id: idEarly } = await eventService.createEvent(event1)
const { id: idLater } = await eventService.createEvent({
...event1,
physical_start_date: laterStartDate
})

const page1Events = await eventService.getAllEvents(1)
expect(page1Events.events).toHaveLength(1)
expect(
page1Events.events.some((event) => event.id === idLater)
).toBeTruthy()

expect(page1Events.nextCursor).toBeDefined()

let snapshot
if (page1Events.nextCursor) {
snapshot = await eventService.getEventSnapshot(page1Events.nextCursor)
}

const page2Events = await eventService.getAllEvents(1, snapshot)
expect(page2Events.events).toHaveLength(1)
expect(
page2Events.events.some((event) => event.id === idEarly)
).toBeTruthy()
})

it("Should be able to add an event", async () => {
const newEvent = await eventService.createEvent(event1)

Expand Down
45 changes: 45 additions & 0 deletions server/src/data-layer/services/EventService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,51 @@ class EventService {
.doc(reservationId)
.delete()
}

/**
* Utility method for getting the snapshot of a document
*
* @param id the document id of the event to check, likely coming from a pagination cursor
*/
public async getEventSnapshot(id: string) {
return await FirestoreCollections.events.doc(id).get()
}

/**
* Returns a list of the latest events. Note that "latest" means events with the latest start date.
*
* @param limit how many events to fetch
* @param startAfter snapshot of document which was the last cursor - should
* fetch using the helper defined as {@link getEventSnapshot}
* @returns an object providing the id of the next snapshot and list of events
*/
public async getAllEvents(
limit: number,
startAfter?: FirebaseFirestore.DocumentSnapshot<
Event,
FirebaseFirestore.DocumentData
>
) {
let query = FirestoreCollections.events
// Start at the largest (latest) date
.orderBy("physical_start_date", "desc")
.limit(limit)

if (startAfter) {
query = query.startAfter(startAfter)
}

const res = await query.get()

const events = res.docs.map((event) => {
return { ...event.data(), id: event.id }
})

return {
events,
nextCursor: res.docs[res.docs.length - 1]?.id || undefined
}
}
}

export default EventService
Loading
Loading