workspace/projects/gamilit/apps/frontend/src/services/api/gamificationAPI.ts
rckrdmrd a249c99be2
Some checks failed
CI Pipeline / changes (push) Has been cancelled
CI Pipeline / core (push) Has been cancelled
CI Pipeline / trading-backend (push) Has been cancelled
CI Pipeline / trading-data-service (push) Has been cancelled
CI Pipeline / trading-frontend (push) Has been cancelled
CI Pipeline / erp-core (push) Has been cancelled
CI Pipeline / erp-mecanicas (push) Has been cancelled
CI Pipeline / gamilit-backend (push) Has been cancelled
CI Pipeline / gamilit-frontend (push) Has been cancelled
feat: Sincronizacion completa workspace 2025-12-26
## Backend
- fix(ranks): Reordenar rutas en RanksController para evitar conflictos 404
- feat(gamification): Agregar MayaRankEntity al modulo
- feat(ml-coins): Expandir funcionalidad del servicio
- feat(teacher): Mejoras en dashboard, mensajes y reportes
- feat(entities): Nuevas entidades admin, educational, progress, social

## Frontend
- feat(gamificationAPI): API completa para ranks con endpoints
- feat(RubricEvaluator): Nuevo componente para evaluacion docente
- refactor(admin): Mejoras en hooks y paginas
- refactor(teacher): Mejoras en paginas del portal

## Database
- fix(initialize_user_stats): Agregar is_current y achieved_at a user_ranks
- fix(notifications-policies): Corregir RLS con JOIN correcto
- feat(friendships): Agregar columna status con estados
- sync(seeds): Homologacion completa DEV <-> PROD

## Docs & Orchestration
- docs(api): Actualizar API-TEACHER-MODULE.md
- docs(frontend): COMPONENTES-INVENTARIO.md
- docs(database): VIEWS-INVENTARIO.md, VALIDACION-DDL-SEEDS
- Reportes de analisis y validacion

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 17:53:38 -06:00

376 lines
9.9 KiB
TypeScript

