import { useTranslation } from 'next-i18next' import { FunctionComponent, useEffect, useState } from 'react' import { toast } from 'react-toastify' import { deleteAccount } from '../../context/actions' import { useUserDispatch } from '../../context/user-info' import { USER_DELETION_URL } from '../../env' import Button from '../Button' import ConfirmDialog from '../ConfirmDialog' import Spinner from '../Spinner' /** * Performs a GET request to the API to initiate user deletion. * @param waiting Function to set the async state of the component * @param error Function for displaying errors (usually component state) * @param success Callback accepting the deletion token on success */ async function requestDeletion( waiting: (a: boolean) => void, error: (msg_id: string) => void, success: (token: string) => void, ) { waiting(true) let res: Response try { res = await fetch(USER_DELETION_URL, { credentials: 'include' }) } catch { error('network-error-try-again') return } finally { waiting(false) } if (res.ok) { const data = await res.json() if (data.status == 'ok') { success(data.token) } else { error(data.message) } } else { error('network-error-try-again') } } const DeleteButton: FunctionComponent = () => { const { t } = useTranslation() // Using state to prevent user repeatedly initating fetches const [clicked, setClicked] = useState(false) const [waiting, setWaiting] = useState(false) const [token, setToken] = useState('') const dispatch = useUserDispatch() // Only make a request on first click useEffect(() => { if (clicked) { requestDeletion( setWaiting, msg_id => { toast.error(t(msg_id)); setClicked(false); }, setToken ) } }, [dispatch, clicked, t]) if (waiting) { return <Spinner size={30} /> } if (token) { // Callbacks must clear the token to hide the dialog return <ConfirmDialog prompt='Delete your account?' entry='I wish to delete my account' action={t('delete-account')} onConfirmed={() => { setWaiting(true) deleteAccount(dispatch, token) .catch(err => { toast.error(t(err)) setClicked(false) }) .finally(() => { setWaiting(false) }) setToken('') }} onCancelled={() => { // Hide dialog and allow reuse of button setToken('') setClicked(false) }} /> } return ( <Button onClick={() => setClicked(true)} type='secondary'> {t('delete-account')} </Button> ) } export default DeleteButton