import CalendarDayGrid from "@/components/Calendar/Components/CalendarDayGrid"; import CalendarHeader from "@/components/Calendar/Components/CalendarHeader"; import { CalendarMeasurement } from "@/components/Calendar/Helpers/CalendarMeasurement"; import { LoadingPlaceholder } from "@/core/ui/LoadingWidget/LoadingWidget"; import { useMeasurementsCategoryQuery } from "@/components/Measurements"; import { DiaryEntry, useNutritionDiaryQuery } from "@/components/Nutrition"; import { useSessionsQuery, WorkoutSession } from "@/components/Routines"; import { useBodyWeightQuery, WeightEntry } from "@/components/Weight"; import { dateToYYYYMMDD, isSameDay } from "@/core/lib/date"; import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; import { Box, Card, CardContent, CardHeader, useMediaQuery, useTheme } from '@mui/material'; import React, { useEffect, useMemo, useState } from 'react'; import { useTranslation } from "react-i18next"; import Entries from './Entries'; export interface DayProps { date: Date, weightEntry: WeightEntry | undefined, measurements: CalendarMeasurement[], nutritionLogs: DiaryEntry[], workoutSession: WorkoutSession | undefined, } const CalendarComponent = (props: { isStandalone?: boolean }) => { const [t] = useTranslation(); const currentDate = new Date(); const [currentMonth, setCurrentMonth] = useState(currentDate.getMonth()); const [currentYear, setCurrentYear] = useState(currentDate.getFullYear()); const startOfMonth = new Date(currentYear, currentMonth, 1); const endOfMonth = new Date(currentYear, currentMonth + 1, 0); const isStandalone = props.isStandalone ?? true; const weightsQuery = useBodyWeightQuery(); const sessionQuery = useSessionsQuery({ filtersetQuerySessions: { "date__gte": dateToYYYYMMDD(startOfMonth), "date__lte": dateToYYYYMMDD(endOfMonth), }, filtersetQueryLogs: { "date__gte": dateToYYYYMMDD(startOfMonth), "date__lte": dateToYYYYMMDD(endOfMonth), } }); const measurementQuery = useMeasurementsCategoryQuery({ filtersetQueryEntries: { "date__gte": dateToYYYYMMDD(startOfMonth), "date__lte": dateToYYYYMMDD(endOfMonth), } }); const nutritionDiaryQuery = useNutritionDiaryQuery({ filtersetQuery: { "datetime__gte": dateToYYYYMMDD(startOfMonth), "datetime__lte": dateToYYYYMMDD(endOfMonth), } }); const isLoading = weightsQuery.isLoading || sessionQuery.isLoading || measurementQuery.isLoading || nutritionDiaryQuery.isLoading; const isSuccess = weightsQuery.isSuccess && sessionQuery.isSuccess && measurementQuery.isSuccess && nutritionDiaryQuery.isSuccess; const defaultDay: DayProps = { date: currentDate, weightEntry: undefined, workoutSession: undefined, measurements: [], nutritionLogs: [] }; const days = useMemo(() => { const year = currentYear; const month = currentMonth; const date = new Date(year, month, 1); const result: DayProps[] = []; const measurements = measurementQuery.data?.flatMap(category => category.entries.map(entry => new CalendarMeasurement(category.name, category.unit, entry.value, entry.date)) ) ?? []; const firstDayOfMonth = new Date(year, month, 1); let dayOfWeek = firstDayOfMonth.getDay(); dayOfWeek = dayOfWeek === 0 ? 6 : dayOfWeek - 1; for (let i = 0; i < dayOfWeek; i++) { result.push({ date: new Date(year, month, -dayOfWeek + i + 1), weightEntry: undefined, measurements: [], nutritionLogs: [], workoutSession: undefined }); } while (date.getMonth() === month) { result.push({ date: new Date(date), weightEntry: weightsQuery.data?.find(w => isSameDay(w.date, date)), measurements: measurements.filter(m => isSameDay(m.date, date)) || [], workoutSession: sessionQuery.data?.find(m => isSameDay(m.date, date)) || undefined, nutritionLogs: nutritionDiaryQuery.data?.filter(m => isSameDay(m.datetime, date)) || [], }); date.setDate(date.getDate() + 1); } const lastDayOfMonth = new Date(year, month + 1, 0); dayOfWeek = lastDayOfMonth.getDay(); const remainingDays = dayOfWeek === 0 ? 0 : 7 - dayOfWeek; for (let i = 1; i <= remainingDays; i++) { result.push({ date: new Date(year, month + 1, i), weightEntry: undefined, workoutSession: undefined, measurements: [], nutritionLogs: [] }); } return result; }, [currentYear, currentMonth, weightsQuery.data, sessionQuery.data, measurementQuery.data, nutritionDiaryQuery.data]); const [selectedDay, setSelectedDay] = useState(days.find(day => isSameDay(day.date, currentDate)) || defaultDay); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); useEffect(() => { if (isSuccess) { const todayWithData = days.find(day => isSameDay(day.date, currentDate)); if (todayWithData) { setSelectedDay(todayWithData); } } }, [isSuccess]); useEffect(() => { setCurrentMonth(selectedDay.date.getMonth()); setCurrentYear(selectedDay.date.getFullYear()); }, [selectedDay]); const handleDayClick = (day: DayProps) => { setSelectedDay(day); }; const handlePrevMonth = () => { if (currentMonth === 0) { setCurrentMonth(11); setCurrentYear(currentYear - 1); } else { setCurrentMonth(currentMonth - 1); } }; const handleNextMonth = () => { if (currentMonth < currentDate.getMonth() || currentYear < currentDate.getFullYear()) { if (currentMonth === 11) { setCurrentMonth(0); setCurrentYear(currentYear + 1); } else { setCurrentMonth(currentMonth + 1); } } }; return (
{t("calendar")}
} />
{isLoading && } {isSuccess && }
); }; export default CalendarComponent;