Files
Homarr/src/widgets/clock/ClockTile.tsx
2022-12-16 21:01:06 +01:00

72 lines
2.4 KiB
TypeScript

import { Center, Stack, Text, Title } from '@mantine/core';
import dayjs from 'dayjs';
import { useEffect, useRef, useState } from 'react';
import { HomarrCardWrapper } from '../../components/Dashboard/Tiles/HomarrCardWrapper';
import { WidgetsMenu } from '../../components/Dashboard/Tiles/Widgets/WidgetsMenu';
import { BaseTileProps } from '../../components/Dashboard/Tiles/type';
import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval';
import { ClockIntegrationType } from '../../types/integration';
interface ClockTileProps extends BaseTileProps {
module: ClockIntegrationType; // TODO: change to new type defined through widgetDefinition
}
export const ClockTile = ({ className, module }: ClockTileProps) => {
const date = useDateState();
const formatString = module?.properties.is24HoursFormat ? 'HH:mm' : 'h:mm A';
// TODO: add widgetWrapper that is generic and uses the definition
return (
<HomarrCardWrapper className={className}>
<WidgetsMenu<'clock'>
integration="clock"
module={module}
options={module?.properties}
labels={{ is24HoursFormat: 'descriptor.settings.display24HourFormat.label' }}
/>
<Center style={{ height: '100%' }}>
<Stack spacing="xs">
<Title>{dayjs(date).format(formatString)}</Title>
<Text size="lg">{dayjs(date).format('dddd, MMMM D')}</Text>
</Stack>
</Center>
</HomarrCardWrapper>
);
};
/**
* State which updates when the minute is changing
* @returns current date updated every new minute
*/
const useDateState = () => {
const [date, setDate] = useState(new Date());
const setSafeInterval = useSetSafeInterval();
const timeoutRef = useRef<NodeJS.Timeout>(); // reference for initial timeout until first minute change
useEffect(() => {
timeoutRef.current = setTimeout(() => {
setDate(new Date());
// Starts intervall which update the date every minute
setSafeInterval(() => {
setDate(new Date());
}, 1000 * 60);
}, getMsUntilNextMinute());
return () => timeoutRef.current && clearTimeout(timeoutRef.current);
}, []);
return date;
};
// calculates the amount of milliseconds until next minute starts.
const getMsUntilNextMinute = () => {
const now = new Date();
const nextMinute = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate(),
now.getHours(),
now.getMinutes() + 1
);
return nextMinute.getTime() - now.getTime();
};