Files
memegoat/frontend/src/app/(dashboard)/meme/[slug]/page.tsx
Mathis HERRIOT 0a1391674f feat(meme): add ViewCounter component to meme detail pages
Integrate the `ViewCounter` component into meme standard and modal detail pages to track and display content views.
2026-01-14 22:18:10 +01:00

101 lines
2.8 KiB
TypeScript

import { ChevronLeft } from "lucide-react";
import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import { ContentCard } from "@/components/content-card";
import { Button } from "@/components/ui/button";
import { ViewCounter } from "@/components/view-counter";
import { ContentService } from "@/services/content.service";
export const revalidate = 3600; // ISR: Revalider toutes les heures
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}): Promise<Metadata> {
const { slug } = await params;
try {
const content = await ContentService.getOne(slug);
return {
title: `${content.title} | MemeGoat`,
description: content.description || `Regardez ce mème : ${content.title}`,
openGraph: {
images: [content.thumbnailUrl || content.url],
},
};
} catch (_error) {
return { title: "Mème non trouvé | MemeGoat" };
}
}
export default async function MemePage({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
try {
const content = await ContentService.getOne(slug);
return (
<div className="max-w-4xl mx-auto py-8 px-4">
<ViewCounter contentId={content.id} />
<Link
href="/"
className="inline-flex items-center text-sm mb-6 hover:text-primary transition-colors"
>
<ChevronLeft className="h-4 w-4 mr-1" />
Retour au flux
</Link>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="lg:col-span-2">
<ContentCard content={content} />
</div>
<div className="space-y-6">
<div className="bg-white dark:bg-zinc-900 p-6 rounded-xl shadow-sm border">
<h2 className="font-bold text-lg mb-4">À propos de ce mème</h2>
<div className="space-y-4 text-sm">
<div>
<p className="text-muted-foreground">Publié par</p>
<p className="font-medium">
{content.author.displayName || content.author.username}
</p>
</div>
<div>
<p className="text-muted-foreground">Date</p>
<p className="font-medium">
{new Date(content.createdAt).toLocaleDateString("fr-FR", {
day: "numeric",
month: "long",
year: "numeric",
})}
</p>
</div>
{content.description && (
<div>
<p className="text-muted-foreground">Description</p>
<p>{content.description}</p>
</div>
)}
</div>
</div>
<div className="bg-white dark:bg-zinc-900 p-6 rounded-xl shadow-sm border text-center">
<p className="text-sm text-muted-foreground mb-4">
Envie de créer votre propre mème ?
</p>
<Button className="w-full">Utiliser ce template</Button>
</div>
</div>
</div>
</div>
);
} catch (_error) {
notFound();
}
}