Fix Apple Review issues: Login cleanup + Account Deletion
Apple App Store Review - Submission ID: 0992528e-4ce9-4167-9a1b-07f4334a8055 Fix #2: Login Screen Cleanup (Guideline 2.1) - Removed non-functional "Create Account" button - Removed "Forgot Password" button (not needed) - Added actual logo image instead of text - Streamlined login screen to focus on core functionality Fix #3: Account Deletion Feature (Guideline 5.1.1(v)) - Added "Delete Account" button to Profile screen - Implemented confirmation dialog with clear warning - API integration: deleteAccount() method in api.ts - Automatically logs out and clears data after deletion - Redirects to login screen after successful deletion Updated APPLE_REVIEW_RESPONSE.md with full documentation.
This commit is contained in:
parent
e4a70ef8c1
commit
7205c2ad1e
@ -78,27 +78,61 @@ The paid digital content, services, or subscriptions included in or accessed by
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Fix #2: Account Creation Button
|
### ✅ Fix #2: Account Creation Button (Login Screen Cleanup)
|
||||||
|
|
||||||
**Date Fixed:** [PENDING]
|
**Date Fixed:** January 12, 2026
|
||||||
|
|
||||||
**Changes Made:**
|
**Changes Made:**
|
||||||
- [TO BE FILLED AFTER INVESTIGATION & FIX]
|
- Removed "Create Account" button from login screen footer (not functional, not needed)
|
||||||
|
- Removed "Forgot Password" button from login screen (not needed for initial release)
|
||||||
|
- Replaced text-based logo with actual app logo image (`icon.png`)
|
||||||
|
- Cleaned up login screen to focus on core functionality
|
||||||
|
|
||||||
**Technical Details:**
|
**Technical Details:**
|
||||||
- [TO BE FILLED AFTER IMPLEMENTATION]
|
- File modified: `app/(auth)/login.tsx`
|
||||||
|
- Removed footer section containing "Create Account" and "Sign Up" link (lines 123-128)
|
||||||
|
- Removed "Forgot Password" TouchableOpacity (lines 109-111)
|
||||||
|
- Changed logo from `<Text>WellNuo</Text>` to `<Image source={require('@/assets/images/icon.png')}`
|
||||||
|
- Added logo style: 120x120px with bottom margin
|
||||||
|
- Removed unused styles: `logoContainer`, `logoText`, `forgotPassword`, `forgotPasswordText`, `footer`, `footerText`, `footerLink`
|
||||||
|
- Login screen now shows only: Logo, "Welcome Back" title, Username/Password inputs, and Sign In button
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Fix #3: Account Deletion Feature
|
### ✅ Fix #3: Account Deletion Feature
|
||||||
|
|
||||||
**Date Fixed:** [PENDING]
|
**Date Fixed:** January 12, 2026
|
||||||
|
|
||||||
**Changes Made:**
|
**Changes Made:**
|
||||||
- [TO BE FILLED AFTER IMPLEMENTATION]
|
- Added "Delete Account" button to Profile screen
|
||||||
|
- Implemented confirmation dialog with clear warning message
|
||||||
|
- API method calls `delete_account` function with proper authentication
|
||||||
|
- Automatically logs out user after successful deletion
|
||||||
|
- Redirects to login screen after account deletion
|
||||||
|
|
||||||
**Technical Details:**
|
**Technical Details:**
|
||||||
- [TO BE FILLED AFTER IMPLEMENTATION]
|
- Files modified:
|
||||||
|
- `services/api.ts` - Added `deleteAccount()` method (lines 150-170)
|
||||||
|
- `app/(tabs)/profile.tsx` - Added Delete Account button and handler
|
||||||
|
|
||||||
|
**API Integration:**
|
||||||
|
- Endpoint: `https://eluxnetworks.net/function/well-api/api`
|
||||||
|
- Function: `delete_account`
|
||||||
|
- Parameters: `user_name`, `token`
|
||||||
|
- Response handling: Success → logout + redirect, Error → show error message
|
||||||
|
|
||||||
|
**User Flow:**
|
||||||
|
1. User taps "Delete Account" button in Profile
|
||||||
|
2. Confirmation alert shown: "Are you sure you want to delete your account? This action cannot be undone. All your data will be permanently deleted."
|
||||||
|
3. User confirms → API call to backend
|
||||||
|
4. Success: Account deleted, SecureStore cleared, redirected to login
|
||||||
|
5. Error: Error message shown, user stays on profile screen
|
||||||
|
|
||||||
|
**UI Details:**
|
||||||
|
- Button styled with red border and red text (destructive action)
|
||||||
|
- Uses trash icon (`trash-outline`)
|
||||||
|
- Positioned above Logout button in Profile screen
|
||||||
|
- Clear visual distinction from other actions
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -58,9 +58,11 @@ export default function LoginScreen() {
|
|||||||
>
|
>
|
||||||
{/* Logo / Header */}
|
{/* Logo / Header */}
|
||||||
<View style={styles.header}>
|
<View style={styles.header}>
|
||||||
<View style={styles.logoContainer}>
|
<Image
|
||||||
<Text style={styles.logoText}>WellNuo</Text>
|
source={require('@/assets/images/icon.png')}
|
||||||
</View>
|
style={styles.logo}
|
||||||
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
<Text style={styles.title}>Welcome Back</Text>
|
<Text style={styles.title}>Welcome Back</Text>
|
||||||
<Text style={styles.subtitle}>Sign in to continue monitoring your loved ones</Text>
|
<Text style={styles.subtitle}>Sign in to continue monitoring your loved ones</Text>
|
||||||
</View>
|
</View>
|
||||||
@ -106,27 +108,16 @@ export default function LoginScreen() {
|
|||||||
returnKeyType="done"
|
returnKeyType="done"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TouchableOpacity style={styles.forgotPassword}>
|
|
||||||
<Text style={styles.forgotPasswordText}>Forgot Password?</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
title="Sign In"
|
title="Sign In"
|
||||||
onPress={handleLogin}
|
onPress={handleLogin}
|
||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
fullWidth
|
fullWidth
|
||||||
size="lg"
|
size="lg"
|
||||||
|
style={styles.signInButton}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Footer */}
|
|
||||||
<View style={styles.footer}>
|
|
||||||
<Text style={styles.footerText}>Don't have an account? </Text>
|
|
||||||
<TouchableOpacity>
|
|
||||||
<Text style={styles.footerLink}>Create Account</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{/* Version Info */}
|
{/* Version Info */}
|
||||||
<Text style={styles.version}>WellNuo v1.0.0</Text>
|
<Text style={styles.version}>WellNuo v1.0.0</Text>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
@ -149,20 +140,11 @@ const styles = StyleSheet.create({
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginBottom: Spacing.xl,
|
marginBottom: Spacing.xl,
|
||||||
},
|
},
|
||||||
logoContainer: {
|
logo: {
|
||||||
width: 80,
|
width: 120,
|
||||||
height: 80,
|
height: 120,
|
||||||
borderRadius: BorderRadius.xl,
|
|
||||||
backgroundColor: AppColors.primary,
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginBottom: Spacing.lg,
|
marginBottom: Spacing.lg,
|
||||||
},
|
},
|
||||||
logoText: {
|
|
||||||
fontSize: FontSizes.lg,
|
|
||||||
fontWeight: '700',
|
|
||||||
color: AppColors.white,
|
|
||||||
},
|
|
||||||
title: {
|
title: {
|
||||||
fontSize: FontSizes['2xl'],
|
fontSize: FontSizes['2xl'],
|
||||||
fontWeight: '700',
|
fontWeight: '700',
|
||||||
@ -177,30 +159,8 @@ const styles = StyleSheet.create({
|
|||||||
form: {
|
form: {
|
||||||
marginBottom: Spacing.xl,
|
marginBottom: Spacing.xl,
|
||||||
},
|
},
|
||||||
forgotPassword: {
|
signInButton: {
|
||||||
alignSelf: 'flex-end',
|
marginTop: Spacing.lg,
|
||||||
marginBottom: Spacing.lg,
|
|
||||||
marginTop: -Spacing.sm,
|
|
||||||
},
|
|
||||||
forgotPasswordText: {
|
|
||||||
fontSize: FontSizes.sm,
|
|
||||||
color: AppColors.primary,
|
|
||||||
fontWeight: '500',
|
|
||||||
},
|
|
||||||
footer: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginBottom: Spacing.xl,
|
|
||||||
},
|
|
||||||
footerText: {
|
|
||||||
fontSize: FontSizes.base,
|
|
||||||
color: AppColors.textSecondary,
|
|
||||||
},
|
|
||||||
footerLink: {
|
|
||||||
fontSize: FontSizes.base,
|
|
||||||
color: AppColors.primary,
|
|
||||||
fontWeight: '600',
|
|
||||||
},
|
},
|
||||||
version: {
|
version: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import { router } from 'expo-router';
|
|||||||
import { Ionicons } from '@expo/vector-icons';
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
import { useAuth } from '@/contexts/AuthContext';
|
import { useAuth } from '@/contexts/AuthContext';
|
||||||
|
import { api } from '@/services/api';
|
||||||
import { AppColors, BorderRadius, FontSizes, Spacing } from '@/constants/theme';
|
import { AppColors, BorderRadius, FontSizes, Spacing } from '@/constants/theme';
|
||||||
|
|
||||||
interface MenuItemProps {
|
interface MenuItemProps {
|
||||||
@ -59,6 +60,30 @@ export default function ProfileScreen() {
|
|||||||
router.push('/privacy');
|
router.push('/privacy');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDeleteAccount = () => {
|
||||||
|
Alert.alert(
|
||||||
|
'Delete Account',
|
||||||
|
'Are you sure you want to delete your account? This action cannot be undone. All your data will be permanently deleted.',
|
||||||
|
[
|
||||||
|
{ text: 'Cancel', style: 'cancel' },
|
||||||
|
{
|
||||||
|
text: 'Delete',
|
||||||
|
style: 'destructive',
|
||||||
|
onPress: async () => {
|
||||||
|
const response = await api.deleteAccount();
|
||||||
|
if (response.ok) {
|
||||||
|
Alert.alert('Success', 'Your account has been deleted successfully');
|
||||||
|
router.replace('/(auth)/login');
|
||||||
|
} else {
|
||||||
|
Alert.alert('Error', response.error?.message || 'Failed to delete account');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{ cancelable: true }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
'Logout',
|
'Logout',
|
||||||
@ -116,6 +141,14 @@ export default function ProfileScreen() {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
{/* Account Actions */}
|
||||||
|
<View style={styles.section}>
|
||||||
|
<TouchableOpacity style={styles.deleteButton} onPress={handleDeleteAccount}>
|
||||||
|
<Ionicons name="trash-outline" size={20} color={AppColors.error} />
|
||||||
|
<Text style={styles.deleteText}>Delete Account</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
{/* Logout Button */}
|
{/* Logout Button */}
|
||||||
<View style={styles.section}>
|
<View style={styles.section}>
|
||||||
<TouchableOpacity style={styles.logoutButton} onPress={handleLogout}>
|
<TouchableOpacity style={styles.logoutButton} onPress={handleLogout}>
|
||||||
@ -231,6 +264,23 @@ const styles = StyleSheet.create({
|
|||||||
backgroundColor: AppColors.border,
|
backgroundColor: AppColors.border,
|
||||||
marginLeft: Spacing.lg + 36 + Spacing.md,
|
marginLeft: Spacing.lg + 36 + Spacing.md,
|
||||||
},
|
},
|
||||||
|
deleteButton: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor: AppColors.background,
|
||||||
|
paddingVertical: Spacing.md,
|
||||||
|
marginHorizontal: Spacing.lg,
|
||||||
|
borderRadius: BorderRadius.lg,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: AppColors.error,
|
||||||
|
},
|
||||||
|
deleteText: {
|
||||||
|
fontSize: FontSizes.base,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: AppColors.error,
|
||||||
|
marginLeft: Spacing.sm,
|
||||||
|
},
|
||||||
logoutButton: {
|
logoutButton: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|||||||
@ -147,6 +147,28 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async deleteAccount(): Promise<ApiResponse<any>> {
|
||||||
|
const token = await this.getToken();
|
||||||
|
const userName = await this.getUserName();
|
||||||
|
|
||||||
|
if (!token || !userName) {
|
||||||
|
return { ok: false, error: { message: 'Not authenticated', code: 'UNAUTHORIZED' } };
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await this.makeRequest<any>({
|
||||||
|
function: 'delete_account',
|
||||||
|
user_name: userName,
|
||||||
|
token: token,
|
||||||
|
});
|
||||||
|
|
||||||
|
// If successful, logout locally
|
||||||
|
if (response.ok) {
|
||||||
|
await this.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
async logout(): Promise<void> {
|
async logout(): Promise<void> {
|
||||||
await SecureStore.deleteItemAsync('accessToken');
|
await SecureStore.deleteItemAsync('accessToken');
|
||||||
await SecureStore.deleteItemAsync('userId');
|
await SecureStore.deleteItemAsync('userId');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user