109 lines
4.5 KiB
TypeScript
109 lines
4.5 KiB
TypeScript
import { useState, useEffect, useCallback } from "react";
|
|
import { useLocation } from "wouter";
|
|
import { Star, Heart, Briefcase, TrendingUp, ChevronLeft, ChevronRight } from "lucide-react";
|
|
import { SIGNS, ELEMENT_COLORS, getHoroscope, getRating } from "@/lib/horoscope-data";
|
|
|
|
function MiniStars({ count, max = 5 }: { count: number; max?: number }) {
|
|
return (
|
|
<div className="flex gap-px">
|
|
{Array.from({ length: max }).map((_, i) => (
|
|
<div key={i} className={`w-1.5 h-1.5 rounded-full ${i < count ? "bg-amber-400" : "bg-white/10"}`} />
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function HoroscopeWidget() {
|
|
const [, navigate] = useLocation();
|
|
const [index, setIndex] = useState(0);
|
|
const [paused, setPaused] = useState(false);
|
|
|
|
const next = useCallback(() => setIndex((i) => (i + 1) % SIGNS.length), []);
|
|
const prev = useCallback(() => setIndex((i) => (i - 1 + SIGNS.length) % SIGNS.length), []);
|
|
|
|
useEffect(() => {
|
|
if (paused) return;
|
|
const timer = setInterval(next, 6000);
|
|
return () => clearInterval(timer);
|
|
}, [paused, next]);
|
|
|
|
const sign = SIGNS[index];
|
|
const horoscope = getHoroscope(index);
|
|
|
|
return (
|
|
<div
|
|
className="rounded-lg border border-card-border overflow-hidden h-full w-full cursor-pointer group hover:border-primary/50 transition-colors flex flex-col"
|
|
style={{ background: "linear-gradient(135deg, hsl(250 30% 14%), hsl(270 25% 10%))" }}
|
|
onMouseEnter={() => setPaused(true)}
|
|
onMouseLeave={() => setPaused(false)}
|
|
onClick={() => navigate("/horoskop")}
|
|
data-testid="widget-horoscope"
|
|
>
|
|
<div className="p-3 flex items-center justify-between border-b border-white/10 flex-shrink-0">
|
|
<div className="flex items-center gap-2">
|
|
<Star className="w-4 h-4 text-amber-400" />
|
|
<h3 className="font-bold text-white text-sm">Horoskop</h3>
|
|
</div>
|
|
<div className="flex gap-1">
|
|
<button
|
|
onClick={(e) => { e.stopPropagation(); prev(); }}
|
|
className="w-5 h-5 rounded-full bg-white/10 hover:bg-white/20 flex items-center justify-center transition-colors"
|
|
data-testid="button-horoscope-prev"
|
|
>
|
|
<ChevronLeft className="w-3 h-3 text-white/70" />
|
|
</button>
|
|
<button
|
|
onClick={(e) => { e.stopPropagation(); next(); }}
|
|
className="w-5 h-5 rounded-full bg-white/10 hover:bg-white/20 flex items-center justify-center transition-colors"
|
|
data-testid="button-horoscope-next"
|
|
>
|
|
<ChevronRight className="w-3 h-3 text-white/70" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div className="flex-1 flex flex-col">
|
|
<div className="p-4 flex items-center gap-3">
|
|
<div className="w-14 h-14 rounded-xl bg-white/5 border border-white/10 flex items-center justify-center flex-shrink-0">
|
|
<span className="text-3xl">{sign.symbol}</span>
|
|
</div>
|
|
<div className="flex-1 min-w-0">
|
|
<p className="font-bold text-lg text-white">{sign.name}</p>
|
|
<p className="text-[10px] text-white/50">{sign.date}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-3 gap-1 px-3 py-1.5 border-t border-b border-white/5">
|
|
<div className="flex flex-col items-center gap-0.5">
|
|
<Heart className="w-3 h-3 text-rose-400" />
|
|
<MiniStars count={getRating(index, "love")} />
|
|
</div>
|
|
<div className="flex flex-col items-center gap-0.5">
|
|
<Briefcase className="w-3 h-3 text-amber-400" />
|
|
<MiniStars count={getRating(index, "career")} />
|
|
</div>
|
|
<div className="flex flex-col items-center gap-0.5">
|
|
<TrendingUp className="w-3 h-3 text-emerald-400" />
|
|
<MiniStars count={getRating(index, "health")} />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="px-3 pb-3 pt-2 flex-1 flex flex-col justify-between">
|
|
<p className="text-xs text-white/60 leading-relaxed line-clamp-5">{horoscope.general}</p>
|
|
<p className="text-[10px] text-amber-400 mt-2 group-hover:underline">Mehr lesen</p>
|
|
</div>
|
|
|
|
<div className="flex justify-center gap-1 pb-3">
|
|
{SIGNS.map((_, i) => (
|
|
<button
|
|
key={i}
|
|
onClick={(e) => { e.stopPropagation(); setIndex(i); }}
|
|
className={`w-1.5 h-1.5 rounded-full transition-all ${i === index ? "bg-amber-400 w-3" : "bg-white/15 hover:bg-white/30"}`}
|
|
data-testid={`button-horoscope-dot-${i}`}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|