- Updated the GET method in the evaluations route to support user authentication via cookies, improving security and user experience. - Added compatibility for legacy parameter-based authentication to ensure backward compatibility. - Refactored the useEvaluation hook to load user profiles from cookies instead of localStorage, streamlining the authentication process. - Introduced a new method in EvaluationService to retrieve user profiles by ID, enhancing data retrieval efficiency. - Updated ApiClient to handle cookie-based requests for loading evaluations, ensuring proper session management.
472 lines
11 KiB
TypeScript
472 lines
11 KiB
TypeScript
import {
|
|
UserEvaluation,
|
|
UserProfile,
|
|
SkillLevel,
|
|
Team,
|
|
SkillCategory,
|
|
Skill,
|
|
} from "../lib/types";
|
|
|
|
export class ApiClient {
|
|
private baseUrl: string;
|
|
|
|
constructor() {
|
|
this.baseUrl = process.env.NEXT_PUBLIC_API_URL || "";
|
|
}
|
|
|
|
/**
|
|
* Charge une évaluation utilisateur depuis l'API
|
|
* Si profile est fourni, utilise les paramètres (mode compatibilité)
|
|
* Sinon, utilise l'authentification par cookie
|
|
*/
|
|
async loadUserEvaluation(
|
|
profile?: UserProfile
|
|
): Promise<UserEvaluation | null> {
|
|
try {
|
|
let url = `${this.baseUrl}/api/evaluations`;
|
|
|
|
// Mode compatibilité avec profile en paramètres
|
|
if (profile) {
|
|
const params = new URLSearchParams({
|
|
firstName: profile.firstName,
|
|
lastName: profile.lastName,
|
|
teamId: profile.teamId,
|
|
});
|
|
url += `?${params}`;
|
|
}
|
|
|
|
const response = await fetch(url, {
|
|
credentials: "same-origin", // Pour inclure les cookies
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Erreur lors du chargement de l'évaluation");
|
|
}
|
|
|
|
const data = await response.json();
|
|
return data.evaluation;
|
|
} catch (error) {
|
|
console.error("Erreur lors du chargement de l'évaluation:", error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sauvegarde une évaluation utilisateur via l'API
|
|
*/
|
|
async saveUserEvaluation(evaluation: UserEvaluation): Promise<void> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/evaluations`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({ evaluation }),
|
|
credentials: "same-origin",
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Erreur lors de la sauvegarde de l'évaluation");
|
|
}
|
|
} catch (error) {
|
|
console.error("Erreur lors de la sauvegarde de l'évaluation:", error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Met à jour le niveau d'une skill
|
|
*/
|
|
async updateSkillLevel(
|
|
profile: UserProfile,
|
|
category: string,
|
|
skillId: string,
|
|
level: SkillLevel
|
|
): Promise<void> {
|
|
await this.updateSkill(profile, category, skillId, {
|
|
action: "updateLevel",
|
|
level,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Met à jour le statut de mentorat d'une skill
|
|
*/
|
|
async updateSkillMentorStatus(
|
|
profile: UserProfile,
|
|
category: string,
|
|
skillId: string,
|
|
canMentor: boolean
|
|
): Promise<void> {
|
|
await this.updateSkill(profile, category, skillId, {
|
|
action: "updateMentorStatus",
|
|
canMentor,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Met à jour le statut d'apprentissage d'une skill
|
|
*/
|
|
async updateSkillLearningStatus(
|
|
profile: UserProfile,
|
|
category: string,
|
|
skillId: string,
|
|
wantsToLearn: boolean
|
|
): Promise<void> {
|
|
await this.updateSkill(profile, category, skillId, {
|
|
action: "updateLearningStatus",
|
|
wantsToLearn,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Ajoute une skill à l'évaluation
|
|
*/
|
|
async addSkillToEvaluation(
|
|
profile: UserProfile,
|
|
category: string,
|
|
skillId: string
|
|
): Promise<void> {
|
|
await this.updateSkill(profile, category, skillId, {
|
|
action: "addSkill",
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Supprime une skill de l'évaluation
|
|
*/
|
|
async removeSkillFromEvaluation(
|
|
profile: UserProfile,
|
|
category: string,
|
|
skillId: string
|
|
): Promise<void> {
|
|
await this.updateSkill(profile, category, skillId, {
|
|
action: "removeSkill",
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Méthode utilitaire pour mettre à jour une skill
|
|
*/
|
|
private async updateSkill(
|
|
profile: UserProfile,
|
|
category: string,
|
|
skillId: string,
|
|
options: {
|
|
action:
|
|
| "updateLevel"
|
|
| "updateMentorStatus"
|
|
| "updateLearningStatus"
|
|
| "addSkill"
|
|
| "removeSkill";
|
|
level?: SkillLevel;
|
|
canMentor?: boolean;
|
|
wantsToLearn?: boolean;
|
|
}
|
|
): Promise<void> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/evaluations/skills`, {
|
|
method: "PUT",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
profile,
|
|
category,
|
|
skillId,
|
|
...options,
|
|
}),
|
|
credentials: "same-origin",
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Erreur lors de la mise à jour de la skill");
|
|
}
|
|
} catch (error) {
|
|
console.error("Erreur lors de la mise à jour de la skill:", error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Charge toutes les équipes
|
|
*/
|
|
async loadTeams(): Promise<Team[]> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/teams`);
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Erreur lors du chargement des équipes");
|
|
}
|
|
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error("Erreur lors du chargement des équipes:", error);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Charge une équipe par ID
|
|
*/
|
|
async loadTeamById(teamId: string): Promise<Team | null> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/teams/${teamId}`);
|
|
|
|
if (!response.ok) {
|
|
if (response.status === 404) {
|
|
return null;
|
|
}
|
|
throw new Error("Erreur lors du chargement de l'équipe");
|
|
}
|
|
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error("Erreur lors du chargement de l'équipe:", error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Charge les équipes par direction
|
|
*/
|
|
async loadTeamsByDirection(direction: string): Promise<Team[]> {
|
|
try {
|
|
const response = await fetch(
|
|
`${this.baseUrl}/api/teams/direction/${direction}`
|
|
);
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Erreur lors du chargement des équipes par direction");
|
|
}
|
|
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error(
|
|
"Erreur lors du chargement des équipes par direction:",
|
|
error
|
|
);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Charge toutes les directions
|
|
*/
|
|
async loadDirections(): Promise<string[]> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/teams/directions`);
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Erreur lors du chargement des directions");
|
|
}
|
|
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error("Erreur lors du chargement des directions:", error);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Crée une nouvelle équipe
|
|
*/
|
|
async createTeam(
|
|
team: Omit<Team, "created_at" | "updated_at">
|
|
): Promise<Team | null> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/teams`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(team),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Erreur lors de la création de l'équipe");
|
|
}
|
|
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error("Erreur lors de la création de l'équipe:", error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Met à jour une équipe
|
|
*/
|
|
async updateTeam(
|
|
teamId: string,
|
|
updates: Partial<Omit<Team, "id">>
|
|
): Promise<Team | null> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/teams/${teamId}`, {
|
|
method: "PUT",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(updates),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Erreur lors de la mise à jour de l'équipe");
|
|
}
|
|
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error("Erreur lors de la mise à jour de l'équipe:", error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Supprime une équipe
|
|
*/
|
|
async deleteTeam(teamId: string): Promise<boolean> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/teams/${teamId}`, {
|
|
method: "DELETE",
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Erreur lors de la suppression de l'équipe");
|
|
}
|
|
|
|
return true;
|
|
} catch (error) {
|
|
console.error("Erreur lors de la suppression de l'équipe:", error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Charge toutes les catégories de skills
|
|
*/
|
|
async loadSkillCategories(): Promise<SkillCategory[]> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/skills`);
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Erreur lors du chargement des catégories de skills");
|
|
}
|
|
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error(
|
|
"Erreur lors du chargement des catégories de skills:",
|
|
error
|
|
);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Charge les skills d'une catégorie
|
|
*/
|
|
async loadSkillsByCategory(categoryId: string): Promise<Skill[]> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/skills/${categoryId}`);
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Erreur lors du chargement des skills par catégorie");
|
|
}
|
|
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error(
|
|
"Erreur lors du chargement des skills par catégorie:",
|
|
error
|
|
);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Migre les skills depuis JSON vers PostgreSQL
|
|
*/
|
|
async migrateSkills(): Promise<{
|
|
success: boolean;
|
|
stats?: any;
|
|
error?: string;
|
|
}> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/skills/migrate`, {
|
|
method: "POST",
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Erreur lors de la migration des skills");
|
|
}
|
|
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error("Erreur lors de la migration des skills:", error);
|
|
return {
|
|
success: false,
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Crée une nouvelle catégorie de skill
|
|
*/
|
|
async createSkillCategory(category: {
|
|
id: string;
|
|
name: string;
|
|
icon: string;
|
|
}): Promise<boolean> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/skills`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(category),
|
|
});
|
|
|
|
return response.ok;
|
|
} catch (error) {
|
|
console.error(
|
|
"Erreur lors de la création de la catégorie de skill:",
|
|
error
|
|
);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Crée une nouvelle skill
|
|
*/
|
|
async createSkill(
|
|
categoryId: string,
|
|
skill: {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
icon?: string;
|
|
links: string[];
|
|
}
|
|
): Promise<boolean> {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}/api/skills/${categoryId}`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(skill),
|
|
});
|
|
|
|
return response.ok;
|
|
} catch (error) {
|
|
console.error("Erreur lors de la création de la skill:", error);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Instance singleton
|
|
export const apiClient = new ApiClient();
|