feat: add home featured toggle, improve account deletion UI, and update business schema and database configuration.
This commit is contained in:
@@ -6,19 +6,48 @@ import {
|
||||
Store,
|
||||
Clock,
|
||||
MessageCircle,
|
||||
Eye
|
||||
Eye,
|
||||
CheckCircle2,
|
||||
UserPlus
|
||||
} from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
|
||||
interface Stats {
|
||||
usersCount: number;
|
||||
businessCount: number;
|
||||
pendingCount: number;
|
||||
commentsCount: number;
|
||||
totalViews: number;
|
||||
uniqueVisitors: number;
|
||||
interface DashboardData {
|
||||
stats: {
|
||||
usersCount: number;
|
||||
businessCount: number;
|
||||
pendingCount: number;
|
||||
commentsCount: number;
|
||||
totalViews: number;
|
||||
uniqueVisitors: number;
|
||||
};
|
||||
latestBusinesses: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
category: string;
|
||||
logoUrl: string;
|
||||
location: string;
|
||||
createdAt: Date;
|
||||
verified: boolean;
|
||||
plan: string;
|
||||
owner?: {
|
||||
name: string;
|
||||
email: string;
|
||||
};
|
||||
}>;
|
||||
activities: Array<{
|
||||
id: string;
|
||||
type: 'comment' | 'user';
|
||||
title: string;
|
||||
subtitle: string;
|
||||
timestamp: Date;
|
||||
avatar?: string | null;
|
||||
}>;
|
||||
}
|
||||
|
||||
export default function DashboardClient({ stats }: { stats: Stats }) {
|
||||
export default function DashboardClient({ initialData }: { initialData: DashboardData }) {
|
||||
const { stats, latestBusinesses, activities } = initialData;
|
||||
|
||||
const statCards = [
|
||||
{ label: 'Utilisateurs', value: stats.usersCount, icon: Users, color: 'text-blue-400' },
|
||||
{ label: 'Visiteurs Uniques', value: stats.uniqueVisitors, icon: Eye, color: 'text-indigo-400' },
|
||||
@@ -50,16 +79,86 @@ export default function DashboardClient({ stats }: { stats: Stats }) {
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
<div className="card">
|
||||
<h2 className="text-xl font-bold text-white mb-4">Derniers entrepreneurs</h2>
|
||||
<div className="space-y-4">
|
||||
<p className="text-slate-500 italic">Bientôt disponible...</p>
|
||||
{/* Derniers entrepreneurs */}
|
||||
<div className="card flex flex-col">
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<h2 className="text-xl font-bold text-white">Derniers entrepreneurs</h2>
|
||||
<Link href="/users" className="text-xs text-indigo-400 hover:underline font-semibold">
|
||||
Voir tout
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4 flex-1">
|
||||
{latestBusinesses.length === 0 ? (
|
||||
<p className="text-slate-500 italic py-8 text-center">Aucune entreprise récente.</p>
|
||||
) : (
|
||||
latestBusinesses.map((b) => (
|
||||
<div key={b.id} className="flex items-center justify-between p-3 rounded-xl bg-slate-800/40 hover:bg-slate-800/80 transition-colors border border-slate-800">
|
||||
<div className="flex items-center gap-3 min-w-0">
|
||||
<div className="w-10 h-10 rounded-lg bg-slate-800 overflow-hidden flex items-center justify-center border border-slate-700 flex-shrink-0">
|
||||
{b.logoUrl ? (
|
||||
<img src={b.logoUrl} alt={b.name} className="w-full h-full object-cover" />
|
||||
) : (
|
||||
<Store className="w-4 h-4 text-slate-500" />
|
||||
)}
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<div className="font-semibold text-white text-sm truncate">{b.name}</div>
|
||||
<div className="text-xs text-slate-400 truncate">{b.category} • {b.location}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 flex-shrink-0 ml-3">
|
||||
<span className={`text-[10px] font-bold px-2 py-0.5 rounded-full uppercase ${
|
||||
b.plan === 'EMPIRE' ? 'bg-purple-500/10 text-purple-400 border border-purple-500/20' :
|
||||
b.plan === 'BOOSTER' ? 'bg-amber-500/10 text-amber-400 border border-amber-500/20' :
|
||||
'bg-slate-500/10 text-slate-400'
|
||||
}`}>
|
||||
{b.plan}
|
||||
</span>
|
||||
{b.verified ? (
|
||||
<CheckCircle2 className="w-4 h-4 text-emerald-500" title="Vérifié" />
|
||||
) : (
|
||||
<Clock className="w-4 h-4 text-amber-500" title="En attente" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="card">
|
||||
<h2 className="text-xl font-bold text-white mb-4">Activité récente</h2>
|
||||
<div className="space-y-4">
|
||||
<p className="text-slate-500 italic">Bientôt disponible...</p>
|
||||
|
||||
{/* Activité récente */}
|
||||
<div className="card flex flex-col">
|
||||
<h2 className="text-xl font-bold text-white mb-6">Activité récente</h2>
|
||||
|
||||
<div className="space-y-4 flex-1">
|
||||
{activities.length === 0 ? (
|
||||
<p className="text-slate-500 italic py-8 text-center">Aucune activité enregistrée.</p>
|
||||
) : (
|
||||
activities.map((act) => (
|
||||
<div key={act.id} className="flex items-start gap-3.5 p-3 rounded-xl bg-slate-800/20 border border-slate-800/50">
|
||||
<div className="mt-0.5 w-8 h-8 rounded-full bg-slate-800 flex items-center justify-center border border-slate-700 flex-shrink-0 overflow-hidden">
|
||||
{act.avatar ? (
|
||||
<img src={act.avatar} alt="" className="w-full h-full object-cover" />
|
||||
) : act.type === 'comment' ? (
|
||||
<MessageCircle className="w-3.5 h-3.5 text-purple-400" />
|
||||
) : (
|
||||
<UserPlus className="w-3.5 h-3.5 text-blue-400" />
|
||||
)}
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<p className="text-xs font-semibold text-slate-200 truncate">{act.title}</p>
|
||||
<span className="text-[10px] text-slate-500 flex-shrink-0">
|
||||
{new Date(act.timestamp).toLocaleDateString('fr-FR', { day: 'numeric', month: 'short' })}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs text-slate-400 mt-0.5 line-clamp-2">{act.subtitle}</p>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user