demo app hanoicomputer home category productdetail cart
This commit is contained in:
6
.expo-shared/assets.json
Normal file
6
.expo-shared/assets.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"e997a5256149a4b76e6bfd6cbf519c5e5a0f1d278a3d8fa1253022b03c90473b": true,
|
||||||
|
"af683c96e0ffd2cf81287651c9433fa44debc1220ca7cb431fe482747f34a505": true,
|
||||||
|
"12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true,
|
||||||
|
"40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true
|
||||||
|
}
|
||||||
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
node_modules/**/*
|
||||||
|
.expo/*
|
||||||
|
npm-debug.*
|
||||||
|
*.jks
|
||||||
|
*.p8
|
||||||
|
*.p12
|
||||||
|
*.key
|
||||||
|
*.mobileprovision
|
||||||
|
*.orig.*
|
||||||
|
web-build/
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
117
App.tsx
Normal file
117
App.tsx
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import { StatusBar } from 'expo-status-bar';
|
||||||
|
import React from 'react';
|
||||||
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||||
|
import { Alert, Button, Image, StyleSheet, Dimensions, SafeAreaView, ScrollView, TouchableOpacity } from 'react-native';
|
||||||
|
import { Header, MainSeach } from './components/header/headerMain';
|
||||||
|
|
||||||
|
import useCachedResources from './hooks/useCachedResources';
|
||||||
|
import useColorScheme from './hooks/useColorScheme';
|
||||||
|
import Navigation from './navigation';
|
||||||
|
import { createDrawerNavigator, DrawerItemList, DrawerItem, DrawerContentScrollView } from '@react-navigation/drawer';
|
||||||
|
import { NavigationContainer } from '@react-navigation/native';
|
||||||
|
import { createStackNavigator, StackScreenProps } from '@react-navigation/stack';
|
||||||
|
import { Text, View, } from './components/Themed';
|
||||||
|
import TabOneScreen from './screens/TabOneScreen';
|
||||||
|
import TabTwoScreen from './screens/TabTwoScreen';
|
||||||
|
import ProductDetail from './screens/ProductDetail';
|
||||||
|
import CartDetail from './screens/Cart';
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
const isLoadingComplete = useCachedResources();
|
||||||
|
const colorScheme = useColorScheme();
|
||||||
|
|
||||||
|
if (!isLoadingComplete) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<NavigationContainer>
|
||||||
|
<MainContentRouter />
|
||||||
|
</NavigationContainer>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Drawer = createDrawerNavigator();
|
||||||
|
const Stack = createStackNavigator();
|
||||||
|
|
||||||
|
/* cài đặt thông số cho header */
|
||||||
|
const HeaderAllPageOpion = ({ navigation }: { navigation: any }) => {
|
||||||
|
return (
|
||||||
|
{
|
||||||
|
headerLeft: () => (
|
||||||
|
<Header props={navigation} />
|
||||||
|
),
|
||||||
|
headerTitle: () => (
|
||||||
|
<Text></Text>
|
||||||
|
),
|
||||||
|
headerStyle: {
|
||||||
|
backgroundColor: '#3385ff',
|
||||||
|
height: 130,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* redirect về trang chủ */
|
||||||
|
const HomePage = ({ navigation }: { navigation: any }) => {
|
||||||
|
return (
|
||||||
|
<Stack.Navigator>
|
||||||
|
<Stack.Screen
|
||||||
|
name="homepage"
|
||||||
|
component={TabOneScreen}
|
||||||
|
options={HeaderAllPageOpion}
|
||||||
|
/>
|
||||||
|
</Stack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* redirect về danh mục */
|
||||||
|
const ProductList = ({ navigation }: { navigation: any }) => {
|
||||||
|
return (
|
||||||
|
<Stack.Navigator>
|
||||||
|
<Stack.Screen
|
||||||
|
name="homepage"
|
||||||
|
component={TabTwoScreen}
|
||||||
|
options={HeaderAllPageOpion}
|
||||||
|
/>
|
||||||
|
</Stack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProductDetailRec = ({ navigation }: { navigation: any }) => {
|
||||||
|
return (
|
||||||
|
<Stack.Navigator>
|
||||||
|
<Stack.Screen
|
||||||
|
name="homepage"
|
||||||
|
component={ProductDetail}
|
||||||
|
options={HeaderAllPageOpion}
|
||||||
|
/>
|
||||||
|
</Stack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const CartPage = ({ navigation }: { navigation: any }) => {
|
||||||
|
return (
|
||||||
|
<Stack.Navigator>
|
||||||
|
<Stack.Screen
|
||||||
|
name="homepage"
|
||||||
|
component={CartDetail}
|
||||||
|
options={HeaderAllPageOpion}
|
||||||
|
/>
|
||||||
|
</Stack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const MainContentRouter = () => {
|
||||||
|
return (
|
||||||
|
<Drawer.Navigator>
|
||||||
|
<Drawer.Screen name="Home" component={HomePage} />
|
||||||
|
<Drawer.Screen name="Laptop, Máy Tính Xách Tay" component={ProductList} />
|
||||||
|
<Drawer.Screen name="Trang san pham" component={ProductDetailRec} />
|
||||||
|
<Drawer.Screen name="cart" component={CartPage} />
|
||||||
|
</Drawer.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
34
app.json
Normal file
34
app.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"expo": {
|
||||||
|
"name": "demo",
|
||||||
|
"slug": "demo",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"orientation": "portrait",
|
||||||
|
"icon": "./assets/images/icon.png",
|
||||||
|
"scheme": "myapp",
|
||||||
|
"userInterfaceStyle": "automatic",
|
||||||
|
"splash": {
|
||||||
|
"image": "./assets/images/splash.png",
|
||||||
|
"resizeMode": "contain",
|
||||||
|
"backgroundColor": "#ffffff"
|
||||||
|
},
|
||||||
|
"updates": {
|
||||||
|
"fallbackToCacheTimeout": 0
|
||||||
|
},
|
||||||
|
"assetBundlePatterns": [
|
||||||
|
"**/*"
|
||||||
|
],
|
||||||
|
"ios": {
|
||||||
|
"supportsTablet": true
|
||||||
|
},
|
||||||
|
"android": {
|
||||||
|
"adaptiveIcon": {
|
||||||
|
"foregroundImage": "./assets/images/adaptive-icon.png",
|
||||||
|
"backgroundColor": "#FFFFFF"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"web": {
|
||||||
|
"favicon": "./assets/images/favicon.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
assets/fonts/SpaceMono-Regular.ttf
Normal file
BIN
assets/fonts/SpaceMono-Regular.ttf
Normal file
Binary file not shown.
BIN
assets/images/adaptive-icon.png
Normal file
BIN
assets/images/adaptive-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
assets/images/favicon.png
Normal file
BIN
assets/images/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/images/icon.png
Normal file
BIN
assets/images/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
assets/images/splash.png
Normal file
BIN
assets/images/splash.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
6
babel.config.js
Normal file
6
babel.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = function(api) {
|
||||||
|
api.cache(true);
|
||||||
|
return {
|
||||||
|
presets: ['babel-preset-expo'],
|
||||||
|
};
|
||||||
|
};
|
||||||
108
components/EditScreenInfo.tsx
Normal file
108
components/EditScreenInfo.tsx
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import * as WebBrowser from 'expo-web-browser';
|
||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet, TouchableOpacity } from 'react-native';
|
||||||
|
|
||||||
|
import Colors from '../constants/Colors';
|
||||||
|
import { MonoText } from './StyledText';
|
||||||
|
import { Text, View } from './Themed';
|
||||||
|
|
||||||
|
export default function EditScreenInfo({ path }: { path: string }) {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<View style={styles.getStartedContainer}>
|
||||||
|
<Text
|
||||||
|
style={styles.getStartedText}
|
||||||
|
lightColor="rgba(0,0,0,0.8)"
|
||||||
|
darkColor="rgba(255,255,255,0.8)">
|
||||||
|
Open up the code for this screen:
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={[styles.codeHighlightContainer, styles.homeScreenFilename]}
|
||||||
|
darkColor="rgba(255,255,255,0.05)"
|
||||||
|
lightColor="rgba(0,0,0,0.05)">
|
||||||
|
<MonoText>{path}</MonoText>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={styles.getStartedText}
|
||||||
|
lightColor="rgba(0,0,0,0.8)"
|
||||||
|
darkColor="rgba(255,255,255,0.8)">
|
||||||
|
Change any of the text, save the file, and your app will automatically update.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.helpContainer}>
|
||||||
|
<TouchableOpacity onPress={handleHelpPress} style={styles.helpLink}>
|
||||||
|
<Text style={styles.helpLinkText} lightColor={Colors.light.tint}>
|
||||||
|
Tap here if your app doesn't automatically update after making changes
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleHelpPress() {
|
||||||
|
WebBrowser.openBrowserAsync(
|
||||||
|
'https://docs.expo.io/get-started/create-a-new-app/#opening-the-app-on-your-phonetablet'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
},
|
||||||
|
developmentModeText: {
|
||||||
|
marginBottom: 20,
|
||||||
|
fontSize: 14,
|
||||||
|
lineHeight: 19,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
contentContainer: {
|
||||||
|
paddingTop: 30,
|
||||||
|
},
|
||||||
|
welcomeContainer: {
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: 10,
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
welcomeImage: {
|
||||||
|
width: 100,
|
||||||
|
height: 80,
|
||||||
|
resizeMode: 'contain',
|
||||||
|
marginTop: 3,
|
||||||
|
marginLeft: -10,
|
||||||
|
},
|
||||||
|
getStartedContainer: {
|
||||||
|
alignItems: 'center',
|
||||||
|
marginHorizontal: 50,
|
||||||
|
},
|
||||||
|
homeScreenFilename: {
|
||||||
|
marginVertical: 7,
|
||||||
|
},
|
||||||
|
codeHighlightText: {
|
||||||
|
color: 'rgba(96,100,109, 0.8)',
|
||||||
|
},
|
||||||
|
codeHighlightContainer: {
|
||||||
|
borderRadius: 3,
|
||||||
|
paddingHorizontal: 4,
|
||||||
|
},
|
||||||
|
getStartedText: {
|
||||||
|
fontSize: 17,
|
||||||
|
lineHeight: 24,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
helpContainer: {
|
||||||
|
marginTop: 15,
|
||||||
|
marginHorizontal: 20,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
helpLink: {
|
||||||
|
paddingVertical: 15,
|
||||||
|
},
|
||||||
|
helpLinkText: {
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
7
components/StyledText.tsx
Normal file
7
components/StyledText.tsx
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { Text, TextProps } from './Themed';
|
||||||
|
|
||||||
|
export function MonoText(props: TextProps) {
|
||||||
|
return <Text {...props} style={[props.style, { fontFamily: 'space-mono' }]} />;
|
||||||
|
}
|
||||||
41
components/Themed.tsx
Normal file
41
components/Themed.tsx
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { Text as DefaultText, View as DefaultView } from 'react-native';
|
||||||
|
|
||||||
|
import Colors from '../constants/Colors';
|
||||||
|
import useColorScheme from '../hooks/useColorScheme';
|
||||||
|
|
||||||
|
export function useThemeColor(
|
||||||
|
props: { light?: string; dark?: string },
|
||||||
|
colorName: keyof typeof Colors.light & keyof typeof Colors.dark
|
||||||
|
) {
|
||||||
|
const theme = useColorScheme();
|
||||||
|
const colorFromProps = props[theme];
|
||||||
|
|
||||||
|
if (colorFromProps) {
|
||||||
|
return colorFromProps;
|
||||||
|
} else {
|
||||||
|
return Colors[theme][colorName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ThemeProps = {
|
||||||
|
lightColor?: string;
|
||||||
|
darkColor?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TextProps = ThemeProps & DefaultText['props'];
|
||||||
|
export type ViewProps = ThemeProps & DefaultView['props'];
|
||||||
|
|
||||||
|
export function Text(props: TextProps) {
|
||||||
|
const { style, lightColor, darkColor, ...otherProps } = props;
|
||||||
|
const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
|
||||||
|
|
||||||
|
return <DefaultText style={[{ color }, style]} {...otherProps} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function View(props: ViewProps) {
|
||||||
|
const { style, lightColor, darkColor, ...otherProps } = props;
|
||||||
|
const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background');
|
||||||
|
|
||||||
|
return <DefaultView style={[{ backgroundColor }, style]} {...otherProps} />;
|
||||||
|
}
|
||||||
10
components/__tests__/StyledText-test.js
Normal file
10
components/__tests__/StyledText-test.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import renderer from 'react-test-renderer';
|
||||||
|
|
||||||
|
import { MonoText } from '../StyledText';
|
||||||
|
|
||||||
|
it(`renders correctly`, () => {
|
||||||
|
const tree = renderer.create(<MonoText>Snapshot test!</MonoText>).toJSON();
|
||||||
|
|
||||||
|
expect(tree).toMatchSnapshot();
|
||||||
|
});
|
||||||
369
components/footer/footerMain.tsx
Normal file
369
components/footer/footerMain.tsx
Normal file
@@ -0,0 +1,369 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Alert, Button, Image, StyleSheet, Dimensions, SafeAreaView, ScrollView, TouchableOpacity } from 'react-native';
|
||||||
|
import { Text, View, } from '../Themed';
|
||||||
|
import { TextInput } from 'react-native-gesture-handler';
|
||||||
|
import { Ionicons, FontAwesome } from '@expo/vector-icons';
|
||||||
|
import { LinearGradient } from 'expo-linear-gradient';
|
||||||
|
|
||||||
|
const PolicyFooter = () => {
|
||||||
|
return (
|
||||||
|
<View style={styles.homePolicy}>
|
||||||
|
<LinearGradient colors={['#243a76', '#ed1b24']} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={styles.bgLinearGradient}>
|
||||||
|
<Text style={styles.homePolicyTitle}>
|
||||||
|
Chính sách bán hàng
|
||||||
|
</Text>
|
||||||
|
</LinearGradient>
|
||||||
|
<View style={styles.homePolicyList}>
|
||||||
|
<View style={styles.homePolicyItem}>
|
||||||
|
<FontAwesome style={styles.homePolicyIcon} name="truck" size={25} />
|
||||||
|
<View>
|
||||||
|
<Text style={styles.homePolicyTextSt}>CHÍNH SÁCH GIAO HÀNG</Text>
|
||||||
|
<Text style={styles.homePolicyTextNd}>Nhận hàng và thanh toán tại nhà</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={styles.homePolicyItem}>
|
||||||
|
<FontAwesome style={styles.homePolicyIcon} name="refresh" size={25} />
|
||||||
|
<View>
|
||||||
|
<Text style={styles.homePolicyTextSt}>ĐỔI TRẢ DỄ DÀNG</Text>
|
||||||
|
<Text style={styles.homePolicyTextNd}>Dùng thử trong vòng 3 ngày</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={styles.homePolicyItem}>
|
||||||
|
<FontAwesome style={styles.homePolicyIcon} name="credit-card" size={25} />
|
||||||
|
<View>
|
||||||
|
<Text style={styles.homePolicyTextSt}>THANH TOÁN TIỆN LỢI</Text>
|
||||||
|
<Text style={styles.homePolicyTextNd}>Trả tiền mặt, CK, trả góp 0%</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={styles.homePolicyItem}>
|
||||||
|
<FontAwesome style={styles.homePolicyIcon} name="comments-o" size={25} />
|
||||||
|
<View>
|
||||||
|
<Text style={styles.homePolicyTextSt}>HỖ TRỢ NHIỆT TÌNH</Text>
|
||||||
|
<Text style={styles.homePolicyTextNd}>Tư vấn, giải đáp mọi thắc mắc</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Social = () => {
|
||||||
|
return (
|
||||||
|
<View style={styles.homeSocial}>
|
||||||
|
<LinearGradient colors={['#243a76', '#ed1b24']} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={styles.bgLinearGradient}>
|
||||||
|
<Text style={styles.homePolicyTitle}>
|
||||||
|
Kết nối với chúng tôi
|
||||||
|
</Text>
|
||||||
|
</LinearGradient>
|
||||||
|
<View style={styles.homeSocialList}>
|
||||||
|
<View style={styles.homeSocialItem}>
|
||||||
|
<FontAwesome style={styles.homeSocialIconFace} name="facebook" size={25} />
|
||||||
|
</View>
|
||||||
|
<View style={styles.homeSocialItem}>
|
||||||
|
<FontAwesome style={styles.homeSocialIconYoutube} name="youtube-play" size={25} />
|
||||||
|
</View>
|
||||||
|
<View style={styles.homeSocialItem}>
|
||||||
|
<LinearGradient colors={['#f09433', '#e6683c', '#dc2743', '#cc2366', '#bc1888']} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={styles.homeSocialItemBg}>
|
||||||
|
<FontAwesome style={styles.homeSocialIconInsta} name="instagram" size={25} />
|
||||||
|
</LinearGradient>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ShowroomList = () => {
|
||||||
|
const [showFooter, setFooter] = useState('');
|
||||||
|
|
||||||
|
const ShowroomData = [
|
||||||
|
{
|
||||||
|
id: 'id1',
|
||||||
|
title: 'HANOICOMPUTER - HAI BÀ TRƯNG',
|
||||||
|
address: '- 129+131 Lê Thanh Nghị - Đồng Tâm - Hai Bà Trưng - Hà Nội\n- Tel: (024) 36282024\n- Email: kinhdoanhle.lethanhnghi@hanoicomputer.com\n\n'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'id2',
|
||||||
|
title: 'HANOICOMPUTER - ĐỐNG ĐA',
|
||||||
|
address: '- 43 Thái Hà - Trung Liệt - Đống Đa - Hà Nội\n- Tel: 1900 1903 (máy lẻ 201) - (024) 35380088\n- Email: kinhdoanhle.thaiha@hanoicomputer.com\n\n'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'id3',
|
||||||
|
title: 'HANOICOMPUTER - CẦU GIẤY',
|
||||||
|
address: '- 79 Nguyễn Văn Huyên - Cầu Giấy - Hà Nội\n- Tel: 1900 1903 (máy lẻ 503) - (024) 38610088\n- Email: kinhdoanhle.caugiay@hanoicomputer.com\n\n'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'id4',
|
||||||
|
title: 'HANOICOMPUTER - HÀ ĐÔNG',
|
||||||
|
address: '- 511+513 Quang Trung - Hà Đông - Hà Nội\n- Tel: 1900 1903 (máy lẻ 600) - (024) 38580088\n- Email: kinhdoanhle.hadong@hanoicomputer.com\n\n'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'id5',
|
||||||
|
title: 'HANOICOMPUTER - HẢI PHÒNG',
|
||||||
|
address: '- A1-6 Lô 8A, Lê Hồng Phong, Quận Ngô Quyền, Hải Phòng\n- Tel: 1900 1903 (máy lẻ 301) - (022) 58830013\n- Email: kinhdoanhle.haiphong@hanoicomputer.com\n\n'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'id6',
|
||||||
|
title: 'HANOICOMPUTER - TP. HỒ CHÍ MINH',
|
||||||
|
address: '- 520 Cách Mạng Tháng Tám - Phường 11 - Quận 3 - TP. Hồ Chí Minh\n- Tel: 1900 1903 (máy lẻ 710) - (028) 73078877\n- Email: kd.hcmq3@hanoicomputer.com\n\n'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'id7',
|
||||||
|
title: 'HANOICOMPUTER - LONG BIÊN',
|
||||||
|
address: '- Số 398 Nguyễn Văn Cừ - Long Biên - Hà Nội\n- Tel: 19001903 (máy lẻ 808) - (024) 73088877\n- Email: kinhdoanh.longbien@hanoicomputer.com\n\n'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'id8',
|
||||||
|
title: 'PHÒNG CAMERA & TB AN NINH',
|
||||||
|
address: '- 43 Thái Hà - Trung Liệt - Đống Đa - Hà Nội\n- Phụ trách: Anh Nguyễn Văn Hiển\n- Mobile: 096.411.0606\n- Email: hiennv@hanoicomputer.com\n\n'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'id9',
|
||||||
|
title: 'PHÒNG BÁN HÀNG DỰ ÁN',
|
||||||
|
address: '- 129 + 131 Lê Thanh Nghị, Đồng Tâm, Hai Bà Trưng, Hà Nội\n- Tel: 0913.226.335\n- Email: diepnm@hanoicomputer.com\n\n'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'id10',
|
||||||
|
title: 'PHÒNG BÁN HÀNG TRỰC TUYẾN',
|
||||||
|
address: '- 129 + 131 Lê Thanh Nghị, Đồng Tâm, Hai Bà Trưng, Hà Nội\n- Tel: 098.33033.90 / 096.266.0316\n- Email: thuydb@hanoicomputer.com\n\n'
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.homeShowrrom}>
|
||||||
|
<LinearGradient colors={['#243a76', '#ed1b24']} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={styles.bgLinearGradient}>
|
||||||
|
<Text style={styles.homePolicyTitle}>
|
||||||
|
Hệ thông showroom
|
||||||
|
</Text>
|
||||||
|
</LinearGradient>
|
||||||
|
<View style={styles.homeShowrromList}>
|
||||||
|
|
||||||
|
{
|
||||||
|
ShowroomData.map(item => <ShowroomOneItem key={item.id}
|
||||||
|
title={item.title} id={item.id} setFooter={setFooter} address={item.address} current_show_id={showFooter} />)
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ShowroomOneItem = (props: { id: string, current_show_id: string, title: string, address: string, setFooter: (id: string) => void }) => {
|
||||||
|
|
||||||
|
const { id, current_show_id, title, address, setFooter } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.homeShowrromItem}>
|
||||||
|
<TouchableOpacity onPress={() => setFooter(id)} style={styles.homeShowrromItemTitle}>
|
||||||
|
<Text style={styles.homeShowrromItemTitleText}>{title}</Text>
|
||||||
|
<Text style={styles.homeShowrromItemTitleIcon}>{current_show_id == id ? '-' : '+'}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<View style={current_show_id == id ? styles.homeShowrromItemContentHienThi : styles.homeShowrromItemContent}>
|
||||||
|
<Text>
|
||||||
|
{address}
|
||||||
|
<TouchableOpacity onPress={() => Alert.alert('Go to map')} style={styles.homeShowrromItemContentMap}>
|
||||||
|
<Text style={styles.homeShowrromItemContentMapText}>- Xem bản đồ</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const FooterInfo = () => {
|
||||||
|
return (
|
||||||
|
<View style={styles.footer}>
|
||||||
|
<Text style={styles.footerBold}>© 2020 Công Ty Cổ Phần Máy Tính Hà Nội</Text>
|
||||||
|
<Text style={styles.footerText}>
|
||||||
|
Địa chỉ: Số 129 + 131, phố Lê Thanh Nghị, Phường Đồng Tâm, Quận Hai Bà Trưng, Hà Nội{'\n'}{'\n'}
|
||||||
|
GPĐKKD số 0101161194 do Sở KHĐT Tp.Hà Nội cấp ngày 31/8/2001{'\n'}{'\n'}
|
||||||
|
Email: hnc@hanoicomputer.com. Điện thoại: 1900 1903
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { PolicyFooter, Social, ShowroomList, FooterInfo }
|
||||||
|
|
||||||
|
let winWidth = Dimensions.get('window').width; //full width
|
||||||
|
let winHeight = Dimensions.get('window').height; //full height
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
bgLinearGradient: {
|
||||||
|
marginBottom: 20,
|
||||||
|
borderRadius: 5,
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
homePolicy: {
|
||||||
|
width: winWidth,
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
},
|
||||||
|
homePolicyTitle: {
|
||||||
|
width: '100%',
|
||||||
|
fontSize: 15,
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
borderRadius: 3,
|
||||||
|
lineHeight: 40,
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
fontWeight: '700',
|
||||||
|
color: '#fff',
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
homePolicyList: {
|
||||||
|
paddingTop: 10,
|
||||||
|
paddingBottom: 10,
|
||||||
|
},
|
||||||
|
homePolicyItem: {
|
||||||
|
marginBottom: 10,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
padding: 10,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#d9d9d9',
|
||||||
|
borderRadius: 5,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
homePolicyIcon: {
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: 50,
|
||||||
|
borderRadius: 25,
|
||||||
|
backgroundColor: '#2b3179',
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 23,
|
||||||
|
overflow: 'hidden',
|
||||||
|
marginRight: 10.
|
||||||
|
},
|
||||||
|
homePolicyTextSt: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
marginBottom: 5,
|
||||||
|
},
|
||||||
|
homePolicyTextNd: {
|
||||||
|
fontSize: 13,
|
||||||
|
},
|
||||||
|
homeSocial: {
|
||||||
|
marginBottom: 20,
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
},
|
||||||
|
homeSocialList: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
homeSocialItem: {
|
||||||
|
marginRight: 10,
|
||||||
|
},
|
||||||
|
homeSocialIconFace: {
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: 50,
|
||||||
|
borderRadius: 25,
|
||||||
|
backgroundColor: '#2b3179',
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 23,
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
homeSocialIconYoutube: {
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: 50,
|
||||||
|
borderRadius: 25,
|
||||||
|
backgroundColor: '#ff0000',
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 23,
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
homeSocialIconInsta: {
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: 50,
|
||||||
|
borderRadius: 25,
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 23,
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
homeSocialItemBg: {
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: 50,
|
||||||
|
borderRadius: 25,
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 23,
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
homeShowrrom: {
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
homeShowrromList: {
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 5,
|
||||||
|
borderColor: '#d9d9d9',
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
homeShowrromItem: {
|
||||||
|
|
||||||
|
},
|
||||||
|
homeShowrromItemTitle: {
|
||||||
|
position: 'relative',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
borderColor: '#d9d9d9',
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
},
|
||||||
|
homeShowrromItemTitleText: {
|
||||||
|
color: '#333',
|
||||||
|
lineHeight: 40,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
homeShowrromItemTitleIcon: {
|
||||||
|
color: '#333',
|
||||||
|
lineHeight: 40,
|
||||||
|
fontSize: 16,
|
||||||
|
},
|
||||||
|
homeShowrromItemContent: {
|
||||||
|
padding: 10,
|
||||||
|
fontSize: 12,
|
||||||
|
borderColor: '#d9d9d9',
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
overflow: 'hidden',
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
homeShowrromItemContentHienThi: {
|
||||||
|
padding: 10,
|
||||||
|
fontSize: 12,
|
||||||
|
borderColor: '#d9d9d9',
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
},
|
||||||
|
homeShowrromItemContentMap: {},
|
||||||
|
homeShowrromItemContentMapText: {
|
||||||
|
color: '#0063C3'
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
},
|
||||||
|
footerBold: {
|
||||||
|
textAlign: 'center',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
footerText: {
|
||||||
|
textAlign: 'center',
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
})
|
||||||
144
components/header/headerMain.tsx
Normal file
144
components/header/headerMain.tsx
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
import 'react-native-gesture-handler';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Alert, Button, Image, StyleSheet, Dimensions, SafeAreaView, ScrollView, TouchableOpacity } from 'react-native';
|
||||||
|
import { Text, View, } from '../Themed';
|
||||||
|
import { TextInput } from 'react-native-gesture-handler';
|
||||||
|
import { Ionicons, FontAwesome } from '@expo/vector-icons';
|
||||||
|
import { createDrawerNavigator, DrawerItemList, DrawerItem, DrawerContentScrollView } from '@react-navigation/drawer';
|
||||||
|
import { NavigationContainer } from '@react-navigation/native';
|
||||||
|
import { createStackNavigator } from '@react-navigation/stack';
|
||||||
|
import Animated, { Easing } from 'react-native-reanimated';
|
||||||
|
|
||||||
|
const Header = ({props} : {props : any}) => {
|
||||||
|
const toggleDrawer = () => {
|
||||||
|
//Props to open/close the drawer
|
||||||
|
props.toggleDrawer();
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<View style={styles.headerAll}>
|
||||||
|
<View style={styles.header}>
|
||||||
|
<TouchableOpacity onPress={toggleDrawer} style={styles.menu}>
|
||||||
|
<Ionicons style={styles.iconMenu} name="md-list" size={32} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<View style={styles.bgNone}>
|
||||||
|
<Image style={styles.img} source={{ uri: 'https://www.hanoicomputer.vn/media/lib/logo-trang.png' }} />
|
||||||
|
</View>
|
||||||
|
<View style={styles.headerCart}>
|
||||||
|
<Ionicons style={styles.iconMenu} name="cart-outline" size={32} />
|
||||||
|
<Text style={styles.countCart}>0</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<MainSeach />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const MainSeach = () => {
|
||||||
|
return (
|
||||||
|
<View style={styles.boxSearch}>
|
||||||
|
<View style={styles.boxSearchBo}>
|
||||||
|
<TextInput style={styles.inputSearch} placeholder="Nhập tên, mã sản phẩm" autoCapitalize="none" />
|
||||||
|
<Ionicons style={styles.buttonSearch} onPress={() => { Alert.alert('aaaaaaaaaa') }} name="search-outline" size={26} />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Header, MainSeach };
|
||||||
|
|
||||||
|
let winWidth = Dimensions.get('window').width; //full width
|
||||||
|
let winHeight = Dimensions.get('window').height; //full height
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
headerAll: {
|
||||||
|
width: winWidth,
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
bgNone: {
|
||||||
|
backgroundColor: 'rgba(0, 0, 0, 0)',
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
backgroundColor: '#243a76',
|
||||||
|
height: 53,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
width: winWidth,
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
menu: {
|
||||||
|
backgroundColor: '#243a76',
|
||||||
|
},
|
||||||
|
iconMenu: {
|
||||||
|
color: '#fff',
|
||||||
|
},
|
||||||
|
headerCart: {
|
||||||
|
backgroundColor: 'rgba(0,0,0,0)',
|
||||||
|
position: 'relative',
|
||||||
|
},
|
||||||
|
countCart: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: -5,
|
||||||
|
right: -5,
|
||||||
|
zIndex: 1,
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
backgroundColor: '#ffe100',
|
||||||
|
borderRadius: 10,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: 20,
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#000',
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
img: {
|
||||||
|
height: 40,
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
boxSearch: {
|
||||||
|
position: 'relative',
|
||||||
|
padding: 10,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
width: winWidth,
|
||||||
|
shadowColor: "#000",
|
||||||
|
shadowOffset: {
|
||||||
|
width: 0,
|
||||||
|
height: 1,
|
||||||
|
},
|
||||||
|
shadowOpacity: 0.18,
|
||||||
|
shadowRadius: 1.00,
|
||||||
|
elevation: 1,
|
||||||
|
},
|
||||||
|
boxSearchBo: {
|
||||||
|
position: 'relative',
|
||||||
|
flexDirection: 'row',
|
||||||
|
borderWidth: 1,
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
borderStyle: 'solid',
|
||||||
|
alignItems: 'center',
|
||||||
|
borderRadius: 5,
|
||||||
|
display: 'flex',
|
||||||
|
height: 38,
|
||||||
|
padding: 0,
|
||||||
|
margin: 0,
|
||||||
|
},
|
||||||
|
inputSearch: {
|
||||||
|
width: winWidth - 65,
|
||||||
|
padding: 10,
|
||||||
|
paddingTop: 10,
|
||||||
|
paddingBottom: 10,
|
||||||
|
height: 36,
|
||||||
|
margin: 0,
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
buttonSearch: {
|
||||||
|
width: 40,
|
||||||
|
textAlign: 'center',
|
||||||
|
height: 36,
|
||||||
|
lineHeight: 36,
|
||||||
|
},
|
||||||
|
})
|
||||||
245
components/product/productItem.tsx
Normal file
245
components/product/productItem.tsx
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Alert, Button, Image, StyleSheet, Dimensions, SafeAreaView, ScrollView, TouchableOpacity, Pressable } from 'react-native';
|
||||||
|
import { Text, View, } from '../Themed';
|
||||||
|
import { Ionicons, FontAwesome } from '@expo/vector-icons';
|
||||||
|
import ProductDetail from '../../screens/ProductDetail';
|
||||||
|
import { createDrawerNavigator, DrawerItemList, DrawerItem, DrawerContentScrollView } from '@react-navigation/drawer';
|
||||||
|
import { NavigationContainer } from '@react-navigation/native';
|
||||||
|
import { createStackNavigator, StackScreenProps } from '@react-navigation/stack';
|
||||||
|
import { NativeRouter, Route, Link } from "react-router-native";
|
||||||
|
import { TextInput } from 'react-native-gesture-handler';
|
||||||
|
import { Checkbox } from 'react-native-paper';
|
||||||
|
|
||||||
|
const Stack = createStackNavigator();
|
||||||
|
const Drawer = createDrawerNavigator();
|
||||||
|
|
||||||
|
function formatCurrency(price: string | number) {
|
||||||
|
let priceConvert = parseFloat(`${price}`).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, "$1.").toString();
|
||||||
|
let len = priceConvert.length;
|
||||||
|
return priceConvert.substring(0, len - 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ShowProductItem = (props: { id: number, productName: string, productSKU: string, productImage: { small: string, medium: string, large: string, original: string }, price: number, marketPrice: number, quantity: number, privateStyle: object }) => {
|
||||||
|
|
||||||
|
const { id, productName, productSKU, productImage, price, marketPrice, quantity, privateStyle } = props;
|
||||||
|
const discount = Math.ceil(100 - (price / marketPrice * 100));
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={[styles.itemProduct, privateStyle]}>
|
||||||
|
<View style={styles.pBloxImgProduct}>
|
||||||
|
<Text style={styles.pSkuProduct}>{productSKU}</Text>
|
||||||
|
<Text style={styles.pDiscountProduct}>-{discount}%</Text>
|
||||||
|
<View style={styles.pBloxImgProductBao}>
|
||||||
|
<Image style={styles.pImgProduct} source={{ uri: productImage.large }} />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.pNameProduct} numberOfLines={2}>
|
||||||
|
{productName}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.priceProduct}>{formatCurrency(price)} đ</Text>
|
||||||
|
<Text style={styles.oldPriceProduct}>{formatCurrency(marketPrice)} đ</Text>
|
||||||
|
<View style={styles.pBottonProduct}>
|
||||||
|
<Text style={styles.pStatusProduct}>
|
||||||
|
{quantity > 0 ? <Ionicons style={styles.pStatusProductIcon} name="checkmark-outline" size={13} /> : <Ionicons style={styles.pStatusProductIcon} name="close-outline" size={13} />}
|
||||||
|
{quantity > 0 ? 'Còn hàng' : 'Hết hàng'}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.pCartProduct}><Ionicons style={styles.pCartProductIcon} name="cart-outline" size={13} />Giỏ hàng</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ItemComboSet = (props: { id: number, productName: string, productSKU: string, productImage: { small: string, medium: string, large: string, original: string }, price: number, marketPrice: number, quantity: number }) => {
|
||||||
|
|
||||||
|
const { id, productName, productSKU, productImage, price, marketPrice, quantity } = props;
|
||||||
|
const discountCombo = Math.ceil(100 - (price / marketPrice * 100));
|
||||||
|
const [checked, setChecked] = React.useState(false);
|
||||||
|
return (
|
||||||
|
<View style={[styles.itemProductCombo]}>
|
||||||
|
<View style={styles.pBloxImgProduct}>
|
||||||
|
<View style={styles.pBloxImgProductBao}>
|
||||||
|
<Image style={styles.pImgProduct} source={{ uri: productImage.large }} />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={styles.pNameProductAll}>
|
||||||
|
<Checkbox.IOS status={checked ? 'checked' : 'unchecked'} onPress={() => setChecked(!checked)} style={styles.inputComboCheck} />
|
||||||
|
<Text style={[styles.pNameProduct, styles.pNameProductCombo]} numberOfLines={2}>
|
||||||
|
{productName}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.priceProductAll}>
|
||||||
|
<Text style={[styles.priceProduct, styles.priceProductCombo]}>{formatCurrency(price)} đ</Text>
|
||||||
|
<Text style={[styles.oldPriceProduct, styles.oldPriceProductCombo]}>{formatCurrency(marketPrice)} đ</Text>
|
||||||
|
<Text style={styles.pDiscountProductCombo}>-{discountCombo}%</Text>
|
||||||
|
</View>
|
||||||
|
<TouchableOpacity onPress={() => Alert.alert('popup product')} >
|
||||||
|
<Text>Chọn tai nghe khác</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ItemComboSetProDetail = (props: { id: number, productName: string, productSKU: string, productImage: { small: string, medium: string, large: string, original: string }, price: number, marketPrice: number, quantity: number }) => {
|
||||||
|
|
||||||
|
const { id, productName, productSKU, productImage, price, marketPrice, quantity } = props;
|
||||||
|
const discountCombo = Math.ceil(100 - (price / marketPrice * 100));
|
||||||
|
return (
|
||||||
|
<View style={[styles.itemProductCombo]}>
|
||||||
|
<View style={styles.pBloxImgProduct}>
|
||||||
|
<View style={styles.pBloxImgProductBao}>
|
||||||
|
<Image style={styles.pImgProduct} source={{ uri: productImage.large }} />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.pNameProduct} numberOfLines={2}>
|
||||||
|
{productName}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.priceProduct}>{formatCurrency(price)} đ</Text>
|
||||||
|
<Text style={styles.oldPriceProduct}>{formatCurrency(marketPrice)} đ</Text>
|
||||||
|
<Text style={styles.pDiscountProductCombo}>-{discountCombo}%</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { ShowProductItem, ItemComboSet, ItemComboSetProDetail };
|
||||||
|
|
||||||
|
let winWidth = Dimensions.get('window').width; //full width
|
||||||
|
let winHeight = Dimensions.get('window').height; //full height
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
itemProduct: {
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
pBloxImgProduct: {
|
||||||
|
position: 'relative',
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
pSkuProduct: {
|
||||||
|
position: 'absolute',
|
||||||
|
fontSize: 12,
|
||||||
|
color: '#e00',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
lineHeight: 36,
|
||||||
|
zIndex: 10,
|
||||||
|
},
|
||||||
|
pDiscountProduct: {
|
||||||
|
width: 36,
|
||||||
|
height: 36,
|
||||||
|
backgroundColor: '#e00',
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
color: '#fff',
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: 36,
|
||||||
|
borderRadius: 18,
|
||||||
|
overflow: 'hidden',
|
||||||
|
fontSize: 12,
|
||||||
|
zIndex: 10,
|
||||||
|
},
|
||||||
|
pBloxImgProductBao: {
|
||||||
|
position: 'relative',
|
||||||
|
paddingTop: '100%',
|
||||||
|
overflow: 'hidden',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
},
|
||||||
|
pImgProduct: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: '5%',
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
maxHeight: 500,
|
||||||
|
width: '90%',
|
||||||
|
},
|
||||||
|
pNameProduct: {
|
||||||
|
height: 40,
|
||||||
|
lineHeight: 20,
|
||||||
|
overflow: 'hidden',
|
||||||
|
fontSize: 14,
|
||||||
|
color: '#111',
|
||||||
|
marginBottom: 5,
|
||||||
|
},
|
||||||
|
priceProduct: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#f10000',
|
||||||
|
marginBottom: 5,
|
||||||
|
},
|
||||||
|
oldPriceProduct: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: '#b7b7b7',
|
||||||
|
marginBottom: 5,
|
||||||
|
height: 24,
|
||||||
|
lineHeight: 24,
|
||||||
|
overflow: 'hidden',
|
||||||
|
textDecorationLine: 'line-through',
|
||||||
|
},
|
||||||
|
pBottonProduct: {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
marginTop: 5,
|
||||||
|
},
|
||||||
|
pStatusProduct: {
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#00a706',
|
||||||
|
},
|
||||||
|
pCartProduct: {
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#333',
|
||||||
|
},
|
||||||
|
pStatusProductIcon: {
|
||||||
|
fontSize: 15,
|
||||||
|
},
|
||||||
|
pCartProductIcon: {
|
||||||
|
fontSize: 15
|
||||||
|
},
|
||||||
|
itemProductCombo: {
|
||||||
|
width: '100%',
|
||||||
|
marginBottom: 10,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#e1e1e1',
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
inputComboCheck: {
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
borderColor: '#222',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 3,
|
||||||
|
alignSelf: 'center',
|
||||||
|
backgroundColor: '#e0c',
|
||||||
|
},
|
||||||
|
pDiscountProductCombo: {
|
||||||
|
textDecorationLine: 'line-through'
|
||||||
|
},
|
||||||
|
priceProductAll: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'baseline'
|
||||||
|
},
|
||||||
|
pNameProductCombo: {
|
||||||
|
paddingLeft: 10,
|
||||||
|
width: winWidth - 70,
|
||||||
|
},
|
||||||
|
pNameProductAll: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
priceProductCombo: {
|
||||||
|
lineHeight: 22,
|
||||||
|
},
|
||||||
|
oldPriceProductCombo: {
|
||||||
|
lineHeight: 22,
|
||||||
|
marginHorizontal: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
})
|
||||||
19
constants/Colors.ts
Normal file
19
constants/Colors.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
const tintColorLight = '#2f95dc';
|
||||||
|
const tintColorDark = '#fff';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
light: {
|
||||||
|
text: '#000',
|
||||||
|
background: '#fff',
|
||||||
|
tint: tintColorLight,
|
||||||
|
tabIconDefault: '#ccc',
|
||||||
|
tabIconSelected: tintColorLight,
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
text: '#fff',
|
||||||
|
background: '#000',
|
||||||
|
tint: tintColorDark,
|
||||||
|
tabIconDefault: '#ccc',
|
||||||
|
tabIconSelected: tintColorDark,
|
||||||
|
},
|
||||||
|
};
|
||||||
12
constants/Layout.ts
Normal file
12
constants/Layout.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { Dimensions } from 'react-native';
|
||||||
|
|
||||||
|
const width = Dimensions.get('window').width;
|
||||||
|
const height = Dimensions.get('window').height;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
window: {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
},
|
||||||
|
isSmallDevice: width < 375,
|
||||||
|
};
|
||||||
33
hooks/useCachedResources.ts
Normal file
33
hooks/useCachedResources.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
import * as Font from 'expo-font';
|
||||||
|
import * as SplashScreen from 'expo-splash-screen';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
export default function useCachedResources() {
|
||||||
|
const [isLoadingComplete, setLoadingComplete] = React.useState(false);
|
||||||
|
|
||||||
|
// Load any resources or data that we need prior to rendering the app
|
||||||
|
React.useEffect(() => {
|
||||||
|
async function loadResourcesAndDataAsync() {
|
||||||
|
try {
|
||||||
|
SplashScreen.preventAutoHideAsync();
|
||||||
|
|
||||||
|
// Load fonts
|
||||||
|
await Font.loadAsync({
|
||||||
|
...Ionicons.font,
|
||||||
|
'space-mono': require('../assets/fonts/SpaceMono-Regular.ttf'),
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
// We might want to provide this error information to an error reporting service
|
||||||
|
console.warn(e);
|
||||||
|
} finally {
|
||||||
|
setLoadingComplete(true);
|
||||||
|
SplashScreen.hideAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadResourcesAndDataAsync();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return isLoadingComplete;
|
||||||
|
}
|
||||||
8
hooks/useColorScheme.ts
Normal file
8
hooks/useColorScheme.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { ColorSchemeName, useColorScheme as _useColorScheme } from 'react-native';
|
||||||
|
|
||||||
|
// The useColorScheme value is always either light or dark, but the built-in
|
||||||
|
// type suggests that it can be null. This will not happen in practice, so this
|
||||||
|
// makes it a bit easier to work with.
|
||||||
|
export default function useColorScheme(): NonNullable<ColorSchemeName> {
|
||||||
|
return _useColorScheme() as NonNullable<ColorSchemeName>;
|
||||||
|
}
|
||||||
5
hooks/useColorScheme.web.ts
Normal file
5
hooks/useColorScheme.web.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// useColorScheme from react-native does not support web currently. You can replace
|
||||||
|
// this with react-native-appearance if you would like theme support on web.
|
||||||
|
export default function useColorScheme() {
|
||||||
|
return 'light';
|
||||||
|
}
|
||||||
73
navigation/BottomTabNavigator.tsx
Normal file
73
navigation/BottomTabNavigator.tsx
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||||
|
import { createStackNavigator } from '@react-navigation/stack';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import Colors from '../constants/Colors';
|
||||||
|
import useColorScheme from '../hooks/useColorScheme';
|
||||||
|
import TabOneScreen from '../screens/TabOneScreen';
|
||||||
|
import TabTwoScreen from '../screens/TabTwoScreen';
|
||||||
|
import { BottomTabParamList, TabOneParamList, TabTwoParamList } from '../types';
|
||||||
|
|
||||||
|
const BottomTab = createBottomTabNavigator<BottomTabParamList>();
|
||||||
|
|
||||||
|
export default function BottomTabNavigator() {
|
||||||
|
const colorScheme = useColorScheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BottomTab.Navigator
|
||||||
|
initialRouteName="TabOne"
|
||||||
|
tabBarOptions={{ activeTintColor: Colors[colorScheme].tint }}>
|
||||||
|
<BottomTab.Screen
|
||||||
|
name="TabOne"
|
||||||
|
component={TabOneNavigator}
|
||||||
|
options={{
|
||||||
|
tabBarIcon: ({ color }) => <TabBarIcon name="ios-code" color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<BottomTab.Screen
|
||||||
|
name="TabTwo"
|
||||||
|
component={TabTwoNavigator}
|
||||||
|
options={{
|
||||||
|
tabBarIcon: ({ color }) => <TabBarIcon name="ios-code" color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</BottomTab.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can explore the built-in icon families and icons on the web at:
|
||||||
|
// https://icons.expo.fyi/
|
||||||
|
function TabBarIcon(props: { name: React.ComponentProps<typeof Ionicons>['name']; color: string }) {
|
||||||
|
return <Ionicons size={30} style={{ marginBottom: -3 }} {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each tab has its own navigation stack, you can read more about this pattern here:
|
||||||
|
// https://reactnavigation.org/docs/tab-based-navigation#a-stack-navigator-for-each-tab
|
||||||
|
const TabOneStack = createStackNavigator<TabOneParamList>();
|
||||||
|
|
||||||
|
function TabOneNavigator() {
|
||||||
|
return (
|
||||||
|
<TabOneStack.Navigator>
|
||||||
|
<TabOneStack.Screen
|
||||||
|
name="TabOneScreen"
|
||||||
|
component={TabOneScreen}
|
||||||
|
options={{ headerTitle: 'Tab One Title' }}
|
||||||
|
/>
|
||||||
|
</TabOneStack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const TabTwoStack = createStackNavigator<TabTwoParamList>();
|
||||||
|
|
||||||
|
function TabTwoNavigator() {
|
||||||
|
return (
|
||||||
|
<TabTwoStack.Navigator>
|
||||||
|
<TabTwoStack.Screen
|
||||||
|
name="TabTwoScreen"
|
||||||
|
component={TabTwoScreen}
|
||||||
|
options={{ headerTitle: 'Tab Two Title' }}
|
||||||
|
/>
|
||||||
|
</TabTwoStack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
24
navigation/LinkingConfiguration.ts
Normal file
24
navigation/LinkingConfiguration.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import * as Linking from 'expo-linking';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
prefixes: [Linking.makeUrl('/')],
|
||||||
|
config: {
|
||||||
|
screens: {
|
||||||
|
Root: {
|
||||||
|
screens: {
|
||||||
|
TabOne: {
|
||||||
|
screens: {
|
||||||
|
TabOneScreen: 'one',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TabTwo: {
|
||||||
|
screens: {
|
||||||
|
TabTwoScreen: 'two',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
NotFound: '*',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
34
navigation/index.tsx
Normal file
34
navigation/index.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { NavigationContainer, DefaultTheme, DarkTheme } from '@react-navigation/native';
|
||||||
|
import { createStackNavigator } from '@react-navigation/stack';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { ColorSchemeName } from 'react-native';
|
||||||
|
|
||||||
|
import NotFoundScreen from '../screens/NotFoundScreen';
|
||||||
|
import { RootStackParamList } from '../types';
|
||||||
|
import BottomTabNavigator from './BottomTabNavigator';
|
||||||
|
import LinkingConfiguration from './LinkingConfiguration';
|
||||||
|
|
||||||
|
// If you are not familiar with React Navigation, we recommend going through the
|
||||||
|
// "Fundamentals" guide: https://reactnavigation.org/docs/getting-started
|
||||||
|
export default function Navigation({ colorScheme }: { colorScheme: ColorSchemeName }) {
|
||||||
|
return (
|
||||||
|
<NavigationContainer
|
||||||
|
linking={LinkingConfiguration}
|
||||||
|
theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
||||||
|
<RootNavigator />
|
||||||
|
</NavigationContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A root stack navigator is often used for displaying modals on top of all other content
|
||||||
|
// Read more here: https://reactnavigation.org/docs/modal
|
||||||
|
const Stack = createStackNavigator<RootStackParamList>();
|
||||||
|
|
||||||
|
function RootNavigator() {
|
||||||
|
return (
|
||||||
|
<Stack.Navigator screenOptions={{ headerShown: false }}>
|
||||||
|
<Stack.Screen name="Root" component={BottomTabNavigator} />
|
||||||
|
<Stack.Screen name="NotFound" component={NotFoundScreen} options={{ title: 'Oops!' }} />
|
||||||
|
</Stack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
32042
package-lock.json
generated
Normal file
32042
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
65
package.json
Normal file
65
package.json
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"main": "node_modules/expo/AppEntry.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "expo start",
|
||||||
|
"android": "expo start --android",
|
||||||
|
"ios": "expo start --ios",
|
||||||
|
"web": "expo start --web",
|
||||||
|
"eject": "expo eject",
|
||||||
|
"test": "jest --watchAll"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"preset": "jest-expo"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@expo/vector-icons": "^12.0.0",
|
||||||
|
"@react-native-community/checkbox": "^0.5.7",
|
||||||
|
"@react-native-community/masked-view": "0.1.10",
|
||||||
|
"@react-native-picker/picker": "^1.9.12",
|
||||||
|
"@react-navigation/bottom-tabs": "5.11.2",
|
||||||
|
"@react-navigation/drawer": "^5.12.4",
|
||||||
|
"@react-navigation/native": "~5.8.10",
|
||||||
|
"@react-navigation/routers": "^5.7.2",
|
||||||
|
"@react-navigation/stack": "^5.12.8",
|
||||||
|
"@types/react-router": "^5.1.11",
|
||||||
|
"expo": "~40.0.0",
|
||||||
|
"expo-asset": "~8.2.1",
|
||||||
|
"expo-av": "~8.7.0",
|
||||||
|
"expo-constants": "~9.3.3",
|
||||||
|
"expo-font": "~8.4.0",
|
||||||
|
"expo-linear-gradient": "~8.4.0",
|
||||||
|
"expo-linking": "~2.0.1",
|
||||||
|
"expo-splash-screen": "~0.8.1",
|
||||||
|
"expo-status-bar": "~1.0.3",
|
||||||
|
"expo-web-browser": "~8.6.0",
|
||||||
|
"react": "16.13.1",
|
||||||
|
"react-dom": "16.13.1",
|
||||||
|
"react-native": "https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz",
|
||||||
|
"react-native-bem-check-box": "^1.0.0",
|
||||||
|
"react-native-gesture-handler": "~1.8.0",
|
||||||
|
"react-native-linear-gradient": "^2.5.6",
|
||||||
|
"react-native-paper": "^4.7.2",
|
||||||
|
"react-native-reanimated": "~1.13.0",
|
||||||
|
"react-native-safe-area-context": "3.1.9",
|
||||||
|
"react-native-screens": "~2.15.2",
|
||||||
|
"react-native-swiper": "^1.6.0-rc.3",
|
||||||
|
"react-native-table-component": "^1.2.1",
|
||||||
|
"react-native-textarea": "^1.0.4",
|
||||||
|
"react-native-web": "~0.13.12",
|
||||||
|
"react-native-youtube-iframe": "^1.4.1",
|
||||||
|
"react-router": "^5.2.0",
|
||||||
|
"react-router-native": "^5.2.0",
|
||||||
|
"styled-components": "^5.2.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "~7.9.0",
|
||||||
|
"@types/react": "~16.9.35",
|
||||||
|
"@types/react-native": "~0.63.2",
|
||||||
|
"@types/react-native-table-component": "^1.2.0",
|
||||||
|
"@types/react-router-native": "^5.1.0",
|
||||||
|
"@types/styled-components": "^5.1.7",
|
||||||
|
"jest-expo": "^40.0.0",
|
||||||
|
"typescript": "~4.0.0"
|
||||||
|
},
|
||||||
|
"private": true
|
||||||
|
}
|
||||||
492
screens/Cart.tsx
Normal file
492
screens/Cart.tsx
Normal file
@@ -0,0 +1,492 @@
|
|||||||
|
import 'react-native-gesture-handler';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Alert, Button, Image, StyleSheet, Dimensions, SafeAreaView, ScrollView, TouchableOpacity, Modal, Pressable, Share } from 'react-native';
|
||||||
|
import Constants from 'expo-constants';
|
||||||
|
import { Ionicons, FontAwesome } from '@expo/vector-icons';
|
||||||
|
import { LinearGradient } from 'expo-linear-gradient';
|
||||||
|
import { PolicyFooter, Social, ShowroomList, FooterInfo } from '../components/footer/footerMain';
|
||||||
|
|
||||||
|
import EditScreenInfo from '../components/EditScreenInfo';
|
||||||
|
import { Text, View, } from '../components/Themed';
|
||||||
|
import useColorScheme from '../hooks/useColorScheme';
|
||||||
|
import { TextInput } from 'react-native-gesture-handler';
|
||||||
|
import { RadioButton, Checkbox } from 'react-native-paper';
|
||||||
|
import { Picker } from '@react-native-picker/picker';
|
||||||
|
|
||||||
|
|
||||||
|
export default function CartDetail() {
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<ScrollView>
|
||||||
|
<View style={styles.boxCartPage}>
|
||||||
|
<View style={styles.boxCartPageHeader}>
|
||||||
|
<View style={styles.boxCartPageBackHome}>
|
||||||
|
<Pressable>
|
||||||
|
<Ionicons style={styles.boxCartPageBackHomeIcon} name="arrow-back-outline" />
|
||||||
|
</Pressable>
|
||||||
|
<Text style={styles.boxCartPageBackHomeText}>Giỏ hàng</Text>
|
||||||
|
</View>
|
||||||
|
<Pressable style={styles.boxCartPageDeleteAll}>
|
||||||
|
<Text style={styles.boxCartPageDeleteAllText}>Xóa toàn bộ</Text>
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
<View style={styles.boxCartPageListProduct}>
|
||||||
|
<CartItem />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Voucher />
|
||||||
|
|
||||||
|
<PayOption />
|
||||||
|
|
||||||
|
<CustommerInfoCart />
|
||||||
|
|
||||||
|
<PolicyFooter />
|
||||||
|
|
||||||
|
<Social />
|
||||||
|
|
||||||
|
<ShowroomList />
|
||||||
|
|
||||||
|
<FooterInfo />
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const CartItem = () => {
|
||||||
|
return (
|
||||||
|
<View style={styles.cartItem}>
|
||||||
|
<View style={styles.cartItemImg}>
|
||||||
|
<Image style={styles.cartItemImgContent} source={{ uri: 'https://hanoicomputercdn.com/media/product/250_56516_vosro3405__4_.png' }} />
|
||||||
|
</View>
|
||||||
|
<View style={styles.cartItemCtNd}>
|
||||||
|
<Text style={styles.cartItemProName} numberOfLines={2}>
|
||||||
|
Laptop Dell Vostro 3405 (V4R53500U003W) (R5 3500U 8GB asa asas )
|
||||||
|
</Text>
|
||||||
|
<TouchableOpacity style={styles.cartItemDelete}>
|
||||||
|
<FontAwesome style={styles.cartItemDeleteIcon} name="trash-o" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
<View style={styles.cartItemCtRd}>
|
||||||
|
<Text style={styles.cartItemPrice}>20.000.000 đ</Text>
|
||||||
|
<View style={styles.cartItemQuantity}>
|
||||||
|
<Pressable style={styles.cartItemQuantityChange}><Text style={styles.cartItemQuantityChangeText}>-</Text></Pressable>
|
||||||
|
<TextInput style={styles.cartItemQuantityInput} value="1" />
|
||||||
|
<Pressable style={styles.cartItemQuantityChange}><Text style={styles.cartItemQuantityChangeText}>+</Text></Pressable>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Voucher = () => {
|
||||||
|
return (
|
||||||
|
<View style={styles.voucher}>
|
||||||
|
<Text style={styles.voucherTitle}>Mã giảm giả / Quà tặng</Text>
|
||||||
|
<View style={styles.voucherContent}>
|
||||||
|
<TextInput style={styles.voucherInput} placeholder="Nhập mã giảm giá" />
|
||||||
|
<Pressable style={styles.voucherSubmit}>
|
||||||
|
<LinearGradient colors={['#243a76', '#ed1b24']} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }} style={styles.linearGradientBg}>
|
||||||
|
<Text style={styles.voucherSubmitText}>Áp dụng</Text>
|
||||||
|
</LinearGradient>
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const PayOption = () => {
|
||||||
|
const [checked, setChecked] = React.useState('pay1');
|
||||||
|
const listPayment = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'Thanh toán tiền mặt khi nhận hàng (tiền mặt / quẹt thẻ ATM, Visa, Master)',
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'Thanh toán qua chuyển khoản qua tài khoản ngân hàng (khuyên dùng)',
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: 'Thanh toán qua Ngân Lượng (ATM nội địa, Visa, Master)',
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: 'Trả góp qua Alepay (Ngân Lượng)',
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
return (
|
||||||
|
<View style={styles.BoxPayment}>
|
||||||
|
<Text style={styles.BoxPaymentTitle}>Lựa chọn hình thức thanh toán</Text>
|
||||||
|
<View style={styles.BoxPaymentList}>
|
||||||
|
{
|
||||||
|
listPayment.map(item => {
|
||||||
|
let idpay = 'pay' + item.id;
|
||||||
|
return (
|
||||||
|
<View style={styles.paymentItem} key={item.id}>
|
||||||
|
<View style={styles.paymentItemRadio}>
|
||||||
|
<RadioButton color={'#243a76'} value={idpay} status={checked === idpay ? 'checked' : 'unchecked'} onPress={() => setChecked(idpay)} />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.paymentItemText}>{item.name}</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const CustommerInfoCart = () => {
|
||||||
|
const [selectedLanguage, setSelectedLanguage] = useState();
|
||||||
|
const [checked, setChecked] = React.useState(false);
|
||||||
|
return (
|
||||||
|
<View style={styles.BoxCustommerInfoCart}>
|
||||||
|
<Text style={styles.BoxPaymentTitle}>Thông tin khách hàng</Text>
|
||||||
|
<View style={styles.BoxCustommerInfoCartList}>
|
||||||
|
<View style={styles.cartCusItem}>
|
||||||
|
<Text style={styles.cartCusItemText}>Họ và tên*</Text>
|
||||||
|
<TextInput style={styles.cartCusItemInput} />
|
||||||
|
</View>
|
||||||
|
<View style={styles.cartCusItem}>
|
||||||
|
<Text style={styles.cartCusItemText}>Email*</Text>
|
||||||
|
<TextInput style={styles.cartCusItemInput} />
|
||||||
|
</View>
|
||||||
|
<View style={styles.cartCusItem}>
|
||||||
|
<Text style={styles.cartCusItemText}>Số điện thoại*</Text>
|
||||||
|
<TextInput style={styles.cartCusItemInput} />
|
||||||
|
</View>
|
||||||
|
<View style={styles.cartCusItem}>
|
||||||
|
<Text style={styles.cartCusItemText}>Chọn tỉnh thành phố*</Text>
|
||||||
|
<Picker
|
||||||
|
style={styles.picker}
|
||||||
|
itemStyle={styles.onePickerItem}
|
||||||
|
selectedValue={selectedLanguage}
|
||||||
|
onValueChange={(itemValue, itemIndex) =>
|
||||||
|
setSelectedLanguage(itemValue)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Picker.Item label="Hà Nội" value="1" />
|
||||||
|
<Picker.Item label="Đà Nẵng" value="2" />
|
||||||
|
<Picker.Item label="Hải Phòng" value="3" />
|
||||||
|
<Picker.Item label="TP Hồ Chí Minh" value="4" />
|
||||||
|
</Picker>
|
||||||
|
</View>
|
||||||
|
<View style={styles.cartCusItem}>
|
||||||
|
<Text style={styles.cartCusItemText}>Địa chỉ*</Text>
|
||||||
|
<TextInput multiline={true} numberOfLines={3} style={styles.cartCusItemArea} />
|
||||||
|
</View>
|
||||||
|
<View style={styles.cartCusItem}>
|
||||||
|
<Text style={styles.cartCusItemText}>Ghi chú</Text>
|
||||||
|
<TextInput multiline={true} numberOfLines={4} style={styles.cartCusItemArea} />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={styles.companyCart}>
|
||||||
|
<View style={styles.companyCartCheck}>
|
||||||
|
<View style={styles.companyCartCheckBox}>
|
||||||
|
<Checkbox.IOS status={checked ? 'checked' : 'unchecked'} onPress={() => setChecked(!checked)} />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.companyCartCheckText}>Xuất hóa đơn công ty</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.companyCartList}>
|
||||||
|
<View style={styles.cartCusItem}>
|
||||||
|
<Text style={styles.cartCusItemText}>Công ty/ tổ chức*:</Text>
|
||||||
|
<TextInput multiline={true} numberOfLines={4} style={styles.cartCusItemArea} />
|
||||||
|
</View>
|
||||||
|
<View style={styles.cartCusItem}>
|
||||||
|
<Text style={styles.cartCusItemText}>Địa chỉ*:</Text>
|
||||||
|
<TextInput multiline={true} numberOfLines={4} style={styles.cartCusItemArea} />
|
||||||
|
</View>
|
||||||
|
<View style={styles.cartCusItem}>
|
||||||
|
<Text style={styles.cartCusItemText}>Mã số thuế*:</Text>
|
||||||
|
<TextInput multiline={true} numberOfLines={4} style={styles.cartCusItemArea} />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const winWidth = Dimensions.get('window').width; //full width
|
||||||
|
const winHeight = Dimensions.get('window').height; //full height
|
||||||
|
const halfWinWidth = winWidth / 2;
|
||||||
|
const ratio = winWidth / 500; //541 is actual image width
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
},
|
||||||
|
boxCartPage: {
|
||||||
|
marginBottom: 20,
|
||||||
|
width: winWidth
|
||||||
|
},
|
||||||
|
boxCartPageHeader: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
width: '100%',
|
||||||
|
height: 40,
|
||||||
|
alignItems: 'center',
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
borderBottomColor: '#d42333',
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
},
|
||||||
|
boxCartPageBackHome: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
boxCartPageBackHomeIcon: {
|
||||||
|
fontSize: 14,
|
||||||
|
marginRight: 8,
|
||||||
|
width: 30
|
||||||
|
},
|
||||||
|
boxCartPageBackHomeText: {
|
||||||
|
fontWeight: 'bold'
|
||||||
|
},
|
||||||
|
boxCartPageDeleteAll: {},
|
||||||
|
boxCartPageDeleteAllText: {
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#f00'
|
||||||
|
},
|
||||||
|
boxCartPageListProduct: {
|
||||||
|
width: winWidth - 20,
|
||||||
|
marginLeft: 10,
|
||||||
|
marginTop: 20,
|
||||||
|
shadowColor: "#000",
|
||||||
|
shadowOffset: {
|
||||||
|
width: 0,
|
||||||
|
height: 2,
|
||||||
|
},
|
||||||
|
shadowOpacity: 0.25,
|
||||||
|
shadowRadius: 3.84,
|
||||||
|
elevation: 5,
|
||||||
|
marginBottom: 15,
|
||||||
|
},
|
||||||
|
cartItem: {
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
cartItemImg: {
|
||||||
|
position: 'relative',
|
||||||
|
paddingTop: '100%',
|
||||||
|
overflow: 'hidden',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
cartItemImgContent: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: '5%',
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
maxHeight: 500,
|
||||||
|
width: '90%',
|
||||||
|
},
|
||||||
|
cartItemCtNd: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
marginBottom: 5,
|
||||||
|
width: '100%',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
cartItemProName: {
|
||||||
|
fontSize: 14,
|
||||||
|
height: 40,
|
||||||
|
lineHeight: 20,
|
||||||
|
width: winWidth - 80,
|
||||||
|
},
|
||||||
|
cartItemDelete: {
|
||||||
|
width: 60,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
height: 40,
|
||||||
|
alignItems: 'center',
|
||||||
|
display: 'flex',
|
||||||
|
},
|
||||||
|
cartItemDeleteIcon: {
|
||||||
|
fontSize: 24,
|
||||||
|
color: '#f00'
|
||||||
|
},
|
||||||
|
cartItemCtRd: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
width: '100%',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
cartItemPrice: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#e00'
|
||||||
|
},
|
||||||
|
cartItemQuantity: {
|
||||||
|
width: 100,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
borderColor: '#e1e1e1',
|
||||||
|
borderWidth: 1,
|
||||||
|
},
|
||||||
|
cartItemQuantityChange: {
|
||||||
|
width: 30,
|
||||||
|
height: 30,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
cartItemQuantityChangeText: {},
|
||||||
|
cartItemQuantityInput: {
|
||||||
|
width: 40,
|
||||||
|
height: 30,
|
||||||
|
textAlign: 'center',
|
||||||
|
borderLeftWidth: 1,
|
||||||
|
borderRightWidth: 1,
|
||||||
|
borderLeftColor: '#e1e1e1',
|
||||||
|
borderRightColor: '#e1e1e1',
|
||||||
|
},
|
||||||
|
voucher: {
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
voucherTitle: {
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: 14,
|
||||||
|
marginBottom: 5,
|
||||||
|
},
|
||||||
|
voucherContent: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
},
|
||||||
|
voucherInput: {
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#ccc',
|
||||||
|
height: 34,
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
borderRadius: 5,
|
||||||
|
width: winWidth - 110,
|
||||||
|
},
|
||||||
|
voucherSubmit: {
|
||||||
|
width: 85,
|
||||||
|
marginLeft: 5,
|
||||||
|
},
|
||||||
|
linearGradientBg: {
|
||||||
|
width: '100%',
|
||||||
|
height: 34,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
borderRadius: 5,
|
||||||
|
},
|
||||||
|
voucherSubmitText: {
|
||||||
|
color: '#fff',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
},
|
||||||
|
BoxPayment: {
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
},
|
||||||
|
BoxPaymentTitle: {
|
||||||
|
padding: 10,
|
||||||
|
backgroundColor: '#243a76',
|
||||||
|
borderRadius: 3,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#fff',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
overflow: 'hidden',
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
BoxPaymentList: {
|
||||||
|
flexDirection: 'column',
|
||||||
|
},
|
||||||
|
paymentItem: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
marginBottom: 10,
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
paymentItemRadio: {
|
||||||
|
width: 36,
|
||||||
|
height: 36,
|
||||||
|
borderRadius: 18,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#222',
|
||||||
|
marginRight: 10,
|
||||||
|
position: 'relative',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
paymentItemText: {
|
||||||
|
width: winWidth - 56,
|
||||||
|
},
|
||||||
|
BoxCustommerInfoCart: {
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
BoxCustommerInfoCartList: {
|
||||||
|
flexDirection: 'column',
|
||||||
|
},
|
||||||
|
cartCusItem: {
|
||||||
|
flexDirection: 'column',
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
cartCusItemText: {
|
||||||
|
fontSize: 14,
|
||||||
|
marginBottom: 5,
|
||||||
|
},
|
||||||
|
cartCusItemInput: {
|
||||||
|
height: 34,
|
||||||
|
width: '100%',
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
borderColor: '#e1e1e1',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 5,
|
||||||
|
},
|
||||||
|
cartCusItemArea: {
|
||||||
|
height: 65,
|
||||||
|
width: '100%',
|
||||||
|
padding: 10,
|
||||||
|
borderColor: '#e1e1e1',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 5,
|
||||||
|
},
|
||||||
|
picker: {
|
||||||
|
height: 42,
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
onePickerItem: {
|
||||||
|
height: 46,
|
||||||
|
color: '#222',
|
||||||
|
fontSize: 14,
|
||||||
|
textAlign: 'center',
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
companyCart: {
|
||||||
|
marginTop: 5,
|
||||||
|
},
|
||||||
|
companyCartCheck: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
companyCartCheckBox: {
|
||||||
|
width: 36,
|
||||||
|
height: 36,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#e1e1e1',
|
||||||
|
marginRight: 10,
|
||||||
|
borderRadius: 18,
|
||||||
|
},
|
||||||
|
companyCartCheckText: {},
|
||||||
|
companyCartList: {},
|
||||||
|
})
|
||||||
40
screens/NotFoundScreen.tsx
Normal file
40
screens/NotFoundScreen.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { StackScreenProps } from '@react-navigation/stack';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||||
|
|
||||||
|
import { RootStackParamList } from '../types';
|
||||||
|
|
||||||
|
export default function NotFoundScreen({
|
||||||
|
navigation,
|
||||||
|
}: StackScreenProps<RootStackParamList, 'NotFound'>) {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text style={styles.title}>This screen doesn't exist.</Text>
|
||||||
|
<TouchableOpacity onPress={() => navigation.replace('Root')} style={styles.link}>
|
||||||
|
<Text style={styles.linkText}>Go to home screen!</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
padding: 20,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
marginTop: 15,
|
||||||
|
paddingVertical: 15,
|
||||||
|
},
|
||||||
|
linkText: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: '#2e78b7',
|
||||||
|
},
|
||||||
|
});
|
||||||
1283
screens/ProductDetail.tsx
Normal file
1283
screens/ProductDetail.tsx
Normal file
File diff suppressed because it is too large
Load Diff
273
screens/TabOneScreen.tsx
Normal file
273
screens/TabOneScreen.tsx
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
import 'react-native-gesture-handler';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Alert, Button, Image, StyleSheet, Dimensions, SafeAreaView, ScrollView, TouchableOpacity } from 'react-native';
|
||||||
|
import Constants from 'expo-constants';
|
||||||
|
import { Ionicons, FontAwesome } from '@expo/vector-icons';
|
||||||
|
import { LinearGradient } from 'expo-linear-gradient';
|
||||||
|
import Swiper from 'react-native-swiper';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { PolicyFooter, Social, ShowroomList, FooterInfo } from '../components/footer/footerMain';
|
||||||
|
import { ShowProductItem } from '../components/product/productItem';
|
||||||
|
|
||||||
|
import EditScreenInfo from '../components/EditScreenInfo';
|
||||||
|
import { Text, View, } from '../components/Themed';
|
||||||
|
import useColorScheme from '../hooks/useColorScheme';
|
||||||
|
|
||||||
|
var winWidth = Dimensions.get('window').width; //full width
|
||||||
|
var winHeight = Dimensions.get('window').height; //full height
|
||||||
|
const ratio = winWidth / 930; //541 is actual image width
|
||||||
|
|
||||||
|
export default function TabOneScreen() {
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<ScrollView>
|
||||||
|
|
||||||
|
<SliderHome />
|
||||||
|
|
||||||
|
<CateHome />
|
||||||
|
|
||||||
|
<ShowProductList />
|
||||||
|
<ShowProductList />
|
||||||
|
|
||||||
|
<PolicyFooter />
|
||||||
|
|
||||||
|
<Social />
|
||||||
|
|
||||||
|
<ShowroomList />
|
||||||
|
|
||||||
|
<FooterInfo />
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const SliderHome = () => {
|
||||||
|
|
||||||
|
const imageSlider = [
|
||||||
|
'https://hanoicomputercdn.com/media/banner/04_Feb6a20714a3495fa80e985095a9a548f98.png',
|
||||||
|
'https://hanoicomputercdn.com/media/banner/19_Febbc8b55d8c3a6be385d8523c79eb4c8da.jpg',
|
||||||
|
'https://hanoicomputercdn.com/media/banner/25_Feb8a3b5d706fea215ed9004c6ad5ea9065.png'
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.slider}>
|
||||||
|
<Swiper style={styles.sliderSwipper} autoplay={true} showsButtons={false} index={3000} showsPagination={false}>
|
||||||
|
{
|
||||||
|
imageSlider.map((item, index) => {
|
||||||
|
return (<Image style={styles.imgSlider} key={index} source={{ uri: item }} />);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Swiper>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const CateHome = () => {
|
||||||
|
return (
|
||||||
|
<View style={styles.catHomepage}>
|
||||||
|
<View style={styles.catHomepageItem}>
|
||||||
|
<Ionicons style={styles.catHomepageIcon} name="list-outline" size={28} />
|
||||||
|
<Text style={styles.catHomepageText}>Danh mục sản phẩm</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.catHomepageItem}>
|
||||||
|
<Ionicons style={styles.catHomepageIcon} name="pricetags-outline" size={28} />
|
||||||
|
<Text style={styles.catHomepageText}>Chương trình khuyến mại</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.catHomepageItem}>
|
||||||
|
<Ionicons style={styles.catHomepageIcon} name="search-outline" size={28} />
|
||||||
|
<Text style={styles.catHomepageText}>Sản phẩm vừa xem</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.catHomepageItem}>
|
||||||
|
<Ionicons style={styles.catHomepageIcon} name="build-outline" size={28} />
|
||||||
|
<Text style={styles.catHomepageText}>Xây dựng cấu hình</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ShowProductList = () => {
|
||||||
|
|
||||||
|
const itemProductHomeStyle = {
|
||||||
|
width: 180,
|
||||||
|
borderRadius: 5,
|
||||||
|
margin: 5,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#e8e8e8',
|
||||||
|
}
|
||||||
|
const productData = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
productName: 'Laptop LG Gram 14ZD90N-V.AX55A5 (i5 1035G7/8GB RAM/512GBSSD/14.0 inch FHD/FP/Xám Bạc) (model 2020)',
|
||||||
|
productSKU: 'TESTSKU',
|
||||||
|
productImage: {
|
||||||
|
small: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
medium: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
large: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
original: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
},
|
||||||
|
price: 30000000,
|
||||||
|
marketPrice: 50000000,
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
productName: 'Laptop LG Gram 14ZD90N-V.AX55A5 (i5 1035G7/8GB RAM/512GBSSD/14.0 inch FHD/FP/Xám Bạc) (model 2020)',
|
||||||
|
productSKU: 'TESTSKU',
|
||||||
|
productImage: {
|
||||||
|
small: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
medium: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
large: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
original: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
},
|
||||||
|
price: 25000000,
|
||||||
|
marketPrice: 50000000,
|
||||||
|
quantity: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
productName: 'Laptop LG Gram 14ZD90N-V.AX55A5 (i5 1035G7/8GB RAM/512GBSSD/14.0 inch FHD/FP/Xám Bạc) (model 2020)',
|
||||||
|
productSKU: 'TESTSKU',
|
||||||
|
productImage: {
|
||||||
|
small: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
medium: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
large: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
original: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
},
|
||||||
|
price: 35000000,
|
||||||
|
marketPrice: 50000000,
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
productName: 'Laptop LG Gram 14ZD90N-V.AX55A5 (i5 1035G7/8GB RAM/512GBSSD/14.0 inch FHD/FP/Xám Bạc) (model 2020)',
|
||||||
|
productSKU: 'TESTSKU',
|
||||||
|
productImage: {
|
||||||
|
small: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
medium: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
large: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
original: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
},
|
||||||
|
price: 40000000,
|
||||||
|
marketPrice: 50000000,
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
productName: 'Laptop LG Gram 14ZD90N-V.AX55A5 (i5 1035G7/8GB RAM/512GBSSD/14.0 inch FHD/FP/Xám Bạc) (model 2020)',
|
||||||
|
productSKU: 'TESTSKU',
|
||||||
|
productImage: {
|
||||||
|
small: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
medium: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
large: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
original: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
},
|
||||||
|
price: 30000000,
|
||||||
|
marketPrice: 50000000,
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.bloxProductHome}>
|
||||||
|
<Text style={styles.titleProductHome}>Lap top, máy tính xách tay</Text>
|
||||||
|
<View style={styles.listProductHomeBao}>
|
||||||
|
<ScrollView horizontal={true} style={styles.listProductHome}>
|
||||||
|
{
|
||||||
|
productData.map(item => <ShowProductItem key={item.id} id={item.id} productName={item.productName}
|
||||||
|
productSKU={item.productSKU} productImage={item.productImage} price={item.price} marketPrice={item.marketPrice} quantity={item.quantity} privateStyle={itemProductHomeStyle}
|
||||||
|
/>)
|
||||||
|
}
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
},
|
||||||
|
slider: {
|
||||||
|
width: winWidth,
|
||||||
|
marginBottom: 20,
|
||||||
|
height: ratio * 430,
|
||||||
|
},
|
||||||
|
sliderSwipper: {
|
||||||
|
},
|
||||||
|
imgSlider: {
|
||||||
|
width: winWidth,
|
||||||
|
height: 430 * ratio,
|
||||||
|
},
|
||||||
|
catHomepage: {
|
||||||
|
width: winWidth,
|
||||||
|
marginBottom: 20,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
catHomepageItem: {
|
||||||
|
width: winWidth / 4,
|
||||||
|
padding: 10,
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
catHomepageIcon: {
|
||||||
|
width: 48,
|
||||||
|
height: 48,
|
||||||
|
backgroundColor: '#2b3179',
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: 48,
|
||||||
|
borderRadius: 24,
|
||||||
|
overflow: 'hidden',
|
||||||
|
color: '#fff',
|
||||||
|
marginBottom: 5,
|
||||||
|
},
|
||||||
|
catHomepageText: {
|
||||||
|
fontSize: 12,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#ff00cc',
|
||||||
|
},
|
||||||
|
bloxProductHome: {
|
||||||
|
width: winWidth,
|
||||||
|
marginBottom: 20,
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
titleProductHome: {
|
||||||
|
backgroundColor: '#243a76',
|
||||||
|
fontSize: 15,
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
borderRadius: 3,
|
||||||
|
lineHeight: 40,
|
||||||
|
marginBottom: 5,
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
fontWeight: '700',
|
||||||
|
color: '#fff',
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
listProductHomeBao: {
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
listProductHome: {
|
||||||
|
marginRight: -5,
|
||||||
|
marginLeft: -5,
|
||||||
|
},
|
||||||
|
});
|
||||||
549
screens/TabTwoScreen.tsx
Normal file
549
screens/TabTwoScreen.tsx
Normal file
@@ -0,0 +1,549 @@
|
|||||||
|
import 'react-native-gesture-handler';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Alert, Button, Image, StyleSheet, Dimensions, SafeAreaView, ScrollView, TouchableOpacity, Modal, Pressable } from 'react-native';
|
||||||
|
import Constants from 'expo-constants';
|
||||||
|
import { Ionicons, FontAwesome } from '@expo/vector-icons';
|
||||||
|
import { LinearGradient } from 'expo-linear-gradient';
|
||||||
|
import Swiper from 'react-native-swiper';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { PolicyFooter, Social, ShowroomList, FooterInfo } from '../components/footer/footerMain';
|
||||||
|
import { ShowProductItem } from '../components/product/productItem';
|
||||||
|
|
||||||
|
import EditScreenInfo from '../components/EditScreenInfo';
|
||||||
|
import { Text, View, } from '../components/Themed';
|
||||||
|
import useColorScheme from '../hooks/useColorScheme';
|
||||||
|
import TabOneScreen from './TabOneScreen';
|
||||||
|
|
||||||
|
export default function TabTwoScreen() {
|
||||||
|
|
||||||
|
const [showFilter, setFilter] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container}>
|
||||||
|
<ScrollView>
|
||||||
|
<View style={styles.brecrumb}>
|
||||||
|
<Text style={styles.brecrumbText}>Trang chủ</Text>
|
||||||
|
<FontAwesome style={styles.brecrumbIcon} name="angle-right" />
|
||||||
|
<Text style={styles.brecrumbTextLast}>Laptop, Máy Tính Xách Tay</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.listCategoryChild}>
|
||||||
|
<TouchableOpacity style={styles.listCategoryChildItem} onPress={() => Alert.alert('danh muc sp')}>
|
||||||
|
<Text style={styles.listCategoryChildName}>Laptop Asus</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.listCategoryChildItem} onPress={() => Alert.alert('danh muc sp')}>
|
||||||
|
<Text style={styles.listCategoryChildName}>Laptop Dell</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.listCategoryChildItem} onPress={() => Alert.alert('danh muc sp')}>
|
||||||
|
<Text style={styles.listCategoryChildName}>Laptop HP</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.listCategoryChildItem} onPress={() => Alert.alert('danh muc sp')}>
|
||||||
|
<Text style={styles.listCategoryChildName}>Laptop Lenovo</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.listCategoryChildItem} onPress={() => Alert.alert('danh muc sp')}>
|
||||||
|
<Text style={styles.listCategoryChildName}>Laptop Acer</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.listCategoryChildItem} onPress={() => Alert.alert('danh muc sp')}>
|
||||||
|
<Text style={styles.listCategoryChildName}>Laptop MSI</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.listFilter}>
|
||||||
|
<FilterBrand />
|
||||||
|
<FilterPrice />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ShowProductListCategory />
|
||||||
|
|
||||||
|
<Paging />
|
||||||
|
|
||||||
|
<ProductCategorySummary />
|
||||||
|
|
||||||
|
<PolicyFooter />
|
||||||
|
|
||||||
|
<Social />
|
||||||
|
|
||||||
|
<ShowroomList />
|
||||||
|
|
||||||
|
<FooterInfo />
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const winWidth = Dimensions.get('window').width; //full width
|
||||||
|
const winHeight = Dimensions.get('window').height; //full height
|
||||||
|
const halfWinWidth = winWidth / 2;
|
||||||
|
const ratio = winWidth / 930; //541 is actual image width
|
||||||
|
|
||||||
|
type ItemTyep = {id:string, title: string}
|
||||||
|
|
||||||
|
const FilterBrand = () => {
|
||||||
|
const [modalVisible, setModalVisible] = useState(false);
|
||||||
|
const dataBrandFilter = [
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: 'Acer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: 'Asus',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: 'HP',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: 'Dell',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: 'Apple',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
return (
|
||||||
|
<View style={styles.filterBox}>
|
||||||
|
<TouchableOpacity style={styles.filterBoxTitle} onPress={() => setModalVisible(true)}>
|
||||||
|
<Text style={styles.filterBoxTitleName}>Thứ tự sản phẩm</Text>
|
||||||
|
<FontAwesome style={styles.filterBoxTitleIcon} name="caret-down" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Modal visible={modalVisible} animationType="slide" transparent={true} onRequestClose={() => { setModalVisible(!modalVisible); }}>
|
||||||
|
<Pressable onPress={() => setModalVisible(!modalVisible)} style={styles.filterItemContent}>
|
||||||
|
<View style={styles.filterItemList}>
|
||||||
|
<View style={styles.filterItemListTitle}>
|
||||||
|
<Text style={styles.filterItemListTitleName}>Hãng sản xuất</Text>
|
||||||
|
<Pressable onPress={() => setModalVisible(!modalVisible)}>
|
||||||
|
<FontAwesome style={styles.filterItemListClose} name="times" />
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
<ScrollView>
|
||||||
|
{
|
||||||
|
dataBrandFilter.map((item , index) =>
|
||||||
|
<FilterItem key={index} name={item.name} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
</Pressable>
|
||||||
|
</Modal>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const FilterPrice = () => {
|
||||||
|
const [modalVisible, setModalVisible] = useState(false);
|
||||||
|
const dataPriceFilter = [
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: '1000000',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: '2000000',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: '3000000',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: '4000000',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: '5000000',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
return (
|
||||||
|
<View style={styles.filterBox}>
|
||||||
|
<TouchableOpacity style={styles.filterBoxTitle} onPress={() => setModalVisible(true)}>
|
||||||
|
<Text style={styles.filterBoxTitleName}>Khoảng giá</Text>
|
||||||
|
<FontAwesome style={styles.filterBoxTitleIcon} name="caret-down" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Modal visible={modalVisible} animationType="slide" transparent={true} onRequestClose={() => { setModalVisible(!modalVisible); }}>
|
||||||
|
<Pressable onPress={() => setModalVisible(!modalVisible)} style={styles.filterItemContent}>
|
||||||
|
<View style={styles.filterItemList}>
|
||||||
|
<View style={styles.filterItemListTitle}>
|
||||||
|
<Text style={styles.filterItemListTitleName}>Khoảng giá</Text>
|
||||||
|
<Pressable onPress={() => setModalVisible(!modalVisible)}>
|
||||||
|
<FontAwesome style={styles.filterItemListClose} name="times" />
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
<ScrollView>
|
||||||
|
{
|
||||||
|
dataPriceFilter.map((item , index) =>
|
||||||
|
<FilterItem key={index} name={item.name} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
</Pressable>
|
||||||
|
</Modal>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const FilterItem = (props: { name: string }) => {
|
||||||
|
const { name } = props;
|
||||||
|
return (
|
||||||
|
<Pressable style={styles.filterItem} onPress={() => Alert.alert('danh muc sp')}>
|
||||||
|
<Text style={styles.filterItemName}>{name}</Text>
|
||||||
|
</Pressable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ShowProductListCategory = () => {
|
||||||
|
|
||||||
|
const itemProductStyle = {
|
||||||
|
width: halfWinWidth,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: '#e8e8e8',
|
||||||
|
borderRightWidth: 1,
|
||||||
|
borderRightColor: '#e8e8e8',
|
||||||
|
}
|
||||||
|
const productData = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
productName: 'Laptop LG Gram 14ZD90N-V.AX55A5 (i5 1035G7/8GB RAM/512GBSSD/14.0 inch FHD/FP/Xám Bạc) (model 2020)',
|
||||||
|
productSKU: 'TESTSKU',
|
||||||
|
productImage: {
|
||||||
|
small: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
medium: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
large: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
original: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
},
|
||||||
|
price: 30000000,
|
||||||
|
marketPrice: 50000000,
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
productName: 'Laptop LG Gram 14ZD90N-V.AX55A5 (i5 1035G7/8GB RAM/512GBSSD/14.0 inch FHD/FP/Xám Bạc) (model 2020)',
|
||||||
|
productSKU: 'TESTSKU',
|
||||||
|
productImage: {
|
||||||
|
small: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
medium: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
large: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
original: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
},
|
||||||
|
price: 25000000,
|
||||||
|
marketPrice: 50000000,
|
||||||
|
quantity: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
productName: 'Laptop LG Gram 14ZD90N-V.AX55A5 (i5 1035G7/8GB RAM/512GBSSD/14.0 inch FHD/FP/Xám Bạc) (model 2020)',
|
||||||
|
productSKU: 'TESTSKU',
|
||||||
|
productImage: {
|
||||||
|
small: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
medium: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
large: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
original: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
},
|
||||||
|
price: 35000000,
|
||||||
|
marketPrice: 50000000,
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
productName: 'Laptop LG Gram 14ZD90N-V.AX55A5 (i5 1035G7/8GB RAM/512GBSSD/14.0 inch FHD/FP/Xám Bạc) (model 2020)',
|
||||||
|
productSKU: 'TESTSKU',
|
||||||
|
productImage: {
|
||||||
|
small: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
medium: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
large: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
original: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
},
|
||||||
|
price: 40000000,
|
||||||
|
marketPrice: 50000000,
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
productName: 'Laptop LG Gram 14ZD90N-V.AX55A5 (i5 1035G7/8GB RAM/512GBSSD/14.0 inch FHD/FP/Xám Bạc) (model 2020)',
|
||||||
|
productSKU: 'TESTSKU',
|
||||||
|
productImage: {
|
||||||
|
small: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
medium: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
large: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
original: 'https://hanoicomputercdn.com/media/product/120_52019_14zd90n_v_ax55a5.png',
|
||||||
|
},
|
||||||
|
price: 30000000,
|
||||||
|
marketPrice: 50000000,
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.boxProductCategory}>
|
||||||
|
<View style={styles.listProductCategory}>
|
||||||
|
{
|
||||||
|
productData.map(item => <ShowProductItem key={item.id} id={item.id} productName={item.productName}
|
||||||
|
productSKU={item.productSKU} productImage={item.productImage} price={item.price} marketPrice={item.marketPrice} quantity={item.quantity} privateStyle={itemProductStyle}
|
||||||
|
/>)
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const Paging = () => {
|
||||||
|
|
||||||
|
const pagingData = [
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: 1,
|
||||||
|
isCurrent: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: 2,
|
||||||
|
isCurrent: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: 3,
|
||||||
|
isCurrent: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: 4,
|
||||||
|
isCurrent: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: '/',
|
||||||
|
name: 5,
|
||||||
|
isCurrent: 0,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.boxPaging}>
|
||||||
|
<View style={styles.boxPagingList}>
|
||||||
|
{
|
||||||
|
pagingData.map((item, index) =>
|
||||||
|
<Pressable key={index} style={item.isCurrent == 1 ? styles.boxPagingItemCurrent : styles.boxPagingItem} onPress={() => Alert.alert('page')}>
|
||||||
|
<Text style={item.isCurrent == 1 ? styles.boxPagingItemCurrentText : styles.boxPagingItemText}>{item.name}</Text>
|
||||||
|
</Pressable>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProductCategorySummary = () => {
|
||||||
|
return(
|
||||||
|
<View style={styles.boxProductCategorySummary}>
|
||||||
|
<Text>NHỮNG ĐIỀU CẦN LƯU Ý KHI CHỌN MUA LAPTOP</Text>
|
||||||
|
<Text>Để có thể sở hữu được một sản phẩm chất lượng và ưng ý nhất thì bạn cần xem xét các yếu tố như sau khi mua laptop:</Text>
|
||||||
|
<Text>Tốt nhất là bạn nên lựa chọn những laptop có thương hiệu nổi tiếng. Điều này phần nào đã chứng minh được chất lượng của laptop. Những thương hiệu được nhiều người ưa chuộng trong thời gian dài thì chắc chắn là sản phẩm có các ưu điểm nổi bật, mang đến nhiều giá trị tối ưu cho người dùng khi sử dụng sản phẩm. Khi đã chọn các thương hiệu nổi tiếng thì hàng chính hãng cũng là điều bạn nên đặc biệt quan tâm bởi vì hàng giả, hàng nhái hiện nay trên thị trường có rất nhiều</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
brecrumb: {
|
||||||
|
display: 'flex',
|
||||||
|
width: winWidth,
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
flexDirection: 'row',
|
||||||
|
height: 18,
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: 10,
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
brecrumbText: {
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#222',
|
||||||
|
},
|
||||||
|
brecrumbTextLast: {
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#b7b7b7',
|
||||||
|
},
|
||||||
|
brecrumbIcon: {
|
||||||
|
fontSize: 13,
|
||||||
|
color: '#222',
|
||||||
|
marginLeft: 6,
|
||||||
|
marginRight: 6
|
||||||
|
},
|
||||||
|
listCategoryChild: {
|
||||||
|
width: winWidth,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
},
|
||||||
|
listCategoryChildItem: {
|
||||||
|
width: halfWinWidth - 15,
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
height: 36,
|
||||||
|
backgroundColor: '#243a76',
|
||||||
|
marginBottom: 10,
|
||||||
|
borderRadius: 5,
|
||||||
|
},
|
||||||
|
listCategoryChildName: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
listFilter: {
|
||||||
|
width: winWidth,
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
},
|
||||||
|
filterBox: {
|
||||||
|
width: halfWinWidth - 15,
|
||||||
|
position: 'relative',
|
||||||
|
marginBottom: 10,
|
||||||
|
zIndex: -1,
|
||||||
|
},
|
||||||
|
filterBox1: {
|
||||||
|
zIndex: 1,
|
||||||
|
},
|
||||||
|
filterBoxTitle: {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
height: 36,
|
||||||
|
backgroundColor: '#dcdcdc',
|
||||||
|
borderRadius: 5,
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
zIndex: 1,
|
||||||
|
position: 'relative',
|
||||||
|
},
|
||||||
|
filterItemListTitleName: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
color: '#222',
|
||||||
|
},
|
||||||
|
filterItemListClose: {
|
||||||
|
fontSize: 16,
|
||||||
|
},
|
||||||
|
filterBoxTitleName: {
|
||||||
|
},
|
||||||
|
filterBoxTitleIcon: {},
|
||||||
|
filterItemContent: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||||
|
position: 'relative',
|
||||||
|
zIndex: 1,
|
||||||
|
},
|
||||||
|
filterItemList: {
|
||||||
|
width: winWidth - 30,
|
||||||
|
maxWidth: 300,
|
||||||
|
height: 450,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
shadowColor: "#000",
|
||||||
|
shadowOffset: {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
},
|
||||||
|
shadowOpacity: 2.22,
|
||||||
|
shadowRadius: 2.22,
|
||||||
|
elevation: 3,
|
||||||
|
borderRadius: 5,
|
||||||
|
overflow: 'hidden',
|
||||||
|
position: 'relative',
|
||||||
|
zIndex: 2,
|
||||||
|
},
|
||||||
|
filterItemListTitle: {
|
||||||
|
height: 40,
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: '#e1e1e1',
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
filterItem: {
|
||||||
|
width: '100%',
|
||||||
|
height: 30,
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
},
|
||||||
|
filterItemName: {},
|
||||||
|
boxProductCategory: {
|
||||||
|
width: winWidth,
|
||||||
|
},
|
||||||
|
listProductCategory: {
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
marginTop: 10,
|
||||||
|
borderTopColor: '#e8e8e8',
|
||||||
|
borderTopWidth: 1,
|
||||||
|
},
|
||||||
|
boxPaging: {
|
||||||
|
width: winWidth,
|
||||||
|
marginTop: 20,
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
boxPagingList: {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
},
|
||||||
|
boxPagingItemCurrent: {
|
||||||
|
paddingHorizontal: 8,
|
||||||
|
paddingVertical: 5,
|
||||||
|
lineHeight: 16,
|
||||||
|
marginHorizontal: 2,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#bbb',
|
||||||
|
borderRadius: 3,
|
||||||
|
backgroundColor: '#243a76'
|
||||||
|
},
|
||||||
|
boxPagingItem: {
|
||||||
|
paddingHorizontal: 8,
|
||||||
|
paddingVertical: 5,
|
||||||
|
lineHeight: 16,
|
||||||
|
marginHorizontal: 2,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#bbb',
|
||||||
|
borderRadius: 3,
|
||||||
|
},
|
||||||
|
boxPagingItemCurrentText: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
boxPagingItemText: {
|
||||||
|
color: '#333',
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
boxProductCategorySummary: {
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
});
|
||||||
12
screens/test.tsx
Normal file
12
screens/test.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Text, View } from 'react-native'
|
||||||
|
import { NavigationContainer } from '@react-navigation/native';
|
||||||
|
import { createStackNavigator } from '@react-navigation/stack';
|
||||||
|
|
||||||
|
function HomeScreen() {
|
||||||
|
return (
|
||||||
|
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }} >
|
||||||
|
<Text> Home Screen </Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
12
tsconfig.json
Normal file
12
tsconfig.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"jsx": "react-native",
|
||||||
|
"lib": ["dom", "esnext"],
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"noEmit": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"strict": true
|
||||||
|
}
|
||||||
|
}
|
||||||
17
types.tsx
Normal file
17
types.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
export type RootStackParamList = {
|
||||||
|
Root: undefined;
|
||||||
|
NotFound: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BottomTabParamList = {
|
||||||
|
TabOne: undefined;
|
||||||
|
TabTwo: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TabOneParamList = {
|
||||||
|
TabOneScreen: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TabTwoParamList = {
|
||||||
|
TabTwoScreen: undefined;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user