Skip to content

Commit

Permalink
feat: fetch accepted events and style upcoming events page (#14)
Browse files Browse the repository at this point in the history
* Created EventListingCard & styled webpage

* fixed ESLint error

* created separate styling file for event card

* created event display page

* added menu icon, changed some styling

---------

Co-authored-by: Celine Ji-Won Choi <[email protected]>
  • Loading branch information
aidenm1 and celinechoiii authored Oct 31, 2024
1 parent 7ba463c commit 3296bd8
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 38 deletions.
33 changes: 31 additions & 2 deletions api/supabase/queries/events.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,45 @@
import { UUID } from 'crypto';
import supabase from '../createClient';

export async function fetchAllEvents() {
const { data, error } = await supabase.from('events').select('*');

if (error) {
console.error('An error occurred trying to read events:', error);
return null;
throw error;
}

return data;
}

export async function fetchAcceptedEventsByVolunteer(volunteer_id: UUID) {
const { data, error } = await supabase
.from('event_signups')
.select('*')
.eq('user_id', volunteer_id)
.eq('is_accepted', true);

if (error) {
throw error;
}
if (!data || data.length === 0) {
//No accepted events for volunteer found
return [];
}

const eventIDs = data.map(data => data.event_id);

const { data: events, error: eventsError } = await supabase
.from('events')
.select('*')
.in('event_id', eventIDs);

if (eventsError) {
throw eventsError;
}

return events;
}

// fetches all events that have event_status = 'Active'
export async function fetchAllActiveEvents() {
const { data, error } = await supabase
Expand Down
41 changes: 41 additions & 0 deletions app/events/page.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use client';

import NextImage from 'next/image';
import styled from 'styled-components';
import COLORS from '@/styles/colors';
import { H3, H6 } from '@/styles/text';

export const Image = styled(NextImage)`
width: 1.5rem;
height: 1.5rem;
margin: 1rem;
`;

export const Page = styled.main`
background-color: ${COLORS.gray1};
flex-direction: column;
min-width: 100%;
min-height: 100svh;
overflow: hidden;
`;

export const AllEventsHolder = styled.main`
padding-left: 1.5rem;
padding-right: 1.5rem;
display: flex;
flex-direction: column;
gap: 1.5rem;
`;

export const Title = styled(H3)`
font-style: normal;
line-height: normal;
`;

export const MonthYear = styled(H6)`
font-style: normal;
line-height: normal;
gap: 1.5rem;
display: flex;
margin-top: 1.25rem;
`;
96 changes: 62 additions & 34 deletions app/events/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
'use client';

import React, { useEffect, useState } from 'react';
import { fetchAllEvents } from '@/api/supabase/queries/events';
import MyEventCard from '@/components/MyEventCard/MyEventCard';
import Menu from '@/public/images/ic_baseline-menu.svg';
import { Event } from '@/types/schema';
import { fetchAllEvents } from '../../api/supabase/queries/events';
import * as styles from './page.style';

export default function Page() {
type GroupedEvents = {
[monthYear: string]: Event[]; // Each key is a "Month Year" string, and the value is an array of Events
};

export default function EventPage() {
const [data, setData] = useState<Event[]>([]);

useEffect(() => {
Expand All @@ -13,38 +20,59 @@ export default function Page() {
});
}, []);

const groupEventsByMonth = (events: Event[]) => {
return events.reduce((acc: GroupedEvents, event) => {
const eventDate = new Date(event.start_date_time); // Assumes `date` field is in the event object
const monthYear = eventDate.toLocaleString('default', {
month: 'long',
year: 'numeric',
});

if (!acc[monthYear]) {
acc[monthYear] = [];
}
acc[monthYear].push(event);
return acc;
}, {} as GroupedEvents);
};

const eventsByMonth = groupEventsByMonth(data);

// Sort the events by month
const sortedEntries = Object.entries(eventsByMonth).sort((a, b) => {
const dateA = new Date(a[0]); // Month Year string from a
const dateB = new Date(b[0]); // Month Year string from b
return dateA.getTime() - dateB.getTime(); // Compare timestamps
});

// Sort events within each month by their start date
sortedEntries.forEach(([, events]) => {
events.sort((a, b) => {
return (
new Date(a.start_date_time).getTime() -
new Date(b.start_date_time).getTime()
);
});
});

return (
<div>
<table>
<thead>
<tr>
<th>event_id</th>
<th>facility_id</th>
<th>start_date_time</th>
<th>end_date_time</th>
<th>performance_type</th>
<th>genre</th>
<th>needs_host</th>
<th>performer_type</th>
<th>event_status</th>
</tr>
</thead>
<tbody>
{data.map(d => (
<tr key={d.event_id}>
<td>{d.event_id}</td>
<td>{d.facility_id}</td>
<td>{d.start_date_time}</td>
<td>{d.end_date_time}</td>
<td>{d.performance_type}</td>
<td>{d.genre}</td>
<td>{d.needs_host}</td>
<td>{d.performer_type}</td>
<td>{d.event_status}</td>
</tr>
))}
</tbody>
</table>
</div>
<styles.Page>
<styles.Image src={Menu} alt="Back icon" />
<styles.AllEventsHolder>
<styles.Title $fontWeight="500" $color="#000" $align="left">
Upcoming Events
</styles.Title>
{sortedEntries.map(([month, events]) => (
<div key={month}>
<styles.MonthYear $fontWeight="500" $color="#000" $align="left">
{month}
</styles.MonthYear>
{events.map(event => (
<MyEventCard key={event.event_id} {...event} />
))}
</div>
))}
</styles.AllEventsHolder>
</styles.Page>
);
}
Binary file added assets/images/bp-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
69 changes: 69 additions & 0 deletions components/MyEventCard/MyEventCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from 'react';
import BPLogo from '@/assets/images/bp-logo.png';
import COLORS from '@/styles/colors';
import { Event } from '@/types/schema';
import * as styles from './style';

export default function MyEventCard(eventData: Event) {
const eventStart = new Date(eventData.start_date_time);
const eventEnd = new Date(eventData.end_date_time);

// function to remove 00 from time if time is on the hour, ex: 4:00 PM -> 4 PM
const formatTime = (date: Date) => {
const minutes = date.getMinutes();

return minutes === 0
? date.toLocaleTimeString([], { hour: 'numeric', hour12: true })
: date.toLocaleTimeString([], {
hour: 'numeric',
minute: '2-digit',
hour12: true,
});
};

const startTime = formatTime(eventStart);
const endTime = formatTime(eventEnd);

const monthNames = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
];
const monthText = monthNames[eventStart.getMonth()];

return (
<styles.EventContainer>
<styles.EventCardContainer>
<styles.BPImage src={BPLogo} alt="Blueprint Logo" />
<div>
<styles.TimeText $fontWeight="400" $color="#000" $align="left">
{monthText} {eventStart.getDate()}, {startTime} - {endTime}
</styles.TimeText>
<styles.EventDescriptionText
$fontWeight="500"
$color="#000"
$align="left"
>
placeholder
</styles.EventDescriptionText>
<styles.LocationText
$fontWeight="400"
$color={COLORS.gray10}
$align="left"
>
placeholder
</styles.LocationText>
</div>
</styles.EventCardContainer>
</styles.EventContainer>
);
}
45 changes: 45 additions & 0 deletions components/MyEventCard/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use client';

import NextImage from 'next/image';
import styled from 'styled-components';
import { P, SMALLER } from '@/styles/text';
import COLORS from '../../styles/colors';

export const BPImage = styled(NextImage)`
layout: responsive;
width: 20%;
height: 90%;
`;

export const EventContainer = styled.main`
margin: auto;
width: 100%;
padding-top: 1.5rem;
`;
export const EventCardContainer = styled.main`
width: 100%;
padding: 1rem;
background: ${COLORS.bread1};
border-radius: 8px;
display: flex;
justify-content: flex-start;
align-items: center;
box-shadow: 4px 4px 4px 0px rgba(0, 0, 0, 0.15);
gap: 1.5rem;
`;

export const TimeText = styled(SMALLER)`
font-style: normal;
line-height: normal;
`;

export const EventDescriptionText = styled(P)`
font-style: normal;
line-height: normal;
`;

export const LocationText = styled(SMALLER)`
color: ${COLORS.gray10};
font-style: normal;
line-height: normal;
`;
5 changes: 5 additions & 0 deletions public/images/ic_baseline-menu.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 8 additions & 2 deletions styles/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,17 @@ export const H6 = styled.h6<TextProps>`
export const P = styled.p<TextProps>`
${TextStyles}
font-size: 1rem;
font-weight: 400;
// font-weight: 400;
`;

export const SMALL = styled.p<TextProps>`
${TextStyles}
font-size: .875rem;
font-weight: 400;
// font-weight: 400;
`;

export const SMALLER = styled.p<TextProps>`
${TextStyles}
font-size: .75rem;
// font-weight: 400;
`;

0 comments on commit 3296bd8

Please sign in to comment.