Skip to content

Commit

Permalink
Merge pull request #225 from UTDNebula/JUP-47-improve-events-page
Browse files Browse the repository at this point in the history
JUP-47: improve events page
  • Loading branch information
nl32 authored Aug 27, 2024
2 parents 049d853 + 1ab87bb commit d71c990
Show file tree
Hide file tree
Showing 15 changed files with 522 additions and 582 deletions.
333 changes: 281 additions & 52 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@
"next": "^14.2.2",
"next-auth": "^4.23.0",
"postgres": "^3.3.5",
"react": "18.2.0",
"react": "^18.2.0",
"react-day-picker": "^8.9.1",
"react-dom": "18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.48.2",
"superjson": "^1.13.1",
"zod": "^3.22.4"
Expand All @@ -49,8 +49,8 @@
"@types/eslint": "^8.44.2",
"@types/jest": "^29.5.5",
"@types/node": "^18.16.0",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"@types/react": "^18.2.79",
"@types/react-dom": "^18.2.25",
"@typescript-eslint/eslint-plugin": "^6.3.0",
"@typescript-eslint/parser": "^6.3.0",
"autoprefixer": "^10.4.14",
Expand All @@ -59,7 +59,7 @@
"dotenv-cli": "^7.3.0",
"drizzle-kit": "^0.19.13",
"eslint": "^8.47.0",
"eslint-config-next": "^13.5.4",
"eslint-config-next": "^14.2.1",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-react": "^7.29.4",
Expand Down
80 changes: 19 additions & 61 deletions src/app/events/eventView.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,33 @@
'use server';
import { GridIcon, ListIcon } from '@src/icons/Icons';
import EventCard from '@src/components/events/EventCard';
import EventSidebar from '@src/components/events/EventSidebar';
import { type RouterOutputs } from '@src/trpc/shared';
import Link from 'next/link';
'use client';
import DateBrowser from '@src/components/events/DateBrowser';
import { type eventParamsSchema } from '@src/utils/eventFilter';
import useSyncedSearchParams from '@src/utils/useSyncedSearchParams';
import { type ReactNode } from 'react';
type Props = {
events: RouterOutputs['event']['findByFilters']['events'];
params: Record<string, string | string[] | undefined>;
children: ReactNode;
searchParams: eventParamsSchema;
};

