From 42f7722e509191a64092cc98289d5d09bdc9b2e2 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sun, 14 Dec 2025 12:41:05 -0800 Subject: [PATCH] batch import: use individual inputs instead of comma-separated - start with 3 inputs, add/remove as needed - avoids issues with item names containing commas --- .../database/characters/import/+page.svelte | 105 ++++++++++++++---- .../database/summons/import/+page.svelte | 105 ++++++++++++++---- .../database/weapons/import/+page.svelte | 105 ++++++++++++++---- 3 files changed, 249 insertions(+), 66 deletions(-) diff --git a/src/routes/(app)/database/characters/import/+page.svelte b/src/routes/(app)/database/characters/import/+page.svelte index 75928a57..b409d54f 100644 --- a/src/routes/(app)/database/characters/import/+page.svelte +++ b/src/routes/(app)/database/characters/import/+page.svelte @@ -18,6 +18,7 @@ import SidebarHeader from '$lib/components/ui/SidebarHeader.svelte' import Button from '$lib/components/ui/Button.svelte' import Input from '$lib/components/ui/Input.svelte' + import Icon from '$lib/components/Icon.svelte' import TagInput from '$lib/components/ui/TagInput.svelte' import type { PageData } from './$types' @@ -35,7 +36,7 @@ let { data }: { data: PageData } = $props() // Input phase - let wikiPagesInput = $state('') + let wikiPagesInputs = $state(['', '', '']) let isFetching = $state(false) let fetchError = $state(null) @@ -135,10 +136,20 @@ } } + // Add/remove input fields + function addInput() { + wikiPagesInputs = [...wikiPagesInputs, ''] + } + + function removeInput(index: number) { + if (wikiPagesInputs.length > 1) { + wikiPagesInputs = wikiPagesInputs.filter((_, i) => i !== index) + } + } + // Fetch wiki data for entered pages async function fetchWikiData() { - const pages = wikiPagesInput - .split(',') + const pages = wikiPagesInputs .map((p) => p.trim()) .filter((p) => p.length > 0) .slice(0, 10) @@ -349,24 +360,41 @@ {#if entities.size === 0}
- -
- -

Enter wiki page names separated by commas (up to 10)

