diff --git a/src/components/Chatbot/TaskAdditionConfirmationDialog.tsx b/src/components/Chatbot/TaskAdditionConfirmationDialog.tsx new file mode 100644 index 0000000..2c9e271 --- /dev/null +++ b/src/components/Chatbot/TaskAdditionConfirmationDialog.tsx @@ -0,0 +1,61 @@ +import { ConfirmationDialog } from '@/components/common' + +interface TaskAdditionConfirmationDialogProps { + confirmationOpen: boolean + setConfirmationOpen: (open: boolean) => void + pendingTask: Task | null + confirmAddTask: () => void +} + +const TaskAdditionConfirmationDialog = ({ + confirmationOpen, + setConfirmationOpen, + pendingTask, + confirmAddTask, +}: TaskAdditionConfirmationDialogProps) => { + return ( + setConfirmationOpen(false)} + onConfirm={confirmAddTask} + title="Confirm Task Addition" + description={( + <> + Do you want to add the task + {' '} + {pendingTask?.title} + {' '} + ? +
+ {pendingTask?.category} + {' '} + task with + {' '} + {' '} + {pendingTask?.priority} + {' '} + priority +
+
+ On + {' '} + {pendingTask?.date} +
+ From + {' '} + {pendingTask?.timeRange?.start} + {' '} + to + {' '} + {pendingTask?.timeRange?.end} + + )} + confirmText="Add Task" + cancelText="Cancel" + confirmColor="primary" + maxWidth="sm" + /> + ) +} + +export default TaskAdditionConfirmationDialog diff --git a/src/components/Chatbot/index.tsx b/src/components/Chatbot/index.tsx index 6fe784d..9037c3b 100644 --- a/src/components/Chatbot/index.tsx +++ b/src/components/Chatbot/index.tsx @@ -12,7 +12,7 @@ interface ChatbotProps { } const Chatbot = ({ open, onClose }: ChatbotProps) => { - const { messages, handleSend, isLoading, chatbotError } = useChatbot() + const { messages, handleSend, isLoading, chatbotError, confirmationDialog } = useChatbot() useEffect(() => { if (chatbotError != null) { @@ -26,6 +26,7 @@ const Chatbot = ({ open, onClose }: ChatbotProps) => { + {confirmationDialog} ) } diff --git a/src/components/Home/Calendar/TaskDialog.tsx b/src/components/Home/Calendar/TaskDialog.tsx index 58b8302..2bbecec 100644 --- a/src/components/Home/Calendar/TaskDialog.tsx +++ b/src/components/Home/Calendar/TaskDialog.tsx @@ -1,4 +1,4 @@ -import { SmallLoadingCircle } from '@/components/common' +import { ConfirmationDialog, SmallLoadingCircle } from '@/components/common' import { useScheduleStore } from '@/stores' import EditIcon from '@mui/icons-material/Edit' import { Button, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Typography } from '@mui/material' @@ -17,6 +17,7 @@ const TaskDialog = ({ open, selectedTask, handleClose }: TaskDialogProps) => { const deleteTask = useScheduleStore(state => state.deleteTask) const [loading, setLoading] = useState(false) const [editDialogOpen, toggleEditDialog] = useToggle() + const [deleteConfirmationOpen, toggleDeleteConfirmation] = useToggle() let actualDateTime = dayjs(selectedTask?.date).format('MMMM D, YYYY') if (selectedTask?.timeRange) { @@ -40,8 +41,9 @@ const TaskDialog = ({ open, selectedTask, handleClose }: TaskDialogProps) => { finally { handleClose() setLoading(false) + toggleDeleteConfirmation() } - }, [deleteTask, handleClose, selectedTask]) + }, [deleteTask, handleClose, selectedTask, toggleDeleteConfirmation]) const getRecurrenceText = (pattern: RecurrencePattern): string => { const intervalText = pattern.interval === 1 ? '' : `every ${pattern.interval} ` @@ -109,10 +111,20 @@ const TaskDialog = ({ open, selectedTask, handleClose }: TaskDialogProps) => { - - @@ -128,6 +140,15 @@ const TaskDialog = ({ open, selectedTask, handleClose }: TaskDialogProps) => { action="Edit" currentTask={selectedTask} /> + + ) } diff --git a/src/components/common/ConfirmationDialog.tsx b/src/components/common/ConfirmationDialog.tsx index a60489d..bbe4d04 100644 --- a/src/components/common/ConfirmationDialog.tsx +++ b/src/components/common/ConfirmationDialog.tsx @@ -5,10 +5,11 @@ interface ConfirmationDialogProps { onClose: () => void onConfirm: () => void title: string - description?: string + description?: string | React.ReactNode confirmText?: string cancelText?: string confirmColor?: 'primary' | 'error' + maxWidth?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | false } const ConfirmationDialog = ({ @@ -20,6 +21,7 @@ const ConfirmationDialog = ({ confirmText = 'Confirm', cancelText = 'Cancel', confirmColor = 'error', + maxWidth, }: ConfirmationDialogProps) => { return ( ) } diff --git a/src/components/common/CustomDialog.tsx b/src/components/common/CustomDialog.tsx index dcbd545..a7f1a6c 100644 --- a/src/components/common/CustomDialog.tsx +++ b/src/components/common/CustomDialog.tsx @@ -17,7 +17,7 @@ interface CustomDialogProps { open: boolean onClose: () => void title: string - description?: string + description?: string | React.ReactNode actions?: DialogAction[] // Array of actions for buttons children?: React.ReactNode // Custom content maxWidth?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | false @@ -47,11 +47,15 @@ const CustomDialog = ({ > {title} - {description?.trim() ?? ( - - {description} - - )} + { + typeof description === 'string' + ? description?.trim() ?? ( + + {description} + + ) + : description + } {children} diff --git a/src/hooks/useChatbot.ts b/src/hooks/useChatbot.tsx similarity index 87% rename from src/hooks/useChatbot.ts rename to src/hooks/useChatbot.tsx index 3cd8993..4ec0249 100644 --- a/src/hooks/useChatbot.ts +++ b/src/hooks/useChatbot.tsx @@ -1,8 +1,9 @@ +import TaskAdditionConfirmationDialog from '@/components/Chatbot/TaskAdditionConfirmationDialog' import { useScheduleStore } from '@/stores' import { DEEPSEEK_API_KEY, DEEPSEEK_API_URL, SYSTEM_PROMPT } from '@/utils/chatbotConst' import { auth } from '@/utils/firebase' import { generateUniqueId } from '@zl-asica/react' -import { useCallback, useReducer } from 'react' +import { useCallback, useReducer, useState } from 'react' import { z } from 'zod' const chatbotResponseContentSchema = z.object({ @@ -48,6 +49,8 @@ const useChatbot = () => { const addTask = useScheduleStore(state => state.addTask) const [messages, dispatchMessage] = useReducer(messageReducer, []) const [state, dispatchChatbot] = useReducer(chatbotReducer, { isLoading: false, chatbotError: null }) + const [pendingTask, setPendingTask] = useState(null) + const [confirmationOpen, setConfirmationOpen] = useState(false) const addMessage = useCallback((text: string, sender: 'user' | 'bot') => { dispatchMessage({ @@ -61,6 +64,14 @@ const useChatbot = () => { }) }, []) + const confirmAddTask = async () => { + if (pendingTask) { + await addTask(pendingTask) + setPendingTask(null) + } + setConfirmationOpen(false) + } + const handleSend = useCallback( async (input: string) => { if (!DEEPSEEK_API_KEY) { @@ -166,7 +177,10 @@ const useChatbot = () => { isRecurring: false, recurrencePattern: null, } - await addTask(newTask) + + // Store the task in the state and open the confirmation dialog + setPendingTask(newTask) + setConfirmationOpen(true) } } catch (error_) { @@ -179,7 +193,7 @@ const useChatbot = () => { dispatchChatbot({ type: 'setLoading', payload: false }) } }, - [addMessage, addTask], + [addMessage, setPendingTask, setConfirmationOpen], ) return { @@ -187,6 +201,14 @@ const useChatbot = () => { handleSend, isLoading: state.isLoading, chatbotError: state.chatbotError, + confirmationDialog: ( + + ), } }