189 lines
6.2 KiB
TypeScript
Raw Normal View History

import Image from 'next/image'
2023-11-15 19:42:05 -08:00
import Link from 'next/link'
2023-11-15 19:42:05 -08:00
import { Card } from '@/components/Card'
import { Container } from '@/components/Container'
import { CalendarDaysIcon } from '@heroicons/react/24/solid'
2023-12-02 16:20:07 -08:00
import exteriorFrontImage from '@/images/photos/exterior-front.png'
2023-11-26 09:36:23 -08:00
import { type BlogPostWithSlug, getAllBlogPosts } from '@/lib/articles'
2023-11-15 19:42:05 -08:00
import { formatDate } from '@/lib/formatDate'
2024-01-28 10:04:06 -08:00
import { promises as fs } from 'fs';
2023-11-15 19:42:05 -08:00
function LinkButton({
href,
children,
}: {
href: string
children: React.ReactNode
}) {
return (
<Link
href={href}
className="rounded-md px-3 py-2 font-semibold text-center transition dark:hover:text-teal-400 bg-sky-300 hover:bg-sky-400 dark:bg-zinc-700/40 dark:hover:bg-zinc-600/40"
>
{children}
</Link>
)
}
2023-11-26 09:36:23 -08:00
function Article({ article }: { article: BlogPostWithSlug }) {
2023-11-15 19:42:05 -08:00
return (
<Card as="article">
2024-01-28 10:01:52 -08:00
<Card.Title href={`/news/${article.slug}`}>
2023-11-15 19:42:05 -08:00
{article.title}
</Card.Title>
<Card.Eyebrow as="time" dateTime={article.date} decorate>
{formatDate(article.date)}
</Card.Eyebrow>
<Card.Description>{article.description}</Card.Description>
<Card.Cta>Read article</Card.Cta>
</Card>
)
}
2023-11-29 20:21:12 -08:00
interface Meeting {
2023-11-15 19:42:05 -08:00
title: string
2023-11-29 20:21:12 -08:00
date: string
startTime: string
endTime?: string
notes?: string
2023-11-15 19:42:05 -08:00
}
2023-11-29 20:21:12 -08:00
function MeetingListItem({ meeting }: { meeting: Meeting }) {
2023-11-15 19:42:05 -08:00
return (
<li className="flex gap-4">
<dl className="flex flex-auto flex-wrap gap-x-2">
2023-11-29 20:21:12 -08:00
<dt className="sr-only">Title</dt>
2023-11-15 19:42:05 -08:00
<dd className="w-full flex-none text-sm font-medium text-zinc-900 dark:text-zinc-100">
2023-11-29 20:21:12 -08:00
{meeting.title}
2023-11-15 19:42:05 -08:00
</dd>
<dt className="sr-only">Date</dt>
2023-11-29 20:21:12 -08:00
<dd className="text-xs text-zinc-500 dark:text-zinc-400">
{meeting.date}
2023-11-15 19:42:05 -08:00
</dd>
2023-11-29 20:21:12 -08:00
<dt className="sr-only">Time</dt>
{meeting.endTime
? <dd
className="ml-auto text-xs text-zinc-400 dark:text-zinc-500"
aria-label={`${meeting.startTime} until ${meeting.endTime}`}
>
<time dateTime={meeting.date + ' ' + meeting.startTime}>{meeting.startTime}</time>{' '}
<span aria-hidden="true"></span>{' '}
<time dateTime={meeting.date + ' ' + meeting.endTime}>{meeting.endTime}</time>{' '}
</dd>
: <dd
className="ml-auto text-xs text-zinc-400 dark:text-zinc-500"
aria-label={`${meeting.startTime}`}
>
<time dateTime={meeting.date + ' ' + meeting.startTime}>{meeting.startTime}</time>{' '}
</dd>
}
2023-11-15 19:42:05 -08:00
</dl>
</li>
)
}
2024-01-28 10:04:06 -08:00
async function Events() {
const now = new Date();
const nowYear = now.getFullYear();
const nowMonth = now.getMonth() + 1;
const nowDay = now.getDate();
const file = await fs.readFile(process.cwd() + '/src/app/upcoming-events.json', 'utf8');
const allEvents: Array<Meeting> = JSON.parse(file);
// Remove any events in the past.
const events = allEvents.filter((e) => {
const [year, month, day] = e.date.split('-');
const parsedYear = parseInt(year)
if (parsedYear > nowYear) {
return true
} else if (parsedYear < nowYear) {
return false
}
const parsedMonth = parseInt(month)
if (parsedMonth > nowMonth) {
return true
} else if (parsedMonth < nowMonth) {
return false
}
const parsedDay = parseInt(day)
return parsedDay >= nowDay
});
2023-11-15 19:42:05 -08:00
return (
<div className="rounded-2xl border border-zinc-100 p-6 dark:border-zinc-700/40">
<h2 className="flex text-sm font-semibold text-zinc-900 dark:text-zinc-100">
2023-11-29 20:21:12 -08:00
<CalendarDaysIcon className="h-6 w-6 flex-none fill-zinc-100 stroke-zinc-400 dark:fill-zinc-100/10 dark:stroke-zinc-500" />
<span className="ml-3">Upcoming Events</span>
2023-11-15 19:42:05 -08:00
</h2>
<ol className="mt-6 space-y-4">
2023-11-29 20:21:12 -08:00
{events.map((meeting, idx) => (
<MeetingListItem key={idx} meeting={meeting} />
2023-11-15 19:42:05 -08:00
))}
</ol>
2024-01-08 14:43:03 -08:00
{/*
2023-11-15 19:42:05 -08:00
<Button href="#" variant="secondary" className="group mt-6 w-full">
2023-11-29 20:21:12 -08:00
Full Calendar
2023-11-15 19:42:05 -08:00
</Button>
2024-01-08 14:43:03 -08:00
*/}
2023-11-15 19:42:05 -08:00
</div>
)
}
export default async function Home() {
2023-11-26 09:36:23 -08:00
let articles = (await getAllBlogPosts()).slice(0, 4)
2023-11-15 19:42:05 -08:00
return (
<>
<div className="mx-auto max-w-7xl px-6 mt-24 lg:px-8">
<div className="relative px-4 sm:px-8 lg:px-12">
<div className="mx-auto max-w-2xl lg:mx-0 grid lg:max-w-none grid-cols-1 lg:grid-cols-2 lg:gap-x-8 gap-y-10">
2024-01-31 20:29:03 -08:00
<h1 className="text-4xl font-bold tracking-tight text-zinc-800 dark:text-zinc-100 sm:text-6xl lg:col-span-2">
West Sound Community Hall
</h1>
<div className="max-w-xl">
<p className="mt-6 text-base text-zinc-600 dark:text-zinc-400">
The West Sound Community Hall is located in the hamlet of West Sound
on Orcas Island, about 10 minutes from the ferry landing and
Eastsound. It has served as a public assembly hall since it was
built by volunteers in 1902.
</p>
<p className="mt-6 text-base text-zinc-600 dark:text-zinc-400">
Facing West Sound, the Hall is at the heart of the West Sound community.
</p>
</div>
<Image
src={exteriorFrontImage}
alt="Exterior front of the West Sound Hall"
className="lg:row-span-2 w-full max-w-xl rounded-2xl object-cover lg:max-w-none"
/>
<div className="h-fit max-w-xl rounded-2xl border border-zinc-100 p-6 dark:border-zinc-700/40">
<div className="flex flex-col gap-y-4">
<LinkButton href='/club'>Join or Renew your Membership</LinkButton>
<LinkButton href='/rental'>Rent the Hall</LinkButton>
</div>
</div>
</div>
2023-11-15 19:42:05 -08:00
</div>
</div>
2023-11-15 19:42:05 -08:00
<Container className="mt-24 md:mt-28">
<div className="mx-auto grid max-w-xl grid-cols-1 gap-y-20 lg:max-w-none lg:grid-cols-2">
<div className="flex flex-col gap-16">
{articles.map((article) => (
<Article key={article.slug} article={article} />
))}
</div>
<div className="lg:pl-16 xl:pl-24">
2023-11-29 20:21:12 -08:00
<Events />
2023-11-15 19:42:05 -08:00
</div>
</div>
</Container>
</>
)
}