Files
Homarr/src/widgets/calendar/CalendarTile.tsx

155 lines
4.3 KiB
TypeScript
Raw Normal View History

2023-01-03 22:30:52 +09:00
import { createStyles, Group, MantineThemeColors, useMantineTheme } from '@mantine/core';
2022-12-11 14:11:25 +01:00
import { Calendar } from '@mantine/dates';
2022-12-18 21:21:23 +01:00
import { IconCalendarTime } from '@tabler/icons';
2022-12-11 14:11:25 +01:00
import { useQuery } from '@tanstack/react-query';
2023-01-31 12:53:32 +09:00
import { i18n } from 'next-i18next';
2022-12-11 14:11:25 +01:00
import { useState } from 'react';
import { useConfigContext } from '../../config/provider';
import { useColorTheme } from '../../tools/color';
import { isToday } from '../../tools/isToday';
2022-12-18 21:21:23 +01:00
import { defineWidget } from '../helper';
import { IWidget } from '../widgets';
2022-12-11 14:11:25 +01:00
import { CalendarDay } from './CalendarDay';
import { MediasType } from './type';
2022-12-18 21:21:23 +01:00
const definition = defineWidget({
id: 'calendar',
icon: IconCalendarTime,
options: {
2023-02-06 01:09:11 +09:00
useSonarrv4: {
type: 'switch',
defaultValue: false,
},
2022-12-18 21:21:23 +01:00
sundayStart: {
type: 'switch',
defaultValue: false,
},
radarrReleaseType: {
type: 'select',
defaultValue: 'inCinemas',
data: [
{ label: 'In Cinemas', value: 'inCinemas' },
{ label: 'Physical', value: 'physicalRelease' },
{ label: 'Digital', value: 'digitalRelease' },
],
},
2022-12-18 21:21:23 +01:00
},
gridstack: {
2023-01-08 12:41:55 +09:00
minWidth: 2,
minHeight: 2,
maxWidth: 12,
maxHeight: 12,
},
2022-12-18 21:21:23 +01:00
component: CalendarTile,
});
export type ICalendarWidget = IWidget<typeof definition['id'], typeof definition>;
interface CalendarTileProps {
widget: ICalendarWidget;
2022-12-11 14:11:25 +01:00
}
function CalendarTile({ widget }: CalendarTileProps) {
2023-01-19 11:15:56 +09:00
const { secondaryColor } = useColorTheme();
2022-12-11 14:11:25 +01:00
const { name: configName } = useConfigContext();
const { classes, cx } = useStyles(secondaryColor);
const { colorScheme, colors } = useMantineTheme();
const [month, setMonth] = useState(new Date());
const { data: medias } = useQuery({
queryKey: ['calendar/medias', { month: month.getMonth(), year: month.getFullYear() }],
staleTime: 1000 * 60 * 60 * 5,
2022-12-11 14:11:25 +01:00
queryFn: async () =>
(await (
await fetch(
`/api/modules/calendar?year=${month.getFullYear()}&month=${
month.getMonth() + 1
}&configName=${configName}`
)
).json()) as MediasType,
});
return (
2023-01-03 22:30:52 +09:00
<Group grow style={{ height: '100%' }}>
<Calendar
2023-01-19 11:13:47 +09:00
m={0}
p={0}
2023-01-03 22:30:52 +09:00
month={month}
// Should be offset 5px to the left
2023-01-19 11:13:47 +09:00
style={{ position: 'relative', top: -15 }}
2023-01-03 22:30:52 +09:00
onMonthChange={setMonth}
size="xs"
2023-01-31 12:53:32 +09:00
locale={i18n?.resolvedLanguage ?? 'en'}
2023-01-03 22:30:52 +09:00
fullWidth
onChange={() => {}}
firstDayOfWeek={widget.properties.sundayStart ? 'sunday' : 'monday'}
dayStyle={(date) => ({
2023-01-19 11:15:56 +09:00
margin: -1,
2023-01-03 22:30:52 +09:00
backgroundColor: isToday(date)
? colorScheme === 'dark'
? colors.dark[5]
: colors.gray[0]
: undefined,
})}
2023-01-19 11:13:47 +09:00
hideWeekdays
2023-01-03 22:30:52 +09:00
styles={{
2023-01-19 11:15:56 +09:00
weekdayCell: {
margin: 0,
padding: 0,
},
2023-01-03 22:30:52 +09:00
calendarHeader: {
2023-01-19 11:15:56 +09:00
position: 'relative',
2023-01-19 11:13:47 +09:00
margin: 0,
padding: 0,
2023-01-03 22:30:52 +09:00
},
}}
allowLevelChange={false}
dayClassName={(_, modifiers) => cx({ [classes.weekend]: modifiers.weekend })}
renderDay={(date) => (
<CalendarDay date={date} medias={getReleasedMediasForDate(medias, date, widget)} />
2023-01-03 22:30:52 +09:00
)}
/>
</Group>
2022-12-11 14:11:25 +01:00
);
2022-12-18 21:21:23 +01:00
}
2022-12-11 14:11:25 +01:00
const useStyles = createStyles((theme, secondaryColor: keyof MantineThemeColors) => ({
weekend: {
color: `${secondaryColor} !important`,
},
}));
const getReleasedMediasForDate = (
medias: MediasType | undefined,
date: Date,
widget: ICalendarWidget
): MediasType => {
const radarrReleaseType = widget.properties.radarrReleaseType ?? 'inCinemas';
2022-12-11 14:11:25 +01:00
const books =
medias?.books.filter((b) => new Date(b.releaseDate).toDateString() === date.toDateString()) ??
[];
const movies =
medias?.movies.filter(
(m) => new Date(m[radarrReleaseType]).toDateString() === date.toDateString()
) ?? [];
2022-12-11 14:11:25 +01:00
const musics =
medias?.musics.filter((m) => new Date(m.releaseDate).toDateString() === date.toDateString()) ??
[];
const tvShows =
medias?.tvShows.filter(
(tv) => new Date(tv.airDateUtc).toDateString() === date.toDateString()
) ?? [];
const totalCount = medias ? books.length + movies.length + musics.length + tvShows.length : 0;
return {
books,
movies,
musics,
tvShows,
totalCount,
};
};
2022-12-18 21:21:23 +01:00
export default definition;