import type { MenuItem } from '@/domain/menu/entities'; import { MEDIA_FOLDERS, SITE_ASSETS, mediaUrl, } from '@/infrastructure/assets/site-assets'; export type PosterVariant = 'standard' | 'optimized'; /** Strip .mp4 extension from a video filename */ export function videoBaseName(videoFilename: string): string { return videoFilename.replace(/\.mp4$/i, ''); } /** Full URL for a dish image filename (e.g. "butter-chicken.jpg") */ export function dishImageUrl(filename: string): string { return mediaUrl(MEDIA_FOLDERS.dishes, filename); } /** Poster URL derived from a video filename */ export function dishPosterFromVideo( videoFilename: string, variant: PosterVariant = 'standard' ): string { const base = videoBaseName(videoFilename); const suffix = variant === 'optimized' ? '-optimized-poster.jpg' : '-poster.jpg'; return mediaUrl(MEDIA_FOLDERS.dishes, `${base}${suffix}`); } /** Primary logo used in navbar, footer, login, etc. */ export function logoUrl(): string { return SITE_ASSETS.logo.primary; } /** Hero banner video sources for homepage */ export function heroBannerSources() { return { mobileWebm: SITE_ASSETS.banner.mobileWebm, mobileMp4: SITE_ASSETS.banner.mobileMp4, desktopMp4: SITE_ASSETS.banner.desktopMp4, }; } /** Chef expression images for PlayfulHeroScene */ export function chefExpressionUrl(expression: 'wink' | 'smile' | 'normal'): string { const map = { wink: SITE_ASSETS.animation.chefWink, smile: SITE_ASSETS.animation.chefSmile, normal: SITE_ASSETS.animation.chefNormal, }; return map[expression]; } /** Resolve primary poster path for a menu item */ export function getMenuPosterSrc( item: MenuItem, variant: PosterVariant = 'standard' ): string { // Prefer static dish photo when available (sweets use synced .jpg, not -poster.jpg) if (item.image) { return dishImageUrl(item.image); } if (item.video) { return dishPosterFromVideo(item.video, variant); } return variant === 'optimized' ? SITE_ASSETS.dishes.defaultPoster : SITE_ASSETS.fallbacks.dishPoster; } /** Poster candidates for progressive fallback in UI `` */ export function getMenuPosterCandidates(item: MenuItem): string[] { const base = item.video ? videoBaseName(item.video) : ''; const candidates: string[] = []; if (item.image) candidates.push(dishImageUrl(item.image)); if (item.video) { candidates.push( dishPosterFromVideo(item.video, 'standard'), dishPosterFromVideo(item.video, 'optimized'), mediaUrl(MEDIA_FOLDERS.dishes, `${base}.jpg`), ); } candidates.push( SITE_ASSETS.dishes.defaultPoster, SITE_ASSETS.fallbacks.dishPoster, SITE_ASSETS.fallbacks.logo, ); return [...new Set(candidates)]; } /** Full video URL for a menu item */ export function getMenuVideoSrc(item: MenuItem): string | null { if (!item.video) return null; return mediaUrl(MEDIA_FOLDERS.videos, item.video); } /** Optimized + fallback video sources for kiosk displays */ export function getMenuVideoSources(videoFilename: string) { if (!videoFilename) { return { webm: '', mp4: '', fallback: '' }; } const base = videoBaseName(videoFilename); return { webm: mediaUrl(MEDIA_FOLDERS.videos, `${base}-optimized.webm`), mp4: mediaUrl(MEDIA_FOLDERS.videos, `${base}-optimized.mp4`), fallback: mediaUrl(MEDIA_FOLDERS.videos, `${base}.mp4`), }; } /** Apply next fallback src in an img onError handler */ export function applyNextImageFallback( target: HTMLImageElement, candidates: string[], currentSrc: string ): void { const currentIndex = candidates.indexOf(currentSrc); const nextIndex = currentIndex >= 0 ? currentIndex + 1 : 0; if (nextIndex < candidates.length) { target.src = candidates[nextIndex]; } } // Re-export registry for direct access when needed export { SITE_ASSETS, MEDIA_FOLDERS, mediaUrl } from '@/infrastructure/assets/site-assets';