-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
805-frontend-display-all-events-to-admin (#814)
* 805-frontend-display-all-events-to-admin Initial commit * Created EventService.ts for fetching all events * Add all files for Admin All Events view Needs refactoring... * Fetch events in WrappedAdminEventView * Center event items * Create variant for EventPreview * Both regular and admin card * Regular is a thicker padding * Admin is a smaller padding * Remove unneeded test file * Document viewButtonText in EventPreview * Update comment for AdminEventView * Also remove `relative` from ReusableButtons as already exists * Reset button changes * Remove code related to EventDetailed
- Loading branch information
1 parent
30a5a47
commit 13817ab
Showing
8 changed files
with
403 additions
and
19 deletions.
There are no files selected for viewing
59 changes: 59 additions & 0 deletions
59
client/src/components/composite/Admin/AdminEventView/AdminAllEvents/AdminAllEvents.story.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import type { Meta, StoryObj } from "@storybook/react" | ||
import AdminAllEvents from "./AdminAllEvents" | ||
import { Timestamp } from "firebase/firestore" | ||
|
||
const meta: Meta<typeof AdminAllEvents> = { | ||
component: AdminAllEvents | ||
} | ||
|
||
export default meta | ||
type Story = StoryObj<typeof meta> | ||
|
||
const earlierStartDate = Timestamp.fromDate(new Date(2023, 1, 1)) | ||
const startDate = Timestamp.fromDate(new Date(2024, 1, 1)) | ||
|
||
export const DefaultEventsPage: Story = { | ||
args: { | ||
rawEvents: [ | ||
{ | ||
id: "1", | ||
title: "UASC New event 1", | ||
location: "UASC", | ||
physical_start_date: earlierStartDate, | ||
sign_up_start_date: earlierStartDate, | ||
sign_up_end_date: earlierStartDate, | ||
google_forms_link: "https://google.com", | ||
description: | ||
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Reprehenderit adipisci repellat perferendis. Quia ipsum laborum est, veniam accusamus voluptas praesentium, odio perspiciatis blanditiis sequi dignissimos unde. Natus delectus nihil cum." | ||
}, | ||
{ | ||
id: "2", | ||
title: "UASC New event 2", | ||
location: "UASC", | ||
physical_start_date: earlierStartDate, | ||
sign_up_start_date: startDate, | ||
sign_up_end_date: earlierStartDate, | ||
description: | ||
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Reprehenderit adipisci repellat perferendis. Quia ipsum laborum est, veniam accusamus voluptas praesentium, odio perspiciatis blanditiis sequi dignissimos unde. Natus delectus nihil cum." | ||
}, | ||
{ | ||
id: "3", | ||
title: "UASC New Event 3", | ||
location: "UASC", | ||
physical_start_date: earlierStartDate, | ||
sign_up_start_date: startDate, | ||
sign_up_end_date: earlierStartDate, | ||
description: | ||
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Reprehenderit adipisci repellat perferendis. Quia ipsum laborum est, veniam accusamus voluptas praesentium, odio perspiciatis blanditiis sequi dignissimos unde. Natus delectus nihil cum." | ||
} | ||
] | ||
}, | ||
tags: ["autodocs"] | ||
} | ||
|
||
export const EmptyEventsPage: Story = { | ||
args: { | ||
rawEvents: [] | ||
}, | ||
tags: ["autodocs"] | ||
} |
190 changes: 190 additions & 0 deletions
190
client/src/components/composite/Admin/AdminEventView/AdminAllEvents/AdminAllEvents.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
import EventsCardPreview, { | ||
IEventsCardPreview | ||
} from "@/components/generic/Event/EventPreview/EventPreview" | ||
import { DateUtils } from "@/components/utils/DateUtils" | ||
import { Event } from "@/models/Events" | ||
import { useCallback, useMemo, useState } from "react" | ||
import { | ||
EventDateComparisons, | ||
EventRenderingUtils | ||
} from "@/components/generic/Event/EventUtils" | ||
import Button from "@/components/generic/FigmaButtons/FigmaButton" | ||
import Loader from "@/components/generic/SuspenseComponent/Loader" | ||
|
||
/** | ||
* Interface representing the properties of the Events Page. | ||
*/ | ||
interface IAdminAllEvents { | ||
/** | ||
* A list of _all_ {@link Event}s which should either be mocked | ||
* or fetched from the backend. **NO** pre-processing should be | ||
* performed on this list as it will be further mutated in the | ||
* {@link EventsPage} component. | ||
*/ | ||
rawEvents?: Event[] | ||
|
||
/** | ||
* Indicates whether the events are currently being loaded. | ||
*/ | ||
isLoading?: boolean | ||
|
||
/** | ||
* Indicates whether there are more events to be fetched. | ||
*/ | ||
hasMoreEvents?: boolean | ||
|
||
/** | ||
* Function to fetch more events. | ||
*/ | ||
fetchMoreEvents?: () => void | ||
|
||
/** | ||
* The ID of the preselected event. | ||
*/ | ||
preselectedEventId?: string | ||
|
||
/** | ||
* Callback function to handle changes to the selected event ID. | ||
* @param id - The new selected event ID. | ||
*/ | ||
onSelectedEventIdChange?: (id?: string) => void | ||
} | ||
|
||
/** | ||
* Helper type to split the raw events into upcoming and past ones, | ||
* this is important as they need to be sorted differently | ||
*/ | ||
interface EventList { | ||
upcomingAndCurrentEvents: Event[] | ||
pastEvents: Event[] | ||
} | ||
|
||
/** | ||
* Used to handle all _presentation_ logic conerning the evnts | ||
* | ||
* - **Do not make any network requests in this component, the data should | ||
* be fetched seperately and passed in as {@link rawEvents}** | ||
* - String operations are ideally done in {@link EventMessages} | ||
* - Complex date comparisons should also be abstracted away into {@link EventDateComparisons} | ||
*/ | ||
const AdminAllEvents = ({ | ||
rawEvents = [], | ||
hasMoreEvents, | ||
isLoading, | ||
fetchMoreEvents, | ||
preselectedEventId, | ||
onSelectedEventIdChange | ||
}: IAdminAllEvents) => { | ||
const [selectedEventId, setSelectedEventId] = useState<string | undefined>( | ||
preselectedEventId | ||
) | ||
|
||
const eventSelectionHandler = useCallback( | ||
(id?: string) => { | ||
setSelectedEventId(id) | ||
onSelectedEventIdChange?.(id) | ||
}, | ||
[setSelectedEventId, onSelectedEventIdChange] | ||
) | ||
|
||
/** | ||
* Partitions of the array that allow us to individually process the ongoing events | ||
*/ | ||
const eventList = useMemo(() => { | ||
return rawEvents.reduce( | ||
(buf: EventList, event) => { | ||
const { physical_start_date, physical_end_date } = event | ||
if ( | ||
EventDateComparisons.isPastEvent( | ||
new Date(DateUtils.timestampMilliseconds(physical_start_date)), | ||
physical_end_date && | ||
new Date(DateUtils.timestampMilliseconds(physical_end_date)) | ||
) | ||
) { | ||
buf.pastEvents.push(event) | ||
} else { | ||
buf.upcomingAndCurrentEvents.push(event) | ||
} | ||
|
||
/** | ||
* Start dates ascending for upcoming and current events | ||
*/ | ||
buf.upcomingAndCurrentEvents.sort( | ||
( | ||
{ physical_start_date: startDate1 }, | ||
{ physical_start_date: startDate2 } | ||
) => | ||
DateUtils.timestampMilliseconds(startDate1) - | ||
DateUtils.timestampMilliseconds(startDate2) | ||
) | ||
|
||
return buf | ||
}, | ||
{ upcomingAndCurrentEvents: [], pastEvents: [] } | ||
) | ||
}, [rawEvents]) | ||
|
||
/** | ||
* Detailed view of the event | ||
*/ | ||
const previewCurrentEvents: IEventsCardPreview[] = | ||
eventList.upcomingAndCurrentEvents?.map((event) => { | ||
return EventRenderingUtils.previewTransformer( | ||
event, | ||
eventSelectionHandler, | ||
"edit event", | ||
"admin" | ||
) | ||
}) || [] | ||
|
||
const previewPastEvents: IEventsCardPreview[] = | ||
eventList.pastEvents?.map((event) => { | ||
return EventRenderingUtils.previewTransformer( | ||
event, | ||
eventSelectionHandler, | ||
"edit event", | ||
"admin" | ||
) | ||
}) || [] | ||
|
||
return ( | ||
<> | ||
<div className={`flex w-full max-w-[1000px] flex-col gap-2`}> | ||
{selectedEventId ? null : ( | ||
<> | ||
{isLoading ? ( | ||
<Loader /> | ||
) : ( | ||
<h5 className="text-dark-blue-100 font-bold uppercase"> | ||
{rawEvents.length > 0 ? ( | ||
<>Upcoming Events</> | ||
) : ( | ||
<>No events found!</> | ||
)} | ||
</h5> | ||
)} | ||
{previewCurrentEvents.map((event) => ( | ||
<EventsCardPreview key={event.title} {...event} /> | ||
))} | ||
|
||
{previewPastEvents.map((event) => ( | ||
<EventsCardPreview key={event.title} {...event} /> | ||
))} | ||
</> | ||
)} | ||
|
||
{hasMoreEvents && !selectedEventId && ( | ||
<Button | ||
variant="default" | ||
onClick={fetchMoreEvents} | ||
disabled={isLoading} | ||
> | ||
Load More | ||
</Button> | ||
)} | ||
</div> | ||
</> | ||
) | ||
} | ||
|
||
export default AdminAllEvents |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.