122 lines
3.7 KiB
TypeScript
122 lines
3.7 KiB
TypeScript
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 {
|
|
if (item.video) {
|
|
return dishPosterFromVideo(item.video, variant);
|
|
}
|
|
if (item.image) {
|
|
return dishImageUrl(item.image);
|
|
}
|
|
return variant === 'optimized'
|
|
? SITE_ASSETS.dishes.defaultPoster
|
|
: SITE_ASSETS.fallbacks.dishPoster;
|
|
}
|
|
|
|
/** Poster candidates for progressive fallback in UI `<img onError>` */
|
|
export function getMenuPosterCandidates(item: MenuItem): string[] {
|
|
if (!item.video) {
|
|
return item.image
|
|
? [dishImageUrl(item.image), SITE_ASSETS.fallbacks.logo]
|
|
: [SITE_ASSETS.fallbacks.logo];
|
|
}
|
|
|
|
const base = videoBaseName(item.video);
|
|
return [
|
|
dishPosterFromVideo(item.video, 'standard'),
|
|
dishPosterFromVideo(item.video, 'optimized'),
|
|
...(item.image ? [dishImageUrl(item.image)] : []),
|
|
mediaUrl(MEDIA_FOLDERS.dishes, `${base}.jpg`),
|
|
SITE_ASSETS.dishes.defaultPoster,
|
|
SITE_ASSETS.fallbacks.dishPoster,
|
|
];
|
|
}
|
|
|
|
/** 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'; |