🐛 Refactor DateTile component to use API timezone (#1563)

and remove unused hook
This commit is contained in:
Thomas Camlong
2023-11-09 20:25:32 +01:00
committed by GitHub
parent 4316ffb27f
commit 545749a057

View File

@@ -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;