369 lines
9.9 KiB
JavaScript
369 lines
9.9 KiB
JavaScript
import React, { useEffect, useReducer, useState } from "react";
|
|
import {
|
|
Dimensions,
|
|
StyleSheet,
|
|
Text,
|
|
TouchableOpacity,
|
|
View,
|
|
} from "react-native";
|
|
import MasonryList from "@react-native-seoul/masonry-list";
|
|
import CartCard from "../../components/cart/CartCard";
|
|
import Checkbox from "expo-checkbox";
|
|
import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome";
|
|
import {
|
|
faArrowLeft,
|
|
faDeleteLeft,
|
|
faTrash,
|
|
} from "@fortawesome/free-solid-svg-icons";
|
|
import DeleteConfirmationModal from "../../components/DeleteConfirmationModal";
|
|
const width = Dimensions.get("window").width;
|
|
const height = Dimensions.get("window").height;
|
|
|
|
const Cart = ({ cartList }) => {
|
|
// Reducer function to handle cart actions
|
|
const [isModalVisible, setModalVisible] = useState(false);
|
|
|
|
const toggleModal = () => {
|
|
setModalVisible(!isModalVisible);
|
|
};
|
|
const cartReducer = (state, action) => {
|
|
switch (action.type) {
|
|
case "INITIALIZE_CART":
|
|
return action.payload;
|
|
|
|
case "TOGGLE_ALL":
|
|
const all = !state.all;
|
|
const updatedCart = state.cart.map((shop) => ({
|
|
...shop,
|
|
selected: all,
|
|
cartItems: shop.cartItems.map((item) => ({
|
|
...item,
|
|
selected: all,
|
|
})),
|
|
}));
|
|
return { ...state, all, cart: updatedCart };
|
|
|
|
case "TOGGLE_SHOP":
|
|
const { shopIndex1 } = action.payload;
|
|
const updatedCartWithShopToggle = [...state.cart];
|
|
updatedCartWithShopToggle[shopIndex1].selected =
|
|
!updatedCartWithShopToggle[shopIndex1].selected;
|
|
updatedCartWithShopToggle[shopIndex1].cartItems =
|
|
updatedCartWithShopToggle[shopIndex1].cartItems.map((item) => ({
|
|
...item,
|
|
selected: updatedCartWithShopToggle[shopIndex1].selected,
|
|
}));
|
|
return { ...state, cart: updatedCartWithShopToggle };
|
|
|
|
case "TOGGLE_PRODUCT":
|
|
const { shopIndex2, prodIndex } = action.payload;
|
|
const updatedCartWithProductToggle = [...state.cart];
|
|
updatedCartWithProductToggle[shopIndex2].cartItems[prodIndex].selected =
|
|
!updatedCartWithProductToggle[shopIndex2].cartItems[prodIndex]
|
|
.selected;
|
|
updatedCartWithProductToggle[shopIndex2].selected = false;
|
|
return { ...state, cart: updatedCartWithProductToggle };
|
|
|
|
case "UPDATE_QUANTITY":
|
|
const {
|
|
shopIndex: shopIdx,
|
|
prodIndex: productIdx,
|
|
qty,
|
|
} = action.payload;
|
|
const updatedCartWithQuantity = [...state.cart];
|
|
// updatedCartWithQuantity[shopIdx].cartItems[productIdx].quantity = qty;
|
|
return { ...state, cart: updatedCartWithQuantity };
|
|
|
|
case "DELETE_ITEMS":
|
|
const updatedCartAfterDelete = state.cart
|
|
.filter((shop) => !shop.selected)
|
|
.map((shop) => ({
|
|
...shop,
|
|
cartItems: shop.cartItems.filter((item) => !item.selected),
|
|
}));
|
|
toggleModal();
|
|
const finalCartList = updatedCartAfterDelete.filter(
|
|
(shop) => shop.cartItems.length > 0
|
|
);
|
|
return { ...state, cart: finalCartList };
|
|
|
|
default:
|
|
return state;
|
|
}
|
|
};
|
|
|
|
const initialState = {
|
|
all: false,
|
|
cart: [],
|
|
};
|
|
const [state, dispatch] = useReducer(cartReducer, initialState);
|
|
const calculateTotalPrice = () => {
|
|
let total = 0;
|
|
|
|
// Iterate through the cartSort to calculate the total price
|
|
// cartSort.forEach((shop) => {
|
|
// let shopHasSelectedProducts = false; // Flag to check if the shop has selected products
|
|
|
|
// shop.cartItems.forEach((product) => {
|
|
// if (product.selected) {
|
|
// // Calculate the total price for the selected product
|
|
// let productTotal = 0;
|
|
|
|
// if (product.promo > 0) {
|
|
// // Apply promo discount if promo is greater than 0
|
|
// productTotal =
|
|
// product.price * (1 - product.promo / 100) * product.quantity; // Assuming promo is in percentage (e.g., 30%)
|
|
// } else {
|
|
// // Otherwise, calculate total without promo discount
|
|
// productTotal = product.price * product.quantity;
|
|
// }
|
|
|
|
// // Add the product total to the overall total
|
|
// total += productTotal;
|
|
|
|
// // Set the flag to true if at least one product is selected in the shop
|
|
// shopHasSelectedProducts = true;
|
|
// }
|
|
// });
|
|
|
|
// if (shopHasSelectedProducts) {
|
|
// // Add the shipping fee for the shop if it has selected products
|
|
// total += shop.shippingFee;
|
|
// }
|
|
// });
|
|
|
|
return total.toFixed(2);
|
|
};
|
|
useEffect(() => {
|
|
// Initialize the cart state when cartList changes
|
|
const cartSorted = cartList.reduce((acc, item) => {
|
|
const shopId = item.shopId;
|
|
const existingShop = acc.find((shop) => shop.shopname === shopId);
|
|
|
|
if (existingShop) {
|
|
existingShop.cartItems.push({ ...item, selected: false });
|
|
} else {
|
|
acc.push({
|
|
shopname: shopId,
|
|
cartItems: [{ ...item, selected: false }],
|
|
selected: false,
|
|
shippingFee: 50,
|
|
});
|
|
}
|
|
|
|
return acc;
|
|
}, []);
|
|
|
|
dispatch({
|
|
type: "INITIALIZE_CART",
|
|
payload: { all: false, cart: cartSorted },
|
|
});
|
|
}, [cartList]);
|
|
|
|
// Rest of your component remains the same, but use 'state' instead of 'cartSort'
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
<View style={styles.header}>
|
|
<Text style={styles.headerText}>CART</Text>
|
|
</View>
|
|
<View style={styles.actions}>
|
|
<View style={{ flexDirection: "row" }}>
|
|
<Checkbox
|
|
value={state.all}
|
|
onValueChange={() => dispatch({ type: "TOGGLE_ALL" })}
|
|
/>
|
|
<Text style={{ marginLeft: 10 }}>Select All</Text>
|
|
</View>
|
|
<TouchableOpacity
|
|
onPress={() => {
|
|
toggleModal();
|
|
}}
|
|
>
|
|
<FontAwesomeIcon icon={faTrash} />
|
|
</TouchableOpacity>
|
|
</View>
|
|
<View style={styles.wrapper}>
|
|
<MasonryList
|
|
data={state.cart}
|
|
keyExtractor={(item) => item.shopname}
|
|
style={styles.list}
|
|
numColumns={1}
|
|
showsVerticalScrollIndicator={false}
|
|
renderItem={({ item, i }) => (
|
|
<CartCard
|
|
all={state.all}
|
|
index={i}
|
|
shopLike={() =>
|
|
dispatch({ type: "TOGGLE_SHOP", payload: { shopIndex1: i } })
|
|
}
|
|
shopProdLike={(prodIndex) =>
|
|
dispatch({
|
|
type: "TOGGLE_PRODUCT",
|
|
payload: { shopIndex2: i, prodIndex },
|
|
})
|
|
}
|
|
cart={item}
|
|
quantityChange={(qty) =>
|
|
dispatch({
|
|
type: "UPDATE_QUANTITY",
|
|
payload: { shopIndex: i, prodIndex: i, qty },
|
|
})
|
|
}
|
|
/>
|
|
)}
|
|
containerStyle={styles.container1}
|
|
contentContainerStyle={styles.content}
|
|
onEndReachedThreshold={0.1}
|
|
/>
|
|
</View>
|
|
<View style={styles.bottom}>
|
|
<View style={styles.details}>
|
|
<View style={styles.detailsTop}>
|
|
<Text style={styles.detailsTopText}>Total Price : </Text>
|
|
<Text style={styles.detailsTopTextPrice}>
|
|
{" "}
|
|
₱{calculateTotalPrice()}
|
|
</Text>
|
|
</View>
|
|
</View>
|
|
<TouchableOpacity style={styles.checkout} >
|
|
<Text style={styles.checkoutText}>CHECKOUT</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
<DeleteConfirmationModal
|
|
isVisible={isModalVisible}
|
|
onCancel={toggleModal}
|
|
onConfirm={() => dispatch({ type: "DELETE_ITEMS" })}
|
|
/>
|
|
</View>
|
|
);
|
|
};
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
backgroundColor: "#ffffff",
|
|
paddingTop: 10,
|
|
height: "100%",
|
|
width: width,
|
|
|
|
// height:height -70
|
|
},
|
|
header: {
|
|
width: "100%",
|
|
top: 0,
|
|
height: 40,
|
|
marginLeft: 15,
|
|
},
|
|
container1: {
|
|
width: "100%",
|
|
},
|
|
|
|
actions: {
|
|
flexDirection: "row",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
padding: 10,
|
|
paddingTop: 0,
|
|
},
|
|
content: {
|
|
width: "100%",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
},
|
|
list: {
|
|
width: "100%",
|
|
},
|
|
headerText: {
|
|
textAlign: "left",
|
|
width: "100%",
|
|
fontWeight: "600",
|
|
fontSize: 16,
|
|
},
|
|
footer: {
|
|
bottom: 0,
|
|
width: "100%",
|
|
},
|
|
wrapper: {
|
|
width: "100%",
|
|
height: "90%",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
padding: 5,
|
|
},
|
|
list: {
|
|
width: "100%",
|
|
height: "90%",
|
|
// justifyContent: "center",
|
|
// alignItems: "center",
|
|
},
|
|
card: {
|
|
width: "100%",
|
|
borderWidth: 1,
|
|
borderColor: "#dddd",
|
|
justifyContent: "center",
|
|
padding: 15,
|
|
paddingVertical: 10,
|
|
borderRadius: 10,
|
|
marginVertical: 2,
|
|
},
|
|
title: {
|
|
fontSize: 16,
|
|
fontWeight: "600",
|
|
},
|
|
body: {
|
|
fontSize: 16,
|
|
// fontWeight: "600",
|
|
marginTop: 5,
|
|
},
|
|
date: {
|
|
fontSize: 12,
|
|
// fontWeight: "600",
|
|
color: "#797979",
|
|
marginTop: 10,
|
|
},
|
|
bottom: {
|
|
position: "absolute",
|
|
bottom: 0,
|
|
backgroundColor: "#fff",
|
|
width: "100%",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
flexDirection: "row",
|
|
borderTopWidth: 1,
|
|
borderColor: "#dddd",
|
|
},
|
|
details: {
|
|
padding: 10,
|
|
},
|
|
detailsTop: {
|
|
// padding:10,
|
|
flexDirection: "row",
|
|
},
|
|
detailsTopText: {
|
|
color: "#363636",
|
|
fontWeight: "600",
|
|
fontSize: 14,
|
|
letterSpacing: 0.5,
|
|
},
|
|
detailsTopTextPrice: {
|
|
color: "#ffaa00",
|
|
fontWeight: "600",
|
|
fontSize: 16,
|
|
letterSpacing: 0.5,
|
|
},
|
|
checkout: {
|
|
backgroundColor: "#ffaa00",
|
|
width: 150,
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
padding: 15,
|
|
},
|
|
checkoutText: {
|
|
color: "#fff",
|
|
fontWeight: "600",
|
|
fontSize: 16,
|
|
letterSpacing: 0.7,
|
|
},
|
|
});
|
|
export default Cart;
|