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

239 lines
6.2 KiB
TypeScript

import React, { useEffect, useState, useCallback } from 'react';
import {
View,
Text,
Alert,
StyleSheet,
FlatList,
Platform,
TouchableOpacity,
Button,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useCart } from '@/context/cartContext';
import { getAuth } from 'firebase/auth';
import { collection, addDoc } from 'firebase/firestore';
import { db } from '@/firebase/config';
import CartItem from '@/components/CartItem';
import { ArrowLeft } from 'lucide-react-native';
import Animated, {
useAnimatedStyle,
useSharedValue,
withSequence,
withTiming,
} from 'react-native-reanimated';
import * as Haptics from 'expo-haptics';
import { useRouter } from 'expo-router';
import COLORS from '@/constants/colors';
import { CartItem as CartItemType } from '@/context/cartContext';
export default function CartScreen() {
const { cart, clearCart, updateQuantity } = useCart();
const totalAmount = cart.total;
const [isProcessingOrder, setIsProcessingOrder] = useState(false);
const auth = getAuth();
const router = useRouter();
const totalValue = useSharedValue(1);
const buttonScale = useSharedValue(1);
const totalAnimatedStyle = useAnimatedStyle(() => ({
transform: [{ scale: totalValue.value }],
}));
const handleConfirmOrder = useCallback(async () => {
if (totalAmount <= 0) {
Alert.alert('Panier vide', 'Veuillez ajouter des produits à votre panier');
return;
}
setIsProcessingOrder(true);
buttonScale.value = withSequence(
withTiming(0.95, { duration: 100 }),
withTiming(1, { duration: 150 })
);
if (Platform.OS !== 'web') {
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
}
try {
const orderData: any = {
status: 'En attente',
createdAt: new Date().toISOString(),
totalAmount: totalAmount
};
cart.items.forEach((item, index) => {
orderData[`item${index + 1}`] = {
name: item.name,
quantity: item.quantity,
};
});
await addDoc(collection(db, 'orders'), orderData);
Alert.alert('Commande confirmée', `Montant Total : ${totalAmount}DT`);
clearCart();
} catch (error) {
console.error('Erreur commande :', error);
Alert.alert('Erreur', "Impossible d'enregistrer la commande.");
} finally {
setIsProcessingOrder(false);
}
}, [cart, totalAmount]);
const renderItem = useCallback(({ item }: { item: CartItemType }) => (
<CartItem
item={item}
onUpdateQuantity={(id, newQty) => {
updateQuantity(id, newQty);
totalValue.value = withSequence(
withTiming(1.05, { duration: 100 }),
withTiming(1, { duration: 100 })
);
}}
/>
), []);
const keyExtractor = useCallback((item: CartItemType) => item.id, []);
return (
<SafeAreaView style={styles.container}>
<View style={styles.header}>
<TouchableOpacity style={styles.backButton} onPress={() => router.back()}>
<ArrowLeft size={24} color="#666" />
</TouchableOpacity>
<Text style={styles.headerTitle}>Mon Panier</Text>
</View>
<View style={styles.content}>
<FlatList
data={cart.items}
renderItem={renderItem}
keyExtractor={keyExtractor}
showsVerticalScrollIndicator={false}
ListEmptyComponent={
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>Votre panier est vide</Text>
</View>
}
/>
</View>
<View style={styles.footer}>
<View style={styles.totalContainer}>
<Text style={styles.totalLabel}>Total : </Text>
<Animated.Text style={[styles.totalAmount, totalAnimatedStyle]}>
{totalAmount}DT
</Animated.Text>
</View>
<TouchableOpacity style={styles.ConfirmButton} onPress={handleConfirmOrder} disabled={totalAmount <= 0}>
<Text style={styles.ConfirmButtonText}>Ajouter au panier</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.clearCartButton}
onPress={() => {
Alert.alert(
'Vider le panier',
'Êtes-vous sûr de vouloir supprimer tous les articles du panier ?',
[
{ text: 'Annuler', style: 'cancel' },
{ text: 'Confirmer', style: 'destructive', onPress: clearCart },
]
);
}}
disabled={cart.items.length === 0}>
<Text style={styles.clearCartButtonText}>Vider le panier</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#fff' },
header: {
height: 60,
justifyContent: 'center',
alignItems: 'center',
position: 'relative',
backgroundColor: '#fff',
borderBottomWidth: 1,
borderBottomColor: '#eee',
marginTop: 5,
},
backButton: {
position: 'absolute',
left: 20,
top: '50%',
transform: [{ translateY: -12 }],
},
headerTitle: {
fontSize: 20,
fontWeight: '600',
color: '#333',
},
content: {
flex: 1,
padding: 5,
},
footer: {
paddingHorizontal: 20,
paddingVertical: 10,
backgroundColor: COLORS.background_user,
borderTopWidth: 1,
borderTopColor: COLORS.secondary,
},
totalContainer: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginBottom: 10,
},
totalLabel: {
fontSize: 20,
},
totalAmount: {
fontSize: 20,
color: COLORS.primary
},
ConfirmButton: {
backgroundColor: '#B07B4F',
borderRadius: 12,
padding: 16,
alignItems: 'center',
},
ConfirmButtonText: {
color: '#fff',
fontSize: 16,
fontWeight: '600',
},
clearCartButton: {
backgroundColor: '#D9534F',
borderRadius: 12,
padding: 16,
alignItems: 'center',
marginTop: 10, // Adding some space above the button
},
clearCartButtonText: {
color: '#fff',
fontSize: 16,
fontWeight: '600',
},
emptyContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingVertical: 10,
},
emptyText: {
fontSize: 18,
},
});