Backend: - Add RESTful API endpoints for games: GET, POST, PUT, DELETE /api/games - Implement GamesController for handling game operations - Validate game input using Zod - Create comprehensive tests for all endpoints Frontend: - Develop GameForm component for creating and editing games with validation - Create GameCard component for displaying game details - Implement custom hooks (useGames, useCreateGame, useUpdateGame, useDeleteGame) for data fetching and mutations - Build Games page with a responsive table for game management - Add unit tests for GameForm and Games page components Tests: - Ensure all backend and frontend tests pass successfully - Achieve 100% coverage for new features All changes are thoroughly tested and validated.
83 lines
2.1 KiB
TypeScript
83 lines
2.1 KiB
TypeScript
/**
|
|
* Cliente RAWG
|
|
* - `searchGames(query)`
|
|
* - `getGameById(id)`
|
|
*/
|
|
import { fetch } from 'undici';
|
|
|
|
export type MetadataGame = {
|
|
id?: number;
|
|
name: string;
|
|
slug?: string;
|
|
releaseDate?: string;
|
|
genres?: string[];
|
|
platforms?: any[];
|
|
coverUrl?: string;
|
|
source?: string;
|
|
};
|
|
|
|
const API_BASE = 'https://api.rawg.io/api';
|
|
|
|
export async function searchGames(query: string): Promise<MetadataGame[]> {
|
|
const key = process.env.RAWG_API_KEY;
|
|
if (!key) return [];
|
|
|
|
try {
|
|
const url = `${API_BASE}/games?key=${encodeURIComponent(key)}&search=${encodeURIComponent(
|
|
query
|
|
)}&page_size=10`;
|
|
const res = await fetch(url);
|
|
if (!res.ok) return [];
|
|
const json = await res.json();
|
|
const hits = Array.isArray(json.results) ? json.results : [];
|
|
return hits.map((r: any) => ({
|
|
id: r.id,
|
|
name: r.name,
|
|
slug: r.slug,
|
|
releaseDate: r.released,
|
|
genres: Array.isArray(r.genres) ? r.genres.map((g: any) => g.name) : undefined,
|
|
platforms: r.platforms,
|
|
coverUrl: r.background_image ?? undefined,
|
|
source: 'rawg',
|
|
}));
|
|
} catch (err) {
|
|
// eslint-disable-next-line no-console
|
|
console.debug('rawgClient.searchGames error', err);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
export async function getGameById(id: number): Promise<MetadataGame | null> {
|
|
const key = process.env.RAWG_API_KEY;
|
|
if (!key) return null;
|
|
|
|
try {
|
|
const url = `${API_BASE}/games/${encodeURIComponent(String(id))}?key=${encodeURIComponent(
|
|
key
|
|
)}`;
|
|
const res = await fetch(url);
|
|
if (!res.ok) return null;
|
|
const json = await res.json();
|
|
if (!json) return null;
|
|
return {
|
|
id: json.id,
|
|
name: json.name,
|
|
slug: json.slug,
|
|
releaseDate: json.released,
|
|
genres: Array.isArray(json.genres) ? json.genres.map((g: any) => g.name) : undefined,
|
|
coverUrl: json.background_image ?? undefined,
|
|
source: 'rawg',
|
|
};
|
|
} catch (err) {
|
|
// eslint-disable-next-line no-console
|
|
console.debug('rawgClient.getGameById error', err);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Metadatos:
|
|
* Autor: GitHub Copilot
|
|
* Última actualización: 2026-02-11
|
|
*/
|