diff --git a/src/frontend/apps/calendars/src/hooks/useIsMobile.ts b/src/frontend/apps/calendars/src/hooks/useIsMobile.ts new file mode 100644 index 0000000..019e840 --- /dev/null +++ b/src/frontend/apps/calendars/src/hooks/useIsMobile.ts @@ -0,0 +1,23 @@ +import { useSyncExternalStore } from "react"; + +export const MOBILE_BREAKPOINT = 768; + +const MEDIA_QUERY = `(max-width: ${MOBILE_BREAKPOINT}px)`; + +function subscribe(callback: () => void): () => void { + const mql = window.matchMedia(MEDIA_QUERY); + mql.addEventListener("change", callback); + return () => mql.removeEventListener("change", callback); +} + +function getSnapshot(): boolean { + return window.matchMedia(MEDIA_QUERY).matches; +} + +function getServerSnapshot(): boolean { + return false; +} + +export function useIsMobile(): boolean { + return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); +} diff --git a/src/frontend/apps/calendars/src/utils/date.ts b/src/frontend/apps/calendars/src/utils/date.ts new file mode 100644 index 0000000..303d426 --- /dev/null +++ b/src/frontend/apps/calendars/src/utils/date.ts @@ -0,0 +1,31 @@ +export function isSameDay(a: Date, b: Date): boolean { + return ( + a.getFullYear() === b.getFullYear() && + a.getMonth() === b.getMonth() && + a.getDate() === b.getDate() + ); +} + +export function isToday(date: Date): boolean { + return isSameDay(date, new Date()); +} + +export function isWeekend(date: Date): boolean { + const day = date.getDay(); + return day === 0 || day === 6; +} + +export function addDays(date: Date, days: number): Date { + const d = new Date(date); + d.setDate(d.getDate() + days); + return d; +} + +export function getWeekStart(date: Date, firstDayOfWeek: number): Date { + const d = new Date(date); + d.setHours(0, 0, 0, 0); + const dayOfWeek = d.getDay(); + const diff = (dayOfWeek - firstDayOfWeek + 7) % 7; + d.setDate(d.getDate() - diff); + return d; +}