Files
homarr/packages/widgets/src/clock/weather-summary.tsx
T

92 lines
2.8 KiB
TypeScript

import { Box, Group, Loader, Stack, Text } from "@mantine/core";
import { clientApi } from "@homarr/api/client";
import { useI18n } from "@homarr/translation/client";
import { zoomCompensatedSize } from "@homarr/ui";
import { isInitialWidgetQueryPending } from "../common/query-state";
import { AnimatedWeatherIcon } from "../weather/animated-icon";
import { WeatherDescription } from "../weather/icon";
interface ClockWeatherSummaryProps {
latitude: number;
longitude: number;
locationName: string;
isFahrenheit: boolean;
animateIcon: boolean;
detailed: boolean;
}
export const ClockWeatherSummary = ({
latitude,
longitude,
locationName,
isFahrenheit,
animateIcon,
detailed,
}: ClockWeatherSummaryProps) => {
const tCommon = useI18n("common");
const weatherQuery = clientApi.widget.weather.atLocation.useQuery({ latitude, longitude });
const weather = weatherQuery.data;
if (!weather) {
if (isInitialWidgetQueryPending(weatherQuery)) {
return <Loader size="xs" aria-label={tCommon("action.loading")} />;
}
return null;
}
const temperature = isFahrenheit ? weather.current.temperature * (9 / 5) + 32 : weather.current.temperature;
const unit = isFahrenheit ? "°F" : "°C";
const today = weather.daily[0];
const formatTemperature = (value: number | null | undefined) => {
if (value === undefined || value === null) return "—";
const preferred = isFahrenheit ? value * (9 / 5) + 32 : value;
return `${Math.round(preferred)}${unit}`;
};
return (
<Stack gap={detailed ? 3 : 2} align={detailed ? "flex-start" : "center"}>
{detailed ? (
<Group gap={5} wrap="nowrap">
<AnimatedWeatherIcon
animated={animateIcon}
code={weather.current.weatherCode}
isDay={weather.current.isDay}
style={zoomCompensatedSize(28)}
/>
<Text size="sm" fw={600}>
{Math.round(temperature)}
{unit}
</Text>
<WeatherDescription weatherOnly weatherCode={weather.current.weatherCode} />
</Group>
) : (
<Stack gap={1} align="center">
<AnimatedWeatherIcon
animated={animateIcon}
code={weather.current.weatherCode}
isDay={weather.current.isDay}
style={zoomCompensatedSize(26)}
/>
<Text size="xs" c="dimmed">
{Math.round(temperature)}
{unit}
</Text>
</Stack>
)}
{detailed && (
<Box>
<Text size="xs" fw={600} lineClamp={1}>
{locationName}
</Text>
<Text size="xs" c="dimmed">
{formatTemperature(today?.maxTemperature)} / {formatTemperature(today?.minTemperature)}
</Text>
</Box>
)}
</Stack>
);
};