diff --git a/web/src/components/feats/hotel/HotelCard.tsx b/web/src/components/feats/hotel/HotelCard.tsx index 5bf234d..847e1b2 100644 --- a/web/src/components/feats/hotel/HotelCard.tsx +++ b/web/src/components/feats/hotel/HotelCard.tsx @@ -2,6 +2,7 @@ import type { EventName } from '@/lib/events'; import type { Hotel } from '@/lib/hotel-utils'; +import { getHotelImageUrl } from '@/lib/hotel-utils'; import { useHoverTracking } from '@/hooks/useHoverTracking'; import PriceDisplay from '@/components/ui/PriceDisplay'; @@ -47,8 +48,6 @@ export default function HotelCard({ hotel }: { hotel: Hotel }) { window.location.href = `/hotel/products/${hotel.id}`; }; - const imageUrl = `https://images.unsplash.com/photo-1551882547-ff40c63fe5fa?w=400&h=300&fit=crop`; - return (
{hotel.name} { diff --git a/web/src/components/feats/hotel/HotelDetails.tsx b/web/src/components/feats/hotel/HotelDetails.tsx index 6cdbbdd..030769f 100644 --- a/web/src/components/feats/hotel/HotelDetails.tsx +++ b/web/src/components/feats/hotel/HotelDetails.tsx @@ -2,6 +2,7 @@ import { useState, useEffect } from 'react'; import type { Hotel } from '@/lib/hotel-utils'; +import { getHotelImageUrl } from '@/lib/hotel-utils'; import PriceDisplay from '@/components/ui/PriceDisplay'; interface HotelDetailsProps { @@ -43,13 +44,11 @@ const PriceTotalDisplay = ({ productId, nights }: { productId: string; nights: n }; export default function HotelDetails({ product, onAddToCart, addedToCart }: HotelDetailsProps) { - const imageUrl = `https://images.unsplash.com/photo-1566073771259-6a8506099945?w=800&h=600&fit=crop`; - return (
{product.name} { diff --git a/web/src/lib/airline-utils.ts b/web/src/lib/airline-utils.ts index 74a1916..b801e14 100644 --- a/web/src/lib/airline-utils.ts +++ b/web/src/lib/airline-utils.ts @@ -31,7 +31,7 @@ export interface Flight { availability: number; } -const EPOCH = new Date(0); +import { dateToDaysFromToday, dateToIndex, todayIndex } from './date-utils'; export const transformProduct = (p: AirlineProduct): Flight => { const { id, flight_type, date_index, metadata, availability } = p; @@ -52,24 +52,4 @@ export const transformProduct = (p: AirlineProduct): Flight => { }; }; -// convert date string to days from today -export const dateToDaysFromToday = (dateStr: string): number => { - const target = new Date(dateStr); - target.setHours(0, 0, 0, 0); - const today = new Date(); - today.setHours(0, 0, 0, 0); - return Math.floor((target.getTime() - today.getTime()) / 86400000); -}; - -// convert date string to date_index (days since epoch) -export const dateToIndex = (dateStr: string): number => { - const d = new Date(dateStr); - return Math.floor((d.getTime() - EPOCH.getTime()) / 86400000); -}; - -// get current date_index -export const todayIndex = (): number => { - const now = new Date(); - now.setHours(0, 0, 0, 0); - return Math.floor((now.getTime() - EPOCH.getTime()) / 86400000); -}; +export { dateToDaysFromToday, dateToIndex, todayIndex }; diff --git a/web/src/lib/date-utils.ts b/web/src/lib/date-utils.ts new file mode 100644 index 0000000..bad1a90 --- /dev/null +++ b/web/src/lib/date-utils.ts @@ -0,0 +1,23 @@ +const EPOCH = new Date(0); +const MS_PER_DAY = 86400000; + +export const dateToDaysFromToday = (dateStr: string): number => { + const target = new Date(dateStr); + target.setHours(0, 0, 0, 0); + const today = new Date(); + today.setHours(0, 0, 0, 0); + return Math.floor((target.getTime() - today.getTime()) / MS_PER_DAY); +}; + +export const dateToIndex = (dateStr: string): number => { + const d = new Date(dateStr); + return Math.floor((d.getTime() - EPOCH.getTime()) / MS_PER_DAY); +}; + +export const todayIndex = (): number => { + const now = new Date(); + now.setHours(0, 0, 0, 0); + return Math.floor((now.getTime() - EPOCH.getTime()) / MS_PER_DAY); +}; + +export { EPOCH, MS_PER_DAY }; diff --git a/web/src/lib/hotel-utils.ts b/web/src/lib/hotel-utils.ts index b59994a..e5ba5c2 100644 --- a/web/src/lib/hotel-utils.ts +++ b/web/src/lib/hotel-utils.ts @@ -25,7 +25,7 @@ export interface Hotel { nights: number; } -const EPOCH = new Date(0); +import { EPOCH, MS_PER_DAY, dateToDaysFromToday, dateToIndex, todayIndex } from './date-utils'; export const transformProduct = (p: HotelProduct): Hotel => { const { id, room_type, date_index, metadata } = p; @@ -37,14 +37,14 @@ export const transformProduct = (p: HotelProduct): Hotel => { // legacy: treat as offset from today const today = new Date(); today.setHours(0, 0, 0, 0); - checkIn = new Date(today.getTime() + date_index * 86400000); + checkIn = new Date(today.getTime() + date_index * MS_PER_DAY); } else { // proper: days since epoch - checkIn = new Date(EPOCH.getTime() + date_index * 86400000); + checkIn = new Date(EPOCH.getTime() + date_index * MS_PER_DAY); } const nights = 1; - const checkOut = new Date(checkIn.getTime() + nights * 86400000); + const checkOut = new Date(checkIn.getTime() + nights * MS_PER_DAY); const formatOpts: Intl.DateTimeFormatOptions = { month: 'short', @@ -65,24 +65,34 @@ export const transformProduct = (p: HotelProduct): Hotel => { }; }; -// convert date string to days from today -export const dateToDaysFromToday = (dateStr: string): number => { - const target = new Date(dateStr); - target.setHours(0, 0, 0, 0); - const today = new Date(); - today.setHours(0, 0, 0, 0); - return Math.floor((target.getTime() - today.getTime()) / 86400000); +const hotelImagePool = [ + 'photo-1566073771259-6a8506099945', + 'photo-1551882547-ff40c63fe5fa', + 'photo-1590490360182-c33d57733427', + 'photo-1582719478250-c89cae4dc85b', + 'photo-1596701062351-8c2c14d1fdd0', + 'photo-1631049307264-da0ec9d70304', + 'photo-1578683010236-d716f9a3f461', + 'photo-1540518614846-7eded433c457', + 'photo-1505693416388-ac5ce068fe85', + 'photo-1522771739844-6a9f6d5f14af', + 'photo-1562438668-bcf0ca6578f0', + 'photo-1595576508898-0ad5c879a061', +]; + +const hashString = (s: string): number => { + let h = 0; + for (let i = 0; i < s.length; i++) { + h = ((h << 5) - h) + s.charCodeAt(i); + h = h & h; + } + return Math.abs(h); }; -// convert date string to date_index (days since epoch) -export const dateToIndex = (dateStr: string): number => { - const d = new Date(dateStr); - return Math.floor((d.getTime() - EPOCH.getTime()) / 86400000); +export const getHotelImageUrl = (hotelId: string, size: { w: number; h: number } = { w: 400, h: 300 }): string => { + const idx = hashString(hotelId) % hotelImagePool.length; + const photoId = hotelImagePool[idx]; + return `https://images.unsplash.com/${photoId}?w=${size.w}&h=${size.h}&fit=crop`; }; -// get current date_index -export const todayIndex = (): number => { - const now = new Date(); - now.setHours(0, 0, 0, 0); - return Math.floor((now.getTime() - EPOCH.getTime()) / 86400000); -}; +export { dateToDaysFromToday, dateToIndex, todayIndex };