first commit
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
import { createSupabaseServiceRoleClient } from "@/lib/supabase/service-role";
|
||||
|
||||
type FavoriteRow = {
|
||||
photo_id: string;
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
type FavoritePhotoRow = {
|
||||
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;
|
||||
urls: Record<string, unknown>;
|
||||
user_info: Record<string, unknown>;
|
||||
picked_at: string | null;
|
||||
oss_url: string | null;
|
||||
};
|
||||
|
||||
const favoritePhotoSelect =
|
||||
"id,unsplash_id,slug,description,alt_description,width,height,color,color_family,urls,user_info,picked_at,oss_url";
|
||||
|
||||
function getPhotoUrl(photo: FavoritePhotoRow) {
|
||||
const urls = photo.urls as Record<string, string> | undefined;
|
||||
return (
|
||||
photo.oss_url ??
|
||||
urls?.regular ??
|
||||
urls?.small ??
|
||||
urls?.raw ??
|
||||
urls?.thumb ??
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
function mapPhoto(photo: FavoritePhotoRow, favoritedAt: string | null) {
|
||||
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,
|
||||
url: getPhotoUrl(photo),
|
||||
sourceUrl: getPhotoUrl({ ...photo, oss_url: null }),
|
||||
user: photo.user_info,
|
||||
pickedAt: photo.picked_at,
|
||||
favoritedAt,
|
||||
};
|
||||
}
|
||||
|
||||
export async function listUserFavorites({
|
||||
page,
|
||||
pageSize,
|
||||
userId,
|
||||
}: {
|
||||
page: number;
|
||||
pageSize: number;
|
||||
userId: string;
|
||||
}) {
|
||||
const supabase = createSupabaseServiceRoleClient();
|
||||
const { data, error, count } = await supabase
|
||||
.from("wg_user_favorites")
|
||||
.select("photo_id,created_at", { count: "exact" })
|
||||
.eq("user_id", userId)
|
||||
.order("created_at", { ascending: false })
|
||||
.range((page - 1) * pageSize, page * pageSize - 1);
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
const favorites = (data ?? []) as FavoriteRow[];
|
||||
const photoIds = favorites.map((favorite) => favorite.photo_id);
|
||||
|
||||
if (photoIds.length === 0) {
|
||||
return {
|
||||
data: [],
|
||||
total: count ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
const { data: photos, error: photosError } = await supabase
|
||||
.from("wg_gallery_photos")
|
||||
.select(favoritePhotoSelect)
|
||||
.eq("is_picked", true)
|
||||
.in("id", photoIds);
|
||||
|
||||
if (photosError) {
|
||||
throw photosError;
|
||||
}
|
||||
|
||||
const favoritedAtByPhotoId = new Map(
|
||||
favorites.map((favorite) => [favorite.photo_id, favorite.created_at]),
|
||||
);
|
||||
const photoById = new Map(
|
||||
((photos ?? []) as FavoritePhotoRow[]).map((photo) => [
|
||||
photo.id,
|
||||
photo,
|
||||
]),
|
||||
);
|
||||
|
||||
return {
|
||||
data: photoIds
|
||||
.map((photoId) => photoById.get(photoId))
|
||||
.filter((photo): photo is FavoritePhotoRow => Boolean(photo))
|
||||
.map((photo) =>
|
||||
mapPhoto(photo, favoritedAtByPhotoId.get(photo.id) ?? null),
|
||||
),
|
||||
total: count ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
export async function addUserFavorite({
|
||||
photoId,
|
||||
userId,
|
||||
}: {
|
||||
photoId: string;
|
||||
userId: string;
|
||||
}) {
|
||||
const supabase = createSupabaseServiceRoleClient();
|
||||
const { data: photo, error: photoError } = await supabase
|
||||
.from("wg_gallery_photos")
|
||||
.select(favoritePhotoSelect)
|
||||
.eq("id", photoId)
|
||||
.eq("is_picked", true)
|
||||
.maybeSingle<FavoritePhotoRow>();
|
||||
|
||||
if (photoError) {
|
||||
throw photoError;
|
||||
}
|
||||
|
||||
if (!photo) {
|
||||
throw new Error("Picked photo was not found.");
|
||||
}
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from("wg_user_favorites")
|
||||
.upsert(
|
||||
{
|
||||
user_id: userId,
|
||||
photo_id: photoId,
|
||||
},
|
||||
{ onConflict: "user_id,photo_id" },
|
||||
)
|
||||
.select("created_at")
|
||||
.single<{ created_at: string }>();
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return mapPhoto(photo, data.created_at);
|
||||
}
|
||||
|
||||
export async function removeUserFavorite({
|
||||
photoId,
|
||||
userId,
|
||||
}: {
|
||||
photoId: string;
|
||||
userId: string;
|
||||
}) {
|
||||
const supabase = createSupabaseServiceRoleClient();
|
||||
const { error } = await supabase
|
||||
.from("wg_user_favorites")
|
||||
.delete()
|
||||
.eq("user_id", userId)
|
||||
.eq("photo_id", photoId);
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user