BrixCafe/app/screens/user/ProductDetailsScreen.tsx
2025-04-23 03:41:33 +01:00

298 lines
7.6 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet, Image, TouchableOpacity, ActivityIndicator,Alert } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useLocalSearchParams, useRouter } from 'expo-router';
import { ChevronLeft, Minus, Plus } from 'lucide-react-native';
import { doc, getDoc } from 'firebase/firestore';
import { db } from '@/firebase/config';
import { useCart } from '@/context/cartContext';
import { Product } from '@/constants/types';
export default function ProductScreen() {
const { productId } = useLocalSearchParams();
const router = useRouter();
const [product, setProduct] = useState<Product | null>(null);
const [quantity, setQuantity] = useState(1);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
// Cart items state
const [cartItems, setCartItems] = useState<{ productName: string; quantity: number }[]>([]);
const fetchProductDetails = async () => {
if (!productId) {
setError('Aucun ID de produit fourni.');
setLoading(false);
return;
}
try {
setLoading(true);
setError(null);
const productDoc = await getDoc(doc(db, 'products', productId as string));
if (productDoc.exists()) {
setProduct({
id: productDoc.id,
...(productDoc.data() as Omit<Product, 'id'>),
});
setQuantity(1);
} else {
setError('Produit non trouvé.');
}
} catch (error) {
console.error('Erreur lors de la récupération du produit:', error);
setError('Impossible de charger le produit. Veuillez réessayer.');
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchProductDetails();
}, [productId]);
// Add item to cart
const { addItem } = useCart();
const handleAddToCart = () => {
if (!product) return;
addItem({
id: product.id,
name: product.productName,
quantity: quantity,
price: parseFloat(product.price), // Assure-toi que price est bien un number
image: product.image,
});
Alert.alert('Ajouté', `${quantity} ${product.productName} ajouté au panier`);
};
return (
<SafeAreaView style={styles.container}>
{/* Header */}
<View style={styles.header}>
<TouchableOpacity onPress={() => router.push('/screens/user/GrainsScreen')}>
<ChevronLeft size={24} color="#333" />
</TouchableOpacity>
<Text style={styles.title}>{product?.productName || 'Détails du produit'}</Text>
</View>
{/* Content */}
{loading ? (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color="#B07B4F" />
<Text style={styles.loadingText}>Chargement...</Text>
</View>
) : error ? (
<View style={styles.errorContainer}>
<Text style={styles.errorText}>{error}</Text>
<TouchableOpacity
style={styles.retryButton}
onPress={() => {
setLoading(true);
fetchProductDetails();
}}
>
<Text style={styles.retryButtonText}>Réessayer</Text>
</TouchableOpacity>
</View>
) : !product ? (
<View style={styles.errorContainer}>
<Text style={styles.errorText}>Produit non trouvé.</Text>
</View>
) : (
<>
<View style={styles.content}>
<View style={styles.imageContainer}>
<Image
source={{ uri: product.image }}
style={styles.image}
resizeMode="cover"
onError={(e) => console.log('Image error:', e.nativeEvent.error)}
/>
{product.inStock && <Text style={styles.stock}>En Stock</Text>}
</View>
<View style={styles.details}>
<Text style={styles.name}>{product.productName}</Text>
<Text style={styles.blend}>{product.description}</Text>
<View style={styles.quantityContainer}>
<Text style={styles.quantityLabel}>Quantité</Text>
<View style={styles.quantityControls}>
<TouchableOpacity
style={styles.quantityButton}
onPress={() => setQuantity(Math.max(1, quantity - 1))}
>
<Minus size={20} color="#666" />
</TouchableOpacity>
<Text style={styles.quantity}>{quantity}</Text>
<TouchableOpacity
style={styles.quantityButton}
onPress={() => setQuantity(quantity + 1)}
>
<Plus size={20} color="#666" />
</TouchableOpacity>
</View>
</View>
</View>
</View>
<View style={styles.footer}>
<TouchableOpacity style={styles.addButton} onPress={handleAddToCart}>
<Text style={styles.addButtonText}>Ajouter au panier</Text>
</TouchableOpacity>
</View>
</>
)}
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F8F9FA',
},
header: {
flexDirection: 'row',
alignItems: 'center',
padding: 20,
backgroundColor: '#fff',
borderBottomWidth: 1,
borderBottomColor: '#eee',
},
title: {
fontSize: 20,
fontWeight: '600',
color: '#333',
marginLeft: 12,
},
content: {
flex: 1,
padding: 20,
},
imageContainer: {
position: 'relative',
backgroundColor: '#fff',
borderRadius: 16,
padding: 20,
alignItems: 'center',
marginBottom: 24,
},
image: {
width: 200,
height: 300,
borderRadius: 12,
backgroundColor: '#eee', // Fallback while loading
},
stock: {
position: 'absolute',
top: 12,
right: 12,
backgroundColor: '#22C55E',
color: '#fff',
fontSize: 12,
paddingHorizontal: 8,
paddingVertical: 4,
borderRadius: 4,
},
details: {
backgroundColor: '#fff',
borderRadius: 16,
padding: 20,
},
name: {
fontSize: 24,
fontWeight: '600',
color: '#333',
marginBottom: 8,
},
blend: {
fontSize: 16,
color: '#666',
marginBottom: 24,
},
quantityContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
quantityLabel: {
fontSize: 16,
color: '#333',
},
quantityControls: {
flexDirection: 'row',
alignItems: 'center',
},
quantityButton: {
width: 40,
height: 40,
backgroundColor: '#F1F3F5',
borderRadius: 20,
alignItems: 'center',
justifyContent: 'center',
},
quantity: {
fontSize: 16,
fontWeight: '600',
marginHorizontal: 16,
},
footer: {
padding: 20,
backgroundColor: '#fff',
borderTopWidth: 1,
borderTopColor: '#eee',
},
addButton: {
backgroundColor: '#B07B4F',
borderRadius: 12,
padding: 16,
alignItems: 'center',
},
addButtonText: {
color: '#fff',
fontSize: 16,
fontWeight: '600',
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
loadingText: {
marginTop: 10,
fontSize: 16,
color: '#666',
},
errorContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
errorText: {
fontSize: 16,
color: '#EF4444',
textAlign: 'center',
marginBottom: 20,
},
retryButton: {
backgroundColor: '#B07B4F',
paddingVertical: 10,
paddingHorizontal: 20,
borderRadius: 8,
},
retryButtonText: {
color: '#fff',
fontSize: 16,
fontWeight: '600',
},
});