refactor(all): migrate from React to Next.js
This commit is contained in:
115
src/app/events/[slug]/page.tsx
Normal file
115
src/app/events/[slug]/page.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
import type { Metadata } from "next";
|
||||
import { notFound } from "next/navigation";
|
||||
import EventDetail from "@/views/EventDetail";
|
||||
import { PublicApiError, getPublicEventBySlug } from "@/lib/public-api";
|
||||
import { siteUrl } from "@/lib/site";
|
||||
import { getThumbUrl } from "@/lib/utils";
|
||||
|
||||
type Params = Promise<{ slug: string }>;
|
||||
|
||||
function cleanText(value?: string | null) {
|
||||
if (!value) return "";
|
||||
return value.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
|
||||
}
|
||||
|
||||
async function loadEvent(slug: string) {
|
||||
try {
|
||||
return await getPublicEventBySlug(slug);
|
||||
} catch (error) {
|
||||
if (error instanceof PublicApiError && error.status === 404) {
|
||||
notFound();
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Params;
|
||||
}): Promise<Metadata> {
|
||||
const { slug } = await params;
|
||||
const event = await loadEvent(slug);
|
||||
const description = cleanText(event.description).slice(0, 160);
|
||||
const image = event.absolute_featured_image_url || getThumbUrl(event) || `${siteUrl}/favicon.ico`;
|
||||
|
||||
return {
|
||||
title: event.title,
|
||||
description,
|
||||
alternates: { canonical: `/events/${event.slug}` },
|
||||
robots: event.status === "draft" ? { index: false, follow: false } : undefined,
|
||||
openGraph: {
|
||||
title: event.title,
|
||||
description,
|
||||
url: `${siteUrl}/events/${event.slug}`,
|
||||
siteName: "انجمن علمی کامپیوتر شرق گیلان",
|
||||
type: "website",
|
||||
images: [image],
|
||||
locale: "fa_IR",
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: event.title,
|
||||
description,
|
||||
images: [image],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default async function EventDetailPage({
|
||||
params,
|
||||
}: {
|
||||
params: Params;
|
||||
}) {
|
||||
const { slug } = await params;
|
||||
const event = await loadEvent(slug);
|
||||
const description = cleanText(event.description).slice(0, 160);
|
||||
|
||||
const structuredData = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Event",
|
||||
name: event.title,
|
||||
description,
|
||||
startDate: event.start_time,
|
||||
endDate: event.end_time,
|
||||
eventStatus:
|
||||
event.status === "completed"
|
||||
? "https://schema.org/EventCompleted"
|
||||
: event.status === "cancelled"
|
||||
? "https://schema.org/EventCancelled"
|
||||
: "https://schema.org/EventScheduled",
|
||||
eventAttendanceMode:
|
||||
event.event_type === "online"
|
||||
? "https://schema.org/OnlineEventAttendanceMode"
|
||||
: event.event_type === "on_site"
|
||||
? "https://schema.org/OfflineEventAttendanceMode"
|
||||
: "https://schema.org/MixedEventAttendanceMode",
|
||||
image: [event.absolute_featured_image_url || getThumbUrl(event) || `${siteUrl}/favicon.ico`],
|
||||
url: `${siteUrl}/events/${event.slug}`,
|
||||
organizer: {
|
||||
"@type": "Organization",
|
||||
name: "انجمن علمی کامپیوتر شرق گیلان",
|
||||
url: siteUrl,
|
||||
},
|
||||
offers: {
|
||||
"@type": "Offer",
|
||||
url: `${siteUrl}/events/${event.slug}`,
|
||||
priceCurrency: "IRR",
|
||||
price: String(event.price ?? 0),
|
||||
availability:
|
||||
(event.capacity ?? 0) > (event.registration_count ?? 0)
|
||||
? "https://schema.org/InStock"
|
||||
: "https://schema.org/SoldOut",
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
|
||||
/>
|
||||
<EventDetail initialEvent={event} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
11
src/app/events/[slug]/success/page.tsx
Normal file
11
src/app/events/[slug]/success/page.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import type { Metadata } from "next";
|
||||
import EventFreeSuccessPage from "@/views/EventFreeSuccessPage";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "نتیجه ثبتنام رویداد",
|
||||
robots: { index: false, follow: false },
|
||||
};
|
||||
|
||||
export default function EventSuccessPage() {
|
||||
return <EventFreeSuccessPage />;
|
||||
}
|
||||
Reference in New Issue
Block a user