From 86dca98d04d03539d0868ec46d6f2a47ba9be0aa Mon Sep 17 00:00:00 2001 From: tomtitherington Date: Sat, 28 Oct 2023 13:41:01 +0100 Subject: [PATCH] Add ability to delete project from the project settings page --- .../projects/hooks/useProjectSettings.ts | 34 +++++++++++++++++-- .../projects/pages/ProjectSettings.tsx | 20 +++++++++-- .../projects/stores/useProjectsStore.ts | 2 +- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/frontend/src/features/projects/hooks/useProjectSettings.ts b/frontend/src/features/projects/hooks/useProjectSettings.ts index 7388fdb..aa99563 100644 --- a/frontend/src/features/projects/hooks/useProjectSettings.ts +++ b/frontend/src/features/projects/hooks/useProjectSettings.ts @@ -1,11 +1,21 @@ +import { ProjectsApi, useApiConfig } from 'api'; import { useFormik } from 'formik'; -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; +import { useProjectsStore } from '../stores/useProjectsStore'; +import { useNavigate } from 'react-router'; + interface FormValues { projectName?: string; + //onDelete?: () => void; } -const useSettings = ({ projectName: initialProjectName }: FormValues) => { +const useSettings = ({ projectName: initialProjectName}: FormValues) => { + const [errors, setErrors] = useState([]); + const [loading, setLoading] = useState(false); + const { fetchAndSelectProject } = useProjectsStore(); + const { config } = useApiConfig(); + const navigate = useNavigate(); const formik = useFormik({ initialValues: { @@ -22,14 +32,32 @@ const useSettings = ({ projectName: initialProjectName }: FormValues) => { }); useEffect(() => { - // this is to prevent infinite re-render cycle + // this is to prevent infinite re-render cycle if (formik.values.projectName !== initialProjectName) { formik.setFieldValue('projectName', initialProjectName); } }, [initialProjectName, formik]); + const deleteProject = async (id: string, onDelete?: () => void) => { + setLoading(true); + try { + const response = await new ProjectsApi(config).destroyProject(id); + fetchAndSelectProject(config); + onDelete?.(); + navigate('/flows'); + } catch (error) { + //TODO: Toast + setErrors(['An error occurred']); + } finally { + setLoading(false); + } + }; + return { formik, + loading, + errors, + deleteProject, }; }; diff --git a/frontend/src/features/projects/pages/ProjectSettings.tsx b/frontend/src/features/projects/pages/ProjectSettings.tsx index ff75ec3..68732ec 100644 --- a/frontend/src/features/projects/pages/ProjectSettings.tsx +++ b/frontend/src/features/projects/pages/ProjectSettings.tsx @@ -7,6 +7,8 @@ import { MembersTable } from 'components/tables'; import { useProjectsStore } from 'features/projects/stores/useProjectsStore'; import { MdAdd } from 'react-icons/md'; import useSettings from '../hooks/useProjectSettings'; +import toast from 'react-hot-toast'; +import Toast from 'components/Toast'; const headers = [ { propertyName: 'email', displayName: 'Email' }, @@ -23,7 +25,7 @@ type UserData = { const Settings = () => { const { selectedProject } = useProjectsStore(); //TODO: Can we improve this to just pass in selectedProject as is without a check? - const { formik } = useSettings( + const { formik, deleteProject } = useSettings( selectedProject.state == 'hasData' ? { projectName: selectedProject?.data.name } : { projectName: '' }, @@ -90,9 +92,21 @@ const Settings = () => {

Danger Zone

-

Delete your project and all associated data.

+

+ Delete your project and all associated data. +

- + + await deleteProject(selectedProject.data.id?.toString() ?? '', () => + toast.custom(t => ( + + )), + ) + } + />
); diff --git a/frontend/src/features/projects/stores/useProjectsStore.ts b/frontend/src/features/projects/stores/useProjectsStore.ts index d63033b..4a2e59c 100644 --- a/frontend/src/features/projects/stores/useProjectsStore.ts +++ b/frontend/src/features/projects/stores/useProjectsStore.ts @@ -7,7 +7,7 @@ type ProjectsStore = { projects: ApiState; fetchProjects: (config: Configuration) => void; setSelectedProject: (projectId: number) => void; - fetchAndSelectProject: (config: Configuration) => void; + fetchAndSelectProject: (config: Configuration) => void; createProject: (name: string, config: Configuration) => void; };