mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-31 04:59:50 +02:00
Add account deletion functionality (#4153)
* chore: delete account * Add account deletion functionality --------- Co-authored-by: Kamran Ahmed <kamranahmed.se@gmail.com>
This commit is contained in:
1843
pnpm-lock.yaml
generated
1843
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -40,12 +40,12 @@ const sidebarLinks = [
|
||||
},
|
||||
},
|
||||
{
|
||||
href: '/account/update-password',
|
||||
title: 'Security',
|
||||
id: 'change-password',
|
||||
href: '/account/settings',
|
||||
title: 'Settings',
|
||||
id: 'settings',
|
||||
isNew: false,
|
||||
icon: {
|
||||
glyph: 'security',
|
||||
glyph: 'cog',
|
||||
classes: 'h-4 w-4',
|
||||
},
|
||||
},
|
||||
|
@@ -33,7 +33,7 @@ function showHideGuestElements(hideOrShow: 'hide' | 'show' = 'hide') {
|
||||
function handleGuest() {
|
||||
const authenticatedRoutes = [
|
||||
'/account/update-profile',
|
||||
'/account/update-password',
|
||||
'/account/settings',
|
||||
'/account/road-card',
|
||||
'/account',
|
||||
];
|
||||
|
16
src/components/DeleteAccount/DeleteAccount.astro
Normal file
16
src/components/DeleteAccount/DeleteAccount.astro
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
import DeleteAccountPopup from "./DeleteAccountPopup.astro";
|
||||
---
|
||||
<DeleteAccountPopup />
|
||||
|
||||
<h2 class='text-xl font-bold sm:text-2xl'>Delete Account</h2>
|
||||
<p class='mt-2 text-gray-400'>
|
||||
Permanently remove your account from the roadmap.sh. This cannot be undone and all your progress and data will be lost.
|
||||
</p>
|
||||
|
||||
<button
|
||||
data-popup='delete-account-popup'
|
||||
class="mt-4 w-full rounded-lg bg-red-600 py-2 text-base font-regular text-white outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-1"
|
||||
>
|
||||
Delete Account
|
||||
</button>
|
89
src/components/DeleteAccount/DeleteAccountForm.tsx
Normal file
89
src/components/DeleteAccount/DeleteAccountForm.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import {useEffect, useState} from 'preact/hooks';
|
||||
import { httpDelete } from '../../lib/http';
|
||||
import { logout } from '../Navigation/navigation';
|
||||
|
||||
export function DeleteAccountForm() {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
const [confirmationText, setConfirmationText] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
setError('');
|
||||
setConfirmationText('');
|
||||
}, [])
|
||||
|
||||
const handleSubmit = async (e: Event) => {
|
||||
e.preventDefault();
|
||||
setIsLoading(true);
|
||||
setError('');
|
||||
|
||||
if (confirmationText.toUpperCase() !== 'DELETE') {
|
||||
setError('Verification text does not match');
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const { response, error } = await httpDelete(
|
||||
`${import.meta.env.PUBLIC_API_URL}/v1-delete-account`
|
||||
);
|
||||
|
||||
if (error || !response) {
|
||||
setIsLoading(false);
|
||||
setError(error?.message || 'Something went wrong');
|
||||
return;
|
||||
}
|
||||
|
||||
logout();
|
||||
};
|
||||
|
||||
const handleClosePopup = () => {
|
||||
setIsLoading(false);
|
||||
setError('');
|
||||
setConfirmationText('');
|
||||
|
||||
const deleteAccountPopup = document.getElementById('delete-account-popup');
|
||||
deleteAccountPopup?.classList.add('hidden');
|
||||
deleteAccountPopup?.classList.remove('flex');
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="my-4">
|
||||
<input
|
||||
type="text"
|
||||
name="delete-account"
|
||||
id="delete-account"
|
||||
className="mt-2 block w-full rounded-md border border-gray-300 py-2 px-3 outline-none placeholder:text-gray-400 focus:border-gray-400"
|
||||
placeholder={'Type "delete" to confirm'}
|
||||
required
|
||||
autoFocus
|
||||
value={confirmationText}
|
||||
onInput={(e) =>
|
||||
setConfirmationText((e.target as HTMLInputElement).value)
|
||||
}
|
||||
/>
|
||||
{error && (
|
||||
<p className="mt-2 rounded-lg bg-red-100 p-2 text-red-700">{error}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
disabled={isLoading}
|
||||
onClick={handleClosePopup}
|
||||
className="flex-grow cursor-pointer rounded-lg bg-gray-200 py-2 text-center"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isLoading || confirmationText.toUpperCase() !== 'DELETE'}
|
||||
className="flex-grow cursor-pointer rounded-lg bg-red-500 py-2 text-white disabled:opacity-40"
|
||||
>
|
||||
{isLoading ? 'Please wait ..' : 'Confirm'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
17
src/components/DeleteAccount/DeleteAccountPopup.astro
Normal file
17
src/components/DeleteAccount/DeleteAccountPopup.astro
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
import Popup from '../Popup/Popup.astro';
|
||||
import { DeleteAccountForm } from './DeleteAccountForm';
|
||||
---
|
||||
|
||||
<Popup id='delete-account-popup' title='Delete Account' subtitle=''>
|
||||
<div class='-mt-2.5'>
|
||||
<p>
|
||||
This will permanently delete your account and all your associated data
|
||||
including your progress.
|
||||
</p>
|
||||
|
||||
<p class="text-black font-medium -mb-2 mt-3 text-base">Please type "delete" to confirm.</p>
|
||||
|
||||
<DeleteAccountForm client:only />
|
||||
</div>
|
||||
</Popup>
|
4
src/icons/cog.svg
Normal file
4
src/icons/cog.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
@@ -2,15 +2,18 @@
|
||||
import AccountSidebar from '../../components/AccountSidebar.astro';
|
||||
import UpdatePasswordForm from '../../components/UpdatePassword/UpdatePasswordForm';
|
||||
import AccountLayout from '../../layouts/AccountLayout.astro';
|
||||
import DeleteAccount from '../../components/DeleteAccount/DeleteAccount.astro';
|
||||
---
|
||||
|
||||
<AccountLayout
|
||||
title='Change Password'
|
||||
title='Settings'
|
||||
description=''
|
||||
noIndex={true}
|
||||
initialLoadingMessage={'Loading profile'}
|
||||
initialLoadingMessage={'Loading settings'}
|
||||
>
|
||||
<AccountSidebar activePageId='change-password' activePageTitle='Change Password'>
|
||||
<AccountSidebar activePageId='settings' activePageTitle='Settings'>
|
||||
<UpdatePasswordForm client:load />
|
||||
<hr class='my-8' />
|
||||
<DeleteAccount />
|
||||
</AccountSidebar>
|
||||
</AccountLayout>
|
Reference in New Issue
Block a user