import { createSupabaseServiceRoleClient } from "@/lib/supabase/service-role"; export type PublicGalleryPhotoRow = { id: string; unsplash_id: string; slug: string | null; description: string | null; alt_description: string | null; width: number | null; height: number | null; color: string | null; color_family: string | null; likes: number | null; urls: Record; user_info: Record; photo_created_at: string | null; picked_at: string | null; oss_url: string | null; }; export const publicGalleryPhotoSelect = "id,unsplash_id,slug,description,alt_description,width,height,color,color_family,likes,urls,user_info,photo_created_at,picked_at,oss_url"; export function getPublicPhotoUrl(photo: PublicGalleryPhotoRow) { const candidates = [ photo.oss_url, photo.urls?.regular, photo.urls?.small, photo.urls?.raw, photo.urls?.thumb, ]; for (const candidate of candidates) { if (typeof candidate === "string" && candidate.length > 0) { return candidate; } } return null; } export async function getFavoritePhotoIds({ photoIds, userId, }: { photoIds: string[]; userId: string | null; }) { if (!userId || photoIds.length === 0) { return new Set(); } const supabase = createSupabaseServiceRoleClient(); const { data, error } = await supabase .from("wg_user_favorites") .select("photo_id") .eq("user_id", userId) .in("photo_id", photoIds); if (error) { throw error; } return new Set((data ?? []).map((favorite) => favorite.photo_id)); } export function mapPublicGalleryPhoto({ favoritePhotoIds, photo, }: { favoritePhotoIds?: Set; photo: PublicGalleryPhotoRow; }) { return { id: photo.id, unsplashId: photo.unsplash_id, slug: photo.slug, description: photo.description, altDescription: photo.alt_description, width: photo.width, height: photo.height, color: photo.color, colorFamily: photo.color_family, likes: photo.likes, url: getPublicPhotoUrl(photo), sourceUrl: getPublicPhotoUrl({ ...photo, oss_url: null }), user: photo.user_info, photoCreatedAt: photo.photo_created_at, pickedAt: photo.picked_at, isFavorited: favoritePhotoIds?.has(photo.id) ?? false, }; } export async function listPickedGalleryPhotos({ colorFamily, page, pageSize, userId, }: { colorFamily: string | null; page: number; pageSize: number; userId: string | null; }) { const supabase = createSupabaseServiceRoleClient(); let query = supabase .from("wg_gallery_photos") .select(publicGalleryPhotoSelect, { count: "exact" }) .eq("is_picked", true); 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) * pageSize, page * pageSize - 1); if (error) { throw error; } const photos = (data ?? []) as PublicGalleryPhotoRow[]; const favoritePhotoIds = await getFavoritePhotoIds({ userId, photoIds: photos.map((photo) => photo.id), }); return { data: photos.map((photo) => mapPublicGalleryPhoto({ photo, favoritePhotoIds }), ), total: count ?? 0, }; } export async function getPickedGalleryPhotoById({ id, userId, }: { id: string; userId: string | null; }) { const supabase = createSupabaseServiceRoleClient(); const { data, error } = await supabase .from("wg_gallery_photos") .select(publicGalleryPhotoSelect) .eq("id", id) .eq("is_picked", true) .maybeSingle(); if (error) { throw error; } if (!data) { return null; } const favoritePhotoIds = await getFavoritePhotoIds({ userId, photoIds: [data.id], }); return mapPublicGalleryPhoto({ photo: data, favoritePhotoIds }); }