+ {#if loading}
+
+ {:else}
+
+
+
+ Categories
- {#if categories.length === 0}
- No categories yet.
- {:else}
-
- {#each categories as cat}
-
- {#if editingCat?.id === cat.id}
-
-
-
-
- {:else}
-
-
{cat.name}
-
-
- {/if}
+
+
+
+
+
+
+ {#if categories.length === 0}
+
No categories yet.
+ {:else}
+
- {/each}
-
- {/if}
-
+ {/if}
+
-
-
- Custom Groups
+
+
+ Custom Groups
-
-
-
+
+
+
+
+
+ {#if groups.length === 0}
+
No groups yet.
+ {:else}
+
+ {#each groups as group}
+
+
+
{group.name}
+
+
+
+ {#each stores as store}
+
+ {/each}
+
+
+ {/each}
+
+ {/if}
+
-
- {#if groups.length === 0}
- No groups yet.
- {:else}
-
- {#each groups as group}
-
-
-
{group.name}
-
-
-
- {#each stores as store}
-
- {/each}
-
-
- {/each}
-
- {/if}
-
- {/if}
+ {/if}
+
diff --git a/src/client/src/routes/admin/stores/[id]/+page.svelte b/src/client/src/routes/admin/stores/[id]/+page.svelte
index 4bfce34..c5a7f44 100644
--- a/src/client/src/routes/admin/stores/[id]/+page.svelte
+++ b/src/client/src/routes/admin/stores/[id]/+page.svelte
@@ -10,42 +10,22 @@
let loading = $state(true);
let form = $state({
- name: '',
- base_url: '',
- search_url: '',
- sel_container: '',
- sel_name: '',
- sel_price: '',
- sel_link: '',
- sel_image: '',
- category_id: '',
- currency: 'EUR',
- rate_limit: 2,
- user_agent: '',
- proxy_url: '',
- headers_json: '',
+ name: '', base_url: '', search_url: '',
+ sel_container: '', sel_name: '', sel_price: '', sel_link: '', sel_image: '',
+ category_id: '', currency: 'EUR', rate_limit: 2,
+ user_agent: '', proxy_url: '', headers_json: '',
});
onMount(async () => {
- const id = $page.params.id;
- const [store, cats] = await Promise.all([getStore(Number(id)), getCategories()]);
+ const [store, cats] = await Promise.all([getStore(Number($page.params.id)), getCategories()]);
categories = cats;
-
form = {
- name: store.name,
- base_url: store.base_url,
- search_url: store.search_url,
- sel_container: store.sel_container,
- sel_name: store.sel_name,
- sel_price: store.sel_price,
- sel_link: store.sel_link,
- sel_image: store.sel_image || '',
- category_id: store.category_id?.toString() || '',
- currency: store.currency,
- rate_limit: store.rate_limit,
- user_agent: store.user_agent || '',
- proxy_url: store.proxy_url || '',
- headers_json: store.headers_json || '',
+ name: store.name, base_url: store.base_url, search_url: store.search_url,
+ sel_container: store.sel_container, sel_name: store.sel_name, sel_price: store.sel_price,
+ sel_link: store.sel_link, sel_image: store.sel_image || '',
+ category_id: store.category_id?.toString() || '', currency: store.currency,
+ rate_limit: store.rate_limit, user_agent: store.user_agent || '',
+ proxy_url: store.proxy_url || '', headers_json: store.headers_json || '',
};
loading = false;
});
@@ -54,147 +34,100 @@
e.preventDefault();
error = '';
saving = true;
-
try {
const data = { ...form };
- if (data.category_id) data.category_id = Number(data.category_id);
- else delete data.category_id;
-
+ if (data.category_id) data.category_id = Number(data.category_id); else delete data.category_id;
await updateStore(Number($page.params.id), data);
goto('/admin');
- } catch (err) {
- error = err.message || 'Failed to update store';
- } finally {
- saving = false;
- }
+ } catch (err) { error = err.message || 'Failed to update store'; }
+ finally { saving = false; }
}
-
-
-
Edit Store
-
- Test Store
-
+
+
- {#if loading}
-
-
-
+
+
+ {#if loading}
+
+ {:else}
+ {#if error}
+
{error}
+ {/if}
+
+
+ {/if}
- {:else}
- {#if error}
-
{error}
- {/if}
-
-
- {/if}
+
diff --git a/src/client/src/routes/admin/stores/[id]/test/+page.svelte b/src/client/src/routes/admin/stores/[id]/test/+page.svelte
index 9dddd30..345a2e5 100644
--- a/src/client/src/routes/admin/stores/[id]/test/+page.svelte
+++ b/src/client/src/routes/admin/stores/[id]/test/+page.svelte
@@ -19,182 +19,167 @@
if (!query.trim()) return;
testing = true;
result = null;
-
- try {
- result = await testStore(Number($page.params.id), query.trim());
- } catch (err) {
- result = { success: false, error: err.message };
- } finally {
- testing = false;
- }
+ try { result = await testStore(Number($page.params.id), query.trim()); }
+ catch (err) { result = { success: false, error: err.message }; }
+ finally { testing = false; }
}
function formatPrice(price, currency) {
if (price === null || price === undefined) return 'N/A';
- try {
- return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(price);
- } catch {
- return `${currency} ${price.toFixed(2)}`;
- }
+ try { return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(price); }
+ catch { return `${currency} ${price.toFixed(2)}`; }
}
-
+
{#if loading}
-
-
-
+
{:else if store}
-
-
←
-
-
Test: {store.name}
-
{store.base_url}
+
+
+
+
←
+
+
Test: {store.name}
+
{store.base_url}
+
-
- {#if store.health}
-
-
-
{store.health.total}
-
Total Scrapes
+
+
+ {#if store.health}
+
+
+
{store.health.total}
+
Total Scrapes
+
+
+
{store.health.successful}
+
Successful
+
+
+
{store.health.failed}
+
Failed
+
+
+
{store.health.avg_duration_ms}ms
+
Avg Duration
+
-
-
{store.health.successful}
-
Successful
-
-
-
{store.health.failed}
-
Failed
-
-
-
{store.health.avg_duration_ms}ms
-
Avg Duration
-
-
- {/if}
+ {/if}
-
-
+
-
- {#if result}
-
-
-
-
- {result.success ? `Found ${result.itemsFound} products` : 'Test failed'}
+
+ {#if result}
+
+
+
+
+
+ {result.success ? `Found ${result.itemsFound} products` : 'Test failed'}
+
{#if result.searchUrl}
-
URL: {result.searchUrl}
+
{result.searchUrl}
{/if}
{#if result.duration}
-
Duration: {result.duration}ms
+
{result.duration}ms
{/if}
{#if result.error}
-
{result.error}
+
{result.error}
{/if}
{#if result.success}
-
-
-
Parsed Products ({result.parsedProducts?.length || 0})
- {#if result.parsedProducts?.length > 0}
-
-
-
-
- | Name |
- Price |
- Raw Price |
- Link |
-
-
-
- {#each result.parsedProducts as product}
-
- | {product.name} |
- {formatPrice(product.price, product.currency)} |
- {product.priceText} |
-
-
- {product.url}
-
- |
-
- {/each}
-
-
+
+ {#if result.parsedProducts?.length > 0}
+
+
+
Parsed Products ({result.parsedProducts.length})
- {:else}
-
No products parsed. Check your CSS selectors.
- {/if}
-
+
+
+
+ | Name |
+ Price |
+ Raw |
+ Link |
+
+
+
+ {#each result.parsedProducts as product}
+
+ | {product.name} |
+ {formatPrice(product.price, product.currency)} |
+ {product.priceText} |
+
+ {product.url}
+ |
+
+ {/each}
+
+
+
+ {:else}
+
+ No products parsed. Check your CSS selectors.
+
+ {/if}
-
-
-
+
+
+
Raw HTML Preview ({result.rawHtmlLength?.toLocaleString()} bytes)
-
-
{result.rawHtmlPreview}
+
+
{result.rawHtmlPreview}
{/if}
{#if result.recentLogs?.length > 0}
-
-
Recent Scrape Logs
-
-
-
-
- | Status |
- Query |
- Results |
- Duration |
- Time |
-
-
-
- {#each result.recentLogs as log}
-
- |
-
- |
- {log.query} |
- {log.result_count} |
- {log.duration_ms}ms |
- {log.scraped_at} |
-
- {/each}
-
-
+
+
+
Recent Scrape Logs
+
+
+
+ |
+ Query |
+ Results |
+ Duration |
+ Time |
+
+
+
+ {#each result.recentLogs as log}
+
+ |
+ {log.query} |
+ {log.result_count} |
+ {log.duration_ms}ms |
+ {log.scraped_at} |
+
+ {/each}
+
+
{/if}
-
- {/if}
+ {/if}
+
{/if}
diff --git a/src/client/src/routes/admin/stores/new/+page.svelte b/src/client/src/routes/admin/stores/new/+page.svelte
index 759f823..345c93d 100644
--- a/src/client/src/routes/admin/stores/new/+page.svelte
+++ b/src/client/src/routes/admin/stores/new/+page.svelte
@@ -8,167 +8,136 @@
let saving = $state(false);
let form = $state({
- name: '',
- base_url: '',
- search_url: '',
- sel_container: '',
- sel_name: '',
- sel_price: '',
- sel_link: '',
- sel_image: '',
- category_id: '',
- currency: 'EUR',
- rate_limit: 2,
- user_agent: '',
- proxy_url: '',
- headers_json: '',
+ name: '', base_url: '', search_url: '',
+ sel_container: '', sel_name: '', sel_price: '', sel_link: '', sel_image: '',
+ category_id: '', currency: 'EUR', rate_limit: 2,
+ user_agent: '', proxy_url: '', headers_json: '',
});
- onMount(async () => {
- categories = await getCategories();
- });
+ onMount(async () => { categories = await getCategories(); });
async function handleSubmit(e) {
e.preventDefault();
error = '';
saving = true;
-
try {
const data = { ...form };
- if (data.category_id) data.category_id = Number(data.category_id);
- else delete data.category_id;
+ if (data.category_id) data.category_id = Number(data.category_id); else delete data.category_id;
if (!data.sel_image) delete data.sel_image;
if (!data.user_agent) delete data.user_agent;
if (!data.proxy_url) delete data.proxy_url;
if (!data.headers_json) delete data.headers_json;
-
const store = await createStore(data);
goto(`/admin/stores/${store.id}/test`);
- } catch (err) {
- error = err.message || 'Failed to create store';
- } finally {
- saving = false;
- }
+ } catch (err) { error = err.message || 'Failed to create store'; }
+ finally { saving = false; }
}
-
-
Add New Store
-
- {#if error}
-
{error}
- {/if}
-
-