From 45026eee4c93bbbe6141dd23a664abe6e9ff3ca2 Mon Sep 17 00:00:00 2001 From: nolawz Date: Tue, 3 Mar 2026 04:04:23 +0530 Subject: Added events section and components required for that --- src/components/EventCard.astro | 63 +++++++++++++ src/components/EventNavigation.astro | 54 +++++++++++ src/components/Footer.astro | 4 +- src/consts.ts | 6 ++ src/content.config.ts | 16 +++- src/content/events/beginning/index.mdx | 9 ++ src/content/events/second/index.mdx | 8 ++ src/lib/data-utils.ts | 54 +++++++++++ src/lib/utils.ts | 10 ++ src/pages/events/[...id].astro | 168 +++++++++++++++++++++++++++++++++ src/pages/events/[...page].astro | 60 ++++++++++++ src/pages/index.astro | 90 ++++++++---------- src/pages/types/[...id].astro | 53 +++++++++++ src/pages/types/index.astro | 35 +++++++ src/types.ts | 2 + 15 files changed, 577 insertions(+), 55 deletions(-) create mode 100644 src/components/EventCard.astro create mode 100644 src/components/EventNavigation.astro create mode 100644 src/content/events/beginning/index.mdx create mode 100644 src/content/events/second/index.mdx create mode 100644 src/pages/events/[...id].astro create mode 100644 src/pages/events/[...page].astro create mode 100644 src/pages/types/[...id].astro create mode 100644 src/pages/types/index.astro (limited to 'src') diff --git a/src/components/EventCard.astro b/src/components/EventCard.astro new file mode 100644 index 0000000..b615c2d --- /dev/null +++ b/src/components/EventCard.astro @@ -0,0 +1,63 @@ +--- +import { Badge } from '@/components/ui/badge' +import { formatDate, iconMappings } from '@/lib/utils' +import { Icon } from 'astro-icon/components' +import { Image } from 'astro:assets' +import type { CollectionEntry } from 'astro:content' +import Link from './Link.astro' + +interface Props { + entry: CollectionEntry<'events'> +} + +const { entry } = Astro.props +const formattedDate = formatDate(entry.data.date) +--- + +
+ + { + entry.data.image && ( +
+ {entry.data.title} +
+ ) + } + +
+

{entry.data.title}

+

{entry.data.description}

+ +
+ {formattedDate} +
+ + { + entry.data.type && ( +
+ + + {entry.data.type} + +
+ ) + } +
+ +
diff --git a/src/components/EventNavigation.astro b/src/components/EventNavigation.astro new file mode 100644 index 0000000..f1b76ce --- /dev/null +++ b/src/components/EventNavigation.astro @@ -0,0 +1,54 @@ +--- +import Link from '@/components/Link.astro' +import { buttonVariants } from '@/components/ui/button' +import { cn } from '@/lib/utils' +import { Icon } from 'astro-icon/components' + +const { newerEvent, olderEvent } = Astro.props +--- + + diff --git a/src/components/Footer.astro b/src/components/Footer.astro index 7ff1e50..6b37226 100644 --- a/src/components/Footer.astro +++ b/src/components/Footer.astro @@ -15,10 +15,10 @@ import SocialIcons from './SocialIcons.astro'

Made with 🤍 by enscribefosscet!

