feat: add UI components for alert dialog, badge, checkbox, dialog, label, select, sheet, table, textarea
- Implemented AlertDialog component with overlay, content, header, footer, title, description, action, and cancel functionalities. - Created Badge component with variant support for different styles. - Developed Checkbox component with custom styling and indicator. - Added Dialog component with trigger, close, overlay, content, header, footer, title, and description. - Introduced Label component for form elements. - Built Select component with trigger, content, group, item, label, separator, and scroll buttons. - Created Sheet component with trigger, close, overlay, content, header, footer, title, and description. - Implemented Table component with header, body, footer, row, head, cell, and caption. - Added Textarea component with custom styling. - Established API service for game management with CRUD operations and metadata search functionalities. - Updated dependencies in package lock files.
This commit is contained in:
189
frontend/src/lib/api.ts
Normal file
189
frontend/src/lib/api.ts
Normal file
@@ -0,0 +1,189 @@
|
||||
const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000/api';
|
||||
|
||||
export interface Game {
|
||||
id: string;
|
||||
title: string;
|
||||
slug: string;
|
||||
description?: string;
|
||||
releaseDate?: string;
|
||||
genre?: string;
|
||||
platform?: string;
|
||||
year?: number;
|
||||
cover?: string;
|
||||
source: string;
|
||||
sourceId?: string;
|
||||
// Campos específicos de ROM (si source = "rom")
|
||||
romPath?: string;
|
||||
romFilename?: string;
|
||||
romSize?: number;
|
||||
romChecksum?: string;
|
||||
romFormat?: string;
|
||||
romHashes?: string;
|
||||
// IDs de integraciones externas
|
||||
igdbId?: number;
|
||||
rawgId?: number;
|
||||
thegamesdbId?: number;
|
||||
// Metadatos adicionales
|
||||
metadata?: string;
|
||||
// Timestamps
|
||||
addedAt?: string;
|
||||
lastSeenAt?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
// Relaciones
|
||||
artworks?: any[];
|
||||
purchases?: any[];
|
||||
gamePlatforms?: any[];
|
||||
tags?: any[];
|
||||
}
|
||||
|
||||
export interface CreateGameInput {
|
||||
title: string;
|
||||
slug?: string;
|
||||
description?: string;
|
||||
releaseDate?: string;
|
||||
genre?: string;
|
||||
platform?: string;
|
||||
year?: number;
|
||||
cover?: string;
|
||||
source?: string;
|
||||
sourceId?: string;
|
||||
platformId?: string;
|
||||
priceCents?: number;
|
||||
currency?: string;
|
||||
store?: string;
|
||||
date?: string;
|
||||
condition?: 'Loose' | 'CIB' | 'New';
|
||||
}
|
||||
|
||||
export interface UpdateGameInput {
|
||||
title?: string;
|
||||
slug?: string;
|
||||
description?: string;
|
||||
releaseDate?: string;
|
||||
genre?: string;
|
||||
platform?: string;
|
||||
year?: number;
|
||||
cover?: string;
|
||||
source?: string;
|
||||
sourceId?: string;
|
||||
platformId?: string;
|
||||
priceCents?: number;
|
||||
currency?: string;
|
||||
store?: string;
|
||||
date?: string;
|
||||
condition?: 'Loose' | 'CIB' | 'New';
|
||||
}
|
||||
|
||||
export interface ImportRequest {
|
||||
directory: string;
|
||||
recursive?: boolean;
|
||||
}
|
||||
|
||||
export interface ImportResult {
|
||||
success: boolean;
|
||||
message: string;
|
||||
imported: number;
|
||||
errors: string[];
|
||||
}
|
||||
|
||||
export const gamesApi = {
|
||||
getAll: async (): Promise<Game[]> => {
|
||||
const response = await fetch(`${API_BASE}/games`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error fetching games: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
},
|
||||
|
||||
getById: async (id: string): Promise<Game> => {
|
||||
const response = await fetch(`${API_BASE}/games/${id}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error fetching game: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
},
|
||||
|
||||
getBySource: async (source: string): Promise<Game[]> => {
|
||||
const response = await fetch(`${API_BASE}/games/source/${source}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error fetching games by source: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
},
|
||||
|
||||
create: async (data: CreateGameInput): Promise<Game> => {
|
||||
const response = await fetch(`${API_BASE}/games`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error creating game: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
},
|
||||
|
||||
update: async (id: string, data: UpdateGameInput): Promise<Game> => {
|
||||
const response = await fetch(`${API_BASE}/games/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error updating game: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
},
|
||||
|
||||
delete: async (id: string): Promise<void> => {
|
||||
const response = await fetch(`${API_BASE}/games/${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error deleting game: ${response.statusText}`);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const importApi = {
|
||||
start: async (data: ImportRequest): Promise<ImportResult> => {
|
||||
const response = await fetch(`${API_BASE}/import`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error starting import: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
},
|
||||
};
|
||||
|
||||
export const metadataApi = {
|
||||
searchIGDB: async (query: string): Promise<any[]> => {
|
||||
const response = await fetch(`${API_BASE}/metadata/igdb/search?q=${encodeURIComponent(query)}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error searching IGDB: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
},
|
||||
|
||||
searchRAWG: async (query: string): Promise<any[]> => {
|
||||
const response = await fetch(`${API_BASE}/metadata/rawg/search?q=${encodeURIComponent(query)}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error searching RAWG: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
},
|
||||
|
||||
searchTheGamesDB: async (query: string): Promise<any[]> => {
|
||||
const response = await fetch(
|
||||
`${API_BASE}/metadata/thegamesdb/search?q=${encodeURIComponent(query)}`
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error searching TheGamesDB: ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user