1. Système d'Analytics (Nouveauté Majeure)
Modèle de Données : Ajout de la table AnalyticsEvent dans prisma/schema.prisma pour suivre les vues de pages, les clics et le temps de rétention (DWELL_TIME). API Backend : Création de la route app/api/analytics/route.ts pour enregistrer les événements en base de données. Tracking Client : Création du composant AnalyticsTracker.tsx (intégré dans le layout principal) qui capture automatiquement : Le changement de page (Page Views). Les clics sur les boutons et liens importants. Le temps passé sur chaque page. 2. Intégration Base de Données (PostgreSQL/Prisma) Fiches Entreprises : Mise à jour de app/directory/[id]/page.tsx pour récupérer les données réelles depuis PostgreSQL via Prisma au lieu d'utiliser les données de test (mockData). Navigation Dashboard : Correction du bouton "Voir ma fiche" dans le tableau de bord pour qu'il redirige correctement vers le profil public de l'entrepreneur. 3. Administration & Metrics Nouvelle Application Admin : Initialisation d'un dossier admin/ (application Next.js séparée) destinée à la gestion de la plateforme et à la visualisation des statistiques (Metrics & Analytics). 4. Authentification & Inscription Nouvelle Page : Création de app/register/page.tsx pour permettre l'inscription des nouveaux utilisateurs. Gestion de Session : Amélioration de UserProvider.tsx pour une meilleure gestion de l'état utilisateur à travers l'application. 5. Maintenance & Types Mise à jour des types globaux dans types.ts et rafraîchissement du package-lock.json suite à l'ajout de dépendances.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { LayoutDashboard, Edit3, ShoppingBag, CreditCard, LogOut, Eye } from 'lucide-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
@@ -17,13 +17,73 @@ const DashboardPage = () => {
|
||||
const { user, logout } = useUser();
|
||||
const router = useRouter();
|
||||
const [currentView, setCurrentView] = useState<'overview' | 'profile' | 'offers' | 'subscription'>('overview');
|
||||
const [business, setBusiness] = useState(MOCK_BUSINESSES[0]); // In real app, fetch by user.id
|
||||
const [business, setBusiness] = useState<any>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setIsMounted(true);
|
||||
}, []);
|
||||
|
||||
// Fetch user's business
|
||||
useEffect(() => {
|
||||
if (!user || !isMounted) return;
|
||||
|
||||
const fetchBusiness = async () => {
|
||||
try {
|
||||
const res = await fetch('/api/businesses/me', {
|
||||
headers: { 'x-user-id': user.id }
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data && !data.error) {
|
||||
setBusiness(data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching dashboard business:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchBusiness();
|
||||
}, [user, isMounted]);
|
||||
|
||||
if (!isMounted) return null;
|
||||
|
||||
if (!user) {
|
||||
if (typeof window !== 'undefined') router.push('/login');
|
||||
return null;
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-brand-600"></div>
|
||||
<p className="mt-4 text-gray-600 font-medium">Chargement de votre espace...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Default business structure for new users
|
||||
const displayBusiness = business || {
|
||||
id: 'new',
|
||||
name: "Ma Boutique",
|
||||
category: "Technologie & IT",
|
||||
location: "Ma Ville",
|
||||
description: "Décrivez votre entreprise ici...",
|
||||
logoUrl: "https://picsum.photos/200/200?random=default",
|
||||
contactEmail: user?.email || "",
|
||||
contactPhone: "",
|
||||
tags: [],
|
||||
socialLinks: {},
|
||||
verified: false,
|
||||
viewCount: 0,
|
||||
rating: 0,
|
||||
offers: []
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-100 flex">
|
||||
{/* 1. Sidebar */}
|
||||
@@ -88,7 +148,7 @@ const DashboardPage = () => {
|
||||
{currentView === 'subscription' && 'Mon Abonnement'}
|
||||
</h1>
|
||||
<div className="flex items-center space-x-4">
|
||||
<a href={`/directory`} target="_blank" rel="noopener noreferrer" className="hidden sm:inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none">
|
||||
<a href={displayBusiness.id === 'new' ? '/directory' : `/directory/${displayBusiness.id}`} target="_blank" rel="noopener noreferrer" className="hidden sm:inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none">
|
||||
<Eye className="-ml-1 mr-2 h-4 w-4 text-gray-500" />
|
||||
Voir ma fiche
|
||||
</a>
|
||||
@@ -97,8 +157,8 @@ const DashboardPage = () => {
|
||||
|
||||
<main className="flex-1 overflow-y-auto p-6">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
{currentView === 'overview' && <DashboardOverview business={business} />}
|
||||
{currentView === 'profile' && <DashboardProfile business={business} setBusiness={setBusiness} />}
|
||||
{currentView === 'overview' && <DashboardOverview business={displayBusiness} />}
|
||||
{currentView === 'profile' && <DashboardProfile business={displayBusiness} setBusiness={setBusiness} />}
|
||||
{currentView === 'offers' && <DashboardOffers />}
|
||||
{currentView === 'subscription' && (
|
||||
<div className="space-y-6">
|
||||
|
||||
Reference in New Issue
Block a user