diff --git a/src/consts.ts b/src/consts.ts index 53d9f3a..c66ef3e 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -8,7 +8,9 @@ export const SITE: Site = { author: 'fosscet', locale: 'en-US', featuredPostCount: 2, + featuredEventsCount: 2, postsPerPage: 3, + eventsPerPage: 3, } export const NAV_LINKS: SocialLink[] = [ @@ -24,6 +26,10 @@ export const NAV_LINKS: SocialLink[] = [ href: '/about', label: 'about', }, + { + href: '/events', + label: 'events', + }, ] export const SOCIAL_LINKS: SocialLink[] = [ diff --git a/src/content.config.ts b/src/content.config.ts index ed8186c..1c01708 100644 --- a/src/content.config.ts +++ b/src/content.config.ts @@ -1,6 +1,20 @@ import { glob } from 'astro/loaders' import { defineCollection, z } from 'astro:content' +const events = defineCollection({ + loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/events' }), + schema: ({ image }) => + z.object({ + title: z.string(), + description: z.string(), + date: z.coerce.date(), + order: z.number().optional(), + image: image().optional(), + type: z.string().optional(), + draft: z.boolean().optional(), + }), +}) + const blog = defineCollection({ loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/blog' }), schema: ({ image }) => @@ -46,4 +60,4 @@ const projects = defineCollection({ }), }) -export const collections = { blog, authors, projects } +export const collections = { events, blog, authors, projects } diff --git a/src/content/events/beginning/index.mdx b/src/content/events/beginning/index.mdx new file mode 100644 index 0000000..7427578 --- /dev/null +++ b/src/content/events/beginning/index.mdx @@ -0,0 +1,9 @@ +--- +title: '2024 Event' +description: 'This is a dummy event conducted in the year 2024.' +date: 2024-06-01 +type: 'workshop' +--- + + +Just for testing purposes only diff --git a/src/content/events/second/index.mdx b/src/content/events/second/index.mdx new file mode 100644 index 0000000..79661e6 --- /dev/null +++ b/src/content/events/second/index.mdx @@ -0,0 +1,8 @@ +--- +title: '2025 Competition' +description: 'This is a competition event conducted in 2025.' +date: 2025-12-01 +type: 'competition' +--- + +I will prbbly create a component for adding the result of competition in the near future diff --git a/src/lib/data-utils.ts b/src/lib/data-utils.ts index f6e566a..ab0176f 100644 --- a/src/lib/data-utils.ts +++ b/src/lib/data-utils.ts @@ -21,6 +21,25 @@ export async function getAllPostsAndSubposts(): Promise< .sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()) } +export async function getAllEvents(): Promise[]> { + const events = await getCollection('events') + return events + .sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()) +} + +export function groupEventsByYear( + events: CollectionEntry<'events'>[], +): Record[]> { + return events.reduce( + (acc: Record[]>, post) => { + const year = post.data.date.getFullYear().toString() + ;(acc[year] ??= []).push(post) + return acc + }, + {}, + ) +} + export async function getAllProjects(): Promise[]> { const projects = await getCollection('projects') return projects.sort((a, b) => { @@ -40,6 +59,14 @@ export async function getAllTags(): Promise> { }, new Map()) } +export async function getAllTypes(): Promise> { + const events = await getAllEvents() + return events.reduce((acc, event) => { + acc.set(event.data.type, (acc.get(event.data.type) || 0) + 1) + return acc + }, new Map()) +} + export async function getAdjacentPosts(currentId: string): Promise<{ newer: CollectionEntry<'blog'> | null older: CollectionEntry<'blog'> | null @@ -99,6 +126,19 @@ export async function getAdjacentPosts(currentId: string): Promise<{ } } +export async function getAdjacentEvents(currentId: string): Promise<{ + newer: CollectionEntry<'events'> | null + older: CollectionEntry<'events'> | null + parent: CollectionEntry<'events'> | null +}> { + const allEvents = await getAllEvents() + const currentIndex = allEvents.findIndex((event) => event.id === currentId) + const newer = currentIndex > 0 ? allEvents[currentIndex - 1] : null + const older = + currentIndex < allEvents.length - 1 ? allEvents[currentIndex + 1] : null + return { newer, older, parent: null } +} + export async function getPostsByAuthor( authorId: string, ): Promise[]> { @@ -113,6 +153,13 @@ export async function getPostsByTag( return posts.filter((post) => post.data.tags?.includes(tag)) } +export async function getEventsByType( + type: string, +): Promise[]> { + const events = await getAllEvents() + return events.filter((event) => event.data.type === type) +} + export async function getRecentPosts( count: number, ): Promise[]> { @@ -120,6 +167,13 @@ export async function getRecentPosts( return posts.slice(0, count) } +export async function getRecentEvents( + count: number, +): Promise[]> { + const events = await getAllEvents() + return events.slice(0, count) +} + export async function getSortedTags(): Promise< { tag: string; count: number }[] > { diff --git a/src/lib/utils.ts b/src/lib/utils.ts index d4d8119..e2e005b 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -35,3 +35,13 @@ export function getHeadingMargin(depth: number): string { } return margins[depth] || '' } +export function capitalizeFirstLetter(val: string): string { + return String(val).charAt(0).toUpperCase() + String(val).slice(1); +} + +export const iconMappings = { + "workshop": "lucide:hammer", + "competition": "lucide:trophy", + "game": "lucide:gamepad-2", + "quiz": "lucide:brain" +} 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) +--- + + + { + headings?.length > 0 && + !(headings.length === 1 && headings[0].text === event.data.title) && ( + + ) + } + +
+
+ +
+ + { + event.data.image && ( + {event.data.title} + ) + } + +
+
+

+ {event.data.title} +

+ +
+
+ {formatDate(event.data.date)} +
+
+
+ { + event.data.type && ( + + + {event.data.type} + + ) + } +
+
+
+ + { + tocSections.length > 0 && ( + + ) + } + +
+ +
+ + +
+ + + + +
+ + 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), +) +--- + + + + + +
+ { + years.map((year) => ( +
+
{year}
+
    + {eventsByYear[year].map((event) => ( +
  • + +
  • + ))} +
+
+ )) + } +
+ + +
diff --git a/src/pages/index.astro b/src/pages/index.astro index 019283d..9549a7c 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,13 +1,15 @@ --- import BlogCard from '@/components/BlogCard.astro' +import EventCard from '@/components/EventCard.astro' import Link from '@/components/Link.astro' import PageHead from '@/components/PageHead.astro' import { buttonVariants } from '@/components/ui/button' import { SITE } from '@/consts' import Layout from '@/layouts/Layout.astro' -import { getRecentPosts } from '@/lib/data-utils' +import { getRecentPosts, getRecentEvents } from '@/lib/data-utils' const blog = await getRecentPosts(SITE.featuredPostCount) +const events = await getRecentEvents(SITE.featuredEventsCount) --- @@ -16,69 +18,53 @@ const blog = await getRecentPosts(SITE.featuredPostCount)