const EventView = ({ events, params }: Props) => {
const view = (params?.view ?? 'list') as 'list' | 'grid';

const EventView = ({ children, searchParams }: Props) => {
const [params, setParams] = useSyncedSearchParams(searchParams, '/events');
return (
<div className="w-full px-6">
<div className="flex flex-col pt-4 sm:flex-row sm:pb-12 md:pr-7.5">
<h1 className="text-left text-2xl font-bold text-[#4D5E80]">Events</h1>
<div className="relative z-0 hidden flex-row gap-x-16 md:ml-auto md:flex">
<Link
className={`z-20 flex flex-row items-center gap-x-4 ${
view === 'list'
? ' -mr-7.5 rounded-full bg-white px-7.5 py-2.5'
: ''
}`}
href={{
pathname: '/events',
query: {
...params,
view: 'list',
},
}}
>
<div className="h-7.5 w-7.5">
<ListIcon />
</div>
<p className="text-sm font-bold text-blue-primary">List view</p>
</Link>
<Link
className={`z-20 flex flex-row items-center gap-x-4 ${
view == 'grid'
? '-ml-7.5 rounded-full bg-white px-7.5 py-2.5'
: 'mr-7.5'
}`}
href={{
pathname: '/events',
query: {
...params,
view: 'grid',
},
}}
>
<div className="h-7.5 w-7.5">
<GridIcon />
</div>
<p className="text-sm font-bold text-blue-primary">Grid view</p>
</Link>
<div className="flex flex-col pt-4 md:flex-row md:items-end md:pb-12 md:pr-7.5">
<h1 className="h-min align-middle text-2xl font-bold text-[#4D5E80]">
Events
</h1>
<div className="relative z-0 mt-2.5 flex flex-row justify-center gap-x-16 md:ml-auto md:mt-0">
<DateBrowser filterState={params} setParams={setParams} />
</div>
</div>
<div className="container flex w-full flex-col overflow-x-clip sm:flex-row sm:space-x-7.5">
<EventSidebar />
<div className="container flex w-full flex-col overflow-x-clip sm:flex-row sm:space-x-7.5 ">
<div
data-view={view}
data-view={'list'}
className={
view === 'list'
? 'group flex flex-col space-y-7.5 pt-10 sm:justify-start'
: 'group flex flex-wrap justify-center gap-x-10 gap-y-7.5 pt-10 sm:justify-start'
'md:items-normal group flex w-full flex-col items-center space-y-7.5 pt-10'
}
>
{events.map((event) => {
return <EventCard key={event.id} event={event} />;
})}
{children}
</div>
</div>
</div>
Expand Down
72 changes: 15 additions & 57 deletions src/app/events/page.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
import { EventHeader } from '@src/components/BaseHeader';
import { type filterState } from '@src/components/events/EventSidebar';
import { api } from '@src/trpc/server';
import { type z } from 'zod';
import { type findByFilterSchema } from '@src/server/api/routers/event';
import EventView from './eventView';
import { type Metadata } from 'next';
import { eventParamsSchema } from '@src/utils/eventFilter';
import EventCard from '@src/components/events/EventCard';

function getStartTime(
filterState: filterState,
): z.infer<typeof findByFilterSchema>['startTime'] {
switch (filterState.filter) {
case 'Upcoming Events':
return { type: 'now' };
case 'Last weeks events':
return { type: 'distance', options: { days: -7 } };
case 'Last month events':
return { type: 'distance', options: { days: -30 } };
case 'pick':
return filterState.date
? { type: 'range', options: filterState.date }
: { type: 'now' };
}
}
export const metadata: Metadata = {
title: 'Events - Jupiter',
description: 'Get connected on campus.',
Expand All @@ -33,48 +16,23 @@ export const metadata: Metadata = {
description: 'Get connected on campus.',
},
};
type searchPams = Partial<
Omit<filterState, 'date' | 'clubs'> & {
date: string | string[] | undefined;
clubs: string | string[] | undefined;
view: 'list' | 'grid' | undefined;
}
>;
const Events = async ({ searchParams }: { searchParams: searchPams }) => {
const filters = {
filter: searchParams.filter ?? 'Upcoming Events',
date:
searchParams.filter === 'pick'
? searchParams.date
? Array.isArray(searchParams.date)
? {
from: searchParams.date[0]
? new Date(Number.parseInt(searchParams.date[0]))
: undefined,
to: searchParams.date[1]
? new Date(Number.parseInt(searchParams.date[1]))
: undefined,
}
: { from: new Date(Number.parseInt(searchParams.date)) }
: undefined
: undefined,
clubs: searchParams.clubs
? Array.isArray(searchParams.clubs)
? searchParams.clubs
: [searchParams.clubs]
: [],
order: searchParams.order ?? 'soon',
types: searchParams.types ?? [],
};
const { events } = await api.event.findByFilters({
startTime: getStartTime(filters),
club: filters.clubs,
order: filters.order,
const Events = async ({
searchParams,
}: {
searchParams: (typeof eventParamsSchema)['_input'];
}) => {
const parsed = eventParamsSchema.parse(searchParams);
const { events } = await api.event.findByDate({
date: parsed.date,
});
return (
<main className="pb-10 md:pl-72">
<EventHeader />
<EventView params={searchParams} events={events} />
<EventView searchParams={parsed}>
{events.map((event) => {
return <EventCard key={event.id} event={event} />;
})}
</EventView>
</main>
);
};
Expand Down
2 changes: 2 additions & 0 deletions src/components/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ type EventClubSearchBarProps = {
export const EventClubSearchBar = ({ addClub }: EventClubSearchBarProps) => {
const [search, setSearch] = useState('');
const [res, setRes] = useState<Club[]>([]);
const utils = api.useUtils();
const clubQuery = api.club.byName.useQuery(
{ name: search },
{
Expand All @@ -152,6 +153,7 @@ export const EventClubSearchBar = ({ addClub }: EventClubSearchBarProps) => {
value={search}
searchResults={res}
onClick={(club) => {
void utils.club.byId.prefetch({ id: club.id });
addClub(club.id);
setSearch('');
}}
Expand Down
69 changes: 69 additions & 0 deletions src/components/events/DateBrowser.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
'use client';

import 'react-day-picker/dist/style.css';
import { LeftArrowIcon, RightArrowIcon } from '@src/icons/Icons';
import { DayPicker, useInput } from 'react-day-picker';
import {
Popover,
PopoverClose,
PopoverContent,
PopoverPortal,
PopoverTrigger,
} from '@radix-ui/react-popover';
import { addDays, subDays } from 'date-fns';
import { useEffect } from 'react';
import { type eventParamsSchema } from '@src/utils/eventFilter';
import { type useSyncedSearchParamsDispatch } from '@src/utils/useSyncedSearchParams';
type DateBrowserProps = {
filterState: eventParamsSchema;
setParams: useSyncedSearchParamsDispatch<eventParamsSchema>;
};
const DateBrowser = ({ filterState, setParams }: DateBrowserProps) => {
const { inputProps, dayPickerProps, setSelected } = useInput({
defaultSelected: filterState.date,
});
useEffect(() => {
if (dayPickerProps.selected != undefined) {
setParams({ date: dayPickerProps.selected });
}
}, [dayPickerProps.selected]);
return (
<div className="flex w-full flex-row justify-between rounded-3xl bg-white px-5 py-2.5 align-middle shadow-md md:w-fit">
{/* eslint-disable-next-line @typescript-eslint/no-misused-promises */}
<button
onClick={() => {
setSelected(subDays(dayPickerProps.selected!, 1));
}}
aria-label="back one day"
type="submit"
>
<div>
<LeftArrowIcon fill="fill-black" />
</div>
</button>
<Popover defaultOpen={false}>
<PopoverTrigger>
<input name="date" {...inputProps} />
</PopoverTrigger>
<PopoverPortal>
<PopoverContent className="flex items-center rounded-lg bg-white p-2 shadow-md">
<DayPicker mode="default" {...dayPickerProps} />
<PopoverClose className="h-5 w-5 text-blue-primary" />
</PopoverContent>
</PopoverPortal>
</Popover>
<button
onClick={() => {
setSelected(addDays(dayPickerProps.selected!, 1));
}}
aria-label="forward one day"
type="submit"
>
<div>
<RightArrowIcon fill="fill-black" />
</div>
</button>
</div>
);
};
export default DateBrowser;
18 changes: 0 additions & 18 deletions src/components/events/DatePopover.tsx

This file was deleted.

6 changes: 5 additions & 1 deletion src/components/events/EventCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ import { format, isSameDay } from 'date-fns';
import Image from 'next/image';
import Link from 'next/link';
import { MoreIcon } from '../../icons/Icons';
import EventTimeAlert from './EventTimeAlert';
import { type RouterOutputs } from '@src/trpc/shared';
import EventLikeButton from '../EventLikeButton';
import { getServerAuthSession } from '@src/server/auth';
import dynamic from 'next/dynamic';

const EventTimeAlert = dynamic(() => import('./EventTimeAlert'), {
ssr: false,
});

type EventCardProps = {
event: RouterOutputs['event']['findByFilters']['events'][number];
Expand Down
Loading

0 comments on commit d71c990

Please sign in to comment.