Admin inventory
+Manage images
+Loading images...
+{{ error.message }}
+diff --git a/apps/api/src/modules/inventory/repositories/inventory-image-repository.js b/apps/api/src/modules/inventory/repositories/inventory-image-repository.js
index 53b3e2b..4e4ddf7 100644
--- a/apps/api/src/modules/inventory/repositories/inventory-image-repository.js
+++ b/apps/api/src/modules/inventory/repositories/inventory-image-repository.js
@@ -43,6 +43,20 @@ export function createInventoryImageRepository(db) {
return image?.image ?? null;
},
+ async listByInventoryItemForSeller(inventoryItemId, sellerId) {
+ return db
+ .select({ image: inventoryImages })
+ .from(inventoryImages)
+ .innerJoin(inventoryItems, eq(inventoryItems.id, inventoryImages.inventoryItemId))
+ .innerJoin(products, eq(products.id, inventoryItems.productId))
+ .where(and(
+ eq(inventoryImages.inventoryItemId, inventoryItemId),
+ eq(products.sellerId, sellerId),
+ ))
+ .orderBy(inventoryImages.sortOrder)
+ .then((rows) => rows.map(({ image }) => image));
+ },
+
async updateOrderForSeller(imageId, sortOrder, sellerId) {
const owned = await this.findByIdForSeller(imageId, sellerId);
if (!owned) return null;
diff --git a/apps/api/src/modules/inventory/routes/admin-image-routes.js b/apps/api/src/modules/inventory/routes/admin-image-routes.js
index db7ca60..4721adf 100644
--- a/apps/api/src/modules/inventory/routes/admin-image-routes.js
+++ b/apps/api/src/modules/inventory/routes/admin-image-routes.js
@@ -78,6 +78,13 @@ export async function registerAdminImageRoutes(app, options) {
return reply.code(201).send({ data: toAdminInventoryImageDto(image) });
});
+ app.get('/inventory/:id/images', async (request) => ({
+ data: (await inventoryImageService.list({
+ inventoryItemId: request.params.id,
+ sellerId: (await authenticateAdmin(request)).sellerId,
+ })).map(toAdminInventoryImageDto),
+ }));
+
async function authorizeAdminMutation(request) {
const admin = await authenticateAdmin(request);
if (!admin?.sellerId) {
diff --git a/apps/api/src/modules/inventory/services/inventory-image-service.js b/apps/api/src/modules/inventory/services/inventory-image-service.js
index efb2830..7275db3 100644
--- a/apps/api/src/modules/inventory/services/inventory-image-service.js
+++ b/apps/api/src/modules/inventory/services/inventory-image-service.js
@@ -23,6 +23,10 @@ export function createInventoryImageService({ inventoryImageRepository, imageDer
return image;
},
+ async list({ inventoryItemId, sellerId }) {
+ return inventoryImageRepository.listByInventoryItemForSeller(inventoryItemId, sellerId);
+ },
+
async upload(input) {
const { data, ...metadata } = input;
validateInventoryImageMetadata(metadata);
diff --git a/apps/web/src/components/organisms/AdminImageManager.stories.js b/apps/web/src/components/organisms/AdminImageManager.stories.js
index fe6d074..2e40ca1 100644
--- a/apps/web/src/components/organisms/AdminImageManager.stories.js
+++ b/apps/web/src/components/organisms/AdminImageManager.stories.js
@@ -12,6 +12,7 @@ export default { title: 'Organisms/AdminImageManager', component: AdminImageMana
export const Completed = { args: { images, processingStatus: 'COMPLETED' } };
export const Processing = { args: { images, processingStatus: 'PROCESSING' } };
export const Failed = { args: { images, processingStatus: 'FAILED', errorMessage: 'Derivative generation failed.' } };
+export const Saving = { args: { images, processingStatus: 'COMPLETED', isSaving: true } };
export const EditAltTextWithKeyboard = {
args: { images, processingStatus: 'COMPLETED' },
diff --git a/apps/web/src/components/organisms/AdminImageManager.vue b/apps/web/src/components/organisms/AdminImageManager.vue
index 7c11f4e..77ec677 100644
--- a/apps/web/src/components/organisms/AdminImageManager.vue
+++ b/apps/web/src/components/organisms/AdminImageManager.vue
@@ -9,6 +9,7 @@ const props = defineProps({
images: { type: Array, required: true },
processingStatus: { type: String, default: 'COMPLETED' },
errorMessage: { type: String, default: '' },
+ isSaving: { type: Boolean, default: false },
});
const emit = defineEmits(['reorder', 'primary', 'alt-text', 'retry', 'delete']);
const altText = ref(props.images.find((image) => image.isPrimary)?.altText ?? '');
@@ -39,6 +40,7 @@ function saveAltText() {
Saving image changes...
Admin inventory
+Loading images...
+{{ error.message }}
+