diff --git a/app/[slug]/page.tsx b/app/[slug]/page.tsx index aecc9b6..cda6d6c 100644 --- a/app/[slug]/page.tsx +++ b/app/[slug]/page.tsx @@ -9,7 +9,7 @@ import { MenuItemActivator } from '@/app/menu' export async function generateStaticParams() { return allPages.map(page => ({ slug: page.slug, - })).filter(slug => slug) + })).filter(({ slug }) => slug) } export default function Page({ params }: { params: { slug: string } }) { diff --git a/app/assignments/assessment/[slug]/page.tsx b/app/assignments/assessment/[slug]/page.tsx index 3ee7e5a..ec30701 100644 --- a/app/assignments/assessment/[slug]/page.tsx +++ b/app/assignments/assessment/[slug]/page.tsx @@ -1,15 +1,16 @@ -import { allAssessments, allHomework } from 'contentlayer/generated' +import { allAssessments } from 'contentlayer/generated' import { notFound } from 'next/navigation' import { useMDXComponent } from 'next-contentlayer/hooks' import { mdxComponents } from '@/components/mdx' import { Card } from '@/components/Card' import { Prose } from '@/components/Prose' -import { MenuItemActivator } from '@/app/menu' export async function generateStaticParams() { + if (!allAssessments.length) return [{ slug: "dummy" }] + return allAssessments.map(page => ({ slug: page.slug, - })).filter(slug => slug) + })) } export default function Assessment({ params }: { params: { slug: string } }) { diff --git a/app/assignments/hw/[slug]/page.tsx b/app/assignments/hw/[slug]/page.tsx index f99e6a4..d7c9a2f 100644 --- a/app/assignments/hw/[slug]/page.tsx +++ b/app/assignments/hw/[slug]/page.tsx @@ -4,12 +4,13 @@ import { useMDXComponent } from 'next-contentlayer/hooks' import { mdxComponents } from '@/components/mdx' import { Card } from '@/components/Card' import { Prose } from '@/components/Prose' -import { MenuItemActivator } from '@/app/menu' export async function generateStaticParams() { + if (!allHomework.length) return [{ slug: "dummy" }] + return allHomework.map(page => ({ slug: page.slug, - })).filter(slug => slug) + })) } export default function Homework({ params }: { params: { slug: string } }) { diff --git a/app/assignments/page.tsx b/app/assignments/page.tsx index c8ea255..13f801d 100644 --- a/app/assignments/page.tsx +++ b/app/assignments/page.tsx @@ -1,8 +1,7 @@ import { allHomework, allAssessments } from 'contentlayer/generated' import { Card } from '@/components/Card' -import { MenuItemActivator } from '@/app/menu' import Link from 'next/link' -import { format } from 'date-fns' +import { FormattedDate } from '@/components/FormattedDate' type Assignment = { title: string @@ -70,11 +69,11 @@ function AssignmentRow({ title, href, isReleased, releaseDate, dates }: Assignme {isReleased ? {title} : - {title}{releaseDate && <> (available {format(releaseDate, "M/d")})}} + {title}{releaseDate && <> (available )}} {dates.map((item, index) =>
- {item.name} {format(item.date, item.specifyTime ? "E, M/d @ h:mmaa" : "E, M/d")} + {item.name}
)} diff --git a/app/layout.tsx b/app/layout.tsx index 21760fd..9045335 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,6 +1,7 @@ import "@/styles/global.css" import "prism-themes/themes/prism-atom-dark.css" import { Menu, MenuContextProvider } from "./menu" +import { TimezoneNotice } from "@/components/TimezoneNotice" export const metadata = { title: 'Next.js', @@ -24,7 +25,12 @@ export default function RootLayout({
-
{children}
+
+ {children} +
+ +
+
diff --git a/app/menu.tsx b/app/menu.tsx index 212c90e..9b1b9e8 100644 --- a/app/menu.tsx +++ b/app/menu.tsx @@ -55,15 +55,10 @@ export function MenuContextProvider({ children }: { children: ReactNode }) { const pathname = usePathname() const [activeState, setActiveState] = useState<{ item: string | null, pathname: string }>({ item: null, pathname }) - useEffect(() => { - if (activeState.pathname !== pathname) { - setActiveState({ item: null, pathname }) - } - }, [pathname]) - return diff --git a/components/FormattedDate.tsx b/components/FormattedDate.tsx new file mode 100644 index 0000000..8ddae19 --- /dev/null +++ b/components/FormattedDate.tsx @@ -0,0 +1,25 @@ +"use client" + +import { useEffect, useState } from "react" +import locale from "date-fns/locale/en-US" +import { formatInTimeZone } from "date-fns-tz" +import { format } from "date-fns" + +export type FormattedDateProps = { + date: Date + format: string +} + +const defaultTimezone = "America/New_York" + +export function FormattedDate({ date, format: formatStr }: FormattedDateProps) { + const [value, setValue] = useState(formatInTimeZone(date, defaultTimezone, formatStr, { + locale, + })) + + useEffect(() => { + setValue(format(date, formatStr)) + }, [date, formatStr]) + + return value +} \ No newline at end of file diff --git a/components/TimezoneNotice.tsx b/components/TimezoneNotice.tsx new file mode 100644 index 0000000..953eb6c --- /dev/null +++ b/components/TimezoneNotice.tsx @@ -0,0 +1,13 @@ +"use client" + +import { useEffect, useState } from "react"; + +export function TimezoneNotice() { + const [isUsingLocalTimezone, setUsingLocalTimezone] = useState(false) + useEffect(() => { + setUsingLocalTimezone(true) + }, []) + + if (isUsingLocalTimezone) return "Dates and times are displayed in your local time zone." + return "Dates and times are displayed in EST." +} \ No newline at end of file diff --git a/content/pages/index.mdx b/content/pages/index.mdx index eeb8047..863bea8 100644 --- a/content/pages/index.mdx +++ b/content/pages/index.mdx @@ -11,6 +11,8 @@ customLayout: true Upcoming Assignments} margin> + **NOTE:** This component is currently broken. It only shows upcoming assignments at page build time, not at view time. + diff --git a/package-lock.json b/package-lock.json index 1f5fad9..df94109 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,8 @@ "@next/mdx": "^14.0.4", "@types/mdx": "^2.0.10", "contentlayer": "^0.3.4", - "date-fns": "^3.0.6", + "date-fns": "^2.30.0", + "date-fns-tz": "^2.0.0", "next": "^14.0.4", "next-contentlayer": "^0.3.4", "prism-themes": "^1.9.0" @@ -3523,12 +3524,26 @@ } }, "node_modules/date-fns": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.0.6.tgz", - "integrity": "sha512-W+G99rycpKMMF2/YD064b2lE7jJGUe+EjOES7Q8BIGY8sbNdbgcs9XFTZwvzc9Jx1f3k7LB7gZaZa7f8Agzljg==", + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/date-fns-tz": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.0.tgz", + "integrity": "sha512-OAtcLdB9vxSXTWHdT8b398ARImVwQMyjfYGkKD2zaGpHseG2UPHbHjXELReErZFxWdSLph3c2zOaaTyHfOhERQ==", + "peerDependencies": { + "date-fns": ">=2.0.0" } }, "node_modules/debug": { diff --git a/package.json b/package.json index f8c4ce8..4488278 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "@next/mdx": "^14.0.4", "@types/mdx": "^2.0.10", "contentlayer": "^0.3.4", - "date-fns": "^3.0.6", + "date-fns": "^2.30.0", + "date-fns-tz": "^2.0.0", "next": "^14.0.4", "next-contentlayer": "^0.3.4", "prism-themes": "^1.9.0"