Files
twotalesanimation 6b15bae62a
Deploy / deploy (push) Successful in 2m50s
Bulk Thumbnails upload
2026-08-06 12:59:28 +02:00

74 lines
2.2 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/auth";
import { db } from "@/lib/db";
const IMAGE_EXTS = new Set(["jpg", "jpeg", "png", "webp", "tiff", "tif", "avif"]);
export interface ThumbnailPreviewItem {
fileName: string;
stemName: string;
shotCode: string | null;
shotId: string | null;
status: "match" | "no-match";
currentThumbnailUrl: string | null;
}
function stem(fileName: string): string {
const dot = fileName.lastIndexOf(".");
return (dot > 0 ? fileName.slice(0, dot) : fileName).toLowerCase();
}
/**
* POST /api/batch-upload/thumbnails
* Body: { projectId: string; fileNames: string[] }
*/
export async function POST(req: NextRequest) {
const session = await auth();
if (!session?.user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
let body: { projectId?: string; fileNames?: string[] };
try {
body = await req.json();
} catch {
return NextResponse.json({ error: "Invalid JSON" }, { status: 400 });
}
const { projectId, fileNames } = body;
if (!projectId || !Array.isArray(fileNames)) {
return NextResponse.json({ error: "projectId and fileNames are required" }, { status: 400 });
}
// Only image files
const imageFiles = fileNames.filter((f) => {
const ext = f.split(".").pop()?.toLowerCase() ?? "";
return IMAGE_EXTS.has(ext);
});
const shots = await db.shot.findMany({
where: { projectId },
select: { id: true, shotCode: true, thumbnailUrl: true },
});
// Build a lowercase map for case-insensitive matching
const shotMap = new Map(shots.map((s) => [s.shotCode.toLowerCase(), s]));
const items: ThumbnailPreviewItem[] = fileNames.map((fileName) => {
const ext = fileName.split(".").pop()?.toLowerCase() ?? "";
if (!IMAGE_EXTS.has(ext)) {
return { fileName, stemName: stem(fileName), shotCode: null, shotId: null, status: "no-match" as const, currentThumbnailUrl: null };
}
const s = stem(fileName);
const shot = shotMap.get(s) ?? null;
return {
fileName,
stemName: s,
shotCode: shot?.shotCode ?? null,
shotId: shot?.id ?? null,
status: shot ? "match" : "no-match",
currentThumbnailUrl: shot?.thumbnailUrl ?? null,
};
});
return NextResponse.json({ items });
}