Source: screens/Login.js

/**
 * @file Login.js
 * @description Écran de connexion de l'application.
 * Permet à l'utilisateur de s'authentifier via son adresse email et son mot de passe.
 * En cas de succès, le token JWT est stocké et l'utilisateur est redirigé vers l'accueil.
 */

import React, { useState } from 'react';
import {
    Text,
    TextInput,
    View,
    StyleSheet,
    TouchableOpacity,
    ActivityIndicator,
    KeyboardAvoidingView,
    Platform,
    ScrollView
} from 'react-native';
import { GlobalStyles } from "../styles/GlobalStyles";
import { useNavigation } from "@react-navigation/native";
import useAuth from "../hooks/useAuth";
import Icon from 'react-native-vector-icons/Feather';
import {EXPO_PUBLIC_API_URL} from "../config";

/**
 * Écran de connexion utilisateur.
 *
 * @component
 * @returns {React.JSX.Element} Le formulaire de connexion avec champs email, mot de passe et bouton de validation.
 */
export default function Login() {
    /** @type {[string, Function]} Adresse email saisie par l'utilisateur. */
    const [mail, setMail] = useState("");

    /** @type {[string, Function]} Mot de passe saisi par l'utilisateur. */
    const [password, setPassword] = useState("");

    /** @type {[string, Function]} Message d'erreur affiché en cas d'échec de connexion. */
    const [error, setError] = useState("");

    /** @type {[boolean, Function]} Indicateur de chargement pendant la requête d'authentification. */
    const [loading, setLoading] = useState(false);

    const navigation = useNavigation();
    const { login } = useAuth();

    /**
     * Envoie les identifiants à l'API et gère la réponse.
     * En cas de succès (200), stocke le token et redirige vers l'écran Home.
     * En cas d'erreur 401, affiche le message renvoyé par l'API.
     *
     * @async
     * @returns {Promise<void>}
     */
    const handleLogin = async () => {
        setError(null);
        setLoading(true);

        try {
            const abortController = new AbortController();

            const response = await fetch(`${EXPO_PUBLIC_API_URL}/client/login`, {
                signal: abortController.signal,
                method: "POST",
                headers: {"Content-Type": "application/json" },
                body: JSON.stringify( { mail: mail, password: password})
            });

            const data = await response.json();

            if (response.ok) {
                const userData = { nom : data.nom };
                login(data.token, userData);

                setTimeout(() => {
                    navigation.navigate("Home");
                }, 100);

            } else {
                if ( response.status === 401){
                    setError(data.message);
                }
            }

        } catch (error) {
            setError("Erreur de serveur, veuillez réssayer plus tard.");
        } finally {
            setLoading(false);
        }
    }

    return (
        /* Gère le clavier qui passe par-dessus les champs */
        <KeyboardAvoidingView
            behavior={Platform.OS === "ios" ? "padding" : "height"}
            style={styles.screen}
        >
            {/* Permet de scroller si l'écran est petit */}
            <ScrollView contentContainerStyle={styles.scrollContainer}>

                {/* En-tête */}
                <View style={styles.header}>
                    <Text style={styles.title}>Bienvenue</Text>
                    <Text style={styles.subtitle}>Connectez-vous pour continuer</Text>
                </View>

                <View style={GlobalStyles.formWrapper}>

                    {/* GROUPE EMAIL (avec icône) */}
                    <Text style={GlobalStyles.label}>Adresse mail :</Text>
                    <View style={styles.inputWrapper}>
                        <Icon name="mail" size={20} color="#888" style={styles.inputIcon} />
                        <TextInput
                            style={styles.inputField}
                            placeholder={"Saisir email"}
                            keyboardType="email-address"
                            autoCapitalize="none"
                            value={mail}
                            onChangeText={(text) => setMail(text)}
                        />
                    </View>

                    {/* GROUPE MOT DE PASSE (avec icône) */}
                    <Text style={GlobalStyles.label}>Mot de passe :</Text>
                    <View style={styles.inputWrapper}>
                        <Icon name="lock" size={20} color="#888" style={styles.inputIcon} />
                        <TextInput
                            style={styles.inputField}
                            placeholder={"Saisir mot de passe"}
                            secureTextEntry={true}
                            value={password}
                            onChangeText={(text) => setPassword(text)}
                        />
                    </View>

                    {/* AFFICHAGE DE L'ERREUR */}
                    {error ? (
                        <Text style={GlobalStyles.errorText}>{error}</Text>
                    ) :  null}

                    {/* BOUTON — affiche un spinner pendant le chargement */}
                    <TouchableOpacity
                        style={styles.button}
                        onPress={handleLogin}
                        disabled={loading}
                    >
                        {loading ? (
                            <ActivityIndicator size="small" color="#ffffff" />
                        ) : (
                            <Text style={styles.buttonText}>Connexion</Text>
                        )}
                    </TouchableOpacity>

                </View>
            </ScrollView>
        </KeyboardAvoidingView>
    );
}

/**
 * Styles locaux de l'écran Login (thème minimaliste).
 * @type {import('react-native').StyleSheet.NamedStyles<any>}
 */
const styles = StyleSheet.create({
    screen: {
        flex: 1,
        backgroundColor: '#FFFFFF',
    },
    scrollContainer: {
        flexGrow: 1,
        justifyContent: 'center',
        padding: 30,
    },
    header: {
        alignItems: 'flex-start',
        marginBottom: 40,
    },
    title: {
        fontSize: 42,
        fontWeight: 'bold',
        color: '#222222',
    },
    subtitle: {
        fontSize: 18,
        color: '#888',
        marginTop: 8,
    },

    // --- Les champs (très minimalistes) ---
    inputWrapper: {
        flexDirection: 'row',
        alignItems: 'center',
        backgroundColor: '#F6F6F6',
        borderRadius: 14,
        height: 60,
        marginBottom: 20,
        paddingHorizontal: 20,
        borderWidth: 1,
        borderColor: '#EFEFEF',
    },
    inputIcon: {
        marginRight: 15,
        color: '#AAAAAA',
    },
    inputField: {
        flex: 1,
        fontSize: 17,
        color: '#333',
        fontWeight: '500',
    },

    // --- Le bouton (forme pilule) ---
    button: {
        backgroundColor: '#2C5F2D',
        height: 60,
        borderRadius: 30,
        alignItems: 'center',
        justifyContent: 'center',
        marginTop: 25,
        shadowColor: '#2C5F2D',
        shadowOffset: {
            width: 0,
            height: 4,
        },
        shadowOpacity: 0.3,
        shadowRadius: 5,
        elevation: 6,
    },
    buttonText: {
        color: '#FFFFFF',
        fontSize: 18,
        fontWeight: 'bold',
    },
});