import { useSocket } from '@/socket/socketContext'; import { IProjectTask } from '@/types/project/projectTasksViewModel.types'; import { DatePicker } from 'antd'; import dayjs from 'dayjs'; import calendar from 'dayjs/plugin/calendar'; import { SocketEvents } from '@/shared/socket-events'; import type { Dayjs } from 'dayjs'; import { useTranslation } from 'react-i18next'; import { useEffect, useState, useMemo } from 'react'; import { useAppSelector } from '@/hooks/useAppSelector'; import { useGetMyTasksQuery } from '@/api/home-page/home-page.api.service'; import { getUserSession } from '@/utils/session-helper'; // Extend dayjs with the calendar plugin dayjs.extend(calendar); type HomeTasksDatePickerProps = { record: IProjectTask; }; const HomeTasksDatePicker = ({ record }: HomeTasksDatePickerProps) => { const { socket, connected } = useSocket(); const { t } = useTranslation('home'); const { homeTasksConfig } = useAppSelector(state => state.homePageReducer); const { refetch } = useGetMyTasksQuery(homeTasksConfig, { skip: false, }); // Use useMemo to avoid re-renders when record.end_date is the same const initialDate = useMemo( () => (record.end_date ? dayjs(record.end_date) : null), [record.end_date] ); const [selectedDate, setSelectedDate] = useState(initialDate); // Update selected date when record changes useEffect(() => { setSelectedDate(initialDate); }, [initialDate]); const handleChangeReceived = (value: any) => { refetch(); }; useEffect(() => { socket?.on(SocketEvents.TASK_END_DATE_CHANGE.toString(), handleChangeReceived); socket?.on(SocketEvents.TASK_STATUS_CHANGE.toString(), handleChangeReceived); return () => { socket?.removeListener(SocketEvents.TASK_END_DATE_CHANGE.toString(), handleChangeReceived); socket?.removeListener(SocketEvents.TASK_STATUS_CHANGE.toString(), handleChangeReceived); }; }, [connected]); const handleEndDateChanged = (value: Dayjs | null, task: IProjectTask) => { setSelectedDate(value); if (!task.id) return; const body = { task_id: task.id, end_date: value?.format('YYYY-MM-DD'), parent_task: task.parent_task_id, time_zone: getUserSession()?.timezone_name ? getUserSession()?.timezone_name : Intl.DateTimeFormat().resolvedOptions().timeZone, }; socket?.emit(SocketEvents.TASK_END_DATE_CHANGE.toString(), JSON.stringify(body)); }; // Function to dynamically format the date based on the calendar rules const getFormattedDate = (date: Dayjs | null) => { if (!date) return ''; return date.calendar(null, { sameDay: '[Today]', nextDay: '[Tomorrow]', nextWeek: 'MMM DD', lastDay: '[Yesterday]', lastWeek: 'MMM DD', sameElse: date.year() === dayjs().year() ? 'MMM DD' : 'MMM DD, YYYY', }); }; return ( current.isBefore(dayjs(record.start_date)) : undefined } placeholder={t('tasks.dueDatePlaceholder')} value={selectedDate} onChange={value => handleEndDateChanged(value || null, record || null)} format={value => getFormattedDate(value)} // Dynamically format the displayed value style={{ color: selectedDate ? selectedDate.isSame(dayjs(), 'day') || selectedDate.isSame(dayjs().add(1, 'day'), 'day') ? '#52c41a' : selectedDate.isAfter(dayjs().add(1, 'day'), 'day') ? undefined : '#ff4d4f' : undefined, width: '125px', // Ensure the input takes full width }} inputReadOnly // Prevent manual input to avoid overflow issues variant={'borderless'} // Make the DatePicker borderless suffixIcon={null} /> ); }; export default HomeTasksDatePicker;