-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #53 from atiqurx/main
add calendar to the events page
- Loading branch information
Showing
8 changed files
with
369 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { NextResponse } from "next/server"; | ||
import { GET as getEvents } from "../route"; | ||
import type { Event } from "@/lib/types.d.ts"; | ||
|
||
const calendarId = process.env.GOOGLE_CALENDAR_ID; | ||
const endpoint = `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events`; | ||
|
||
export async function GET(request: Request) { | ||
const url = new URL(request.url); | ||
const year = parseInt(url.searchParams.get("year") || "0", 10); | ||
const month = parseInt(url.searchParams.get("month") || "0", 10); | ||
|
||
// Fetch filtered events directly | ||
const filteredEvents = await byDate(month, year); | ||
return NextResponse.json(filteredEvents); | ||
} | ||
|
||
export async function byDate(month: number, year: number): Promise<Event[]> { | ||
const response = await getEvents(); // Fetch the events data directly | ||
const data = await response.json(); // Parse the response to JSON | ||
const earliest = new Date(year, month, 1); | ||
const latest = new Date(year, month + 1, 0); | ||
|
||
// Filter and transform events in a single pass | ||
const filteredEvents = data | ||
.map((item: any) => { | ||
const startDate = item.start ? new Date(item.start) : undefined; // Ensure start is defined | ||
return { | ||
...item, | ||
start: startDate, | ||
}; | ||
}) | ||
.filter((event: Event) => { | ||
if (!event.start) return false; // Exclude events with no start date | ||
const eventDate = new Date(event.start); | ||
return eventDate >= earliest && eventDate <= latest; | ||
}); | ||
|
||
return filteredEvents; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import type { Event } from "@/lib/types.d.ts"; | ||
import { NextResponse } from "next/server"; | ||
|
||
export const dynamic = "force-dynamic"; | ||
const calendarId = process.env.GOOGLE_CALENDAR_ID; | ||
const endpoint = `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events`; | ||
|
||
export async function GET() { | ||
// Fetch and parse data | ||
const response = await fetch( | ||
`${endpoint}?key=${process.env.CALENDAR_API_KEY}`, | ||
{ cache: "no-store" } | ||
); | ||
const data = await response.json(); | ||
|
||
const items = data.items as unknown[] | undefined; | ||
|
||
if (!items || !Array.isArray(items) || items.length === 0) { | ||
return new Response("No events found", { status: 404 }); | ||
} | ||
|
||
// Use a single pass to parse and filter | ||
const now = new Date(); | ||
now.setHours(0, 0, 0, 0); | ||
|
||
const upcoming = items | ||
.filter((item: unknown) => { | ||
// Check for necessary properties | ||
return ( | ||
item && | ||
typeof item === "object" && | ||
"id" in item && | ||
"summary" in item && | ||
"start" in item && | ||
typeof item.start === "object" && | ||
item.start !== null && | ||
"dateTime" in item.start && | ||
typeof item.start.dateTime === "string" | ||
); | ||
}) | ||
.map((item: any) => ({ | ||
id: item.id as string, | ||
title: item.summary as string, | ||
location: typeof item.location === "string" ? item.location : undefined, | ||
start: new Date(item.start.dateTime), | ||
})) | ||
.filter((event: Event) => event.start !== undefined && event.start > now) | ||
.sort((a, b) => a.start.getTime() - b.start.getTime()); | ||
|
||
return new NextResponse<Event[]>(JSON.stringify(upcoming)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import Calendar from "@/components/events/Calendar"; | ||
type Params = { | ||
month: string | null; | ||
year: string | null; | ||
}; | ||
|
||
export default function Events({ searchParams }: { searchParams: Params }) { | ||
const today = new Date(); | ||
const month = parseInt(searchParams.month || today.getMonth().toString()); | ||
const year = parseInt(searchParams.year || today.getFullYear().toString()); | ||
|
||
return ( | ||
<div className="h-fit w-full bg-[url(/assets/apply/apply-bg.png)] bg-cover bg-center py-20"> | ||
<div className="flex p-10 md:p-4 justify-between pt-16 md:mx-20"> | ||
<Calendar month={month} year={year} /> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import Link from "next/link"; | ||
import CalendarBody from "./CalendarBody"; | ||
import { byDate } from "@/app/api/events/byDate/route"; | ||
|
||
type Props = { | ||
month: number; | ||
year: number; | ||
}; | ||
|
||
const monthNames = [ | ||
"January", | ||
"February", | ||
"March", | ||
"April", | ||
"May", | ||
"June", | ||
"July", | ||
"August", | ||
"September", | ||
"October", | ||
"November", | ||
"December", | ||
]; | ||
|
||
function changeMonth( | ||
amt: "inc" | "dec", | ||
{ month, year }: { month: number; year: number } | ||
) { | ||
if (amt === "inc") { | ||
if (month === 11) return { month: 0, year: year + 1 }; | ||
return { month: month + 1, year }; | ||
} | ||
if (month === 0) return { month: 11, year: year - 1 }; | ||
return { month: month - 1, year }; | ||
} | ||
|
||
async function Calendar({ month, year }: Props) { | ||
const events = await byDate(month, year); | ||
const nextParams = changeMonth("inc", { month, year }); | ||
const prevParams = changeMonth("dec", { month, year }); | ||
|
||
return ( | ||
<div className="w-full rounded-3xl border border-[#ffffff82] bg-gradient-to-tr from-[#ffffff1f] from-[3.07%] to-[#ffffff08] to-[96.39%] p-5 shadow-md backdrop-blur-xl"> | ||
<div className="mb-5 flex items-center justify-between text-white flex-wrap"> | ||
<Link | ||
className="w-10 text-lg md:text-xl" | ||
href={{ | ||
pathname: "/events", | ||
query: { month: prevParams.month, year: prevParams.year }, | ||
}} | ||
>{`<`}</Link> | ||
<span className="w-32 text-center text-xl font-semibold md:text-2xl"> | ||
{monthNames[month]} | ||
</span> | ||
<Link | ||
className="w-10 text-lg md:text-xl" | ||
href={{ | ||
pathname: "/events", | ||
query: { month: nextParams.month, year: nextParams.year }, | ||
}} | ||
>{`>`}</Link> | ||
</div> | ||
<CalendarBody month={month} year={year} events={events} /> | ||
</div> | ||
); | ||
} | ||
|
||
export default Calendar; |
Oops, something went wrong.