Files
quasar/backend/src/controllers/gamesController.ts
Benito Rodríguez 630ebe0dc8 feat: implement complete game management with CRUD functionality
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.
2026-02-11 22:09:02 +01:00

181 lines
4.2 KiB
TypeScript

import { prisma } from '../plugins/prisma';
import { CreateGameInput, UpdateGameInput } from '../validators/gameValidator';
import { Prisma } from '@prisma/client';
export class GamesController {
/**
* Listar todos los juegos con sus plataformas y compras
*/
static async listGames() {
return await prisma.game.findMany({
include: {
gamePlatforms: {
include: {
platform: true,
},
},
purchases: true,
},
orderBy: {
title: 'asc',
},
});
}
/**
* Crear un juego nuevo
*/
static async createGame(input: CreateGameInput) {
const { title, platformId, description, priceCents, currency, store, date, condition } = input;
// Generar slug basado en el título
const slug = title
.toLowerCase()
.replace(/\s+/g, '-')
.replace(/[^\w-]/g, '');
const gameData: Prisma.GameCreateInput = {
title,
slug: `${slug}-${Date.now()}`, // Hacer slug único agregando timestamp
description: description || null,
};
// Si se proporciona una plataforma, crearla en gamePlatforms
if (platformId) {
gameData.gamePlatforms = {
create: {
platformId,
},
};
}
// Si se proporciona precio, crear en purchases
if (priceCents) {
gameData.purchases = {
create: {
priceCents,
currency: currency || 'USD',
store: store || null,
date: date ? new Date(date) : new Date(),
},
};
}
return await prisma.game.create({
data: gameData,
include: {
gamePlatforms: {
include: {
platform: true,
},
},
purchases: true,
},
});
}
/**
* Actualizar un juego existente
*/
static async updateGame(id: string, input: UpdateGameInput) {
const { title, platformId, description, priceCents, currency, store, date } = input;
const updateData: Prisma.GameUpdateInput = {};
if (title !== undefined) {
updateData.title = title;
// Regenerar slug si cambia el título
const slug = title
.toLowerCase()
.replace(/\s+/g, '-')
.replace(/[^\w-]/g, '');
updateData.slug = `${slug}-${Date.now()}`;
}
if (description !== undefined) {
updateData.description = description;
}
const game = await prisma.game.update({
where: { id },
data: updateData,
include: {
gamePlatforms: {
include: {
platform: true,
},
},
purchases: true,
},
});
// Si se actualiza plataforma, sincronizar
if (platformId !== undefined) {
// Eliminar relaciones antiguas
await prisma.gamePlatform.deleteMany({
where: { gameId: id },
});
// Crear nueva relación si se proporcionó platformId
if (platformId) {
await prisma.gamePlatform.create({
data: {
gameId: id,
platformId,
},
});
}
}
// Si se actualiza precio, agregar nueva compra (crear histórico)
if (priceCents !== undefined) {
await prisma.purchase.create({
data: {
gameId: id,
priceCents,
currency: currency || 'USD',
store: store || null,
date: date ? new Date(date) : new Date(),
},
});
}
// Retornar el juego actualizado
return await prisma.game.findUniqueOrThrow({
where: { id },
include: {
gamePlatforms: {
include: {
platform: true,
},
},
purchases: true,
},
});
}
/**
* Eliminar un juego (y sus relaciones en cascada)
*/
static async deleteGame(id: string) {
// Validar que el juego existe
const game = await prisma.game.findUnique({ where: { id } });
if (!game) {
throw new Error('Juego no encontrado');
}
// Eliminar todas las relaciones (Prisma maneja cascada según schema)
await prisma.game.delete({
where: { id },
});
return { message: 'Juego eliminado correctamente' };
}
}
/**
* Metadatos:
* Autor: GitHub Copilot
* Última actualización: 2026-02-11
*/