refactor: SSR on skills management

This commit is contained in:
Julien Froidefond
2025-08-25 09:04:33 +02:00
parent e02af4f992
commit 0c7903bcb2
6 changed files with 51 additions and 52 deletions

View File

@@ -4,10 +4,15 @@ import { SkillsManagementPage } from "@/components/admin/skills";
export default async function SkillsPage() {
// Charger les données côté serveur
try {
const { skillCategories, teams } = await AdminService.getAdminData();
const { skillCategories, teams, skills } =
await AdminService.getAdminData();
return (
<SkillsManagementPage skillCategories={skillCategories} teams={teams} />
<SkillsManagementPage
skillCategories={skillCategories}
teams={teams}
initialSkills={skills}
/>
);
} catch (error) {
console.error("Failed to load admin data:", error);

View File

@@ -4,20 +4,6 @@ import { SkillsService } from "@/services/skills-service";
// Configuration pour éviter la génération statique
export const dynamic = "force-dynamic";
// GET - Récupérer toutes les skills
export async function GET() {
try {
const skills = await SkillsService.getAllSkillsWithUsage();
return NextResponse.json(skills);
} catch (error) {
console.error("Error fetching skills:", error);
return NextResponse.json(
{ error: "Erreur lors de la récupération des skills" },
{ status: 500 }
);
}
}
// POST - Créer une nouvelle skill
export async function POST(request: NextRequest) {
try {

View File

@@ -41,10 +41,6 @@ export interface User {
export class AdminClient extends BaseHttpClient {
// Skills Management
async getSkills(): Promise<Skill[]> {
return await this.get<Skill[]>(`/admin/skills`);
}
async createSkill(
skillData: Omit<Skill, "id" | "usageCount">
): Promise<Skill> {

View File

@@ -15,11 +15,13 @@ import { SkillsList } from "./skills-list";
interface SkillsManagementPageProps {
skillCategories: SkillCategory[];
teams: Team[];
initialSkills: any[];
}
export function SkillsManagementPage({
skillCategories,
teams,
initialSkills,
}: SkillsManagementPageProps) {
const [searchTerm, setSearchTerm] = useState("");
const {
@@ -43,7 +45,7 @@ export function SkillsManagementPage({
handleEditSkill,
handleUpdateSkill,
handleDeleteSkill,
} = useSkillsManagement(skillCategories);
} = useSkillsManagement(skillCategories, initialSkills);
// Utilisation du hook factorisé pour la vue arborescente
const {

View File

@@ -11,9 +11,12 @@ interface SkillFormData {
icon: string;
}
export function useSkillsManagement(skillCategories: SkillCategory[]) {
const [skills, setSkills] = useState<Skill[]>([]);
const [isLoading, setIsLoading] = useState(true);
export function useSkillsManagement(
skillCategories: SkillCategory[],
initialSkills?: any[]
) {
const [skills, setSkills] = useState<Skill[]>(initialSkills || []);
const [isLoading, setIsLoading] = useState(!initialSkills);
const [editingSkill, setEditingSkill] = useState<Skill | null>(null);
const [skillFormData, setSkillFormData] = useState<SkillFormData>({
name: "",
@@ -24,28 +27,28 @@ export function useSkillsManagement(skillCategories: SkillCategory[]) {
const [isSubmitting, setIsSubmitting] = useState(false);
const { toast } = useToast();
// Charger les skills depuis l'API
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);
}
};
// Charger les skills au montage du composant
// Charger les skills depuis l'API si pas de skills initiales
useEffect(() => {
fetchSkills();
}, []);
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: "" });

View File

@@ -1,6 +1,7 @@
import { getPool } from "./database";
import { Team, SkillCategory } from "@/lib/types";
import { TeamMember, TeamStats, DirectionStats } from "@/lib/admin-types";
import { SkillsService } from "./skills-service";
export class AdminService {
/**
@@ -197,18 +198,23 @@ export class AdminService {
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] = 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 [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 teams = teamsResult.rows;
const skillCategories = categoriesResult.rows.map((row) => ({
@@ -224,6 +230,7 @@ export class AdminService {
skillCategories,
teamStats,
directionStats,
skills,
};
} catch (error) {
console.error("Error fetching admin data:", error);