diff --git a/src/components/forms/date-picker-select.tsx b/src/components/forms/date-picker-select.tsx index 6c84088..18fedd8 100644 --- a/src/components/forms/date-picker-select.tsx +++ b/src/components/forms/date-picker-select.tsx @@ -10,6 +10,7 @@ type DatePickerSelectProps = { value: Date | undefined isDateDisabled?: (date: Date) => boolean onChange: (date: Date | undefined) => void + disabled: boolean } export const DatePickerSelect = ({ @@ -17,6 +18,7 @@ export const DatePickerSelect = ({ value, onChange, isDateDisabled, + disabled, }: DatePickerSelectProps) => { const [open, setOpen] = React.useState(false) @@ -28,6 +30,7 @@ export const DatePickerSelect = ({ variant="outline" data-selected={value ? 'true' : 'false'} className="w-full justify-between font-normal data-[selected=false]:text-gray-500" + disabled={disabled} > {value ? value.toLocaleDateString() : 'Select date'} @@ -39,6 +42,7 @@ export const DatePickerSelect = ({ selected={value} captionLayout="dropdown" isDateDisabled={isDateDisabled} + disabled={disabled} onSelect={(date) => { onChange(date) setOpen(false) diff --git a/src/components/todos/create-edit-todo-dialog.tsx b/src/components/todos/create-edit-todo-dialog.tsx deleted file mode 100644 index 1ab739c..0000000 --- a/src/components/todos/create-edit-todo-dialog.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { CreateEditTodoForm, TTodoFormData } from '@/components/todos/create-edit-todo-form' -import { - AlertDialog, - AlertDialogContent, - AlertDialogHeader, - AlertDialogTitle, - AlertDialogTrigger, -} from '@/components/ui/alert-dialog' -import { type ReactNode } from 'react' - -type BaseProps = { - open: boolean - children: ReactNode - isMutationPending?: boolean - onSubmit: (data: TTodoFormData) => void - onOpenChange: (open: boolean) => void -} - -type CreateModeProps = BaseProps & { - mode: 'create' - defaultData?: Partial -} - -type EditModeProps = BaseProps & { - mode: 'edit' - defaultData: Partial -} - -type CreateEditTodoDialogProps = CreateModeProps | EditModeProps - -export const CreateEditTodoDialog = ({ - mode, - open, - children, - onSubmit, - defaultData, - onOpenChange, - isMutationPending, -}: CreateEditTodoDialogProps) => { - return ( - - {children} - - - - - {mode === 'create' ? 'Create Todo' : 'Edit Todo'} - - - - onOpenChange(false)} - /> - - - ) -} diff --git a/src/components/todos/create-todo-button.tsx b/src/components/todos/create-todo-button.tsx index b5ea777..c00e69a 100644 --- a/src/components/todos/create-todo-button.tsx +++ b/src/components/todos/create-todo-button.tsx @@ -1,13 +1,13 @@ import { USER_TYPE_ENUM } from '@/api/common/common-enum' import { TasksApi } from '@/api/tasks/tasks.api' import { TeamsApi } from '@/api/teams/teams.api' -import { CreateEditTodoDialog } from '@/components/todos/create-edit-todo-dialog' +import { TodoDialog } from '@/components/todos/todo-dialog' import { Button } from '@/components/ui/button' import { useMutation, useQueryClient } from '@tanstack/react-query' import { PlusIcon } from 'lucide-react' import { useState } from 'react' import { toast } from 'sonner' -import { TTodoFormData } from './create-edit-todo-form' +import { TTodoFormData } from './todo-form' type Props = { defaultData?: Partial @@ -47,7 +47,7 @@ export const CreateTodoButton = ({ defaultData, teamId }: Props) => { }) return ( - { Create Todo - + ) } diff --git a/src/components/todos/deferred-task-button.tsx b/src/components/todos/deferred-task-button.tsx index 8ce401a..2b5ea42 100644 --- a/src/components/todos/deferred-task-button.tsx +++ b/src/components/todos/deferred-task-button.tsx @@ -14,15 +14,16 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' import { useMemo, useState } from 'react' import { toast } from 'sonner' import { DatePickerSelect } from '../forms/date-picker-select' -import { TTodoFormData } from './create-edit-todo-form' +import { TTodoFormData } from './todo-form' type DeferredTaskButtonProps = { todo: Partial open: boolean setOpen: (open: boolean) => void + disabled: boolean } -export const DeferredTaskButton = ({ todo, open, setOpen }: DeferredTaskButtonProps) => { +export const DeferredTaskButton = ({ todo, open, setOpen, disabled }: DeferredTaskButtonProps) => { const [deferredTill, setDeferredTill] = useState() const queryClient = useQueryClient() @@ -80,6 +81,7 @@ export const DeferredTaskButton = ({ todo, open, setOpen }: DeferredTaskButtonPr value={deferredTill} onChange={setDeferredTill} isDateDisabled={(date) => !isDateValidForDefer(date, todo.dueDate)} + disabled={disabled} /> diff --git a/src/components/todos/edit-task-button.tsx b/src/components/todos/edit-task-button.tsx index 18c8456..81aa269 100644 --- a/src/components/todos/edit-task-button.tsx +++ b/src/components/todos/edit-task-button.tsx @@ -1,15 +1,12 @@ -import { USER_TYPE_ENUM } from '@/api/common/common-enum' -import { TasksApi } from '@/api/tasks/tasks.api' import { TTask } from '@/api/tasks/tasks.types' +import { useUpdateTask } from '@/hooks/useUpdateTask' import { TodoUtil } from '@/lib/todo-util' -import { useMutation, useQueryClient } from '@tanstack/react-query' import { Edit2 } from 'lucide-react' import { useState } from 'react' -import { toast } from 'sonner' -import { CreateEditTodoDialog } from './create-edit-todo-dialog' -import { TTodoFormData } from './create-edit-todo-form' import { Button } from '../ui/button' import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip' +import { TodoDialog } from './todo-dialog' +import { TTodoFormData } from './todo-form' type EditTodoButtonProps = { todo: TTask @@ -17,56 +14,26 @@ type EditTodoButtonProps = { } export const EditTodoButton = ({ todo, teamId }: EditTodoButtonProps) => { - const queryClient = useQueryClient() - const [showEditTaskForm, setShowEditTaskForm] = useState(false) - const updateTaskMutation = useMutation({ - mutationFn: TasksApi.updateTask.fn, - onSuccess: (res) => { - void queryClient.invalidateQueries({ queryKey: TasksApi.getTasks.key() }) - void queryClient.invalidateQueries({ queryKey: TasksApi.getWatchListTasks.key }) - void queryClient.invalidateQueries({ - queryKey: TasksApi.getTasks.key({ status: 'DEFERRED' }), - }) - - if (res.assignee?.user_type === USER_TYPE_ENUM.TEAM) { - void queryClient.invalidateQueries({ - queryKey: TasksApi.getTasks.key({ teamId: res.assignee.assignee_id }), - }) - } - - // invalidate a task on the teams page if the task edited - if (teamId) { - void queryClient.invalidateQueries({ queryKey: TasksApi.getTasks.key({ teamId }) }) - } - - toast.success('Todo updated successfully') - setShowEditTaskForm(false) - }, - onError: () => { - toast.error('Failed to update todo, please try again') - }, + const { mutation, handleSubmission } = useUpdateTask({ + todo, + teamId, }) - const handleSubmission = async (todoDetails: TTodoFormData) => { - const updateDetails = TodoUtil.getUpdateTodoDetails(todoDetails, todo) - - if (Object.keys(updateDetails).length > 0) { - updateTaskMutation.mutate({ - id: todo.id, - ...updateDetails, - }) - } + const handleSubmit = (todoDetails: TTodoFormData) => { + handleSubmission(todoDetails, () => { + setShowEditTaskForm(false) + }) } return ( - @@ -82,6 +49,6 @@ export const EditTodoButton = ({ todo, teamId }: EditTodoButtonProps) => { Edit Todo - + ) } diff --git a/src/components/todos/todo-dialog.tsx b/src/components/todos/todo-dialog.tsx new file mode 100644 index 0000000..eef1f78 --- /dev/null +++ b/src/components/todos/todo-dialog.tsx @@ -0,0 +1,86 @@ +import { TodoForm, TTodoFormData } from '@/components/todos/todo-form' +import { + AlertDialog, + AlertDialogContent, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger, +} from '@/components/ui/alert-dialog' +import { type ReactNode } from 'react' + +type BaseProps = { + open: boolean + children: ReactNode + onOpenChange: (open: boolean) => void +} + +type CreateModeProps = BaseProps & { + mode: 'create' + defaultData?: Partial + onSubmit: (data: TTodoFormData) => void + isMutationPending?: boolean +} + +type EditModeProps = BaseProps & { + mode: 'edit' + defaultData: Partial + onSubmit: (data: TTodoFormData) => void + isMutationPending?: boolean +} + +type ViewModeProps = BaseProps & { + mode: 'view' + defaultData: Partial + onSubmit?: undefined + isMutationPending?: undefined +} + +export type TodoDialogProps = CreateModeProps | EditModeProps | ViewModeProps + +export type DialogMode = TodoDialogProps['mode'] + +const TITLE_BY_MODE: Record = { + create: 'Create Todo', + edit: 'Edit Todo', + view: 'View Todo', +} + +export const TodoDialog = ({ + mode, + open, + children, + defaultData, + onOpenChange, + onSubmit, + isMutationPending, +}: TodoDialogProps) => { + return ( + + {children} + + + + {TITLE_BY_MODE[mode]} + + + {mode === 'view' ? ( + onOpenChange(false)} + disabled={true} + /> + ) : ( + onOpenChange(false)} + disabled={false} + onSubmit={onSubmit} + isSubmitting={isMutationPending} + /> + )} + + + ) +} diff --git a/src/components/todos/create-edit-todo-form.tsx b/src/components/todos/todo-form.tsx similarity index 91% rename from src/components/todos/create-edit-todo-form.tsx rename to src/components/todos/todo-form.tsx index 733ec7b..9d66554 100644 --- a/src/components/todos/create-edit-todo-form.tsx +++ b/src/components/todos/todo-form.tsx @@ -103,21 +103,35 @@ const SubmitButton = ({ text, isLoading, isDisabled, watch }: SubmitButtonProps) ) } -type CreateEditTodoFormProps = { - isSubmitting?: boolean - mode?: 'create' | 'edit' +type BaseFormProps = { initialData?: Partial onCancel: () => void + mode?: 'create' | 'edit' | 'view' + disabled: boolean +} + +type CreateEditTodoFormProps = BaseFormProps & { + disabled: false onSubmit: (data: TTodoFormData) => void + isSubmitting?: boolean } -export const CreateEditTodoForm = ({ +type ViewTodoFormProps = BaseFormProps & { + disabled: true + onSubmit?: undefined + isSubmitting?: undefined +} + +type TodoFormProps = CreateEditTodoFormProps | ViewTodoFormProps + +export const TodoForm = ({ onCancel, - onSubmit, initialData, - isSubmitting, mode = 'create', -}: CreateEditTodoFormProps) => { + disabled, + onSubmit, + isSubmitting, +}: TodoFormProps) => { const { control, register, @@ -142,6 +156,7 @@ export const CreateEditTodoForm = ({ const [deferModalOpen, setDeferModalOpen] = useState(false) const handleFormSubmit = (data: TTodoFormData) => { + if (disabled) return onSubmit(data) } @@ -166,6 +181,7 @@ export const CreateEditTodoForm = ({ type="text" placeholder="e.g Cool new title for my todo" {...register('title')} + disabled={disabled} /> @@ -181,6 +197,7 @@ export const CreateEditTodoForm = ({ placeholder="e.g Nothing is cool in here" className="break-word max-h-32" {...register('description')} + disabled={disabled} /> @@ -200,6 +217,7 @@ export const CreateEditTodoForm = ({ value={field.value} placeholder="Select assignee" onChange={(selectedOption) => field.onChange(selectedOption)} + disabled={disabled} /> )} @@ -227,6 +245,7 @@ export const CreateEditTodoForm = ({ isDateDisabled={(date) => isPastDate(date)} value={field.value ? new Date(field.value) : undefined} onChange={(date) => field.onChange(date?.toISOString())} + disabled={disabled} /> @@ -247,6 +266,7 @@ export const CreateEditTodoForm = ({