239 lines
6.2 KiB
TypeScript
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,
|
|
},
|
|
});
|