From 26eb9644c16d2ac73ed42d9af0ade78bee55d6a0 Mon Sep 17 00:00:00 2001 From: AnAs101AlAa Date: Wed, 2 Oct 2024 16:52:59 +0300 Subject: [PATCH 1/2] added endpoints for main events page. ui should be interfaced and done. only left is the event details page --- frontend/src/endpoints/mainEventsEndpoints.js | 69 ++++++++ frontend/src/pages/events/Events.jsx | 162 ++++-------------- .../pages/events/components/eventPoster.jsx | 40 ++++- 3 files changed, 135 insertions(+), 136 deletions(-) create mode 100644 frontend/src/endpoints/mainEventsEndpoints.js diff --git a/frontend/src/endpoints/mainEventsEndpoints.js b/frontend/src/endpoints/mainEventsEndpoints.js new file mode 100644 index 0000000..5ab8da3 --- /dev/null +++ b/frontend/src/endpoints/mainEventsEndpoints.js @@ -0,0 +1,69 @@ +export const fetchEvents = async () => { + try { + const response = await fetch("http://localhost:5300/api/v1/events", { + method: "GET", + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + return data; + } catch (error) { + console.error("Error fetching events:", error); + return null; + } +}; + +export const fetchBookmarkedEvents = async () => { + try { + const response = await fetch("http://localhost:5300/api/v1/events/bookmarks", { + method: "GET", + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + return data; + } catch (error) { + console.error("Error fetching bookmarked events:", error); + return null; + } +}; + +export const bookEvent = async (eventID) => { + try { + const response = await fetch(`http://localhost:5300/api/v1/events/${eventID}/bookmark`, { + method: "POST", + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return true; + } + catch (error) { + console.error("Error booking event:", error); + return false; + } +}; + +export const unbookEvent = async (eventID) => { + try { + const response = await fetch(`http://localhost:5300/api/v1/events/${eventID}/remove-bookmark`, { + method: "POST", + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return true; + } + catch (error) { + console.error("Error unbooking event:", error); + return false; + } +}; \ No newline at end of file diff --git a/frontend/src/pages/events/Events.jsx b/frontend/src/pages/events/Events.jsx index 7b33ec3..f100442 100644 --- a/frontend/src/pages/events/Events.jsx +++ b/frontend/src/pages/events/Events.jsx @@ -1,155 +1,58 @@ import withNavbar from '../../components/HOC/withNavbar' import EventPoster from './components/eventPoster' import '@/styles/eventPage.css' - +import { fetchEvents, fetchBookmarkedEvents } from '../../endpoints/mainEventsEndpoints'; import { PiHeartBreak } from "react-icons/pi"; import { FaChevronUp } from "react-icons/fa"; import { FaChevronDown } from "react-icons/fa6"; import { FaChevronLeft } from "react-icons/fa"; import { FaChevronRight } from "react-icons/fa"; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef } from 'react'; const Events = () => { - const eventssample = [ - { - title: 'Event 1', - date: '2022-12-12', - description: 'This is a sample event description for event 1', - location: 'Sample Location 1', - saved: true, - finished: false - }, - { - title: 'Event 2', - date: '2022-12-12', - description: 'This is a sample event description for event 2', - location: 'Sample Location 2', - saved: true, - finished: false - }, - { - title: 'Event 3', - date: '2022-12-12', - description: 'This is a sample event description for event 3', - location: 'Sample Location 3', - saved: true, - finished: false - }, - { - title: 'Event 4', - date: '2022-12-12', - description: 'This is a sample event description for event 4', - location: 'Sample Location 4', - saved: true, - finished: false - }, - { - title: 'Event 5', - date: '2022-12-12', - description: 'This is a sample event description for event 5', - location: 'Sample Location 5', - saved: true, - finished: false - }, - { - title: 'Event 6', - date: '2022-12-12', - description: 'This is a sample event description for event 6', - location: 'Sample Location 6', - saved: true, - finished: false - }, - { - title: 'Event 7', - date: '2022-12-12', - description: 'This is a sample event description for event 7', - location: 'Sample Location 7', - saved: true, - finished: false - }, - { - title: 'Event 8', - date: '2022-12-12', - description: 'This is a sample event description for event 8', - location: 'Sample Location 8', - saved: true, - finished: false - }, - { - title: 'Event 9', - date: '2022-12-12', - description: 'This is a sample event description for event 9', - location: 'Sample Location 9', - saved: true, - finished: false - }, - { - title: 'Event 10', - date: '2022-12-12', - description: 'This is a sample event description for event 10', - location: 'Sample Location 10', - saved: true, - finished: false - } - ] - - const sampleOldEvents = [ - { - title: 'Event 1', - date: '2022-12-12', - description: 'This is a sample event description for event 1', - location: 'Sample Location 1', - saved: true, - finished: true - }, - { - title: 'Event 2', - date: '2022-12-12', - description: 'This is a sample event description for event 2', - location: 'Sample Location 2', - saved: true, - finished: true - }, - { - title: 'Event 3', - date: '2022-12-12', - description: 'This is a sample event description for event 3', - location: 'Sample Location 3', - saved: true, - finished: true - }, - { - title: 'Event 4', - date: '2022-12-12', - description: 'This is a sample event description for event 4', - location: 'Sample Location 4', - saved: true, - finished: true - } - ]; const [upcomingEvents, setUpcomingEvents] = useState([]); const [pastEvents, setPastEvents] = useState([]); const [loading, setLoading] = useState(true); const [listUpcomingNum, setListUpcomingNum] = useState(0); const [listPastNum, setListPastNum] = useState(0); + const eventRefs = useRef([]); + const containerRef = useRef(null); useEffect(() => { - setUpcomingEvents(eventssample); - setPastEvents(sampleOldEvents); - setLoading(false); - + fetchEvents().then((events) => { + if(!events) return; + fetchBookmarkedEvents().then((bookmarkedEvents) => { + const eventsBookmarked = events.map((event) => {if(bookmarkedEvents.includes(event._id)) return {...event, saved: true}; return {...event, saved: false}}); + const eventListProcess = eventsBookmarked.map((event) => {if(event.date > new Date()) return {...event, finished: false}; return {...event, finished: true}}); + setUpcomingEvents(eventListProcess.filter((event) => !event.finished)); + setPastEvents(eventListProcess.filter((event) => event.finished)); + setLoading(false); + }); + }); }, []); const startUpcomingIndex = listUpcomingNum * 3; - const displayedUpcomingEvents = upcomingEvents.slice(startUpcomingIndex, startUpcomingIndex + 3); const totalUpcomingPages = Math.ceil(upcomingEvents.length / 3); const startPastIndex = listPastNum * 3; const displayedPastEvents = pastEvents.slice(startPastIndex, startPastIndex + 3); const totalPastPages = Math.ceil(pastEvents.length / 3); + const scrollToEvent = (index) => { + if (eventRefs.current[index] && containerRef.current) { + containerRef.current.scrollTo({ + top: eventRefs.current[index].offsetTop - containerRef.current.offsetTop, + behavior: 'smooth', + }); + } + }; + + useEffect(() => { + scrollToEvent(listUpcomingNum * 3); + }, [listUpcomingNum]); + return ( <> {!loading ? ( @@ -164,11 +67,12 @@ const Events = () => {

No upcoming events at the moment

) : ( -
-
- {displayedUpcomingEvents.map((event, index) => ( - - ))} +
+
+ {upcomingEvents.map((event, index) => ( +
{ eventRefs.current[index] = el; }}> + +
))}
{totalUpcomingPages > 1 ? (
setListUpcomingNum(Math.max(listUpcomingNum - 1, 0))} disabled={listUpcomingNum === 0} className='px-4 py-2 disabled:opacity-50 hover:cursor-pointer'> diff --git a/frontend/src/pages/events/components/eventPoster.jsx b/frontend/src/pages/events/components/eventPoster.jsx index 7611b52..fe71573 100644 --- a/frontend/src/pages/events/components/eventPoster.jsx +++ b/frontend/src/pages/events/components/eventPoster.jsx @@ -2,6 +2,7 @@ import { useEffect, useState } from "react"; import PropTypes from 'prop-types'; import fakeEventImage from '@/assets/tccdbackground.jpeg'; import "@/styles/eventPage.css"; +import { bookEvent, unbookEvent } from "@/endpoints/mainEventsEndpoints"; import { FaRegStar } from "react-icons/fa"; import { LuStarOff } from "react-icons/lu"; @@ -10,7 +11,7 @@ import { LuStarOff } from "react-icons/lu"; export default function EventPoster({ eventData, eventsList, setEventsList }) { const [fadeIn, setFadeIn] = useState('opacity-0 -translate-x-1/2'); const [registerEvent, setRegisterEvent] = useState(false); - + const formattedDate = new Date(eventData.date).toLocaleDateString('en-US', { year: 'numeric', month: 'long', @@ -24,7 +25,6 @@ export default function EventPoster({ eventData, eventsList, setEventsList }) { setFadeIn('opacity-100'); }, 300); }, 10); - }, []); @@ -36,11 +36,37 @@ export default function EventPoster({ eventData, eventsList, setEventsList }) { } }, [registerEvent]); + const handleBookEvent = async () => { + const success = await bookEvent(eventData._id); + if (success) { + const updatedEventsList = eventsList.map(event => { + if (event.id === eventData.id) { + return { ...event, saved: !event.saved }; + } + return event; + }); + setEventsList(updatedEventsList); + } + }; + + const handleUnBookEvent = async () => { + const success = await unbookEvent(eventData._id); + if (success) { + const updatedEventsList = eventsList.map(event => { + if (event.id === eventData.id) { + return { ...event, saved: !event.saved }; + } + return event; + }); + setEventsList(updatedEventsList); + } + }; + return ( <> -
- {!eventData.saved ? - : } +
+ {!eventData.saved ? handleBookEvent()} className="absolute z-30 top-4 right-4 text-2xl hover:opacity-100 opacity-50 hover:cursor-pointer transition-all duration-150 ease-in-out" /> + : handleUnBookEvent()} className="absolute z-30 top-4 right-4 text-2xl hover:opacity-100 opacity-50 hover:cursor-pointer transition-all duration-150 ease-in-out" />}
event
@@ -70,11 +96,11 @@ export default function EventPoster({ eventData, eventsList, setEventsList }) { {!eventData.saved ?
- + handleBookEvent()} className="hover:opacity-60 opacity-100 hover:cursor-pointer transition-all duration-150 ease-in-out" />
:
- + handleUnBookEvent()} className="hover:opacity-60 opacity-100 hover:cursor-pointer transition-all duration-150 ease-in-out" />
}
From bfe3cbee711acba22b59fbe33f95f69c1040c9a2 Mon Sep 17 00:00:00 2001 From: AnAs101AlAa Date: Thu, 3 Oct 2024 14:05:17 +0300 Subject: [PATCH 2/2] task 2 done --- frontend/src/endpoints/mainEventsEndpoints.js | 14 ++++++++++++++ frontend/src/pages/events/Events.jsx | 3 ++- .../src/pages/events/components/eventPoster.jsx | 15 ++++++--------- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/frontend/src/endpoints/mainEventsEndpoints.js b/frontend/src/endpoints/mainEventsEndpoints.js index 5ab8da3..9b0c870 100644 --- a/frontend/src/endpoints/mainEventsEndpoints.js +++ b/frontend/src/endpoints/mainEventsEndpoints.js @@ -1,7 +1,12 @@ +import { getToken } from "../utils/helper"; + export const fetchEvents = async () => { try { const response = await fetch("http://localhost:5300/api/v1/events", { method: "GET", + headers: { + Authorization: `Bearer ${getToken()}`, + } }); if (!response.ok) { @@ -20,6 +25,9 @@ export const fetchBookmarkedEvents = async () => { try { const response = await fetch("http://localhost:5300/api/v1/events/bookmarks", { method: "GET", + headers: { + Authorization: `Bearer ${getToken()}`, + } }); if (!response.ok) { @@ -38,6 +46,9 @@ export const bookEvent = async (eventID) => { try { const response = await fetch(`http://localhost:5300/api/v1/events/${eventID}/bookmark`, { method: "POST", + headers: { + Authorization: `Bearer ${getToken()}`, + } }); if (!response.ok) { @@ -55,6 +66,9 @@ export const unbookEvent = async (eventID) => { try { const response = await fetch(`http://localhost:5300/api/v1/events/${eventID}/remove-bookmark`, { method: "POST", + headers: { + Authorization: `Bearer ${getToken()}`, + } }); if (!response.ok) { diff --git a/frontend/src/pages/events/Events.jsx b/frontend/src/pages/events/Events.jsx index f100442..6144c91 100644 --- a/frontend/src/pages/events/Events.jsx +++ b/frontend/src/pages/events/Events.jsx @@ -23,8 +23,9 @@ const Events = () => { useEffect(() => { fetchEvents().then((events) => { if(!events) return; + console.log(events); fetchBookmarkedEvents().then((bookmarkedEvents) => { - const eventsBookmarked = events.map((event) => {if(bookmarkedEvents.includes(event._id)) return {...event, saved: true}; return {...event, saved: false}}); + const eventsBookmarked = events.map((event) => {if(bookmarkedEvents.events.includes(event._id)) return {...event, saved: true}; return {...event, saved: false}}); const eventListProcess = eventsBookmarked.map((event) => {if(event.date > new Date()) return {...event, finished: false}; return {...event, finished: true}}); setUpcomingEvents(eventListProcess.filter((event) => !event.finished)); setPastEvents(eventListProcess.filter((event) => event.finished)); diff --git a/frontend/src/pages/events/components/eventPoster.jsx b/frontend/src/pages/events/components/eventPoster.jsx index fe71573..54a07b8 100644 --- a/frontend/src/pages/events/components/eventPoster.jsx +++ b/frontend/src/pages/events/components/eventPoster.jsx @@ -40,7 +40,7 @@ export default function EventPoster({ eventData, eventsList, setEventsList }) { const success = await bookEvent(eventData._id); if (success) { const updatedEventsList = eventsList.map(event => { - if (event.id === eventData.id) { + if (event._id === eventData._id) { return { ...event, saved: !event.saved }; } return event; @@ -53,7 +53,7 @@ export default function EventPoster({ eventData, eventsList, setEventsList }) { const success = await unbookEvent(eventData._id); if (success) { const updatedEventsList = eventsList.map(event => { - if (event.id === eventData.id) { + if (event._id === eventData._id) { return { ...event, saved: !event.saved }; } return event; @@ -93,15 +93,12 @@ export default function EventPoster({ eventData, eventsList, setEventsList }) {
event
- - {!eventData.saved ? -
- handleBookEvent()} className="hover:opacity-60 opacity-100 hover:cursor-pointer transition-all duration-150 ease-in-out" /> +
+ handleBookEvent()} className={`hover:opacity-60 opacity-100 hover:cursor-pointer transition-all duration-150 ease-in-out`} />
- : -
+
handleUnBookEvent()} className="hover:opacity-60 opacity-100 hover:cursor-pointer transition-all duration-150 ease-in-out" /> -
} +

{eventData.title}