refactor: modularize AdminClientWrapper by extracting components
- Removed unused imports and components from AdminClientWrapper. - Introduced AdminHeader, AdminOverviewCards, AdminFilters, and AdminContentTabs for better code organization and readability. - Streamlined the layout and functionality of the admin dashboard, enhancing maintainability.
This commit is contained in:
134
components/admin/admin-overview-cards.tsx
Normal file
134
components/admin/admin-overview-cards.tsx
Normal file
@@ -0,0 +1,134 @@
|
||||
"use client";
|
||||
|
||||
import { Users, Target, Building2, UserCheck } from "lucide-react";
|
||||
import { Team, SkillCategory } from "@/lib/types";
|
||||
import { TeamStats, DirectionStats } from "@/services/admin-service";
|
||||
|
||||
interface AdminOverviewCardsProps {
|
||||
teams: Team[];
|
||||
skillCategories: SkillCategory[];
|
||||
teamStats: TeamStats[];
|
||||
directionStats: DirectionStats[];
|
||||
selectedDirections: string[];
|
||||
selectedTeams: string[];
|
||||
getFilteredTeamStats: () => TeamStats[];
|
||||
getFilteredDirectionStats: () => DirectionStats[];
|
||||
}
|
||||
|
||||
export function AdminOverviewCards({
|
||||
teams,
|
||||
skillCategories,
|
||||
teamStats,
|
||||
directionStats,
|
||||
selectedDirections,
|
||||
selectedTeams,
|
||||
getFilteredTeamStats,
|
||||
getFilteredDirectionStats,
|
||||
}: AdminOverviewCardsProps) {
|
||||
const hasFilters = selectedDirections.length > 0 || selectedTeams.length > 0;
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
|
||||
<div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6 hover:bg-white/10 transition-colors">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div className="p-2 bg-blue-500/20 border border-blue-500/30 rounded-xl">
|
||||
<Users className="h-5 w-5 text-blue-400" />
|
||||
</div>
|
||||
<div className="text-xs text-slate-400 font-medium">
|
||||
{hasFilters ? "FILTRÉES" : "TOTAL"}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<p className="text-2xl font-bold text-white">
|
||||
{hasFilters ? getFilteredTeamStats().length : teams.length}
|
||||
</p>
|
||||
<p className="text-sm text-slate-400">
|
||||
{hasFilters ? "Équipes filtrées" : "Équipes"}
|
||||
</p>
|
||||
{hasFilters && (
|
||||
<p className="text-xs text-slate-500">
|
||||
sur {teams.length} au total
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6 hover:bg-white/10 transition-colors">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div className="p-2 bg-green-500/20 border border-green-500/30 rounded-xl">
|
||||
<UserCheck className="h-5 w-5 text-green-400" />
|
||||
</div>
|
||||
<div className="text-xs text-slate-400 font-medium">
|
||||
{hasFilters ? "FILTRÉS" : "TOTAL"}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<p className="text-2xl font-bold text-white">
|
||||
{hasFilters
|
||||
? getFilteredTeamStats().reduce(
|
||||
(sum, t) => sum + t.totalMembers,
|
||||
0
|
||||
)
|
||||
: teamStats.reduce((sum, t) => sum + t.totalMembers, 0)}
|
||||
</p>
|
||||
<p className="text-sm text-slate-400">
|
||||
{hasFilters ? "Membres filtrés" : "Membres"}
|
||||
</p>
|
||||
{hasFilters && (
|
||||
<p className="text-xs text-slate-500">
|
||||
sur {teamStats.reduce((sum, t) => sum + t.totalMembers, 0)} au
|
||||
total
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6 hover:bg-white/10 transition-colors">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div className="p-2 bg-purple-500/20 border border-purple-500/30 rounded-xl">
|
||||
<Building2 className="h-5 w-5 text-purple-400" />
|
||||
</div>
|
||||
<div className="text-xs text-slate-400 font-medium">
|
||||
{hasFilters ? "FILTRÉES" : "TOTAL"}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<p className="text-2xl font-bold text-white">
|
||||
{hasFilters
|
||||
? getFilteredDirectionStats().length
|
||||
: directionStats.length}
|
||||
</p>
|
||||
<p className="text-sm text-slate-400">
|
||||
{hasFilters ? "Directions filtrées" : "Directions"}
|
||||
</p>
|
||||
{hasFilters && (
|
||||
<p className="text-xs text-slate-500">
|
||||
sur {directionStats.length} au total
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-6 hover:bg-white/10 transition-colors">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div className="p-2 bg-orange-500/20 border border-orange-500/30 rounded-xl">
|
||||
<Target className="h-5 w-5 text-orange-400" />
|
||||
</div>
|
||||
<div className="text-xs text-slate-400 font-medium">RÉFÉRENTIEL</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<p className="text-2xl font-bold text-white">
|
||||
{skillCategories.reduce(
|
||||
(sum, cat) => sum + (cat.skills?.length || 0),
|
||||
0
|
||||
)}
|
||||
</p>
|
||||
<p className="text-sm text-slate-400">Compétences suivies</p>
|
||||
<p className="text-xs text-slate-500">
|
||||
{skillCategories.length} catégories
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user