Source: screens/Products.js

/**
 * @file Products.js
 * @description Écran catalogue listant l'ensemble des produits disponibles.
 * Récupère les produits depuis l'API au montage du composant et les affiche
 * sous forme de grille à deux colonnes. Chaque produit est cliquable et
 * redirige vers la fiche détaillée (ProductsCard).
 */

import React, { useEffect, useState } from 'react';
import { FlatList, Text, TouchableOpacity, View, Image, ActivityIndicator, StyleSheet } from 'react-native';
import { useNavigation } from "@react-navigation/native";
import ProtectedRoute from "../components/ProtectedRoute";
import { GlobalStyles } from "../styles/GlobalStyles";
import {EXPO_PUBLIC_API_URL} from "../config";

/**
 * Écran affichant le catalogue complet des produits sous forme de grille.
 *
 * @component
 * @returns {React.JSX.Element} La grille des produits, ou un état de chargement/erreur/vide.
 */
const Products = () => {
    /** @type {[Array<Object>, Function]} Liste des produits récupérés depuis l'API. */
    const [data, setData] = useState([]);

    /** @type {[boolean, Function]} Indicateur de chargement des données. */
    const [loading, setLoading] = useState(true);

    /** @type {[string|null, Function]} Message d'erreur en cas d'échec du fetch. */
    const [error, setError] = useState(null);

    const navigation = useNavigation();

    useEffect(() => {
        const abortController = new AbortController();

        /**
         * Récupère la liste complète des produits depuis l'API.
         * Gère les états de chargement et d'erreur.
         *
         * @async
         * @returns {Promise<void>}
         */
        const fetchProductsData = async () => {
            setLoading(true);
            setError(null);
            try {
                const response = await fetch (
                    `${EXPO_PUBLIC_API_URL}/produits/`,
                    { signal: abortController.signal }
                );

                const productsList = await response.json();

                if (!response.ok) {
                    throw new Error(productsList.message || "Erreur lors de la récupération des produits.");
                }

                setData(productsList);

            } catch(error) {
                if (error.name !== 'AbortError') {
                    console.error("Erreur de fetch produits:", error);
                    setError("Impossible de charger les produits. Veuillez réessayer.");
                }
            } finally {
                setLoading(false);
            }
        };

        fetchProductsData();
        return () => abortController.abort();
    }, []);


    if (loading) {
        return (
            <View style={GlobalStyles.loadingContainer}>
                <ActivityIndicator size="large" color="#1e3c72" />
                <Text style={GlobalStyles.loadingText}>Chargement des produits...</Text>
            </View>
        );
    }

    if (error) {
        return (
            <View style={GlobalStyles.container}>
                <Text style={GlobalStyles.errorText}>{error}</Text>
            </View>
        );
    }

    if (data.length === 0) {
        return (
            <View style={GlobalStyles.container}>
                <Text style={GlobalStyles.emptyText}>Aucun produit disponible pour le moment.</Text>
            </View>
        );
    }

    return (
        <FlatList
            data={data}
            keyExtractor={(item) => item.reference.toString()}
            numColumns={2}
            contentContainerStyle={GlobalStyles.productsGridContainer}
            renderItem={({ item }) => (
                <TouchableOpacity
                    style={GlobalStyles.productGridItem}
                    onPress={() => navigation.navigate("ProductsCard", item)}
                >
                    <Image
                        source={{ uri:`${EXPO_PUBLIC_API_URL}` + "/images/produits/" + item.imageUrl }}
                        style={GlobalStyles.productImage}
                    />
                    <Text style={GlobalStyles.productName}>{item.designation}</Text>
                    <Text style={GlobalStyles.productName}>{item.prix_unitaire_HT} €</Text>
                </TouchableOpacity>
            )}
        />
    );
};

export default Products;