up
3
.env
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
EXPO_HOME=D:/bestpc_mobile/.expo
|
||||||
|
EXPO_CACHE_DIR=D:/bestpc_mobile/.expo/cache
|
||||||
|
EXPO_PROJECT_DIR=D:/bestpc_mobile
|
||||||
53
App.tsx
@@ -1,20 +1,53 @@
|
|||||||
import { StatusBar } from 'expo-status-bar';
|
import { StatusBar } from "expo-status-bar";
|
||||||
import { StyleSheet, Text, View } from 'react-native';
|
import { StyleSheet, ScrollView } from "react-native";
|
||||||
|
import { SafeAreaProvider } from "react-native-safe-area-context";
|
||||||
|
import { NavigationContainer } from "@react-navigation/native";
|
||||||
|
import {
|
||||||
|
createStackNavigator,
|
||||||
|
StackScreenProps,
|
||||||
|
} from "@react-navigation/stack";
|
||||||
|
import {
|
||||||
|
createDrawerNavigator,
|
||||||
|
DrawerItemList,
|
||||||
|
DrawerItem,
|
||||||
|
DrawerContentScrollView,
|
||||||
|
} from "@react-navigation/drawer";
|
||||||
|
|
||||||
|
import Header from "./src/components/header/Header";
|
||||||
|
import Footer from "./src/components/footer/Footer";
|
||||||
|
import HomePage from "./src/screens/HomeScreen";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<SafeAreaProvider>
|
||||||
<Text>Open up App.tsx to start working on your app!</Text>
|
<Header />
|
||||||
<StatusBar style="auto" />
|
<NavigationContainer>
|
||||||
</View>
|
<AllPage />
|
||||||
|
</NavigationContainer>
|
||||||
|
{/* <Footer /> */}
|
||||||
|
</SafeAreaProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const Drawer = createDrawerNavigator();
|
||||||
|
const Stack = createStackNavigator();
|
||||||
|
|
||||||
|
const AllPage = () => {
|
||||||
|
return (
|
||||||
|
<Stack.Navigator
|
||||||
|
initialRouteName="homepage"
|
||||||
|
screenOptions={{
|
||||||
|
headerShown: false, // Ẩn header cho tất cả màn hình
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack.Screen name="homepage" component={HomePage} />
|
||||||
|
</Stack.Navigator>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
marginLeft: "auto",
|
||||||
backgroundColor: '#fff',
|
marginRight: "auto",
|
||||||
alignItems: 'center',
|
maxWidth: 480,
|
||||||
justifyContent: 'center',
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
37
app.config.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import 'dotenv/config'; // Đảm bảo tải biến môi trường
|
||||||
|
|
||||||
|
export default {
|
||||||
|
expo: {
|
||||||
|
name: "bestpc_mobile",
|
||||||
|
slug: "bestpc-mobile",
|
||||||
|
platforms: ["ios", "android"],
|
||||||
|
version: "1.0.0",
|
||||||
|
orientation: "portrait",
|
||||||
|
splash: {
|
||||||
|
resizeMode: "contain",
|
||||||
|
backgroundColor: "#ffffff"
|
||||||
|
},
|
||||||
|
updates: {
|
||||||
|
fallbackToCacheTimeout: 0
|
||||||
|
},
|
||||||
|
assetBundlePatterns: [
|
||||||
|
"**/*"
|
||||||
|
],
|
||||||
|
ios: {
|
||||||
|
supportsTablet: true
|
||||||
|
},
|
||||||
|
android: {
|
||||||
|
adaptiveIcon: {
|
||||||
|
backgroundColor: "#ffffff"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
packagerOpts: {
|
||||||
|
sourceExts: ["js", "json", "ts", "tsx"]
|
||||||
|
},
|
||||||
|
extra: {
|
||||||
|
expoHome: process.env.EXPO_HOME,
|
||||||
|
expoCacheDir: process.env.EXPO_CACHE_DIR,
|
||||||
|
expoProjectDir: process.env.EXPO_PROJECT_DIR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
22
app.json
@@ -1,29 +1,33 @@
|
|||||||
{
|
{
|
||||||
"expo": {
|
"expo": {
|
||||||
"name": "bestpc_mobile",
|
"name": "bestpc_mobile",
|
||||||
"slug": "bestpc_mobile",
|
"slug": "bestpc-mobile",
|
||||||
|
"platforms": ["ios", "android", "web"],
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"icon": "./assets/icon.png",
|
|
||||||
"userInterfaceStyle": "light",
|
|
||||||
"newArchEnabled": true,
|
|
||||||
"splash": {
|
"splash": {
|
||||||
"image": "./assets/splash-icon.png",
|
|
||||||
"resizeMode": "contain",
|
"resizeMode": "contain",
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
},
|
},
|
||||||
|
"updates": {
|
||||||
|
"fallbackToCacheTimeout": 0
|
||||||
|
},
|
||||||
|
"assetBundlePatterns": ["**/*"],
|
||||||
"ios": {
|
"ios": {
|
||||||
"supportsTablet": true
|
"supportsTablet": true
|
||||||
},
|
},
|
||||||
"android": {
|
"android": {
|
||||||
"adaptiveIcon": {
|
"adaptiveIcon": {
|
||||||
"foregroundImage": "./assets/adaptive-icon.png",
|
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"edgeToEdgeEnabled": true
|
"packagerOpts": {
|
||||||
|
"sourceExts": ["js", "json", "ts", "tsx"]
|
||||||
},
|
},
|
||||||
"web": {
|
"extra": {
|
||||||
"favicon": "./assets/favicon.png"
|
"expoHome": "E:/bestpc_mobile/.expo",
|
||||||
|
"expoCacheDir": "E:/bestpc_mobile/.expo/cache",
|
||||||
|
"expoProjectDir": "E:/bestpc_mobile"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
assets/images/banner_slider.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
BIN
assets/images/category-banphim.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
assets/images/category-laptop.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/images/category-linhkien.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
assets/images/category-pc.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/images/category-phukien.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
assets/images/category-tainhiet.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
assets/images/icon_2025.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
assets/images/icon_article.png
Normal file
|
After Width: | Height: | Size: 482 B |
BIN
assets/images/icon_box.png
Normal file
|
After Width: | Height: | Size: 435 B |
BIN
assets/images/icon_buildpc.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
assets/images/icon_location.png
Normal file
|
After Width: | Height: | Size: 905 B |
BIN
assets/images/icon_question.png
Normal file
|
After Width: | Height: | Size: 957 B |
BIN
assets/images/icon_star_0.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/images/icon_star_1.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/images/icon_star_2.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/images/icon_star_3.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/images/icon_star_4.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/images/icon_star_5.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/images/icon_store.png
Normal file
|
After Width: | Height: | Size: 927 B |
BIN
assets/images/icon_store_white.png
Normal file
|
After Width: | Height: | Size: 772 B |
BIN
assets/images/logo.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
56761
package-lock.json
generated
Normal file
24
package.json
@@ -10,14 +10,34 @@
|
|||||||
"web": "expo start --web"
|
"web": "expo start --web"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"expo": "~53.0.9",
|
"@expo/metro-runtime": "~5.0.4",
|
||||||
|
"@expo/vector-icons": "^14.1.0",
|
||||||
|
"@react-native-picker/picker": "^2.11.0",
|
||||||
|
"@react-navigation/drawer": "^7.3.12",
|
||||||
|
"@react-navigation/native": "^7.1.9",
|
||||||
|
"@react-navigation/native-stack": "^7.3.13",
|
||||||
|
"@react-navigation/stack": "^7.3.2",
|
||||||
|
"dotenv": "^16.5.0",
|
||||||
|
"expo-cli": "^4.9.1",
|
||||||
"expo-status-bar": "~2.2.3",
|
"expo-status-bar": "~2.2.3",
|
||||||
|
"hermes-engine": "^0.11.0",
|
||||||
|
"metro-runtime": "^0.82.3",
|
||||||
"react": "19.0.0",
|
"react": "19.0.0",
|
||||||
"react-native": "0.79.2"
|
"react-dom": "^19.0.0",
|
||||||
|
"react-native": "^0.79.2",
|
||||||
|
"react-native-gesture-handler": "~2.24.0",
|
||||||
|
"react-native-reanimated": "~3.17.4",
|
||||||
|
"react-native-safe-area-context": "^5.4.0",
|
||||||
|
"react-native-screens": "~4.10.0",
|
||||||
|
"react-native-swiper": "^1.6.0",
|
||||||
|
"react-native-web": "^0.20.0",
|
||||||
|
"react-navigation": "^5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
"@types/react": "~19.0.10",
|
"@types/react": "~19.0.10",
|
||||||
|
"@types/react-native": "^0.73.0",
|
||||||
|
"expo": "^53.0.9",
|
||||||
"typescript": "~5.8.3"
|
"typescript": "~5.8.3"
|
||||||
},
|
},
|
||||||
"private": true
|
"private": true
|
||||||
|
|||||||
102
src/components/footer/Footer.tsx
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import { View, Text, StyleSheet, Image, TouchableOpacity } from "react-native";
|
||||||
|
|
||||||
|
type FooterItemProps = {
|
||||||
|
label: string;
|
||||||
|
icon: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const FooterItem = ({ label, icon }: FooterItemProps) => (
|
||||||
|
<TouchableOpacity style={styles.footerItem}>
|
||||||
|
<Text style={styles.footerItemText}>{label}</Text>
|
||||||
|
<Image
|
||||||
|
source={{ uri: icon }}
|
||||||
|
style={styles.footerItemIcon}
|
||||||
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
|
||||||
|
const Footer = () => {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<View style={styles.spacer} />
|
||||||
|
<View style={styles.content}>
|
||||||
|
<FooterItem
|
||||||
|
label="Về chúng tôi"
|
||||||
|
icon="https://cdn.builder.io/api/v1/image/assets/TEMP/0f5cda0be55412240422e2274330e3f6e64023d3?placeholderIfAbsent=true&apiKey=1fa9f06a1e81406d92148011750a3756"
|
||||||
|
/>
|
||||||
|
<FooterItem
|
||||||
|
label="Tuyển dụng"
|
||||||
|
icon="https://cdn.builder.io/api/v1/image/assets/TEMP/0f5cda0be55412240422e2274330e3f6e64023d3?placeholderIfAbsent=true&apiKey=1fa9f06a1e81406d92148011750a3756"
|
||||||
|
/>
|
||||||
|
<FooterItem
|
||||||
|
label="Liên kết"
|
||||||
|
icon="https://cdn.builder.io/api/v1/image/assets/TEMP/0f5cda0be55412240422e2274330e3f6e64023d3?placeholderIfAbsent=true&apiKey=1fa9f06a1e81406d92148011750a3756"
|
||||||
|
/>
|
||||||
|
<FooterItem
|
||||||
|
label="Giới thiệu"
|
||||||
|
icon="https://cdn.builder.io/api/v1/image/assets/TEMP/5263024b89e68e21be091071a684ede939b2cbf7?placeholderIfAbsent=true&apiKey=1fa9f06a1e81406d92148011750a3756"
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
source={{
|
||||||
|
uri: "https://cdn.builder.io/api/v1/image/assets/TEMP/e7727a56c76a2e7c02cd1646e68e8b20cefb30e1?placeholderIfAbsent=true&apiKey=1fa9f06a1e81406d92148011750a3756",
|
||||||
|
}}
|
||||||
|
style={styles.logo}
|
||||||
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
alignSelf: "stretch",
|
||||||
|
marginTop: 28,
|
||||||
|
width: "100%",
|
||||||
|
paddingBottom: 21,
|
||||||
|
},
|
||||||
|
spacer: {
|
||||||
|
display: "flex",
|
||||||
|
minHeight: 10,
|
||||||
|
width: "100%",
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
marginTop: 17,
|
||||||
|
width: "100%",
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
},
|
||||||
|
footerItem: {
|
||||||
|
borderRadius: 4,
|
||||||
|
display: "flex",
|
||||||
|
paddingLeft: 9,
|
||||||
|
paddingRight: 9,
|
||||||
|
paddingTop: 6,
|
||||||
|
paddingBottom: 13,
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
footerItemText: {
|
||||||
|
color: "#444",
|
||||||
|
fontFamily: "Shopee Display, -apple-system, Roboto, Helvetica, sans-serif",
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: "700",
|
||||||
|
},
|
||||||
|
footerItemIcon: {
|
||||||
|
width: 11,
|
||||||
|
height: 6,
|
||||||
|
marginTop: 7,
|
||||||
|
},
|
||||||
|
logo: {
|
||||||
|
width: 95,
|
||||||
|
height: 40,
|
||||||
|
marginTop: 17,
|
||||||
|
marginLeft: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Footer;
|
||||||
431
src/components/header/Header.tsx
Normal file
@@ -0,0 +1,431 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
StyleSheet,
|
||||||
|
Image,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
TouchableOpacity,
|
||||||
|
Dimensions,
|
||||||
|
} from "react-native";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { Picker } from "@react-native-picker/picker";
|
||||||
|
import { NavigationContainer } from "@react-navigation/native";
|
||||||
|
import { createDrawerNavigator } from "@react-navigation/drawer";
|
||||||
|
import { createNativeStackNavigator } from "@react-navigation/native-stack";
|
||||||
|
|
||||||
|
const Header = () => {
|
||||||
|
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.headerTop}>
|
||||||
|
<View style={styles.headerTopLeft}>
|
||||||
|
<TouchableOpacity onPress={toggleDrawer} style={styles.menu}>
|
||||||
|
<Ionicons style={styles.iconMenu} name="menu-outline" size={30} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Image
|
||||||
|
source={require("../../../assets/images/logo.png")}
|
||||||
|
style={styles.logo}
|
||||||
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.boxLocation}>
|
||||||
|
<Ionicons style={styles.location} name="location-outline" size={34} />
|
||||||
|
<View>
|
||||||
|
<Text style={styles.textLocation}>Bạn đang ở</Text>
|
||||||
|
|
||||||
|
<View style={styles.boxSort}>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.boxSortButton}
|
||||||
|
onPress={() => setopenSort(!openSort)}
|
||||||
|
>
|
||||||
|
<Text style={styles.boxSortButtonActive}>Hà nội</Text>
|
||||||
|
<Ionicons
|
||||||
|
style={styles.boxSortButtonIcon}
|
||||||
|
name="caret-down-outline"
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<View
|
||||||
|
style={
|
||||||
|
openSort
|
||||||
|
? styles.boxSortList
|
||||||
|
: [styles.boxSortList, styles.boxSortListActive]
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.boxSortItem, styles.boxSortItemActive]}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.boxSortItemText,
|
||||||
|
styles.boxSortItemTextActive,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
Hà nội
|
||||||
|
</Text>
|
||||||
|
<Ionicons
|
||||||
|
style={styles.boxSortItemTextIcon}
|
||||||
|
name="checkmark-outline"
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.boxSortItem}>
|
||||||
|
<Text style={styles.boxSortItemText}>HCM</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.boxSortItem}>
|
||||||
|
<Text style={styles.boxSortItemText}>Đà nẵng</Text>
|
||||||
|
</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({
|
||||||
|
headerTop: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
width: winWidth,
|
||||||
|
paddingRight: 10,
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingTop: 45,
|
||||||
|
paddingBottom: 10,
|
||||||
|
backgroundColor: "#462F91",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
|
headerTopLeft: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 5,
|
||||||
|
},
|
||||||
|
logo: {
|
||||||
|
width: 99,
|
||||||
|
height: 20,
|
||||||
|
},
|
||||||
|
searchContainer: {
|
||||||
|
width: winWidth,
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
paddingTop: 9,
|
||||||
|
paddingBottom: 9,
|
||||||
|
backgroundColor: "#462F91",
|
||||||
|
},
|
||||||
|
searchBar: {
|
||||||
|
borderRadius: 4,
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
paddingTop: 6,
|
||||||
|
paddingBottom: 6,
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
},
|
||||||
|
searchInput: {
|
||||||
|
flex: 1,
|
||||||
|
fontSize: 12,
|
||||||
|
fontFamily: "Roboto, -apple-system, Roboto, Helvetica, sans-serif",
|
||||||
|
fontWeight: "500",
|
||||||
|
color: "#000000",
|
||||||
|
height: 32,
|
||||||
|
},
|
||||||
|
searchIconContainer: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 9,
|
||||||
|
},
|
||||||
|
divider: {
|
||||||
|
borderColor: "rgba(179, 179, 179, 1)",
|
||||||
|
borderStyle: "solid",
|
||||||
|
borderWidth: 1,
|
||||||
|
width: 1,
|
||||||
|
height: 20,
|
||||||
|
},
|
||||||
|
iconMenu: {
|
||||||
|
color: "#462f91",
|
||||||
|
},
|
||||||
|
location: {
|
||||||
|
color: "#FFFFFF",
|
||||||
|
width: 34,
|
||||||
|
height: 34,
|
||||||
|
},
|
||||||
|
boxlocalistion: {
|
||||||
|
height: 20,
|
||||||
|
width: 40,
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
boxLocation: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 5,
|
||||||
|
color: "#FFFFFF",
|
||||||
|
},
|
||||||
|
textLocation: {
|
||||||
|
color: "#FFFFFF",
|
||||||
|
fontSize: 10,
|
||||||
|
},
|
||||||
|
boxSort: {
|
||||||
|
zIndex: 1,
|
||||||
|
},
|
||||||
|
boxSortButton: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
height: 30,
|
||||||
|
},
|
||||||
|
boxSortButtonTextBold: {
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
boxSortButtonActive: {
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
boxSortButtonIcon: {
|
||||||
|
marginLeft: 5,
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
boxSortList: {
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
position: "absolute",
|
||||||
|
right: 0,
|
||||||
|
top: 40,
|
||||||
|
display: "none",
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
boxSortListActive: {
|
||||||
|
display: "flex",
|
||||||
|
},
|
||||||
|
boxSortItem: {
|
||||||
|
paddingVertical: 10,
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
|
boxSortItemActive: {
|
||||||
|
borderBottomColor: "#D8262F",
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
},
|
||||||
|
boxSortItemText: {
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
boxSortItemTextActive: {
|
||||||
|
color: "#D8262F",
|
||||||
|
},
|
||||||
|
boxSortItemTextIcon: {
|
||||||
|
color: "#D8262F",
|
||||||
|
},
|
||||||
|
boxFilter: {
|
||||||
|
width: 70,
|
||||||
|
height: 30,
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
borderLeftWidth: 1,
|
||||||
|
borderLeftColor: "#e1e1e1",
|
||||||
|
},
|
||||||
|
menu: {
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
width: 30,
|
||||||
|
height: 30,
|
||||||
|
borderRadius: 4,
|
||||||
|
alignItems: "center",
|
||||||
|
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;
|
||||||
198
src/components/product/ItemProduct.tsx
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
StyleSheet,
|
||||||
|
Image,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
TouchableOpacity,
|
||||||
|
Dimensions,
|
||||||
|
} from "react-native";
|
||||||
|
|
||||||
|
var winWidth = Dimensions.get("window").width; //full width
|
||||||
|
var winHeight = Dimensions.get("window").height;
|
||||||
|
|
||||||
|
const ItemProduct = ({ product }: { product: any }) => {
|
||||||
|
function formatCurrency(a: number | string): string {
|
||||||
|
let b = parseFloat(a.toString())
|
||||||
|
.toFixed(2)
|
||||||
|
.replace(/(\d)(?=(\d{3})+\.)/g, "$1.")
|
||||||
|
.toString();
|
||||||
|
var len = b.length;
|
||||||
|
b = b.substring(0, len - 3);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.productItem}>
|
||||||
|
<TouchableOpacity style={styles.productImage}>
|
||||||
|
<Image
|
||||||
|
source={{ uri: product.productImage.large }}
|
||||||
|
style={styles.productImg}
|
||||||
|
alt={product.productName}
|
||||||
|
/>
|
||||||
|
<View style={styles.boxSaleoff}>
|
||||||
|
<View style={styles.beforeSaleoff}></View>
|
||||||
|
<Text style={styles.saleoffText}>{product.saleOff}</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<View>
|
||||||
|
<TouchableOpacity>
|
||||||
|
<Text numberOfLines={2} style={styles.productName}>
|
||||||
|
{product.productName}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<View style={styles.BoxPriceRating}>
|
||||||
|
<View>
|
||||||
|
<Text style={styles.price}>{formatCurrency(product.price)}đ</Text>
|
||||||
|
<Text style={styles.oldPrice}>
|
||||||
|
{formatCurrency(product.oldPrice)}đ
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View>
|
||||||
|
<Image
|
||||||
|
source={
|
||||||
|
product.review.rate !== undefined
|
||||||
|
? require(`../../../assets/images/icon_star_${product.review.rate}.png`)
|
||||||
|
: require("../../../assets/images/icon_star_0.png")
|
||||||
|
}
|
||||||
|
style={styles.iconReviewRating}
|
||||||
|
alt="icon review"
|
||||||
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={styles.boxStore}>
|
||||||
|
<View style={styles.boxIconStore}>
|
||||||
|
<Image
|
||||||
|
source={require("../../../assets/images/icon_store_white.png")}
|
||||||
|
style={styles.iconStore}
|
||||||
|
alt="icon store"
|
||||||
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.storeName}>
|
||||||
|
Có {product.toltalStore} cửa hàng bán
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
productItem: {
|
||||||
|
width: winWidth / 2 - 20,
|
||||||
|
marginRight: 10,
|
||||||
|
marginBottom: 10,
|
||||||
|
padding: 12,
|
||||||
|
},
|
||||||
|
productImage: {
|
||||||
|
width: winWidth / 2 - 20,
|
||||||
|
height: 150,
|
||||||
|
position: "relative",
|
||||||
|
marginBottom: 5,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: "#d3d3d3",
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
productImg: {
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
objectFit: "contain",
|
||||||
|
},
|
||||||
|
boxSaleoff: {
|
||||||
|
position: "absolute",
|
||||||
|
right: 10,
|
||||||
|
top: 10,
|
||||||
|
width: 35,
|
||||||
|
height: 35,
|
||||||
|
borderRadius: 25,
|
||||||
|
backgroundColor: "#da251c",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
beforeSaleoff: {
|
||||||
|
position: "absolute",
|
||||||
|
top: "50%",
|
||||||
|
left: "50%",
|
||||||
|
transform: [{ translateY: "-50%" }, { translateX: "-50%" }],
|
||||||
|
width: 30,
|
||||||
|
height: 30,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderStyle: "dashed",
|
||||||
|
borderColor: "#fff",
|
||||||
|
borderRadius: 25,
|
||||||
|
},
|
||||||
|
saleoffText: {
|
||||||
|
fontSize: 8,
|
||||||
|
fontWeight: 700,
|
||||||
|
backgroundColor: "#da251c",
|
||||||
|
borderRadius: 25,
|
||||||
|
color: "#fff",
|
||||||
|
paddingLeft: 2,
|
||||||
|
},
|
||||||
|
productName: {
|
||||||
|
fontWeight: 700,
|
||||||
|
fontSize: 13,
|
||||||
|
color: "#000",
|
||||||
|
marginBottom: 5,
|
||||||
|
},
|
||||||
|
summary: {
|
||||||
|
marginTop: 5,
|
||||||
|
color: "#595959",
|
||||||
|
},
|
||||||
|
locahostPro: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
iconMap: {},
|
||||||
|
BoxPriceRating: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "flex-end",
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#d80a00",
|
||||||
|
},
|
||||||
|
oldPrice: {
|
||||||
|
fontSize: 13,
|
||||||
|
textDecorationLine: "line-through",
|
||||||
|
color: "#595959",
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
iconReviewRating: {
|
||||||
|
width: 58,
|
||||||
|
height: 11,
|
||||||
|
marginBottom: 2,
|
||||||
|
},
|
||||||
|
boxStore: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
marginTop: 5,
|
||||||
|
},
|
||||||
|
boxIconStore: {
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
borderRadius: 25,
|
||||||
|
backgroundColor: "#FF7A00",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginRight: 5,
|
||||||
|
},
|
||||||
|
iconStore: {
|
||||||
|
width: 18,
|
||||||
|
height: 18,
|
||||||
|
},
|
||||||
|
storeName: {
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#000",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ItemProduct;
|
||||||
42
src/data/category.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
export const categories = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Laptop văn phòng",
|
||||||
|
image: "../../assets/images/category-laptop.png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Tản nhiệt, đèn",
|
||||||
|
image: "../../assets/images/category-tannhiet.png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Linh kiện máy tính",
|
||||||
|
image: "../../assets/images/category-linhkien.png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "Bàn phím, chuột",
|
||||||
|
image: "../../assets/images/category-banphim.png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "Laptop gaming",
|
||||||
|
image: "../../assets/images/category-laptop.png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "Phụ kiện đi kèm",
|
||||||
|
image: "../../assets/images/category-phukien.png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
name: "PC đồ họa, gaming",
|
||||||
|
image: "../../assets/images/category-pc.png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
name: "Pc văn phòng",
|
||||||
|
image: "../../assets/images/category-pc.png",
|
||||||
|
},
|
||||||
|
];
|
||||||
80
src/data/product.tsx
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
export const products = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
productName: "Laptop văn phòng Dell RAM 8G Core i7",
|
||||||
|
productImage: {
|
||||||
|
small:
|
||||||
|
"https://demopc8.hurasoft.com/media/product/75_2038_12546_qvc_pcgaming02.jpg",
|
||||||
|
large:
|
||||||
|
"https://demopc8.hurasoft.com/media/product/250_2038_12546_qvc_pcgaming02.jpg",
|
||||||
|
original:
|
||||||
|
"https://demopc8.hurasoft.com/media/product/2038_12546_qvc_pcgaming02.jpg",
|
||||||
|
},
|
||||||
|
price: 1000000,
|
||||||
|
oldPrice: 1200000,
|
||||||
|
saleOff: "20%",
|
||||||
|
description: "Intel Core i7 / 8GB / 512GB / SSD",
|
||||||
|
review: {
|
||||||
|
rate: 5,
|
||||||
|
total: 1,
|
||||||
|
},
|
||||||
|
toltalStore: 12,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
productName: "Laptop văn phòng Dell RAM 8G Core i7",
|
||||||
|
productImage: {
|
||||||
|
small: "https://demopc8.hurasoft.com/media/product/75_2027_picture2.jpg",
|
||||||
|
large: "https://demopc8.hurasoft.com/media/product/250_2027_picture2.jpg",
|
||||||
|
original: "https://demopc8.hurasoft.com/media/product/2027_picture2.jpg",
|
||||||
|
},
|
||||||
|
price: 2000000,
|
||||||
|
oldPrice: 2200000,
|
||||||
|
saleOff: "10%",
|
||||||
|
description: "Intel Core i7 / 8GB / 512GB / SSD",
|
||||||
|
review: {
|
||||||
|
rate: 5,
|
||||||
|
total: 1,
|
||||||
|
},
|
||||||
|
toltalStore: 12,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
productName: "Laptop văn phòng Dell RAM 8G Core i7",
|
||||||
|
productImage: {
|
||||||
|
small: "https://demopc8.hurasoft.com/media/product/75_2026_cccccccc.jpg",
|
||||||
|
large: "https://demopc8.hurasoft.com/media/product/250_2026_cccccccc.jpg",
|
||||||
|
original: "https://demopc8.hurasoft.com/media/product/2026_cccccccc.jpg",
|
||||||
|
},
|
||||||
|
description: "Intel Core i7 / 8GB / 512GB / SSD",
|
||||||
|
price: 2000000,
|
||||||
|
oldPrice: 2200000,
|
||||||
|
saleOff: "10%",
|
||||||
|
review: {
|
||||||
|
rate: 5,
|
||||||
|
total: 1,
|
||||||
|
},
|
||||||
|
toltalStore: 12,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
productName: "Laptop văn phòng Dell RAM 8G Core i7",
|
||||||
|
productImage: {
|
||||||
|
small:
|
||||||
|
"https://demopc8.hurasoft.com/media/product/75_2008_colorful_igame_geforce_rtx_3060_ti_ultra_oc_white_8g_v_photo_01.jpg",
|
||||||
|
large:
|
||||||
|
"https://demopc8.hurasoft.com/media/product/250_2008_colorful_igame_geforce_rtx_3060_ti_ultra_oc_white_8g_v_photo_01.jpg",
|
||||||
|
original:
|
||||||
|
"https://demopc8.hurasoft.com/media/product2008_colorful_igame_geforce_rtx_3060_ti_ultra_oc_white_8g_v_photo_01.jpg",
|
||||||
|
},
|
||||||
|
price: 3100000,
|
||||||
|
oldPrice: 3300000,
|
||||||
|
saleOff: "10%",
|
||||||
|
description: "Intel Core i7 / 8GB / 512GB / SSD",
|
||||||
|
review: {
|
||||||
|
rate: 5,
|
||||||
|
total: 1,
|
||||||
|
},
|
||||||
|
toltalStore: 12,
|
||||||
|
},
|
||||||
|
];
|
||||||
5
src/images.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// src/images.d.ts hoặc ./images.d.ts
|
||||||
|
declare module '*.png';
|
||||||
|
declare module '*.jpg';
|
||||||
|
declare module '*.jpeg';
|
||||||
|
declare module '*.gif';
|
||||||
20
src/navigation/AppNavigator.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// src/navigation/AppNavigator.tsx
|
||||||
|
import React from "react";
|
||||||
|
import { createStackNavigator } from "@react-navigation/stack";
|
||||||
|
import { NavigationContainer } from "@react-navigation/native";
|
||||||
|
import HomeScreen from "../screens/HomeScreen";
|
||||||
|
|
||||||
|
const Stack = createStackNavigator();
|
||||||
|
|
||||||
|
const AppNavigator: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<NavigationContainer>
|
||||||
|
<Stack.Navigator initialRouteName="Home">
|
||||||
|
<Stack.Screen name="Home" component={HomeScreen} />
|
||||||
|
<Stack.Screen name="Product" />
|
||||||
|
</Stack.Navigator>
|
||||||
|
</NavigationContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AppNavigator;
|
||||||
330
src/screens/HomeScreen.tsx
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
// src/screens/HomeScreen.tsx
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
StyleSheet,
|
||||||
|
ScrollView,
|
||||||
|
Dimensions,
|
||||||
|
Image,
|
||||||
|
ImageBackground,
|
||||||
|
TouchableOpacity,
|
||||||
|
SafeAreaView,
|
||||||
|
} 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";
|
||||||
|
import { categories } from "../data/category";
|
||||||
|
|
||||||
|
var winWidth = Dimensions.get("window").width; //full width
|
||||||
|
var winHeight = Dimensions.get("window").height; //full height
|
||||||
|
const ratio = winWidth / 930;
|
||||||
|
const HomeScreen: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<ScrollView>
|
||||||
|
<SliderHome />
|
||||||
|
<BoxMenuHome />
|
||||||
|
<BoxProductReviewTop />
|
||||||
|
<BoxCategoryHome />
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SliderHome = () => {
|
||||||
|
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}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
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="contain"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={styles.imgContainer}>
|
||||||
|
<Image
|
||||||
|
style={styles.imgSlider}
|
||||||
|
source={require("../../assets/images/banner_slider.png")}
|
||||||
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={styles.imgContainer}>
|
||||||
|
<Image
|
||||||
|
style={styles.imgSlider}
|
||||||
|
source={require("../../assets/images/banner_slider.png")}
|
||||||
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={styles.imgContainer}>
|
||||||
|
<Image
|
||||||
|
style={styles.imgSlider}
|
||||||
|
source={require("../../assets/images/banner_slider.png")}
|
||||||
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</Swiper>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const BoxMenuHome = () => {
|
||||||
|
return (
|
||||||
|
<View style={styles.boxMenuHome}>
|
||||||
|
<TouchableOpacity style={styles.MenuItem}>
|
||||||
|
<View style={styles.boxIconMenu}>
|
||||||
|
<Image
|
||||||
|
source={require("../../assets/images/icon_buildpc.png")}
|
||||||
|
style={styles.iconMenuItem}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.textMenu}>Build pc</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.MenuItem}>
|
||||||
|
<View style={styles.boxIconMenu}>
|
||||||
|
<Image
|
||||||
|
source={require("../../assets/images/icon_store.png")}
|
||||||
|
style={styles.iconMenuItem}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.textMenu}>Tìm người bán</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.MenuItem}>
|
||||||
|
<View style={styles.boxIconMenu}>
|
||||||
|
<Image
|
||||||
|
source={require("../../assets/images/icon_location.png")}
|
||||||
|
style={styles.iconlocationMenuItem}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.textMenu}>Địa chỉ sửa chữa</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.MenuItem}>
|
||||||
|
<View style={styles.boxIconMenu}>
|
||||||
|
<Image
|
||||||
|
source={require("../../assets/images/icon_box.png")}
|
||||||
|
style={styles.iconMenuItem}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.textMenu}>Sản phẩm đã lưu</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.MenuItem}>
|
||||||
|
<View style={styles.boxIconMenu}>
|
||||||
|
<Image
|
||||||
|
source={require("../../assets/images/icon_article.png")}
|
||||||
|
style={styles.iconMenuItem}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.textMenu}>Tin rao vặt</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.MenuItem}>
|
||||||
|
<View style={styles.boxIconMenu}>
|
||||||
|
<Image
|
||||||
|
source={require("../../assets/images/icon_question.png")}
|
||||||
|
style={styles.iconMenuItem}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.textMenu}>Hỏi đáp</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const BoxProductReviewTop = () => {
|
||||||
|
const [activeIndex, setActiveIndex] = useState(1);
|
||||||
|
|
||||||
|
const listTab = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Laptop",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Màn hình",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Bàn phím",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "Cpu",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "Chuột",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "Ram",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={globalStyles.boxProductReviewTop}>
|
||||||
|
<Text style={globalStyles.textBoxProductReviewTop}>
|
||||||
|
Sản phẩm được đánh giá tốt nhất
|
||||||
|
</Text>
|
||||||
|
<Text style={globalStyles.noteTextReviewTop}>
|
||||||
|
Tổng hợp các sản phẩm hot theo xu hướng và có nhiều lượt review và đánh
|
||||||
|
giá nhất hiện nay
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<ScrollView horizontal={true} style={globalStyles.listTab}>
|
||||||
|
{listTab.map((item, index) => (
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[
|
||||||
|
globalStyles.tabItem,
|
||||||
|
activeIndex === item.id && globalStyles.activeItem,
|
||||||
|
]}
|
||||||
|
key={item.id}
|
||||||
|
onPress={() => setActiveIndex(item.id)}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
globalStyles.textTabItem,
|
||||||
|
activeIndex === item.id && globalStyles.activeText,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<View style={globalStyles.listProduct}>
|
||||||
|
{products.map((item) => (
|
||||||
|
<ProductItem key={item.id} product={item} />
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<TouchableOpacity>
|
||||||
|
<Text style={globalStyles.moreAll}>Xem tất cả</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const BoxCategoryHome = () => {
|
||||||
|
return (
|
||||||
|
<View style={globalStyles.boxCategoryHome}>
|
||||||
|
<Text style={globalStyles.textBoxCategoryHome}>Tìm theo danh mục</Text>
|
||||||
|
<View style={globalStyles.listCategoryBox}>
|
||||||
|
{categories.map((item) => (
|
||||||
|
<TouchableOpacity key={item.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>
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HomeScreen;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
},
|
||||||
|
homePage: {
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
},
|
||||||
|
slider: {
|
||||||
|
width: winWidth,
|
||||||
|
padding: 10,
|
||||||
|
borderRadius: 10,
|
||||||
|
height: ratio * 430,
|
||||||
|
},
|
||||||
|
sliderSwipper: {
|
||||||
|
borderRadius: 10,
|
||||||
|
},
|
||||||
|
imgContainer: {
|
||||||
|
width: winWidth,
|
||||||
|
height: 220,
|
||||||
|
borderRadius: 10,
|
||||||
|
overflow: "hidden",
|
||||||
|
},
|
||||||
|
imgSlider: {
|
||||||
|
width: winWidth,
|
||||||
|
height: "100%",
|
||||||
|
},
|
||||||
|
buttonNext: {
|
||||||
|
color: "#fff", // Màu chữ cho các nút chuyển
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
buttonPrev: {
|
||||||
|
color: "#fff", // Màu chữ cho các nút chuyển
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
boxMenuHome: {
|
||||||
|
flexDirection: "row",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
marginLeft: 20,
|
||||||
|
marginRight: 20,
|
||||||
|
gap: 20,
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
},
|
||||||
|
MenuItem: {
|
||||||
|
width: winWidth / 4 - 25,
|
||||||
|
},
|
||||||
|
boxIconMenu: {
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
marginBottom: 5,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
backgroundColor: "#eeeeee",
|
||||||
|
borderRadius: 25,
|
||||||
|
marginLeft: "auto",
|
||||||
|
marginRight: "auto",
|
||||||
|
},
|
||||||
|
textMenu: {
|
||||||
|
textAlign: "center",
|
||||||
|
fontSize: 14,
|
||||||
|
color: "#333",
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
iconMenuItem: {
|
||||||
|
width: 20,
|
||||||
|
resizeMode: "contain",
|
||||||
|
},
|
||||||
|
iconlocationMenuItem: {
|
||||||
|
width: 13,
|
||||||
|
resizeMode: "contain",
|
||||||
|
},
|
||||||
|
});
|
||||||
108
src/styles/globalStyles.ts
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
// src/styles/globalStyles.ts
|
||||||
|
import { StyleSheet, Dimensions } from 'react-native';
|
||||||
|
var winWidth = Dimensions.get("window").width;
|
||||||
|
|
||||||
|
export const globalStyles = StyleSheet.create({
|
||||||
|
boxProductReviewTop: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
marginTop: 25,
|
||||||
|
},
|
||||||
|
textBoxProductReviewTop: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#0d0d9c',
|
||||||
|
marginBottom: 8,
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
noteTextReviewTop: {
|
||||||
|
marginBottom: 8,
|
||||||
|
textAlign: 'center',
|
||||||
|
fontSize: 12,
|
||||||
|
color: "#000"
|
||||||
|
},
|
||||||
|
listTab: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
},
|
||||||
|
tabItem: {
|
||||||
|
padding: 10,
|
||||||
|
width: 100,
|
||||||
|
marginRight: 10,
|
||||||
|
textAlign: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor: '#ececec',
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
textTabItem: {
|
||||||
|
fontSize: 15,
|
||||||
|
},
|
||||||
|
activeItem: {
|
||||||
|
backgroundColor: '#462f91',
|
||||||
|
},
|
||||||
|
activeText: {
|
||||||
|
color: '#fff'
|
||||||
|
},
|
||||||
|
listProduct: {
|
||||||
|
marginTop: 10,
|
||||||
|
marginBottom: 10,
|
||||||
|
flexDirection: 'row',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
marginLeft: -10,
|
||||||
|
},
|
||||||
|
moreAll: {
|
||||||
|
width: 110,
|
||||||
|
height: 30,
|
||||||
|
borderColor: '#FF7A00',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 20,
|
||||||
|
textAlign: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
lineHeight: 28,
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
color: '#FF7A00',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
boxCategoryHome: {
|
||||||
|
marginTop: 25,
|
||||||
|
},
|
||||||
|
textBoxCategoryHome: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: "#0d0d9c",
|
||||||
|
marginBottom: 8,
|
||||||
|
textTransform: "uppercase",
|
||||||
|
textAlign: "center",
|
||||||
|
},
|
||||||
|
listCategoryBox: {
|
||||||
|
marginTop: 10,
|
||||||
|
},
|
||||||
|
categoryItem: {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
boxImageCategory: {
|
||||||
|
width: 70,
|
||||||
|
height: 70,
|
||||||
|
borderRadius: "50%",
|
||||||
|
overflow: 'hidden',
|
||||||
|
backgroundColor: '#f4f0ff',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
iconCategory: {
|
||||||
|
width: 50,
|
||||||
|
objectFit: 'contain',
|
||||||
|
},
|
||||||
|
categoryName: {
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: '500',
|
||||||
|
marginTop: 5,
|
||||||
|
textAlign: 'center',
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
6
src/types/ProductType.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// src/types/ProductType.ts
|
||||||
|
export interface Product {
|
||||||
|
name: string;
|
||||||
|
price: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
{
|
{
|
||||||
"extends": "expo/tsconfig.base",
|
"extends": "expo/tsconfig.base",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"strict": true
|
"strict": true,
|
||||||
}
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"forceConsistentCasingInFileNames": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*", "assets/**/*"]
|
||||||
}
|
}
|
||||||
|
|||||||