import { FC, useEffect, useState } from 'react' import { useRouter } from 'next/router' import { Button, Input } from 'ui' import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useStore, checkPermissions } from 'hooks' import { API_URL, PRICING_TIER_PRODUCT_IDS } from 'lib/constants' import { delete_, post } from 'lib/common/fetch' import TextConfirmModal from 'components/ui/Modals/TextConfirmModal' import { CANCELLATION_REASONS } from 'components/interfaces/Billing/Billing.constants' interface Props { type?: 'danger' | 'default' } const DeleteProjectButton: FC = ({ type = 'danger' }) => { const router = useRouter() const { app, ui } = useStore() const project = ui.selectedProject const projectRef = project?.ref const projectTier = project?.subscription_tier ?? PRICING_TIER_PRODUCT_IDS.FREE const isFree = projectTier === PRICING_TIER_PRODUCT_IDS.FREE const [isOpen, setIsOpen] = useState(false) const [loading, setLoading] = useState(false) const [selectedReasons, setSelectedReasons] = useState([]) const [cancellationMessage, setCancellationMessage] = useState('') useEffect(() => { if (isOpen) { setSelectedReasons([]) setCancellationMessage('') } }, [isOpen]) const canDeleteProject = checkPermissions(PermissionAction.UPDATE, 'projects') const toggle = () => { if (loading) return setIsOpen(!isOpen) } const onSelectCancellationReason = (reason: string) => { const existingSelection = selectedReasons.find((x) => x === reason) const updatedSelection = existingSelection === undefined ? selectedReasons.concat([reason]) : selectedReasons.filter((x) => x !== reason) setSelectedReasons(updatedSelection) } async function handleDeleteProject() { if (project === undefined) return if (!isFree && selectedReasons.length === 0) { return ui.setNotification({ category: 'error', duration: 4000, message: 'Please select at least one reason for deleting your project', }) } setLoading(true) try { const response = await delete_(`${API_URL}/projects/${projectRef}`) if (response.error) throw response.error app.onProjectDeleted(response) ui.setNotification({ category: 'success', message: `Successfully deleted ${project.name}` }) router.push(`/projects`) } catch (error: any) { setLoading(false) ui.setNotification({ category: 'error', message: `Failed to delete project ${project.name}: ${error.message}`, }) } // Submit exit survey to Hubspot for paid projects if (!isFree) { const feedbackRes = await post(`${API_URL}/feedback/downgrade`, { projectRef, reasons: selectedReasons.reduce((a, b) => `${a}- ${b}\n`, ''), additionalFeedback: cancellationMessage, exitAction: 'delete', }) if (feedbackRes.error) throw feedbackRes.error } } return ( <> {!canDeleteProject && (
You need additional permissions to delete this project
)}
{/* [Joshen] This is basically ExitSurvey.tsx, ideally we have one shared component but the one in ExitSurvey has a Form wrapped around it already. Will probably need some effort to refactor but leaving that for the future. */} {!isFree && ( <>

We're sad that you're leaving.

We always strive to improve Supabase as much as we can. Please let us know the reasons you are deleting your project so that we can improve in the future.

{CANCELLATION_REASONS.map((option) => { const active = selectedReasons.find((x) => x === option) return ( ) })}
setCancellationMessage(event.target.value)} />
)}
) } export default DeleteProjectButton