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

195 lines
5.2 KiB
TypeScript
Raw Normal View History

2023-04-24 21:39:04 +02:00
import { useMantineTheme } from '@mantine/core';
2022-12-11 14:11:25 +01:00
import { Calendar } from '@mantine/dates';
import { IconCalendarTime } from '@tabler/icons-react';
import { useSession } from 'next-auth/react';
2022-12-11 14:11:25 +01:00
import { useState } from 'react';
import { getLanguageByCode } from '~/tools/language';
import { RouterOutputs, api } from '~/utils/api';
2023-07-21 18:08:40 +09:00
2023-09-03 16:23:40 +02:00
import { useEditModeStore } from '~/components/Dashboard/Views/useEditModeStore';
import { useConfigContext } from '~/config/provider';
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';
2023-04-24 21:39:04 +02:00
import { getBgColorByDateAndTheme } from './bg-calculator';
2022-12-11 14:11:25 +01:00
import { MediasType } from './type';
2022-12-18 21:21:23 +01:00
const definition = defineWidget({
id: 'calendar',
icon: IconCalendarTime,
options: {
hideWeekDays: {
type: 'switch',
defaultValue: true,
},
2023-02-06 01:09:11 +09:00
useSonarrv4: {
type: 'switch',
defaultValue: false,
},
radarrReleaseType: {
type: 'select',
defaultValue: 'inCinemas',
data: [
{ value: 'inCinemas' },
{ value: 'physicalRelease' },
{ value: 'digitalRelease' },
],
},
2023-07-21 18:08:40 +09:00
fontSize: {
type: 'select',
defaultValue: 'xs',
data: [
{ value: 'xs' },
{ value: 'sm' },
{ value: 'md' },
{ value: 'lg' },
{ value: 'xl' },
2023-07-21 18:08:40 +09:00
],
},
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>;
2022-12-18 21:21:23 +01:00
interface CalendarTileProps {
widget: ICalendarWidget;
2022-12-11 14:11:25 +01:00
}
function CalendarTile({ widget }: CalendarTileProps) {
const { colorScheme, radius } = useMantineTheme();
2022-12-11 14:11:25 +01:00
const { name: configName } = useConfigContext();
const [month, setMonth] = useState(new Date());
const isEditMode = useEditModeStore((x) => x.enabled);
const { data: sessionData } = useSession();
const { data: userWithSettings } = api.user.withSettings.useQuery(undefined, {
enabled: !!sessionData?.user,
});
2022-12-11 14:11:25 +01:00
const language = getLanguageByCode(userWithSettings?.settings.language ?? 'en');
2023-06-10 18:00:24 +02:00
const { data: medias } = api.calendar.medias.useQuery(
{
configName: configName!,
month: month.getMonth() + 1,
year: month.getFullYear(),
options: { useSonarrv4: widget.properties.useSonarrv4 },
},
{
staleTime: 1000 * 60 * 60 * 5,
enabled: isEditMode === false,
}
);
2022-12-11 14:11:25 +01:00
const firstDayOfWeek = userWithSettings?.settings.firstDayOfWeek ?? 'monday';
2022-12-11 14:11:25 +01:00
return (
2023-04-17 14:48:04 +09:00
<Calendar
defaultDate={new Date()}
onPreviousMonth={setMonth}
onNextMonth={setMonth}
size={widget.properties.fontSize}
locale={language.locale}
firstDayOfWeek={getFirstDayOfWeek(firstDayOfWeek)}
2023-07-17 00:26:10 +02:00
hideWeekdays={widget.properties.hideWeekDays}
style={{ position: 'relative' }}
2023-04-17 14:48:04 +09:00
date={month}
maxLevel="month"
hasNextLevel={false}
styles={{
calendarHeader: {
maxWidth: 'inherit',
marginBottom: '0.35rem !important',
},
calendarHeaderLevel: {
2023-07-21 18:08:40 +09:00
height: '100%',
},
2023-07-21 18:08:40 +09:00
calendarHeaderControl: {
height: '100%',
2023-04-17 14:48:04 +09:00
},
calendar: {
height: '100%',
display: 'flex',
flexDirection: 'column',
width: '100%',
},
monthLevelGroup: {
height: '100%',
},
monthLevel: {
height: '100%',
display: 'flex',
flexDirection: 'column',
width: '100%',
},
2023-07-21 18:08:40 +09:00
monthCell: {
textAlign: 'center',
},
2023-04-17 14:48:04 +09:00
month: {
flex: 1,
},
2023-07-21 18:08:40 +09:00
day: {
borderRadius: ['xs', 'sm'].includes(widget.properties.fontSize) ? radius.md : radius.lg,
},
2023-04-17 14:48:04 +09:00
}}
2023-04-24 21:39:04 +02:00
getDayProps={(date) => ({
bg: getBgColorByDateAndTheme(colorScheme, date),
})}
2023-04-17 14:48:04 +09:00
renderDay={(date) => (
2023-07-21 18:08:40 +09:00
<CalendarDay
date={date}
medias={getReleasedMediasForDate(medias, date, widget)}
size={widget.properties.fontSize}
/>
2023-04-17 14:48:04 +09:00
)}
/>
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 getFirstDayOfWeek = (
firstDayOfWeek: RouterOutputs['user']['withSettings']['settings']['firstDayOfWeek']
) => {
if (firstDayOfWeek === 'sunday') return 0;
if (firstDayOfWeek === 'monday') return 1;
return 6;
};
const getReleasedMediasForDate = (
medias: MediasType | undefined,
date: Date,
widget: ICalendarWidget
): MediasType => {
const { radarrReleaseType } = widget.properties;
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;