From e33e5a2fcadcbbccb1b0349ec00f12a2b0b17681 Mon Sep 17 00:00:00 2001 From: Alex Zhang Date: Sat, 30 Dec 2023 23:21:29 -0800 Subject: [PATCH 1/7] Initial layout for events page --- src/components/events/EventDisplay/index.tsx | 3 +- src/components/events/EventModal/index.tsx | 2 +- src/lib/utils.ts | 65 +++++++ src/pages/events.tsx | 185 ++++++++++++++++++- src/pages/leaderboard.tsx | 51 +---- src/styles/pages/Home.module.scss | 12 -- src/styles/pages/Home.module.scss.d.ts | 2 - src/styles/pages/events.module.scss | 36 ++++ src/styles/pages/events.module.scss.d.ts | 12 ++ 9 files changed, 301 insertions(+), 67 deletions(-) create mode 100644 src/styles/pages/events.module.scss create mode 100644 src/styles/pages/events.module.scss.d.ts diff --git a/src/components/events/EventDisplay/index.tsx b/src/components/events/EventDisplay/index.tsx index 25e1f2e2..1f7348b6 100644 --- a/src/components/events/EventDisplay/index.tsx +++ b/src/components/events/EventDisplay/index.tsx @@ -8,10 +8,9 @@ interface EventDisplayProps { } const EventDisplay = ({ events, attendances }: EventDisplayProps) => { - const displayedEvents = events.slice(0, 20); return (
- {displayedEvents.map(event => ( + {events.map(event => ( { variant="title/medium" suppressHydrationWarning > - {formatEventDate(start, end)} + {formatEventDate(start, end, true)} {location} diff --git a/src/lib/utils.ts b/src/lib/utils.ts index fa96effa..dabe4294 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -126,3 +126,68 @@ export const formatEventDate = ( export const formatURLEventTitle = (title: string): string => { return encodeURIComponent(title.toLowerCase().trim().replace(/ /g, '-')); }; + +/** Year ACM was founded. */ +const START_YEAR = 2019; +/** Number of seconds in a day. */ +const DAY_SECONDS = 86400; + +/** + * @returns The end of the current academic year. + */ +export const getEndYear = (): number => { + const today = new Date(); + // Arbitrarily start the next academic year in August + return today.getMonth() < 7 ? today.getFullYear() : today.getFullYear() + 1; +}; + +/** + * @returns A list of all years that ACM has existed. + */ +export const getYears = () => { + const endYear = getEndYear(); + const years = []; + for (let year = START_YEAR; year < endYear; year += 1) { + years.unshift({ value: String(year), label: `${year}–${year + 1}` }); + } + return years; +}; + +/** + * Given a sort option, returns the range of times to filter events/attendances by. + * @param sort Either a year (2023, 2019, etc.) or a string option (past-week, all-time, etc.) + * @returns A range of times to filter results by. + */ +export const getDateRange = (sort: string | number) => { + const now = Date.now() / 1000; + let from; + let to; + switch (sort) { + case 'upcoming': { + from = now; + break; + } + case 'past-week': { + from = now - DAY_SECONDS * 7; + break; + } + case 'past-month': { + from = now - DAY_SECONDS * 28; + break; + } + case 'past-year': { + from = now - DAY_SECONDS * 365; + break; + } + case 'all-time': { + break; + } + default: { + const year = +sort; + // Arbitrarily academic years on August 1, which should be during the summer + from = new Date(year, 7, 1).getTime() / 1000; + to = new Date(year + 1, 7, 1).getTime() / 1000; + } + } + return { from, to }; +}; diff --git a/src/pages/events.tsx b/src/pages/events.tsx index 8be8d91d..d5d3ef5b 100644 --- a/src/pages/events.tsx +++ b/src/pages/events.tsx @@ -1,16 +1,187 @@ +import { Dropdown, PaginationControls, Typography } from '@/components/common'; +import EventDisplay from '@/components/events/EventDisplay'; +import { EventAPI } from '@/lib/api'; import withAccessType from '@/lib/hoc/withAccessType'; -import { PermissionService } from '@/lib/services'; -import type { GetServerSideProps, NextPage } from 'next'; +import { CookieService, PermissionService } from '@/lib/services'; +import { PublicAttendance, PublicEvent } from '@/lib/types/apiResponses'; +import { CookieType } from '@/lib/types/enums'; +import { getDateRange, getYears } from '@/lib/utils'; +import styles from '@/styles/pages/events.module.scss'; +import type { GetServerSideProps } from 'next'; +import { useMemo, useState } from 'react'; -const EventsPage: NextPage = () => { - return

Events Page

; +interface EventsPageProps { + events: PublicEvent[]; + attendances: PublicAttendance[]; +} + +interface FilterOptions { + query: string; + communityFilter: string; + dateFilter: string | number; + attendedFilter: string; +} + +const filterEvent = ( + event: PublicEvent, + attendances: PublicAttendance[], + { query, communityFilter, dateFilter, attendedFilter }: FilterOptions +): boolean => { + if (query !== '' && !event.title.toLowerCase().includes(query)) { + return false; + } + if (communityFilter !== 'all' && event.committee.toLowerCase() !== communityFilter) { + return false; + } + const { from, to } = getDateRange(dateFilter); + if (from !== undefined && new Date(event.start) < new Date(from * 1000)) { + return false; + } + if (to !== undefined && new Date(event.end) > new Date(to * 1000)) { + return false; + } + + if (attendedFilter === 'all') { + return true; + } + + const attended = attendances.some(a => a.event.uuid === event.uuid); + if (attendedFilter === 'attended' && !attended) { + return false; + } + if (attendedFilter === 'not-attended' && attended) { + return false; + } + return true; +}; + +const ROWS_PER_PAGE = 25; +const EventsPage = ({ events, attendances }: EventsPageProps) => { + const [page, setPage] = useState(0); + const [communityFilter, setCommunityFilter] = useState('all'); + const [dateFilter, setDateFilter] = useState('upcoming'); + const [attendedFilter, setAttendedFilter] = useState('all'); + const [query, setQuery] = useState(''); + + const years = useMemo(() => getYears(), []); + + const filteredEvents = events.filter(e => + filterEvent(e, attendances, { query, communityFilter, dateFilter, attendedFilter }) + ); + const displayedEvents = filteredEvents.slice(page * ROWS_PER_PAGE, (page + 1) * ROWS_PER_PAGE); + + return ( +
+ Events +
+ { + setQuery(e.currentTarget.value); + setPage(0); + }} + /> +
+ { + setCommunityFilter(v); + setPage(0); + }} + /> +
+ +
+ { + setDateFilter(v); + setPage(0); + }} + /> +
+ +
+ { + setAttendedFilter(v); + setPage(0); + }} + /> +
+
+ + + {filteredEvents.length > 0 && ( + setPage(page)} + pages={Math.ceil(filteredEvents.length / ROWS_PER_PAGE)} + /> + )} +
+ ); }; export default EventsPage; -const getServerSidePropsFunc: GetServerSideProps = async () => ({ - props: {}, -}); +const getServerSidePropsFunc: GetServerSideProps = async ({ req, res }) => { + const authToken = CookieService.getServerCookie(CookieType.ACCESS_TOKEN, { req, res }); + const events = await EventAPI.getAllEvents(); + const attendances = await EventAPI.getAttendancesForUser(authToken); + + const now = new Date(); + const pastEvents: PublicEvent[] = []; + const upcomingEvents: PublicEvent[] = []; + const liveEvents: PublicEvent[] = []; + + events.forEach(e => { + const start = new Date(e.start); + const end = new Date(e.end); + if (end < now) { + pastEvents.push(e); + } else if (start > now) { + upcomingEvents.push(e); + } else { + liveEvents.push(e); + } + }); + + return { props: { events, attendances } }; +}; export const getServerSideProps = withAccessType( getServerSidePropsFunc, diff --git a/src/pages/leaderboard.tsx b/src/pages/leaderboard.tsx index c2b953a0..7c225202 100644 --- a/src/pages/leaderboard.tsx +++ b/src/pages/leaderboard.tsx @@ -7,18 +7,13 @@ import { CookieService, PermissionService } from '@/lib/services'; import { SlidingLeaderboardQueryParams } from '@/lib/types/apiRequests'; import { PrivateProfile, PublicProfile } from '@/lib/types/apiResponses'; import { CookieType } from '@/lib/types/enums'; -import { getProfilePicture, getUserRank } from '@/lib/utils'; +import { getDateRange, getEndYear, getProfilePicture, getUserRank, getYears } from '@/lib/utils'; import MyPositionIcon from '@/public/assets/icons/my-position-icon.svg'; import styles from '@/styles/pages/leaderboard.module.scss'; import { GetServerSideProps } from 'next'; import { useRouter } from 'next/router'; import { useMemo, useState } from 'react'; -/** Year ACM was founded. */ -const START_YEAR = 2019; -/** Number of seconds in a day. */ -const DAY_SECONDS = 86400; - interface Match { index: number; length: number; @@ -31,37 +26,14 @@ function filter(users: T[], query: string): (T & { matc }); } -function getEndYear(): number { - const today = new Date(); - // Arbitrarily start the next academic year in August - return today.getMonth() < 7 ? today.getFullYear() : today.getFullYear() + 1; -} - function getLeaderboardRange(sort: string | number, limit = 0): SlidingLeaderboardQueryParams { const params: SlidingLeaderboardQueryParams = { limit }; - const now = Date.now() / 1000; - switch (sort) { - case 'past-week': { - params.from = now - DAY_SECONDS * 7; - break; - } - case 'past-month': { - params.from = now - DAY_SECONDS * 28; - break; - } - case 'past-year': { - params.from = now - DAY_SECONDS * 365; - break; - } - case 'all-time': { - break; - } - default: { - const year = +sort; - // Arbitrarily academic years on August 1, which should be during the summer - params.from = new Date(year, 7, 1).getTime() / 1000; - params.to = new Date(year + 1, 7, 1).getTime() / 1000; - } + const { from, to } = getDateRange(sort); + if (from !== undefined) { + params.from = from; + } + if (to !== undefined) { + params.to = to; } return params; } @@ -83,14 +55,7 @@ const LeaderboardPage = ({ sort, leaderboard, user: { uuid } }: LeaderboardProps // user presses the button multiple times const [scrollIntoView, setScrollIntoView] = useState(0); - const years = useMemo(() => { - const endYear = getEndYear(); - const years = []; - for (let year = START_YEAR; year < endYear; year += 1) { - years.unshift({ value: String(year), label: `${year}–${year + 1}` }); - } - return years; - }, []); + const years = useMemo(() => getYears(), []); const { allRows, myIndex } = useMemo(() => { const results = leaderboard.map((user, index) => ({ ...user, position: index + 1 })); diff --git a/src/styles/pages/Home.module.scss b/src/styles/pages/Home.module.scss index 54642013..1859b666 100644 --- a/src/styles/pages/Home.module.scss +++ b/src/styles/pages/Home.module.scss @@ -2,16 +2,4 @@ display: flex; flex-direction: column; gap: 3rem; - - .eventDisplay { - display: flex; - flex-direction: column; - gap: 1rem; - - .eventDisplayHeader { - display: flex; - flex-direction: column; - gap: 0.5rem; - } - } } diff --git a/src/styles/pages/Home.module.scss.d.ts b/src/styles/pages/Home.module.scss.d.ts index 0302f70e..190f135c 100644 --- a/src/styles/pages/Home.module.scss.d.ts +++ b/src/styles/pages/Home.module.scss.d.ts @@ -1,6 +1,4 @@ export type Styles = { - eventDisplay: string; - eventDisplayHeader: string; page: string; }; diff --git a/src/styles/pages/events.module.scss b/src/styles/pages/events.module.scss new file mode 100644 index 00000000..bf1e70a8 --- /dev/null +++ b/src/styles/pages/events.module.scss @@ -0,0 +1,36 @@ +.page { + display: flex; + flex-direction: column; + gap: 2rem; + + .controls { + align-items: center; + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 1rem; + + .search { + background: none; + border: 1px solid var(--theme-text-on-background-1); + border-radius: 1rem; + color: inherit; + font-size: 14px; + height: 2rem; + max-width: 18rem; + padding-left: 1.5rem; + padding-right: 0.5rem; + width: 100%; + + &::placeholder { + color: var(--theme-text-on-background-3); + } + } + + .filterOption { + border: 1px solid var(--theme-text-on-background-1); + border-radius: 1rem; + padding: 0.5rem; + } + } +} diff --git a/src/styles/pages/events.module.scss.d.ts b/src/styles/pages/events.module.scss.d.ts new file mode 100644 index 00000000..e67e6d63 --- /dev/null +++ b/src/styles/pages/events.module.scss.d.ts @@ -0,0 +1,12 @@ +export type Styles = { + controls: string; + filterOption: string; + page: string; + search: string; +}; + +export type ClassNames = keyof Styles; + +declare const styles: Styles; + +export default styles; From d0341de57cdd70dd622b59594932ac9368f311af Mon Sep 17 00:00:00 2001 From: Alex Zhang Date: Sat, 30 Dec 2023 23:30:44 -0800 Subject: [PATCH 2/7] messing around with search bar size --- src/styles/pages/events.module.scss | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/styles/pages/events.module.scss b/src/styles/pages/events.module.scss index bf1e70a8..690b771f 100644 --- a/src/styles/pages/events.module.scss +++ b/src/styles/pages/events.module.scss @@ -15,11 +15,10 @@ border: 1px solid var(--theme-text-on-background-1); border-radius: 1rem; color: inherit; - font-size: 14px; - height: 2rem; + font-size: 1.5rem; + font-weight: bold; max-width: 18rem; - padding-left: 1.5rem; - padding-right: 0.5rem; + padding: 0.5rem; width: 100%; &::placeholder { From dcfd0334ea092763de92f07dcb23b0eac9e8e548 Mon Sep 17 00:00:00 2001 From: Alex Zhang Date: Sun, 31 Dec 2023 00:03:24 -0800 Subject: [PATCH 3/7] Styling changes --- src/components/events/EventDisplay/index.tsx | 4 ++++ src/styles/pages/events.module.scss | 7 +++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/events/EventDisplay/index.tsx b/src/components/events/EventDisplay/index.tsx index 1f7348b6..57a002df 100644 --- a/src/components/events/EventDisplay/index.tsx +++ b/src/components/events/EventDisplay/index.tsx @@ -1,3 +1,4 @@ +import { Typography } from '@/components/common'; import EventCard from '@/components/events/EventCard'; import { PublicAttendance, PublicEvent } from '@/lib/types/apiResponses'; import styles from './style.module.scss'; @@ -8,6 +9,9 @@ interface EventDisplayProps { } const EventDisplay = ({ events, attendances }: EventDisplayProps) => { + if (events.length === 0) { + return No events found :(; + } return (
{events.map(event => ( diff --git a/src/styles/pages/events.module.scss b/src/styles/pages/events.module.scss index 690b771f..8d37f182 100644 --- a/src/styles/pages/events.module.scss +++ b/src/styles/pages/events.module.scss @@ -15,10 +15,9 @@ border: 1px solid var(--theme-text-on-background-1); border-radius: 1rem; color: inherit; - font-size: 1.5rem; - font-weight: bold; + font-size: 1.25rem; max-width: 18rem; - padding: 0.5rem; + padding: 0.5rem 1rem; width: 100%; &::placeholder { @@ -29,7 +28,7 @@ .filterOption { border: 1px solid var(--theme-text-on-background-1); border-radius: 1rem; - padding: 0.5rem; + padding: 0.5rem 1rem; } } } From 816716affab9f0aa7fc4824dc7ac16a6fb807647 Mon Sep 17 00:00:00 2001 From: Alex Zhang Date: Sun, 31 Dec 2023 00:39:12 -0800 Subject: [PATCH 4/7] Resize dropdown --- src/pages/events.tsx | 17 ----------------- src/styles/pages/events.module.scss | 4 ++++ 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/pages/events.tsx b/src/pages/events.tsx index d5d3ef5b..30eae6d2 100644 --- a/src/pages/events.tsx +++ b/src/pages/events.tsx @@ -163,23 +163,6 @@ const getServerSidePropsFunc: GetServerSideProps = async ({ req, res }) => { const events = await EventAPI.getAllEvents(); const attendances = await EventAPI.getAttendancesForUser(authToken); - const now = new Date(); - const pastEvents: PublicEvent[] = []; - const upcomingEvents: PublicEvent[] = []; - const liveEvents: PublicEvent[] = []; - - events.forEach(e => { - const start = new Date(e.start); - const end = new Date(e.end); - if (end < now) { - pastEvents.push(e); - } else if (start > now) { - upcomingEvents.push(e); - } else { - liveEvents.push(e); - } - }); - return { props: { events, attendances } }; }; diff --git a/src/styles/pages/events.module.scss b/src/styles/pages/events.module.scss index 8d37f182..1ddf332e 100644 --- a/src/styles/pages/events.module.scss +++ b/src/styles/pages/events.module.scss @@ -29,6 +29,10 @@ border: 1px solid var(--theme-text-on-background-1); border-radius: 1rem; padding: 0.5rem 1rem; + + div > select { + font-size: 1.25rem; + } } } } From d2690b21b0537125b99b5ceafadbd4473ceafa5b Mon Sep 17 00:00:00 2001 From: Alex Zhang Date: Mon, 1 Jan 2024 19:07:35 -0800 Subject: [PATCH 5/7] Address comments --- src/components/events/EventCard/style.module.scss | 4 ++-- src/components/events/index.tsx | 2 ++ src/pages/events.tsx | 12 +++++++----- src/pages/index.tsx | 2 +- src/styles/pages/events.module.scss | 9 ++++++--- 5 files changed, 18 insertions(+), 11 deletions(-) create mode 100644 src/components/events/index.tsx diff --git a/src/components/events/EventCard/style.module.scss b/src/components/events/EventCard/style.module.scss index 39881251..8dfd50cc 100644 --- a/src/components/events/EventCard/style.module.scss +++ b/src/components/events/EventCard/style.module.scss @@ -16,11 +16,11 @@ } .image { + aspect-ratio: 1.778; flex-shrink: 0; - height: 11.25rem; overflow: none; position: relative; - width: 20rem; + width: 100%; } .info { diff --git a/src/components/events/index.tsx b/src/components/events/index.tsx new file mode 100644 index 00000000..18664aff --- /dev/null +++ b/src/components/events/index.tsx @@ -0,0 +1,2 @@ +export { default as EventCarousel } from './EventCarousel'; +export { default as EventDisplay } from './EventDisplay'; diff --git a/src/pages/events.tsx b/src/pages/events.tsx index 30eae6d2..dd336d64 100644 --- a/src/pages/events.tsx +++ b/src/pages/events.tsx @@ -1,9 +1,9 @@ import { Dropdown, PaginationControls, Typography } from '@/components/common'; -import EventDisplay from '@/components/events/EventDisplay'; +import { EventDisplay } from '@/components/events'; import { EventAPI } from '@/lib/api'; import withAccessType from '@/lib/hoc/withAccessType'; import { CookieService, PermissionService } from '@/lib/services'; -import { PublicAttendance, PublicEvent } from '@/lib/types/apiResponses'; +import type { PublicAttendance, PublicEvent } from '@/lib/types/apiResponses'; import { CookieType } from '@/lib/types/enums'; import { getDateRange, getYears } from '@/lib/utils'; import styles from '@/styles/pages/events.module.scss'; @@ -27,12 +27,15 @@ const filterEvent = ( attendances: PublicAttendance[], { query, communityFilter, dateFilter, attendedFilter }: FilterOptions ): boolean => { + // Filter search query if (query !== '' && !event.title.toLowerCase().includes(query)) { return false; } + // Filter by community if (communityFilter !== 'all' && event.committee.toLowerCase() !== communityFilter) { return false; } + // Filter by date const { from, to } = getDateRange(dateFilter); if (from !== undefined && new Date(event.start) < new Date(from * 1000)) { return false; @@ -40,11 +43,10 @@ const filterEvent = ( if (to !== undefined && new Date(event.end) > new Date(to * 1000)) { return false; } - + // Filter by attendance if (attendedFilter === 'all') { return true; } - const attended = attendances.some(a => a.event.uuid === event.uuid); if (attendedFilter === 'attended' && !attended) { return false; @@ -63,7 +65,7 @@ const EventsPage = ({ events, attendances }: EventsPageProps) => { const [attendedFilter, setAttendedFilter] = useState('all'); const [query, setQuery] = useState(''); - const years = useMemo(() => getYears(), []); + const years = useMemo(getYears, []); const filteredEvents = events.filter(e => filterEvent(e, attendances, { query, communityFilter, dateFilter, attendedFilter }) diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 5ecd8fe2..c6338047 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,4 +1,4 @@ -import EventCarousel from '@/components/events/EventCarousel'; +import EventCarousel from '@/components/events'; import { EventAPI } from '@/lib/api'; import withAccessType from '@/lib/hoc/withAccessType'; import { CookieService, PermissionService } from '@/lib/services'; diff --git a/src/styles/pages/events.module.scss b/src/styles/pages/events.module.scss index 1ddf332e..c2b0e3cb 100644 --- a/src/styles/pages/events.module.scss +++ b/src/styles/pages/events.module.scss @@ -1,7 +1,7 @@ .page { display: flex; flex-direction: column; - gap: 2rem; + gap: 1.5rem; .controls { align-items: center; @@ -15,7 +15,8 @@ border: 1px solid var(--theme-text-on-background-1); border-radius: 1rem; color: inherit; - font-size: 1.25rem; + font-size: 1rem; + line-height: 1.25rem; max-width: 18rem; padding: 0.5rem 1rem; width: 100%; @@ -31,7 +32,9 @@ padding: 0.5rem 1rem; div > select { - font-size: 1.25rem; + font-size: 1rem; + font-weight: normal; + line-height: 1.25rem; } } } From bc33ba3c9c18d724364862e0740101b99820e870 Mon Sep 17 00:00:00 2001 From: Alex Zhang Date: Mon, 1 Jan 2024 19:14:24 -0800 Subject: [PATCH 6/7] Add search improvements, fix import --- src/lib/utils.ts | 8 ++++++++ src/pages/events.tsx | 4 ++-- src/pages/index.tsx | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/lib/utils.ts b/src/lib/utils.ts index dabe4294..c9f638c1 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -55,6 +55,14 @@ export const capitalize = (text: string): string => { return text.slice(0, 1).toUpperCase() + text.slice(1).toLowerCase(); }; +/** + * Given text, removes all non alphanumeric characters. + * This makes search terms more lenient. + */ +export const formatSearch = (text: string): string => { + return text.toLowerCase().replace(/[^0-9a-zA-Z]/g, ''); +}; + /** * Helper function to map each user to a numeric value deterministically * TODO: Use the user's UUID to hash to a number since it will never change diff --git a/src/pages/events.tsx b/src/pages/events.tsx index dd336d64..3c49f923 100644 --- a/src/pages/events.tsx +++ b/src/pages/events.tsx @@ -5,7 +5,7 @@ import withAccessType from '@/lib/hoc/withAccessType'; import { CookieService, PermissionService } from '@/lib/services'; import type { PublicAttendance, PublicEvent } from '@/lib/types/apiResponses'; import { CookieType } from '@/lib/types/enums'; -import { getDateRange, getYears } from '@/lib/utils'; +import { formatSearch, getDateRange, getYears } from '@/lib/utils'; import styles from '@/styles/pages/events.module.scss'; import type { GetServerSideProps } from 'next'; import { useMemo, useState } from 'react'; @@ -28,7 +28,7 @@ const filterEvent = ( { query, communityFilter, dateFilter, attendedFilter }: FilterOptions ): boolean => { // Filter search query - if (query !== '' && !event.title.toLowerCase().includes(query)) { + if (query !== '' && !formatSearch(event.title).includes(formatSearch(query))) { return false; } // Filter by community diff --git a/src/pages/index.tsx b/src/pages/index.tsx index c6338047..3e45a8d8 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,4 +1,4 @@ -import EventCarousel from '@/components/events'; +import { EventCarousel } from '@/components/events'; import { EventAPI } from '@/lib/api'; import withAccessType from '@/lib/hoc/withAccessType'; import { CookieService, PermissionService } from '@/lib/services'; From 79e1e03bae83b54f48091773a86a44b2358df131 Mon Sep 17 00:00:00 2001 From: Alex Zhang Date: Mon, 1 Jan 2024 19:16:44 -0800 Subject: [PATCH 7/7] Small cleanup --- src/pages/leaderboard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/leaderboard.tsx b/src/pages/leaderboard.tsx index 7c225202..592b6bb1 100644 --- a/src/pages/leaderboard.tsx +++ b/src/pages/leaderboard.tsx @@ -55,7 +55,7 @@ const LeaderboardPage = ({ sort, leaderboard, user: { uuid } }: LeaderboardProps // user presses the button multiple times const [scrollIntoView, setScrollIntoView] = useState(0); - const years = useMemo(() => getYears(), []); + const years = useMemo(getYears, []); const { allRows, myIndex } = useMemo(() => { const results = leaderboard.map((user, index) => ({ ...user, position: index + 1 }));