Added events page
This commit is contained in:
parent
545138aa35
commit
cc607fc1a9
3 changed files with 226 additions and 0 deletions
35
src/components/react/Event.jsx
Normal file
35
src/components/react/Event.jsx
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Event.jsx
|
||||||
|
import React from "react";
|
||||||
|
function stripHtml(html) {
|
||||||
|
return html.replace(/<\/?[^>]+(>|$)/g, "");
|
||||||
|
}
|
||||||
|
const Event = ({
|
||||||
|
index,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
location,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
month,
|
||||||
|
day,
|
||||||
|
year,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div class="flex flex-col md:relative md:before:absolute md:before:top-2 md:before:w-4 md:before:h-4 md:before:rounded-full md:before:left-[-35px] md:before:z-[1] before:bg-ieee">
|
||||||
|
<h3 class="text-xl font-semibold tracking-wide">{name}</h3>
|
||||||
|
<time class="text-xs tracking-wide text-gray-400">
|
||||||
|
<div>
|
||||||
|
{start} to {end}
|
||||||
|
</div>
|
||||||
|
<div>Location: {location ? location : "N/A"} </div>
|
||||||
|
</time>
|
||||||
|
<div className="event-description mt-2 text-gray-600">
|
||||||
|
{description
|
||||||
|
? stripHtml(description)
|
||||||
|
: "No description provided."}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Event;
|
176
src/components/react/EventList.jsx
Normal file
176
src/components/react/EventList.jsx
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import ReactDOM from "react-dom";
|
||||||
|
import Event from "./Event"; // Adjust the import path as necessary
|
||||||
|
|
||||||
|
const EventList = ({ CALENDAR_API_KEY }) => {
|
||||||
|
const [events, setEvents] = useState([]); // Use an array to store multiple events
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const apiKey = CALENDAR_API_KEY;
|
||||||
|
const calendarId =
|
||||||
|
"666sh64sku5n29qv2a2f4598jc@group.calendar.google.com";
|
||||||
|
const userTimeZone = "America/Los_Angeles";
|
||||||
|
|
||||||
|
const loadGapiAndListEvents = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (typeof window.gapi === "undefined") {
|
||||||
|
const script = document.createElement("script");
|
||||||
|
script.src = "https://apis.google.com/js/api.js";
|
||||||
|
document.body.appendChild(script);
|
||||||
|
script.onload = () => {
|
||||||
|
window.gapi.load("client", resolve);
|
||||||
|
};
|
||||||
|
script.onerror = (error) => {
|
||||||
|
reject(
|
||||||
|
new Error("Failed to load the Google API script.")
|
||||||
|
);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
window.gapi.load("client", resolve);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return gapi.client.init({
|
||||||
|
apiKey: apiKey,
|
||||||
|
discoveryDocs: [
|
||||||
|
"https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return gapi.client.calendar.events.list({
|
||||||
|
calendarId: calendarId,
|
||||||
|
timeZone: userTimeZone,
|
||||||
|
singleEvents: true,
|
||||||
|
timeMin: new Date().toISOString(),
|
||||||
|
maxResults: 10,
|
||||||
|
orderBy: "startTime",
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (
|
||||||
|
response.result.items &&
|
||||||
|
response.result.items.length > 0
|
||||||
|
) {
|
||||||
|
setEvents(response.result.items);
|
||||||
|
} else {
|
||||||
|
setError("No upcoming events found.");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error: ", error.message);
|
||||||
|
setError(error.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
loadGapiAndListEvents().finally(() => {
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
if (events.length === 0) {
|
||||||
|
return (
|
||||||
|
<div class="m-8">
|
||||||
|
<div class="container max-w-5xl px-4 py-12 mx-auto">
|
||||||
|
<div class="grid gap-4 mx-4 md:grid-cols-12">
|
||||||
|
<div class="col-span-12 md:col-span-3">
|
||||||
|
<div class="text-center md:text-left mb-14 before:block before:w-24 before:h-3 before:mb-5 before:rounded-md before:mx-auto md:before:mx-0 before:bg-ieee">
|
||||||
|
<h3 class="text-3xl font-semibold">
|
||||||
|
Upcoming Events
|
||||||
|
</h3>
|
||||||
|
<span class="text-sm font-bold tracking-wider uppercase text-gray-400">
|
||||||
|
Scroll down to see the upcoming events for
|
||||||
|
IEEE!
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="relative col-span-12 px-4 space-y-6 md:col-span-9">
|
||||||
|
<div class="col-span-12 space-y-12 relative px-4 md:col-span-8 md:space-y-8 md:before:absolute md:before:top-2 md:before:bottom-0 md:before:w-0.5 md:before:-left-3 before:bg-gray-700">
|
||||||
|
<div class="flex flex-col md:relative md:before:absolute md:before:top-2 md:before:w-4 md:before:h-4 md:before:rounded-full md:before:left-[-35px] md:before:z-[1] before:bg-ieee">
|
||||||
|
<h3 class="text-xl font-semibold tracking-wide">
|
||||||
|
No Upcoming Events!
|
||||||
|
</h3>
|
||||||
|
<time class="text-xs tracking-wide text-gray-400">
|
||||||
|
<div>¯\_(ツ)_/¯ </div>
|
||||||
|
</time>
|
||||||
|
<div className="event-description mt-2 text-gray-600">
|
||||||
|
<div>
|
||||||
|
There are no upcoming events! Check
|
||||||
|
back again soon :)
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
...or just wait for the entire page
|
||||||
|
to load. This is here by default LOL
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div class="m-8">
|
||||||
|
<div class="container max-w-5xl px-4 py-12 mx-auto">
|
||||||
|
<div class="grid gap-4 mx-4 md:grid-cols-12">
|
||||||
|
<div class="col-span-12 md:col-span-3">
|
||||||
|
<div class="text-center md:text-left mb-14 before:block before:w-24 before:h-3 before:mb-5 before:rounded-md before:mx-auto md:before:mx-0 before:bg-ieee">
|
||||||
|
<h3 class="text-3xl font-semibold">
|
||||||
|
Upcoming Events
|
||||||
|
</h3>
|
||||||
|
<span class="text-sm font-bold tracking-wider uppercase dark:text-gray-400">
|
||||||
|
Scroll down to see the upcoming events for IEEE!
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="relative col-span-12 px-4 space-y-6 md:col-span-9">
|
||||||
|
<div class="col-span-12 space-y-12 relative px-4 md:col-span-8 md:space-y-8 md:before:absolute md:before:top-2 md:before:bottom-0 md:before:w-0.5 md:before:-left-3 before:dark:bg-gray-700">
|
||||||
|
{events.map((event, index) => {
|
||||||
|
const startDate = moment(event.start.dateTime);
|
||||||
|
const month = startDate.format("MMMM");
|
||||||
|
const day = startDate.format("D");
|
||||||
|
const year = startDate.format("YYYY");
|
||||||
|
|
||||||
|
const startsAt =
|
||||||
|
startDate.format("L") +
|
||||||
|
" " +
|
||||||
|
startDate.format("LT");
|
||||||
|
const endsAt = moment(
|
||||||
|
event.end.dateTime
|
||||||
|
).format("LT");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Event
|
||||||
|
key={index}
|
||||||
|
name={event.summary}
|
||||||
|
description={
|
||||||
|
event.description ||
|
||||||
|
"No description provided."
|
||||||
|
}
|
||||||
|
location={
|
||||||
|
event.location ||
|
||||||
|
"No location provided."
|
||||||
|
}
|
||||||
|
start={startsAt}
|
||||||
|
end={endsAt}
|
||||||
|
month={month}
|
||||||
|
day={day}
|
||||||
|
year={year}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EventList;
|
15
src/pages/events.astro
Normal file
15
src/pages/events.astro
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
import EventList from "../components/react/EventList.jsx";
|
||||||
|
import Layout from "../layouts/Layout.astro";
|
||||||
|
const CALENDAR_API_KEY = import.meta.env.CALENDAR_API_KEY;
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<div
|
||||||
|
class="flex justify-center items-center font-medium text-ieee text-[2em] mt-6 mx-auto text-wrap text-center"
|
||||||
|
>
|
||||||
|
Here is our timeline for the IEEE UCSD events:
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<EventList client:load CALENDAR_API_KEY={CALENDAR_API_KEY} />
|
||||||
|
</Layout>
|
Loading…
Reference in a new issue