feat: add image project dashboard and canvas editor
Verify and deploy production / verify-and-deploy (push) Successful in 2m34s

This commit is contained in:
2026-10-05 15:20:43 +08:00
parent e961e3091b
commit 276a8ae473
12 changed files with 675 additions and 203 deletions
@@ -0,0 +1,14 @@
import { NextResponse } from "next/server";
import { readImageProjectFile } from "../../../../../../lib/image-projects";
import { errorResponse } from "../../../../../../lib/http";
export const runtime = "nodejs";
type Context = { params: Promise<{ id: string; file: string }> };
export async function GET(_: Request, context: Context) {
try {
const { id, file } = await context.params;
const image = await readImageProjectFile(id, file);
return new NextResponse(image.data, { headers: { "Content-Type": image.mimeType, "Cache-Control": "private, max-age=3600" } });
} catch (error) { return errorResponse(error); }
}
@@ -0,0 +1,14 @@
import { NextResponse } from "next/server";
import { addImagesToProject } from "../../../../../lib/image-projects";
import { errorResponse } from "../../../../../lib/http";
export const runtime = "nodejs";
type Context = { params: Promise<{ id: string }> };
export async function POST(request: Request, context: Context) {
try {
const form = await request.formData();
const files = form.getAll("images").filter((item): item is File => item instanceof File);
return NextResponse.json({ project: await addImagesToProject((await context.params).id, files) });
} catch (error) { return errorResponse(error); }
}
+16
View File
@@ -0,0 +1,16 @@
import { NextResponse } from "next/server";
import { getImageProject, updateImageProject } from "../../../../lib/image-projects";
import { errorResponse } from "../../../../lib/http";
export const runtime = "nodejs";
type Context = { params: Promise<{ id: string }> };
export async function GET(_: Request, context: Context) {
try { return NextResponse.json({ project: await getImageProject((await context.params).id) }); }
catch (error) { return errorResponse(error); }
}
export async function PUT(request: Request, context: Context) {
try { return NextResponse.json({ project: await updateImageProject((await context.params).id, await request.json()) }); }
catch (error) { return errorResponse(error); }
}
+19
View File
@@ -0,0 +1,19 @@
import { NextResponse } from "next/server";
import { createImageProject, listImageProjects } from "../../../lib/image-projects";
import { errorResponse } from "../../../lib/http";
export const runtime = "nodejs";
export async function GET() {
try { return NextResponse.json({ projects: await listImageProjects() }); }
catch (error) { return errorResponse(error); }
}
export async function POST(request: Request) {
try {
const form = await request.formData();
const files = form.getAll("images").filter((item): item is File => item instanceof File);
const project = await createImageProject(files, form.get("name"));
return NextResponse.json({ project }, { status: 201 });
} catch (error) { return errorResponse(error); }
}