IGDB integration: auto-scrape on upload + manual scrape button

- New IgdbService: Twitch OAuth2, IGDB API v4 search, cover download
- Upload auto-scrapes IGDB after extracting game ZIP
- GameDetail page: 'Auto Scrape' + 'Search' buttons + result picker
- Upload dialog: optional title field (defaults to filename)
- Jackson SNAKE_CASE naming to match frontend expectations
- IGDB status endpoint to check credentials
This commit is contained in:
David Alvarez
2026-05-25 10:22:58 +02:00
parent f2bd6ca3fb
commit 466299b8f0
8 changed files with 779 additions and 32 deletions
+32 -10
View File
@@ -7,6 +7,7 @@
let search = $state("");
let uploading = $state(false);
let uploadError = $state("");
let uploadTitle = $state("");
let fileInput;
async function loadGames() {
@@ -26,7 +27,8 @@
uploading = true;
uploadError = "";
try {
await uploadGame(file);
await uploadGame(file, uploadTitle.trim() || undefined);
uploadTitle = "";
await loadGames();
fileInput.value = "";
} catch (err) {
@@ -50,17 +52,26 @@
bind:value={search}
oninput={() => loadGames()}
/>
<label class="btn btn-primary upload-label">
{uploading ? "Uploading..." : "+ Upload Game"}
<div class="upload-group">
<input
bind:this={fileInput}
type="file"
accept=".zip"
class="hidden-input"
onchange={handleUpload}
type="text"
class="title-input"
placeholder="Title (optional)"
bind:value={uploadTitle}
disabled={uploading}
/>
</label>
<label class="btn btn-primary upload-label">
{uploading ? "Uploading..." : "+ Upload"}
<input
bind:this={fileInput}
type="file"
accept=".zip"
class="hidden-input"
onchange={handleUpload}
disabled={uploading}
/>
</label>
</div>
</div>
</div>
@@ -111,15 +122,26 @@
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
}
.toolbar-actions input {
min-width: 200px;
}
.upload-group {
display: flex;
gap: 8px;
align-items: center;
}
.title-input {
min-width: 160px !important;
width: 160px;
}
.hidden-input {
display: none;
}
.upload-label {
cursor: pointer;
white-space: nowrap;
}
.grid {
display: grid;
@@ -162,4 +184,4 @@
color: var(--text-dim);
font-size: 0.85rem;
}
</style>
</style>