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:
@@ -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' }}>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user