138 lines
4.1 KiB
TypeScript
138 lines
4.1 KiB
TypeScript
import { auth } from "@/lib/auth";
|
|
import { createSupabaseServiceRoleClient } from "@/lib/supabase/service-role";
|
|
import { updateGalleryPhotoPickStatus } from "@/server/admin/gallery-pick";
|
|
import { NextResponse, type NextRequest } from "next/server";
|
|
import { z } from "zod";
|
|
|
|
export const runtime = "nodejs";
|
|
export const dynamic = "force-dynamic";
|
|
|
|
const galleryPhotoSelect =
|
|
"id,unsplash_id,slug,description,alt_description,width,height,color,color_family,likes,urls,user_info,photo_created_at,is_picked,picked_at,picked_by,oss_url,oss_object_key,oss_synced_at,oss_sync_error";
|
|
|
|
const patchSchema = z.object({
|
|
unsplashId: z.string().min(1),
|
|
isPicked: z.boolean(),
|
|
});
|
|
|
|
async function requireAdminSession() {
|
|
const session = await auth();
|
|
|
|
if (!session) {
|
|
return null;
|
|
}
|
|
|
|
return session;
|
|
}
|
|
|
|
export async function GET(request: NextRequest) {
|
|
try {
|
|
const session = await requireAdminSession();
|
|
|
|
if (!session) {
|
|
return NextResponse.json(
|
|
{ ok: false, error: "Unauthorized." },
|
|
{ status: 401 },
|
|
);
|
|
}
|
|
|
|
const { searchParams } = new URL(request.url);
|
|
const page = parseInt(searchParams.get("page") || "1", 10);
|
|
const perPage = parseInt(searchParams.get("per_page") || "24", 10);
|
|
const picked = searchParams.get("picked");
|
|
const colorFamily = searchParams.get("color_family");
|
|
|
|
if (page < 1 || perPage < 1 || perPage > 100) {
|
|
return NextResponse.json(
|
|
{ ok: false, error: "Invalid pagination parameters." },
|
|
{ status: 400 },
|
|
);
|
|
}
|
|
|
|
const supabase = createSupabaseServiceRoleClient();
|
|
|
|
let query = supabase
|
|
.from("wg_gallery_photos")
|
|
.select(galleryPhotoSelect, { count: "exact" });
|
|
|
|
if (picked === "true") {
|
|
query = query.eq("is_picked", true);
|
|
} else if (picked === "false") {
|
|
query = query.eq("is_picked", false);
|
|
}
|
|
|
|
if (colorFamily && colorFamily !== "all") {
|
|
query = query.eq("color_family", colorFamily);
|
|
}
|
|
|
|
const { data, error, count } = await query
|
|
.order("picked_at", { ascending: false, nullsFirst: false })
|
|
.order("photo_created_at", { ascending: false })
|
|
.range((page - 1) * perPage, page * perPage - 1);
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return NextResponse.json({
|
|
ok: true,
|
|
data: data ?? [],
|
|
pagination: {
|
|
page,
|
|
perPage,
|
|
total: count ?? 0,
|
|
hasMore: (count ?? 0) > page * perPage,
|
|
},
|
|
});
|
|
} catch (error) {
|
|
const message =
|
|
error instanceof Error ? error.message : "Unknown error.";
|
|
console.error("[api/admin/gallery-photos] PATCH failed", error);
|
|
return NextResponse.json(
|
|
{ ok: false, error: message },
|
|
{ status: 500 },
|
|
);
|
|
}
|
|
}
|
|
|
|
export async function PATCH(request: NextRequest) {
|
|
try {
|
|
const session = await requireAdminSession();
|
|
|
|
if (!session) {
|
|
return NextResponse.json(
|
|
{ ok: false, error: "Unauthorized." },
|
|
{ status: 401 },
|
|
);
|
|
}
|
|
|
|
const parsed = patchSchema.safeParse(await request.json());
|
|
|
|
if (!parsed.success) {
|
|
return NextResponse.json(
|
|
{ ok: false, error: "Invalid request body." },
|
|
{ status: 400 },
|
|
);
|
|
}
|
|
|
|
const data = await updateGalleryPhotoPickStatus({
|
|
isPicked: parsed.data.isPicked,
|
|
pickedBy:
|
|
session.user?.email ?? session.user?.id ?? "wallora-admin",
|
|
unsplashId: parsed.data.unsplashId,
|
|
});
|
|
|
|
return NextResponse.json({
|
|
ok: true,
|
|
data,
|
|
});
|
|
} catch (error) {
|
|
const message =
|
|
error instanceof Error ? error.message : "Unknown error.";
|
|
return NextResponse.json(
|
|
{ ok: false, error: message },
|
|
{ status: 500 },
|
|
);
|
|
}
|
|
}
|