-
- {#if fetchError} -

{fetchError}

- {/if} -
- -
-
+

Enter up to 10 wiki page names to import data

+
+ {#each wikiPagesInputs as _, index} +
+ + {#if wikiPagesInputs.length > 1} + + {/if} +
+ {/each} + +
+ {#if fetchError} +

{fetchError}

+ {/if} +
+ +
{:else} @@ -586,15 +614,48 @@ } .input-phase { + display: flex; + flex-direction: column; + gap: spacing.$unit-2x; padding: spacing.$unit-2x; } - .wiki-input { + .wiki-inputs { display: flex; flex-direction: column; gap: spacing.$unit; } + .input-row { + display: flex; + gap: spacing.$unit; + align-items: center; + } + + .remove-button { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + padding: 0; + background: transparent; + border: none; + border-radius: layout.$input-corner; + color: colors.$grey-50; + cursor: pointer; + flex-shrink: 0; + + &:hover { + background: colors.$grey-90; + color: colors.$grey-30; + } + + :global(svg) { + fill: currentColor; + } + } + .hint { font-size: typography.$font-small; color: colors.$grey-50; diff --git a/src/routes/(app)/database/summons/import/+page.svelte b/src/routes/(app)/database/summons/import/+page.svelte index 8d27bf28..1604f8dc 100644 --- a/src/routes/(app)/database/summons/import/+page.svelte +++ b/src/routes/(app)/database/summons/import/+page.svelte @@ -18,6 +18,7 @@ import SidebarHeader from '$lib/components/ui/SidebarHeader.svelte' import Button from '$lib/components/ui/Button.svelte' import Input from '$lib/components/ui/Input.svelte' + import Icon from '$lib/components/Icon.svelte' import TagInput from '$lib/components/ui/TagInput.svelte' import type { PageData } from './$types' @@ -34,7 +35,7 @@ let { data }: { data: PageData } = $props() // Input phase - let wikiPagesInput = $state('') + let wikiPagesInputs = $state(['', '', '']) let isFetching = $state(false) let fetchError = $state(null) @@ -125,10 +126,20 @@ } } + // Add/remove input fields + function addInput() { + wikiPagesInputs = [...wikiPagesInputs, ''] + } + + function removeInput(index: number) { + if (wikiPagesInputs.length > 1) { + wikiPagesInputs = wikiPagesInputs.filter((_, i) => i !== index) + } + } + // Fetch wiki data for entered pages async function fetchWikiData() { - const pages = wikiPagesInput - .split(',') + const pages = wikiPagesInputs .map((p) => p.trim()) .filter((p) => p.length > 0) .slice(0, 10) @@ -326,24 +337,41 @@ {#if entities.size === 0}
- -
- -

Enter wiki page names separated by commas (up to 10)

-
- {#if fetchError} -

{fetchError}

- {/if} -
- -
-
+

Enter up to 10 wiki page names to import data

+
+ {#each wikiPagesInputs as _, index} +
+ + {#if wikiPagesInputs.length > 1} + + {/if} +
+ {/each} + +
+ {#if fetchError} +

{fetchError}

+ {/if} +
+ +
{:else} @@ -564,15 +592,48 @@ } .input-phase { + display: flex; + flex-direction: column; + gap: spacing.$unit-2x; padding: spacing.$unit-2x; } - .wiki-input { + .wiki-inputs { display: flex; flex-direction: column; gap: spacing.$unit; } + .input-row { + display: flex; + gap: spacing.$unit; + align-items: center; + } + + .remove-button { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + padding: 0; + background: transparent; + border: none; + border-radius: layout.$input-corner; + color: colors.$grey-50; + cursor: pointer; + flex-shrink: 0; + + &:hover { + background: colors.$grey-90; + color: colors.$grey-30; + } + + :global(svg) { + fill: currentColor; + } + } + .hint { font-size: typography.$font-small; color: colors.$grey-50; diff --git a/src/routes/(app)/database/weapons/import/+page.svelte b/src/routes/(app)/database/weapons/import/+page.svelte index 9f7be10a..7414c770 100644 --- a/src/routes/(app)/database/weapons/import/+page.svelte +++ b/src/routes/(app)/database/weapons/import/+page.svelte @@ -18,6 +18,7 @@ import SidebarHeader from '$lib/components/ui/SidebarHeader.svelte' import Button from '$lib/components/ui/Button.svelte' import Input from '$lib/components/ui/Input.svelte' + import Icon from '$lib/components/Icon.svelte' import TagInput from '$lib/components/ui/TagInput.svelte' import CharacterTypeahead from '$lib/components/ui/CharacterTypeahead.svelte' @@ -35,7 +36,7 @@ let { data }: { data: PageData } = $props() // Input phase - let wikiPagesInput = $state('') + let wikiPagesInputs = $state(['', '', '']) let isFetching = $state(false) let fetchError = $state(null) @@ -127,10 +128,20 @@ } } + // Add/remove input fields + function addInput() { + wikiPagesInputs = [...wikiPagesInputs, ''] + } + + function removeInput(index: number) { + if (wikiPagesInputs.length > 1) { + wikiPagesInputs = wikiPagesInputs.filter((_, i) => i !== index) + } + } + // Fetch wiki data for entered pages async function fetchWikiData() { - const pages = wikiPagesInput - .split(',') + const pages = wikiPagesInputs .map((p) => p.trim()) .filter((p) => p.length > 0) .slice(0, 10) @@ -331,24 +342,41 @@ {#if entities.size === 0}
- -
- -

Enter wiki page names separated by commas (up to 10)

-
- {#if fetchError} -

{fetchError}

- {/if} -
- -
-
+

Enter up to 10 wiki page names to import data

+
+ {#each wikiPagesInputs as _, index} +
+ + {#if wikiPagesInputs.length > 1} + + {/if} +
+ {/each} + +
+ {#if fetchError} +

{fetchError}

+ {/if} +
+ +
{:else} @@ -567,15 +595,48 @@ } .input-phase { + display: flex; + flex-direction: column; + gap: spacing.$unit-2x; padding: spacing.$unit-2x; } - .wiki-input { + .wiki-inputs { display: flex; flex-direction: column; gap: spacing.$unit; } + .input-row { + display: flex; + gap: spacing.$unit; + align-items: center; + } + + .remove-button { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + padding: 0; + background: transparent; + border: none; + border-radius: layout.$input-corner; + color: colors.$grey-50; + cursor: pointer; + flex-shrink: 0; + + &:hover { + background: colors.$grey-90; + color: colors.$grey-30; + } + + :global(svg) { + fill: currentColor; + } + } + .hint { font-size: typography.$font-small; color: colors.$grey-50;