From 67939d2f540c55bcd27995968b3248e25b470a86 Mon Sep 17 00:00:00 2001 From: Tieptk Date: Mon, 4 Aug 2025 10:17:58 +0700 Subject: [PATCH] upload 04/08 --- App.tsx | 10 +- app.config.js | 2 +- babel.config.js | 1 + package-lock.json | 93 +- package.json | 4 +- src/components/buildpc/CreateBuildpc.tsx | 2 +- src/components/footer/ButtonFooter.tsx | 12 +- src/components/footer/Footer.tsx | 22 +- src/components/header/Header.tsx | 264 +--- src/components/header/Menu.tsx | 197 +++ src/components/product/ItemProduct.tsx | 6 +- src/components/product/itemProductSave.tsx | 6 +- src/layouts/AppLayout.tsx | 56 +- src/navigation/AppNavigator.tsx | 1 + src/screens/HomeScreen.tsx | 414 +++--- src/screens/buildpc/Buildpc.tsx | 2 +- src/screens/buildpc/BuildpcDetail.tsx | 1 - src/screens/buildpc/CompareBuildpc.tsx | 1 - src/screens/classifieds/HomeClassifieds.tsx | 76 ++ src/screens/product/ProductDetail.tsx | 4 +- src/screens/product/ProductList.tsx | 1 - src/screens/product/ProductListBig.tsx | 1 - src/styles/globalStyles.ts | 47 +- yarn.lock | 1349 +++++++++++++++++-- 24 files changed, 1917 insertions(+), 655 deletions(-) create mode 100644 src/components/header/Menu.tsx create mode 100644 src/screens/classifieds/HomeClassifieds.tsx diff --git a/App.tsx b/App.tsx index e098b2d..05e5eda 100644 --- a/App.tsx +++ b/App.tsx @@ -1,9 +1,17 @@ -import React from "react"; +import React, { useEffect } from "react"; import { NavigationContainer } from "@react-navigation/native"; +import { Platform } from "react-native"; import { SafeAreaProvider } from "react-native-safe-area-context"; import AppNavigator from "./src/navigation/AppNavigator"; export default function App() { + useEffect(() => { + if (Platform.OS === "web") { + // Fix scroll bị chặn trên web + document.body.style.overflow = "auto"; + document.documentElement.style.overflow = "auto"; + } + }, []); return ( diff --git a/app.config.js b/app.config.js index 5e06406..016fc3c 100644 --- a/app.config.js +++ b/app.config.js @@ -4,7 +4,7 @@ export default { expo: { name: "bestpc_mobile", slug: "bestpc-mobile", - platforms: ["ios", "android"], + platforms: ["ios", "android", "web"], version: "1.0.0", orientation: "portrait", splash: { diff --git a/babel.config.js b/babel.config.js index e7428ed..0ccfdd2 100644 --- a/babel.config.js +++ b/babel.config.js @@ -14,5 +14,6 @@ module.exports = { }, }, ], + 'react-native-reanimated/plugin' ], }; diff --git a/package-lock.json b/package-lock.json index a2bf27f..9e9cccc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,12 +18,13 @@ "@react-navigation/stack": "^7.3.2", "dotenv": "^16.5.0", "expo-image-picker": "~16.1.4", + "expo-linear-gradient": "~14.1.4", "expo-status-bar": "~2.2.3", "hermes-engine": "^0.11.0", "lodash": "^4.17.21", "metro-runtime": "^0.82.3", - "react": "19.0.0", - "react-dom": "^19.0.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", "react-native": "^0.79.2", "react-native-collapsible": "^1.6.2", "react-native-gesture-handler": "~2.24.0", @@ -5203,16 +5204,16 @@ } }, "node_modules/compression": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz", - "integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "license": "MIT", "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", - "on-headers": "~1.0.2", + "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" }, @@ -5999,6 +6000,17 @@ "react": "*" } }, + "node_modules/expo-linear-gradient": { + "version": "14.1.5", + "resolved": "https://registry.npmjs.org/expo-linear-gradient/-/expo-linear-gradient-14.1.5.tgz", + "integrity": "sha512-BSN3MkSGLZoHMduEnAgfhoj3xqcDWaoICgIr4cIYEx1GcHfKMhzA/O4mpZJ/WC27BP1rnAqoKfbclk1eA70ndQ==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, "node_modules/expo-modules-autolinking": { "version": "2.1.10", "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-2.1.10.tgz", @@ -8951,9 +8963,9 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -9584,9 +9596,9 @@ } }, "node_modules/react": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", - "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9624,17 +9636,23 @@ } }, "node_modules/react-dom": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", - "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", "license": "MIT", "dependencies": { - "scheduler": "^0.25.0" + "scheduler": "^0.26.0" }, "peerDependencies": { - "react": "^19.0.0" + "react": "^19.1.0" } }, + "node_modules/react-dom/node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" + }, "node_modules/react-freeze": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.4.tgz", @@ -15619,15 +15637,15 @@ } }, "compression": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz", - "integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "requires": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", - "on-headers": "~1.0.2", + "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" }, @@ -16136,6 +16154,12 @@ "integrity": "sha512-wU9qOnosy4+U4z/o4h8W9PjPvcFMfZXrlUoKTMBW7F4pLqhkkP/5G4EviPZixv4XWFMjn1ExQ5rV6BX8GwJsWA==", "requires": {} }, + "expo-linear-gradient": { + "version": "14.1.5", + "resolved": "https://registry.npmjs.org/expo-linear-gradient/-/expo-linear-gradient-14.1.5.tgz", + "integrity": "sha512-BSN3MkSGLZoHMduEnAgfhoj3xqcDWaoICgIr4cIYEx1GcHfKMhzA/O4mpZJ/WC27BP1rnAqoKfbclk1eA70ndQ==", + "requires": {} + }, "expo-modules-autolinking": { "version": "2.1.10", "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-2.1.10.tgz", @@ -18140,9 +18164,9 @@ } }, "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==" }, "once": { "version": "1.4.0", @@ -18551,9 +18575,9 @@ } }, "react": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", - "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==" + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==" }, "react-devtools-core": { "version": "6.1.2", @@ -18573,11 +18597,18 @@ } }, "react-dom": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", - "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", "requires": { - "scheduler": "^0.25.0" + "scheduler": "^0.26.0" + }, + "dependencies": { + "scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==" + } } }, "react-freeze": { diff --git a/package.json b/package.json index a7296ee..3ea3217 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,8 @@ "hermes-engine": "^0.11.0", "lodash": "^4.17.21", "metro-runtime": "^0.82.3", - "react": "19.0.0", - "react-dom": "^19.0.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", "react-native": "^0.79.2", "react-native-collapsible": "^1.6.2", "react-native-gesture-handler": "~2.24.0", diff --git a/src/components/buildpc/CreateBuildpc.tsx b/src/components/buildpc/CreateBuildpc.tsx index f974e12..1da90a9 100644 --- a/src/components/buildpc/CreateBuildpc.tsx +++ b/src/components/buildpc/CreateBuildpc.tsx @@ -221,7 +221,7 @@ export function CreateBuildpc() { {/* Popup */} {showPopup && ( - setShowPopup(false)} /> + setShowPopup(false)} /> )} ); diff --git a/src/components/footer/ButtonFooter.tsx b/src/components/footer/ButtonFooter.tsx index 52820b1..12b61f6 100644 --- a/src/components/footer/ButtonFooter.tsx +++ b/src/components/footer/ButtonFooter.tsx @@ -4,7 +4,7 @@ import { Text, TouchableOpacity, StyleSheet, - ScrollView, + Platform, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { NavigationProp } from "@react-navigation/native"; @@ -33,7 +33,7 @@ const ButtonFooter: React.FC = ({ navigation, activeTab }) => { onPress={() => navigation?.navigate(tab.route)} > @@ -54,9 +54,15 @@ const styles = StyleSheet.create({ backgroundColor: "#fff", paddingVertical: 8, justifyContent: "space-around", - position: "absolute", bottom: 0, + left: 0, width: "100%", + ...Platform.select({ + web: { position: "fixed" as any }, + default: { + position: "absolute", + }, + }), }, navItem: { alignItems: "center", diff --git a/src/components/footer/Footer.tsx b/src/components/footer/Footer.tsx index 56ee3ca..7a5d735 100644 --- a/src/components/footer/Footer.tsx +++ b/src/components/footer/Footer.tsx @@ -82,15 +82,19 @@ const Footer: React.FC = ({ navigation, activeTab = "homepage" }) => { /> - {item.links?.map((link, linkIndex) => ( - handleLinkPress(link.route)} - > - {link.title} - - ))} + {item.links && item.links.length > 0 ? ( + item.links.map((link, linkIndex) => ( + handleLinkPress(link.route)} + > + {link.title} + + )) + ) : item.content ? ( + {item.content} + ) : null} ))} diff --git a/src/components/header/Header.tsx b/src/components/header/Header.tsx index 1926b8e..5fd2896 100644 --- a/src/components/header/Header.tsx +++ b/src/components/header/Header.tsx @@ -7,6 +7,7 @@ import { TextInput, TouchableOpacity, Dimensions, + Platform, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { Picker } from "@react-native-picker/picker"; @@ -14,25 +15,15 @@ import { NavigationContainer } from "@react-navigation/native"; import { createDrawerNavigator } from "@react-navigation/drawer"; import { createNativeStackNavigator } from "@react-navigation/native-stack"; -const Header = () => { +const Header = ({ toggleMenu }: { toggleMenu: () => void }) => { const [openSort, setopenSort] = useState(true); const [openFilter, setOpenFilter] = useState(false); - const [isMenuOpen, setIsMenuOpen] = useState(false); - - const toggleDrawer = () => { - //Props to open/close the drawer - setIsMenuOpen(!isMenuOpen); - }; - - const closeMenu = () => { - setIsMenuOpen(false); // Đóng menu - }; return ( - + - + { name="caret-down-outline" /> - - - - Hà nội - - - - - HCM - - - Đà nẵng - - @@ -102,102 +63,60 @@ const Header = () => { - {isMenuOpen && ( - - - - )} - - ); -}; - -const MainMenu = ({ closeMenu }: { closeMenu: () => void }) => { - return ( - - - Menu - - + + + + Hà nội + + - - - - - - Build PC - - + + HCM - - - - Tìm người bán - - - - - - - Địa chỉ sửa chữa - - - - - - - Hỏi đáp - - - - - - - Sản phẩm đã lưu - - - - - - - Tin rao vặt - - + + Đà nẵng ); }; -export { MainMenu }; - let winWidth = Dimensions.get("window").width; //full width let winHeight = Dimensions.get("window").height; //full height const styles = StyleSheet.create({ + BoxHeader: { + width: winWidth, + zIndex: 9999, + ...Platform.select({ + web: { + position: "fixed" as any, + top: 0, + }, + default: { + position: "absolute", + top: 0, + left: 0, + }, + }), + }, headerTop: { flexDirection: "row", alignItems: "center", width: winWidth, paddingRight: 10, paddingLeft: 10, - paddingTop: 45, + paddingTop: 10, paddingBottom: 10, backgroundColor: "#462F91", justifyContent: "space-between", @@ -212,12 +131,14 @@ const styles = StyleSheet.create({ height: 20, }, searchContainer: { - width: winWidth, + width: "100%", paddingLeft: 10, paddingRight: 10, paddingTop: 9, paddingBottom: 9, backgroundColor: "#462F91", + position: "relative", + zIndex: 1, }, searchBar: { borderRadius: 4, @@ -236,9 +157,8 @@ const styles = StyleSheet.create({ color: "#000000", height: 32, lineHeight: 32, - paddingTop: 7, - marginTop: 5, width: winWidth - 60, + outlineWidth: 0, }, searchIconContainer: { flexDirection: "row", @@ -270,6 +190,7 @@ const styles = StyleSheet.create({ alignItems: "center", gap: 5, color: "#FFFFFF", + position: "relative", }, textLocation: { color: "#FFFFFF", @@ -298,10 +219,15 @@ const styles = StyleSheet.create({ paddingHorizontal: 10, position: "absolute", right: 0, - top: 40, + top: 60, display: "none", backgroundColor: "#fff", width: 100, + zIndex: 999, + shadowColor: "#000", + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.3, + shadowRadius: 5, }, boxSortListActive: { display: "flex", @@ -343,91 +269,5 @@ const styles = StyleSheet.create({ justifyContent: "center", display: "flex", }, - headerMenu: { - alignItems: "center", - justifyContent: "space-between", - flexDirection: "row", - padding: 10, - backgroundColor: "#462F91", - paddingTop: 55, - }, - menuFixed: { - position: "absolute", - top: 0, - left: 0, - width: "85%", - height: winHeight, - backgroundColor: "#fff", - zIndex: 99, - }, - headerMenuText: { - color: "#fff", - fontWeight: "bold", - }, - closeMenu: { - backgroundColor: "#fff", - width: 20, - height: 20, - color: "#000", - borderRadius: 50, - }, - iconBuild: { - width: 30, - objectFit: "contain", - }, - iconStore: { - width: 20, - objectFit: "contain", - }, - iconCart: { - width: 20, - objectFit: "contain", - }, - iconProduct: { - width: 20, - objectFit: "contain", - }, - iconArticle: { - width: 20, - objectFit: "contain", - }, - iconLocation: { - width: 20, - objectFit: "contain", - }, - iconBox: { - width: 20, - objectFit: "contain", - }, - itemMenu: { - alignItems: "center", - flexDirection: "row", - justifyContent: "space-between", - gap: 10, - marginBottom: 10, - padding: 10, - borderBottomWidth: 1, - borderBottomColor: "#e1e1e1", - height: 50, - }, - itemText: { - fontSize: 15, - color: "#000", - fontWeight: "bold", - }, - textLeft: { - alignItems: "center", - gap: 10, - flexDirection: "row", - }, - overlay: { - position: "absolute", - top: 0, - left: 0, - right: 0, - bottom: 0, - backgroundColor: "rgba(0, 0, 0, 0.5)", // Lớp nền bán trong suốt - zIndex: 98, // Đảm bảo lớp overlay nằm dưới menu - }, }); export default Header; diff --git a/src/components/header/Menu.tsx b/src/components/header/Menu.tsx new file mode 100644 index 0000000..47bc9b9 --- /dev/null +++ b/src/components/header/Menu.tsx @@ -0,0 +1,197 @@ +import React, { useState, useRef, useEffect } from "react"; +import { + View, + StyleSheet, + Image, + Text, + TextInput, + TouchableOpacity, + Dimensions, + Modal, + Animated, +} from "react-native"; +import { Ionicons } from "@expo/vector-icons"; + +const MainMenu = ({ + visible, + onClose, +}: { + visible: boolean; + onClose: () => void; +}) => { + const [internalVisible, setInternalVisible] = useState(visible); + const slideAnim = useRef(new Animated.Value(-winWidth * 0.85)).current; + + useEffect(() => { + if (visible) { + setInternalVisible(true); + Animated.timing(slideAnim, { + toValue: 0, + duration: 250, + useNativeDriver: false, + }).start(); + } else { + Animated.timing(slideAnim, { + toValue: -winWidth * 0.85, + duration: 250, + useNativeDriver: false, + }).start(() => { + setInternalVisible(false); // Tắt Modal sau animation + }); + } + }, [visible]); + + if (!internalVisible) return null; + + return ( + + + + + Menu + + + + + + + + + Build PC + + + + + + + Tìm người bán + + + + + + + Địa chỉ sửa chữa + + + + + + + Hỏi đáp + + + + + + + Sản phẩm đã lưu + + + + + + + Tin rao vặt + + + + + + + ); +}; + +export { MainMenu }; + +let winWidth = Dimensions.get("window").width; //full width +let winHeight = Dimensions.get("window").height; //full height + +const styles = StyleSheet.create({ + headerMenu: { + alignItems: "center", + justifyContent: "space-between", + flexDirection: "row", + padding: 10, + backgroundColor: "#462F91", + }, + menuFixed: { + width: "85%", + height: "100%", + backgroundColor: "#fff", + zIndex: 999, + }, + headerMenuText: { + color: "#fff", + fontWeight: "bold", + }, + closeMenu: { + backgroundColor: "#fff", + width: 20, + height: 20, + color: "#000", + borderRadius: 50, + }, + iconFix: { + width: 25, + resizeMode: "contain", + }, + itemMenu: { + alignItems: "center", + flexDirection: "row", + justifyContent: "space-between", + gap: 10, + marginBottom: 10, + padding: 10, + borderBottomWidth: 1, + borderBottomColor: "#e1e1e1", + height: 50, + }, + itemText: { + fontSize: 15, + color: "#000", + fontWeight: "bold", + }, + textLeft: { + alignItems: "center", + gap: 10, + flexDirection: "row", + }, + overlay: { + position: "absolute", + top: 0, + left: 0, + right: 0, + bottom: 0, + backgroundColor: "rgba(0, 0, 0, 0.5)", // Lớp nền bán trong suốt + zIndex: 98, // Đảm bảo lớp overlay nằm dưới menu + }, +}); diff --git a/src/components/product/ItemProduct.tsx b/src/components/product/ItemProduct.tsx index 1d3d1d6..3a3be76 100644 --- a/src/components/product/ItemProduct.tsx +++ b/src/components/product/ItemProduct.tsx @@ -99,7 +99,7 @@ const styles = StyleSheet.create({ backgroundColor: "#fff", }, productImage: { - width: winWidth / 2 - 44, + width: "100%", height: 150, position: "relative", marginBottom: 5, @@ -112,8 +112,8 @@ const styles = StyleSheet.create({ }, boxSaleoff: { position: "absolute", - right: 10, - top: 10, + right: 0, + top: 0, width: 35, height: 35, borderRadius: 25, diff --git a/src/components/product/itemProductSave.tsx b/src/components/product/itemProductSave.tsx index fbf1d95..aae27af 100644 --- a/src/components/product/itemProductSave.tsx +++ b/src/components/product/itemProductSave.tsx @@ -37,6 +37,7 @@ const ItemProductSave = ({ product }: { product: any }) => { source={require("../../../assets/images/icon_heart.png")} style={styles.imgsave} alt="icon-heart" + resizeMode="contain" /> @@ -74,10 +75,10 @@ const ItemProductSave = ({ product }: { product: any }) => { const styles = StyleSheet.create({ productItem: { - width: winWidth / 2 - 20, + width: winWidth / 2 - 15, }, productImage: { - width: winWidth / 2 - 20, + width: "100%", height: 200, position: "relative", marginBottom: 5, @@ -85,6 +86,7 @@ const styles = StyleSheet.create({ borderColor: "#d3d3d3", backgroundColor: "#fff", borderRadius: 8, + overflow: "hidden", }, productImg: { width: "100%", diff --git a/src/layouts/AppLayout.tsx b/src/layouts/AppLayout.tsx index 751be92..1bf0de1 100644 --- a/src/layouts/AppLayout.tsx +++ b/src/layouts/AppLayout.tsx @@ -1,12 +1,24 @@ -import React from "react"; -import { View, StyleSheet, ScrollView } from "react-native"; +import React, { useState } from "react"; +import { + View, + StyleSheet, + ScrollView, + Dimensions, + Platform, +} from "react-native"; import { useNavigation, NavigationProp, NavigationContainer, } from "@react-navigation/native"; +import { SafeAreaView } from "react-native-safe-area-context"; import Header from "../components/header/Header"; +import { MainMenu } from "@components/header/Menu"; +import Footer from "../components/footer/Footer"; + import ButtonFooter from "../components/footer/ButtonFooter"; +var winWidth = Dimensions.get("window").width; //full width +const winHeight = Dimensions.get("window").height; type Props = { children: React.ReactNode; @@ -15,27 +27,49 @@ type Props = { const AppLayout = ({ children, activeTab }: Props) => { const navigation = useNavigation>(); + const [isMenuOpen, setIsMenuOpen] = useState(false); return ( - -
- {children} + +
setIsMenuOpen(true)} /> + setIsMenuOpen(false)} /> + + {children} + + +