import { notFound } from "next/navigation"; import Image from "next/image"; import { Metadata } from "next"; import { MDXRemote } from "next-mdx-remote/rsc"; import { Container } from "@/components/layout/Container"; import { Button } from "@/components/ui/Button"; import { getAllResources, getResourceBySlug } from "@/lib/resources"; import { ResourcesGrid } from "../resources-client"; function MdxLink(props: React.AnchorHTMLAttributes) { const { href, children, ...rest } = props; const isExternal = href?.startsWith("http"); return ( {children} ); } const mdxComponents = { a: MdxLink, }; const NEWS_CATEGORIES = ["News & Updates", "Customer Stories"]; const ACTIVITY_CATEGORIES = ["Activities", "Simulator Activities"]; const CATEGORY_SLUGS: Record = { "getting-started": { name: "Getting Started", description: "Everything you need to get up and running with the Micromelon platform.", }, activities: { name: "Activities", description: "Hands-on activities for the Micromelon Rover and Robot Simulator.", matchCategories: ["Activities", "Simulator Activities"], filterCategories: ["Activities", "Simulator Activities"], }, "sensor-guides": { name: "Sensor Guides", description: "Learn how each sensor on the Micromelon Rover works and how to code it.", }, "3d-printing-guides": { name: "3D Printing Guides", description: "Guides for designing, printing, and troubleshooting rover attachments.", }, "advanced-guides": { name: "Advanced Guides", description: "I2C, UART, OpenMV, and other advanced topics for experienced users.", }, "build-guides": { name: "Build Guides", description: "Step-by-step instructions for building rover attachments.", }, "design-blogs": { name: "Design Blogs", description: "Read about the design process behind rover attachments.", }, }; interface ResourcePageProps { params: Promise<{ slug: string }>; } export function generateStaticParams() { const resources = getAllResources(); const resourceParams = resources.map((resource) => ({ slug: resource.slug, })); const categoryParams = Object.keys(CATEGORY_SLUGS).map((slug) => ({ slug, })); return [...resourceParams, ...categoryParams]; } export async function generateMetadata({ params, }: ResourcePageProps): Promise { const { slug } = await params; const category = CATEGORY_SLUGS[slug]; if (category) { return { title: `${category.name} - Resources`, description: category.description, }; } const resource = getResourceBySlug(slug); if (!resource) return {}; return { title: resource.title, description: resource.excerpt, }; } export default async function ResourcePage({ params }: ResourcePageProps) { const { slug } = await params; /* Category page */ const category = CATEGORY_SLUGS[slug]; if (category) { const cats = category.matchCategories || [category.name]; const resources = getAllResources() .filter((r) => r.categories.some((c) => cats.includes(c))) .map(({ content, ...meta }) => meta); return ( <>
); } /* Individual resource page */ const resource = getResourceBySlug(slug); if (!resource) { notFound(); } const isNews = resource.categories.some((cat) => NEWS_CATEGORIES.includes(cat) ); const isActivity = resource.categories.some((cat) => ACTIVITY_CATEGORIES.includes(cat) ); if (isActivity) { return ( <> {/* Activity Hero */}
{resource.categories.map((cat) => ( {cat} ))}

{resource.title}

{(resource.codingSkills.length > 0 || resource.roverConcepts.length > 0) && (
{resource.codingSkills.length > 0 && (

Coding Skills

{resource.codingSkills.map((skill) => ( {skill} ))}
)} {resource.roverConcepts.length > 0 && (

Rover Concepts

{resource.roverConcepts.map((concept) => ( {concept} ))}
)}
)}
{resource.featuredImage && (
{resource.title}
)}
{/* Activity Content */}
); } const backHref = isNews ? "/news" : "/resources"; const backLabel = isNews ? "Back to News" : "Back to Resources"; const returnLabel = isNews ? "Return to News" : "Return to Resources"; return ( <> {/* Hero */}
{resource.categories.map((cat) => ( {cat} ))}

{resource.title}

{new Date(resource.date).toLocaleDateString("en-AU", { year: "numeric", month: "long", day: "numeric", })}

{resource.featuredImage && (
{resource.title}
)}
{/* Content */}
); }