/**
* Gamification API Integration
*
* API client for gamification features including user stats, achievements,
* ML Coins, ranks, and leaderboards.
*/
import { apiClient } from '@/services/api/apiClient';
import { handleAPIError } from './apiErrorHandler';
// ============================================================================
// TYPE DEFINITIONS
// ============================================================================
/**
* User Gamification Summary
*
* Consolidated gamification data for Admin/Teacher portals
*/
export interface UserGamificationSummary {
userId: string;
level: number;
totalXP: number;
mlCoins: number;
rank: string;
rankColor?: string;
progressToNextLevel: number;
xpToNextLevel: number;
achievements: string[];
totalAchievements: number;
}
/**
* Rank Metadata
* Information about a Maya rank configuration
*/
export interface RankMetadata {
rank: string;
name: string;
description: string;
xp_min: number;
xp_max: number;
ml_coins_bonus: number;
order: number;
}
/**
* User Rank
* Current rank record for a user
*/
export interface UserRank {
id: string;
user_id: string;
rank: string;
is_current: boolean;
achieved_at: string;
created_at: string;
updated_at: string;
}
/**
* Rank Progress
* Progress towards the next rank
*/
export interface RankProgress {
currentRank: string;
nextRank: string | null;
currentXP: number;
xpForCurrentRank: number;
xpForNextRank: number;
progressPercentage: number;
xpRemaining: number;
isMaxRank: boolean;
}
/**
* Create User Rank DTO (Admin)
*/
export interface CreateUserRankDto {
user_id: string;
rank: string;
is_current?: boolean;
}
/**
* Update User Rank DTO (Admin)
*/
export interface UpdateUserRankDto {
rank?: string;
is_current?: boolean;
}
// ============================================================================
// API FUNCTIONS
// ============================================================================
/**
* Get user gamification summary
*
* @description Fetches consolidated gamification data for a user.
* Used in Admin/Teacher portals to display user's level, XP, coins, rank, etc.
*
* @param userId - User UUID
* @returns Promise<UserGamificationSummary>
*
* @endpoint GET /api/v1/gamification/users/:userId/summary
*
* @example
* ```ts
* const summary = await getUserGamificationSummary('550e8400-e29b-41d4-a716-446655440000');
* console.log(summary.level, summary.rank, summary.mlCoins);
* ```
*/
export async function getUserGamificationSummary(userId: string): Promise<UserGamificationSummary> {
try {
const response = await apiClient.get<UserGamificationSummary>(
`/gamification/users/${userId}/summary`,
);
return response.data;
} catch (error) {
throw handleAPIError(error, 'Failed to fetch user gamification summary');
}
}
// ============================================================================
// RANKS API FUNCTIONS
// ============================================================================
/**
* List all available ranks
*
* @description Fetches all Maya ranks with their metadata (XP requirements, bonuses, etc.)
* @returns Promise<RankMetadata[]>
* @endpoint GET /api/v1/gamification/ranks
*/
export async function listRanks(): Promise<RankMetadata[]> {
try {
const response = await apiClient.get<RankMetadata[]>('/gamification/ranks');
return response.data;
} catch (error) {
throw handleAPIError(error, 'Failed to fetch ranks list');
}
}
/**
* Get current user's rank
*
* @description Fetches the current rank of the authenticated user
* @returns Promise<UserRank>
* @endpoint GET /api/v1/gamification/ranks/current
*/
export async function getCurrentRank(): Promise<UserRank> {
try {
const response = await apiClient.get<UserRank>('/gamification/ranks/current');
return response.data;
} catch (error) {
throw handleAPIError(error, 'Failed to fetch current rank');
}
}
/**
* Get user's rank progress
*
* @description Calculates and returns progress towards the next rank
* @param userId - User UUID
* @returns Promise<RankProgress>
* @endpoint GET /api/v1/gamification/ranks/users/:userId/rank-progress
*/
export async function getRankProgress(userId: string): Promise<RankProgress> {
try {
const response = await apiClient.get<RankProgress>(
`/gamification/ranks/users/${userId}/rank-progress`,
);
return response.data;
} catch (error) {
throw handleAPIError(error, 'Failed to fetch rank progress');
}
}
/**
* Get user's rank history
*
* @description Fetches the complete history of ranks achieved by the user
* @param userId - User UUID
* @returns Promise<UserRank[]>
* @endpoint GET /api/v1/gamification/ranks/users/:userId/rank-history
*/
export async function getRankHistory(userId: string): Promise<UserRank[]> {
try {
const response = await apiClient.get<UserRank[]>(
`/gamification/ranks/users/${userId}/rank-history`,
);
return response.data;
} catch (error) {
throw handleAPIError(error, 'Failed to fetch rank history');
}
}
/**
* Check promotion eligibility
*
* @description Verifies if the user meets requirements for rank promotion
* @param userId - User UUID
* @returns Promise<{ eligible: boolean }>
* @endpoint GET /api/v1/gamification/ranks/check-promotion/:userId
*/
export async function checkPromotionEligibility(userId: string): Promise<{ eligible: boolean }> {
try {
const response = await apiClient.get<{ eligible: boolean }>(
`/gamification/ranks/check-promotion/${userId}`,
);
return response.data;
} catch (error) {
throw handleAPIError(error, 'Failed to check promotion eligibility');
}
}
/**
* Promote user to next rank
*
* @description Promotes the user to the next Maya rank if eligible
* @param userId - User UUID
* @returns Promise<UserRank>
* @endpoint POST /api/v1/gamification/ranks/promote/:userId
*/
export async function promoteUser(userId: string): Promise<UserRank> {
try {
const response = await apiClient.post<UserRank>(
`/gamification/ranks/promote/${userId}`,
);
return response.data;
} catch (error) {
throw handleAPIError(error, 'Failed to promote user');
}
}
/**
* Get rank details by ID
*
* @description Fetches detailed information about a specific rank record
* @param rankId - Rank record UUID
* @returns Promise<UserRank>
* @endpoint GET /api/v1/gamification/ranks/:id
*/
export async function getRankDetails(rankId: string): Promise<UserRank> {
try {
const response = await apiClient.get<UserRank>(`/gamification/ranks/${rankId}`);
return response.data;
} catch (error) {
throw handleAPIError(error, 'Failed to fetch rank details');
}
}
// ============================================================================
// ADMIN RANKS API FUNCTIONS
// ============================================================================
/**
* Create rank record (Admin)
*
* @description Manually creates a new rank record. Admin only.
* @param dto - CreateUserRankDto with user_id and rank
* @returns Promise<UserRank>
* @endpoint POST /api/v1/gamification/ranks/admin/ranks
*/
export async function createRank(dto: CreateUserRankDto): Promise<UserRank> {
try {
const response = await apiClient.post<UserRank>('/gamification/ranks/admin/ranks', dto);
return response.data;
} catch (error) {
throw handleAPIError(error, 'Failed to create rank');
}
}
/**
* Update rank record (Admin)
*
* @description Updates an existing rank record. Admin only.
* @param rankId - Rank record UUID
* @param dto - UpdateUserRankDto with fields to update
* @returns Promise<UserRank>
* @endpoint PUT /api/v1/gamification/ranks/admin/ranks/:id
*/
export async function updateRank(rankId: string, dto: UpdateUserRankDto): Promise<UserRank> {
try {
const response = await apiClient.put<UserRank>(
`/gamification/ranks/admin/ranks/${rankId}`,
dto,
);
return response.data;
} catch (error) {
throw handleAPIError(error, 'Failed to update rank');
}
}
/**
* Delete rank record (Admin)
*
* @description Deletes a rank record. Cannot delete current rank. Admin only.
* @param rankId - Rank record UUID
* @returns Promise<void>
* @endpoint DELETE /api/v1/gamification/ranks/admin/ranks/:id
*/
export async function deleteRank(rankId: string): Promise<void> {
try {
await apiClient.delete(`/gamification/ranks/admin/ranks/${rankId}`);
} catch (error) {
throw handleAPIError(error, 'Failed to delete rank');
}
}
// ============================================================================
// EXPORTS
// ============================================================================
/**
* Gamification API namespace
*
* @usage
* ```ts
* import { gamificationAPI } from '@/services/api/gamificationAPI';
*
* const summary = await gamificationAPI.getUserSummary('user-id');
* const ranks = await gamificationAPI.ranks.list();
* const progress = await gamificationAPI.ranks.getProgress('user-id');
* ```
*/
export const gamificationAPI = {
getUserSummary: getUserGamificationSummary,
// Ranks sub-namespace
ranks: {
list: listRanks,
getCurrent: getCurrentRank,
getProgress: getRankProgress,
getHistory: getRankHistory,
checkPromotion: checkPromotionEligibility,
promote: promoteUser,
getDetails: getRankDetails,
// Admin operations
admin: {
create: createRank,
update: updateRank,
delete: deleteRank,
},
},
};
/**
* Standalone Ranks API for direct imports
*
* @usage
* ```ts
* import { ranksAPI } from '@/services/api/gamificationAPI';
*
* const progress = await ranksAPI.getProgress('user-id');
* ```
*/
export const ranksAPI = {
list: listRanks,
getCurrent: getCurrentRank,
getProgress: getRankProgress,
getHistory: getRankHistory,
checkPromotion: checkPromotionEligibility,
promote: promoteUser,
getDetails: getRankDetails,
admin: {
create: createRank,
update: updateRank,
delete: deleteRank,
},
};
export default gamificationAPI;