mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-02-25 11:27:09 -05:00
Prompt for reasons upon profile deletion
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@compass/api",
|
||||
"description": "Backend API endpoints",
|
||||
"version": "1.11.1",
|
||||
"version": "1.12.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"watch:serve": "tsx watch src/serve.ts",
|
||||
|
||||
@@ -5,7 +5,7 @@ import {getUser} from 'shared/utils'
|
||||
|
||||
import {APIError, APIHandler} from './helpers/endpoint'
|
||||
|
||||
export const deleteMe: APIHandler<'me/delete'> = async (_, auth) => {
|
||||
export const deleteMe: APIHandler<'me/delete'> = async ({reasonCategory, reasonDetails}, auth) => {
|
||||
const user = await getUser(auth.uid)
|
||||
if (!user) {
|
||||
throw new APIError(401, 'Your account was not found')
|
||||
@@ -15,8 +15,23 @@ export const deleteMe: APIHandler<'me/delete'> = async (_, auth) => {
|
||||
throw new APIError(400, 'Invalid user ID')
|
||||
}
|
||||
|
||||
// Remove user data from Supabase
|
||||
const pg = createSupabaseDirectClient()
|
||||
|
||||
// Store deletion reason before deleting the account
|
||||
try {
|
||||
await pg.none(
|
||||
`
|
||||
INSERT INTO deleted_users (username, reason_category, reason_details)
|
||||
VALUES ($1, $2, $3)
|
||||
`,
|
||||
[user.username, reasonCategory, reasonDetails],
|
||||
)
|
||||
} catch (e) {
|
||||
console.error('Error storing deletion reason:', e)
|
||||
// Don't fail the deletion if we can't store the reason
|
||||
}
|
||||
|
||||
// Remove user data from Supabase
|
||||
await pg.none('DELETE FROM users WHERE id = $1', [userId])
|
||||
// Should cascade delete in other tables
|
||||
|
||||
|
||||
@@ -48,4 +48,5 @@ BEGIN;
|
||||
\i backend/supabase/migrations/20260213_add_big_5_to_profiles.sql
|
||||
\i backend/supabase/migrations/20260218_add_events.sql
|
||||
\i backend/supabase/migrations/20260218_add_notification_templates.sql
|
||||
\i backend/supabase/migrations/20260222_add_deleted_users.sql
|
||||
COMMIT;
|
||||
|
||||
21
backend/supabase/migrations/20260222_add_deleted_users.sql
Normal file
21
backend/supabase/migrations/20260222_add_deleted_users.sql
Normal file
@@ -0,0 +1,21 @@
|
||||
-- Create deleted_users table to store information about deleted accounts
|
||||
CREATE TABLE IF NOT EXISTS deleted_users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
username TEXT ,
|
||||
reason_category TEXT,
|
||||
reason_details TEXT,
|
||||
deleted_time TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
-- Create indexes for performance
|
||||
CREATE INDEX IF NOT EXISTS idx_deleted_users_username ON deleted_users (username);
|
||||
CREATE INDEX IF NOT EXISTS idx_deleted_users_deleted_time ON deleted_users (deleted_time);
|
||||
CREATE INDEX IF NOT EXISTS idx_deleted_users_reason_category ON deleted_users (reason_category);
|
||||
|
||||
-- Enable RLS
|
||||
ALTER TABLE deleted_users ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Policy: Allow insert for everyone (for account deletion)
|
||||
DROP POLICY IF EXISTS "anyone can insert" ON deleted_users;
|
||||
CREATE POLICY "anyone can insert" ON deleted_users
|
||||
FOR INSERT WITH CHECK (true);
|
||||
@@ -250,7 +250,12 @@ export const API = (_apiTypeCheck = {
|
||||
method: 'POST',
|
||||
authed: true,
|
||||
rateLimited: true,
|
||||
props: z.object({}),
|
||||
props: z
|
||||
.object({
|
||||
reasonCategory: z.string().nullable().optional(),
|
||||
reasonDetails: z.string().optional(),
|
||||
})
|
||||
.strict(),
|
||||
summary: 'Delete the authenticated user account',
|
||||
tag: 'Users',
|
||||
},
|
||||
|
||||
@@ -321,6 +321,30 @@ export type Database = {
|
||||
},
|
||||
]
|
||||
}
|
||||
deleted_users: {
|
||||
Row: {
|
||||
deleted_time: string
|
||||
id: string
|
||||
reason_category: string | null
|
||||
reason_details: string | null
|
||||
username: string | null
|
||||
}
|
||||
Insert: {
|
||||
deleted_time?: string
|
||||
id?: string
|
||||
reason_category?: string | null
|
||||
reason_details?: string | null
|
||||
username?: string | null
|
||||
}
|
||||
Update: {
|
||||
deleted_time?: string
|
||||
id?: string
|
||||
reason_category?: string | null
|
||||
reason_details?: string | null
|
||||
username?: string | null
|
||||
}
|
||||
Relationships: []
|
||||
}
|
||||
events: {
|
||||
Row: {
|
||||
created_time: string
|
||||
|
||||
@@ -24,6 +24,7 @@ export function ConfirmationButton(props: {
|
||||
label?: string
|
||||
color?: ColorType
|
||||
isSubmitting?: boolean
|
||||
disabled?: boolean
|
||||
}
|
||||
children: ReactNode
|
||||
onSubmit?: () => void
|
||||
@@ -73,6 +74,7 @@ export function ConfirmationButton(props: {
|
||||
}
|
||||
}
|
||||
loading={submitBtn?.isSubmitting}
|
||||
disabled={submitBtn?.disabled}
|
||||
>
|
||||
{submitBtn?.label ?? 'Submit'}
|
||||
</Button>
|
||||
|
||||
223
web/components/profile/delete-account-survey-modal.tsx
Normal file
223
web/components/profile/delete-account-survey-modal.tsx
Normal file
@@ -0,0 +1,223 @@
|
||||
import {RadioGroup} from '@headlessui/react'
|
||||
import router from 'next/router'
|
||||
import {useState} from 'react'
|
||||
import toast from 'react-hot-toast'
|
||||
import {useT} from 'web/lib/locale'
|
||||
import {deleteAccount} from 'web/lib/util/delete'
|
||||
|
||||
import {ConfirmationButton} from '../buttons/confirmation-button'
|
||||
import {Col} from '../layout/col'
|
||||
import {Title} from '../widgets/title'
|
||||
|
||||
export function DeleteAccountSurveyModal() {
|
||||
const [selectedReason, setSelectedReason] = useState<string | null>(null)
|
||||
const [reasonFreeText, setReasonFreeText] = useState('')
|
||||
const [deleteError, setDeleteError] = useState<string | null>(null)
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
const t = useT()
|
||||
|
||||
const reasonsMap: Record<string, string> = {
|
||||
found_connection_on_compass: t(
|
||||
'delete_survey.reasons.found_connection_on_compass',
|
||||
'I found a meaningful connection on Compass',
|
||||
),
|
||||
|
||||
found_connection_elsewhere: t(
|
||||
'delete_survey.reasons.found_connection_elsewhere',
|
||||
'I found a connection elsewhere',
|
||||
),
|
||||
|
||||
not_enough_relevant_people: t(
|
||||
'delete_survey.reasons.not_enough_relevant_people',
|
||||
'Not enough relevant people near me',
|
||||
),
|
||||
|
||||
conversations_didnt_progress: t(
|
||||
'delete_survey.reasons.conversations_didnt_progress',
|
||||
'Conversations didn’t turn into real connections',
|
||||
),
|
||||
|
||||
low_response_rate: t(
|
||||
'delete_survey.reasons.low_response_rate',
|
||||
'Messages often went unanswered',
|
||||
),
|
||||
|
||||
platform_not_active_enough: t(
|
||||
'delete_survey.reasons.platform_not_active_enough',
|
||||
'The community didn’t feel active enough',
|
||||
),
|
||||
|
||||
not_meeting_depth_expectations: t(
|
||||
'delete_survey.reasons.not_meeting_depth_expectations',
|
||||
'Interactions felt more surface-level than expected',
|
||||
),
|
||||
|
||||
too_much_time_or_effort: t(
|
||||
'delete_survey.reasons.too_much_time_or_effort',
|
||||
'Using the platform required more time or effort than I can give',
|
||||
),
|
||||
|
||||
prefer_simpler_apps: t(
|
||||
'delete_survey.reasons.prefer_simpler_apps',
|
||||
'I prefer simpler or faster apps',
|
||||
),
|
||||
|
||||
privacy_concerns: t(
|
||||
'delete_survey.reasons.privacy_concerns',
|
||||
'Concerns about privacy or profile visibility',
|
||||
),
|
||||
|
||||
technical_issues: t('delete_survey.reasons.technical_issues', 'Technical issues or bugs'),
|
||||
|
||||
taking_a_break: t(
|
||||
'delete_survey.reasons.taking_a_break',
|
||||
'I’m taking a break from meeting apps',
|
||||
),
|
||||
|
||||
life_circumstances_changed: t(
|
||||
'delete_survey.reasons.life_circumstances_changed',
|
||||
'My life circumstances changed',
|
||||
),
|
||||
|
||||
other: t('delete_survey.reasons.other', 'Other'),
|
||||
}
|
||||
|
||||
const handleDeleteAccount = async () => {
|
||||
setDeleteError(null) // Clear previous errors
|
||||
|
||||
// if (!selectedReason) {}
|
||||
// setDeleteError()
|
||||
setIsSubmitting(true)
|
||||
|
||||
// Delete the account (now includes storing the deletion reason)
|
||||
try {
|
||||
toast
|
||||
.promise(
|
||||
deleteAccount({
|
||||
reasonCategory: selectedReason,
|
||||
reasonDetails: reasonFreeText,
|
||||
}),
|
||||
{
|
||||
loading: t('delete_yourself.toast.loading', 'Deleting account...'),
|
||||
success: () => {
|
||||
router.push('/')
|
||||
return t('delete_yourself.toast.success', 'Your account has been deleted.')
|
||||
},
|
||||
error: () => {
|
||||
setDeleteError(t('delete_yourself.toast.error', 'Failed to delete account.'))
|
||||
return t('delete_yourself.toast.error', 'Failed to delete account.')
|
||||
},
|
||||
},
|
||||
)
|
||||
.catch(() => {
|
||||
setDeleteError(t('delete_survey.error_saving_reason', 'Error deleting account'))
|
||||
console.log('Failed to delete account')
|
||||
})
|
||||
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('Error deleting account:', error)
|
||||
setDeleteError(t('delete_survey.error_saving_reason', 'Error deleting account'))
|
||||
toast.error(t('delete_survey.error_saving_reason', 'Error deleting account'))
|
||||
return false
|
||||
} finally {
|
||||
setIsSubmitting(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ConfirmationButton
|
||||
openModalBtn={{
|
||||
className: 'p-2',
|
||||
label: t('delete_yourself.open_label', 'Delete account'),
|
||||
color: 'red',
|
||||
}}
|
||||
submitBtn={{
|
||||
label: t('delete_yourself.submit', 'Delete account'),
|
||||
color: selectedReason ? 'red' : 'gray',
|
||||
isSubmitting: isSubmitting,
|
||||
disabled: !(selectedReason && reasonFreeText),
|
||||
}}
|
||||
onSubmitWithSuccess={handleDeleteAccount}
|
||||
disabled={false}
|
||||
>
|
||||
<Col className="gap-4">
|
||||
<Title>{t('delete_survey.title', 'Sorry to see you go')}</Title>
|
||||
|
||||
<div>
|
||||
{t(
|
||||
'delete_survey.description',
|
||||
"We're sorry to see you go. To help us improve Compass, please let us know why you're deleting your account.",
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="w-full">
|
||||
<RadioGroup value={selectedReason} onChange={setSelectedReason} className="space-y-2">
|
||||
<RadioGroup.Label className="text-sm font-medium">
|
||||
{t('delete_survey.reason_label', 'Why are you deleting your account?')}
|
||||
</RadioGroup.Label>
|
||||
|
||||
<div className="space-y-2 mt-2">
|
||||
{Object.entries(reasonsMap).map(([key, value]) => (
|
||||
<RadioGroup.Option
|
||||
key={key}
|
||||
value={key}
|
||||
className={({checked}) =>
|
||||
`${
|
||||
checked ? 'bg-canvas-100' : 'border-gray-300'
|
||||
} relative block cursor-pointer rounded-lg border p-4 focus:bg-canvas-100`
|
||||
}
|
||||
>
|
||||
{({checked}) => (
|
||||
<div className="flex items-center">
|
||||
<div className="flex h-5 items-center">
|
||||
<input
|
||||
type="radio"
|
||||
className="h-4 w-4 text-indigo-600 focus:ring-indigo-500"
|
||||
checked={checked}
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
<div className="ml-3 text-sm">
|
||||
<RadioGroup.Label as="span" className={`font-medium`}>
|
||||
{value}
|
||||
</RadioGroup.Label>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</RadioGroup.Option>
|
||||
))}
|
||||
</div>
|
||||
</RadioGroup>
|
||||
|
||||
{
|
||||
<div className="mt-4">
|
||||
<label htmlFor="otherReason" className="block text-sm font-medium">
|
||||
{t('delete_survey.other_placeholder', 'Please share more details')}*
|
||||
</label>
|
||||
<div className="mt-1">
|
||||
<textarea
|
||||
id="otherReason"
|
||||
rows={3}
|
||||
className="block w-full bg-canvas-0 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
||||
placeholder={t('delete_survey.other_placeholder', 'Please share more details')}
|
||||
value={reasonFreeText}
|
||||
onChange={(e) => setReasonFreeText(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
{/* Error message display */}
|
||||
{deleteError && (
|
||||
<div className="rounded-md">
|
||||
<h3 className="text-sm font-medium text-red-800">
|
||||
{t('delete_survey.error_title', 'Error')}: {deleteError}
|
||||
</h3>
|
||||
</div>
|
||||
)}
|
||||
</Col>
|
||||
</ConfirmationButton>
|
||||
)
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
import {TrashIcon} from '@heroicons/react/solid'
|
||||
import router from 'next/router'
|
||||
import {useState} from 'react'
|
||||
import toast from 'react-hot-toast'
|
||||
import {useT} from 'web/lib/locale'
|
||||
import {deleteAccount} from 'web/lib/util/delete'
|
||||
|
||||
import {ConfirmationButton} from '../buttons/confirmation-button'
|
||||
import {Col} from '../layout/col'
|
||||
import {Input} from '../widgets/input'
|
||||
import {Title} from '../widgets/title'
|
||||
|
||||
export function DeleteYourselfButton() {
|
||||
const [deleteAccountConfirmation, setDeleteAccountConfirmation] = useState('')
|
||||
const t = useT()
|
||||
const confirmPhrase = t('delete_yourself.confirm_phrase', 'delete my account')
|
||||
|
||||
return (
|
||||
<ConfirmationButton
|
||||
openModalBtn={{
|
||||
className: 'p-2',
|
||||
label: t('delete_yourself.open_label', 'Permanently delete this account'),
|
||||
icon: <TrashIcon className="mr-1 h-5 w-5" />,
|
||||
color: 'red',
|
||||
}}
|
||||
submitBtn={{
|
||||
label: t('delete_yourself.submit', 'Delete account'),
|
||||
color: deleteAccountConfirmation == confirmPhrase ? 'red' : 'gray',
|
||||
}}
|
||||
onSubmitWithSuccess={async () => {
|
||||
if (deleteAccountConfirmation == confirmPhrase) {
|
||||
toast
|
||||
.promise(deleteAccount(), {
|
||||
loading: t('delete_yourself.toast.loading', 'Deleting account...'),
|
||||
success: () => {
|
||||
router.push('/')
|
||||
return t('delete_yourself.toast.success', 'Your account has been deleted.')
|
||||
},
|
||||
error: () => {
|
||||
return t('delete_yourself.toast.error', 'Failed to delete account.')
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
return true
|
||||
})
|
||||
.catch(() => {
|
||||
return false
|
||||
})
|
||||
}
|
||||
return false
|
||||
}}
|
||||
>
|
||||
<Col>
|
||||
<Title>{t('delete_yourself.title', 'Are you sure?')}</Title>
|
||||
<div>
|
||||
{t(
|
||||
'delete_yourself.description',
|
||||
'Deleting your account means you will no longer be able to use your account. You will lose access to all of your data.',
|
||||
)}
|
||||
</div>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder={t(
|
||||
'delete_yourself.input_placeholder',
|
||||
"Type 'delete my account' to confirm",
|
||||
)}
|
||||
className="w-full"
|
||||
value={deleteAccountConfirmation}
|
||||
onChange={(e) => setDeleteAccountConfirmation(e.target.value)}
|
||||
/>
|
||||
</Col>
|
||||
</ConfirmationButton>
|
||||
)
|
||||
}
|
||||
@@ -4,9 +4,9 @@ import {api} from 'web/lib/api'
|
||||
import {firebaseLogout} from 'web/lib/firebase/users'
|
||||
import {track} from 'web/lib/service/analytics'
|
||||
|
||||
export async function deleteAccount() {
|
||||
export async function deleteAccount(reasons?: {reasonCategory?: string | null; reasonDetails?: string}) {
|
||||
track('delete account')
|
||||
await api('me/delete')
|
||||
await api('me/delete', reasons || {})
|
||||
await firebaseLogout()
|
||||
clearUserCookie()
|
||||
localStorage.clear()
|
||||
|
||||
@@ -197,6 +197,25 @@
|
||||
"delete_yourself.toast.error": "Kontolöschung fehlgeschlagen.",
|
||||
"delete_yourself.toast.loading": "Konto wird gelöscht..",
|
||||
"delete_yourself.toast.success": "Ihr Konto wurde gelöscht.",
|
||||
"delete_survey.title": "Schade, dass Sie gehen",
|
||||
"delete_survey.description": "Es tut uns leid, dass Sie gehen. Um uns bei der Verbesserung von Compass zu helfen, teilen Sie uns bitte mit, warum Sie Ihr Konto löschen.",
|
||||
"delete_survey.reason_label": "Warum löschen Sie Ihr Konto?",
|
||||
"delete_survey.reasons.found_connection_on_compass": "Ich habe eine bedeutungsvolle Verbindung auf Compass gefunden",
|
||||
"delete_survey.reasons.found_connection_elsewhere": "Ich habe woanders eine Verbindung gefunden",
|
||||
"delete_survey.reasons.not_enough_relevant_people": "Nicht genügend relevante Leute in meiner Nähe",
|
||||
"delete_survey.reasons.conversations_didnt_progress": "Gespräche wurden nicht zu echten Verbindungen",
|
||||
"delete_survey.reasons.low_response_rate": "Nachrichten blieben oft unbeantwortet",
|
||||
"delete_survey.reasons.platform_not_active_enough": "Die Community fühlte sich nicht aktiv genug an",
|
||||
"delete_survey.reasons.not_meeting_depth_expectations": "Interaktionen fühlten sich oberflächlicher an als erwartet",
|
||||
"delete_survey.reasons.too_much_time_or_effort": "Die Nutzung der Plattform erforderte mehr Zeit oder Aufwand als ich geben kann",
|
||||
"delete_survey.reasons.prefer_simpler_apps": "Ich bevorzuge einfachere oder schnellere Apps",
|
||||
"delete_survey.reasons.privacy_concerns": "Bedenken bezüglich Datenschutz oder Profilsichtbarkeit",
|
||||
"delete_survey.reasons.technical_issues": "Technische Probleme oder Fehler",
|
||||
"delete_survey.reasons.taking_a_break": "Ich mache eine Pause von Dating-Apps",
|
||||
"delete_survey.reasons.life_circumstances_changed": "Meine Lebensumstände haben sich geändert",
|
||||
"delete_survey.reasons.other": "Andere",
|
||||
"delete_survey.other_placeholder": "Bitte geben Sie weitere Details an",
|
||||
"delete_survey.error_saving_reason": "Fehler beim Speichern des Löschgrunds",
|
||||
"donate.seo.description": "Spenden Sie zur Unterstützung von Compass",
|
||||
"donate.seo.title": "Spenden",
|
||||
"donate.title": "Spenden",
|
||||
|
||||
@@ -194,6 +194,25 @@
|
||||
"delete_yourself.toast.error": "Échec de la suppression du compte.",
|
||||
"delete_yourself.toast.loading": "Suppression du compte..",
|
||||
"delete_yourself.toast.success": "Votre compte a été supprimé.",
|
||||
"delete_survey.title": "Désolé de vous voir partir",
|
||||
"delete_survey.description": "Nous sommes désolés de vous voir partir. Pour nous aider à améliorer Compass, veuillez nous indiquer pourquoi vous supprimez votre compte.",
|
||||
"delete_survey.reason_label": "Pourquoi supprimez-vous votre compte ?",
|
||||
"delete_survey.reasons.found_connection_on_compass": "J'ai trouvé une relation significative sur Compass",
|
||||
"delete_survey.reasons.found_connection_elsewhere": "J'ai trouvé une relation ailleurs",
|
||||
"delete_survey.reasons.not_enough_relevant_people": "Pas assez de personnes pertinentes près de chez moi",
|
||||
"delete_survey.reasons.conversations_didnt_progress": "Les conversations ne se sont pas transformées en vraies relations",
|
||||
"delete_survey.reasons.low_response_rate": "Les messages restaient souvent sans réponse",
|
||||
"delete_survey.reasons.platform_not_active_enough": "La communauté ne semblait pas assez active",
|
||||
"delete_survey.reasons.not_meeting_depth_expectations": "Les interactions semblaient plus superficielles que prévu",
|
||||
"delete_survey.reasons.too_much_time_or_effort": "Utiliser la plateforme demandait plus de temps ou d'effort que je ne peux donner",
|
||||
"delete_survey.reasons.prefer_simpler_apps": "Je préfère des applications plus simples ou plus rapides",
|
||||
"delete_survey.reasons.privacy_concerns": "Préoccupations concernant la confidentialité ou la visibilité du profil",
|
||||
"delete_survey.reasons.technical_issues": "Problèmes techniques ou bugs",
|
||||
"delete_survey.reasons.taking_a_break": "Je fais une pause des applications de rencontre",
|
||||
"delete_survey.reasons.life_circumstances_changed": "Mes circonstances de vie ont changé",
|
||||
"delete_survey.reasons.other": "Autre",
|
||||
"delete_survey.other_placeholder": "Veuillez partager plus de détails",
|
||||
"delete_survey.error_saving_reason": "Erreur lors de l'enregistrement de la raison de suppression",
|
||||
"donate.seo.description": "Faites un don pour soutenir Compass",
|
||||
"donate.seo.title": "Faire un don",
|
||||
"donate.title": "Faire un don",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {PrivateUser} from 'common/src/user'
|
||||
import {updateEmail} from 'firebase/auth'
|
||||
import router from 'next/router'
|
||||
import {useState} from 'react'
|
||||
import {useForm} from 'react-hook-form'
|
||||
import toast from 'react-hot-toast'
|
||||
@@ -15,6 +14,7 @@ import MeasurementSystemToggle from 'web/components/measurement-system-toggle'
|
||||
import {NoSEO} from 'web/components/NoSEO'
|
||||
import {NotificationSettings} from 'web/components/notifications'
|
||||
import {PageBase} from 'web/components/page-base'
|
||||
import {DeleteAccountSurveyModal} from 'web/components/profile/delete-account-survey-modal'
|
||||
import HiddenProfilesModal from 'web/components/settings/hidden-profiles-modal'
|
||||
import ThemeIcon from 'web/components/theme-icon'
|
||||
import {WithPrivateUser} from 'web/components/user/with-user'
|
||||
@@ -26,7 +26,6 @@ import {useUser} from 'web/hooks/use-user'
|
||||
import {api} from 'web/lib/api'
|
||||
import {sendPasswordReset} from 'web/lib/firebase/password'
|
||||
import {useT} from 'web/lib/locale'
|
||||
import {deleteAccount} from 'web/lib/util/delete'
|
||||
import {isNativeMobile} from 'web/lib/util/webview'
|
||||
|
||||
export default function NotificationsPage() {
|
||||
@@ -78,31 +77,6 @@ const LoadedGeneralSettings = (props: {privateUser: PrivateUser}) => {
|
||||
const user = useFirebaseUser()
|
||||
if (!user) return null
|
||||
|
||||
const handleDeleteAccount = async () => {
|
||||
const confirmed = confirm(
|
||||
t(
|
||||
'settings.delete_confirm',
|
||||
'Are you sure you want to delete your profile? This cannot be undone.',
|
||||
),
|
||||
)
|
||||
if (confirmed) {
|
||||
toast
|
||||
.promise(deleteAccount(), {
|
||||
loading: t('settings.delete.loading', 'Deleting account...'),
|
||||
success: () => {
|
||||
router.push('/')
|
||||
return t('settings.delete.success', 'Your account has been deleted.')
|
||||
},
|
||||
error: () => {
|
||||
return t('settings.delete.error', 'Failed to delete account.')
|
||||
},
|
||||
})
|
||||
.catch(() => {
|
||||
console.log('Failed to delete account')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const changeUserEmail = async (newEmail: string) => {
|
||||
if (!user) return
|
||||
|
||||
@@ -217,9 +191,9 @@ const LoadedGeneralSettings = (props: {privateUser: PrivateUser}) => {
|
||||
</Button>
|
||||
|
||||
<h5>{t('settings.danger_zone', 'Danger Zone')}</h5>
|
||||
<Button color="red" onClick={handleDeleteAccount} className="w-fit">
|
||||
{t('settings.delete_account', 'Delete Account')}
|
||||
</Button>
|
||||
<div className={'w-fit'}>
|
||||
<DeleteAccountSurveyModal />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Hidden profiles modal */}
|
||||
|
||||
Reference in New Issue
Block a user