59 lines
1.5 KiB
TypeScript
59 lines
1.5 KiB
TypeScript
import { Prisma, ListingStatus } from '@prisma/client';
|
|
import { prisma } from './prisma';
|
|
import { DEFAULT_LOCALE, SAMPLE_LISTING_SLUG } from './sampleListing';
|
|
|
|
export type ListingWithTranslations = Prisma.ListingTranslationGetPayload<{
|
|
include: {
|
|
listing: {
|
|
include: {
|
|
images: true;
|
|
owner: true;
|
|
};
|
|
};
|
|
};
|
|
}>;
|
|
|
|
type FetchOptions = {
|
|
slug: string;
|
|
locale?: string;
|
|
};
|
|
|
|
/**
|
|
* Fetch a listing translation by slug and locale.
|
|
* Falls back to any locale if the requested locale is missing.
|
|
*/
|
|
export async function getListingBySlug({ slug, locale }: FetchOptions): Promise<ListingWithTranslations | null> {
|
|
const targetLocale = locale ?? DEFAULT_LOCALE;
|
|
|
|
const translation = await prisma.listingTranslation.findFirst({
|
|
where: { slug, locale: targetLocale, listing: { status: ListingStatus.PUBLISHED, removedAt: null } },
|
|
include: {
|
|
listing: {
|
|
include: {
|
|
images: { orderBy: { order: 'asc' } },
|
|
owner: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
if (translation) {
|
|
return translation;
|
|
}
|
|
|
|
// Fallback: first translation for this slug
|
|
return prisma.listingTranslation.findFirst({
|
|
where: { slug, listing: { status: ListingStatus.PUBLISHED, removedAt: null } },
|
|
include: {
|
|
listing: {
|
|
include: {
|
|
images: { orderBy: { order: 'asc' } },
|
|
owner: true,
|
|
},
|
|
},
|
|
},
|
|
orderBy: { createdAt: 'asc' },
|
|
});
|
|
}
|
|
|
|
export { SAMPLE_LISTING_SLUG, DEFAULT_LOCALE };
|