diff --git a/src/lib/features/database/detail/DetailScaffold.svelte b/src/lib/features/database/detail/DetailScaffold.svelte
index 2190d99c..fc7be0fa 100644
--- a/src/lib/features/database/detail/DetailScaffold.svelte
+++ b/src/lib/features/database/detail/DetailScaffold.svelte
@@ -1,9 +1,11 @@
@@ -74,6 +113,48 @@
Images
Raw Data
+
+ {#if showDownloadDropdown}
+
+
+
+ {#snippet child({ props })}
+
+ {/snippet}
+
+
+
+
+
+
+
+ {/if}
{/if}
@@ -109,6 +190,15 @@
.tab-navigation {
padding: spacing.$unit-2x;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: spacing.$unit;
+ }
+
+ .download-dropdown {
+ margin-left: auto;
}
.edit-controls {
@@ -139,4 +229,36 @@
opacity: 1;
}
}
+
+ // Import menu styles
+ :global(.dropdown-menu) {
+ background: var(--app-bg, white);
+ border: 1px solid var(--border-color, #ddd);
+ border-radius: layout.$card-corner;
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+ padding: spacing.$unit-half;
+ min-width: calc(spacing.$unit * 22.5);
+ z-index: 200;
+ }
+
+ :global(.dropdown-menu-item) {
+ padding: spacing.$unit spacing.$unit-2x;
+ border-radius: layout.$item-corner-small;
+ cursor: pointer;
+ font-size: typography.$font-regular;
+ color: var(--text-primary);
+ display: flex;
+ align-items: center;
+ gap: spacing.$unit;
+
+ &:hover {
+ background: var(--button-contained-bg-hover, #f5f5f5);
+ }
+ }
+
+ :global(.dropdown-menu-separator) {
+ height: 1px;
+ background: var(--menu-separator, #e5e5e5);
+ margin: spacing.$unit-half 0;
+ }
diff --git a/src/lib/features/database/detail/tabs/EntityImagesTab.svelte b/src/lib/features/database/detail/tabs/EntityImagesTab.svelte
index c568e4a1..967f1494 100644
--- a/src/lib/features/database/detail/tabs/EntityImagesTab.svelte
+++ b/src/lib/features/database/detail/tabs/EntityImagesTab.svelte
@@ -1,31 +1,205 @@
-
- {#each images as image}
-
-
-
-
-
{image.label}
-
- {/each}
-
+ {#each sortedPoses as pose}
+ {@const poseImages = imagesByPose.get(pose) ?? []}
+ {@const poseLabel = getPoseLabel(pose, poseImages)}
+ {@const showHeader = poseLabel && sortedPoses.length > 1}
+
+ {#if showHeader}
+
+ {/if}
+
+
+ {#each poseImages as image}
+ {@const imageKey = getImageKey(image)}
+ {@const isDownloading = downloadingImages.has(imageKey)}
+
+ {#if canEdit && onDownloadImage}
+
+ {#snippet trigger()}
+
+ {/snippet}
+
+ {#snippet menu()}
+
+
+ {#if onDownloadAllPose}
+
+
+ {/if}
+
+
+ {/snippet}
+
+ {:else}
+
+
+
+
+
{image.variant}
+
+ {/if}
+ {/each}
+
+ {/each}
diff --git a/src/lib/utils/images.ts b/src/lib/utils/images.ts
index 1baaa1f5..5cedadcd 100644
--- a/src/lib/utils/images.ts
+++ b/src/lib/utils/images.ts
@@ -119,13 +119,33 @@ export function getCharacterDetailImage(
/**
* Get weapon image URL
+ * @param transformation - Optional transformation suffix ('02' for transcendence)
*/
export function getWeaponImage(
id: string | number | null | undefined,
variant: ImageVariant = 'main',
- element?: number
+ element?: number,
+ transformation?: string
): string {
- return getImageUrl('weapon', id, variant, { element })
+ if (!id) {
+ return getPlaceholderImage('weapon', variant)
+ }
+
+ const directory = getImageDirectory('weapon', variant)
+ const extension = getFileExtension('weapon', variant)
+ const basePath = `${getBasePath()}/${directory}`
+
+ // Handle element-specific weapon grids
+ if (variant === 'grid' && element && element > 0) {
+ return `${basePath}/${id}_${element}${extension}`
+ }
+
+ // Handle transformation suffix (transcendence)
+ if (transformation) {
+ return `${basePath}/${id}_${transformation}${extension}`
+ }
+
+ return `${basePath}/${id}${extension}`
}
/**
@@ -139,12 +159,27 @@ export function getWeaponBaseImage(
/**
* Get summon image URL
+ * @param transformation - Optional transformation suffix ('02' for ULB, '03' for transcendence)
*/
export function getSummonImage(
id: string | number | null | undefined,
- variant: ImageVariant = 'main'
+ variant: ImageVariant = 'main',
+ transformation?: string
): string {
- return getImageUrl('summon', id, variant)
+ if (!id) {
+ return getPlaceholderImage('summon', variant)
+ }
+
+ const directory = getImageDirectory('summon', variant)
+ const extension = getFileExtension('summon', variant)
+ const basePath = `${getBasePath()}/${directory}`
+
+ // Handle transformation suffix (ULB, transcendence)
+ if (transformation) {
+ return `${basePath}/${id}_${transformation}${extension}`
+ }
+
+ return `${basePath}/${id}${extension}`
}
/**