Skip to content

Commit

Permalink
➡️ merge pull request #49 from devsoc-unsw/feature/calendarFrontendTo…
Browse files Browse the repository at this point in the history
…Backend

Feature/calendar frontend to backend
  • Loading branch information
lachlanshoesmith authored Dec 15, 2024
2 parents e1c9e45 + 1bdb29b commit cb90abf
Show file tree
Hide file tree
Showing 14 changed files with 218 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
Warnings:
- A unique constraint covering the columns `[text]` on the table `Keyword` will be added. If there are existing duplicate values, this will fail.
*/
-- CreateIndex
CREATE UNIQUE INDEX "Keyword_text_key" ON "Keyword"("text");
4 changes: 2 additions & 2 deletions backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ app.get('/events', async (req, res: Response) => {
skip: page * 10,
take: 10,
});

if (!events || events.length === 0) {
return res.status(404).json({ message: 'No events found.' });
}
Expand Down Expand Up @@ -828,7 +828,7 @@ app.get('/user/events', async (req, res: Response) => {
take: 10,
}),
});

if (!events || events.length === 0) {
return res.status(404).json({ message: 'No events found.' });
}
Expand Down
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
},
"devDependencies": {
"@eslint/js": "^9.16.0",
"@types/node": "^22.10.2",
"@types/react": "^18.3.14",
"@types/react-dom": "^18.3.3",
"@vitejs/plugin-react": "^4.3.4",
Expand Down
26 changes: 21 additions & 5 deletions frontend/pnpm-lock.yaml

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

2 changes: 1 addition & 1 deletion frontend/src/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type ButtonProps = {
variant?: ButtonVariants;
className?: string;
type: React.ButtonHTMLAttributes<HTMLButtonElement>['type'];
onClick?: () => void;
onClick?: () => void; //put this here so that I can pass an onclick function to the button
};

function Button(props: ButtonProps) {
Expand Down
1 change: 0 additions & 1 deletion frontend/src/Calendar/Calendar.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,3 @@
.monthYearName {
font-size: 1.5rem;
}

66 changes: 61 additions & 5 deletions frontend/src/Calendar/Calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { useState } from 'react'
import { format, startOfMonth, endOfMonth, eachDayOfInterval, getDay, addMonths, subMonths, getDaysInMonth } from 'date-fns'
import { useState, useEffect } from 'react'
import { format, startOfMonth, endOfMonth, eachDayOfInterval, getDay, addMonths, subMonths, getDaysInMonth, getTime, startOfDay } from 'date-fns'
import { ArrowLeftIcon, ArrowRightIcon } from "@heroicons/react/24/outline"
import classes from './Calendar.module.css'
import CalendarCell from '../CalendarCell/CalendarCell'
import CalendarDayName from '../CalendarDayName/CalendarDayName'
interface Event {
startDateTime: Date;
[key: string]: any;
};

function Calendar() {
const mapDayIndex = (dayIndex:number) => {
Expand All @@ -12,11 +16,12 @@ function Calendar() {

const addMonth = (currentDate:Date) => {
setCurrentDate(addMonths(currentDate, 1));
fetchEvents();
}

const subMonth = (currentDate:Date) => {
console.log(subMonth);
setCurrentDate(subMonths(currentDate, 1));
fetchEvents();
}

const [currentDate, setCurrentDate] = useState(new Date());
Expand All @@ -29,8 +34,59 @@ function Calendar() {
const days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
const startDayIndex = mapDayIndex(getDay(firstDay));
const dayBuffer = (42-(getDaysInMonth(currentDate)+startDayIndex));
//const [eventsInMonth, setEventsInMonth] = useState([]);

const getEventsInMonth = async(firstDay:Date, lastDay:Date) => {
const params = new URLSearchParams({
after: format(firstDay, 'yyyy-MM-dd'),
before: format(lastDay, 'yyyy-MM-dd'),
});

try {
//not gonna use user/events for now as idk if login is working with the frontedn
const res = await fetch(`${import.meta.env.VITE_BACKEND_URL + '/user/events?' + params}`)

if (res.ok) {
const data = await res.json();
return data;
} else {
return [];
}

} catch(error) {
console.error(error);
return []
}
}
const [eventsInMonth, setEventsInMonth] = useState([]);
const [eventsByDate, setEventsByDate] = useState<Record<number, Event[]>>({});

const fetchEvents = async () => {
const events = await getEventsInMonth(firstDay, lastDay);
setEventsInMonth(events);
};

const buildEventsDict = async (events: Event[]) => {
const dict: Record<number, any> = {}
events.forEach((item: Event) => {
const date = getTime(startOfDay(item.startDateTime));
if(!dict[date]) {
dict[date] = []
}
dict[date].push(item);
});
setEventsByDate(dict);
}

useEffect(() => {
fetchEvents();
}, [currentDate]);

useEffect(() => {
buildEventsDict(eventsInMonth);
}, [eventsInMonth])

console.log(eventsInMonth)
console.log(eventsByDate);
return (
<div className={classes.container}>
<div className={classes.calendar}>
Expand All @@ -53,7 +109,7 @@ function Calendar() {
})}

{ daysOfMonth.map((day) => {
return <CalendarCell date={format(day, 'dd/MM')}/>
return <CalendarCell date={format(day, 'dd/MM')} events={eventsByDate[getTime(startOfDay(day))]}/>
})}

{Array.from({length:dayBuffer}).map((_, ) => {
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/CalendarCell/CalendarCell.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
.dateElement {
font-size: 0.875rem;
}
.eventSpace{
height: 100%;
.eventSpace {
display: flex;
flex-direction: column;
align-items: center;
padding-top: 3%;
}
15 changes: 13 additions & 2 deletions frontend/src/CalendarCell/CalendarCell.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import classes from './CalendarCell.module.css';
import CalendarEventElem from '../CalendarEventElem/CalendarEventElem';
interface Event {
startDateTime: Date;
[key: string]: any;
};

type CalendarCellProps = {
date?: string
date?: string,
events?: Event[]
[key: string]: any; //gonna fix this and fill it out with whatever the backend sends soon
};

function CalendarCell(props: CalendarCellProps) {
Expand All @@ -11,7 +18,11 @@ function CalendarCell(props: CalendarCellProps) {
<p className={classes.dateElement}>{props.date ? props.date : ''}</p>
</div>
<div className={classes.eventSpace}>

{
props.events ? props.events.map((event) => {
return <CalendarEventElem event={event}/>
}) : ''
}
</div>
</div>
)
Expand Down
40 changes: 40 additions & 0 deletions frontend/src/CalendarEventElem/CalendarEventElem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import classes from './CalendarEventElement.module.css';
import EventDetails from '../EventDetails/EventDetails';
import { useState } from 'react';
import ReactDOM from 'react-dom';
import { format } from 'date-fns'

interface Event {
startDateTime: Date;
[key: string]: any;
};

type CalendarEventElemProps = {
event: Event
}

function CalendarEventElem(props: CalendarEventElemProps) {
const [eventDetailsOpen, setEventDetailsOpen] = useState(false);
const containerDOM = document.querySelector(`.${classes.container}`)

const showEventDetails = () => {
setEventDetailsOpen(true);
}
const closeEventDetails = () => setEventDetailsOpen(false);

return (
<div className={classes.CalEventElemWrapper} onClick={showEventDetails}>
<p className={classes.title}>{props.event.name}</p>
<p className={classes.startTime}>{format(props.event.startDateTime, 'ha')}</p>

{
containerDOM && eventDetailsOpen && ReactDOM.createPortal(
<EventDetails image={props.event.image} backgroundPositionY={props.event.backgroundPositionY} name={props.event.name}
society={props.event.society} eventDate={format(props.event.startDateTime, 'dd-MM-yyyy')} startTime={format(props.event.startDateTime, 'ha')}
endTime={format(props.event.endDateTime, 'ha')} location={props.event.location} attending={0} description={props.event.description} closeEventDetails={closeEventDetails}/>, containerDOM
)}
</div>
)
}

export default CalendarEventElem
28 changes: 28 additions & 0 deletions frontend/src/CalendarEventElem/CalendarEventElement.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.CalEventElemWrapper{
border-radius: 20px;
display: flex;
justify-content: space-between;
align-items: center;
width: 90%;
height: 20px;
padding: 2%;
background-color: hsl(201, 39%, 87%);
margin-bottom: 5px;
}

.title {
margin-left: 2%;
white-space: nowrap;
overflow: hidden;
font-size: 14px;
color: hsl(216.4,78%,24.9%);
font-weight:bold;
max-width: 70%;
text-overflow: ellipsis;
}

.startTime{
margin-right: 2%;
font-size: 12px;
color: hsl(216, 50%, 35%);
}
6 changes: 4 additions & 2 deletions frontend/src/EventDetails/EventDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ type EventDetailsProps = {
backgroundPositionY: string;
name: string;
society: string;
date: string;
eventDate: string;
startTime: string;
endTime: string;
location: string;
locationUrl?: string;
attending: number;
description: string;
keywords?: string[];
closeEventDetails: () => void
};

function EventDetails(props: EventDetailsProps) {
Expand All @@ -41,6 +42,7 @@ function EventDetails(props: EventDetailsProps) {
icon={ButtonIcons.Cross}
variant={ButtonVariants.Primary}
className={classes.exitIcon}
onClick={props.closeEventDetails}
></Button>
</div>

Expand All @@ -53,7 +55,7 @@ function EventDetails(props: EventDetailsProps) {
</div>
<div className={classes.detail}>
<CalendarIcon className={classes.icon}></CalendarIcon>
<p className={classes.detailInfo}>{props.date}</p>
<p className={classes.detailInfo}>{props.eventDate}</p>
</div>
<div className={classes.detail}>
<ClockIcon className={classes.icon}></ClockIcon>
Expand Down
Loading

0 comments on commit cb90abf

Please sign in to comment.