fix: manual title input searches IGDB first, warns before uploading
Build & Deploy / build-and-deploy (push) Successful in 45s
Build & Deploy / build-and-deploy (push) Successful in 45s
Flow when auto-search finds nothing: 1. User types a title → presses Enter/clicks button 2. System searches IGDB with that title 3a. Results found → shown as selectable cards 3b. No results → warning + amber 'Upload anyway as xxx' button 4. Button label changes: 'Search' → 'Upload' after manual search Also changed Enter key behavior: first press searches, second press uploads (if no results after manual search)
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
let searching = $state(false);
|
let searching = $state(false);
|
||||||
let searchError = $state("");
|
let searchError = $state("");
|
||||||
let igdbResults = $state(null); // null=loading, []=no results, [{...}]=matches
|
let igdbResults = $state(null); // null=loading, []=no results, [{...}]=matches
|
||||||
|
let manualSearched = $state(false); // true after user clicked Search manually
|
||||||
|
|
||||||
let fileInput;
|
let fileInput;
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@
|
|||||||
igdbResults = null;
|
igdbResults = null;
|
||||||
searching = true;
|
searching = true;
|
||||||
searchError = "";
|
searchError = "";
|
||||||
|
manualSearched = false;
|
||||||
fileInput.value = "";
|
fileInput.value = "";
|
||||||
// Auto-search IGDB with the filename
|
// Auto-search IGDB with the filename
|
||||||
searchIGDB(name).then(data => {
|
searchIGDB(name).then(data => {
|
||||||
@@ -54,6 +56,7 @@
|
|||||||
async function handleManualSearch() {
|
async function handleManualSearch() {
|
||||||
const q = pendingTitle.trim();
|
const q = pendingTitle.trim();
|
||||||
if (!q) return;
|
if (!q) return;
|
||||||
|
manualSearched = true;
|
||||||
searching = true;
|
searching = true;
|
||||||
searchError = "";
|
searchError = "";
|
||||||
igdbResults = null;
|
igdbResults = null;
|
||||||
@@ -61,7 +64,7 @@
|
|||||||
const data = await searchIGDB(q);
|
const data = await searchIGDB(q);
|
||||||
igdbResults = data.results || [];
|
igdbResults = data.results || [];
|
||||||
if (igdbResults.length === 0) {
|
if (igdbResults.length === 0) {
|
||||||
searchError = "No matches found on IGDB.";
|
searchError = "No matches found for \"" + q + "\" on IGDB.";
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
searchError = "IGDB search failed: " + err.message;
|
searchError = "IGDB search failed: " + err.message;
|
||||||
@@ -76,6 +79,7 @@
|
|||||||
pendingTitle = "";
|
pendingTitle = "";
|
||||||
igdbResults = null;
|
igdbResults = null;
|
||||||
searchError = "";
|
searchError = "";
|
||||||
|
manualSearched = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function doUpload(title) {
|
async function doUpload(title) {
|
||||||
@@ -173,20 +177,27 @@
|
|||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
{#if searchError}
|
{#if searchError}
|
||||||
<div class="status-msg error-msg">{searchError}</div>
|
<div class="status-msg error-msg">
|
||||||
|
{searchError}
|
||||||
|
{#if manualSearched}
|
||||||
|
<button class="btn btn-sm btn-upload-anyway" onclick={() => doUpload(pendingTitle.trim())} disabled={uploading}>
|
||||||
|
{uploading ? "Uploading..." : "Upload anyway as \"" + pendingTitle.trim() + "\""}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<p class="match-label">No matches found on IGDB. Enter a title manually:</p>
|
<p class="match-label">No matches found. Enter a title to search IGDB:</p>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="upload-custom-row">
|
<div class="upload-custom-row">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Enter game title..."
|
placeholder="Search IGDB..."
|
||||||
bind:value={pendingTitle}
|
bind:value={pendingTitle}
|
||||||
disabled={uploading}
|
disabled={uploading || searching}
|
||||||
onkeydown={(e) => e.key === "Enter" && doUpload(pendingTitle.trim())}
|
onkeydown={(e) => e.key === "Enter" && (manualSearched ? doUpload(pendingTitle.trim()) : handleManualSearch())}
|
||||||
/>
|
/>
|
||||||
<button class="btn" onclick={() => doUpload(pendingTitle.trim())} disabled={uploading || !pendingTitle.trim()}>
|
<button class="btn" onclick={manualSearched ? () => doUpload(pendingTitle.trim()) : handleManualSearch} disabled={uploading || searching || !pendingTitle.trim()}>
|
||||||
{uploading ? "Uploading..." : "Upload"}
|
{uploading ? "Uploading..." : manualSearched ? "Upload" : "Search"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-secondary" onclick={() => doUpload(pendingFileName)} disabled={uploading}>
|
<button class="btn btn-secondary" onclick={() => doUpload(pendingFileName)} disabled={uploading}>
|
||||||
@@ -466,4 +477,15 @@
|
|||||||
.btn-secondary:hover {
|
.btn-secondary:hover {
|
||||||
border-color: var(--text-dim);
|
border-color: var(--text-dim);
|
||||||
}
|
}
|
||||||
|
.btn-upload-anyway {
|
||||||
|
margin-top: 8px;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
border-color: #cc8833;
|
||||||
|
color: #ffaa44;
|
||||||
|
}
|
||||||
|
.btn-upload-anyway:hover {
|
||||||
|
background: #332211;
|
||||||
|
border-color: #ffaa44;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user