From 50a0f0240d7fef133eb5acc1bea2b1168b08e9db Mon Sep 17 00:00:00 2001 From: Factiven Date: Sun, 24 Dec 2023 13:03:54 +0700 Subject: migrate to typescript --- pages/en/schedule/index.js | 485 -------------------------------------------- pages/en/schedule/index.tsx | 484 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 484 insertions(+), 485 deletions(-) delete mode 100644 pages/en/schedule/index.js create mode 100644 pages/en/schedule/index.tsx (limited to 'pages/en/schedule') diff --git a/pages/en/schedule/index.js b/pages/en/schedule/index.js deleted file mode 100644 index f1e6730..0000000 --- a/pages/en/schedule/index.js +++ /dev/null @@ -1,485 +0,0 @@ -import Image from "next/image"; -import { useEffect, useRef, useState } from "react"; -import Link from "next/link"; -import { CalendarIcon } from "@heroicons/react/24/solid"; -import { ClockIcon } from "@heroicons/react/24/outline"; -import Loading from "@/components/shared/loading"; -import { timeStamptoAMPM, timeStamptoHour } from "@/utils/getTimes"; -import { - filterFormattedSchedule, - filterScheduleByDay, - sortScheduleByDay, - transformSchedule, -} from "@/utils/schedulesUtils"; - -import { scheduleQuery } from "@/lib/graphql/query"; -import MobileNav from "@/components/shared/MobileNav"; - -import { useSession } from "next-auth/react"; -import { redis } from "@/lib/redis"; -import Head from "next/head"; -import { NewNavbar } from "@/components/shared/NavBar"; - -const day = [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", -]; - -const isAired = (timestamp) => { - const currentTime = new Date().getTime() / 1000; - return timestamp <= currentTime; -}; - -export async function getServerSideProps() { - const now = new Date(); - // Adjust for Japan timezone (add 9 hours) - const nowJapan = new Date(now.getTime() + 9 * 60 * 60 * 1000); - - // Calculate the time until midnight of the next day in Japan timezone - const midnightTomorrowJapan = new Date( - nowJapan.getFullYear(), - nowJapan.getMonth(), - nowJapan.getDate() + 1, - 0, - 0, - 0, - 0 - ); - const timeUntilMidnightJapan = Math.round( - (midnightTomorrowJapan - nowJapan) / 1000 - ); - - let cachedData; - - // Check if the data is already in Redis - if (redis) { - cachedData = await redis.get("new_schedule"); - } - - if (cachedData) { - const scheduleByDay = JSON.parse(cachedData); - - return { - props: { - schedule: scheduleByDay, - // today: todaySchedule, - }, - }; - } else { - now.setHours(0, 0, 0, 0); // Set the time to 00:00:00.000 - const dayInSeconds = 86400; // Number of seconds in a day - const yesterdayStart = Math.floor(now.getTime() / 1000) - dayInSeconds; - // Calculate weekStart from yesterday's 00:00:00 - const weekStart = yesterdayStart; - const weekEnd = weekStart + 604800; - - let page = 1; - const airingSchedules = []; - - while (true) { - const res = await fetch("https://graphql.anilist.co", { - method: "POST", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify({ - query: scheduleQuery, - variables: { - weekStart, - weekEnd, - page, - }, - }), - }); - - const json = await res.json(); - const schedules = json.data.Page.airingSchedules; - - if (schedules.length === 0) { - break; // No more data to fetch - } - - airingSchedules.push(...schedules); - page++; - } - - const timestampToDay = (timestamp) => { - const options = { weekday: "long" }; - return new Date(timestamp * 1000).toLocaleDateString(undefined, options); - }; - - const scheduleByDay = {}; - airingSchedules.forEach((schedule) => { - const day = timestampToDay(schedule.airingAt); - if (!scheduleByDay[day]) { - scheduleByDay[day] = []; - } - scheduleByDay[day].push(schedule); - }); - - if (redis) { - await redis.set( - "new_schedule", - JSON.stringify(scheduleByDay), - "EX", - timeUntilMidnightJapan - ); - } - - return { - props: { - schedule: scheduleByDay, - // today: todaySchedule, - }, - }; - } - // setSchedule(scheduleByDay); -} - -export default function Schedule({ schedule }) { - const { data: session } = useSession(); - - // const [schedule, setSchedule] = useState({}); - const [filterDay, setFilterDay] = useState("All"); - const [loading, setLoading] = useState(true); - - useEffect(() => { - setLoading(true); - async function setDay() { - const now = new Date(); - const today = day[now.getDay()]; - setFilterDay(today); - setLoading(false); - } - setDay(); - }, []); - // Sort the schedule object by day, placing today's schedule first - const sortedSchedule = sortScheduleByDay(schedule); - const formattedSchedule = transformSchedule(schedule); - - // State to keep track of the next airing anime - const [nextAiringAnime, setNextAiringAnime] = useState(null); - // const [nextAiringBanner, setNextAiringBanner] = useState(null); - - // State to keep track of the currently airing anime - const [currentlyAiringAnime, setCurrentlyAiringAnime] = useState(null); - - const [layout, setLayout] = useState(1); - - // Effect to update the next and currently airing anime - useEffect(() => { - const now = new Date().getTime() / 1000; // Current time in seconds - let nextAiring = null; - let currentlyAiring = null; - - for (const [, schedules] of Object.entries(sortedSchedule)) { - for (const s of schedules) { - if (s.airingAt > now) { - if (!nextAiring) { - nextAiring = s.id; - // setNextAiringBanner(s.media.bannerImage); - } - } else if (s.airingAt + 1440 > now) { - currentlyAiring = s.id; - } - } - if (nextAiring && currentlyAiring) break; - } - - setNextAiringAnime(nextAiring); - setCurrentlyAiringAnime(currentlyAiring); - }, [sortedSchedule]); - - const scrollContainerRef = useRef(null); - - useEffect(() => { - // Scroll to center the active button when it changes - if (scrollContainerRef.current) { - const activeButton = - scrollContainerRef.current.querySelector(".text-action"); - if (activeButton) { - const containerWidth = scrollContainerRef.current.clientWidth; - const buttonLeft = activeButton.offsetLeft; - const buttonWidth = activeButton.clientWidth; - const scrollLeft = buttonLeft - containerWidth / 2 + buttonWidth / 2; - scrollContainerRef.current.scrollLeft = scrollLeft; - } - } - }, [filterDay]); - - return ( - <> - - Moopa - Schedule - {/* write a meta with good seo for this page */} - - - - - - - - - - - - - - - {/* - */} - - - - - - - -
- -
- -
-
-
    - - {day.map((i) => ( - - ))} -
-
- setLayout(1)} - /> - setLayout(2)} - /> -
-
- - {layout === 1 ? ( - !loading ? ( - Object.entries( - filterFormattedSchedule(formattedSchedule, filterDay) - ).map(([day, timeSlots], index) => ( -
-

- {day} -

- {Object.entries(timeSlots).map(([time, animeList]) => ( -
-
-

- {timeStamptoAMPM(time)} -

- {/* {!isAired(time) &&

Airing Next

} */} -

-
-
- {animeList.map((s, index) => { - const m = s.media; - return ( - <> - - image -
-

- {m.title.romaji} -

-

- Ep {s.episode} {timeStamptoHour(s.airingAt)} -

-
- -

- - ); - })} -
-
- ))} -
- )) - ) : ( -
- -
- ) - ) : !loading ? ( - Object.entries(filterScheduleByDay(sortedSchedule, filterDay)).map( - ([day, schedules]) => ( -
-

- {day} -

-
- {schedules.map((s) => { - const m = s.media; - - return ( - - {/*

*/} -

- - {/* */} - - Next Airing - -

-

- - - - Airing Now - -

- image -
-

- {m.title.romaji} -

-

- Ep {s.episode} {timeStamptoHour(s.airingAt)} -

-
- - ); - })} -
-
- ) - ) - ) : ( -
- -
- )} -
-
- - ); -} diff --git a/pages/en/schedule/index.tsx b/pages/en/schedule/index.tsx new file mode 100644 index 0000000..aa30259 --- /dev/null +++ b/pages/en/schedule/index.tsx @@ -0,0 +1,484 @@ +import Image from "next/image"; +import { useEffect, useRef, useState } from "react"; +import Link from "next/link"; +import { CalendarIcon } from "@heroicons/react/24/solid"; +import { ClockIcon } from "@heroicons/react/24/outline"; +import Loading from "@/components/shared/loading"; +import { timeStamptoAMPM, timeStamptoHour } from "@/utils/getTimes"; +import { + filterFormattedSchedule, + filterScheduleByDay, + sortScheduleByDay, + transformSchedule, +} from "@/utils/schedulesUtils"; + +import { scheduleQuery } from "@/lib/graphql/query"; +import MobileNav from "@/components/shared/MobileNav"; + +import { useSession } from "next-auth/react"; +import { redis } from "@/lib/redis"; +import Head from "next/head"; +import { Navbar } from "@/components/shared/NavBar"; + +const day = [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", +]; + +const isAired = (timestamp: number | null) => { + if (!timestamp) return false; + const currentTime = new Date().getTime() / 1000; + return timestamp <= currentTime; +}; + +export async function getServerSideProps() { + const now = new Date(); + // Adjust for Japan timezone (add 9 hours) + const nowJapan = new Date(now.getTime() + 9 * 60 * 60 * 1000); + + // Calculate the time until midnight of the next day in Japan timezone + const midnightTomorrowJapan = new Date( + nowJapan.getFullYear(), + nowJapan.getMonth(), + nowJapan.getDate() + 1, + 0, + 0, + 0, + 0 + ); + const timeUntilMidnightJapan = Math.round( + (midnightTomorrowJapan.getTime() - nowJapan.getTime()) / 1000 + ); + + let cachedData; + + // Check if the data is already in Redis + if (redis) { + cachedData = await redis.get("new_schedule"); + } + + if (cachedData) { + const scheduleByDay = JSON.parse(cachedData); + + return { + props: { + schedule: scheduleByDay, + // today: todaySchedule, + }, + }; + } else { + now.setHours(0, 0, 0, 0); // Set the time to 00:00:00.000 + const dayInSeconds = 86400; // Number of seconds in a day + const yesterdayStart = Math.floor(now.getTime() / 1000) - dayInSeconds; + // Calculate weekStart from yesterday's 00:00:00 + const weekStart = yesterdayStart; + const weekEnd = weekStart + 604800; + + let page = 1; + const airingSchedules = []; + + while (true) { + const res = await fetch("https://graphql.anilist.co", { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify({ + query: scheduleQuery, + variables: { + weekStart, + weekEnd, + page, + }, + }), + }); + + const json = await res.json(); + const schedules = json.data.Page.airingSchedules; + + if (schedules.length === 0) { + break; // No more data to fetch + } + + airingSchedules.push(...schedules); + page++; + } + + const timestampToDay = (timestamp: number) => { + return new Date(timestamp * 1000).toLocaleDateString(undefined, { + weekday: "long", + }); + }; + + const scheduleByDay: { [key: string]: any } = {}; + airingSchedules.forEach((schedule) => { + const day = timestampToDay(schedule.airingAt); + if (!scheduleByDay[day]) { + scheduleByDay[day] = []; + } + scheduleByDay[day].push(schedule); + }); + + if (redis) { + await redis.set( + "new_schedule", + JSON.stringify(scheduleByDay), + "EX", + timeUntilMidnightJapan + ); + } + + return { + props: { + schedule: scheduleByDay, + // today: todaySchedule, + }, + }; + } + // setSchedule(scheduleByDay); +} + +export default function Schedule({ schedule }: any) { + const [filterDay, setFilterDay] = useState("All"); + const [loading, setLoading] = useState(true); + + useEffect(() => { + setLoading(true); + async function setDay() { + const now = new Date(); + const today = day[now.getDay()]; + setFilterDay(today); + setLoading(false); + } + setDay(); + }, []); + // Sort the schedule object by day, placing today's schedule first + const sortedSchedule = sortScheduleByDay(schedule); + const formattedSchedule = transformSchedule(schedule); + + // State to keep track of the next airing anime + const [nextAiringAnime, setNextAiringAnime] = useState(null); + // const [nextAiringBanner, setNextAiringBanner] = useState(null); + + // State to keep track of the currently airing anime + const [currentlyAiringAnime, setCurrentlyAiringAnime] = useState(null); + + const [layout, setLayout] = useState(1); + + // Effect to update the next and currently airing anime + useEffect(() => { + const now = new Date().getTime() / 1000; // Current time in seconds + let nextAiring = null; + let currentlyAiring = null; + + for (const [, schedules] of Object.entries(sortedSchedule as object)) { + for (const s of schedules) { + if (s.airingAt > now) { + if (!nextAiring) { + nextAiring = s.id; + // setNextAiringBanner(s.media.bannerImage); + } + } else if (s.airingAt + 1440 > now) { + currentlyAiring = s.id; + } + } + if (nextAiring && currentlyAiring) break; + } + + setNextAiringAnime(nextAiring); + setCurrentlyAiringAnime(currentlyAiring); + }, [sortedSchedule]); + + const scrollContainerRef = useRef(null); + + useEffect(() => { + // Scroll to center the active button when it changes + if (scrollContainerRef.current) { + const activeButton = + scrollContainerRef.current?.querySelector(".text-action"); + if (activeButton) { + const containerWidth = scrollContainerRef.current.clientWidth; + const buttonLeft = (activeButton as HTMLElement).offsetLeft; + const buttonWidth = activeButton.clientWidth; + const scrollLeft = buttonLeft - containerWidth / 2 + buttonWidth / 2; + scrollContainerRef.current.scrollLeft = scrollLeft; + } + } + }, [filterDay]); + + return ( + <> + + Moopa - Schedule + {/* write a meta with good seo for this page */} + + + + + + + + + + + + + + + {/* + */} + + + + + + + +
+ +
+ +
+
+
    + + {day.map((i) => ( + + ))} +
+
+ setLayout(1)} + /> + setLayout(2)} + /> +
+
+ + {layout === 1 ? ( + !loading ? ( + Object.entries( + filterFormattedSchedule(formattedSchedule, filterDay) + ).map(([day, timeSlots], index) => ( +
+

+ {day} +

+ {Object.entries(timeSlots).map(([time, animeList]) => ( +
+
+

+ {time && timeStamptoAMPM(time)} +

+ {/* {!isAired(time) &&

Airing Next

} */} +

+
+
+ {animeList.map((s, index) => { + const m = s.media; + return ( + <> + + image +
+

+ {m.title.romaji} +

+

+ Ep {s.episode} {timeStamptoHour(s.airingAt)} +

+
+ +

+ + ); + })} +
+
+ ))} +
+ )) + ) : ( +
+ +
+ ) + ) : !loading ? ( + Object.entries(filterScheduleByDay(sortedSchedule, filterDay)).map( + ([day, schedules]) => ( +
+

+ {day} +

+
+ {schedules.map((s) => { + const m = s.media; + + return ( + + {/*

*/} +

+ + {/* */} + + Next Airing + +

+

+ + + + Airing Now + +

+ image +
+

+ {m.title.romaji} +

+

+ Ep {s.episode} {timeStamptoHour(s.airingAt)} +

+
+ + ); + })} +
+
+ ) + ) + ) : ( +
+ +
+ )} +
+
+ + ); +} -- cgit v1.2.3