forecast/src/components/weather/animated-sprite.tsx
Mathis 00fbfeeb17
feat(component): add WeatherSprite with animations
Introduces a new WeatherSprite component featuring Lottie animations based on WMO weather codes. Includes utility subcomponents for displaying titles and indicators.
2024-09-27 16:57:22 +02:00

74 lines
2.2 KiB
TypeScript

'use client'
import LottieReact from "@lottielab/lottie-player/react";
import {cn} from "@/lib/utils";
import {Clock4, LucideIcon} from "lucide-react";
import {DateFormatter} from "@/lib/date";
import Image from "next/image";
// Follow WMO weather interpretation codes.
interface SpriteTitleProps {
title?: string;
icon?: LucideIcon
}
function SpriteTitle(props: SpriteTitleProps) {
const Icon = props.icon || Clock4;
const title = props.title || new DateFormatter().generateFormattedDate(new Date(), { formatTemplate: "PPP", locale: "fr" })
return (<div className={"flex justify-center items-center gap-1"}>
<Icon/>
<h2 >{title}</h2>
</div>)
}
type SpriteIndicatorProps = {
type : "slippery" | "snow-covered" | "strong-wind"
className?: string
}
function SpriteIndicator(props: SpriteIndicatorProps) {
switch (props.type) {
case "slippery":
return (<div className={cn("animate-pulse scale-125", props.className)}>
<Image src={"route_glisante.svg"} alt={"Panneau route glisante"} width={256} height={256}/>
</div>)
}
}
interface WeatherSpriteProps {
weather: number;
title?: string;
indicator?: SpriteIndicatorProps
className?: string;
danger?: boolean;
}
export default function WeatherSprite(props: WeatherSpriteProps) {
const wmo = new Map([
[0, "clear.json"],
[1, "partial_cloud.json"],
[2, "partial_cloud.json"],
[3, "cloud.json"],
[45, "foggy.json"],
[48, "fog.json"],
])
const displayWmo = new Map([
[0, "Ciel clair"],
[1, "Principalement clair"],
[2, "Partiellement nuageux"],
[3, "Partiellement couvert"],
[45, "Brouillard"],
[48, "Brouillard givrant"],
])
return (<div className={cn("flex flex-col justify-center items-center gap-1 h-fit w-fit text-lg px-3 py-2 font-bold rounded-xl relative", props.danger ? "bg-destructive" : "", props.className)}>
{props.title && <SpriteTitle title={props.title}/>}
{
props.indicator && <div className={"absolute top-12 left-10 z-30"}>
<SpriteIndicator type={props.indicator.type} className={cn("w-20 h-20", props.indicator.className)}/>
</div>
}
<LottieReact src={wmo.get(props.weather) || "clear.json"} className={"w-full h-full z-5"}/>
<h3 className={"tracking-widest uppercase"}>{displayWmo.get(props.weather)}</h3>
</div>)
}