mirror of
https://github.com/ajnart/homarr.git
synced 2026-02-26 00:10:56 +01:00
🐛 Refactor DateTile component to use API timezone (#1563)
and remove unused hook
This commit is contained in:
@@ -6,12 +6,12 @@ import advancedFormat from 'dayjs/plugin/advancedFormat';
|
||||
import timezones from 'dayjs/plugin/timezone';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useSetSafeInterval } from '~/hooks/useSetSafeInterval';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { getLanguageByCode } from '~/tools/language';
|
||||
import { api } from '~/utils/api';
|
||||
|
||||
import { defineWidget } from '../helper';
|
||||
import { WidgetLoading } from '../loading';
|
||||
import { IWidget } from '../widgets';
|
||||
|
||||
dayjs.extend(advancedFormat);
|
||||
@@ -76,12 +76,31 @@ interface DateTileProps {
|
||||
}
|
||||
|
||||
function DateTile({ widget }: DateTileProps) {
|
||||
const date = useDateState(
|
||||
widget.properties.enableTimezone ? widget.properties.timezoneLocation : undefined
|
||||
);
|
||||
const formatString = widget.properties.display24HourFormat ? 'HH:mm' : 'h:mm A';
|
||||
const { ref, width } = useElementSize();
|
||||
const { cx, classes } = useStyles();
|
||||
const { data: sessionData } = useSession();
|
||||
const [now, setDate] = useState(new Date());
|
||||
const { data, isFetching } = api.timezone.at.useQuery(
|
||||
{
|
||||
latitude: widget.properties.timezoneLocation.latitude,
|
||||
longitude: widget.properties.timezoneLocation.longitude,
|
||||
},
|
||||
{
|
||||
enabled: location !== undefined && widget.properties.enableTimezone,
|
||||
retry: false,
|
||||
}
|
||||
);
|
||||
useEffect(() => {
|
||||
// Refresh the time every second
|
||||
const interval = setInterval(() => setDate(new Date()), 1000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const language = getLanguageByCode(sessionData?.user.language ?? 'en');
|
||||
dayjs.locale(language.locale);
|
||||
|
||||
if (isFetching) return <WidgetLoading />;
|
||||
|
||||
return (
|
||||
<Stack ref={ref} className={cx(classes.wrapper, 'dashboard-tile-clock-wrapper')}>
|
||||
@@ -90,12 +109,13 @@ function DateTile({ widget }: DateTileProps) {
|
||||
size={width < 150 ? 'sm' : 'lg'}
|
||||
className={cx(classes.extras, 'dashboard-tile-clock-city')}
|
||||
>
|
||||
{isFetching}
|
||||
{widget.properties.timezoneLocation.name}
|
||||
{widget.properties.titleState === 'both' && dayjs(date).format(' (z)')}
|
||||
{widget.properties.titleState === 'both' && dayjs(now).tz(data).format(' (z)')}
|
||||
</Text>
|
||||
)}
|
||||
<Text className={cx(classes.clock, 'dashboard-tile-clock-hour')}>
|
||||
{dayjs(date).format(formatString)}
|
||||
{dayjs(now).tz(data).format(formatString)}
|
||||
</Text>
|
||||
{!widget.properties.dateFormat.includes('hide') && (
|
||||
<Text
|
||||
@@ -103,7 +123,7 @@ function DateTile({ widget }: DateTileProps) {
|
||||
pt="0.2rem"
|
||||
className={cx(classes.extras, 'dashboard-tile-clock-date')}
|
||||
>
|
||||
{dayjs(date).format(widget.properties.dateFormat)}
|
||||
{dayjs(now).tz(data).format(widget.properties.dateFormat)}
|
||||
</Text>
|
||||
)}
|
||||
</Stack>
|
||||
@@ -131,50 +151,4 @@ const useStyles = createStyles(() => ({
|
||||
},
|
||||
}));
|
||||
|
||||
/**
|
||||
* State which updates when the minute is changing
|
||||
* @returns current date updated every new minute
|
||||
*/
|
||||
const useDateState = (location?: { latitude: number; longitude: number }) => {
|
||||
//Gets a timezone from user input location. If location is undefined, then it means it's a local timezone so keep undefined
|
||||
const { data: timezone } = api.timezone.at.useQuery(location!, {
|
||||
enabled: location !== undefined,
|
||||
});
|
||||
const { data: sessionData } = useSession();
|
||||
const { data: userWithSettings } = api.user.withSettings.useQuery(undefined, {
|
||||
enabled: !!sessionData?.user,
|
||||
});
|
||||
const userLanguage = userWithSettings?.settings.language;
|
||||
const [date, setDate] = useState(getNewDate(timezone));
|
||||
const setSafeInterval = useSetSafeInterval();
|
||||
const timeoutRef = useRef<NodeJS.Timeout>(); // reference for initial timeout until first minute change
|
||||
useEffect(() => {
|
||||
const language = getLanguageByCode(userLanguage ?? 'en');
|
||||
dayjs.locale(language.locale);
|
||||
setDate(getNewDate(timezone));
|
||||
timeoutRef.current = setTimeout(
|
||||
() => {
|
||||
setDate(getNewDate(timezone));
|
||||
// Starts interval which update the date every minute
|
||||
setSafeInterval(() => {
|
||||
setDate(getNewDate(timezone));
|
||||
}, 1000 * 60);
|
||||
//1 minute - current seconds and milliseconds count
|
||||
},
|
||||
1000 * 60 - (1000 * dayjs().second() + dayjs().millisecond())
|
||||
);
|
||||
return () => timeoutRef.current && clearTimeout(timeoutRef.current);
|
||||
}, [timezone, userLanguage]);
|
||||
|
||||
return date;
|
||||
};
|
||||
|
||||
//Returns a local date if no inputs or returns date from input zone
|
||||
const getNewDate = (timezone?: string) => {
|
||||
if (timezone) {
|
||||
return dayjs().tz(timezone);
|
||||
}
|
||||
return dayjs();
|
||||
};
|
||||
|
||||
export default definition;
|
||||
|
||||
Reference in New Issue
Block a user