71 lines
2.5 KiB
TypeScript
71 lines
2.5 KiB
TypeScript
import { Role } from '@prisma/client';
|
|
import { NextResponse } from 'next/server';
|
|
import { prisma } from '../../../../../../lib/prisma';
|
|
import { requireAuth } from '../../../../../../lib/jwt';
|
|
|
|
export async function DELETE(req: Request, { params }: { params: { id: string; imageId: string } }) {
|
|
try {
|
|
const auth = await requireAuth(req);
|
|
const listing = await prisma.listing.findUnique({
|
|
where: { id: params.id, removedAt: null },
|
|
select: {
|
|
id: true,
|
|
ownerId: true,
|
|
status: true,
|
|
images: { orderBy: { order: 'asc' }, select: { id: true, isCover: true, order: true } },
|
|
},
|
|
});
|
|
|
|
if (!listing) {
|
|
return NextResponse.json({ error: 'Listing not found' }, { status: 404 });
|
|
}
|
|
|
|
const isOwner = listing.ownerId === auth.userId;
|
|
const isAdmin = auth.role === Role.ADMIN;
|
|
if (!isOwner && !isAdmin) {
|
|
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
|
|
}
|
|
|
|
const targetImage = listing.images.find((img) => img.id === params.imageId);
|
|
if (!targetImage) {
|
|
return NextResponse.json({ error: 'Image not found' }, { status: 404 });
|
|
}
|
|
|
|
if (listing.images.length <= 1) {
|
|
return NextResponse.json({ error: 'At least one image is required' }, { status: 400 });
|
|
}
|
|
|
|
const remaining = listing.images.filter((img) => img.id !== params.imageId);
|
|
const newCoverId = remaining.find((img) => img.isCover)?.id ?? remaining[0]?.id ?? null;
|
|
|
|
await prisma.$transaction([
|
|
prisma.listingImage.delete({ where: { id: params.imageId } }),
|
|
...remaining.map((img, idx) =>
|
|
prisma.listingImage.update({
|
|
where: { id: img.id },
|
|
data: { order: idx + 1, isCover: newCoverId ? img.id === newCoverId : img.isCover },
|
|
}),
|
|
),
|
|
]);
|
|
|
|
const updated = await prisma.listing.findUnique({
|
|
where: { id: listing.id },
|
|
select: {
|
|
images: {
|
|
orderBy: { order: 'asc' },
|
|
select: { id: true, url: true, altText: true, order: true, isCover: true, size: true, mimeType: true },
|
|
},
|
|
},
|
|
});
|
|
|
|
return NextResponse.json({ ok: true, images: updated?.images ?? [] });
|
|
} catch (error: any) {
|
|
console.error('Delete listing image error', error);
|
|
if (String(error).includes('Unauthorized')) {
|
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
|
}
|
|
return NextResponse.json({ error: 'Failed to delete image' }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
export const dynamic = 'force-dynamic';
|