Compare commits
No commits in common. "52ec6d7b8169d3e4635141ffe48372d29d938bd0" and "283b5d8a49b6eddb0a35fe26050d008565a43af7" have entirely different histories.
52ec6d7b81
...
283b5d8a49
54
README.md
54
README.md
@ -1,41 +1,10 @@
|
|||||||
# West Sound Hall Website
|
# Spotlight
|
||||||
|
|
||||||
This is the website for the West Sound Hall and Community Club on Orcas Island, WA.
|
Spotlight is a [Tailwind UI](https://tailwindui.com) site template built using [Tailwind CSS](https://tailwindcss.com) and [Next.js](https://nextjs.org).
|
||||||
|
|
||||||
https://westsoundhall.org
|
## Getting started
|
||||||
|
|
||||||
## Running
|
To get started with this template, first install the npm dependencies:
|
||||||
|
|
||||||
Pre-build containers are created whenever a version is tagged in this
|
|
||||||
repository. Pull the [latest
|
|
||||||
version](https://git.grosinger.net/tgrosinger/-/packages/container/west-sound-hall/)
|
|
||||||
and run on a server with Docker available.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker run -p 3000:3000 git.grosinger.net/tgrosinger/west-sound-hall:0.0.14
|
|
||||||
```
|
|
||||||
|
|
||||||
## Updating
|
|
||||||
|
|
||||||
### Events on the Homepage
|
|
||||||
|
|
||||||
The homepage has a list of upcoming events. This list is created from [`src/app/upcoming-events.json`](https://git.grosinger.net/tgrosinger/west-sound-hall/src/branch/main/src/app/upcoming-events.json). To update the events listed, modify that file, tag a new version, and then update the running container to the latest version.
|
|
||||||
|
|
||||||
Events in the past will be automatically hidden from view.
|
|
||||||
|
|
||||||
### News Posts
|
|
||||||
|
|
||||||
News posts are written in [`src/app/news`](https://git.grosinger.net/tgrosinger/west-sound-hall/src/branch/main/src/app/news). Each post requires a directory within this folder, and the directory title will become the last segment of the news post URL.
|
|
||||||
|
|
||||||
To create a new post, create a new directory in that folder, then within that folder create a `page.mdx`. Use an existing news post as a template by copying its `page.mdx` then modify the author, date, title, description, and the body of the post as needed.
|
|
||||||
|
|
||||||
Posts are written in [mdx](https://mdxjs.com/) however for most news posts you can just consider the body of the post to be [standard markdown](https://www.markdownguide.org/basic-syntax/).
|
|
||||||
|
|
||||||
Photos can be added in the same directory as the `page.mdx` file. Refer to another news post for an example of how to embed them.
|
|
||||||
|
|
||||||
## Developing
|
|
||||||
|
|
||||||
To get started, first install the npm dependencies:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install
|
npm install
|
||||||
@ -55,8 +24,19 @@ npm run dev
|
|||||||
|
|
||||||
Finally, open [http://localhost:3000](http://localhost:3000) in your browser to view the website.
|
Finally, open [http://localhost:3000](http://localhost:3000) in your browser to view the website.
|
||||||
|
|
||||||
|
## Customizing
|
||||||
|
|
||||||
|
You can start editing this template by modifying the files in the `/src` folder. The site will auto-update as you edit these files.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This site is based off of the Spotlight template from Tailwind, and licensed under the [Tailwind UI license](https://tailwindui.com/license).
|
This site template is a commercial product and is licensed under the [Tailwind UI license](https://tailwindui.com/license).
|
||||||
|
|
||||||
It was purchased by Tony Grosinger.
|
## Learn more
|
||||||
|
|
||||||
|
To learn more about the technologies used in this site template, see the following resources:
|
||||||
|
|
||||||
|
- [Tailwind CSS](https://tailwindcss.com/docs) - the official Tailwind CSS documentation
|
||||||
|
- [Next.js](https://nextjs.org/docs) - the official Next.js documentation
|
||||||
|
- [Headless UI](https://headlessui.dev) - the official Headless UI documentation
|
||||||
|
- [MDX](https://mdxjs.com) - the MDX documentation
|
||||||
|
@ -9,7 +9,7 @@ function Article({ article }: { article: BlogPostWithSlug }) {
|
|||||||
return (
|
return (
|
||||||
<article className="md:grid md:grid-cols-4 md:items-baseline">
|
<article className="md:grid md:grid-cols-4 md:items-baseline">
|
||||||
<Card className="md:col-span-3">
|
<Card className="md:col-span-3">
|
||||||
<Card.Title href={`/news/${article.slug}`}>
|
<Card.Title href={`/blog/${article.slug}`}>
|
||||||
{article.title}
|
{article.title}
|
||||||
</Card.Title>
|
</Card.Title>
|
||||||
<Card.Eyebrow
|
<Card.Eyebrow
|
||||||
@ -35,7 +35,7 @@ function Article({ article }: { article: BlogPostWithSlug }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'Club News',
|
title: 'Blog',
|
||||||
description: 'History, Announcements, and more from the West Sound Hall and Community Club.',
|
description: 'History, Announcements, and more from the West Sound Hall and Community Club.',
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ export default async function ArticlesIndex() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<SimpleLayout
|
<SimpleLayout
|
||||||
title="West Sound Hall News"
|
title="West Sound Hall Blog"
|
||||||
intro="History, Announcements, and more from the West Sound Hall and Community Club."
|
intro="History, Announcements, and more from the West Sound Hall and Community Club."
|
||||||
>
|
>
|
||||||
<div className="md:border-l md:border-zinc-100 md:pl-6 md:dark:border-zinc-700/40">
|
<div className="md:border-l md:border-zinc-100 md:pl-6 md:dark:border-zinc-700/40">
|
Before Width: | Height: | Size: 644 KiB After Width: | Height: | Size: 644 KiB |
@ -59,6 +59,7 @@ function CheckoutForm({
|
|||||||
const [selectedAdditionalDonation, setSelectedAdditionalDonation] = useState<number | null>(null);
|
const [selectedAdditionalDonation, setSelectedAdditionalDonation] = useState<number | null>(null);
|
||||||
const [customAmount, setCustomAmount] = useState('');
|
const [customAmount, setCustomAmount] = useState('');
|
||||||
const [email, setEmail] = useState('');
|
const [email, setEmail] = useState('');
|
||||||
|
const [offsetFees, setOffsetFees] = useState(true);
|
||||||
const [totalAmount, setTotalAmount] = useState(300);
|
const [totalAmount, setTotalAmount] = useState(300);
|
||||||
const [message, setMessage] = useState<string>('');
|
const [message, setMessage] = useState<string>('');
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
@ -110,7 +111,9 @@ function CheckoutForm({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (offsetFees) {
|
||||||
subtotal = Math.ceil(subtotal * 1.03)
|
subtotal = Math.ceil(subtotal * 1.03)
|
||||||
|
}
|
||||||
|
|
||||||
setTotalAmount(subtotal);
|
setTotalAmount(subtotal);
|
||||||
|
|
||||||
@ -125,7 +128,7 @@ function CheckoutForm({
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
}, [paymentIntentID, selectedMembershipLevel, selectedAdditionalDonation, customAmount, email])
|
}, [paymentIntentID, selectedMembershipLevel, selectedAdditionalDonation, customAmount, offsetFees, email])
|
||||||
|
|
||||||
const handleSubmit = async (e: FormEvent) => {
|
const handleSubmit = async (e: FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -300,16 +303,33 @@ function CheckoutForm({
|
|||||||
Payment
|
Payment
|
||||||
</h2>
|
</h2>
|
||||||
<div className="mt-1 text-sm text-gray-500">
|
<div className="mt-1 text-sm text-gray-500">
|
||||||
Credit card fees included. If you would like to avoid these fees or
|
If you would like to pay by cash or check, please instead
|
||||||
to pay by cash or check, please instead <a className="underline
|
<a className="underline mx-1" href="/WSCC-Membership-Form.pdf">fill out a paper form</a>
|
||||||
mx-1" href="/WSCC-Membership-Form.pdf">fill out a paper form</a> and
|
and mail to the address on the form.
|
||||||
mail to the address on the form.
|
|
||||||
</div>
|
</div>
|
||||||
<PaymentElement id="payment-element" />
|
<PaymentElement id="payment-element" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* TODO: Automatically renew toggle? */}
|
{/* TODO: Automatically renew toggle? */}
|
||||||
|
|
||||||
|
<div className="relative flex gap-x-3">
|
||||||
|
<div className="flex h-6 items-center">
|
||||||
|
<input
|
||||||
|
id="offsetFees"
|
||||||
|
name="offsetFees"
|
||||||
|
type="checkbox"
|
||||||
|
checked={offsetFees}
|
||||||
|
onChange={(e) => setOffsetFees(e.target.checked)}
|
||||||
|
className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-600"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="text-sm leading-6">
|
||||||
|
<label htmlFor="offsetFees" className="font-medium text-gray-900">
|
||||||
|
Help offset credit card fees
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className="mt-6 w-full rounded-md flex justify-center border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
className="mt-6 w-full rounded-md flex justify-center border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
||||||
disabled={isLoading || !stripe || !elements}
|
disabled={isLoading || !stripe || !elements}
|
||||||
|
@ -36,17 +36,17 @@ export async function GET(req: Request) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let articleIds = require
|
let articleIds = require
|
||||||
.context('../news', true, /\/page\.mdx$/)
|
.context('../blog', true, /\/page\.mdx$/)
|
||||||
.keys()
|
.keys()
|
||||||
.filter((key) => key.startsWith('./'))
|
.filter((key) => key.startsWith('./'))
|
||||||
.map((key) => key.slice(2).replace(/\/page\.mdx$/, ''));
|
.map((key) => key.slice(2).replace(/\/page\.mdx$/, ''));
|
||||||
|
|
||||||
for (let id of articleIds) {
|
for (let id of articleIds) {
|
||||||
let url = String(new URL(`/news/${id}`, req.url));
|
let url = String(new URL(`/blog/${id}`, req.url));
|
||||||
let html = await (await fetch(url)).text();
|
let html = await (await fetch(url)).text();
|
||||||
let $ = cheerio.load(html);
|
let $ = cheerio.load(html);
|
||||||
|
|
||||||
let publicUrl = `${siteUrl}/news/${id}`;
|
let publicUrl = `${siteUrl}/blog/${id}`;
|
||||||
let article = $('article').first();
|
let article = $('article').first();
|
||||||
let title = article.find('h1').first().text();
|
let title = article.find('h1').first().text();
|
||||||
let date = article.find('time').first().attr('datetime');
|
let date = article.find('time').first().attr('datetime');
|
||||||
|
125
src/app/page.tsx
125
src/app/page.tsx
@ -1,14 +1,17 @@
|
|||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
|
import clsx from 'clsx'
|
||||||
|
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { Card } from '@/components/Card'
|
import { Card } from '@/components/Card'
|
||||||
import { Container } from '@/components/Container'
|
import { Container } from '@/components/Container'
|
||||||
import { CalendarDaysIcon } from '@heroicons/react/24/solid'
|
import { CalendarDaysIcon, EnvelopeIcon } from '@heroicons/react/24/solid'
|
||||||
import exteriorFrontImage from '@/images/photos/exterior-front.png'
|
import exteriorFrontImage from '@/images/photos/exterior-front.png'
|
||||||
|
import stageImage from '@/images/photos/stage.jpg'
|
||||||
|
import exteriorSoutheastImage from '@/images/photos/exterior-southeast.jpg'
|
||||||
|
import interorEmptyImage from '@/images/photos/interior-empty.jpg'
|
||||||
|
import kitchenImage from '@/images/photos/kitchen.jpg'
|
||||||
import { type BlogPostWithSlug, getAllBlogPosts } from '@/lib/articles'
|
import { type BlogPostWithSlug, getAllBlogPosts } from '@/lib/articles'
|
||||||
import { formatDate } from '@/lib/formatDate'
|
import { formatDate } from '@/lib/formatDate'
|
||||||
import { promises as fs } from 'fs';
|
|
||||||
|
|
||||||
|
|
||||||
function LinkButton({
|
function LinkButton({
|
||||||
href,
|
href,
|
||||||
@ -20,7 +23,9 @@ function LinkButton({
|
|||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
href={href}
|
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"
|
className="rounded-md px-3 py-2 font-semibold text-center transition hover:text-teal-500 dark:hover:text-teal-400 bg-zinc-200 hover:bg-zinc-100 dark:bg-zinc-700/40 dark:hover:bg-zinc-600/40"
|
||||||
|
|
||||||
|
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Link>
|
</Link>
|
||||||
@ -30,7 +35,7 @@ function LinkButton({
|
|||||||
function Article({ article }: { article: BlogPostWithSlug }) {
|
function Article({ article }: { article: BlogPostWithSlug }) {
|
||||||
return (
|
return (
|
||||||
<Card as="article">
|
<Card as="article">
|
||||||
<Card.Title href={`/news/${article.slug}`}>
|
<Card.Title href={`/blog/${article.slug}`}>
|
||||||
{article.title}
|
{article.title}
|
||||||
</Card.Title>
|
</Card.Title>
|
||||||
<Card.Eyebrow as="time" dateTime={article.date} decorate>
|
<Card.Eyebrow as="time" dateTime={article.date} decorate>
|
||||||
@ -42,6 +47,17 @@ function Article({ article }: { article: BlogPostWithSlug }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Newsletter() {
|
||||||
|
return (
|
||||||
|
<div className="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>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
interface Meeting {
|
interface Meeting {
|
||||||
title: string
|
title: string
|
||||||
date: string
|
date: string
|
||||||
@ -84,36 +100,21 @@ function MeetingListItem({ meeting }: { meeting: Meeting }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function Events() {
|
function Events() {
|
||||||
const now = new Date();
|
let events: Array<Meeting> = [
|
||||||
const nowYear = now.getFullYear();
|
{
|
||||||
const nowMonth = now.getMonth() + 1;
|
title: 'January Potluck',
|
||||||
const nowDay = now.getDate();
|
date: '2024-01-20',
|
||||||
|
startTime: '6:00pm',
|
||||||
const file = await fs.readFile(process.cwd() + '/src/app/upcoming-events.json', 'utf8');
|
},
|
||||||
const allEvents: Array<Meeting> = JSON.parse(file);
|
{
|
||||||
|
title: 'February Potluck',
|
||||||
// Remove any events in the past.
|
date: '2024-02-17',
|
||||||
const events = allEvents.filter((e) => {
|
startTime: '6:00pm',
|
||||||
const [year, month, day] = e.date.split('-');
|
// endTime: '8:00pm',
|
||||||
|
// notes: 'Bring your own chair.'
|
||||||
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
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="rounded-2xl border border-zinc-100 p-6 dark:border-zinc-700/40">
|
<div className="rounded-2xl border border-zinc-100 p-6 dark:border-zinc-700/40">
|
||||||
@ -135,18 +136,43 @@ async function Events() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Photos() {
|
||||||
|
let rotations = ['rotate-2', '-rotate-2', 'rotate-2', 'rotate-2', '-rotate-2']
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-16 sm:mt-20">
|
||||||
|
<div className="-my-4 flex justify-center gap-5 overflow-hidden py-4 sm:gap-8">
|
||||||
|
{[exteriorSoutheastImage, stageImage, exteriorFrontImage, interorEmptyImage, kitchenImage].map((image, imageIndex) => (
|
||||||
|
<div
|
||||||
|
key={image.src}
|
||||||
|
className={clsx(
|
||||||
|
'relative aspect-[9/10] w-44 flex-none overflow-hidden rounded-xl bg-zinc-100 dark:bg-zinc-800 sm:w-72 sm:rounded-2xl',
|
||||||
|
rotations[imageIndex % rotations.length],
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src={image}
|
||||||
|
alt=""
|
||||||
|
sizes="(min-width: 640px) 18rem, 11rem"
|
||||||
|
className="absolute inset-0 h-full w-full object-cover"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export default async function Home() {
|
export default async function Home() {
|
||||||
let articles = (await getAllBlogPosts()).slice(0, 4)
|
let articles = (await getAllBlogPosts()).slice(0, 4)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="mx-auto max-w-7xl px-6 mt-24 lg:px-8">
|
<Container className="mt-9">
|
||||||
<div className="relative px-4 sm:px-8 lg:px-12">
|
<div className="max-w-2xl">
|
||||||
<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">
|
<h1 className="text-4xl font-bold tracking-tight text-zinc-800 dark:text-zinc-100 sm:text-5xl">
|
||||||
<h1 className="text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl lg:col-span-2">
|
|
||||||
West Sound Community Hall
|
West Sound Community Hall
|
||||||
</h1>
|
</h1>
|
||||||
<div className="max-w-xl">
|
|
||||||
<p className="mt-6 text-base text-zinc-600 dark:text-zinc-400">
|
<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
|
The West Sound Community Hall is located in the hamlet of West Sound
|
||||||
on Orcas Island, about 10 minutes from the ferry landing and
|
on Orcas Island, about 10 minutes from the ferry landing and
|
||||||
@ -157,20 +183,8 @@ export default async function Home() {
|
|||||||
Facing West Sound, the Hall is at the heart of the West Sound community.
|
Facing West Sound, the Hall is at the heart of the West Sound community.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Image
|
</Container>
|
||||||
src={exteriorFrontImage}
|
<Photos />
|
||||||
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>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Container className="mt-24 md:mt-28">
|
<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="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">
|
<div className="flex flex-col gap-16">
|
||||||
@ -178,7 +192,8 @@ export default async function Home() {
|
|||||||
<Article key={article.slug} article={article} />
|
<Article key={article.slug} article={article} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="lg:pl-16 xl:pl-24">
|
<div className="space-y-10 lg:pl-16 xl:pl-24">
|
||||||
|
<Newsletter />
|
||||||
<Events />
|
<Events />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"title": "January Potluck",
|
|
||||||
"date": "2024-01-20",
|
|
||||||
"startTime": "6:00pm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "February Potluck",
|
|
||||||
"date": "2024-02-17",
|
|
||||||
"startTime": "6:00pm",
|
|
||||||
"notes": "With historic West Sound slide show."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Town Hall Meeting",
|
|
||||||
"date": "2024-03-06",
|
|
||||||
"startTime": "6:00pm",
|
|
||||||
"endTime": "8:00pm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "March Potluck",
|
|
||||||
"date": "2024-03-16",
|
|
||||||
"startTime": "6:00pm"
|
|
||||||
}
|
|
||||||
]
|
|
@ -28,7 +28,6 @@ export function Footer() {
|
|||||||
<div className="flex flex-col items-center justify-between gap-6 sm:flex-row">
|
<div className="flex flex-col items-center justify-between gap-6 sm:flex-row">
|
||||||
<div className="flex flex-wrap justify-center gap-x-6 gap-y-1 text-sm font-medium text-zinc-800 dark:text-zinc-200">
|
<div className="flex flex-wrap justify-center gap-x-6 gap-y-1 text-sm font-medium text-zinc-800 dark:text-zinc-200">
|
||||||
<NavLink href="/hall-history">History</NavLink>
|
<NavLink href="/hall-history">History</NavLink>
|
||||||
<NavLink href="/news">News</NavLink>
|
|
||||||
<NavLink href="/rental">Rental</NavLink>
|
<NavLink href="/rental">Rental</NavLink>
|
||||||
<NavLink href="/club">Club</NavLink>
|
<NavLink href="/club">Club</NavLink>
|
||||||
</div>
|
</div>
|
||||||
|
File diff suppressed because one or more lines are too long
@ -12,7 +12,7 @@ export interface BlogPostWithSlug extends BlogPost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function importBlogPost(filename: string): Promise<BlogPostWithSlug> {
|
async function importBlogPost(filename: string): Promise<BlogPostWithSlug> {
|
||||||
let { article } = (await import(`../app/news/${filename}`)) as {
|
let { article } = (await import(`../app/blog/${filename}`)) as {
|
||||||
default: React.ComponentType;
|
default: React.ComponentType;
|
||||||
article: BlogPost;
|
article: BlogPost;
|
||||||
};
|
};
|
||||||
@ -25,7 +25,7 @@ async function importBlogPost(filename: string): Promise<BlogPostWithSlug> {
|
|||||||
|
|
||||||
export async function getAllBlogPosts() {
|
export async function getAllBlogPosts() {
|
||||||
let articleFilenames = await glob('*/page.mdx', {
|
let articleFilenames = await glob('*/page.mdx', {
|
||||||
cwd: './src/app/news',
|
cwd: './src/app/blog',
|
||||||
});
|
});
|
||||||
|
|
||||||
const posts = await Promise.all(articleFilenames.map(importBlogPost));
|
const posts = await Promise.all(articleFilenames.map(importBlogPost));
|
||||||
|
Loading…
Reference in New Issue
Block a user