upload 04/08
This commit is contained in:
10
App.tsx
10
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 (
|
||||
<SafeAreaProvider>
|
||||
<NavigationContainer>
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -14,5 +14,6 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
],
|
||||
'react-native-reanimated/plugin'
|
||||
],
|
||||
};
|
||||
|
||||
93
package-lock.json
generated
93
package-lock.json
generated
@@ -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": {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -221,7 +221,7 @@ export function CreateBuildpc() {
|
||||
</View>
|
||||
{/* Popup */}
|
||||
{showPopup && (
|
||||
<PopupBuildpc visible={showPopup} onClose={() => setShowPopup(false)} />
|
||||
<PopupBuildpc show={showPopup} onClose={() => setShowPopup(false)} />
|
||||
)}
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
@@ -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<Props> = ({ navigation, activeTab }) => {
|
||||
onPress={() => navigation?.navigate(tab.route)}
|
||||
>
|
||||
<Ionicons
|
||||
name={tab.icon}
|
||||
name={tab?.icon}
|
||||
size={22}
|
||||
color={isActive ? "#4a00e0" : "#666"}
|
||||
/>
|
||||
@@ -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",
|
||||
|
||||
@@ -82,7 +82,8 @@ const Footer: React.FC<Props> = ({ navigation, activeTab = "homepage" }) => {
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<Collapsible collapsed={activeIndex !== index}>
|
||||
{item.links?.map((link, linkIndex) => (
|
||||
{item.links && item.links.length > 0 ? (
|
||||
item.links.map((link, linkIndex) => (
|
||||
<TouchableOpacity
|
||||
key={linkIndex}
|
||||
style={styles.linkItem}
|
||||
@@ -90,7 +91,10 @@ const Footer: React.FC<Props> = ({ navigation, activeTab = "homepage" }) => {
|
||||
>
|
||||
<Text style={styles.linkText}>{link.title}</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
))
|
||||
) : item.content ? (
|
||||
<Text style={styles.accordionContent}>{item.content}</Text>
|
||||
) : null}
|
||||
</Collapsible>
|
||||
</View>
|
||||
))}
|
||||
|
||||
@@ -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 (
|
||||
<View>
|
||||
<View style={styles.BoxHeader}>
|
||||
<View style={styles.headerTop}>
|
||||
<View style={styles.headerTopLeft}>
|
||||
<TouchableOpacity onPress={toggleDrawer} style={styles.menu}>
|
||||
<TouchableOpacity onPress={toggleMenu} style={styles.menu}>
|
||||
<Ionicons style={styles.iconMenu} name="menu-outline" size={30} />
|
||||
</TouchableOpacity>
|
||||
<Image
|
||||
@@ -58,6 +49,20 @@ const Header = () => {
|
||||
name="caret-down-outline"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.searchContainer}>
|
||||
<View style={styles.searchBar}>
|
||||
<TextInput
|
||||
style={styles.searchInput}
|
||||
placeholder="Tìm kiếm khuyến mãi, cửa hàng, sản phẩm,..."
|
||||
placeholderTextColor="rgba(169, 169, 169, 1)"
|
||||
/>
|
||||
<Ionicons style={styles.iconMenu} name="search-outline" size={19} />
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
openSort
|
||||
@@ -68,12 +73,7 @@ const Header = () => {
|
||||
<TouchableOpacity
|
||||
style={[styles.boxSortItem, styles.boxSortItemActive]}
|
||||
>
|
||||
<Text
|
||||
style={[
|
||||
styles.boxSortItemText,
|
||||
styles.boxSortItemTextActive,
|
||||
]}
|
||||
>
|
||||
<Text style={[styles.boxSortItemText, styles.boxSortItemTextActive]}>
|
||||
Hà nội
|
||||
</Text>
|
||||
<Ionicons
|
||||
@@ -89,115 +89,34 @@ const Header = () => {
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.searchContainer}>
|
||||
<View style={styles.searchBar}>
|
||||
<TextInput
|
||||
style={styles.searchInput}
|
||||
placeholder="Tìm kiếm khuyến mãi, cửa hàng, sản phẩm,..."
|
||||
placeholderTextColor="rgba(169, 169, 169, 1)"
|
||||
/>
|
||||
<Ionicons style={styles.iconMenu} name="search-outline" size={19} />
|
||||
</View>
|
||||
</View>
|
||||
{isMenuOpen && (
|
||||
<View style={styles.overlay} onTouchStart={closeMenu}>
|
||||
<MainMenu closeMenu={closeMenu} />
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const MainMenu = ({ closeMenu }: { closeMenu: () => void }) => {
|
||||
return (
|
||||
<View style={styles.menuFixed}>
|
||||
<View style={styles.headerMenu}>
|
||||
<Text style={styles.headerMenuText}>Menu</Text>
|
||||
<TouchableOpacity onPress={closeMenu}>
|
||||
<Ionicons style={styles.closeMenu} name="close-outline" size={20} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View>
|
||||
<TouchableOpacity style={styles.itemMenu}>
|
||||
<View style={styles.textLeft}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_buildpc.png")}
|
||||
style={styles.iconBuild}
|
||||
/>
|
||||
<Text style={styles.itemText}>Build PC</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward-outline" size={20} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.itemMenu}>
|
||||
<View style={styles.textLeft}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_store.png")}
|
||||
style={styles.iconStore}
|
||||
/>
|
||||
<Text style={styles.itemText}>Tìm người bán</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward-outline" size={20} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.itemMenu}>
|
||||
<View style={styles.textLeft}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_location.png")}
|
||||
style={styles.iconLocation}
|
||||
/>
|
||||
<Text style={styles.itemText}>Địa chỉ sửa chữa</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward-outline" size={20} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.itemMenu}>
|
||||
<View style={styles.textLeft}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_question.png")}
|
||||
style={styles.iconProduct}
|
||||
/>
|
||||
<Text style={styles.itemText}>Hỏi đáp</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward-outline" size={20} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.itemMenu}>
|
||||
<View style={styles.textLeft}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_box.png")}
|
||||
style={styles.iconBox}
|
||||
/>
|
||||
<Text style={styles.itemText}>Sản phẩm đã lưu</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward-outline" size={20} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.itemMenu}>
|
||||
<View style={styles.textLeft}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_article.png")}
|
||||
style={styles.iconArticle}
|
||||
/>
|
||||
<Text style={styles.itemText}>Tin rao vặt</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward-outline" size={20} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
197
src/components/header/Menu.tsx
Normal file
197
src/components/header/Menu.tsx
Normal file
@@ -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 (
|
||||
<Modal visible={internalVisible} transparent animationType="none">
|
||||
<TouchableOpacity
|
||||
style={styles.overlay}
|
||||
onPress={onClose}
|
||||
activeOpacity={1}
|
||||
/>
|
||||
<Animated.View style={[styles.menuFixed, { left: slideAnim }]}>
|
||||
<View style={styles.headerMenu}>
|
||||
<Text style={styles.headerMenuText}>Menu</Text>
|
||||
<TouchableOpacity onPress={onClose}>
|
||||
<Ionicons name="close-outline" size={20} style={styles.closeMenu} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View>
|
||||
<TouchableOpacity style={styles.itemMenu}>
|
||||
<View style={styles.textLeft}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_buildpc.png")}
|
||||
style={styles.iconFix}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
<Text style={styles.itemText}>Build PC</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward-outline" size={20} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.itemMenu}>
|
||||
<View style={styles.textLeft}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_store.png")}
|
||||
style={styles.iconFix}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
<Text style={styles.itemText}>Tìm người bán</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward-outline" size={20} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.itemMenu}>
|
||||
<View style={styles.textLeft}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_location.png")}
|
||||
style={styles.iconFix}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
<Text style={styles.itemText}>Địa chỉ sửa chữa</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward-outline" size={20} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.itemMenu}>
|
||||
<View style={styles.textLeft}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_question.png")}
|
||||
style={styles.iconFix}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
<Text style={styles.itemText}>Hỏi đáp</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward-outline" size={20} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.itemMenu}>
|
||||
<View style={styles.textLeft}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_box.png")}
|
||||
style={styles.iconFix}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
<Text style={styles.itemText}>Sản phẩm đã lưu</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward-outline" size={20} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.itemMenu}>
|
||||
<View style={styles.textLeft}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_article.png")}
|
||||
style={styles.iconFix}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
<Text style={styles.itemText}>Tin rao vặt</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward-outline" size={20} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</Animated.View>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
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
|
||||
},
|
||||
});
|
||||
@@ -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,
|
||||
|
||||
@@ -37,6 +37,7 @@ const ItemProductSave = ({ product }: { product: any }) => {
|
||||
source={require("../../../assets/images/icon_heart.png")}
|
||||
style={styles.imgsave}
|
||||
alt="icon-heart"
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
@@ -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%",
|
||||
|
||||
@@ -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<NavigationProp<any>>();
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Header />
|
||||
<View style={styles.content}>{children}</View>
|
||||
<SafeAreaView style={styles.wrapper}>
|
||||
<Header toggleMenu={() => setIsMenuOpen(true)} />
|
||||
<MainMenu visible={isMenuOpen} onClose={() => setIsMenuOpen(false)} />
|
||||
<ScrollView
|
||||
style={styles.scroll}
|
||||
contentContainerStyle={styles.scrollContainer}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
>
|
||||
{children}
|
||||
</ScrollView>
|
||||
|
||||
<Footer navigation={navigation} />
|
||||
<ButtonFooter navigation={navigation} activeTab={activeTab} />
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppLayout;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
marginLeft: "auto",
|
||||
marginRight: "auto",
|
||||
maxWidth: 480,
|
||||
wrapper: {
|
||||
flex: 1,
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
content: {
|
||||
scroll: {
|
||||
flex: 1,
|
||||
...Platform.select({
|
||||
web: { marginTop: 113 },
|
||||
default: { marginTop: 0 },
|
||||
}),
|
||||
},
|
||||
scrollWrapper: {
|
||||
flex: 1,
|
||||
overflow: "scroll",
|
||||
},
|
||||
scrollContainer: {
|
||||
flexGrow: 1,
|
||||
},
|
||||
webScrollArea: {
|
||||
flex: 1,
|
||||
overflow: "auto" as any,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -25,6 +25,7 @@ const AppNavigator: React.FC = () => {
|
||||
<Stack.Screen name="buildpc" component={Buildpc} />
|
||||
<Stack.Screen name="comparebuildpc" component={CompareBuildpc} />
|
||||
<Stack.Screen name="buildpcdetail" component={BuildpcDeail} />
|
||||
<Stack.Screen name="classifieds" component={BuildpcDeail} />
|
||||
</Stack.Navigator>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// src/screens/HomeScreen.tsx
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useRef } from "react";
|
||||
import { useNavigation, NavigationProp } from "@react-navigation/native";
|
||||
import {
|
||||
View,
|
||||
@@ -11,9 +11,9 @@ import {
|
||||
ImageBackground,
|
||||
TouchableOpacity,
|
||||
SafeAreaView,
|
||||
ScrollViewBase,
|
||||
} from "react-native";
|
||||
import { globalStyles } from "../styles/globalStyles";
|
||||
import Swiper from "react-native-swiper";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { products } from "../data/product";
|
||||
import ProductItem from "../components/product/ItemProduct";
|
||||
@@ -23,17 +23,19 @@ import chunk from "lodash/chunk";
|
||||
import { globalAgent } from "http";
|
||||
import { WebView } from "react-native-webview";
|
||||
import AppLayout from "../layouts/AppLayout";
|
||||
import Footer from "../components/footer/Footer";
|
||||
import Carousel, { ICarouselInstance } from "react-native-reanimated-carousel";
|
||||
|
||||
var winWidth = Dimensions.get("window").width; //full width
|
||||
var winHeight = Dimensions.get("window").height; //full height
|
||||
const ratio = winWidth / 930;
|
||||
|
||||
const HomeScreen: React.FC = () => {
|
||||
const navigation = useNavigation<NavigationProp<any>>();
|
||||
return (
|
||||
<AppLayout activeTab="homepage">
|
||||
<ScrollView>
|
||||
<ScrollView
|
||||
keyboardShouldPersistTaps="handled"
|
||||
showsVerticalScrollIndicator={true}
|
||||
>
|
||||
<SliderHome />
|
||||
<BoxMenuHome />
|
||||
<BoxProductReviewTop />
|
||||
@@ -45,67 +47,58 @@ const HomeScreen: React.FC = () => {
|
||||
<BoxArticleClassifieds />
|
||||
<BoxBannerSaleHome />
|
||||
<BoxPromotionHome />
|
||||
<Footer navigation={navigation} />
|
||||
</ScrollView>
|
||||
</AppLayout>
|
||||
);
|
||||
};
|
||||
|
||||
const SliderHome = () => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
const carouselRef = useRef<ICarouselInstance>(null);
|
||||
|
||||
const handleDotPress = (index: number) => {
|
||||
if (carouselRef.current) {
|
||||
carouselRef.current?.scrollTo({ index, animated: true });
|
||||
}
|
||||
};
|
||||
|
||||
const banner_list = [
|
||||
require("../../assets/images/banner_slider.png"),
|
||||
require("../../assets/images/banner_slider.png"),
|
||||
require("../../assets/images/banner_slider.png"),
|
||||
require("../../assets/images/banner_slider.png"),
|
||||
];
|
||||
|
||||
return (
|
||||
<View style={styles.slider}>
|
||||
<Swiper
|
||||
style={styles.sliderSwipper}
|
||||
autoplay={false}
|
||||
autoplayTimeout={3}
|
||||
showsButtons={true}
|
||||
showsPagination={false}
|
||||
nextButton={
|
||||
<Ionicons
|
||||
name="chevron-forward-outline"
|
||||
size={30}
|
||||
color="white"
|
||||
style={styles.buttonNext}
|
||||
<Carousel
|
||||
loop
|
||||
autoPlay
|
||||
autoPlayInterval={3000}
|
||||
width={winWidth}
|
||||
height={200}
|
||||
data={banner_list}
|
||||
scrollAnimationDuration={1000}
|
||||
onSnapToItem={(index) => {
|
||||
setCurrentIndex(index);
|
||||
}}
|
||||
renderItem={({ item }) => (
|
||||
<Image source={item} style={styles.imgSlider} resizeMode="cover" />
|
||||
)}
|
||||
/>
|
||||
}
|
||||
prevButton={
|
||||
<Ionicons
|
||||
name="chevron-back-outline"
|
||||
size={30}
|
||||
color="white"
|
||||
style={styles.buttonPrev}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<View style={styles.imgContainer}>
|
||||
<Image
|
||||
style={styles.imgSlider}
|
||||
source={require("../../assets/images/banner_slider.png")}
|
||||
resizeMode="cover"
|
||||
<View style={globalStyles.dotWrapper}>
|
||||
{banner_list.map((_, index) => (
|
||||
<TouchableOpacity key={index} onPress={() => handleDotPress(index)}>
|
||||
<View
|
||||
key={index}
|
||||
style={[
|
||||
globalStyles.dot,
|
||||
currentIndex === index && globalStyles.activeDot,
|
||||
]}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
<View style={styles.imgContainer}>
|
||||
<Image
|
||||
style={styles.imgSlider}
|
||||
source={require("../../assets/images/banner_slider.png")}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.imgContainer}>
|
||||
<Image
|
||||
style={styles.imgSlider}
|
||||
source={require("../../assets/images/banner_slider.png")}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.imgContainer}>
|
||||
<Image
|
||||
style={styles.imgSlider}
|
||||
source={require("../../assets/images/banner_slider.png")}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
</View>
|
||||
</Swiper>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -252,124 +245,132 @@ const BoxProductReviewTop = () => {
|
||||
|
||||
const BoxCategoryHome = () => {
|
||||
const chunkedItems = chunk(categories, 8);
|
||||
const [activeIndex, setActiveIndex] = useState(0);
|
||||
const carouselRef = useRef<ICarouselInstance>(null);
|
||||
|
||||
const handleDotPress = (index: number) => {
|
||||
if (carouselRef.current) {
|
||||
carouselRef.current?.scrollTo({ index, animated: true });
|
||||
}
|
||||
};
|
||||
return (
|
||||
<View style={globalStyles.boxCategoryHome}>
|
||||
<Text style={globalStyles.textBoxCategoryHome}>Tìm theo danh mục</Text>
|
||||
<Swiper
|
||||
style={globalStyles.listCategoryBox}
|
||||
<Carousel
|
||||
loop={false}
|
||||
showsPagination={true}
|
||||
dot={<View style={globalStyles.dot} />}
|
||||
activeDot={<View style={globalStyles.activeDot} />}
|
||||
paginationStyle={{
|
||||
bottom: 10,
|
||||
}}
|
||||
>
|
||||
{chunkedItems.map((group, slideIndex) => (
|
||||
width={winWidth}
|
||||
height={300}
|
||||
data={chunkedItems}
|
||||
scrollAnimationDuration={500}
|
||||
onSnapToItem={(index) => setActiveIndex(index)}
|
||||
renderItem={({ item }) => (
|
||||
<View
|
||||
key={`slide-${slideIndex}`}
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
justifyContent: "space-between",
|
||||
paddingHorizontal: 10,
|
||||
}}
|
||||
>
|
||||
{group.map((item) => (
|
||||
<TouchableOpacity key={item.id} style={globalStyles.categoryItem}>
|
||||
{item.map((cat) => (
|
||||
<TouchableOpacity key={cat.id} style={globalStyles.categoryItem}>
|
||||
<View style={globalStyles.boxImageCategory}>
|
||||
<Image
|
||||
source={require("../../assets/images/category-laptop.png")}
|
||||
style={globalStyles.iconCategory}
|
||||
/>
|
||||
</View>
|
||||
<Text style={globalStyles.categoryName}>{item.name}</Text>
|
||||
<Text style={globalStyles.categoryName}>{cat.name}</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
)}
|
||||
/>
|
||||
<View style={globalStyles.dotWrapper}>
|
||||
{chunkedItems.map((_, index) => (
|
||||
<TouchableOpacity key={index} onPress={() => handleDotPress(index)}>
|
||||
<View
|
||||
key={index}
|
||||
style={[
|
||||
globalStyles.dot,
|
||||
activeIndex === index && globalStyles.activeDot,
|
||||
]}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</Swiper>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const BoxBusiness = () => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
const carouselRef = useRef<ICarouselInstance>(null);
|
||||
|
||||
const handleDotPress = (index: number) => {
|
||||
if (carouselRef.current) {
|
||||
carouselRef.current?.scrollTo({ index, animated: true });
|
||||
}
|
||||
};
|
||||
|
||||
const slides = [
|
||||
[
|
||||
require("../../assets/images/logo-hacom.png"),
|
||||
require("../../assets/images/logo-hacom.png"),
|
||||
require("../../assets/images/logo-anphat.png"),
|
||||
require("../../assets/images/logo-gearvn.png"),
|
||||
],
|
||||
[
|
||||
require("../../assets/images/logo-hacom.png"),
|
||||
require("../../assets/images/logo-hacom.png"),
|
||||
require("../../assets/images/logo-anphat.png"),
|
||||
require("../../assets/images/logo-gearvn.png"),
|
||||
],
|
||||
];
|
||||
|
||||
return (
|
||||
<View style={globalStyles.BoxBusiness}>
|
||||
<Text style={globalStyles.textBoxBusiness}>DOANH NGHIỆP NỔI BẬT</Text>
|
||||
|
||||
<Swiper
|
||||
<Carousel
|
||||
style={globalStyles.sliderBusinesses}
|
||||
autoplay={false}
|
||||
showsPagination={true}
|
||||
dot={<View style={globalStyles.dot} />}
|
||||
activeDot={<View style={globalStyles.activeDot} />}
|
||||
paginationStyle={{
|
||||
bottom: 10,
|
||||
}}
|
||||
>
|
||||
loop={false}
|
||||
width={winWidth}
|
||||
height={45}
|
||||
data={slides}
|
||||
scrollAnimationDuration={500}
|
||||
onSnapToItem={(index) => setCurrentIndex(index)}
|
||||
renderItem={({ item }) => (
|
||||
<View style={{ flexDirection: "row", paddingHorizontal: 10 }}>
|
||||
{item.map((logo, idx) => (
|
||||
<TouchableOpacity key={idx} style={globalStyles.logoItem}>
|
||||
<Image source={logo} style={globalStyles.logoImage} />
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* Custom Dots */}
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
paddingHorizontal: 10,
|
||||
justifyContent: "center",
|
||||
marginTop: 10,
|
||||
}}
|
||||
>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-hacom.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-hacom.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-anphat.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-gearvn.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
{slides.map((_, index) => (
|
||||
<TouchableOpacity key={index} onPress={() => handleDotPress(index)}>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
paddingHorizontal: 10,
|
||||
}}
|
||||
>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-hacom.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-hacom.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-anphat.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-gearvn.png")}
|
||||
style={globalStyles.logoImage}
|
||||
key={index}
|
||||
style={[
|
||||
globalStyles.dot,
|
||||
currentIndex === index && globalStyles.activeDot,
|
||||
]}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
</Swiper>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -738,67 +739,65 @@ const BoxArticleClassifieds = () => {
|
||||
};
|
||||
|
||||
const BoxBannerSaleHome = () => {
|
||||
const [activeIndex, setActiveIndex] = useState(0);
|
||||
const carouselRef = useRef<ICarouselInstance>(null);
|
||||
|
||||
const slides = [
|
||||
[
|
||||
require("../../assets/images/banner-sale-1.png"),
|
||||
require("../../assets/images/banner-sale-2.png"),
|
||||
],
|
||||
[
|
||||
require("../../assets/images/banner-sale-2.png"),
|
||||
require("../../assets/images/banner-sale-3.png"),
|
||||
],
|
||||
[
|
||||
require("../../assets/images/banner-sale-3.png"),
|
||||
require("../../assets/images/banner-sale-1.png"),
|
||||
],
|
||||
];
|
||||
|
||||
const handleDotPress = (index: number) => {
|
||||
if (carouselRef.current) {
|
||||
carouselRef.current.scrollTo({ index, animated: true });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={globalStyles.BoxBannerSaleHome}>
|
||||
<Swiper
|
||||
style={globalStyles.sliderBannerSale}
|
||||
autoplay={false}
|
||||
showsPagination={true}
|
||||
dot={<View style={globalStyles.dot} />}
|
||||
activeDot={<View style={globalStyles.activeDot} />}
|
||||
paginationStyle={{
|
||||
bottom: 10,
|
||||
}}
|
||||
>
|
||||
<View style={{ flexDirection: "row" }}>
|
||||
<TouchableOpacity style={globalStyles.itemBannerSale}>
|
||||
<Image
|
||||
source={require("../../assets/images/banner-sale-1.png")}
|
||||
style={globalStyles.imgBannerSale}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.itemBannerSale}>
|
||||
<Image
|
||||
source={require("../../assets/images/banner-sale-2.png")}
|
||||
style={globalStyles.imgBannerSale}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
<Carousel
|
||||
ref={carouselRef}
|
||||
width={winWidth}
|
||||
height={220}
|
||||
data={slides}
|
||||
loop
|
||||
autoPlay
|
||||
autoPlayInterval={5000}
|
||||
scrollAnimationDuration={600}
|
||||
onSnapToItem={(index) => setActiveIndex(index)}
|
||||
renderItem={({ item }) => (
|
||||
<View style={{ flexDirection: "row", paddingHorizontal: 10 }}>
|
||||
{item.map((logo, idx) => (
|
||||
<TouchableOpacity key={idx} style={globalStyles.itemBannerSale}>
|
||||
<Image source={logo} style={globalStyles.imgBannerSale} />
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
<View style={{ flexDirection: "row" }}>
|
||||
<TouchableOpacity style={globalStyles.itemBannerSale}>
|
||||
<Image
|
||||
source={require("../../assets/images/banner-sale-2.png")}
|
||||
style={globalStyles.imgBannerSale}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.itemBannerSale}>
|
||||
<Image
|
||||
source={require("../../assets/images/banner-sale-3.png")}
|
||||
style={globalStyles.imgBannerSale}
|
||||
alt="anh tin tuc"
|
||||
)}
|
||||
/>
|
||||
<View style={globalStyles.dotWrapper}>
|
||||
{slides.map((_, index) => (
|
||||
<TouchableOpacity key={index} onPress={() => handleDotPress(index)}>
|
||||
<View
|
||||
style={
|
||||
index === activeIndex
|
||||
? globalStyles.activeDot
|
||||
: globalStyles.dot
|
||||
}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
<View style={{ flexDirection: "row" }}>
|
||||
<TouchableOpacity style={globalStyles.itemBannerSale}>
|
||||
<Image
|
||||
source={require("../../assets/images/banner-sale-3.png")}
|
||||
style={globalStyles.imgBannerSale}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.itemBannerSale}>
|
||||
<Image
|
||||
source={require("../../assets/images/banner-sale-1.png")}
|
||||
style={globalStyles.imgBannerSale}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</Swiper>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -899,6 +898,7 @@ const styles = StyleSheet.create({
|
||||
overflow: "hidden",
|
||||
borderRadius: 10,
|
||||
margin: 10,
|
||||
flex: 1,
|
||||
},
|
||||
sliderSwipper: {
|
||||
height: 210,
|
||||
@@ -913,11 +913,12 @@ const styles = StyleSheet.create({
|
||||
objectFit: "cover",
|
||||
},
|
||||
imgSlider: {
|
||||
width: winWidth,
|
||||
width: winWidth - 20,
|
||||
height: "100%",
|
||||
objectFit: "cover",
|
||||
overflow: "hidden",
|
||||
borderRadius: 10,
|
||||
marginRight: 10,
|
||||
},
|
||||
buttonNext: {
|
||||
color: "#fff", // Màu chữ cho các nút chuyển
|
||||
@@ -930,15 +931,19 @@ const styles = StyleSheet.create({
|
||||
fontWeight: "bold",
|
||||
},
|
||||
boxMenuHome: {
|
||||
marginTop: 10,
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
justifyContent: "flex-start",
|
||||
marginLeft: 20,
|
||||
marginRight: 20,
|
||||
gap: 20,
|
||||
gap: 10,
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
MenuItem: {
|
||||
width: winWidth / 4 - 25,
|
||||
width: winWidth / 4 - 20,
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
},
|
||||
boxIconMenu: {
|
||||
width: 50,
|
||||
@@ -948,14 +953,15 @@ const styles = StyleSheet.create({
|
||||
justifyContent: "center",
|
||||
backgroundColor: "#eeeeee",
|
||||
borderRadius: 25,
|
||||
marginLeft: "auto",
|
||||
marginRight: "auto",
|
||||
flexDirection: "row",
|
||||
margin: "auto",
|
||||
},
|
||||
textMenu: {
|
||||
textAlign: "center",
|
||||
fontSize: 14,
|
||||
color: "#333",
|
||||
fontWeight: "bold",
|
||||
height: 35,
|
||||
},
|
||||
iconMenuItem: {
|
||||
width: 20,
|
||||
|
||||
@@ -92,7 +92,6 @@ export default function Buildpc() {
|
||||
{/* Buildpc Content */}
|
||||
<CreateBuildpc />
|
||||
</View>
|
||||
<Footer navigation={navigation} />
|
||||
</ScrollView>
|
||||
</AppLayout>
|
||||
);
|
||||
@@ -136,6 +135,7 @@ const styles = StyleSheet.create({
|
||||
marginTop: 12,
|
||||
backgroundColor: "#fff",
|
||||
borderRadius: 8,
|
||||
marginBottom: 10,
|
||||
},
|
||||
inputBox: {
|
||||
flexDirection: "row",
|
||||
|
||||
@@ -81,7 +81,6 @@ export function BuildpcDeail() {
|
||||
{/* đánh giá */}
|
||||
<ReviewList />
|
||||
</View>
|
||||
<Footer navigation={navigation} />
|
||||
</ScrollView>
|
||||
</AppLayout>
|
||||
);
|
||||
|
||||
@@ -58,7 +58,6 @@ export function CompareBuildpc() {
|
||||
|
||||
<ListCompare />
|
||||
</View>
|
||||
<Footer navigation={navigation} />
|
||||
</ScrollView>
|
||||
</AppLayout>
|
||||
);
|
||||
|
||||
76
src/screens/classifieds/HomeClassifieds.tsx
Normal file
76
src/screens/classifieds/HomeClassifieds.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import React from "react";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
Image,
|
||||
TouchableOpacity,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Dimensions,
|
||||
} from "react-native";
|
||||
const { width } = Dimensions.get("window");
|
||||
import { useNavigation, NavigationProp } from "@react-navigation/native";
|
||||
import Footer from "@components/footer/Footer";
|
||||
import AppLayout from "@layouts/AppLayout";
|
||||
import { Ionicons } from "@expo/vector-icons"; // hoặc icon_2025 nếu bạn có icon font riêng
|
||||
|
||||
export default function ListCompare() {
|
||||
const navigation = useNavigation<NavigationProp<any>>();
|
||||
|
||||
return (
|
||||
<AppLayout activeTab="classifieds">
|
||||
<ScrollView>
|
||||
<View style={styles.container}>
|
||||
{/* Breadcrumb */}
|
||||
<View style={styles.breadcrumb}>
|
||||
<View style={styles.breadcrumbItem}>
|
||||
<TouchableOpacity>
|
||||
<Ionicons
|
||||
name="home"
|
||||
size={16}
|
||||
color="#637381"
|
||||
style={styles.icon}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<Text style={styles.angle}>›</Text>
|
||||
</View>
|
||||
<View style={styles.breadcrumbItem}>
|
||||
<Text style={styles.text}>Rao vặt</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.boxCategory}>
|
||||
<Text>Danh mục</Text>
|
||||
</View>
|
||||
</View>
|
||||
<Footer navigation={navigation} />
|
||||
</ScrollView>
|
||||
</AppLayout>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
paddingHorizontal: 10,
|
||||
},
|
||||
breadcrumb: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
paddingVertical: 12,
|
||||
flexWrap: "wrap",
|
||||
},
|
||||
breadcrumbItem: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginRight: 8,
|
||||
},
|
||||
text: {
|
||||
color: "#000",
|
||||
},
|
||||
icon: {
|
||||
marginRight: 5,
|
||||
},
|
||||
angle: {
|
||||
marginLeft: 12,
|
||||
color: "#888",
|
||||
},
|
||||
});
|
||||
@@ -24,7 +24,6 @@ import ProductInformation from "./ProductInformation";
|
||||
import ProductSpecification from "./ProductSpecification";
|
||||
import { products } from "../../data/product";
|
||||
import ProductItem from "@components/product/ItemProduct";
|
||||
import Footer from "@components/footer/Footer";
|
||||
|
||||
const ProductDetail = () => {
|
||||
const navigation = useNavigation<NavigationProp<any>>();
|
||||
@@ -192,7 +191,6 @@ const ProductDetail = () => {
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
<Footer navigation={navigation} />
|
||||
</ScrollView>
|
||||
</AppLayout>
|
||||
);
|
||||
@@ -358,7 +356,7 @@ const styles = StyleSheet.create({
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
gap: 5,
|
||||
marginLeft: 7,
|
||||
marginTop: 10,
|
||||
marginLeft: 7,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -70,7 +70,6 @@ const ProductList = () => {
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
<Footer navigation={navigation} />
|
||||
</ScrollView>
|
||||
</AppLayout>
|
||||
);
|
||||
|
||||
@@ -67,7 +67,6 @@ const ProductListBig = () => {
|
||||
showsVerticalScrollIndicator={false}
|
||||
/>
|
||||
</View>
|
||||
<Footer navigation={navigation} />
|
||||
</ScrollView>
|
||||
</AppLayout>
|
||||
);
|
||||
|
||||
@@ -51,7 +51,7 @@ export const globalStyles = StyleSheet.create({
|
||||
marginBottom: 10,
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
gap: 10
|
||||
gap: 10,
|
||||
},
|
||||
moreAll: {
|
||||
width: 110,
|
||||
@@ -85,8 +85,11 @@ export const globalStyles = StyleSheet.create({
|
||||
height: 300
|
||||
},
|
||||
categoryItem: {
|
||||
width: '25%',
|
||||
marginBottom: 25
|
||||
width: winWidth / 4 - 15,
|
||||
marginBottom: 25,
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
boxImageCategory: {
|
||||
width: 70,
|
||||
@@ -99,7 +102,8 @@ export const globalStyles = StyleSheet.create({
|
||||
alignItems: 'center',
|
||||
},
|
||||
iconCategory: {
|
||||
width: 50,
|
||||
width: 45,
|
||||
height: 45,
|
||||
objectFit: 'contain',
|
||||
},
|
||||
categoryName: {
|
||||
@@ -107,6 +111,15 @@ export const globalStyles = StyleSheet.create({
|
||||
fontWeight: '500',
|
||||
marginTop: 5,
|
||||
textAlign: 'center',
|
||||
height: 40
|
||||
},
|
||||
dotWrapper: {
|
||||
position: 'absolute',
|
||||
bottom: 10,
|
||||
left: 0,
|
||||
right: 0,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
dot: {
|
||||
backgroundColor: 'rgba(0,0,0,.2)',
|
||||
@@ -116,11 +129,7 @@ export const globalStyles = StyleSheet.create({
|
||||
margin: 3,
|
||||
},
|
||||
activeDot: {
|
||||
backgroundColor: '#ff7a00',
|
||||
width: 40,
|
||||
height: 10,
|
||||
borderRadius: 5,
|
||||
margin: 3,
|
||||
backgroundColor: '#f9ef06',
|
||||
},
|
||||
BoxBusiness: {
|
||||
marginTop: 25,
|
||||
@@ -135,10 +144,11 @@ export const globalStyles = StyleSheet.create({
|
||||
},
|
||||
sliderBusinesses: {
|
||||
marginTop: 20,
|
||||
height: 85
|
||||
width: winWidth - 10,
|
||||
marginBottom: 10
|
||||
},
|
||||
logoItem: {
|
||||
width: itemWidth,
|
||||
width: itemWidth - 3,
|
||||
height: 40,
|
||||
borderRadius: 8,
|
||||
backgroundColor: '#fff',
|
||||
@@ -159,7 +169,7 @@ export const globalStyles = StyleSheet.create({
|
||||
marginTop: 20,
|
||||
width: winWidth,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
paddingRight: 10
|
||||
},
|
||||
textBoxProductSaveHome: {
|
||||
fontSize: 20,
|
||||
@@ -289,18 +299,13 @@ export const globalStyles = StyleSheet.create({
|
||||
imgBannerSale: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'cover',
|
||||
resizeMode: 'cover',
|
||||
borderRadius: 12
|
||||
},
|
||||
sliderBannerSale: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
height: 200
|
||||
},
|
||||
itemBannerSale: {
|
||||
width: winWidth - 50,
|
||||
height: 160,
|
||||
objectFit: 'cover',
|
||||
width: winWidth - 80,
|
||||
height: 180,
|
||||
resizeMode: 'cover',
|
||||
marginRight: 10
|
||||
},
|
||||
BoxPromotionHome: {
|
||||
|
||||
Reference in New Issue
Block a user