Skip to content

Commit

Permalink
Add confirmation modal before deleting a task status (#3309)
Browse files Browse the repository at this point in the history
* add confirmation modal before deleteing a task status if used

* update the status to 'open' after deleting a used status
  • Loading branch information
CREDO23 authored Nov 14, 2024
1 parent 3b1c019 commit fb2c1a6
Show file tree
Hide file tree
Showing 15 changed files with 159 additions and 3 deletions.
100 changes: 100 additions & 0 deletions apps/web/lib/features/task-status/delete-status-confirmation-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { ITaskStatusItemList, TaskStatusEnum } from '@/app/interfaces';
import { useTaskStatus, useTeamTasks } from '@app/hooks';
import { Button, Card, Modal, Text } from 'lib/components';
import { useTranslations } from 'next-intl';
import { useCallback, useMemo } from 'react';

interface DeleteTaskStatusModalProps {
open: boolean;
closeModal: () => void;
status: ITaskStatusItemList;
onCancel: () => void;
}

/**
* A confirmation modal before deleting a status that is used by at least one task in the team.
*
* @param {Object} props - The props Object
* @param {boolean} props.open - If true open the modal otherwise close the modal
* @param {() => void} props.closeModal - A function to close the modal
* @param {ITaskStatusItemList} props.status - The status object to be deleted
* @param {() => void} props.onCancel - Callback function when deletion is cancelled
*
* @returns {JSX.Element} The modal element
*/
export function DeleteTaskStatusConfirmationModal(props: DeleteTaskStatusModalProps) {
const { closeModal, open, status, onCancel } = props;
const { deleteTaskStatus, deleteTaskStatusLoading } = useTaskStatus();
const t = useTranslations();
const { tasks, updateTask } = useTeamTasks();

// Filter tasks that are using the current status
const tasksUsingStatus = useMemo(() => tasks.filter((task) => task.status === status.name), [tasks, status.name]);

const handleCloseModal = useCallback(() => {
onCancel();
closeModal();
}, [closeModal, onCancel]);

// Function to handle task status deletion
const handleDeleteTaskStatus = useCallback(async () => {
if (!status.id) {
console.error('Status ID is not provided.');
return;
}

try {
// Update each task that uses the current status
const updatePromises = tasksUsingStatus.map((task) => updateTask({ ...task, status: TaskStatusEnum.OPEN }));

await Promise.all(updatePromises);

// Delete the task status after updating related tasks
await deleteTaskStatus(status.id);
} catch (error) {
console.error('Error while deleting task status:', error);
} finally {
handleCloseModal();
}
}, [deleteTaskStatus, handleCloseModal, status, tasksUsingStatus, updateTask]);

return (
<Modal
isOpen={open}
closeModal={closeModal}
className="w-[98%] md:w-[530px] relative"
showCloseIcon={false}
aria-labelledby="delete-status-modal-title"
aria-describedby="delete-status-modal-description"
>
<Card className="w-full" shadow="custom">
<div className="w-full flex flex-col justify-between gap-6">
<Text.Heading as="h5" id="delete-status-modal-title" className="mb-3 text-center">
{t('pages.taskStatus.DELETE_STATUS_CONFIRMATION', { statusName: status.name })}
</Text.Heading>
<div className="w-full flex items-center justify-evenly">
<Button
disabled={deleteTaskStatusLoading}
variant="outline"
type="button"
onClick={handleCloseModal}
className="rounded-md font-light text-md dark:text-white dark:bg-slate-700 dark:border-slate-600"
>
{t('common.NO')}
</Button>
<Button
loading={deleteTaskStatusLoading}
disabled={deleteTaskStatusLoading}
onClick={handleDeleteTaskStatus}
variant="primary"
type="submit"
className=" rounded-md font-light text-md dark:text-white"
>
{t('common.YES')}
</Button>
</div>
</div>
</Card>
</Modal>
);
}
23 changes: 20 additions & 3 deletions apps/web/lib/settings/task-statuses-form.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable no-mixed-spaces-and-tabs */
import { useModal, useRefetchData, useTaskStatus } from '@app/hooks';
import { useModal, useRefetchData, useTaskStatus, useTeamTasks } from '@app/hooks';
import { IIcon, ITaskStatusItemList } from '@app/interfaces';
import { userState } from '@app/stores';
import { clsxm } from '@app/utils';
Expand All @@ -15,6 +15,7 @@ import IconPopover from './icon-popover';
import { StatusesListCard } from './list-card';
import SortTasksStatusSettings from '@components/pages/kanban/sort-tasks-status-settings';
import { StandardTaskStatusDropDown } from 'lib/features';
import { DeleteTaskStatusConfirmationModal } from '../features/task-status/delete-status-confirmation-modal';

type StatusForm = {
formOnly?: boolean;
Expand Down Expand Up @@ -152,6 +153,9 @@ export const TaskStatusesForm = ({
? updateArray.sort((a: any, b: any) => a.order - b.order)
: [];
const { isOpen, closeModal, openModal } = useModal();
const {isOpen : isDeleteConfirmationOpen , closeModal : closeDeleteConfirmationModal, openModal : openDeleteConfirmationModal} = useModal()
const [statusToDelete, setStatusToDelete] = useState<ITaskStatusItemList | null>(null)
const {tasks} = useTeamTasks()

return (
<>
Expand Down Expand Up @@ -282,8 +286,20 @@ export const TaskStatusesForm = ({
setCreateNew(false);
setEdit(status);
}}
onDelete={() => {
deleteTaskStatus(status.id);
onDelete={async () => {
try {
const isStatusUsed = tasks.find(
(t) => t.status?.toLowerCase() === status.name?.toLowerCase()
);
if (isStatusUsed) {
setStatusToDelete(status);
openDeleteConfirmationModal();
} else {
await deleteTaskStatus(status.id);
}
} catch (error) {
console.error(error);
}
}}
isStatus={true}
/>
Expand All @@ -298,6 +314,7 @@ export const TaskStatusesForm = ({
</div>
</div>
</form>
{statusToDelete && <DeleteTaskStatusConfirmationModal onCancel={() => setStatusToDelete(null)} status={statusToDelete} open={isDeleteConfirmationOpen} closeModal={closeDeleteConfirmationModal}/>}
</>
);
};
3 changes: 3 additions & 0 deletions apps/web/locales/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@
"TASK_IS_ALREADY_EPIC": "لا يمكن تغيير نوع المهمة الملحمية.",
"TASK_HAS_PARENT": "لا يمكن تغيير نوع المهمة حيث أن لديها بالفعل والد."
},
"taskStatus": {
"DELETE_STATUS_CONFIRMATION": "أنت على وشك حذف الحالة {statusName} التي يتم استخدامها من قبل المهام النشطة؛ يرجى تأكيد الإجراء"
},
"auth": {
"SEND_CODE": "إرسال الرمز",
"RESEND_CODE": "إعادة إرسال الرمز",
Expand Down
3 changes: 3 additions & 0 deletions apps/web/locales/bg.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@
"TASK_IS_ALREADY_EPIC": "Епичният тип задача не може да бъде променен.",
"TASK_HAS_PARENT": "Типът задача не може да бъде променен, тъй като задачата вече има родител."
},
"taskStatus": {
"DELETE_STATUS_CONFIRMATION": "Вие сте на път да изтриете състоянието {statusName}, което се използва от активни задачи; моля, потвърдете действието"
},
"auth": {
"SEND_CODE": "изпрати код",
"RESEND_CODE": "Изпрати код отново",
Expand Down
3 changes: 3 additions & 0 deletions apps/web/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@
"TASK_IS_ALREADY_EPIC": "Epische Aufgabentypen können nicht geändert werden.",
"TASK_HAS_PARENT": "Der Aufgabentyp kann nicht geändert werden, da die Aufgabe bereits ein übergeordnetes Element hat."
},
"taskStatus": {
"DELETE_STATUS_CONFIRMATION": "Sie sind dabei, den Status {statusName} zu löschen, der von aktiven Aufgaben verwendet wird; bitte bestätigen Sie die Aktion"
},
"auth": {
"SEND_CODE": "Code senden",
"RESEND_CODE": "Code erneut senden",
Expand Down
3 changes: 3 additions & 0 deletions apps/web/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@
"TASK_IS_ALREADY_EPIC": "Epic Task Type can not be changed.",
"TASK_HAS_PARENT": "Task Type can not be changed as Task has already Parent."
},
"taskStatus": {
"DELETE_STATUS_CONFIRMATION": "You are about to Delete the Status {statusName} that is used by active tasks; please confirm action"
},
"auth": {
"SEND_CODE": "send code",
"RESEND_CODE": "Resend Code",
Expand Down
3 changes: 3 additions & 0 deletions apps/web/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@
"TASK_IS_ALREADY_EPIC": "La tarea de tipo Épico no se puede cambiar.",
"TASK_HAS_PARENT": "El tipo de tarea no se puede cambiar porque la tarea ya tiene un padre."
},
"taskStatus": {
"DELETE_STATUS_CONFIRMATION": "Está a punto de eliminar el estado {statusName} que está siendo utilizado por tareas activas; por favor confirme la acción"
},
"auth": {
"SEND_CODE": "enviar código",
"RESEND_CODE": "Reenviar código",
Expand Down
3 changes: 3 additions & 0 deletions apps/web/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@
"TASK_IS_ALREADY_EPIC": "Le type de tâche épique ne peut pas être modifié.",
"TASK_HAS_PARENT": "Le type de tâche ne peut pas être modifié car la tâche a déjà un parent."
},
"taskStatus": {
"DELETE_STATUS_CONFIRMATION": "Vous êtes sur le point de supprimer le statut {statusName} qui est utilisé par des tâches actives ; veuillez confirmer l'action"
},
"auth": {
"SEND_CODE": "envoyer le code",
"RESEND_CODE": "Renvoyer le code",
Expand Down
3 changes: 3 additions & 0 deletions apps/web/locales/he.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@
"TASK_IS_ALREADY_EPIC": "לא ניתן לשנות סוג משימה אפית.",
"TASK_HAS_PARENT": "לא ניתן לשנות סוג משימה מכיוון שלמשימה כבר יש הורה."
},
"taskStatus": {
"DELETE_STATUS_CONFIRMATION": "אתה עומד למחוק את המצב {statusName} המשמש במשימות פעילות; נא לאשר פעולה"
},
"auth": {
"SEND_CODE": "שלח קוד",
"RESEND_CODE": "שלח קוד מחדש",
Expand Down
3 changes: 3 additions & 0 deletions apps/web/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@
"TASK_IS_ALREADY_EPIC": "Il tipo di Compito Epico non può essere cambiato.",
"TASK_HAS_PARENT": "Il tipo di Compito non può essere cambiato poiché il Compito ha già un Genitore."
},
"taskStatus": {
"DELETE_STATUS_CONFIRMATION": "Stai per eliminare lo stato {statusName} utilizzato da attività attive; per favore conferma l'azione"
},
"auth": {
"SEND_CODE": "Invia Codice",
"RESEND_CODE": "Reinvia Codice",
Expand Down
3 changes: 3 additions & 0 deletions apps/web/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@
"TASK_IS_ALREADY_EPIC": "Epic taaktype kan niet worden gewijzigd.",
"TASK_HAS_PARENT": "Taaktype kan niet worden gewijzigd omdat de taak al een bovenliggende taak heeft."
},
"taskStatus": {
"DELETE_STATUS_CONFIRMATION": "U staat op het punt de status {statusName} te verwijderen die wordt gebruikt door actieve taken; bevestig alstublieft de actie"
},
"auth": {
"SEND_CODE": "code verzenden",
"RESEND_CODE": "Code opnieuw verzenden",
Expand Down
3 changes: 3 additions & 0 deletions apps/web/locales/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@
"TASK_IS_ALREADY_EPIC": "Typ Zadania jako 'Epic' nie może zostać zmieniony.",
"TASK_HAS_PARENT": "Typ Zadania nie może zostać zmieniony, ponieważ Zadanie ma już przypisanego rodzica."
},
"taskStatus": {
"DELETE_STATUS_CONFIRMATION": "Zaraz usuniesz status {statusName}, który jest używany przez aktywne zadania; proszę potwierdzić akcję"
},
"auth": {
"SEND_CODE": "wyślij kod",
"RESEND_CODE": "Wyślij ponownie kod",
Expand Down
3 changes: 3 additions & 0 deletions apps/web/locales/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@
"TASK_IS_ALREADY_EPIC": "O Tipo de Tarefa Épica não pode ser alterado.",
"TASK_HAS_PARENT": "O Tipo de Tarefa não pode ser alterado, pois a Tarefa já possui um Pai."
},
"taskStatus": {
"DELETE_STATUS_CONFIRMATION": "Está prestes a eliminar o status {statusName} que está a ser usado por tarefas ativas; por favor, confirme a ação"
},
"auth": {
"SEND_CODE": "enviar código",
"RESEND_CODE": "Reenviar Código",
Expand Down
3 changes: 3 additions & 0 deletions apps/web/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@
"TASK_IS_ALREADY_EPIC": "Тип задачи 'Epic' не может быть изменен.",
"TASK_HAS_PARENT": "Тип задачи не может быть изменен, так как у задачи уже есть родитель."
},
"taskStatus": {
"DELETE_STATUS_CONFIRMATION": "Вы собираетесь удалить статус {statusName}, который используется активными задачами; пожалуйста, подтвердите действие"
},
"auth": {
"SEND_CODE": "отправить код",
"RESEND_CODE": "Отправить код повторно",
Expand Down
3 changes: 3 additions & 0 deletions apps/web/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@
"TASK_IS_ALREADY_EPIC": "史诗类型任务无法更改。",
"TASK_HAS_PARENT": "任务已有父任务,无法更改任务类型。"
},
"taskStatus": {
"DELETE_STATUS_CONFIRMATION": "您即将删除正在被活跃任务使用的状态 {statusName};请确认操作"
},
"auth": {
"SEND_CODE": "发送验证码",
"RESEND_CODE": "重新发送验证码",
Expand Down

0 comments on commit fb2c1a6

Please sign in to comment.