Update expo application
Build and Push Next App / quality (push) Successful in 1m27s
Build and Push Next App / build-next (push) Successful in 3m58s

This commit is contained in:
Gabriel Brown
2026-06-22 12:13:02 -04:00
parent ddce5efb13
commit 42f95530de
78 changed files with 5315 additions and 421 deletions
@@ -0,0 +1,108 @@
import { useState } from 'react';
import { Alert, Text } from 'react-native';
import { Stack } from 'expo-router';
import { useAction, useMutation, useQuery } from 'convex/react';
import { api } from '@spoon/backend/convex/_generated/api.js';
import { AppScreen } from '~/components/ui/app-screen';
import { Button } from '~/components/ui/button';
import { Card } from '~/components/ui/card';
import { Field } from '~/components/ui/field';
import { titleize } from '~/utils/format';
const ProfileRoute = () => {
const user = useQuery(api.auth.getUser, {});
const provider = useQuery(api.auth.getUserProvider, {});
const updateUser = useMutation(api.auth.updateUser);
const updatePassword = useAction(api.auth.updateUserPassword);
const [name, setName] = useState(user?.name ?? '');
const [email, setEmail] = useState(user?.email ?? '');
const [currentPassword, setCurrentPassword] = useState('');
const [newPassword, setNewPassword] = useState('');
const [savingProfile, setSavingProfile] = useState(false);
const [savingPassword, setSavingPassword] = useState(false);
const saveProfile = async () => {
setSavingProfile(true);
try {
await updateUser({ name, email });
Alert.alert('Saved', 'Profile updated.');
} catch (error) {
console.error(error);
Alert.alert('Could not save profile.');
} finally {
setSavingProfile(false);
}
};
const savePassword = async () => {
setSavingPassword(true);
try {
await updatePassword({ currentPassword, newPassword });
setCurrentPassword('');
setNewPassword('');
Alert.alert('Saved', 'Password updated.');
} catch (error) {
console.error(error);
Alert.alert('Could not update password.');
} finally {
setSavingPassword(false);
}
};
return (
<AppScreen>
<Stack.Screen options={{ title: 'Profile' }} />
<Text className='text-foreground text-3xl font-bold'>Profile</Text>
<Card className='gap-4'>
<Text className='text-muted-foreground text-sm'>
Email is currently managed by {titleize(provider ?? 'your provider')}.
</Text>
<Field label='Name' value={name} onChangeText={setName} />
<Field
keyboardType='email-address'
label='Email'
value={email}
onChangeText={setEmail}
/>
<Button disabled={savingProfile} onPress={() => void saveProfile()}>
{savingProfile ? 'Saving...' : 'Save profile'}
</Button>
</Card>
{provider === 'password' ? (
<Card className='gap-4'>
<Text className='text-foreground font-semibold'>Password</Text>
<Field
label='Current password'
secureTextEntry
value={currentPassword}
onChangeText={setCurrentPassword}
/>
<Field
label='New password'
secureTextEntry
value={newPassword}
onChangeText={setNewPassword}
/>
<Button
disabled={savingPassword}
variant='outline'
onPress={() => void savePassword()}
>
{savingPassword ? 'Updating...' : 'Update password'}
</Button>
</Card>
) : (
<Card>
<Text className='text-muted-foreground text-sm leading-5'>
Password changes are hidden because this account is currently using{' '}
{titleize(provider ?? 'an OAuth provider')}.
</Text>
</Card>
)}
</AppScreen>
);
};
export default ProfileRoute;