diff --git a/apps/client/src/widgets/launch_bar/Calendar.tsx b/apps/client/src/widgets/launch_bar/Calendar.tsx new file mode 100644 index 000000000..b1753a038 --- /dev/null +++ b/apps/client/src/widgets/launch_bar/Calendar.tsx @@ -0,0 +1,175 @@ +import { useTriliumOptionInt } from "../react/hooks"; +import clsx from "clsx"; +import server from "../../services/server"; +import { VNode } from "preact"; +import { useEffect, useState } from "preact/hooks"; +import { Dayjs } from "@triliumnext/commons"; +import { t } from "../../services/i18n"; + +interface DateNotesForMonth { + [date: string]: string; +} + +const DAYS_OF_WEEK = [ + t("calendar.sun"), + t("calendar.mon"), + t("calendar.tue"), + t("calendar.wed"), + t("calendar.thu"), + t("calendar.fri"), + t("calendar.sat") +]; + +interface DateRangeInfo { + weekNumbers: number[]; + dates: Dayjs[]; +} + +export default function Calendar({ date }: { date: Dayjs }) { + const [ rawFirstDayOfWeek ] = useTriliumOptionInt("firstDayOfWeek") ?? 0; + const firstDayOfWeekISO = (rawFirstDayOfWeek === 0 ? 7 : rawFirstDayOfWeek); + + const month = date.format('YYYY-MM'); + const firstDay = date.startOf('month'); + const firstDayISO = firstDay.isoWeekday(); + const monthInfo = getMonthInformation(date, firstDayISO, firstDayOfWeekISO); + + return ( + <> + +
+ {firstDayISO !== firstDayOfWeekISO && } + + +
+ + ) +} + +function CalendarWeekHeader({ rawFirstDayOfWeek }: { rawFirstDayOfWeek: number }) { + let localeDaysOfWeek = [...DAYS_OF_WEEK]; + const shifted = localeDaysOfWeek.splice(0, rawFirstDayOfWeek); + localeDaysOfWeek = ['', ...localeDaysOfWeek, ...shifted]; + + return ( +
+ {localeDaysOfWeek.map(dayOfWeek => {dayOfWeek})} +
+ ) +} + +function PreviousMonthDays({ date, info: { dates, weekNumbers } }: { date: Dayjs, info: DateRangeInfo }) { + const prevMonth = date.subtract(1, 'month').format('YYYY-MM'); + const [ dateNotesForPrevMonth, setDateNotesForPrevMonth ] = useState(); + + useEffect(() => { + server.get(`special-notes/notes-for-month/${prevMonth}`).then(setDateNotesForPrevMonth); + }, [ date ]); + + return ( + <> + + {dates.map(date => )} + + ) +} + +function CurrentMonthDays({ date, firstDayOfWeekISO }: { date: Dayjs, firstDayOfWeekISO: number }) { + let dateCursor = date; + const currentMonth = date.month(); + const items: VNode[] = []; + while (dateCursor.month() === currentMonth) { + const weekNumber = getWeekNumber(dateCursor, firstDayOfWeekISO); + if (dateCursor.isoWeekday() === firstDayOfWeekISO) { + items.push() + } + + items.push() + dateCursor = dateCursor.add(1, "day"); + } + + return items; +} + +function NextMonthDays({ date, dates }: { date: Dayjs, dates: Dayjs[] }) { + const nextMonth = date.add(1, 'month').format('YYYY-MM'); + const [ dateNotesForNextMonth, setDateNotesForNextMonth ] = useState(); + + useEffect(() => { + server.get(`special-notes/notes-for-month/${nextMonth}`).then(setDateNotesForNextMonth); + }, [ date ]); + + return dates.map(date => ( + + )); +} + +function CalendarDay({ date, dateNotesForMonth, className }: { date: Dayjs, dateNotesForMonth?: DateNotesForMonth, className?: string }) { + return ( + + + {date.date()} + + + ); +} + +function CalendarWeek({ weekNumber }: { weekNumber: number }) { + return ( + {weekNumber} + ) +} + +export function getMonthInformation(date: Dayjs, firstDayISO: number, firstDayOfWeekISO: number) { + return { + prevMonth: getPrevMonthDays(date, firstDayISO, firstDayOfWeekISO), + nextMonth: getNextMonthDays(date, firstDayOfWeekISO) + } +} + +function getPrevMonthDays(date: Dayjs, firstDayISO: number, firstDayOfWeekISO: number): DateRangeInfo { + const prevMonthLastDay = date.subtract(1, 'month').endOf('month'); + const daysToAdd = (firstDayISO - firstDayOfWeekISO + 7) % 7; + const dates: Dayjs[] = []; + + const firstDay = date.startOf('month'); + const weekNumber = getWeekNumber(firstDay, firstDayOfWeekISO); + + // Get dates from previous month + for (let i = daysToAdd - 1; i >= 0; i--) { + dates.push(prevMonthLastDay.subtract(i, 'day')); + } + + return { weekNumbers: [ weekNumber ], dates }; +} + +function getNextMonthDays(date: Dayjs, firstDayOfWeekISO: number): DateRangeInfo { + const lastDayOfMonth = date.endOf('month'); + const lastDayISO = lastDayOfMonth.isoWeekday(); + const lastDayOfUserWeek = ((firstDayOfWeekISO + 6 - 1) % 7) + 1; + const nextMonthFirstDay = date.add(1, 'month').startOf('month'); + const dates: Dayjs[] = []; + + if (lastDayISO !== lastDayOfUserWeek) { + const daysToAdd = (lastDayOfUserWeek - lastDayISO + 7) % 7; + + for (let i = 0; i < daysToAdd; i++) { + dates.push(nextMonthFirstDay.add(i, 'day')); + } + } + return { weekNumbers: [], dates }; +} + +export function getWeekNumber(date: Dayjs, firstDayOfWeekISO: number): number { + const weekStart = getWeekStartDate(date, firstDayOfWeekISO); + return weekStart.isoWeek(); +} + +function getWeekStartDate(date: Dayjs, firstDayOfWeekISO: number): Dayjs { + const currentISO = date.isoWeekday(); + const diff = (currentISO - firstDayOfWeekISO + 7) % 7; + return date.clone().subtract(diff, "day").startOf("day"); +} diff --git a/apps/client/src/widgets/launch_bar/CalendarWidget.tsx b/apps/client/src/widgets/launch_bar/CalendarWidget.tsx index f8b20c2f0..873567b29 100644 --- a/apps/client/src/widgets/launch_bar/CalendarWidget.tsx +++ b/apps/client/src/widgets/launch_bar/CalendarWidget.tsx @@ -3,25 +3,13 @@ import FNote from "../../entities/fnote"; import { LaunchBarDropdownButton, useLauncherIconAndTitle } from "./launch_bar_widgets"; import { Dayjs, dayjs } from "@triliumnext/commons"; import appContext from "../../components/app_context"; -import { useTriliumOptionInt } from "../react/hooks"; -import clsx from "clsx"; import "./CalendarWidget.css"; -import server from "../../services/server"; -import { DateRangeInfo, DAYS_OF_WEEK, getMonthInformation, getWeekNumber } from "./CalendarWidgetUtils"; -import { VNode } from "preact"; - -interface DateNotesForMonth { - [date: string]: string; -} +import Calendar from "./Calendar"; export default function CalendarWidget({ launcherNote }: { launcherNote: FNote }) { const { title, icon } = useLauncherIconAndTitle(launcherNote); const [ date, setDate ] = useState(); - useEffect(() => { - - }) - return ( - -
- {firstDayISO !== firstDayOfWeekISO && } - - -
- - ) -} - -function CalendarWeekHeader({ rawFirstDayOfWeek }: { rawFirstDayOfWeek: number }) { - let localeDaysOfWeek = [...DAYS_OF_WEEK]; - const shifted = localeDaysOfWeek.splice(0, rawFirstDayOfWeek); - localeDaysOfWeek = ['', ...localeDaysOfWeek, ...shifted]; - - return ( -
- {localeDaysOfWeek.map(dayOfWeek => {dayOfWeek})} -
- ) -} - -function PreviousMonthDays({ date, info: { dates, weekNumbers } }: { date: Dayjs, info: DateRangeInfo }) { - const prevMonth = date.subtract(1, 'month').format('YYYY-MM'); - const [ dateNotesForPrevMonth, setDateNotesForPrevMonth ] = useState(); - - useEffect(() => { - server.get(`special-notes/notes-for-month/${prevMonth}`).then(setDateNotesForPrevMonth); - }, [ date ]); - - return ( - <> - - {dates.map(date => )} - - ) -} - -function CurrentMonthDays({ date, firstDayOfWeekISO }: { date: Dayjs, firstDayOfWeekISO: number }) { - let dateCursor = date; - const currentMonth = date.month(); - const items: VNode[] = []; - while (dateCursor.month() === currentMonth) { - const weekNumber = getWeekNumber(dateCursor, firstDayOfWeekISO); - if (dateCursor.isoWeekday() === firstDayOfWeekISO) { - items.push() - } - - items.push() - dateCursor = dateCursor.add(1, "day"); - } - - return items; -} - -function NextMonthDays({ date, dates }: { date: Dayjs, dates: Dayjs[] }) { - const nextMonth = date.add(1, 'month').format('YYYY-MM'); - const [ dateNotesForNextMonth, setDateNotesForNextMonth ] = useState(); - - useEffect(() => { - server.get(`special-notes/notes-for-month/${nextMonth}`).then(setDateNotesForNextMonth); - }, [ date ]); - - return dates.map(date => ( - - )); -} - -function CalendarDay({ date, dateNotesForMonth, className }: { date: Dayjs, dateNotesForMonth?: DateNotesForMonth, className?: string }) { - return ( - - - {date.date()} - - - ); -} - -function CalendarWeek({ weekNumber }: { weekNumber: number }) { - return ( - {weekNumber} - ) -} diff --git a/apps/client/src/widgets/launch_bar/CalendarWidgetUtils.ts b/apps/client/src/widgets/launch_bar/CalendarWidgetUtils.ts deleted file mode 100644 index 3b598bbe9..000000000 --- a/apps/client/src/widgets/launch_bar/CalendarWidgetUtils.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Dayjs } from "@triliumnext/commons"; -import { t } from "../../services/i18n"; - -export const DAYS_OF_WEEK = [ - t("calendar.sun"), - t("calendar.mon"), - t("calendar.tue"), - t("calendar.wed"), - t("calendar.thu"), - t("calendar.fri"), - t("calendar.sat") -]; - -export interface DateRangeInfo { - weekNumbers: number[]; - dates: Dayjs[]; -} - -export function getMonthInformation(date: Dayjs, firstDayISO: number, firstDayOfWeekISO: number) { - return { - prevMonth: getPrevMonthDays(date, firstDayISO, firstDayOfWeekISO), - nextMonth: getNextMonthDays(date, firstDayOfWeekISO) - } -} - -function getPrevMonthDays(date: Dayjs, firstDayISO: number, firstDayOfWeekISO: number): DateRangeInfo { - const prevMonthLastDay = date.subtract(1, 'month').endOf('month'); - const daysToAdd = (firstDayISO - firstDayOfWeekISO + 7) % 7; - const dates: Dayjs[] = []; - - const firstDay = date.startOf('month'); - const weekNumber = getWeekNumber(firstDay, firstDayOfWeekISO); - - // Get dates from previous month - for (let i = daysToAdd - 1; i >= 0; i--) { - dates.push(prevMonthLastDay.subtract(i, 'day')); - } - - return { weekNumbers: [ weekNumber ], dates }; -} - -function getNextMonthDays(date: Dayjs, firstDayOfWeekISO: number): DateRangeInfo { - const lastDayOfMonth = date.endOf('month'); - const lastDayISO = lastDayOfMonth.isoWeekday(); - const lastDayOfUserWeek = ((firstDayOfWeekISO + 6 - 1) % 7) + 1; - const nextMonthFirstDay = date.add(1, 'month').startOf('month'); - const dates: Dayjs[] = []; - - if (lastDayISO !== lastDayOfUserWeek) { - const daysToAdd = (lastDayOfUserWeek - lastDayISO + 7) % 7; - - for (let i = 0; i < daysToAdd; i++) { - dates.push(nextMonthFirstDay.add(i, 'day')); - } - } - return { weekNumbers: [], dates }; -} - -export function getWeekNumber(date: Dayjs, firstDayOfWeekISO: number): number { - const weekStart = getWeekStartDate(date, firstDayOfWeekISO); - return weekStart.isoWeek(); -} - -function getWeekStartDate(date: Dayjs, firstDayOfWeekISO: number): Dayjs { - const currentISO = date.isoWeekday(); - const diff = (currentISO - firstDayOfWeekISO + 7) % 7; - return date.clone().subtract(diff, "day").startOf("day"); -}