Skip to content

Commit

Permalink
Merge pull request #868 from acm-ucr/shahdivyank/multiple_calendars
Browse files Browse the repository at this point in the history
Multiple Calendar Support
  • Loading branch information
menthy-wu authored Nov 6, 2023
2 parents 85a1da7 + c0eaee2 commit a208e00
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 52 deletions.
27 changes: 24 additions & 3 deletions src/app/api/checkin/route.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { NextResponse } from "next/server";
import { db } from "../../../../firebase";
import { doc, getDoc, updateDoc, arrayUnion } from "firebase/firestore";
import {
doc,
getDoc,
updateDoc,
arrayUnion,
increment,
setDoc,
} from "firebase/firestore";
import { authenticate } from "@/utils/auth";

export async function GET(req) {
Expand All @@ -20,7 +27,8 @@ export async function GET(req) {

try {
const docSnap = await getDoc(doc(db, "users", uid));
const data = docSnap.data().events;
const data = docSnap.data().events || [];
console.log(data);
return res.json({ message: "OK", items: data }, { status: 200 });
} catch (err) {
return res.json(
Expand All @@ -43,12 +51,25 @@ export async function PUT(req) {
);
}

const { uid, event } = await req.json();
const { uid, event, name } = await req.json();

try {
await updateDoc(doc(db, "users", uid), {
events: arrayUnion(event),
});

const data = await getDoc(doc(db, "events", event));
if (data.exists()) {
await updateDoc(doc(db, "events", event), {
attendance: increment(1),
});
} else {
await setDoc(doc(db, "events", event), {
attendance: 1,
name: name,
});
}

return res.json({ message: "OK" }, { status: 200 });
} catch (err) {
return res.json(
Expand Down
17 changes: 15 additions & 2 deletions src/app/api/statistics/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
query,
collection,
getCountFromServer,
getDocs,
} from "firebase/firestore";
import { authenticate } from "@/utils/auth";

Expand Down Expand Up @@ -71,7 +72,16 @@ export async function GET() {
)
).data().count;

const items = {
const events = await getDocs(collection(db, "events"));

const eventAttendees = {};

events.forEach((doc) => {
const { name, attendance } = doc.data();
eventAttendees[name] = attendance;
});

const users = {
participants,
teams,
judges,
Expand All @@ -81,7 +91,10 @@ export async function GET() {
admins,
};

return res.json({ items: items }, { status: 200 });
return res.json(
{ items: { users, events: eventAttendees } },
{ status: 200 }
);
} catch (err) {
return res.json(
{ message: `Internal Server Error: ${err}` },
Expand Down
22 changes: 14 additions & 8 deletions src/components/dynamic/admin/services/calendar/Event.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
const Event = ({ event }) => {
const Event = ({ event, view }) => {
console.log(event);

return (
<div className="p-1">
<p className="inline whitespace-nowrap">
<div className="p-0.5">
<p className="inline text-xs">
{event.summary}
<br />
{new Date(event.start).toLocaleTimeString(navigator.language, {
hour: "2-digit",
minute: "2-digit",
})}
{view === "month" && (
<>
{" - "}
{new Date(event.start).toLocaleTimeString(navigator.language, {
hour: "2-digit",
minute: "2-digit",
})}
</>
)}
</p>
</div>
);
Expand Down
44 changes: 27 additions & 17 deletions src/components/dynamic/admin/services/calendar/Events.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,33 @@ const CalendarEvents = () => {
};

useEffect(() => {
axios
.get(
`https://www.googleapis.com/calendar/v3/calendars/${process.env.NEXT_PUBLIC_GOOGLE_CALENDAR_EMAIL}/events?key=${process.env.NEXT_PUBLIC_GOOGLE_CALENDAR_API_KEY}&singleEvents=true&orderBy=startTime`
)
.then((response) => {
const items = response.data.items.map((item) => {
item.start = new Date(item.start.dateTime);
item.end = new Date(item.end.dateTime);
item.color =
LABELS[
item.description.split("\n")[1].split(": ")[1].toLowerCase()
].background;
item.hidden = false;
const hackathon = axios.get(
`https://www.googleapis.com/calendar/v3/calendars/${process.env.NEXT_PUBLIC_GOOGLE_CALENDAR}/events?key=${process.env.NEXT_PUBLIC_GOOGLE_CALENDAR_API_KEY}&singleEvents=true&orderBy=startTime`
);

return item;
});
setEvents(items);
const leads = axios.get(
`https://www.googleapis.com/calendar/v3/calendars/${process.env.NEXT_PUBLIC_GOOGLE_CALENDAR_LEADS}/events?key=${process.env.NEXT_PUBLIC_GOOGLE_CALENDAR_API_KEY}&singleEvents=true&orderBy=startTime`
);

Promise.all([hackathon, leads]).then(([hackathonData, leadsData]) => {
const hackathon = hackathonData.data.items;
const leads = leadsData.data.items;

const rawEvents = [...hackathon, ...leads];

rawEvents.forEach((item) => {
item.start = new Date(item.start.dateTime);
item.end = new Date(item.end.dateTime);
item.color =
LABELS[
item.description.split("\n")[1].split(": ")[1].toLowerCase()
].background;
item.hidden = false;
});

setEvents(rawEvents);
});

document.addEventListener("keydown", handleShortcuts);
return () => document.removeEventListener("keydown", handleShortcuts);
}, []);
Expand All @@ -59,14 +68,15 @@ const CalendarEvents = () => {
date={date}
view={view}
className="py-4"
step={15}
events={events.filter((event) => !event.hidden)}
localizer={mLocalizer}
defaultView="month"
views={["month", "week"]}
onNavigate={(newDate) => setDate(newDate)}
onView={(newView) => setView(newView)}
components={{
event: Event,
event: (props) => <Event {...props} view={view} />,
toolbar: (props) => (
<Toolbar {...props} events={events} setEvents={setEvents} />
),
Expand Down
5 changes: 3 additions & 2 deletions src/components/dynamic/admin/services/checkin/CheckIn.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const CheckIn = () => {
useEffect(() => {
axios
.get(
`https://www.googleapis.com/calendar/v3/calendars/${process.env.NEXT_PUBLIC_GOOGLE_CALENDAR_EMAIL}/events?key=${process.env.NEXT_PUBLIC_GOOGLE_CALENDAR_API_KEY}&singleEvents=true&orderBy=startTime`
`https://www.googleapis.com/calendar/v3/calendars/${process.env.NEXT_PUBLIC_GOOGLE_CALENDAR}/events?key=${process.env.NEXT_PUBLIC_GOOGLE_CALENDAR_API_KEY}&singleEvents=true&orderBy=startTime`
)
.then((response) => {
setEvents(
Expand Down Expand Up @@ -48,14 +48,15 @@ const CheckIn = () => {
// TODO: CHANGE TO 5 SECONDS ONCE DEPLOYED
if (delta < 5000) {
const response = await axios.get(`/api/checkin?uid=${user}`);
console.log(response.data);

if (response.data.items.includes(event.id)) {
toast("❌ Already Checked In!");
return;
}

axios
.put("/api/checkin", { uid: user, event: event.id })
.put("/api/checkin", { uid: user, event: event.id, name: event.name })
.then(() => toast(`✅ Checked in for ${event.name}`));
} else {
toast("❌ Expired QR code!");
Expand Down
13 changes: 8 additions & 5 deletions src/components/dynamic/admin/services/statistics/Statistics.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,21 @@ import Tabs from "./Tabs";
import axios from "axios";

const Statistics = () => {
const [counts, setCounts] = useState({});
const [counts, setCounts] = useState({
users: {},
events: {},
});

useEffect(() => {
axios
.get("/api/statistics")
.then((response) => setCounts(response.data.items));
axios.get("/api/statistics").then((response) => {
setCounts(response.data.items);
});
}, []);

return (
<div className="h-full font-poppins flex flex-col py-4">
<Title title="Statistics" />
<Tabs counts={counts} />
<Tabs counts={counts.users} events={counts.events} />
</div>
);
};
Expand Down
19 changes: 13 additions & 6 deletions src/components/dynamic/admin/services/statistics/Tabs.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import Tab from "./Tab";

const Tabs = ({ counts }) => {
const Tabs = ({ counts, events }) => {
return (
<div className="w-full mt-3 grid grid-cols-7">
{Object.entries(counts).map(([title, count], index) => (
<Tab key={index} title={title} value={count} />
))}
</div>
<>
<div className="w-full mt-3 grid grid-cols-7">
{Object.entries(counts).map(([title, count], index) => (
<Tab key={index} title={title} value={count} />
))}
</div>
<div className="w-full mt-3 grid grid-cols-4">
{Object.entries(events).map(([title, count], index) => (
<Tab key={index} title={title} value={count} />
))}
</div>
</>
);
};

Expand Down
4 changes: 2 additions & 2 deletions src/data/dynamic/Navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,12 @@ export const TABS = {
tabs: [
{
name: "dashboard",
link: "/users/dashboard",
link: "/user/dashboard",
icon: <BsFillPersonFill className={iconStyle} />,
},
{
name: "checkin",
link: "/users/checkin",
link: "/user/checkin",
icon: <AiOutlineQrcode className={iconStyle} />,
},
{
Expand Down
14 changes: 7 additions & 7 deletions src/data/dynamic/admin/Calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export const LABELS = {
color: "gray",
background: "!bg-hackathon-tags-gray-text",
},
director: {
directors: {
color: "red",
background: "!bg-hackathon-tags-red-text",
},
Expand All @@ -27,20 +27,20 @@ export const LABELS = {
color: "teal",
background: "!bg-hackathon-tags-teal-text",
},
UIUX: {
uiux: {
color: "lightgreen",
background: "!bg-hackathon-tags-lightgreen-text",
},
activities: {
color: "pink",
background: "!bg-hackathon-tags-pink-text",
},
workshop: {
color: "grayblue",
background: "!bg-hackathon-tags-grayblue-text",
},
general: {
leads: {
color: "red",
background: "!bg-hackathon-tags-red-text",
},
hackathon: {
color: "pink",
background: "!bg-hackathon-tags-pink-text",
},
};

0 comments on commit a208e00

Please sign in to comment.