diff --git a/src/api/auth/use-user.tsx b/src/api/auth/use-user.tsx index fdca349f3..01d7c3fdc 100644 --- a/src/api/auth/use-user.tsx +++ b/src/api/auth/use-user.tsx @@ -1,4 +1,4 @@ -import { createQuery } from 'react-query-kit'; +import { createMutation, createQuery } from 'react-query-kit'; import { client } from '../common'; @@ -10,6 +10,10 @@ export type User = { birthday: Date | null; }; +export type DeleteUserVariables = { + email: string; +}; + const getUser = async () => { const { data } = await client({ url: '/v1/users', @@ -18,7 +22,18 @@ const getUser = async () => { return data; }; +const deleteUser = async (variables: DeleteUserVariables) => { + const { data } = await client.delete('/v1/users', { + data: variables, + }); + return data; +}; + export const useUser = createQuery({ queryKey: ['getUser'], fetcher: getUser, }); + +export const useDeleteUser = createMutation<{}, DeleteUserVariables>({ + mutationFn: deleteUser, +}); diff --git a/src/app/(app)/settings.tsx b/src/app/(app)/settings.tsx index ae32809df..43ea00ac8 100644 --- a/src/app/(app)/settings.tsx +++ b/src/app/(app)/settings.tsx @@ -2,9 +2,11 @@ import { Link } from 'expo-router'; import { useColorScheme } from 'nativewind'; import React from 'react'; +import { showMessage } from 'react-native-flash-message'; -import { useUser } from '@/api/auth/use-user'; +import { useDeleteUser, useUser } from '@/api/auth/use-user'; import { useAuth } from '@/components/providers/auth'; +import { DeleteAccountItem } from '@/components/settings/delete-account-item'; import { Item } from '@/components/settings/item'; import { ItemsContainer } from '@/components/settings/items-container'; import { LanguageItem } from '@/components/settings/language-item'; @@ -15,12 +17,25 @@ import { colors, FocusAwareStatusBar, ScrollView, Text, View } from '@/ui'; import { Website } from '@/ui/icons'; export default function Settings() { - const { data: userData } = useUser(); const { logout } = useAuth(); + const { data: userData } = useUser(); + const { mutateAsync: deleteUserAsync } = useDeleteUser({ + onSuccess: () => { + logout(); + }, + onError: (error) => showMessage({ message: error.message, type: 'danger' }), + }); const { colorScheme } = useColorScheme(); const iconColor = colorScheme === 'dark' ? colors.neutral[400] : colors.neutral[500]; + const handleDeleteUser = async () => { + if (!userData?.email) { + return; + } + await deleteUserAsync({ email: userData?.email }); + }; + return ( <> @@ -77,6 +92,7 @@ export default function Settings() { + diff --git a/src/components/settings/delete-account-item.tsx b/src/components/settings/delete-account-item.tsx new file mode 100644 index 000000000..dba9b33f0 --- /dev/null +++ b/src/components/settings/delete-account-item.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { Alert } from 'react-native'; + +import { translate } from '@/core'; + +import { Item } from './item'; + +export type DeleteAccountItemProps = { + onDelete: () => void; +}; + +export const DeleteAccountItem = (props: DeleteAccountItemProps) => { + const handleDeleteAccount = () => { + props.onDelete(); + }; + + const confirmDelete = () => { + Alert.alert( + translate('settings.deleteAccount.confirmTitle'), + translate('settings.deleteAccount.confirmMessage'), + [ + { text: translate('settings.deleteAccount.cancel'), style: 'cancel' }, + { + text: translate('settings.deleteAccount.delete'), + style: 'destructive', + onPress: handleDeleteAccount, + }, + ], + ); + }; + + return ; +}; diff --git a/src/components/settings/item.tsx b/src/components/settings/item.tsx index 71407741a..35cf7db55 100644 --- a/src/components/settings/item.tsx +++ b/src/components/settings/item.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { forwardRef } from 'react'; import type { TxKeyPath } from '@/core'; import { Pressable, Text, View } from '@/ui'; @@ -11,26 +11,29 @@ type ItemProps = { icon?: React.ReactNode; }; -export const Item = ({ text, value, icon, onPress }: ItemProps) => { - const isPressable = onPress !== undefined; - return ( - - - {icon && {icon}} - - - - {value} - {isPressable && ( - - - - )} - - - ); -}; +export const Item = forwardRef( + ({ text, value, icon, onPress }: ItemProps, ref) => { + const isPressable = onPress !== undefined; + return ( + + + {icon && {icon}} + + + + {value} + {isPressable && ( + + + + )} + + + ); + }, +); diff --git a/src/translations/en.json b/src/translations/en.json index 6c4062794..bd423eb96 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -72,6 +72,13 @@ }, "app_name": "App Name", "arabic": "Arabic", + "deleteAccount": { + "cancel": "Cancel", + "confirmMessage": "Are you sure you want to delete your account? This action cannot be undone.", + "confirmTitle": "Confirm Delete", + "delete": "Delete", + "title": "Delete account" + }, "english": "English", "generale": "General", "github": "Github", @@ -83,7 +90,7 @@ "rate": "Rate", "share": "Share", "support": "Support", - "support_us": "Support Us", + "supportUs": "Support Us", "terms": "Terms of Service", "theme": { "dark": "Dark",