aboutsummaryrefslogtreecommitdiffstats
path: root/src/pages/events
diff options
context:
space:
mode:
authornolawz <amananudhiu@gmail.com>2026-03-03 04:04:23 +0530
committernolawz <amananudhiu@gmail.com>2026-03-03 04:04:23 +0530
commit45026eee4c93bbbe6141dd23a664abe6e9ff3ca2 (patch)
tree3d5762cb539d88cf1fc464ab07f9ecd49182ad08 /src/pages/events
parentd41eff9eccf66644c4c60f53cb516bf079937a28 (diff)
Added events section and components required for that
Diffstat (limited to 'src/pages/events')
-rw-r--r--src/pages/events/[...id].astro168
-rw-r--r--src/pages/events/[...page].astro60
2 files changed, 228 insertions, 0 deletions
diff --git a/src/pages/events/[...id].astro b/src/pages/events/[...id].astro
new file mode 100644
index 0000000..44d8ec4
--- /dev/null
+++ b/src/pages/events/[...id].astro
@@ -0,0 +1,168 @@
+---
+import Breadcrumbs from '@/components/Breadcrumbs.astro'
+import EventNavigation from '@/components/EventNavigation.astro'
+import TOCHeader from '@/components/TOCHeader.astro'
+import TOCSidebar from '@/components/TOCSidebar.astro'
+import { badgeVariants } from '@/components/ui/badge'
+import { Button } from '@/components/ui/button'
+import Layout from '@/layouts/Layout.astro'
+import {
+ getAdjacentEvents,
+ getAllEvents,
+ getTOCSections,
+} from '@/lib/data-utils'
+import { formatDate, iconMappings } from '@/lib/utils'
+import { Icon } from 'astro-icon/components'
+import { Image } from 'astro:assets'
+import { render } from 'astro:content'
+
+export async function getStaticPaths() {
+ const events = await getAllEvents()
+ return events.map((event) => ({
+ params: { id: event.id },
+ props: event,
+ }))
+}
+
+const event = Astro.props
+const currentPostId = Astro.params.id
+const navigation = await getAdjacentEvents(currentPostId)
+const { Content, headings } = await render(event)
+
+const tocSections = await getTOCSections(currentPostId)
+---
+
+<Layout>
+ {
+ headings?.length > 0 &&
+ !(headings.length === 1 && headings[0].text === event.data.title) && (
+ <TOCHeader slot="table-of-contents" headings={headings} />
+ )
+ }
+
+ <section
+ class="grid grid-cols-[minmax(0px,1fr)_min(calc(var(--breakpoint-md)-2rem),100%)_minmax(0px,1fr)] gap-y-6"
+ >
+ <div class="col-start-2">
+ <Breadcrumbs
+ items={[{ href: '/events', label: 'Events', icon: 'lucide:calendar' }]}
+ />
+ </div>
+
+ {
+ event.data.image && (
+ <Image
+ src={event.data.image}
+ alt={event.data.title}
+ width={1200}
+ height={630}
+ class="col-span-full mx-auto w-full max-w-5xl object-cover"
+ />
+ )
+ }
+
+ <section class="col-start-2 flex flex-col gap-y-6 text-center">
+ <div class="flex flex-col">
+ <h1
+ class="mb-2 scroll-mt-31 text-3xl leading-tight font-medium sm:text-4xl"
+ id="event-title"
+ >
+ {event.data.title}
+ </h1>
+
+ <div
+ class="text-muted-foreground divide-border mb-4 flex flex-col items-center justify-center divide-y text-xs sm:flex-row sm:flex-wrap sm:divide-x sm:divide-y-0 sm:text-sm"
+ >
+ <div
+ class="flex w-full items-center justify-center gap-2 py-2 sm:w-fit sm:px-2 sm:py-0 first:sm:pl-0 last:sm:pr-0"
+ >
+ <span>{formatDate(event.data.date)}</span>
+ </div>
+ </div>
+ <div class="flex flex-wrap justify-center gap-2">
+ {
+ event.data.type && (
+ <a
+ href={`/types/${event.data.type}`}
+ class={badgeVariants({ variant: 'muted' })}
+ >
+ <Icon
+ name={iconMappings[event.data.type] || 'lucide:hash'}
+ class="size-3"
+ />
+ {event.data.type}
+ </a>
+ )
+ }
+ </div>
+ </div>
+ </section>
+
+ {
+ tocSections.length > 0 && (
+ <TOCSidebar sections={tocSections} currentPostId={currentPostId} />
+ )
+ }
+
+ <article class="prose col-start-2 max-w-none">
+ <Content />
+ </article>
+
+ <EventNavigation
+ newerEvent={navigation.newer}
+ olderEvent={navigation.older}
+ />
+ </section>
+
+ <Button
+ variant="outline"
+ size="icon"
+ className="group fixed right-8 bottom-8 z-50 hidden"
+ id="scroll-to-top"
+ title="Scroll to top"
+ aria-label="Scroll to top"
+ >
+ <Icon
+ name="lucide:arrow-up"
+ class="mx-auto size-4 transition-all group-hover:-translate-y-0.5"
+ />
+ </Button>
+
+ <script>
+ document.addEventListener('astro:page-load', () => {
+ const scrollToTopButton = document.getElementById('scroll-to-top')
+ const footer = document.querySelector('footer')
+
+ if (scrollToTopButton && footer) {
+ scrollToTopButton.addEventListener('click', () => {
+ window.scrollTo({ top: 0, behavior: 'smooth' })
+ })
+
+ window.addEventListener('scroll', () => {
+ const footerRect = footer.getBoundingClientRect()
+ const isFooterVisible = footerRect.top <= window.innerHeight
+
+ scrollToTopButton.classList.toggle(
+ 'hidden',
+ window.scrollY <= 300 || isFooterVisible,
+ )
+ })
+ }
+ })
+ </script>
+</Layout>
+
+<script>
+ const ensureKatexStyles = () => {
+ if (!document.querySelector('.katex')) return
+ if (document.querySelector('link[href*="katex.min.css"]')) return
+
+ const link = document.createElement('link')
+ link.rel = 'stylesheet'
+ link.href = 'https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.css'
+ document.head.appendChild(link)
+ }
+
+ document.addEventListener('astro:page-load', ensureKatexStyles)
+ document.addEventListener('astro:after-swap', ensureKatexStyles)
+</script>
diff --git a/src/pages/events/[...page].astro b/src/pages/events/[...page].astro
new file mode 100644
index 0000000..2625ab0
--- /dev/null
+++ b/src/pages/events/[...page].astro
@@ -0,0 +1,60 @@
+---
+import Breadcrumbs from '@/components/Breadcrumbs.astro'
+import EventCard from '@/components/EventCard.astro'
+import PageHead from '@/components/PageHead.astro'
+import PaginationComponent from '@/components/ui/pagination'
+import { SITE } from '@/consts'
+import Layout from '@/layouts/Layout.astro'
+import { getAllEvents, groupEventsByYear } from '@/lib/data-utils'
+import type { PaginateFunction } from 'astro'
+
+export async function getStaticPaths({
+ paginate,
+}: {
+ paginate: PaginateFunction
+}) {
+ const allEvents = await getAllEvents()
+ return paginate(allEvents, { pageSize: SITE.eventsPerPage })
+}
+
+const { page } = Astro.props
+
+const eventsByYear = groupEventsByYear(page.data)
+const years = Object.keys(eventsByYear).sort(
+ (a, b) => parseInt(b) - parseInt(a),
+)
+---
+
+<Layout class="max-w-3xl">
+ <PageHead slot="head" title="Events" />
+ <Breadcrumbs
+ items={[
+ { label: 'Events', href: '/events', icon: 'lucide:calendar-range' },
+ { label: `Page ${page.currentPage}`, icon: 'lucide:calendar' },
+ ]}
+ />
+
+ <div class="flex min-h-[calc(100vh-18rem)] flex-col gap-y-8">
+ {
+ years.map((year) => (
+ <section class="flex flex-col gap-y-4">
+ <div class="font-medium">{year}</div>
+ <ul class="flex flex-col gap-4">
+ {eventsByYear[year].map((event) => (
+ <li>
+ <EventCard entry={event} />
+ </li>
+ ))}
+ </ul>
+ </section>
+ ))
+ }
+ </div>
+
+ <PaginationComponent
+ currentPage={page.currentPage}
+ totalPages={page.lastPage}
+ baseUrl="/events/"
+ client:load
+ />
+</Layout>