refactor: SSR on page teams and split getAdminData
This commit is contained in:
@@ -4,13 +4,11 @@ import { SkillsManagementPage } from "@/components/admin/skills";
|
||||
export default async function SkillsPage() {
|
||||
// Charger les données côté serveur
|
||||
try {
|
||||
const { skillCategories, teams, skills } =
|
||||
await AdminService.getAdminData();
|
||||
const { skillCategories, skills } = await AdminService.getSkillsPageData();
|
||||
|
||||
return (
|
||||
<SkillsManagementPage
|
||||
skillCategories={skillCategories}
|
||||
teams={teams}
|
||||
initialSkills={skills}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -4,16 +4,10 @@ import { TeamsManagementPage } from "@/components/admin/teams";
|
||||
export default async function TeamsPage() {
|
||||
// Charger les données côté serveur
|
||||
try {
|
||||
const { teams, teamStats, skillCategories } =
|
||||
await AdminService.getAdminData();
|
||||
const { teams, teamStats, directionStats } =
|
||||
await AdminService.getTeamsPageData();
|
||||
|
||||
return (
|
||||
<TeamsManagementPage
|
||||
teams={teams}
|
||||
teamStats={teamStats}
|
||||
skillCategories={skillCategories}
|
||||
/>
|
||||
);
|
||||
return <TeamsManagementPage teams={teams} teamStats={teamStats} />;
|
||||
} catch (error) {
|
||||
console.error("Failed to load admin data:", error);
|
||||
return (
|
||||
|
||||
@@ -4,9 +4,9 @@ import { UsersManagementPage } from "@/components/admin/users";
|
||||
export default async function UsersPage() {
|
||||
// Charger les données côté serveur
|
||||
try {
|
||||
const { teams } = await AdminService.getAdminData();
|
||||
const { teams, users } = await AdminService.getUsersPageData();
|
||||
|
||||
return <UsersManagementPage teams={teams} />;
|
||||
return <UsersManagementPage teams={teams} initialUsers={users} />;
|
||||
} catch (error) {
|
||||
console.error("Failed to load admin data:", error);
|
||||
return (
|
||||
|
||||
@@ -4,7 +4,7 @@ import { AdminClientWrapper } from "@/components/admin";
|
||||
export default async function AdminPage() {
|
||||
// Charger les données côté serveur
|
||||
try {
|
||||
const adminData = await AdminService.getAdminData();
|
||||
const adminData = await AdminService.getOverviewPageData();
|
||||
|
||||
return (
|
||||
<AdminClientWrapper
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { UserService } from "@/services/user-service";
|
||||
|
||||
// GET - Récupérer la liste des utilisateurs
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const users = await UserService.getAllUsersForAdmin();
|
||||
return NextResponse.json(users);
|
||||
} catch (error) {
|
||||
console.error("Error fetching users:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors de la récupération des utilisateurs" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -90,10 +90,6 @@ export class AdminClient extends BaseHttpClient {
|
||||
}
|
||||
|
||||
// User Management
|
||||
async getUsers(): Promise<User[]> {
|
||||
return await this.get<User[]>(`/admin/users`);
|
||||
}
|
||||
|
||||
async createUser(userData: UserFormData): Promise<User> {
|
||||
return await this.post<User>(`/admin/users`, userData);
|
||||
}
|
||||
|
||||
@@ -14,13 +14,11 @@ import { SkillsList } from "./skills-list";
|
||||
|
||||
interface SkillsManagementPageProps {
|
||||
skillCategories: SkillCategory[];
|
||||
teams: Team[];
|
||||
initialSkills: any[];
|
||||
}
|
||||
|
||||
export function SkillsManagementPage({
|
||||
skillCategories,
|
||||
teams,
|
||||
initialSkills,
|
||||
}: SkillsManagementPageProps) {
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
|
||||
@@ -16,13 +16,11 @@ import { TeamMembersModal } from "../management/team-members-modal";
|
||||
interface TeamsManagementPageProps {
|
||||
teams: TeamType[];
|
||||
teamStats: TeamStats[];
|
||||
skillCategories: SkillCategory[];
|
||||
}
|
||||
|
||||
export function TeamsManagementPage({
|
||||
teams,
|
||||
teamStats,
|
||||
skillCategories,
|
||||
}: TeamsManagementPageProps) {
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [isMembersModalOpen, setIsMembersModalOpen] = useState(false);
|
||||
|
||||
@@ -13,9 +13,13 @@ import { UsersList } from "./users-list";
|
||||
|
||||
interface UsersManagementPageProps {
|
||||
teams: Team[];
|
||||
initialUsers: any[];
|
||||
}
|
||||
|
||||
export function UsersManagementPage({ teams }: UsersManagementPageProps) {
|
||||
export function UsersManagementPage({
|
||||
teams,
|
||||
initialUsers,
|
||||
}: UsersManagementPageProps) {
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
|
||||
const { isCreateDialogOpen, openCreateDialog, closeCreateDialog } =
|
||||
@@ -31,7 +35,7 @@ export function UsersManagementPage({ teams }: UsersManagementPageProps) {
|
||||
resetForm,
|
||||
handleCreateUser,
|
||||
handleDeleteUser,
|
||||
} = useUsersManagement(teams);
|
||||
} = useUsersManagement(teams, initialUsers);
|
||||
|
||||
// Utilisation du hook factorisé pour la vue arborescente
|
||||
const {
|
||||
|
||||
@@ -27,36 +27,12 @@ export function useSkillsManagement(
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const { toast } = useToast();
|
||||
|
||||
// Charger les skills depuis l'API si pas de skills initiales
|
||||
useEffect(() => {
|
||||
if (!initialSkills) {
|
||||
const fetchSkills = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const skillsData = await adminClient.getSkills();
|
||||
setSkills(skillsData);
|
||||
} catch (error) {
|
||||
console.error("Error fetching skills:", error);
|
||||
toast({
|
||||
title: "Erreur",
|
||||
description: "Impossible de charger les skills",
|
||||
variant: "destructive",
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchSkills();
|
||||
}
|
||||
}, [initialSkills]);
|
||||
|
||||
const resetForm = () => {
|
||||
setSkillFormData({ name: "", categoryId: "", description: "", icon: "" });
|
||||
setEditingSkill(null);
|
||||
};
|
||||
|
||||
const handleCreateSkill = async () => {
|
||||
console.log("skillFormData", skillFormData);
|
||||
if (!skillFormData.name || !skillFormData.categoryId) {
|
||||
toast({
|
||||
title: "Erreur",
|
||||
|
||||
@@ -23,27 +23,6 @@ export function useTeamsManagement(
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const { toast } = useToast();
|
||||
|
||||
// Charger les teams depuis l'API
|
||||
const fetchTeams = async () => {
|
||||
try {
|
||||
const teamsData = await adminClient.getTeams();
|
||||
// Note: on garde les teams existantes pour la compatibilité
|
||||
// Les nouvelles teams créées via l'API seront visibles après rafraîchissement
|
||||
} catch (error) {
|
||||
console.error("Error fetching teams:", error);
|
||||
toast({
|
||||
title: "Erreur",
|
||||
description: "Impossible de charger les teams",
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Charger les teams au montage du composant
|
||||
useEffect(() => {
|
||||
fetchTeams();
|
||||
}, []);
|
||||
|
||||
const resetForm = () => {
|
||||
setTeamFormData({ name: "", direction: "" });
|
||||
setEditingTeam(null);
|
||||
|
||||
@@ -4,9 +4,9 @@ import { Team } from "@/lib/types";
|
||||
import { adminClient } from "@/clients";
|
||||
import { User, UserFormData } from "@/clients/domains/admin-client";
|
||||
|
||||
export function useUsersManagement(teams: Team[]) {
|
||||
const [users, setUsers] = useState<User[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
export function useUsersManagement(teams: Team[], initialUsers?: any[]) {
|
||||
const [users, setUsers] = useState<User[]>(initialUsers || []);
|
||||
const [isLoading, setIsLoading] = useState(!initialUsers);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [deletingUserId, setDeletingUserId] = useState<string | null>(null);
|
||||
const [userFormData, setUserFormData] = useState<UserFormData>({
|
||||
@@ -17,25 +17,6 @@ export function useUsersManagement(teams: Team[]) {
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const { toast } = useToast();
|
||||
|
||||
// Charger les utilisateurs depuis l'API
|
||||
const fetchUsers = async () => {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const usersData = await adminClient.getUsers();
|
||||
setUsers(usersData);
|
||||
} catch (err: any) {
|
||||
setError(err.message || "Erreur lors du chargement des utilisateurs");
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Charger les utilisateurs au montage du composant
|
||||
useEffect(() => {
|
||||
fetchUsers();
|
||||
}, []);
|
||||
|
||||
const resetForm = () => {
|
||||
setUserFormData({ firstName: "", lastName: "", teamId: "" });
|
||||
};
|
||||
@@ -52,15 +33,15 @@ export function useUsersManagement(teams: Team[]) {
|
||||
|
||||
try {
|
||||
setIsSubmitting(true);
|
||||
await adminClient.createUser(userFormData);
|
||||
const newUser = await adminClient.createUser(userFormData);
|
||||
toast({
|
||||
title: "Succès",
|
||||
description: "Utilisateur créé avec succès",
|
||||
});
|
||||
|
||||
// Ajouter le nouvel utilisateur à la liste locale
|
||||
setUsers([...users, newUser]);
|
||||
resetForm();
|
||||
// Rafraîchir la liste
|
||||
await fetchUsers();
|
||||
return true;
|
||||
} catch (error: any) {
|
||||
toast({
|
||||
@@ -128,6 +109,5 @@ export function useUsersManagement(teams: Team[]) {
|
||||
resetForm,
|
||||
handleCreateUser,
|
||||
handleDeleteUser,
|
||||
fetchUsers,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -191,36 +191,132 @@ export class AdminService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère toutes les données nécessaires pour l'admin
|
||||
* Récupère les données nécessaires pour la page de gestion des skills
|
||||
*/
|
||||
static async getAdminData(): Promise<{
|
||||
teams: Team[];
|
||||
static async getSkillsPageData(): Promise<{
|
||||
skillCategories: SkillCategory[];
|
||||
teamStats: TeamStats[];
|
||||
directionStats: DirectionStats[];
|
||||
skills: any[];
|
||||
}> {
|
||||
const pool = getPool();
|
||||
|
||||
try {
|
||||
// Récupérer toutes les données en parallèle
|
||||
const [teamsResult, categoriesResult, teamStats, skills] =
|
||||
await Promise.all([
|
||||
pool.query(
|
||||
"SELECT id, name, direction FROM teams ORDER BY direction, name"
|
||||
),
|
||||
pool.query(
|
||||
"SELECT id, name, icon FROM skill_categories ORDER BY name"
|
||||
),
|
||||
AdminService.getTeamsStats(),
|
||||
SkillsService.getAllSkillsWithUsage(),
|
||||
]);
|
||||
const [categoriesResult, skills] = await Promise.all([
|
||||
pool.query("SELECT id, name, icon FROM skill_categories ORDER BY name"),
|
||||
SkillsService.getAllSkillsWithUsage(),
|
||||
]);
|
||||
|
||||
const skillCategories = categoriesResult.rows.map((row) => ({
|
||||
...row,
|
||||
category: row.name,
|
||||
skills: [],
|
||||
}));
|
||||
|
||||
return {
|
||||
skillCategories,
|
||||
skills,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error fetching skills page data:", error);
|
||||
throw new Error("Failed to fetch skills page data");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les données nécessaires pour la page de gestion des utilisateurs
|
||||
*/
|
||||
static async getUsersPageData(): Promise<{
|
||||
teams: Team[];
|
||||
users: any[];
|
||||
}> {
|
||||
const pool = getPool();
|
||||
|
||||
try {
|
||||
const [teamsResult, usersResult] = await Promise.all([
|
||||
pool.query(
|
||||
"SELECT id, name, direction FROM teams ORDER BY direction, name"
|
||||
),
|
||||
pool.query(`
|
||||
SELECT
|
||||
u.uuid_id as uuid,
|
||||
u.first_name as "firstName",
|
||||
u.last_name as "lastName",
|
||||
t.name as "teamName",
|
||||
EXISTS (
|
||||
SELECT 1 FROM user_evaluations ue
|
||||
WHERE ue.user_uuid = u.uuid_id
|
||||
) as "hasEvaluations"
|
||||
FROM users u
|
||||
LEFT JOIN teams t ON u.team_id = t.id
|
||||
ORDER BY u.first_name, u.last_name
|
||||
`),
|
||||
]);
|
||||
|
||||
return {
|
||||
teams: teamsResult.rows,
|
||||
users: usersResult.rows,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error fetching users page data:", error);
|
||||
throw new Error("Failed to fetch users page data");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les données nécessaires pour la page de gestion des équipes
|
||||
*/
|
||||
static async getTeamsPageData(): Promise<{
|
||||
teams: Team[];
|
||||
teamStats: TeamStats[];
|
||||
directionStats: DirectionStats[];
|
||||
}> {
|
||||
const pool = getPool();
|
||||
|
||||
try {
|
||||
const [teamsResult, teamStats] = await Promise.all([
|
||||
pool.query(
|
||||
"SELECT id, name, direction FROM teams ORDER BY direction, name"
|
||||
),
|
||||
AdminService.getTeamsStats(),
|
||||
]);
|
||||
|
||||
const directionStats = AdminService.generateDirectionStats(teamStats);
|
||||
|
||||
return {
|
||||
teams: teamsResult.rows,
|
||||
teamStats,
|
||||
directionStats,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error fetching teams page data:", error);
|
||||
throw new Error("Failed to fetch teams page data");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les données nécessaires pour la page d'accueil admin
|
||||
*/
|
||||
static async getOverviewPageData(): Promise<{
|
||||
teams: Team[];
|
||||
skillCategories: SkillCategory[];
|
||||
teamStats: TeamStats[];
|
||||
directionStats: DirectionStats[];
|
||||
}> {
|
||||
const pool = getPool();
|
||||
|
||||
try {
|
||||
const [teamsResult, categoriesResult, teamStats] = await Promise.all([
|
||||
pool.query(
|
||||
"SELECT id, name, direction FROM teams ORDER BY direction, name"
|
||||
),
|
||||
pool.query("SELECT id, name, icon FROM skill_categories ORDER BY name"),
|
||||
AdminService.getTeamsStats(),
|
||||
]);
|
||||
|
||||
const teams = teamsResult.rows;
|
||||
const skillCategories = categoriesResult.rows.map((row) => ({
|
||||
...row,
|
||||
category: row.name, // Adapter le format
|
||||
skills: [], // Les skills individuelles ne sont pas nécessaires pour l'admin
|
||||
category: row.name,
|
||||
skills: [],
|
||||
}));
|
||||
|
||||
const directionStats = AdminService.generateDirectionStats(teamStats);
|
||||
@@ -230,11 +326,10 @@ export class AdminService {
|
||||
skillCategories,
|
||||
teamStats,
|
||||
directionStats,
|
||||
skills,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error fetching admin data:", error);
|
||||
throw new Error("Failed to fetch admin data");
|
||||
console.error("Error fetching overview page data:", error);
|
||||
throw new Error("Failed to fetch overview page data");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user