diff --git a/src/routes/(app)/database/characters/import/+page.server.ts b/src/routes/(app)/database/characters/import/+page.server.ts
new file mode 100644
index 00000000..583d67be
--- /dev/null
+++ b/src/routes/(app)/database/characters/import/+page.server.ts
@@ -0,0 +1,15 @@
+import type { PageServerLoad } from './$types'
+import { redirect } from '@sveltejs/kit'
+
+export const load: PageServerLoad = async ({ parent }) => {
+ const parentData = await parent()
+
+ // Require editor role (>= 7) to access batch import
+ if (!parentData.role || parentData.role < 7) {
+ throw redirect(302, '/database/characters')
+ }
+
+ return {
+ role: parentData.role
+ }
+}
diff --git a/src/routes/(app)/database/characters/import/+page.svelte b/src/routes/(app)/database/characters/import/+page.svelte
new file mode 100644
index 00000000..7661a800
--- /dev/null
+++ b/src/routes/(app)/database/characters/import/+page.svelte
@@ -0,0 +1,612 @@
+
+
+
+
+
+
+ {#snippet leftAccessory()}
+
+ {/snippet}
+ {#snippet rightAccessory()}
+ {#if selectedEntity?.status === 'success'}
+
+ {/if}
+ {/snippet}
+
+
+ {#if saveError}
+
{saveError}
+ {/if}
+
+
+ {#if entities.size === 0}
+
+ {:else}
+
+
+
+
+
+
+ {#if selectedEntity}
+ {#if selectedEntity.status === 'error'}
+
+
Failed to load: {selectedWikiPage}
+
{selectedEntity.error}
+
+ {:else if selectedEntity.status === 'loading'}
+
+ {:else if selectedFormData}
+ {@const suggestions = selectedEntity.suggestions}
+ {@const dismissed = selectedDismissed}
+
+
+ handleAcceptSuggestion('name', suggestions?.nameEn)}
+ onDismissSuggestion={() => handleDismissSuggestion('name')}
+ />
+ handleAcceptSuggestion('nameJp', suggestions?.nameJp)}
+ onDismissSuggestion={() => handleDismissSuggestion('nameJp')}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ handleAcceptSuggestion('releaseDate', suggestions?.releaseDate)}
+ onDismissSuggestion={() => handleDismissSuggestion('releaseDate')}
+ />
+ {#if selectedFormData.flb}
+ handleAcceptSuggestion('flbDate', suggestions?.flbDate)}
+ onDismissSuggestion={() => handleDismissSuggestion('flbDate')}
+ />
+ {/if}
+ {#if selectedFormData.ulb}
+ handleAcceptSuggestion('ulbDate', suggestions?.ulbDate)}
+ onDismissSuggestion={() => handleDismissSuggestion('ulbDate')}
+ />
+ {/if}
+
+
+
+
+
+ handleAcceptSuggestion('gamewith', suggestions?.gamewith)}
+ onDismissSuggestion={() => handleDismissSuggestion('gamewith')}
+ />
+ handleAcceptSuggestion('kamigame', suggestions?.kamigame)}
+ onDismissSuggestion={() => handleDismissSuggestion('kamigame')}
+ />
+
+
+ {/if}
+ {/if}
+ {/if}
+
+
+
diff --git a/src/routes/(app)/database/summons/import/+page.server.ts b/src/routes/(app)/database/summons/import/+page.server.ts
new file mode 100644
index 00000000..863e682b
--- /dev/null
+++ b/src/routes/(app)/database/summons/import/+page.server.ts
@@ -0,0 +1,15 @@
+import type { PageServerLoad } from './$types'
+import { redirect } from '@sveltejs/kit'
+
+export const load: PageServerLoad = async ({ parent }) => {
+ const parentData = await parent()
+
+ // Require editor role (>= 7) to access batch import
+ if (!parentData.role || parentData.role < 7) {
+ throw redirect(302, '/database/summons')
+ }
+
+ return {
+ role: parentData.role
+ }
+}
diff --git a/src/routes/(app)/database/summons/import/+page.svelte b/src/routes/(app)/database/summons/import/+page.svelte
new file mode 100644
index 00000000..23a5cd42
--- /dev/null
+++ b/src/routes/(app)/database/summons/import/+page.svelte
@@ -0,0 +1,610 @@
+
+
+ {#snippet leftAccessory()}
+
+ {/snippet}
+ {#snippet rightAccessory()}
+ {#if selectedEntity?.status === 'success'}
+
+ {/if}
+ {/snippet}
+
+
+ {#if saveError}
+
{saveError}
+ {/if}
+
+
+ {#if entities.size === 0}
+
+ {:else}
+
+
+
+
+
+
+ {#if selectedEntity}
+ {#if selectedEntity.status === 'error'}
+
+
Failed to load: {selectedWikiPage}
+
{selectedEntity.error}
+
+ {:else if selectedEntity.status === 'loading'}
+
+ {:else if selectedFormData}
+ {@const suggestions = selectedEntity.suggestions}
+ {@const dismissed = selectedDismissed}
+
+
+ handleAcceptSuggestion('name', suggestions?.nameEn)}
+ onDismissSuggestion={() => handleDismissSuggestion('name')}
+ />
+ handleAcceptSuggestion('nameJp', suggestions?.nameJp)}
+ onDismissSuggestion={() => handleDismissSuggestion('nameJp')}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ handleAcceptSuggestion('releaseDate', suggestions?.releaseDate)}
+ onDismissSuggestion={() => handleDismissSuggestion('releaseDate')}
+ />
+ {#if selectedFormData.flb}
+ handleAcceptSuggestion('flbDate', suggestions?.flbDate)}
+ onDismissSuggestion={() => handleDismissSuggestion('flbDate')}
+ />
+ {/if}
+ {#if selectedFormData.ulb}
+ handleAcceptSuggestion('ulbDate', suggestions?.ulbDate)}
+ onDismissSuggestion={() => handleDismissSuggestion('ulbDate')}
+ />
+ {/if}
+ {#if selectedFormData.transcendence}
+
+ {/if}
+
+
+
+
+
+ handleAcceptSuggestion('gamewith', suggestions?.gamewith)}
+ onDismissSuggestion={() => handleDismissSuggestion('gamewith')}
+ />
+ handleAcceptSuggestion('kamigame', suggestions?.kamigame)}
+ onDismissSuggestion={() => handleDismissSuggestion('kamigame')}
+ />
+
+
+ {/if}
+ {/if}
+ {/if}
+
+
+
diff --git a/src/routes/(app)/database/weapons/import/+page.server.ts b/src/routes/(app)/database/weapons/import/+page.server.ts
new file mode 100644
index 00000000..6d6a1746
--- /dev/null
+++ b/src/routes/(app)/database/weapons/import/+page.server.ts
@@ -0,0 +1,15 @@
+import type { PageServerLoad } from './$types'
+import { redirect } from '@sveltejs/kit'
+
+export const load: PageServerLoad = async ({ parent }) => {
+ const parentData = await parent()
+
+ // Require editor role (>= 7) to access batch import
+ if (!parentData.role || parentData.role < 7) {
+ throw redirect(302, '/database/weapons')
+ }
+
+ return {
+ role: parentData.role
+ }
+}
diff --git a/src/routes/(app)/database/weapons/import/+page.svelte b/src/routes/(app)/database/weapons/import/+page.svelte
new file mode 100644
index 00000000..dac2aee1
--- /dev/null
+++ b/src/routes/(app)/database/weapons/import/+page.svelte
@@ -0,0 +1,613 @@
+
+
+ {#snippet leftAccessory()}
+
+ {/snippet}
+ {#snippet rightAccessory()}
+ {#if selectedEntity?.status === 'success'}
+
+ {/if}
+ {/snippet}
+
+
+ {#if saveError}
+
{saveError}
+ {/if}
+
+
+ {#if entities.size === 0}
+
+ {:else}
+
+
+
+
+
+
+ {#if selectedEntity}
+ {#if selectedEntity.status === 'error'}
+
+
Failed to load: {selectedWikiPage}
+
{selectedEntity.error}
+
+ {:else if selectedEntity.status === 'loading'}
+
+ {:else if selectedFormData}
+ {@const suggestions = selectedEntity.suggestions}
+ {@const dismissed = selectedDismissed}
+
+
+ handleAcceptSuggestion('name', suggestions?.nameEn)}
+ onDismissSuggestion={() => handleDismissSuggestion('name')}
+ />
+ handleAcceptSuggestion('nameJp', suggestions?.nameJp)}
+ onDismissSuggestion={() => handleDismissSuggestion('nameJp')}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ handleAcceptSuggestion('releaseDate', suggestions?.releaseDate)}
+ onDismissSuggestion={() => handleDismissSuggestion('releaseDate')}
+ />
+ {#if selectedFormData.flb}
+ handleAcceptSuggestion('flbDate', suggestions?.flbDate)}
+ onDismissSuggestion={() => handleDismissSuggestion('flbDate')}
+ />
+ {/if}
+ {#if selectedFormData.ulb}
+ handleAcceptSuggestion('ulbDate', suggestions?.ulbDate)}
+ onDismissSuggestion={() => handleDismissSuggestion('ulbDate')}
+ />
+ {/if}
+ {#if selectedFormData.transcendence}
+
+ {/if}
+
+
+
+
+
+ handleAcceptSuggestion('gamewith', suggestions?.gamewith)}
+ onDismissSuggestion={() => handleDismissSuggestion('gamewith')}
+ />
+ handleAcceptSuggestion('kamigame', suggestions?.kamigame)}
+ onDismissSuggestion={() => handleDismissSuggestion('kamigame')}
+ />
+
+
+ {/if}
+ {/if}
+ {/if}
+
+
+