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.
This commit is contained in:
parent
fd591b44c3
commit
00fbfeeb17
74
src/components/weather/animated-sprite.tsx
Normal file
74
src/components/weather/animated-sprite.tsx
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
'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>)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user