chore: build
Backend - Build & Lint / build (push) Failing after 29m5s
Frontend Client - EAS Build / build (push) Failing after 2h25m33s

This commit is contained in:
Nuxgrid
2026-07-14 18:34:58 +02:00
parent 8c3fa39d86
commit 734493363f
17 changed files with 2014 additions and 7 deletions
@@ -61,7 +61,11 @@ const LoginClient = () => {
formData.username,
formData.password,
);
if (result.success && result.access_token) {
if (result.requires_2fa && result.session_token) {
navigation.navigate("clientTwoFA", {
sessionToken: result.session_token,
});
} else if (result.success && result.access_token) {
await loginClient(result.access_token, result.user?.must_change_password ?? false);
} else {
const errorMessage =
@@ -0,0 +1,200 @@
import React, { useState, useMemo } from "react";
import {
View,
Text,
TextInput,
TouchableOpacity,
ActivityIndicator,
StyleSheet,
KeyboardAvoidingView,
ScrollView,
} from "react-native";
import { Feather } from "@expo/vector-icons";
import { verifyClient2FA } from "../../api/api";
import { useAuth } from "../../auth/AuthContext";
import { useNavigation, useRoute, type RouteProp } from "@react-navigation/native";
import type { NativeStackNavigationProp } from "@react-navigation/native-stack";
import type { RootStackParamList } from "../../navigation/types";
import { useTheme } from "../../context/ThemeContext";
type TwoFANavigationProp = NativeStackNavigationProp<
RootStackParamList,
"clientTwoFA"
>;
type TwoFARouteProp = RouteProp<RootStackParamList, "clientTwoFA">;
const ClientTwoFAScreen = () => {
const navigation = useNavigation<TwoFANavigationProp>();
const route = useRoute<TwoFARouteProp>();
const { sessionToken } = route.params;
const { loginClient } = useAuth();
const { colors } = useTheme();
const [code, setCode] = useState("");
const [apiError, setApiError] = useState("");
const [isLoading, setIsLoading] = useState(false);
const handleSubmit = async () => {
if (code.trim().length !== 6) {
setApiError("Le code doit contenir 6 chiffres");
return;
}
setIsLoading(true);
setApiError("");
try {
const result = await verifyClient2FA(sessionToken, code.trim());
if (result.success && result.access_token) {
await loginClient(result.access_token, result.user?.must_change_password ?? false);
} else {
setApiError(result.message || "Code invalide");
}
} catch (err) {
const message =
err instanceof Error ? err.message : "Erreur de connexion";
setApiError(message);
} finally {
setIsLoading(false);
}
};
const handleChangeCode = (value: string) => {
const digitsOnly = value.replace(/[^0-9]/g, "").slice(0, 6);
setCode(digitsOnly);
if (apiError) setApiError("");
};
const styles = useMemo(
() =>
StyleSheet.create({
container: { flex: 1, backgroundColor: colors.bgSecondary },
scrollContent: {
flexGrow: 1,
justifyContent: "center",
alignItems: "center",
padding: 16,
},
card: {
width: "100%",
maxWidth: 400,
borderRadius: 16,
padding: 24,
backgroundColor: colors.bgPrimary,
},
header: { alignItems: "center", marginBottom: 24 },
title: {
fontSize: 24,
fontWeight: "bold",
marginTop: 8,
color: colors.textPrimary,
},
subtitle: {
fontSize: 14,
marginTop: 4,
textAlign: "center",
color: colors.textMuted,
},
apiError: {
backgroundColor: "#fee2e2",
color: "#991b1b",
padding: 12,
borderRadius: 6,
marginBottom: 16,
textAlign: "center",
},
inputGroup: { marginBottom: 16 },
label: { marginBottom: 4, fontWeight: "500", color: colors.textSecondary },
inputWrapper: {
flexDirection: "row",
alignItems: "center",
borderWidth: 1,
borderRadius: 8,
paddingHorizontal: 12,
borderColor: colors.border,
backgroundColor: colors.bgInput,
},
icon: { marginRight: 8 },
input: {
flex: 1,
height: 48,
color: colors.textPrimary,
fontSize: 20,
letterSpacing: 8,
textAlign: "center",
},
submitButton: {
backgroundColor: colors.accent,
borderRadius: 8,
padding: 12,
alignItems: "center",
marginTop: 8,
},
submitText: { color: colors.white, fontWeight: "600", fontSize: 16 },
backButton: { alignItems: "center", marginTop: 16 },
backText: { color: colors.textMuted, fontSize: 14 },
}),
[colors],
);
return (
<KeyboardAvoidingView style={styles.container} behavior="padding">
<ScrollView
contentContainerStyle={styles.scrollContent}
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
>
<View style={styles.card}>
<View style={styles.header}>
<Feather name="shield" size={48} color={colors.accent} />
<Text style={styles.title}>Vérification en deux étapes</Text>
<Text style={styles.subtitle}>
Entrez le code à 6 chiffres envoyé sur Telegram
</Text>
</View>
{apiError ? (
<Text style={styles.apiError}> {apiError}</Text>
) : null}
<View style={styles.inputGroup}>
<Text style={styles.label}>Code de vérification</Text>
<View style={styles.inputWrapper}>
<TextInput
style={styles.input}
placeholder="000000"
placeholderTextColor={colors.textMuted}
value={code}
onChangeText={handleChangeCode}
editable={!isLoading}
keyboardType="number-pad"
maxLength={6}
autoFocus
/>
</View>
</View>
<TouchableOpacity
style={[styles.submitButton, isLoading && { opacity: 0.6 }]}
onPress={handleSubmit}
disabled={isLoading}
>
{isLoading ? (
<ActivityIndicator color={colors.white} />
) : (
<Text style={styles.submitText}>Vérifier</Text>
)}
</TouchableOpacity>
<TouchableOpacity
style={styles.backButton}
onPress={() => navigation.goBack()}
disabled={isLoading}
>
<Text style={styles.backText}>Retour à la connexion</Text>
</TouchableOpacity>
</View>
</ScrollView>
</KeyboardAvoidingView>
);
};
export default ClientTwoFAScreen;