Skip to content
Learni
Voir tous les tutoriels
Développement Web

Comment implémenter un système d'avis clients en 2026

Read in English

Introduction

Gérer les avis clients est crucial pour la confiance et le SEO. En 2026, les systèmes doivent inclure validation stricte, modération automatisée et affichage performant. Ce tutoriel vous guide pas à pas dans la création d'une solution complète avec Next.js App Router, Prisma et TypeScript. Vous apprendrez à sécuriser les soumissions, calculer les notes moyennes et optimiser les requêtes pour des milliers d'avis.

Prérequis

  • Next.js 15 avec TypeScript
  • Node.js 20+
  • Prisma 5.20+
  • Base de données PostgreSQL
  • Connaissances solides en React et API routes

Schéma Prisma pour les avis

prisma/schema.prisma
model Review {
  id        Int      @id @default(autoincrement())
  rating    Int
  comment   String   @db.Text
  approved  Boolean  @default(false)
  userId    String
  productId String
  createdAt DateTime @default(now())
  user      User     @relation(fields: [userId], references: [id])
  product   Product  @relation(fields: [productId], references: [id])
}

Ce schéma définit le modèle Review avec validation de note, modération et relations. Le champ approved permet la modération manuelle avant affichage public.

Route API POST pour soumettre un avis

app/api/reviews/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/lib/prisma';
import { z } from 'zod';

const reviewSchema = z.object({
  rating: z.number().min(1).max(5),
  comment: z.string().min(10).max(500),
  productId: z.string(),
});

export async function POST(req: NextRequest) {
  const body = await req.json();
  const parsed = reviewSchema.safeParse(body);
  if (!parsed.success) return NextResponse.json({ error: 'Invalid data' }, { status: 400 });
  const { rating, comment, productId } = parsed.data;
  const review = await prisma.review.create({
    data: { rating, comment, productId, userId: 'user-123', approved: false }
  });
  return NextResponse.json(review, { status: 201 });
}

Cette route utilise Zod pour valider les données entrantes et crée l'avis en mode non-approuvé par défaut. Elle empêche les soumissions invalides et les injections.

Route API GET pour les avis approuvés

app/api/reviews/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/lib/prisma';

export async function GET(req: NextRequest) {
  const { searchParams } = new URL(req.url);
  const productId = searchParams.get('productId');
  if (!productId) return NextResponse.json({ error: 'Missing productId' }, { status: 400 });
  const reviews = await prisma.review.findMany({
    where: { productId, approved: true },
    orderBy: { createdAt: 'desc' },
    take: 20
  });
  return NextResponse.json(reviews);
}

Cette requête optimise les performances en filtrant uniquement les avis approuvés et en limitant les résultats. Idéale pour l'affichage côté client.

Composant d'affichage des étoiles

components/ReviewStars.tsx
import React from 'react';
interface Props { rating: number; }
export default function ReviewStars({ rating }: Props) {
  return (
    <div className="flex">
      {Array.from({ length: 5 }).map((_, i) => (
        <span key={i} className={i < rating ? 'text-yellow-500' : 'text-gray-300'}>★</span>
      ))}
    </div>
  );
}

Composant réutilisable et accessible qui affiche visuellement la note. Il est optimisé pour le rendu côté serveur et évite les re-rendus inutiles.

Fonction de calcul de note moyenne

lib/reviewUtils.ts
import { prisma } from './prisma';
export async function getAverageRating(productId: string): Promise<number> {
  const result = await prisma.review.aggregate({
    where: { productId, approved: true },
    _avg: { rating: true }
  });
  return result._avg.rating || 0;
}

Utilise l'agrégation Prisma pour calculer la moyenne en base de données, évitant de charger tous les avis en mémoire. Très performant à grande échelle.

Bonnes pratiques

  • Toujours valider les entrées côté serveur avec Zod
  • Modérer les avis avant publication
  • Utiliser des index sur productId et approved
  • Limiter le nombre d'avis retournés par requête
  • Protéger les routes avec authentification

Erreurs courantes à éviter

  • Oublier la validation et autoriser les notes invalides
  • Ne pas séparer création et modération
  • Charger tous les avis sans pagination
  • Ignorer les injections SQL via des requêtes dynamiques mal construites