basic games page layout

This commit is contained in:
roormonger
2026-03-23 22:24:45 -04:00
parent 80a198b324
commit 5fe789a8fd
4 changed files with 452 additions and 13 deletions

View File

@@ -2,8 +2,25 @@ export interface Game {
id: string;
title: string;
system: string;
size: string;
coverUrl: string;
size: number;
}
export interface Platform {
id: number;
name: string;
slug: string;
romCount: number;
iconUrl?: string;
}
export interface DetailedGame extends Game {
summary?: string;
developer?: string;
publisher?: string;
genres?: string[];
releaseDate?: string;
screenshots?: string[];
}
export interface RommCollection {
@@ -45,23 +62,23 @@ const getFullImageUrl = (urlPath: string | undefined): string | undefined => {
// Map RomM's native spec to our simplified app interface
const mapRomToGame = (apiRom: any): Game => {
let coverUrl = 'https://images.unsplash.com/photo-1550745165-9bc0b252726f?auto=format&fit=crop&q=80&w=400';
if (apiRom.url_cover) {
coverUrl = getFullImageUrl(apiRom.url_cover) || coverUrl;
} else if (apiRom.url_covers_large && apiRom.url_covers_large.length > 0) {
coverUrl = getFullImageUrl(apiRom.url_covers_large[0]) || coverUrl;
}
return {
id: String(apiRom.id),
title: apiRom.name || apiRom.fs_name_no_ext || 'Unknown Title',
title: apiRom.name || apiRom.fs_name,
system: apiRom.platform_display_name || apiRom.platform_slug || 'Unknown Platform',
coverUrl,
size: apiRom.fs_size_bytes || 0
size: formatBytes(apiRom.fs_size_bytes || 0),
coverUrl: getFullImageUrl(apiRom.url_cover) || 'https://images.unsplash.com/photo-1550745165-9bc0b252726f?auto=format&fit=crop&q=80&w=400',
};
};
const formatBytes = (bytes: number) => {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
};
export const rommApiClient = {
get apiBase() {
const cleanUrl = getBaseUrl();
@@ -131,6 +148,42 @@ export const rommApiClient = {
return res.json();
},
async fetchPlatforms(): Promise<Platform[]> {
const res = await fetch(`${this.apiBase}/platforms`, { headers: this.headers });
if (!res.ok) throw new Error('Failed to fetch platforms.');
const json = await res.json();
return json.map((p: any) => ({
id: p.id,
name: p.display_name || p.name || p.fs_slug,
slug: p.fs_slug,
romCount: p.rom_count || 0,
iconUrl: getFullImageUrl(p.url_logo)
}));
},
async fetchGamesByPlatform(platformId: number): Promise<Game[]> {
const res = await fetch(`${this.apiBase}/roms?platform_ids=${platformId}&limit=100`, { headers: this.headers });
if (!res.ok) throw new Error('Failed to fetch platform games.');
const json = await res.json();
return json.items ? json.items.map(mapRomToGame) : [];
},
async fetchGameDetails(gameId: string): Promise<DetailedGame> {
const res = await fetch(`${this.apiBase}/roms/${gameId}`, { headers: this.headers });
if (!res.ok) throw new Error('Failed to fetch game details.');
const json = await res.json();
const game = mapRomToGame(json);
return {
...game,
summary: json.summary,
developer: json.developer,
publisher: json.publisher,
genres: json.genres,
releaseDate: json.release_date,
screenshots: (json.screenshots || []).map((s: any) => getFullImageUrl(s.url) || '')
};
},
async fetchCollections(): Promise<RommCollection[]> {
const res = await fetch(`${this.apiBase}/collections`, { headers: this.headers });
if (!res.ok) throw new Error('Failed to fetch collections meta.');