Files
jellybloom/src/pages/home/home-utils.tsx
T

124 lines
4.3 KiB
TypeScript

import { Compass } from '../../lib/icons'
export interface TimeSlot {
title: string
subtitle: string
genres: string[]
}
export function pickTimeOfDaySlot(): TimeSlot {
const hour = new Date().getHours()
if (hour >= 5 && hour < 12) {
return {
title: 'A gentle start',
subtitle: 'Morning picks - light comedy, animation, and feel-good',
genres: ['Comedy', 'Animation', 'Family'],
}
}
if (hour >= 12 && hour < 17) {
return {
title: 'Afternoon adventure',
subtitle: 'Action, sci-fi, and adventure for the daylight hours',
genres: ['Action', 'Adventure', 'Science Fiction'],
}
}
if (hour >= 17 && hour < 22) {
return {
title: 'Evening watch',
subtitle: 'Prestige drama and thrillers for prime time',
genres: ['Drama', 'Thriller', 'Mystery'],
}
}
return {
title: 'After hours',
subtitle: 'Horror, noir, and the dark stuff for late nights',
genres: ['Horror', 'Crime', 'Thriller'],
}
}
/** Day-bucketed shuffle - rotates a few times a day, stable within a session. */
export function dailyBucket(): number {
// Changes every 6 hours so the order rotates a few times a day
return Math.floor(Date.now() / (6 * 3600 * 1000))
}
export function seededShuffle<T>(arr: T[], seed: number): T[] {
const out = [...arr]
let s = seed | 0
const random = () => {
s = (s + 0x6D2B79F5) | 0
let t = Math.imul(s ^ (s >>> 15), 1 | s)
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
}
for (let i = out.length - 1; i > 0; i--) {
const j = Math.floor(random() * (i + 1))
;[out[i], out[j]] = [out[j], out[i]]
}
return out
}
export function Dot() {
return <span className="text-white/30">·</span>
}
export function HomeSkeleton() {
return (
<div className="pb-12">
<div className="relative h-[60vh] min-h-[440px] -mt-14 mb-2 overflow-hidden">
<div className="absolute inset-0 skeleton" />
<div className="absolute inset-0 bg-gradient-to-r from-void via-void/50 to-transparent" />
<div className="absolute inset-0 bg-gradient-to-t from-void via-transparent to-transparent" />
<div className="relative h-full flex items-end pb-16 px-7">
<div className="max-w-2xl space-y-3 w-full">
<div className="skeleton h-5 w-24 rounded" />
<div className="skeleton h-12 w-2/3 rounded" />
<div className="skeleton h-4 w-1/3 rounded" />
<div className="skeleton h-12 w-1/2 rounded mt-4" />
<div className="flex gap-2 mt-2">
<div className="skeleton h-10 w-24 rounded-lg" />
<div className="skeleton h-10 w-28 rounded-lg" />
</div>
</div>
</div>
</div>
<div className="-mt-4 relative z-10 space-y-10">
{[0, 1, 2].map(i => (
<div key={i}>
<div className="px-7 mb-3.5">
<div className="skeleton h-5 w-40 rounded mb-1.5" />
<div className="skeleton h-3 w-56 rounded" />
</div>
<div className="px-7 flex gap-3">
{Array.from({ length: 6 }).map((_, j) => (
<div key={j} className="shrink-0 w-[160px]">
<div className="skeleton aspect-[2/3] rounded-lg" />
<div className="skeleton h-3 w-3/4 mt-2 rounded" />
<div className="skeleton h-2.5 w-1/2 mt-1 rounded" />
</div>
))}
</div>
</div>
))}
</div>
</div>
)
}
export function EmptyHome() {
return (
<div className="flex flex-col items-center justify-center min-h-[70vh] text-center px-6">
<div className="relative w-20 h-20 mb-5">
<div className="absolute inset-0 rounded-full bg-accent/10 blur-2xl" />
<div className="relative w-full h-full rounded-full bg-gradient-to-br from-accent/20 to-accent/5 ring-1 ring-accent/20 grid place-items-center">
<Compass size={28} className="text-accent" />
</div>
</div>
<h2 className="text-[20px] font-semibold text-text-1 mb-1.5 tracking-tight">Welcome to Jellybloom</h2>
<p className="text-[13px] text-text-3 max-w-md leading-relaxed">
Your library is quiet. Add movies, shows, or music to your server and they'll appear here.
</p>
</div>
)
}