/**
* @file HistoriqueCommande.js
* @description Écran d'historique des commandes du client connecté.
* Récupère l'ensemble des commandes depuis l'API, les groupe par numéro de commande
* et les affiche sous forme de cartes. Chaque commande peut être re-commandée
* avec un retour visuel indépendant par commande.
*/
import React, { useEffect, useState } from 'react';
import {Text, View, ScrollView, Image, StyleSheet, ActivityIndicator, TouchableOpacity} from 'react-native';
import ProtectedRoute from "../components/ProtectedRoute";
import useAuth from "../hooks/useAuth";
import { EXPO_PUBLIC_API_URL } from "../config";
import { usePanier } from './store';
/**
* Écran affichant l'historique complet des commandes du client.
*
* @component
* @returns {React.JSX.Element} La liste des commandes passées ou un indicateur de chargement/erreur.
*/
const HistoriqueCommande = () => {
const { token, loading: isAuthLoading } = useAuth();
const { ajouterAuPanier } = usePanier();
/**
* Liste des commandes groupées par numéro de commande.
* Chaque élément est un tableau d'articles appartenant à la même commande.
* @type {[Array<Array<Object>>, Function]}
*/
const [commandes, setCommandes] = 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);
/**
* Dictionnaire des états d'ajout par identifiant de commande.
* Permet d'afficher un feedback visuel indépendant pour chaque bouton "Re-commander".
* @type {[Object.<number, boolean>, Function]}
*/
const [addedOrders, setAddedOrders] = useState({});
/**
* Ajoute au panier tous les articles d'une commande donnée.
* Déclenche un feedback visuel spécifique à cette commande pendant 2 secondes.
*
* @param {Array<Object>} articlesDeLaCommande - Les articles de la commande à re-commander.
* @param {number} orderId - L'identifiant unique de la commande (numéro de commande).
*/
const handleRecommander = (articlesDeLaCommande, orderId) => {
if (!articlesDeLaCommande || articlesDeLaCommande.length === 0) return;
console.log(articlesDeLaCommande);
console.log(commandes);
articlesDeLaCommande.forEach(article => {
ajouterAuPanier({
id: article.reference,
designation: article.designation,
prix: article.prix_unitaire_HT || (article.total_ligne_HT / article.quantite_demandee),
imageUrl: article.imageUrl,
quantite: article.quantite_demandee,
});
});
setAddedOrders(prev => ({ ...prev, [orderId]: true }));
setTimeout(() => {
setAddedOrders(prev => ({ ...prev, [orderId]: false }));
}, 2000);
};
useEffect(() => {
/**
* Récupère l'historique des commandes depuis l'API et les groupe par numéro de commande.
*
* @async
* @returns {Promise<void>}
*/
const fetchHistorique = async () => {
try {
setLoading(true);
const response = await fetch(`${EXPO_PUBLIC_API_URL}/profil/historique`, {
headers: { 'Authorization': `Bearer ${token}` }
});
if (!response.ok) throw new Error("Erreur réseau");
const data = await response.json();
// Groupement des articles par numéro de commande
const grouped = data.reduce((acc, curr) => {
const id = curr.numero_commande;
if (!acc[id]) acc[id] = [];
acc[id].push(curr);
return acc;
}, {});
setCommandes(Object.values(grouped));
} catch (err) {
setError("Impossible de charger l'historique.");
} finally {
setLoading(false);
}
};
if (token) fetchHistorique();
}, [token]);
if (loading || isAuthLoading) {
return (
<View style={styles.center}><ActivityIndicator size="large" color="#1E3C72" /></View>
);
}
return (
<ProtectedRoute>
<ScrollView style={styles.container}>
<Text style={styles.mainTitle}>Mon Historique</Text>
{commandes.length === 0 ? (
<Text style={styles.emptyText}>Aucune commande passée pour le moment.</Text>
) : (
commandes.map((commande, index) => {
const orderId = commande[0].numero_commande;
const isThisAdded = addedOrders[orderId];
return (
<View key={orderId} style={styles.orderCard}>
{/* En-tête de la commande : date et référence */}
<View style={styles.header}>
<Text style={styles.dateText}>
Le {new Date(commande[0].date_commande).toLocaleDateString('fr-FR')}
</Text>
<Text style={styles.refText}>Réf: #{orderId}</Text>
</View>
{/* Liste des articles de la commande */}
{commande.map((item, index) => (
<View key={index} style={styles.itemRow}>
<Image
source={{ uri: `${EXPO_PUBLIC_API_URL}/images/produits/${item.imageUrl}` }}
style={styles.itemImage}
/>
<View style={{ flex: 1 }}>
<Text style={styles.itemName}>{item.designation}</Text>
<Text style={styles.itemDetails}>Quantité: {item.quantite_demandee}</Text>
</View>
<Text style={styles.itemPrice}>{item.total_ligne_HT} €</Text>
</View>
))}
{/* Pied de carte : total TTC et bouton de re-commande */}
<View style={styles.footer}>
<View>
<Text style={styles.totalLabel}>Total TTC</Text>
<Text style={styles.totalValue}>{commande[0].total_commande_TTC.toFixed(2)} €</Text>
</View>
<TouchableOpacity
style={[
styles.btnAjouter,
{ backgroundColor: isThisAdded ? '#28a745' : '#007bff' }
]}
onPress={() => handleRecommander(commande, orderId)}
disabled={isThisAdded}
>
<Text style={styles.btnAjouterText}>
{isThisAdded ? "Ajouté ! ✅" : "Re-commander"}
</Text>
</TouchableOpacity>
</View>
</View>
);
})
)}
</ScrollView>
</ProtectedRoute>
);
};
/**
* Styles locaux de l'écran HistoriqueCommande.
* @type {import('react-native').StyleSheet.NamedStyles<any>}
*/
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#F4F7F9', padding: 15 },
center: { flex: 1, justifyContent: 'center', alignItems: 'center' },
mainTitle: { fontSize: 24, fontWeight: '800', marginBottom: 20, color: '#1A1A1A' },
emptyText: { textAlign: 'center', marginTop: 40, color: '#666' },
orderCard: {
backgroundColor: '#FFF',
borderRadius: 15,
padding: 15,
marginBottom: 20,
elevation: 4,
shadowColor: '#000',
shadowOpacity: 0.1,
shadowRadius: 10,
},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
borderBottomWidth: 1,
borderBottomColor: '#EEE',
paddingBottom: 10,
marginBottom: 10
},
dateText: { fontWeight: 'bold', color: '#333' },
refText: { color: '#888', fontSize: 12 },
itemRow: { flexDirection: 'row', alignItems: 'center', marginBottom: 10 },
itemImage: { width: 40, height: 40, borderRadius: 5, marginRight: 10 },
itemName: { fontSize: 14, fontWeight: '600' },
itemDetails: { fontSize: 12, color: '#666' },
itemPrice: { fontWeight: 'bold' },
footer: {
marginTop: 10,
paddingTop: 10,
borderTopWidth: 1,
borderTopColor: '#EEE',
flexDirection: 'row',
justifyContent: 'space-between'
},
btnAjouter: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
paddingVertical: 6,
paddingHorizontal: 12,
borderRadius: 8,
alignSelf: 'center',
},
btnAjouterText: {
color: '#ffffff',
fontSize: 15,
fontWeight: '600',
textTransform: 'none',
letterSpacing: 0.5,
},
totalLabel: { fontSize: 16, fontWeight: '700' },
totalValue: { fontSize: 18, fontWeight: '900', color: '#1E3C72' }
});
export default HistoriqueCommande;