174 lines
4.7 KiB
TypeScript
174 lines
4.7 KiB
TypeScript
// services/propertyMediaService.ts
|
|
// Handle property photos, videos, and document uploads
|
|
|
|
import { and, eq } from "drizzle-orm";
|
|
import { db } from "../db/db.ts";
|
|
import { property_media } from "../db/schema.ts";
|
|
import {
|
|
addE2EPropertyMedia,
|
|
deleteE2EAllMediaForProperty,
|
|
deleteE2EPropertyMedia,
|
|
getE2EMediaByProperty,
|
|
getE2EMediaByPropertyAndType,
|
|
getE2EMediaCountByProperty,
|
|
getE2EPrimaryPhoto,
|
|
isE2EEnabled,
|
|
updateE2EMultipleMediaOrders,
|
|
updateE2EPropertyMediaOrder,
|
|
} from "./e2eFixtures.ts";
|
|
|
|
export interface PropertyMedia {
|
|
id: string;
|
|
property_id: string;
|
|
media_type: string | null; // 'photo', 'video', 'document'
|
|
file_url: string | null;
|
|
file_name: string | null;
|
|
display_order: number | null;
|
|
created_on: number;
|
|
}
|
|
|
|
// Create new media entry
|
|
export async function createPropertyMedia(
|
|
property_id: string,
|
|
media_type: string,
|
|
file_url: string,
|
|
file_name: string,
|
|
display_order: number = 0,
|
|
) {
|
|
if (isE2EEnabled()) {
|
|
return [addE2EPropertyMedia(
|
|
property_id,
|
|
media_type,
|
|
file_url,
|
|
file_name,
|
|
display_order,
|
|
)];
|
|
}
|
|
const now = Date.now();
|
|
return await db.insert(property_media)
|
|
.values({
|
|
id: crypto.randomUUID(),
|
|
property_id,
|
|
media_type,
|
|
file_url,
|
|
file_name,
|
|
display_order,
|
|
created_on: now,
|
|
})
|
|
.returning();
|
|
}
|
|
|
|
// Get all media for a property
|
|
export async function getMediaByProperty(property_id: string) {
|
|
if (isE2EEnabled()) {
|
|
return getE2EMediaByProperty(property_id);
|
|
}
|
|
return await db.select()
|
|
.from(property_media)
|
|
.where(eq(property_media.property_id, property_id))
|
|
.orderBy(property_media.display_order);
|
|
}
|
|
|
|
// Get media by type for a property
|
|
export async function getMediaByPropertyAndType(
|
|
property_id: string,
|
|
media_type: string,
|
|
) {
|
|
if (isE2EEnabled()) {
|
|
return getE2EMediaByPropertyAndType(property_id, media_type);
|
|
}
|
|
return await db.select()
|
|
.from(property_media)
|
|
.where(and(
|
|
eq(property_media.property_id, property_id),
|
|
eq(property_media.media_type, media_type),
|
|
))
|
|
.orderBy(property_media.display_order);
|
|
}
|
|
|
|
// Get photos only for a property
|
|
export async function getPhotosByProperty(property_id: string) {
|
|
return await getMediaByPropertyAndType(property_id, "photo");
|
|
}
|
|
|
|
// Get documents only for a property
|
|
export async function getDocumentsByProperty(property_id: string) {
|
|
return await getMediaByPropertyAndType(property_id, "document");
|
|
}
|
|
|
|
// Update media display order
|
|
export async function updateMediaOrder(id: string, display_order: number) {
|
|
if (isE2EEnabled()) {
|
|
return updateE2EPropertyMediaOrder(id, display_order);
|
|
}
|
|
return await db.update(property_media)
|
|
.set({ display_order })
|
|
.where(eq(property_media.id, id))
|
|
.returning();
|
|
}
|
|
|
|
// Update multiple media orders (for drag-drop reordering)
|
|
export async function updateMultipleMediaOrders(
|
|
updates: { id: string; display_order: number }[],
|
|
) {
|
|
if (isE2EEnabled()) {
|
|
return updateE2EMultipleMediaOrders(updates);
|
|
}
|
|
const promises = updates.map((update) =>
|
|
db.update(property_media)
|
|
.set({ display_order: update.display_order })
|
|
.where(eq(property_media.id, update.id))
|
|
.returning()
|
|
);
|
|
|
|
return await Promise.all(promises);
|
|
}
|
|
|
|
// Delete media
|
|
export async function deletePropertyMedia(id: string) {
|
|
if (isE2EEnabled()) {
|
|
return deleteE2EPropertyMedia(id);
|
|
}
|
|
return await db.delete(property_media)
|
|
.where(eq(property_media.id, id))
|
|
.returning();
|
|
}
|
|
|
|
// Delete all media for a property
|
|
export async function deleteAllMediaForProperty(property_id: string) {
|
|
if (isE2EEnabled()) {
|
|
return deleteE2EAllMediaForProperty(property_id);
|
|
}
|
|
return await db.delete(property_media)
|
|
.where(eq(property_media.property_id, property_id))
|
|
.returning();
|
|
}
|
|
|
|
// Get media count by property
|
|
export async function getMediaCountByProperty(property_id: string) {
|
|
if (isE2EEnabled()) {
|
|
return getE2EMediaCountByProperty(property_id);
|
|
}
|
|
const media = await getMediaByProperty(property_id);
|
|
return {
|
|
total: media.length,
|
|
photos: media.filter((m) => m.media_type === "photo").length,
|
|
videos: media.filter((m) => m.media_type === "video").length,
|
|
documents: media.filter((m) => m.media_type === "document").length,
|
|
};
|
|
}
|
|
|
|
// Get primary photo for a property (first photo by display order)
|
|
export async function getPrimaryPhoto(property_id: string) {
|
|
if (isE2EEnabled()) {
|
|
return getE2EPrimaryPhoto(property_id);
|
|
}
|
|
const photos = await getPhotosByProperty(property_id);
|
|
return photos[0] || null;
|
|
}
|
|
|
|
// Get property media by property (alias for compatibility)
|
|
export async function getPropertyMediaByProperty(property_id: string) {
|
|
return await getMediaByProperty(property_id);
|
|
}
|