diff --git a/AppNavigator.js b/AppNavigator.js index 3fa5b5f..4a60621 100644 --- a/AppNavigator.js +++ b/AppNavigator.js @@ -85,7 +85,7 @@ export default function AppNavigator() { component={Category} options={{ resetOnBlur: true, - headerShown: false, + }} /> diff --git a/Screen/Category.js b/Screen/Category.js index 1b93b31..1e63040 100644 --- a/Screen/Category.js +++ b/Screen/Category.js @@ -5,7 +5,7 @@ import {View, Text, StyleSheet} from 'react-native'; export default function Category(){ return( - This is screen Category + This is screen Category. ) } diff --git a/Screen/ConfirmationOrder/ConfirmationOrder.js b/Screen/ConfirmationOrder/ConfirmationOrder.js index 1aebbb1..7f54172 100644 --- a/Screen/ConfirmationOrder/ConfirmationOrder.js +++ b/Screen/ConfirmationOrder/ConfirmationOrder.js @@ -85,6 +85,10 @@ const ConfirmationOrder = (props) => { console.log("selectedOption", selectedOption); if (selectedOption === "card") { paymentmethod = 2; + const rewardType3Exists = state.UseVoucher.some( + (voucher) => voucher.reward_type === 3 + ); + navigation.navigate("VerifyVnPayPayMent", { cartItems: Orderdata.item_id, cartId: Orderdata.Cart_id, @@ -92,10 +96,15 @@ const ConfirmationOrder = (props) => { shippingAddressId: addresses[0]?.id, paymentMethodId: paymentmethod, voucherId: state.UseVoucher.map((voucher) => voucher.voucher_id), + freightCost: rewardType3Exists ? 0 : 10000, }); } if (selectedOption === "cash") { paymentmethod = 1; + const rewardType3Exists = state.UseVoucher.some( + (voucher) => voucher.reward_type === 3 + ); + const orderData = { cartItems: Orderdata.item_id, cartId: Orderdata.Cart_id, @@ -103,6 +112,7 @@ const ConfirmationOrder = (props) => { shippingAddressId: addresses[0]?.id, paymentMethodId: paymentmethod, voucherIds: state.UseVoucher.map((voucher) => voucher.voucher_id), + freightCost: rewardType3Exists ? 0 : 10000, }; const data = await Orders(orderData); console.log("data", data); @@ -702,4 +712,4 @@ const styles = StyleSheet.create({ flex: 1, backgroundColor: "#fff", }, -}); +}); \ No newline at end of file diff --git a/Screen/ConfirmationOrder/Verifyvnpaypayment.js b/Screen/ConfirmationOrder/Verifyvnpaypayment.js index 4ecddb2..f2c3600 100644 --- a/Screen/ConfirmationOrder/Verifyvnpaypayment.js +++ b/Screen/ConfirmationOrder/Verifyvnpaypayment.js @@ -4,31 +4,67 @@ import { PulseIndicator } from "react-native-indicators"; import { useNavigation } from "@react-navigation/native"; import FontAwesome from "react-native-vector-icons/FontAwesome"; import { WebView } from "react-native-webview"; +import useAuth from "../../Services/auth.services"; import axios from "axios"; +import Config from "../../Api/Config"; +import { AuthStatus } from "../../Services/AuthContext"; +import authHeader from "../../Services/auth.header"; -const VerifyVnPayPayment = () => { +const VerifyVnPayPayment = (props) => { const navigation = useNavigation(); const [webViewUrl, setWebViewUrl] = useState(null); + const { Orders } = useAuth(); + const { state, dispatch } = AuthStatus(); + const { + cartItems, + cartId, + totalPrice, + shippingAddressId, + paymentMethodId, + voucherId, + freightCost, + } = props.route.params; + console.log("cartItems", cartItems, cartId, totalPrice, shippingAddressId); useEffect(() => { const fetchData = async () => { try { - const response = await axios.post( - "http://192.168.0.103:3000/api/v1/payment/vnpay/create_payment_url", - { - orderId: 1, - amount: "70000", - bankCode: "VNBANK", - language: "vn", - } - ); - console.log("Payment URL response: ", response.data); - setWebViewUrl(response.data.url); + const data = await Orders(props.route.params); + if (data.message === "ok") { + const usedVoucherIds = state.UseVoucher.map( + (voucher) => voucher.voucher_id + ); + + // Filter out the used vouchers from the state.UseVoucher array + const updatedVouchers = state.UseVoucher.filter( + (voucher) => !usedVoucherIds.includes(voucher.voucher_id) + ); + + // Update the state with the remaining vouchers + dispatch({ type: "USE_VOUCHER", payload: updatedVouchers }); + console.log("orderId", data); + + const headers = await authHeader(); + const response = await axios.post( + `${Config.API_BASE_URL}/payment/vnpay/create_payment_url`, + { + orderId: data.orderId, + amount: totalPrice, + bankCode: "VNBANK", + language: "vn", + }, { + headers: headers + } + ); + console.log("Payment URL response: ", response.data); + setWebViewUrl(response.data.url); + } } catch (error) { console.error("Error fetching payment URL:", error); ToastAndroid.show("Error fetching payment URL", ToastAndroid.SHORT); } }; + fetchData(); }, []); @@ -52,7 +88,7 @@ const VerifyVnPayPayment = () => { if (response.RspCode === "00") { ToastAndroid.show("Thanh toán thành công", ToastAndroid.SHORT); navigation.navigate("Home"); - } else if (response.RspCode === "-01") { + } else if (response.RspCode === "01") { ToastAndroid.show("Thanh toán đã bị hủy", ToastAndroid.SHORT); navigation.goBack(); } else { @@ -99,4 +135,4 @@ const styles = StyleSheet.create({ }, }); -export default VerifyVnPayPayment; +export default VerifyVnPayPayment; \ No newline at end of file diff --git a/Screen/Informations/OrderInfo.js b/Screen/Informations/OrderInfo.js index a9f7009..4d7e460 100644 --- a/Screen/Informations/OrderInfo.js +++ b/Screen/Informations/OrderInfo.js @@ -7,15 +7,49 @@ import { TouchableOpacity, Image, } from "react-native"; -import change from "../../images/ReChange.png"; -import wait from "../../images/2.png"; -import ship from "../../images/3.png"; -import mess from "../../images/4.png"; -import pay from "../../images/5.png"; +import PENDING from "../../images/1.png"; +import PROCESSING from "../../images/2.png"; +import SHIPPING from "../../images/3.png"; +import SHIPPED from "../../images/4.png"; +import DELIVERED from "../../images/5.png"; +import CANCELED from "../../images/6.png"; -export default OrderInfo = ({ navigation }) => { - const hanldChoThanhToan = () => { - +import useAuth from "../../Services/auth.services"; +import { useEffect, useState } from "react"; +import { useNavigation } from "@react-navigation/native"; + +export default OrderInfo = () => { + const { totalOrderStatus } = useAuth(); + const [totalOrderStatusItem, setTotalOrderStatusItem] = useState([]); + const navigation = useNavigation(); + const hanldChoThanhToan = (key) => { + navigation.navigate("MainTabPurchase", { initialTabIndex: key }); + }; + useEffect(() => { + totalOrderStatus().then((res) => { + setTotalOrderStatusItem(res.data); + }); + }, [navigation]); + totalOrderStatus().then((res) => { + console.log("res", res); + }); + const getIconByStatusId = (statusId) => { + switch (statusId) { + case 1: + return PROCESSING; + case 2: + return PENDING; + case 3: + return SHIPPING; + case 4: + return SHIPPED; + case 5: + return DELIVERED; + case 6: + return CANCELED; + default: + return null; // Trả về hình ảnh mặc định hoặc null nếu không tìm thấy + } }; return ( @@ -32,46 +66,24 @@ export default OrderInfo = ({ navigation }) => { - { - hanldChoThanhToan(); - }} - > - - - 29 - - Chờ Thanh Toán - - - - - 29 - - Chờ Vận Chuyển - - - - - 29 - - Chờ Giao Hàng - - - - - 29 - - Đơn đã đổi trả & hủy đơn - - {/* - - - 29 - - Phản hồi Về Sản Phẩm - */} + {totalOrderStatusItem.map((item, index) => ( + { + hanldChoThanhToan(item.status_id - 1); + }} + > + + + {item.total_orders} + + {item.status_name} + + ))} ); @@ -88,7 +100,7 @@ const styles = StyleSheet.create({ width: "100%", paddingVertical: 5, paddingHorizontal: 10, - height: 90, + height: 80, }, iconsContainer: { @@ -100,7 +112,7 @@ const styles = StyleSheet.create({ iconItem: { alignItems: "center", marginBottom: 20, - width: "20%", // Adjusted width to fit three items in a row + width: "15%", }, iconImage: { width: 30, @@ -135,7 +147,7 @@ const styles = StyleSheet.create({ }, badge: { position: "absolute", - right: 12, + right: 7, top: -5, backgroundColor: "red", borderRadius: 9, @@ -148,4 +160,4 @@ const styles = StyleSheet.create({ color: "white", fontSize: 10, }, -}); +}); \ No newline at end of file diff --git a/Screen/Products/ListProduct.js b/Screen/Products/ListProduct.js index a259fdc..e75dcfe 100644 --- a/Screen/Products/ListProduct.js +++ b/Screen/Products/ListProduct.js @@ -223,7 +223,9 @@ export default function ListProduct({ navigation }) { ); return filteredProducts; }; - + const fun_productDetail = (item) => { + navigation.navigate("ProductDetail", { product: item }); + }; return ( @@ -300,7 +302,7 @@ export default function ListProduct({ navigation }) { keyExtractor={(item) => item.id} style={{ marginHorizontal: 5 }} renderItem={({ item, index }) => ( - + )} /> @@ -392,4 +394,4 @@ const styles = StyleSheet.create({ marginTop: 100, alignSelf: "center", }, -}); +}); \ No newline at end of file diff --git a/Screen/PurchaseOrder/ChoGiaoHang.js b/Screen/PurchaseOrder/ChoGiaoHang.js index bd09b9d..21fe2a4 100644 --- a/Screen/PurchaseOrder/ChoGiaoHang.js +++ b/Screen/PurchaseOrder/ChoGiaoHang.js @@ -16,42 +16,40 @@ const ChoGiaoHang = () => { }, []); const renderItem = ({ item }) => ( - - {/* Map through the order details here */} - {item.OrderDetails.map((detail, index) => ( - - - - - Mũ Lưỡi Trai Nam Nữ Nhiều Hoa Tiết Thêu - Màu Be - - - ₫{parseFloat(detail.price).toLocaleString("vi-VN")} - - x{detail.quantity} - - - ))} - - - Tổng thanh toán: ₫ - {parseFloat(item.totalAmount).toLocaleString("vi-VN")} - - - - - - {item.OrderStatus.name} + + {item.OrderDetails.map((detail, index) => ( + + + + + {detail.ProductDetail.Product.product_name} + + ₫{parseFloat(detail.price).toLocaleString("vi-VN")} + + x{detail.quantity} + ))} + + + Tổng thanh toán: ₫ + {parseFloat(item.totalAmount).toLocaleString("vi-VN")} + - ); + + + + {item.OrderStatus.name} + + + + +); + return ( { const renderItem = ({ item }) => ( - {/* Map through the order details here */} {item.OrderDetails.map((detail, index) => ( - Mũ Lưỡi Trai Nam Nữ Nhiều Hoa Tiết Thêu - Màu Be + {detail.ProductDetail.Product.product_name} ₫{parseFloat(detail.price).toLocaleString("vi-VN")} @@ -115,4 +112,4 @@ const styles = StyleSheet.create({ }, }); -export default ChoXacNhan; +export default ChoXacNhan; \ No newline at end of file diff --git a/Screen/PurchaseOrder/DaGiaoHang.js b/Screen/PurchaseOrder/DaGiaoHang.js index 4c0e08c..a26d1f5 100644 --- a/Screen/PurchaseOrder/DaGiaoHang.js +++ b/Screen/PurchaseOrder/DaGiaoHang.js @@ -1,39 +1,61 @@ import React, { useEffect, useState } from "react"; -import { View, Text, Image, StyleSheet, FlatList } from "react-native"; +import { + View, + Text, + Image, + StyleSheet, + FlatList, + TouchableOpacity, + ToastAndroid, +} from "react-native"; import useAuth from "../../Services/auth.services"; const DaGiaoHang = () => { - const { CheckStatusOrder } = useAuth(); + const { CheckStatusOrder, VerifyDelivered } = useAuth(); const [orders, setOrders] = useState([]); const fetchOrders = async () => { const res = await CheckStatusOrder("SHIPPED"); - setOrders(res); + if (res){ + setOrders(res); + } + + }; useEffect(() => { fetchOrders(); }, []); - + const XacNhanDaNhanHang = async (order_id) => { + console.log("order_id", order_id); + const res = await VerifyDelivered(order_id); + if (res) { + fetchOrders(); + ToastAndroid.show("Xác nhận thành công", ToastAndroid.SHORT); + } + }; const renderItem = ({ item }) => ( - {/* Map through the order details here */} {item.OrderDetails.map((detail, index) => ( - Mũ Lưỡi Trai Nam Nữ Nhiều Hoa Tiết Thêu - Màu Be + {detail.ProductDetail.Product.product_name} ₫{parseFloat(detail.price).toLocaleString("vi-VN")} x{detail.quantity} + + Size: {detail.ProductDetail.size} + + Color: {detail.ProductDetail.color} + + ))} @@ -44,11 +66,18 @@ const DaGiaoHang = () => { - - - {item.OrderStatus.name} - - + XacNhanDaNhanHang(item.order_id)} + > + + + {item.OrderStatus.code === "SHIPPED" + ? "Xác Nhận" + : "Đã Nhận Hàng"} + + + ); @@ -113,6 +142,9 @@ const styles = StyleSheet.create({ fontWeight: "bold", fontSize: 16, }, + size: { + marginRight: 10, + }, }); -export default DaGiaoHang; +export default DaGiaoHang; \ No newline at end of file diff --git a/Screen/PurchaseOrder/DaHuy.js b/Screen/PurchaseOrder/DaHuy.js index 0481ee3..b134dfb 100644 --- a/Screen/PurchaseOrder/DaHuy.js +++ b/Screen/PurchaseOrder/DaHuy.js @@ -16,42 +16,40 @@ const DaHuy = () => { }, []); const renderItem = ({ item }) => ( - - {/* Map through the order details here */} - {item.OrderDetails.map((detail, index) => ( - - - - - Mũ Lưỡi Trai Nam Nữ Nhiều Hoa Tiết Thêu - Màu Be - - - ₫{parseFloat(detail.price).toLocaleString("vi-VN")} - - x{detail.quantity} - - - ))} - - - Tổng thanh toán: ₫ - {parseFloat(item.totalAmount).toLocaleString("vi-VN")} - - - - - - {item.OrderStatus.name} + + {item.OrderDetails.map((detail, index) => ( + + + + + {detail.ProductDetail.Product.product_name} + + ₫{parseFloat(detail.price).toLocaleString("vi-VN")} + + x{detail.quantity} + ))} + + + Tổng thanh toán: ₫ + {parseFloat(item.totalAmount).toLocaleString("vi-VN")} + - ); + + + + {item.OrderStatus.name} + + + + +); + return ( { }, []); const renderItem = ({ item }) => ( - - {/* Map through the order details here */} - {item.OrderDetails.map((detail, index) => ( - - - - - Mũ Lưỡi Trai Nam Nữ Nhiều Hoa Tiết Thêu - Màu Be - - - ₫{parseFloat(detail.price).toLocaleString("vi-VN")} - - x{detail.quantity} - - - ))} - - - Tổng thanh toán: ₫ - {parseFloat(item.totalAmount).toLocaleString("vi-VN")} - - - - - - {item.OrderStatus.name} + + {item.OrderDetails.map((detail, index) => ( + + + + + {detail.ProductDetail.Product.product_name} + + ₫{parseFloat(detail.price).toLocaleString("vi-VN")} + + x{detail.quantity} + ))} + + + Tổng thanh toán: ₫ + {parseFloat(item.totalAmount).toLocaleString("vi-VN")} + - ); + + + + {item.OrderStatus.name} + + + + +); + return ( { }, []); const renderItem = ({ item }) => ( - - {/* Map through the order details here */} - {item.OrderDetails.map((detail, index) => ( - - - - - Mũ Lưỡi Trai Nam Nữ Nhiều Hoa Tiết Thêu - Màu Be - - - ₫{parseFloat(detail.price).toLocaleString("vi-VN")} - - x{detail.quantity} - - - ))} - - - Tổng thanh toán: ₫ - {parseFloat(item.totalAmount).toLocaleString("vi-VN")} - - - - - - {item.OrderStatus.name} + + {item.OrderDetails.map((detail, index) => ( + + + + + {detail.ProductDetail.Product.product_name} + + ₫{parseFloat(detail.price).toLocaleString("vi-VN")} + + x{detail.quantity} + ))} + + + Tổng thanh toán: ₫ + {parseFloat(item.totalAmount).toLocaleString("vi-VN")} + - ); + + + + {item.OrderStatus.name} + + + + +); + return ( { +const MainTabPurchase = ({ navigation, route }) => { + const initialTabIndex = route.params?.initialTabIndex ?? 0; const layout = useWindowDimensions(); - const [index, setIndex] = useState(0); + const [index, setIndex] = useState(initialTabIndex); const [routes] = useState([ { key: "choXacNhan", title: "Chờ xác nhận" }, { key: "dangXuLy", title: "Đang xử lý" }, { key: "choGiaoHang", title: "Chờ giao hàng" }, { key: "daGiaoHangGiao", title: "Đã giao hàng" }, - { key: "daXacNhan", title: "Đã xác nhận"}, + { key: "daXacNhan", title: "Đã xác nhận" }, { key: "daHuy", title: "Đã hủy" }, ]); - const [tabKeys, setTabKeys] = useState(routes.reduce((keys, route) => { - keys[route.key] = 0; - return keys; - }, {})); - + const [tabKeys, setTabKeys] = useState( + routes.reduce((keys, route) => { + keys[route.key] = 0; + return keys; + }, {}) + ); + useEffect(() => { + setIndex(initialTabIndex); + }, [initialTabIndex]); const updateTabKey = (tabKey) => { - setTabKeys(prevKeys => ({ + setTabKeys((prevKeys) => ({ ...prevKeys, - [tabKey]: prevKeys[tabKey] + 1 + [tabKey]: prevKeys[tabKey] + 1, })); }; @@ -41,18 +52,18 @@ const MainTabPurchase = ({ navigation }) => { const renderScene = ({ route }) => { switch (route.key) { - case 'choXacNhan': - return ; - case 'dangXuLy': - return ; - case 'choGiaoHang': - return ; - case 'daGiaoHangGiao': - return ; - case 'daXacNhan': - return ; - case 'daHuy': - return ; + case "choXacNhan": + return ; + case "dangXuLy": + return ; + case "choGiaoHang": + return ; + case "daGiaoHangGiao": + return ; + case "daXacNhan": + return ; + case "daHuy": + return ; default: return null; } @@ -113,4 +124,4 @@ const styles = StyleSheet.create({ }, }); -export default MainTabPurchase; +export default MainTabPurchase; \ No newline at end of file diff --git a/Screen/Splash/SplashStore copy.js b/Screen/Splash/SplashStore copy.js new file mode 100644 index 0000000..8caf9ca --- /dev/null +++ b/Screen/Splash/SplashStore copy.js @@ -0,0 +1,58 @@ +import React, { useEffect } from "react"; +import { View, Image, StyleSheet, Text } from "react-native"; +import SplashScreen from "react-native-splash-screen"; + +const SplashStore = ({ navigation }) => { + useEffect(() => { + const timer = setTimeout(() => { + navigation.replace("BottomTabNavigation"); + }, 2500); + + return () => clearTimeout(timer); + }, []); + + return ( + + + + Sneaker Store + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: "center", + alignItems: "center", + width: "100%", + }, + Icon: { + width: "100%", + height: "100%", + }, + Text1: { + position: "absolute", + fontSize: 30, + fontWeight: "bold", + color: "black", + alignItems: "center", + top: "57%", + }, + Text2: { + position: "absolute", + fontSize: 30, + fontWeight: "bold", + color: "rgba(4, 3, 26, 0.8)", + alignItems: "center", + top: "57%", + }, +}); + +export default SplashStore; \ No newline at end of file diff --git a/Screen/Splash/SplashStore.js b/Screen/Splash/SplashStore.js index 5f0935f..07d9649 100644 --- a/Screen/Splash/SplashStore.js +++ b/Screen/Splash/SplashStore.js @@ -1,28 +1,87 @@ -import React, { useEffect } from "react"; -import { View, Image, StyleSheet, Text } from "react-native"; +import React, { useEffect, useState } from "react"; +import { + View, + Image, + StyleSheet, + Text, + ImageBackground, + Alert, +} from "react-native"; import SplashScreen from "react-native-splash-screen"; +import { Audio } from "expo-av"; +import { BackHandler } from "react-native"; const SplashStore = ({ navigation }) => { useEffect(() => { + const backAction = () => { + Alert.alert("Ôi !!!", "Bạn có muốn thoát khỏi ứng dụng không !", [ + { + text: "Không", + onPress: () => null, + style: "cancel", + }, + { text: "Có", onPress: () => BackHandler.exitApp() }, + ]); + return true; + }; + + const backHandler = BackHandler.addEventListener( + "hardwareBackPress", + backAction + ); + + return () => backHandler.remove(); + }, []); + const playSound = async () => { + try { + const { sound } = await Audio.Sound.createAsync( + require("../../assets/audio/JingleBells.mp3"), + { shouldPlay: true } + ); + + sound.setOnPlaybackStatusUpdate((status) => { + if (status.didJustFinish) { + sound.unloadAsync(); + } + }); + + return sound; + } catch (e) { + console.log(`cannot play the sound file`, e); + } + }; + + useEffect(() => { + let soundObject; + + const startSound = async () => { + soundObject = await playSound(); + }; + + startSound(); + const timer = setTimeout(() => { - navigation.replace("BottomTabNavigation"); - }, 2500); + navigation.push("BottomTabNavigation"); + }, 4000); - return () => clearTimeout(timer); + return () => { + clearTimeout(timer); + soundObject?.unloadAsync(); + }; }, []); return ( - + - - Sneaker Store - - + ); }; @@ -32,6 +91,7 @@ const styles = StyleSheet.create({ justifyContent: "center", alignItems: "center", width: "100%", + height: "100%", }, Icon: { width: "100%", @@ -55,4 +115,4 @@ const styles = StyleSheet.create({ }, }); -export default SplashStore; +export default SplashStore; \ No newline at end of file diff --git a/Services/auth.services.js b/Services/auth.services.js index 0d6246a..87b3c47 100644 --- a/Services/auth.services.js +++ b/Services/auth.services.js @@ -419,7 +419,7 @@ const useAuth = () => { const VerifyDelivered = async (order_id) => { const headers = await authHeader(); try { - const response = await axios.put( + const response = await axios.patch( `${Config.API_BASE_URL}/orders/${order_id}/verify-delivered`, {}, { @@ -469,6 +469,23 @@ const useAuth = () => { return error.response.data; } }; + const totalOrderStatus = async () => { + const headers = await authHeader(); + try { + const response = await axios.get( + `${Config.API_BASE_URL}/orders/total-order-status`, + { + headers: headers, + } + ); + if (response.data) { + return response.data; + } + } catch (error) { + console.log("Lỗi mạng", error); + return error.response.data; + } + } return { loginUser, registerUser, @@ -497,7 +514,8 @@ const useAuth = () => { VerifyDelivered, CheckStatusOrder, UpdateInfoUser, + totalOrderStatus }; }; -export default useAuth; +export default useAuth; \ No newline at end of file diff --git a/assets/audio/JingleBells.mp3 b/assets/audio/JingleBells.mp3 new file mode 100644 index 0000000..7fc7ad2 Binary files /dev/null and b/assets/audio/JingleBells.mp3 differ diff --git a/components/MenuCategory/Category.js b/components/MenuCategory/Category.js index 5ae494a..7e95a59 100644 --- a/components/MenuCategory/Category.js +++ b/components/MenuCategory/Category.js @@ -1,5 +1,5 @@ import { faL } from "@fortawesome/free-solid-svg-icons"; -import React from "react"; +import React, { useLayoutEffect } from "react"; import { StyleSheet, Text, @@ -8,138 +8,204 @@ import { FlatList, TouchableOpacity, Pressable, + Dimensions, } from "react-native"; +import { FlatGrid } from "react-native-super-grid"; import { useNavigation } from "@react-navigation/native"; // Import useNavigation hook import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome"; import { faTriangleExclamation } from "@fortawesome/free-solid-svg-icons"; +import FontAwesome from "react-native-vector-icons/FontAwesome"; +const WIDTH = Dimensions.get("window").width; const Category = ({ route }) => { - const { categoryData } = route.params; + const { categoryData, categoryName } = route.params; const navigation = useNavigation(); + useLayoutEffect(() => { + navigation.setOptions({ + headerTitle: "Danh mục " + categoryName, + headerLeft: () => ( + navigation.goBack()} + style={{ marginLeft: 5, marginRight: 10 }} + > + + + ), + }); + }, []); if (!categoryData || !categoryData.length) { return ( - - Danh mục này hiện chưa có sản phẩm nào - - - { - navigation.goBack(); + width={200} + height={200} + source={{ + uri: "https://iili.io/JuxEicg.png", }} - > - Quay lại trang chủ - + /> ); } const handlePressDetailProduct = (item) => { - // navigation.navigate("ProductDetail", { product: item }); - alert('Chức năng đang cập nhật') + console.log("item", item); + navigation.navigate("ProductDetail", { product: item }); + }; + const renderItem = ({ item }) => { + let tensp = + item.name.length > 10 ? item.name.slice(0, 25) + "..." : item.name; + let totalQuantitySold = item.total_quantity_sold; + if (totalQuantitySold === null) { + totalQuantitySold = 0; + } else { + totalQuantitySold = parseInt(totalQuantitySold); + } + + return ( + handlePressDetailProduct(item)} + style={styles.container} + > + + + {tensp} + + + Đã bán + {totalQuantitySold} + + + + đ + + {parseFloat(item.price).toLocaleString("vi-VN")} + + + + + + + ); }; - const renderItem = ({ item }) => ( - { - handlePressDetailProduct(); - }} - > - - Name: {item.name} - Price: {item.price} - - ); return ( - item.id.toString()} - numColumns={2} // Set the number of columns to 2 + itemDimension={WIDTH / 3} /> - - navigation.goBack()} - > - Quay lại - ); }; const styles = StyleSheet.create({ container: { + borderRadius: 10, flex: 1, - padding: 16, - }, - emptyText: { - fontSize: 18, - width: "100%", - backgroundColor: "yellow", - position: "absolute", - alignSelf: "center", - top: 370, + overflow: "hidden", + alignItems: "center", }, - iconn: { - alignSelf: "center", - marginTop: 25, + + shadow: { + borderRadius: 10, + overflow: "hidden", + position: "relative", + backgroundColor: "rgba(255, 255, 255, 0.72)", + shadowOpacity: 0.1, + shadowRadius: 10, + shadowOffset: { width: 0, height: 0 }, }, - itemContainer: { - flex: 1, - flexDirection: "column", - margin: 8, + item_1: { + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + marginStart: 5, + marginEnd: 5, + marginTop: 5, + marginBottom: 5, }, - thumbnail: { + img: { + aspectRatio: 1, width: "100%", - height: 100, - resizeMode: "cover", + borderTopRightRadius: 10, + borderTopLeftRadius: 10, }, - title: { - fontSize: 16, - fontWeight: "bold", - marginTop: 8, + tensp: { + fontSize: 15, + marginBottom: 0, + fontWeight: "600", + marginVertical: 3, + marginLeft: 10, + height: 45, }, price: { - fontSize: 14, - color: "green", - marginTop: 4, + flexDirection: "row", + alignItems: "center", + justifyContent: "flex-start", + marginStart: 5, + marginEnd: 5, + marginLeft: 11, }, - description: { - fontSize: 12, - marginTop: 4, + item_price: { + color: "#F60000", + fontStyle: "normal", + fontWeight: "600", + + fontSize: 15, + }, + kihieu: { + color: "red", + fontWeight: "600", + fontSize: 15, + textDecorationLine: "underline", + paddingRight: 3, }, - goBackButton: { - backgroundColor: "blue", - padding: 10, - borderRadius: 5, + addToCart: { + position: "absolute", + right: 5, + bottom: -10, + + borderRadius: 50, + borderWidth: 1, + width: 25, + height: 25, + backgroundColor: "white", alignItems: "center", + justifyContent: "center", + padding: 15, }, - goBackButtonText: { - color: "white", - fontSize: 16, + iconAddToCart: { + fontSize: 15, + color: "red", }, - goback: { - fontSize: 20, - textAlign: "center", - color: "white", - paddingTop: 10, + itemsolid: { + flexDirection: "row", + justifyContent: "flex-start", + alignItems: "center", + marginStart: 10, + marginEnd: 5, + marginTop: 5, + marginBottom: 5, + }, + daban: { + fontSize: 12, + color: "rgba(0, 0, 0, 0.72)", + fontWeight: "600", + marginEnd: 5, }, - pressText: { - alignSelf: "center", - borderRadius: 5, - width: "80%", - height: 50, - backgroundColor: "red", + item_solid_quantity: { + fontSize: 12, + color: "rgba(0, 0, 0, 0.72)", + fontWeight: "600", + marginEnd: 5, }, }); -export default Category; +export default Category; \ No newline at end of file diff --git a/components/Product/productHorizontal.js b/components/Product/productHorizontal.js index 72a68c9..574eba6 100644 --- a/components/Product/productHorizontal.js +++ b/components/Product/productHorizontal.js @@ -15,7 +15,18 @@ import { } from "react-native"; export default ProductHorizontal = (props) => { - const { item } = props; + const { item, fun_productDetail } = props; + const fun_handlePress = () => { + fun_productDetail ? fun_productDetail(item) : null; + }; + let tensp = + item.name.length > 10 ? item.name.slice(0, 15) + "..." : item.name; + let totalQuantitySold = item.total_quantity_sold; + if (totalQuantitySold === null) { + totalQuantitySold = 0; + } else { + totalQuantitySold = parseInt(totalQuantitySold); + } return ( { marginHorizontal: 5, }} > - navigation.navigate("Details")}> + { /> - navigation.navigate("Details")}> - - {item.name} - - + + {tensp} + + Đã bán @@ -113,4 +123,4 @@ const styles = StyleSheet.create({ textDecorationLine: "underline", paddingRight: 3, }, -}); +}); \ No newline at end of file diff --git a/package.json b/package.json index 151a0cd..7e5fc24 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,8 @@ "react-redux": "^8.0.5", "redux": "^4.2.1", "redux-thunk": "^2.4.2", - "use-force-update": "^1.0.11" + "use-force-update": "^1.0.11", + "expo-av": "~13.4.1" }, "devDependencies": { "@babel/core": "^7.20.0", @@ -92,4 +93,4 @@ "expo-module-scripts": "^3.1.0" }, "private": true -} +} \ No newline at end of file