feat(task-drawer): integrate socket handling for recurring task updates

Enhance the TaskDrawerRecurringConfig component to include socket communication for handling recurring task changes. This update introduces the use of Redux for managing state updates related to recurring schedules, ensuring real-time synchronization of task configurations. Additionally, the code has been refactored for improved readability and maintainability.
This commit is contained in:
chamikaJ
2025-05-16 12:37:02 +05:30
parent d333104f43
commit ebd0f66768
2 changed files with 275 additions and 216 deletions

View File

@@ -1,13 +1,26 @@
import React, { useState, useMemo, useEffect } from 'react'; import React, { useState, useMemo, useEffect } from 'react';
import { Form, Switch, Button, Popover, Select, Checkbox, Radio, InputNumber, Skeleton, Row, Col } from 'antd'; import {
Form,
Switch,
Button,
Popover,
Select,
Checkbox,
Radio,
InputNumber,
Skeleton,
Row,
Col,
} from 'antd';
import { SettingOutlined } from '@ant-design/icons'; import { SettingOutlined } from '@ant-design/icons';
import { useSocket } from '@/socket/socketContext'; import { useSocket } from '@/socket/socketContext';
import { SocketEvents } from '@/shared/socket-events'; import { SocketEvents } from '@/shared/socket-events';
import { ITaskRecurringScheduleData } from '@/types/tasks/task-recurring-schedule'; import { ITaskRecurringScheduleData } from '@/types/tasks/task-recurring-schedule';
import { ITaskViewModel } from '@/types/tasks/task.types'; import { ITaskViewModel } from '@/types/tasks/task.types';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { updateRecurringChange } from '@/features/tasks/tasks.slice';
// Dummy enums and types for demonstration; replace with actual imports/types
const ITaskRecurring = { const ITaskRecurring = {
Weekly: 'weekly', Weekly: 'weekly',
EveryXDays: 'every_x_days', EveryXDays: 'every_x_days',
@@ -46,6 +59,7 @@ const dayOptions = daysOfWeek.map(d => ({ label: d.label, value: d.value }));
const TaskDrawerRecurringConfig = ({ task }: { task: ITaskViewModel }) => { const TaskDrawerRecurringConfig = ({ task }: { task: ITaskViewModel }) => {
const { socket, connected } = useSocket(); const { socket, connected } = useSocket();
const dispatch = useAppDispatch();
const { t } = useTranslation('task-drawer/task-drawer-recurring-config'); const { t } = useTranslation('task-drawer/task-drawer-recurring-config');
const [recurring, setRecurring] = useState(false); const [recurring, setRecurring] = useState(false);
@@ -63,15 +77,36 @@ const TaskDrawerRecurringConfig = ({ task }: {task: ITaskViewModel}) => {
const [updatingData, setUpdatingData] = useState(false); const [updatingData, setUpdatingData] = useState(false);
const handleChange = (checked: boolean) => { const handleChange = (checked: boolean) => {
if (!task.id) return;
socket?.emit(SocketEvents.TASK_RECURRING_CHANGE.toString(), {
task_id: task.id,
schedule_id: task.schedule_id,
});
socket?.once(
SocketEvents.TASK_RECURRING_CHANGE.toString(),
(schedule: ITaskRecurringScheduleData) => {
if (schedule.id && schedule.schedule_type) {
const selected = repeatOptions.find(e => e.value == schedule.schedule_type);
if (selected) setRepeatOption(selected);
}
dispatch(updateRecurringChange(schedule));
setRecurring(checked); setRecurring(checked);
if (!checked) setShowConfig(false); if (!checked) setShowConfig(false);
}
);
}; };
const configVisibleChange = (visible: boolean) => { const configVisibleChange = (visible: boolean) => {
setShowConfig(visible); setShowConfig(visible);
}; };
const isMonthlySelected = useMemo(() => repeatOption.value === ITaskRecurring.Monthly, [repeatOption]); const isMonthlySelected = useMemo(
() => repeatOption.value === ITaskRecurring.Monthly,
[repeatOption]
);
const handleDayCheckboxChange = (checkedValues: string[]) => { const handleDayCheckboxChange = (checkedValues: string[]) => {
setSelectedDays(checkedValues as unknown as string[]); setSelectedDays(checkedValues as unknown as string[]);
@@ -95,19 +130,17 @@ const TaskDrawerRecurringConfig = ({ task }: {task: ITaskViewModel}) => {
setShowConfig(false); setShowConfig(false);
}; };
const getScheduleData = () => { const getScheduleData = () => {};
};
const handleResponse = (response: ITaskRecurringScheduleData) => { const handleResponse = (response: ITaskRecurringScheduleData) => {
if (!task || !response.task_id) return; if (!task || !response.task_id) return;
} };
useEffect(() => { useEffect(() => {
if (task) setRecurring(!!task.schedule_id); if (task) setRecurring(!!task.schedule_id);
if (recurring) void getScheduleData(); if (recurring) void getScheduleData();
socket?.on(SocketEvents.TASK_RECURRING_CHANGE.toString(), handleResponse) socket?.on(SocketEvents.TASK_RECURRING_CHANGE.toString(), handleResponse);
}, []) }, []);
return ( return (
<div> <div>
@@ -170,7 +203,10 @@ const TaskDrawerRecurringConfig = ({ task }: {task: ITaskViewModel}) => {
<Select <Select
value={selectedMonthlyDate} value={selectedMonthlyDate}
onChange={setSelectedMonthlyDate} onChange={setSelectedMonthlyDate}
options={monthlyDateOptions.map(date => ({ label: date.toString(), value: date }))} options={monthlyDateOptions.map(date => ({
label: date.toString(),
value: date,
}))}
style={{ width: 120 }} style={{ width: 120 }}
/> />
</Form.Item> </Form.Item>
@@ -200,17 +236,29 @@ const TaskDrawerRecurringConfig = ({ task }: {task: ITaskViewModel}) => {
{repeatOption.value === ITaskRecurring.EveryXDays && ( {repeatOption.value === ITaskRecurring.EveryXDays && (
<Form.Item label="Interval (days)"> <Form.Item label="Interval (days)">
<InputNumber min={1} value={intervalDays} onChange={(value) => value && setIntervalDays(value)} /> <InputNumber
min={1}
value={intervalDays}
onChange={value => value && setIntervalDays(value)}
/>
</Form.Item> </Form.Item>
)} )}
{repeatOption.value === ITaskRecurring.EveryXWeeks && ( {repeatOption.value === ITaskRecurring.EveryXWeeks && (
<Form.Item label="Interval (weeks)"> <Form.Item label="Interval (weeks)">
<InputNumber min={1} value={intervalWeeks} onChange={(value) => value && setIntervalWeeks(value)} /> <InputNumber
min={1}
value={intervalWeeks}
onChange={value => value && setIntervalWeeks(value)}
/>
</Form.Item> </Form.Item>
)} )}
{repeatOption.value === ITaskRecurring.EveryXMonths && ( {repeatOption.value === ITaskRecurring.EveryXMonths && (
<Form.Item label="Interval (months)"> <Form.Item label="Interval (months)">
<InputNumber min={1} value={intervalMonths} onChange={(value) => value && setIntervalMonths(value)} /> <InputNumber
min={1}
value={intervalMonths}
onChange={value => value && setIntervalMonths(value)}
/>
</Form.Item> </Form.Item>
)} )}
<Form.Item style={{ marginBottom: 0, textAlign: 'right' }}> <Form.Item style={{ marginBottom: 0, textAlign: 'right' }}>

View File

@@ -22,6 +22,7 @@ import { ITaskPhaseChangeResponse } from '@/types/tasks/task-phase-change-respon
import { produce } from 'immer'; import { produce } from 'immer';
import { tasksCustomColumnsService } from '@/api/tasks/tasks-custom-columns.service'; import { tasksCustomColumnsService } from '@/api/tasks/tasks-custom-columns.service';
import { SocketEvents } from '@/shared/socket-events'; import { SocketEvents } from '@/shared/socket-events';
import { ITaskRecurringScheduleData } from '@/types/tasks/task-recurring-schedule';
export enum IGroupBy { export enum IGroupBy {
STATUS = 'status', STATUS = 'status',
@@ -1006,6 +1007,15 @@ const taskSlice = createSlice({
column.pinned = isVisible; column.pinned = isVisible;
} }
}, },
updateRecurringChange: (state, action: PayloadAction<ITaskRecurringScheduleData>) => {
const {id, schedule_type, task_id} = action.payload;
const taskInfo = findTaskInGroups(state.taskGroups, task_id as string);
if (!taskInfo) return;
const { task } = taskInfo;
task.schedule_id = id;
}
}, },
extraReducers: builder => { extraReducers: builder => {
@@ -1165,6 +1175,7 @@ export const {
updateSubTasks, updateSubTasks,
updateCustomColumnValue, updateCustomColumnValue,
updateCustomColumnPinned, updateCustomColumnPinned,
updateRecurringChange
} = taskSlice.actions; } = taskSlice.actions;
export default taskSlice.reducer; export default taskSlice.reducer;