Files
casadoc-app/app/profile/password.tsx
T
2026-08-26 23:01:07 +03:00

100 lines
3.3 KiB
TypeScript

import React, { useState } from 'react';
import { Alert, KeyboardAvoidingView, Platform, Pressable, ScrollView, StyleSheet, Text } from 'react-native';
import { useRouter } from 'expo-router';
import { useMutation } from '@tanstack/react-query';
import { api } from '@/api';
import { useT } from '@/i18n';
import { AppBar } from '@/components/AppBar';
import { Button, Field, TextField } from '@/components/ui';
import { colors, fontSize, spacing } from '@/theme';
const MIN_PASSWORD = 8;
export default function ChangePasswordScreen() {
const router = useRouter();
const t = useT();
const [current, setCurrent] = useState('');
const [next, setNext] = useState('');
const [show, setShow] = useState(false);
const change = useMutation({
mutationFn: () => api.auth.changePassword(current, next),
onSuccess: () => {
// The backend keeps this device signed in and drops the others.
Alert.alert(t('changePassword.doneTitle'), t('changePassword.doneBody'), [
{ text: 'OK', onPress: () => router.back() },
]);
},
onError: (e: any) => {
const wrong = e?.fields?.current_password?.length;
Alert.alert(
t('changePassword.failed'),
wrong ? t('changePassword.wrongCurrent') : (e?.message ?? t('common.tryAgain')),
);
},
});
function onSubmit() {
if (!current) return Alert.alert(t('changePassword.failed'), t('changePassword.wrongCurrent'));
if (next.length < MIN_PASSWORD) {
return Alert.alert(
t('changePassword.failed'),
t('register.shortPassword', { count: MIN_PASSWORD }),
);
}
change.mutate();
}
return (
<KeyboardAvoidingView
style={{ flex: 1, backgroundColor: colors.bgApp }}
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
>
<AppBar title={t('changePassword.title')} back />
<ScrollView contentContainerStyle={styles.body} keyboardShouldPersistTaps="handled">
<Field label={t('changePassword.current')}>
<TextField
icon="lock-closed-outline"
value={current}
onChangeText={setCurrent}
secureTextEntry={!show}
autoCapitalize="none"
textContentType="password"
/>
</Field>
<Field label={t('changePassword.next')}>
<TextField
icon="key-outline"
value={next}
onChangeText={setNext}
placeholder={t('register.passwordHint', { count: MIN_PASSWORD })}
secureTextEntry={!show}
autoCapitalize="none"
textContentType="newPassword"
/>
<Pressable onPress={() => setShow((v) => !v)} style={styles.showPass} hitSlop={8}>
<Text style={styles.link}>{show ? t('login.hide') : t('login.show')}</Text>
</Pressable>
</Field>
<Button
title={t('changePassword.submit')}
icon="checkmark"
size="lg"
block
loading={change.isPending}
onPress={onSubmit}
/>
</ScrollView>
</KeyboardAvoidingView>
);
}
const styles = StyleSheet.create({
body: { padding: spacing[4], paddingBottom: spacing[9] },
showPass: { position: 'absolute', right: 14, top: 40 },
link: { color: colors.teal700, fontWeight: '600', fontSize: fontSize.sm },
});