er·u·dite

- /ˈer(y)əˌdīt/ • adjective + /ˈer(y)əˌdīt/ • adjective

-
-

- astro-erudite is an opinionated, unstyled static blogging template built - with Astro, Tailwind, and shadcn/ui. Extraordinarily loosely based on the Astro Micro theme. -

-

- To use this template, check out the GitHub repository. To learn more about why this template exists, read this blog - post: The State of Static Blogs in 2024. -

+ +
+

Latest events

+
    + { + events.map((event) => ( +
  • + +
  • + )) + } +
+
+ + See all posts → +

Latest posts

    { - blog.map((post) => ( -
  • - -
  • - )) + blog.map((post) => ( +
  • + +
  • + )) }
- See all posts → + href="/blog" + class={buttonVariants({ variant: 'ghost' }) + ' group'} + > + See all posts →
diff --git a/src/pages/types/[...id].astro b/src/pages/types/[...id].astro new file mode 100644 index 0000000..26640a9 --- /dev/null +++ b/src/pages/types/[...id].astro @@ -0,0 +1,53 @@ +--- +import Breadcrumbs from '@/components/Breadcrumbs.astro' +import PageHead from '@/components/PageHead.astro' +import Layout from '@/layouts/Layout.astro' +import { getAllTypes, getEventsByType } from '@/lib/data-utils' +import { capitalizeFirstLetter, iconMappings } from '@/lib/utils' +import EventCard from '../../components/EventCard.astro' + +export async function getStaticPaths() { + const typeMap = await getAllTypes() + const uniqueTags = Array.from(typeMap.keys()) + + return Promise.all( + uniqueTags.map(async (type) => { + const events = await getEventsByType(type) + return { + params: { id: type }, + props: { + type, + events, + }, + } + }), + ) +} + +const { type, events } = Astro.props +--- + + + + + +
    + { + events.map((event) => ( +
  • + +
  • + )) + } +
+
diff --git a/src/pages/types/index.astro b/src/pages/types/index.astro new file mode 100644 index 0000000..c269c22 --- /dev/null +++ b/src/pages/types/index.astro @@ -0,0 +1,35 @@ +--- +import Breadcrumbs from '@/components/Breadcrumbs.astro' +import Link from '@/components/Link.astro' +import PageHead from '@/components/PageHead.astro' +import { badgeVariants } from '@/components/ui/badge' +import Layout from '@/layouts/Layout.astro' +import { getAllTypes } from '@/lib/data-utils' +import { iconMappings } from '@/lib/utils' +import { Icon } from 'astro-icon/components' + +const types = await getAllTypes() +--- + + + + + +
+
+ {console.log([...types.entries()].map((a) => console.log(a)))} + { + [...types.entries()].map(([type, count]) => ( + + + {type} + ({count}) + + )) + } +
+
+
diff --git a/src/types.ts b/src/types.ts index b03a955..4fedcdd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -5,7 +5,9 @@ export type Site = { author: string locale: string featuredPostCount: number + featuredEventsCount: number postsPerPage: number + eventsPerPage: number } export type SocialLink = { -- cgit v1.2.3