├── .prettierrc ├── .vscode └── settings.json ├── assets ├── icon.png ├── favicon.png ├── splash.png ├── icons │ ├── ring.png │ ├── Giftbox.png │ ├── apple.png │ ├── paypal.png │ ├── computer.png │ ├── mans-clothe.png │ ├── masterCard.png │ ├── three-dots.png │ └── womans-clothes.png ├── adaptive-icon.png ├── font │ ├── Inter-Bold.ttf │ ├── Inter-Light.ttf │ ├── Inter-Medium.ttf │ ├── Inter-Regular.ttf │ ├── Poppins-Bold.ttf │ ├── Poppins-Light.ttf │ ├── Inter-SemiBold.ttf │ ├── Poppins-Medium.ttf │ ├── Poppins-Regular.ttf │ └── Poppins-SemiBold.ttf └── images │ └── empty-cart.png ├── babel.config.js ├── .expo-shared └── assets.json ├── .gitignore ├── README.md ├── store ├── index.js ├── reducers │ ├── index.js │ ├── alert.js │ ├── product.js │ └── cart.js └── actions │ ├── types.js │ └── cartActions.js ├── utilities └── tag.js ├── components ├── UI │ ├── Text.js │ ├── IconButton.js │ ├── View.js │ ├── Button.js │ ├── Alert.js │ └── CategoryButton.js ├── Block │ ├── Categories.js │ ├── EmptyCart.js │ ├── PromocodeInput.js │ ├── PaymentHeader.js │ ├── CartHeader.js │ ├── Header.js │ ├── Offer.js │ ├── PaymentCard.js │ ├── HorizontalProductView.js │ ├── PaymentMethods.js │ ├── ProductInfo.js │ ├── ProductCard.js │ └── CartProductCard.js └── Section │ └── PaymentModel.js ├── Navigator ├── CartNavigator.js ├── ProductNavigator.js └── index.js ├── screens ├── Profile.js ├── Category.js ├── Products.js ├── ProductDetail.js └── Cart.js ├── constants └── COLORS.js ├── app.json ├── App.js ├── package.json └── dummy_data └── products.js /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": ["Ionicons"] 3 | } 4 | -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/icon.png -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/favicon.png -------------------------------------------------------------------------------- /assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/splash.png -------------------------------------------------------------------------------- /assets/icons/ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/icons/ring.png -------------------------------------------------------------------------------- /assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/adaptive-icon.png -------------------------------------------------------------------------------- /assets/icons/Giftbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/icons/Giftbox.png -------------------------------------------------------------------------------- /assets/icons/apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/icons/apple.png -------------------------------------------------------------------------------- /assets/icons/paypal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/icons/paypal.png -------------------------------------------------------------------------------- /assets/font/Inter-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/font/Inter-Bold.ttf -------------------------------------------------------------------------------- /assets/icons/computer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/icons/computer.png -------------------------------------------------------------------------------- /assets/font/Inter-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/font/Inter-Light.ttf -------------------------------------------------------------------------------- /assets/font/Inter-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/font/Inter-Medium.ttf -------------------------------------------------------------------------------- /assets/font/Inter-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/font/Inter-Regular.ttf -------------------------------------------------------------------------------- /assets/font/Poppins-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/font/Poppins-Bold.ttf -------------------------------------------------------------------------------- /assets/font/Poppins-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/font/Poppins-Light.ttf -------------------------------------------------------------------------------- /assets/icons/mans-clothe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/icons/mans-clothe.png -------------------------------------------------------------------------------- /assets/icons/masterCard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/icons/masterCard.png -------------------------------------------------------------------------------- /assets/icons/three-dots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/icons/three-dots.png -------------------------------------------------------------------------------- /assets/images/empty-cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/images/empty-cart.png -------------------------------------------------------------------------------- /assets/font/Inter-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/font/Inter-SemiBold.ttf -------------------------------------------------------------------------------- /assets/font/Poppins-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/font/Poppins-Medium.ttf -------------------------------------------------------------------------------- /assets/font/Poppins-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/font/Poppins-Regular.ttf -------------------------------------------------------------------------------- /assets/icons/womans-clothes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/icons/womans-clothes.png -------------------------------------------------------------------------------- /assets/font/Poppins-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rish7223/NativeShop/HEAD/assets/font/Poppins-SemiBold.ttf -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, 3 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | npm-debug.* 4 | *.jks 5 | *.p8 6 | *.p12 7 | *.key 8 | *.mobileprovision 9 | *.orig.* 10 | web-build/ 11 | 12 | # macOS 13 | .DS_Store 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NativeShop 2 | 3 | A full fledged E-Commerce app using React native & Expo 4 | 5 | ## setup 6 | 7 | - clone the repo `git clone` 8 | - install all dependencies `npm install` 9 | - run the app `expo start` 10 | -------------------------------------------------------------------------------- /store/index.js: -------------------------------------------------------------------------------- 1 | import { createStore } from 'redux'; 2 | import rootReducer from './reducers'; 3 | import { composeWithDevTools } from 'redux-devtools-extension'; 4 | 5 | const store = createStore(rootReducer, composeWithDevTools()); 6 | 7 | export default store; 8 | -------------------------------------------------------------------------------- /utilities/tag.js: -------------------------------------------------------------------------------- 1 | export const getTag = (name) => { 2 | switch (name) { 3 | case `men's clothing`: 4 | return 'For Men'; 5 | case `women's clothing`: 6 | return 'For Women'; 7 | default: 8 | return name; 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /store/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import product from '../reducers/product'; 3 | import cart from './cart'; 4 | import alert from './alert'; 5 | 6 | export default combineReducers({ 7 | alert, 8 | product, 9 | cart, 10 | }); 11 | -------------------------------------------------------------------------------- /components/UI/Text.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, Text } from 'react-native'; 3 | 4 | const UiText = ({ children, style }) => { 5 | return {children}; 6 | }; 7 | 8 | const Styles = StyleSheet.create({ 9 | text: { 10 | fontFamily: 'Nunito', 11 | }, 12 | }); 13 | 14 | export default UiText; 15 | -------------------------------------------------------------------------------- /Navigator/CartNavigator.js: -------------------------------------------------------------------------------- 1 | import { createStackNavigator } from 'react-navigation-stack'; 2 | import Cart from '../screens/Cart'; 3 | import ProductDetail from '../screens/ProductDetail'; 4 | 5 | export const CartStackNavigator = createStackNavigator( 6 | { 7 | Cart: { 8 | screen: Cart, 9 | }, 10 | CartProductDetail: { 11 | screen: ProductDetail, 12 | }, 13 | }, 14 | { 15 | headerMode: 'none', 16 | } 17 | ); 18 | -------------------------------------------------------------------------------- /store/actions/types.js: -------------------------------------------------------------------------------- 1 | export const SET_ALERT = 'SET_ALERT'; 2 | export const REMOVE_ALERT = 'REMOVE_ALERT'; 3 | 4 | export const GET_ALL_PRODUCTS = 'GET_ALL_PRODUCTS'; 5 | export const GET_PRODUCTS_BY_CATEGORY = 'GET_PRODUCTS_BY_CATEGORY'; 6 | export const GET_PRODUCT_DETAIL = 'GET_PRODUCT_DETAIL'; 7 | 8 | export const GET_CART_ITEMS = 'GET_CART_ITEMS'; 9 | export const ADD_ITEM_CART = 'ADD_ITEM_CART'; 10 | export const REMOVE_ITEM_CART = 'REMOVE_ITEM_CART'; 11 | -------------------------------------------------------------------------------- /screens/Profile.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import UiText from '../components/UI/Text'; 4 | 5 | const Profile = () => { 6 | return ( 7 | 8 | User Profile Page! 9 | 10 | ); 11 | }; 12 | 13 | const styles = StyleSheet.create({ 14 | screen: { 15 | flex: 1, 16 | alignItems: 'center', 17 | justifyContent: 'center', 18 | }, 19 | }); 20 | 21 | export default Profile; 22 | -------------------------------------------------------------------------------- /screens/Category.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet } from 'react-native'; 3 | import UiText from '../components/UI/Text'; 4 | import UiView from '../components/UI/View'; 5 | 6 | const Category = ({ navigation }) => { 7 | return ( 8 | 9 | Category screen 10 | 11 | ); 12 | }; 13 | 14 | const Styles = StyleSheet.create({ 15 | screen: { 16 | position: 'relative', 17 | }, 18 | }); 19 | 20 | export default Category; 21 | -------------------------------------------------------------------------------- /store/reducers/alert.js: -------------------------------------------------------------------------------- 1 | import { SET_ALERT, REMOVE_ALERT } from '../actions/types'; 2 | 3 | const initialState = { 4 | message: '', 5 | type: null, 6 | }; 7 | 8 | const alert = (state = initialState, action) => { 9 | const { type, payload } = action; 10 | switch (type) { 11 | case SET_ALERT: 12 | return { message: payload.message, type: payload.type }; 13 | case REMOVE_ALERT: 14 | return { message: '', type: null }; 15 | default: 16 | return state; 17 | } 18 | }; 19 | 20 | export default alert; 21 | -------------------------------------------------------------------------------- /store/reducers/product.js: -------------------------------------------------------------------------------- 1 | import { GET_PRODUCTS_BY_CATEGORY, GET_PRODUCT_DETAIL } from '../actions/types'; 2 | import PRODUCTS, { PopularProducts } from '../../dummy_data/products'; 3 | const initialState = { 4 | products: PRODUCTS, 5 | categoryProducts: [], 6 | popularProducts: PopularProducts, 7 | loading: false, 8 | }; 9 | 10 | const productReducer = (state = initialState, actions) => { 11 | const { type, payload } = actions; 12 | switch (type) { 13 | default: 14 | return state; 15 | } 16 | }; 17 | 18 | export default productReducer; 19 | -------------------------------------------------------------------------------- /constants/COLORS.js: -------------------------------------------------------------------------------- 1 | export default { 2 | primaryColor: '#262E34', 3 | textColorLight: '#9AA1A7', 4 | black: '#000000', 5 | 6 | grey: '#787878', 7 | borderGrey: '#e5e5e5', 8 | lightGrayColor: '#F6F6F6', 9 | bgColor: '#FDFDFD', 10 | white: '#ffffff', 11 | whiteTrans: '#ffffffaa', 12 | 13 | red: '#fe2367', 14 | 15 | blue: '#9492EB', 16 | blueLight: '#EEF6FF', 17 | orange: '#FA8454', 18 | orangeLight: '#FFF7F3', 19 | pink: '#ED7584', 20 | pinkLight: '#FEE4E8', 21 | 22 | cardLinear1: '#343434', 23 | cardLinear2: '#4f4f4f', 24 | }; 25 | -------------------------------------------------------------------------------- /Navigator/ProductNavigator.js: -------------------------------------------------------------------------------- 1 | import { createStackNavigator } from 'react-navigation-stack'; 2 | import Category from '../screens/Category'; 3 | import ProductDetail from '../screens/ProductDetail'; 4 | import Products from '../screens/Products'; 5 | 6 | export const ProductStackNavigator = createStackNavigator( 7 | { 8 | Products: { 9 | screen: Products, 10 | }, 11 | ProductDetail: { 12 | screen: ProductDetail, 13 | }, 14 | Category: { 15 | screen: Category, 16 | }, 17 | }, 18 | { 19 | headerMode: 'none', 20 | } 21 | ); 22 | -------------------------------------------------------------------------------- /components/UI/IconButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Pressable, StyleSheet } from 'react-native'; 3 | 4 | const UiIconButton = ({ children, style, onPress }) => { 5 | return ( 6 | 11 | {children} 12 | 13 | ); 14 | }; 15 | 16 | const Styles = StyleSheet.create({ 17 | button: { 18 | alignItems: 'center', 19 | justifyContent: 'center', 20 | overflow: 'hidden', 21 | }, 22 | }); 23 | 24 | export default UiIconButton; 25 | -------------------------------------------------------------------------------- /components/UI/View.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ScrollView, StyleSheet, View } from 'react-native'; 3 | import COLORS from '../../constants/COLORS'; 4 | 5 | const UiView = ({ children, style }) => { 6 | return ( 7 | 8 | 9 | {children} 10 | 11 | 12 | ); 13 | }; 14 | 15 | const Styles = StyleSheet.create({ 16 | screen: { 17 | backgroundColor: COLORS.bgColor, 18 | position: 'relative', 19 | flex: 1, 20 | }, 21 | container: { 22 | width: '100%', 23 | }, 24 | }); 25 | 26 | export default UiView; 27 | -------------------------------------------------------------------------------- /store/reducers/cart.js: -------------------------------------------------------------------------------- 1 | import products from '../../dummy_data/products'; 2 | import { 3 | GET_CART_ITEMS, 4 | ADD_ITEM_CART, 5 | REMOVE_ITEM_CART, 6 | } from '../actions/types'; 7 | 8 | const initialState = { 9 | items: [], 10 | loading: false, 11 | alert: null, 12 | }; 13 | 14 | const cart = (state = initialState, action) => { 15 | const { type, payload } = action; 16 | 17 | switch (type) { 18 | case GET_CART_ITEMS: 19 | return state; 20 | case ADD_ITEM_CART: 21 | return { ...state, items: [payload, ...state.items] }; 22 | case REMOVE_ITEM_CART: 23 | return { ...state, items: payload }; 24 | default: 25 | return state; 26 | } 27 | }; 28 | 29 | export default cart; 30 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "NativeShopApp", 4 | "slug": "NativeShopApp", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "splash": { 9 | "image": "./assets/splash.png", 10 | "resizeMode": "contain", 11 | "backgroundColor": "#ffffff" 12 | }, 13 | "updates": { 14 | "fallbackToCacheTimeout": 0 15 | }, 16 | "assetBundlePatterns": [ 17 | "**/*" 18 | ], 19 | "ios": { 20 | "supportsTablet": true 21 | }, 22 | "android": { 23 | "adaptiveIcon": { 24 | "foregroundImage": "./assets/adaptive-icon.png", 25 | "backgroundColor": "#FFFFFF" 26 | } 27 | }, 28 | "web": { 29 | "favicon": "./assets/favicon.png" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useFonts } from 'expo-font'; 3 | import AppLoading from 'expo-app-loading'; 4 | import Navigation from './Navigator'; 5 | import { Provider } from 'react-redux'; 6 | import store from './store'; 7 | // custom fonts 8 | const fontsData = { 9 | Nunito: require('./assets/font/Inter-Regular.ttf'), 10 | 'Nunito-light': require('./assets/font/Inter-Light.ttf'), 11 | 'Nunito-SemiBold': require('./assets/font/Inter-Medium.ttf'), 12 | 'Nunito-Bold': require('./assets/font/Inter-SemiBold.ttf'), 13 | }; 14 | 15 | export default function App() { 16 | const [loaded] = useFonts(fontsData); 17 | if (!loaded) { 18 | return ; 19 | } 20 | return ( 21 | 22 | 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /components/UI/Button.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Pressable, StyleSheet } from 'react-native'; 3 | import COLORS from '../../constants/COLORS'; 4 | import UiText from './Text'; 5 | 6 | const UiButton = ({ children, onPress, style, textStyle }) => { 7 | return ( 8 | 13 | {children} 14 | 15 | ); 16 | }; 17 | 18 | const Styles = StyleSheet.create({ 19 | button: { 20 | alignItems: 'center', 21 | justifyContent: 'center', 22 | }, 23 | text: { 24 | color: COLORS.primaryColor, 25 | fontFamily: 'Nunito-SemiBold', 26 | }, 27 | }); 28 | 29 | export default UiButton; 30 | -------------------------------------------------------------------------------- /components/UI/Alert.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import COLORS from '../../constants/COLORS'; 4 | import UiText from './Text'; 5 | import { useSelector } from 'react-redux'; 6 | 7 | const UiAlert = () => { 8 | const alert = useSelector((state) => state.alert); 9 | if (alert.message === '') { 10 | return null; 11 | } 12 | return ( 13 | 14 | {alert.message} 15 | 16 | ); 17 | }; 18 | 19 | const Styles = StyleSheet.create({ 20 | alert: { 21 | position: 'absolute', 22 | paddingHorizontal: 20, 23 | paddingVertical: 10, 24 | borderRadius: 30, 25 | backgroundColor: COLORS.primaryColor, 26 | alignItems: 'center', 27 | justifyContent: 'center', 28 | bottom: 10, 29 | alignSelf: 'center', 30 | elevation: 2, 31 | }, 32 | alertText: { 33 | fontFamily: 'Nunito-Bold', 34 | fontSize: 15, 35 | color: COLORS.white, 36 | }, 37 | }); 38 | 39 | export default UiAlert; 40 | -------------------------------------------------------------------------------- /store/actions/cartActions.js: -------------------------------------------------------------------------------- 1 | import { 2 | GET_CART_ITEMS, 3 | ADD_ITEM_CART, 4 | SET_ALERT, 5 | REMOVE_ALERT, 6 | REMOVE_ITEM_CART, 7 | } from './types'; 8 | import products from '../../dummy_data/products'; 9 | 10 | export const getCartItems = async (dispatch) => { 11 | try { 12 | const data = dispatch({ type: GET_CART_ITEMS }); 13 | } catch (error) { 14 | console.log(error); 15 | } 16 | }; 17 | 18 | export const addItemToCart = (productId, dispatch, isAlready) => { 19 | const product = products.find((item) => item.id === productId); 20 | if (!isAlready) { 21 | dispatch({ type: ADD_ITEM_CART, payload: product }); 22 | dispatch({ 23 | type: SET_ALERT, 24 | payload: { message: 'Added to cart', type: 'success' }, 25 | }); 26 | } else { 27 | dispatch({ 28 | type: SET_ALERT, 29 | payload: { message: 'Already listed', type: 'success' }, 30 | }); 31 | } 32 | 33 | setTimeout(() => { 34 | dispatch({ 35 | type: REMOVE_ALERT, 36 | }); 37 | }, 3000); 38 | }; 39 | 40 | export const removeItemFromCart = (dispatch, productId, cartList) => { 41 | const newList = cartList.filter((item) => productId !== item.id); 42 | dispatch({ type: REMOVE_ITEM_CART, payload: newList }); 43 | }; 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "node_modules/expo/AppEntry.js", 3 | "scripts": { 4 | "start": "expo start", 5 | "android": "expo start --android", 6 | "ios": "expo start --ios", 7 | "web": "expo start --web", 8 | "eject": "expo eject" 9 | }, 10 | "dependencies": { 11 | "@types/react-native": "^0.64.12", 12 | "expo": "~42.0.1", 13 | "expo-app-loading": "^1.1.2", 14 | "expo-linear-gradient": "~9.2.0", 15 | "expo-status-bar": "~1.0.4", 16 | "react": "16.13.1", 17 | "react-dom": "16.13.1", 18 | "react-native": "https://github.com/expo/react-native/archive/sdk-42.0.0.tar.gz", 19 | "react-native-gesture-handler": "~1.10.2", 20 | "react-native-paper": "^4.9.2", 21 | "react-native-safe-area-context": "3.2.0", 22 | "react-native-screens": "~3.4.0", 23 | "react-native-web": "~0.13.12", 24 | "react-navigation": "^4.4.4", 25 | "react-navigation-drawer": "^2.7.1", 26 | "react-navigation-header-buttons": "6", 27 | "react-navigation-material-bottom-tabs": "^2.3.4", 28 | "react-navigation-stack": "^2.10.4", 29 | "react-navigation-tabs": "^2.11.1", 30 | "react-redux": "^7.2.4", 31 | "redux": "^4.1.0", 32 | "redux-devtools-extension": "^2.13.9" 33 | }, 34 | "devDependencies": { 35 | "@babel/core": "^7.9.0" 36 | }, 37 | "private": true 38 | } 39 | -------------------------------------------------------------------------------- /components/Block/Categories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ScrollView, StyleSheet, View } from 'react-native'; 3 | import { CATEGORIES } from '../../dummy_data/products'; 4 | import UiCategoryButton from '../UI/CategoryButton'; 5 | 6 | const CategoriesBlock = ({ navigation }) => { 7 | return ( 8 | 9 | 14 | {CATEGORIES.map((data) => ( 15 | 21 | navigation.navigate('Category', { 22 | categoryName: data, 23 | }) 24 | } 25 | /> 26 | ))} 27 | 28 | 29 | ); 30 | }; 31 | 32 | const Styles = StyleSheet.create({ 33 | content: { 34 | marginTop: 20, 35 | marginBottom: 10, 36 | }, 37 | button: { 38 | paddingHorizontal: 15, 39 | paddingVertical: 15, 40 | borderRadius: 10, 41 | marginHorizontal: 15, 42 | }, 43 | btnText: { 44 | fontSize: 17, 45 | }, 46 | }); 47 | 48 | export default CategoriesBlock; 49 | -------------------------------------------------------------------------------- /components/Block/EmptyCart.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ImageBackground, StyleSheet, View } from 'react-native'; 3 | import UiText from '../UI/Text'; 4 | 5 | const EmptyCart = () => { 6 | return ( 7 | 8 | 9 | 14 | 15 | 16 | Your cart is empty. 17 | Please add a few items. 18 | 19 | 20 | ); 21 | }; 22 | 23 | const Styles = StyleSheet.create({ 24 | emptyPage: { 25 | flex: 1, 26 | alignItems: 'center', 27 | justifyContent: 'center', 28 | }, 29 | illustration: { 30 | height: 200, 31 | width: 300, 32 | }, 33 | illustrationImage: { 34 | height: '100%', 35 | width: '100%', 36 | }, 37 | emptyTextBox: { 38 | marginTop: 20, 39 | }, 40 | emptyText: { 41 | fontFamily: 'Nunito-Bold', 42 | fontSize: 18, 43 | textAlign: 'center', 44 | lineHeight: 22, 45 | letterSpacing: 0.7, 46 | }, 47 | }); 48 | 49 | export default EmptyCart; 50 | -------------------------------------------------------------------------------- /components/Block/PromocodeInput.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | View, 4 | TextInput, 5 | StyleSheet, 6 | KeyboardAvoidingView, 7 | } from 'react-native'; 8 | import COLORS from '../../constants/COLORS'; 9 | import UiButton from '../UI/Button'; 10 | 11 | const PromocodeInputBlock = () => { 12 | return ( 13 | 14 | 15 | 16 | 17 | Apply 18 | 19 | 20 | 21 | ); 22 | }; 23 | 24 | const Styles = StyleSheet.create({ 25 | container: { 26 | backgroundColor: COLORS.lightGrayColor, 27 | flexDirection: 'row', 28 | alignItems: 'center', 29 | paddingHorizontal: 10, 30 | paddingVertical: 5, 31 | borderRadius: 15, 32 | marginTop: 10, 33 | }, 34 | input: { 35 | flex: 1, 36 | paddingHorizontal: 10, 37 | paddingVertical: 14, 38 | fontSize: 16, 39 | fontFamily: 'Nunito-SemiBold', 40 | }, 41 | button: { 42 | backgroundColor: COLORS.primaryColor, 43 | paddingHorizontal: 25, 44 | paddingVertical: 14, 45 | borderRadius: 15, 46 | }, 47 | btnText: { 48 | color: COLORS.white, 49 | fontFamily: 'Nunito-SemiBold', 50 | fontSize: 16, 51 | }, 52 | }); 53 | 54 | export default PromocodeInputBlock; 55 | -------------------------------------------------------------------------------- /Navigator/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs'; 3 | import { Ionicons } from '@expo/vector-icons'; 4 | import COLORS from '../constants/COLORS'; 5 | import { createAppContainer } from 'react-navigation'; 6 | import { ProductStackNavigator } from './ProductNavigator'; 7 | import Profile from '../screens/Profile'; 8 | import { CartStackNavigator } from './CartNavigator'; 9 | 10 | const tabScreensConfig = { 11 | Products: { 12 | screen: ProductStackNavigator, 13 | navigationOptions: { 14 | tabBarIcon: (tabInfo) => ( 15 | 16 | ), 17 | }, 18 | }, 19 | Cart: { 20 | screen: CartStackNavigator, 21 | navigationOptions: { 22 | tabBarIcon: (tabInfo) => ( 23 | 24 | ), 25 | }, 26 | }, 27 | Profile: { 28 | screen: Profile, 29 | navigationOptions: { 30 | tabBarIcon: (tabInfo) => ( 31 | 32 | ), 33 | }, 34 | }, 35 | }; 36 | 37 | const AppTabNavigation = createMaterialBottomTabNavigator(tabScreensConfig, { 38 | activeColor: COLORS.primaryColor, 39 | shifting: true, 40 | barStyle: { 41 | backgroundColor: '#fff', 42 | }, 43 | }); 44 | 45 | export default createAppContainer(AppTabNavigation); 46 | -------------------------------------------------------------------------------- /components/Block/PaymentHeader.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import UiIconButton from '../UI/IconButton'; 4 | import { AntDesign } from '@expo/vector-icons'; 5 | import UiText from '../UI/Text'; 6 | import COLORS from '../../constants/COLORS'; 7 | 8 | const PaymentHeaderBlock = ({ closeModel }) => { 9 | return ( 10 | 11 | 12 | { 14 | closeModel(false); 15 | }} 16 | > 17 | 18 | 19 | 20 | 21 | Payment 22 | 23 | 24 | 25 | ); 26 | }; 27 | 28 | const Styles = StyleSheet.create({ 29 | container: { 30 | paddingHorizontal: 15, 31 | paddingVertical: 15, 32 | flexDirection: 'row', 33 | alignItems: 'center', 34 | justifyContent: 'space-between', 35 | position: 'absolute', 36 | width: '100%', 37 | top: 5, 38 | zIndex: 30, 39 | }, 40 | 41 | headerText: { 42 | fontFamily: 'Nunito-Bold', 43 | fontSize: 20, 44 | color: COLORS.primaryColor, 45 | }, 46 | leftContent: { 47 | flexDirection: 'row', 48 | alignItems: 'center', 49 | justifyContent: 'center', 50 | }, 51 | }); 52 | 53 | export default PaymentHeaderBlock; 54 | -------------------------------------------------------------------------------- /components/Block/CartHeader.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import UiIconButton from '../UI/IconButton'; 4 | import { AntDesign } from '@expo/vector-icons'; 5 | import UiText from '../UI/Text'; 6 | import COLORS from '../../constants/COLORS'; 7 | 8 | const CartHeaderBlock = ({ navigation }) => { 9 | return ( 10 | 11 | 12 | { 14 | navigation.navigate('Products'); 15 | }} 16 | > 17 | 18 | 19 | 20 | 21 | Cart 22 | 23 | 24 | 25 | ); 26 | }; 27 | 28 | const Styles = StyleSheet.create({ 29 | container: { 30 | paddingHorizontal: 15, 31 | paddingVertical: 15, 32 | flexDirection: 'row', 33 | alignItems: 'center', 34 | justifyContent: 'space-between', 35 | position: 'absolute', 36 | width: '100%', 37 | top: 30, 38 | zIndex: 30, 39 | }, 40 | 41 | headerText: { 42 | fontFamily: 'Nunito-Bold', 43 | fontSize: 20, 44 | color: COLORS.primaryColor, 45 | }, 46 | leftContent: { 47 | flexDirection: 'row', 48 | alignItems: 'center', 49 | justifyContent: 'center', 50 | }, 51 | }); 52 | 53 | export default CartHeaderBlock; 54 | -------------------------------------------------------------------------------- /components/Block/Header.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { AntDesign } from '@expo/vector-icons'; 3 | import COLORS from '../../constants/COLORS'; 4 | import { StyleSheet, View } from 'react-native'; 5 | import UiIconButton from '../UI/IconButton'; 6 | 7 | const UiHeader = ({ navigation, onPress, isFav }) => { 8 | return ( 9 | 10 | 11 | navigation.goBack()}> 12 | 13 | 14 | {/* {title} */} 15 | 16 | 17 | 18 | 23 | 24 | 25 | 26 | ); 27 | }; 28 | 29 | const Styles = StyleSheet.create({ 30 | header: { 31 | paddingHorizontal: 15, 32 | paddingVertical: 15, 33 | flexDirection: 'row', 34 | alignItems: 'center', 35 | justifyContent: 'space-between', 36 | position: 'absolute', 37 | width: '100%', 38 | top: 30, 39 | zIndex: 10, 40 | }, 41 | leftContent: { 42 | flexDirection: 'row', 43 | alignItems: 'center', 44 | justifyContent: 'center', 45 | }, 46 | 47 | heading: { 48 | fontSize: 18, 49 | fontFamily: 'Nunito-SemiBold', 50 | color: COLORS.primaryColor, 51 | marginLeft: 20, 52 | }, 53 | }); 54 | export default UiHeader; 55 | -------------------------------------------------------------------------------- /components/Block/Offer.js: -------------------------------------------------------------------------------- 1 | import { LinearGradient } from 'expo-linear-gradient'; 2 | import React from 'react'; 3 | import { Image, StyleSheet, View } from 'react-native'; 4 | import COLORS from '../../constants/COLORS'; 5 | import UiText from '../UI/Text'; 6 | 7 | const OfferBlock = () => { 8 | return ( 9 | 10 | 15 | Get 10% off 16 | 17 | Use code RISH10 at checkout. 18 | 19 | 23 | 24 | 25 | ); 26 | }; 27 | 28 | const styles = StyleSheet.create({ 29 | offerBox: { 30 | marginHorizontal: 15, 31 | overflow: 'hidden', 32 | marginTop: 20, 33 | marginBottom: 10, 34 | borderRadius: 10, 35 | }, 36 | offer: { 37 | paddingHorizontal: 15, 38 | height: 70, 39 | alignItems: 'flex-end', 40 | justifyContent: 'center', 41 | position: 'relative', 42 | }, 43 | offerText: { 44 | color: COLORS.white, 45 | fontFamily: 'Nunito-Bold', 46 | fontSize: 20, 47 | }, 48 | offerCodeText: { 49 | fontFamily: 'Nunito-SemiBold', 50 | fontSize: 15, 51 | color: COLORS.white, 52 | }, 53 | giftBox: { 54 | position: 'absolute', 55 | maxHeight: 80, 56 | maxWidth: 80, 57 | left: 0, 58 | }, 59 | }); 60 | 61 | export default OfferBlock; 62 | -------------------------------------------------------------------------------- /components/Block/PaymentCard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { LinearGradient } from 'expo-linear-gradient'; 3 | import COLORS from '../../constants/COLORS'; 4 | import { Image, StyleSheet, View } from 'react-native'; 5 | import UiText from '../UI/Text'; 6 | const PaymentCardBlock = () => { 7 | return ( 8 | 13 | Credit Card 14 | 15 | 16 | 3541 4476535 00435 17 | Rishabh Tyagi 18 | 19 | 23 | 24 | ); 25 | }; 26 | 27 | const Styles = StyleSheet.create({ 28 | container: { 29 | paddingHorizontal: 20, 30 | paddingVertical: 20, 31 | minHeight: 150, 32 | borderRadius: 20, 33 | justifyContent: 'space-between', 34 | position: 'relative', 35 | }, 36 | title: { 37 | color: COLORS.white, 38 | fontFamily: 'Nunito-SemiBold', 39 | fontSize: 16, 40 | }, 41 | cardNo: { 42 | fontFamily: 'Nunito-SemiBold', 43 | fontSize: 20, 44 | color: COLORS.white, 45 | marginBottom: 6, 46 | }, 47 | cardUser: { 48 | fontFamily: 'Nunito', 49 | fontSize: 16, 50 | color: COLORS.white, 51 | }, 52 | masterCard: { 53 | position: 'absolute', 54 | height: 50, 55 | width: 50, 56 | bottom: 5, 57 | right: 20, 58 | }, 59 | }); 60 | 61 | export default PaymentCardBlock; 62 | -------------------------------------------------------------------------------- /screens/Products.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import CategoriesBlock from '../components/Block/Categories'; 4 | import HorizontalProductView from '../components/Block/HorizontalProductView'; 5 | import UiText from '../components/UI/Text'; 6 | import UiView from '../components/UI/View'; 7 | import COLORS from '../constants/COLORS'; 8 | import { useSelector } from 'react-redux'; 9 | import OfferBlock from '../components/Block/Offer'; 10 | import UiAlert from '../components/UI/Alert'; 11 | 12 | const Products = ({ navigation }) => { 13 | const popularProducts = useSelector((state) => state.product.popularProducts); 14 | 15 | return ( 16 | 17 | 18 | 19 | NativeShop 20 | A perfect shoppers stop 21 | 22 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | ); 34 | }; 35 | 36 | const styles = StyleSheet.create({ 37 | view: { 38 | position: 'relative', 39 | flex: 1, 40 | }, 41 | screen: { 42 | paddingTop: 50, 43 | }, 44 | head: { 45 | paddingHorizontal: 15, 46 | }, 47 | heading: { 48 | fontSize: 25, 49 | fontFamily: 'Nunito-Bold', 50 | color: COLORS.primaryColor, 51 | }, 52 | subHeading: { 53 | fontSize: 16, 54 | color: COLORS.textColorLight, 55 | }, 56 | empty: { 57 | minHeight: 60, 58 | }, 59 | }); 60 | 61 | export default Products; 62 | -------------------------------------------------------------------------------- /components/Block/HorizontalProductView.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Pressable, ScrollView, StyleSheet, View } from 'react-native'; 3 | import COLORS from '../../constants/COLORS'; 4 | import UiButton from '../UI/Button'; 5 | import UiText from '../UI/Text'; 6 | import ProductCardBlock from './ProductCard'; 7 | 8 | const HorizontalProductView = ({ data, headTitle, navigation }) => { 9 | return ( 10 | 11 | 12 | {headTitle} 13 | { 16 | console.log('See All Clicked'); 17 | }} 18 | > 19 | See All 20 | 21 | 22 | 27 | {data.map((product) => ( 28 | 31 | navigation.navigate('ProductDetail', { 32 | productData: product, 33 | }) 34 | } 35 | > 36 | 37 | 38 | ))} 39 | 40 | 41 | ); 42 | }; 43 | 44 | const Styles = StyleSheet.create({ 45 | container: { 46 | marginTop: 20, 47 | marginBottom: 10, 48 | }, 49 | head: { 50 | paddingHorizontal: 15, 51 | flexDirection: 'row', 52 | alignItems: 'center', 53 | justifyContent: 'space-between', 54 | }, 55 | heading: { 56 | fontSize: 16, 57 | fontFamily: 'Nunito-Bold', 58 | color: COLORS.primaryColor, 59 | }, 60 | dataSec: { 61 | marginTop: 20, 62 | }, 63 | }); 64 | 65 | export default HorizontalProductView; 66 | -------------------------------------------------------------------------------- /components/UI/CategoryButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Image, Pressable, StyleSheet } from 'react-native'; 3 | import COLORS from '../../constants/COLORS'; 4 | import UiText from './Text'; 5 | 6 | const UiCategoryButton = ({ data, style, onPress, textStyle }) => { 7 | const ProductIcon = ({ name }) => { 8 | switch (name) { 9 | case `men's clothing`: 10 | return ( 11 | 15 | ); 16 | case `women's clothing`: 17 | return ( 18 | 22 | ); 23 | case 'electronics': 24 | return ( 25 | 29 | ); 30 | default: 31 | return ( 32 | 36 | ); 37 | } 38 | }; 39 | return ( 40 | 41 | 42 | {data.name} 43 | 44 | ); 45 | }; 46 | 47 | const Styles = StyleSheet.create({ 48 | button: { 49 | flexDirection: 'row', 50 | alignItems: 'center', 51 | justifyContent: 'space-between', 52 | }, 53 | text: { 54 | color: COLORS.primaryColor, 55 | fontFamily: 'Nunito-SemiBold', 56 | marginLeft: 20, 57 | }, 58 | icons: { 59 | height: 20, 60 | width: 20, 61 | }, 62 | }); 63 | 64 | export default UiCategoryButton; 65 | -------------------------------------------------------------------------------- /components/Block/PaymentMethods.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ImageBackground, StyleSheet, View } from 'react-native'; 3 | import COLORS from '../../constants/COLORS'; 4 | import UiIconButton from '../UI/IconButton'; 5 | 6 | const PaymentMethodsBlock = () => { 7 | return ( 8 | 9 | 10 | 15 | 16 | 17 | 22 | 23 | 24 | 29 | 30 | 31 | 36 | 37 | 38 | ); 39 | }; 40 | const Styles = StyleSheet.create({ 41 | methods: { 42 | marginTop: 15, 43 | flexDirection: 'row', 44 | justifyContent: 'space-between', 45 | alignItems: 'flex-start', 46 | }, 47 | paymentIcons: { 48 | height: '100%', 49 | width: '100%', 50 | }, 51 | paymentMethodBtn: { 52 | height: 50, 53 | width: 70, 54 | position: 'relative', 55 | borderWidth: 2, 56 | borderColor: COLORS.borderGrey, 57 | borderRadius: 15, 58 | }, 59 | }); 60 | 61 | export default PaymentMethodsBlock; 62 | -------------------------------------------------------------------------------- /components/Section/PaymentModel.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Modal, ScrollView, StyleSheet, View } from 'react-native'; 3 | import COLORS from '../../constants/COLORS'; 4 | import PaymentCardBlock from '../Block/PaymentCard'; 5 | import PaymentHeaderBlock from '../Block/PaymentHeader'; 6 | import PaymentMethodsBlock from '../Block/PaymentMethods'; 7 | import PromocodeInputBlock from '../Block/PromocodeInput'; 8 | import UiButton from '../UI/Button'; 9 | import UiText from '../UI/Text'; 10 | 11 | const PaymentModelSection = ({ isVisible, setIsVisible, totalPrice }) => { 12 | return ( 13 | 14 | 15 | 16 | 17 | 18 | 19 | Choose Payment Methods 20 | 21 | 22 | 23 | Promo Code 24 | 25 | 26 | 27 | 28 | 29 | Total Payment 30 | ${totalPrice} 31 | 32 | 33 | Payment 34 | 35 | 36 | 37 | 38 | ); 39 | }; 40 | 41 | const Styles = StyleSheet.create({ 42 | container: { 43 | flex: 1, 44 | backgroundColor: COLORS.bgColor, 45 | }, 46 | content: { 47 | transform: [{ translateY: 70 }], 48 | paddingHorizontal: 15, 49 | }, 50 | paymentMethods: { 51 | marginTop: 25, 52 | }, 53 | headText: { 54 | fontSize: 17, 55 | fontFamily: 'Nunito-SemiBold', 56 | }, 57 | promo: { 58 | marginTop: 15, 59 | }, 60 | paymentAction: { 61 | position: 'absolute', 62 | width: '100%', 63 | paddingHorizontal: 15, 64 | bottom: 10, 65 | }, 66 | paymentInfo: { 67 | flexDirection: 'row', 68 | alignItems: 'center', 69 | justifyContent: 'space-between', 70 | }, 71 | paymentBtn: { 72 | backgroundColor: COLORS.primaryColor, 73 | paddingVertical: 15, 74 | borderRadius: 15, 75 | marginTop: 10, 76 | }, 77 | paymentBtnText: { 78 | fontFamily: 'Nunito-SemiBold', 79 | fontSize: 16, 80 | color: COLORS.white, 81 | }, 82 | }); 83 | 84 | export default PaymentModelSection; 85 | -------------------------------------------------------------------------------- /components/Block/ProductInfo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import COLORS from '../../constants/COLORS'; 4 | import { getTag } from '../../utilities/tag'; 5 | import UiButton from '../UI/Button'; 6 | import UiText from '../UI/Text'; 7 | 8 | const sizes = ['sm', 'md', 'lg', 'xl', 'xxl']; 9 | 10 | const ProductInfoBlock = ({ data }) => { 11 | return ( 12 | 13 | 14 | 15 | {data.title} 16 | {getTag(data.category)} 17 | 18 | ${data.price} 19 | 20 | {data.category !== 'electronics' && ( 21 | 22 | Size 23 | 24 | {sizes.map((data) => ( 25 | 30 | {data} 31 | 32 | ))} 33 | 34 | 35 | )} 36 | 37 | Description 38 | {data.description} 39 | 40 | 41 | ); 42 | }; 43 | 44 | const Styles = StyleSheet.create({ 45 | container: {}, 46 | productInfo: { 47 | flexDirection: 'row', 48 | alignItems: 'center', 49 | justifyContent: 'space-between', 50 | }, 51 | 52 | title: { 53 | fontSize: 18, 54 | fontFamily: 'Nunito-Bold', 55 | color: COLORS.primaryColor, 56 | }, 57 | 58 | tag: { 59 | marginTop: 0, 60 | fontSize: 15, 61 | fontFamily: 'Nunito-SemiBold', 62 | color: COLORS.textColorLight, 63 | }, 64 | 65 | price: { 66 | fontSize: 24, 67 | fontFamily: 'Nunito-Bold', 68 | color: COLORS.primaryColor, 69 | transform: [{ translateY: 15 }, { translateX: -3 }], 70 | }, 71 | size: { 72 | marginTop: 20, 73 | }, 74 | sizes: { 75 | flexDirection: 'row', 76 | alignItems: 'center', 77 | justifyContent: 'space-between', 78 | }, 79 | sizeBar: { 80 | marginTop: 10, 81 | height: 50, 82 | width: 50, 83 | alignItems: 'center', 84 | justifyContent: 'center', 85 | borderWidth: 2, 86 | borderColor: COLORS.textColorLight, 87 | borderRadius: 10, 88 | }, 89 | sizeBarText: { 90 | fontFamily: 'Nunito-SemiBold', 91 | fontSize: 17, 92 | }, 93 | description: { 94 | marginVertical: 20, 95 | }, 96 | head: { 97 | fontSize: 17, 98 | fontFamily: 'Nunito-Bold', 99 | color: COLORS.primaryColor, 100 | }, 101 | descriptionText: { 102 | marginTop: 10, 103 | fontSize: 15, 104 | fontFamily: 'Nunito-SemiBold', 105 | color: COLORS.textColorLight, 106 | letterSpacing: 0.2, 107 | }, 108 | }); 109 | 110 | export default ProductInfoBlock; 111 | -------------------------------------------------------------------------------- /screens/ProductDetail.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { ImageBackground, Pressable, StyleSheet, View } from 'react-native'; 3 | import { Feather } from '@expo/vector-icons'; 4 | import UiHeader from '../components/Block/Header'; 5 | import COLORS from '../constants/COLORS'; 6 | import UiView from '../components/UI/View'; 7 | import ProductInfoBlock from '../components/Block/ProductInfo'; 8 | import UiAlert from '../components/UI/Alert'; 9 | import { useDispatch, useSelector } from 'react-redux'; 10 | import { addItemToCart } from '../store/actions/cartActions'; 11 | import UiIconButton from '../components/UI/IconButton'; 12 | 13 | const ProductDetail = ({ navigation }) => { 14 | const [isFavItem, setIsFavItem] = useState(false); 15 | const productData = navigation.getParam('productData'); 16 | const cartItems = useSelector((state) => state.cart.items); 17 | const dispatch = useDispatch(); 18 | 19 | function toggleFavHandler() { 20 | setIsFavItem(!isFavItem); 21 | } 22 | return ( 23 | 24 | 29 | 30 | 37 | 38 | 39 | 40 | 41 | 42 | { 45 | const isAlready = cartItems.find( 46 | (item) => item.id === productData.id 47 | ); 48 | addItemToCart(productData.id, dispatch, isAlready); 49 | }} 50 | > 51 | 52 | 53 | 54 | 55 | 56 | ); 57 | }; 58 | 59 | const Styles = StyleSheet.create({ 60 | screen: { 61 | flex: 1, 62 | position: 'relative', 63 | backgroundColor: COLORS.white, 64 | }, 65 | 66 | imageView: { 67 | flex: 1, 68 | paddingVertical: 40, 69 | }, 70 | productImage: { 71 | height: '100%', 72 | width: '100%', 73 | transform: [{ translateY: 30 }], 74 | }, 75 | infoView: { 76 | flex: 1, 77 | borderTopLeftRadius: 30, 78 | borderTopRightRadius: 30, 79 | backgroundColor: COLORS.bgColor, 80 | elevation: 40, 81 | paddingTop: 20, 82 | }, 83 | container: { 84 | paddingHorizontal: 15, 85 | }, 86 | 87 | addToCart: { 88 | position: 'absolute', 89 | flexDirection: 'row', 90 | alignItems: 'center', 91 | justifyContent: 'center', 92 | bottom: 10, 93 | right: 10, 94 | alignSelf: 'center', 95 | padding: 15, 96 | borderRadius: 50, 97 | elevation: 5, 98 | backgroundColor: COLORS.primaryColor, 99 | }, 100 | 101 | empty: { 102 | minHeight: 50, 103 | }, 104 | }); 105 | 106 | export default ProductDetail; 107 | -------------------------------------------------------------------------------- /components/Block/ProductCard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View, ImageBackground } from 'react-native'; 3 | import COLORS from '../../constants/COLORS'; 4 | import { getTag } from '../../utilities/tag'; 5 | import UiIconButton from '../UI/IconButton'; 6 | import UiText from '../UI/Text'; 7 | import { MaterialIcons } from '@expo/vector-icons'; 8 | import { useDispatch, useSelector } from 'react-redux'; 9 | import { addItemToCart } from '../../store/actions/cartActions'; 10 | 11 | const ProductCardBlock = ({ data }) => { 12 | const dispatch = useDispatch(); 13 | const cartItems = useSelector((state) => state.cart.items); 14 | return ( 15 | 16 | 17 | 24 | 25 | 26 | { 29 | const isAlready = cartItems.find((item) => item.id === data.id); 30 | addItemToCart(data.id, dispatch, isAlready); 31 | }} 32 | > 33 | 34 | 35 | {data.title} 36 | 37 | {getTag(data.category)} 38 | ${data.price} 39 | 40 | 41 | 42 | ); 43 | }; 44 | 45 | const Styles = StyleSheet.create({ 46 | container: { 47 | borderRadius: 20, 48 | height: 270, 49 | maxHeight: 270, 50 | minWidth: 230, 51 | maxWidth: 230, 52 | backgroundColor: COLORS.lightGrayColor, 53 | position: 'relative', 54 | padding: 10, 55 | marginHorizontal: 15, 56 | }, 57 | imageSec: { 58 | width: '100%', 59 | maxHeight: 170, 60 | height: '100%', 61 | borderRadius: 20, 62 | overflow: 'hidden', 63 | padding: 15, 64 | backgroundColor: COLORS.bgColor, 65 | }, 66 | 67 | productImage: { 68 | height: '100%', 69 | width: '100%', 70 | }, 71 | 72 | infoSec: { 73 | paddingTop: 30, 74 | paddingHorizontal: 10, 75 | position: 'relative', 76 | }, 77 | title: { 78 | fontFamily: 'Nunito-Bold', 79 | fontSize: 15, 80 | }, 81 | 82 | subInfo: { 83 | marginTop: 0, 84 | flexDirection: 'row', 85 | alignItems: 'center', 86 | justifyContent: 'space-between', 87 | }, 88 | 89 | tag: { 90 | fontSize: 14, 91 | color: COLORS.textColorLight, 92 | fontFamily: 'Nunito-SemiBold', 93 | }, 94 | price: { 95 | fontSize: 18, 96 | fontFamily: 'Nunito-Bold', 97 | color: COLORS.black, 98 | }, 99 | 100 | addToBag: { 101 | position: 'absolute', 102 | right: 20, 103 | top: -20, 104 | height: 40, 105 | width: 40, 106 | backgroundColor: COLORS.primaryColor, 107 | borderRadius: 20, 108 | elevation: 5, 109 | }, 110 | }); 111 | 112 | export default ProductCardBlock; 113 | -------------------------------------------------------------------------------- /screens/Cart.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { StyleSheet, View, ScrollView, ImageBackground } from 'react-native'; 3 | import CartHeaderBlock from '../components/Block/CartHeader'; 4 | import CartProductCard from '../components/Block/CartProductCard'; 5 | import { useSelector } from 'react-redux'; 6 | import UiButton from '../components/UI/Button'; 7 | import COLORS from '../constants/COLORS'; 8 | import UiText from '../components/UI/Text'; 9 | import { LinearGradient } from 'expo-linear-gradient'; 10 | import EmptyCart from '../components/Block/EmptyCart'; 11 | import PaymentModelSection from '../components/Section/PaymentModel'; 12 | 13 | const Cart = ({ navigation }) => { 14 | const cartItems = useSelector((state) => state.cart.items); 15 | const [totalPrice, setTotalPrice] = useState(0); 16 | const [isModelVisible, setModelVisible] = useState(false); 17 | useEffect(() => { 18 | let priceTotal = 0; 19 | cartItems.forEach((item) => { 20 | priceTotal += Number(item.price); 21 | }); 22 | setTotalPrice(Number(priceTotal).toFixed(2)); 23 | }, [cartItems]); 24 | return ( 25 | 26 | 32 | 33 | {cartItems.length > 0 ? ( 34 | <> 35 | 36 | 37 | {cartItems.map((productData) => ( 38 | 45 | ))} 46 | 47 | 48 | 49 | 53 | { 57 | setModelVisible(true); 58 | }} 59 | > 60 | Checkout 61 | 62 | Price: ${totalPrice} 63 | 64 | 65 | ) : ( 66 | 67 | )} 68 | 69 | ); 70 | }; 71 | 72 | const styles = StyleSheet.create({ 73 | view: { 74 | flex: 1, 75 | position: 'relative', 76 | backgroundColor: COLORS.bgColor, 77 | }, 78 | screen: { 79 | position: 'relative', 80 | }, 81 | list: { 82 | paddingHorizontal: 15, 83 | transform: [{ translateY: 90 }], 84 | }, 85 | emptyItem: { 86 | minHeight: 170, 87 | }, 88 | checkout: { 89 | position: 'absolute', 90 | bottom: 0, 91 | width: '100%', 92 | paddingHorizontal: 15, 93 | alignSelf: 'center', 94 | paddingVertical: 10, 95 | flexDirection: 'row', 96 | alignItems: 'center', 97 | }, 98 | checkoutBtn: { 99 | flex: 1, 100 | paddingHorizontal: 20, 101 | paddingVertical: 15, 102 | borderRadius: 10, 103 | backgroundColor: COLORS.primaryColor, 104 | marginRight: 10, 105 | elevation: 3, 106 | }, 107 | checkoutText: { 108 | fontFamily: 'Nunito-Bold', 109 | color: COLORS.white, 110 | fontSize: 15, 111 | }, 112 | checkoutPrice: { 113 | flex: 1, 114 | paddingHorizontal: 20, 115 | paddingVertical: 15, 116 | backgroundColor: COLORS.white, 117 | borderRadius: 10, 118 | fontFamily: 'Nunito-Bold', 119 | fontSize: 15, 120 | textAlign: 'center', 121 | elevation: 3, 122 | }, 123 | }); 124 | 125 | export default Cart; 126 | -------------------------------------------------------------------------------- /components/Block/CartProductCard.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { StyleSheet, View, ImageBackground, Pressable } from 'react-native'; 3 | import COLORS from '../../constants/COLORS'; 4 | import UiIconButton from '../UI/IconButton'; 5 | import UiText from '../UI/Text'; 6 | import { AntDesign, Feather } from '@expo/vector-icons'; 7 | import { useDispatch, useSelector } from 'react-redux'; 8 | import { removeItemFromCart } from '../../store/actions/cartActions'; 9 | 10 | const CartProductCard = ({ productData, navigation }) => { 11 | const { image, title, price, id } = productData; 12 | const [quantity, setQuantity] = useState(1); 13 | const [productPrice, setProductPrice] = useState(price); 14 | const cartItems = useSelector((state) => state.cart.items); 15 | const dispatch = useDispatch(); 16 | 17 | useEffect(() => { 18 | setProductPrice(price * quantity); 19 | }, [quantity]); 20 | 21 | const handleIncreaseQuantity = () => { 22 | if (quantity < 6) { 23 | setQuantity(quantity + 1); 24 | } 25 | }; 26 | const handleDecreaseQuantity = () => { 27 | if (quantity > 1) { 28 | setQuantity(quantity - 1); 29 | } 30 | }; 31 | 32 | return ( 33 | 34 | { 37 | navigation.navigate('CartProductDetail', { 38 | productData: productData, 39 | }); 40 | }} 41 | > 42 | 47 | 48 | 49 | 50 | {title} 51 | ${productPrice} 52 | 53 | 54 | 55 | 59 | 60 | 61 | {quantity} 62 | 66 | 67 | 68 | 69 | { 72 | removeItemFromCart(dispatch, id, cartItems); 73 | }} 74 | > 75 | 76 | 77 | 78 | 79 | 80 | ); 81 | }; 82 | 83 | const Styles = StyleSheet.create({ 84 | container: { 85 | width: '100%', 86 | backgroundColor: COLORS.lightGrayColor, 87 | borderRadius: 10, 88 | paddingVertical: 10, 89 | marginBottom: 20, 90 | flexDirection: 'row', 91 | alignItems: 'center', 92 | paddingHorizontal: 10, 93 | }, 94 | imageView: { 95 | width: 80, 96 | height: 80, 97 | borderRadius: 10, 98 | overflow: 'hidden', 99 | padding: 15, 100 | backgroundColor: COLORS.bgColor, 101 | }, 102 | productImage: { 103 | height: '100%', 104 | width: '100%', 105 | }, 106 | contentView: { 107 | flex: 1, 108 | paddingHorizontal: 10, 109 | }, 110 | 111 | title: { 112 | fontFamily: 'Nunito-Bold', 113 | fontSize: 16, 114 | color: COLORS.primaryColor, 115 | }, 116 | size: { 117 | fontFamily: 'Nunito-Bold', 118 | fontSize: 14, 119 | color: COLORS.textColorLight, 120 | }, 121 | 122 | actionBox: { 123 | flexDirection: 'row', 124 | alignItems: 'center', 125 | justifyContent: 'space-between', 126 | marginTop: 5, 127 | }, 128 | priceText: { 129 | fontFamily: 'Nunito-SemiBold', 130 | fontSize: 14, 131 | color: COLORS.blue, 132 | }, 133 | actions: { 134 | flexDirection: 'row', 135 | alignItems: 'center', 136 | }, 137 | quantityText: { 138 | fontFamily: 'Nunito-SemiBold', 139 | fontSize: 18, 140 | color: COLORS.primaryColor, 141 | marginHorizontal: 10, 142 | }, 143 | actionBtnMinus: { 144 | height: 25, 145 | width: 25, 146 | borderWidth: 1.5, 147 | borderColor: COLORS.textColorLight, 148 | borderRadius: 5, 149 | }, 150 | actionBtn: { 151 | backgroundColor: COLORS.primaryColor, 152 | height: 28, 153 | width: 28, 154 | alignItems: 'center', 155 | justifyContent: 'center', 156 | borderRadius: 5, 157 | }, 158 | deleteItemBtn: { 159 | borderWidth: 1, 160 | borderColor: COLORS.textColorLight, 161 | padding: 7, 162 | borderRadius: 50, 163 | }, 164 | }); 165 | 166 | export default CartProductCard; 167 | -------------------------------------------------------------------------------- /dummy_data/products.js: -------------------------------------------------------------------------------- 1 | import COLORS from '../constants/COLORS'; 2 | 3 | export default [ 4 | { 5 | id: 1, 6 | title: 'Foldsack No. 1 Backpack', 7 | price: 109.95, 8 | description: 9 | 'Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday', 10 | category: "men's clothing", 11 | image: 'https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg', 12 | }, 13 | { 14 | id: 2, 15 | title: 'Slim Fit T-Shirts', 16 | price: 22.3, 17 | description: 18 | 'Slim-fitting style, contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable and comfortable wearing. And Solid stitched shirts with round neck made for durability and a great fit for casual fashion wear and diehard baseball fans. The Henley style round neckline includes a three-button placket.', 19 | category: "men's clothing", 20 | image: 21 | 'https://fakestoreapi.com/img/71-3HjGNDUL._AC_SY879._SX._UX._SY._UY_.jpg', 22 | }, 23 | { 24 | id: 3, 25 | title: 'Cotton Jacket', 26 | price: 55.99, 27 | description: 28 | 'great outerwear jackets for Spring/Autumn/Winter, suitable for many occasions, such as working, hiking, camping, mountain/rock climbing, cycling, traveling or other outdoors. Good gift choice for you or your family member. A warm hearted love to Father, husband or son in this thanksgiving or Christmas Day.', 29 | category: "men's clothing", 30 | image: 'https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg', 31 | }, 32 | { 33 | id: 4, 34 | title: 'Casual Slim Fit', 35 | price: 15.99, 36 | description: 37 | 'The color could be slightly different between on the screen and in practice. / Please note that body builds vary by person, therefore, detailed size information should be reviewed below on the product description.', 38 | category: "men's clothing", 39 | image: 'https://fakestoreapi.com/img/71YXzeOuslL._AC_UY879_.jpg', 40 | }, 41 | { 42 | id: 5, 43 | title: 'Chain Bracelet', 44 | price: 695, 45 | description: 46 | "From our Legends Collection, the Naga was inspired by the mythical water dragon that protects the ocean's pearl. Wear facing inward to be bestowed with love and abundance, or outward for protection.", 47 | category: 'jewelery', 48 | image: 'https://fakestoreapi.com/img/71pWzhdJNwL._AC_UL640_QL65_ML3_.jpg', 49 | }, 50 | { 51 | id: 6, 52 | title: 'MicroWave', 53 | price: 168, 54 | description: 55 | 'Satisfaction Guaranteed. Return or exchange any order within 30 days.Designed and sold by Hafeez Center in the United States. Satisfaction Guaranteed. Return or exchange any order within 30 days.', 56 | category: 'jewelery', 57 | image: 'https://fakestoreapi.com/img/61sbMiUnoGL._AC_UL640_QL65_ML3_.jpg', 58 | }, 59 | { 60 | id: 7, 61 | title: 'Gold Plated Princess', 62 | price: 9.99, 63 | description: 64 | "Classic Created Wedding Engagement Solitaire Diamond Promise Ring for Her. Gifts to spoil your love more for Engagement, Wedding, Anniversary, Valentine's Day...", 65 | category: 'jewelery', 66 | image: 'https://fakestoreapi.com/img/71YAIFU48IL._AC_UL640_QL65_ML3_.jpg', 67 | }, 68 | { 69 | id: 8, 70 | title: 'Stainless Steel Double', 71 | price: 10.99, 72 | description: 73 | 'Rose Gold Plated Double Flared Tunnel Plug Earrings. Made of 316L Stainless Steel', 74 | category: 'jewelery', 75 | image: 'https://fakestoreapi.com/img/51UDEzMJVpL._AC_UL640_QL65_ML3_.jpg', 76 | }, 77 | { 78 | id: 9, 79 | title: '2TB External Hard-Drive', 80 | price: 64, 81 | description: 82 | 'USB 3.0 and USB 2.0 Compatibility Fast data transfers Improve PC Performance High Capacity; Compatibility Formatted NTFS for Windows 10, Windows 8.1, Windows 7; Reformatting may be required for other operating systems; Compatibility may vary depending on user’s hardware configuration and operating system', 83 | category: 'electronics', 84 | image: 'https://fakestoreapi.com/img/61IBBVJvSDL._AC_SY879_.jpg', 85 | }, 86 | { 87 | id: 10, 88 | title: '1TB Internal SSD', 89 | price: 109, 90 | description: 91 | 'Easy upgrade for faster boot up, shutdown, application load and response (As compared to 5400 RPM SATA 2.5” hard drive; Based on published specifications and internal benchmarking tests using PCMark vantage scores) Boosts burst write performance, making it ideal for typical PC workloads The perfect balance of performance and reliability Read/write speeds of up to 535MB/s/450MB/s (Based on internal testing; Performance may vary depending upon drive capacity, host device, OS and application.)', 92 | category: 'electronics', 93 | image: 'https://fakestoreapi.com/img/61U7T1koQqL._AC_SX679_.jpg', 94 | }, 95 | { 96 | id: 11, 97 | title: 'Power 256GB SSD', 98 | price: 109, 99 | description: 100 | '3D NAND flash are applied to deliver high transfer speeds Remarkable transfer speeds that enable faster bootup and improved overall system performance. The advanced SLC Cache Technology allows performance boost and longer lifespan 7mm slim design suitable for Ultrabooks and Ultra-slim notebooks. Supports TRIM command, Garbage Collection technology, RAID, and ECC (Error Checking & Correction) to provide the optimized performance and enhanced reliability.', 101 | category: 'electronics', 102 | image: 'https://fakestoreapi.com/img/71kWymZ+c+L._AC_SX679_.jpg', 103 | }, 104 | { 105 | id: 12, 106 | title: '4TB Gaming Drive', 107 | price: 114, 108 | description: 109 | "Expand your PS4 gaming experience, Play anywhere Fast and easy, setup Sleek design with high capacity, 3-year manufacturer's limited warranty", 110 | category: 'electronics', 111 | image: 'https://fakestoreapi.com/img/61mtL65D4cL._AC_SX679_.jpg', 112 | }, 113 | { 114 | id: 13, 115 | title: 'Acer Ultra-Thin', 116 | price: 599, 117 | description: 118 | '21. 5 inches Full HD (1920 x 1080) widescreen IPS display And Radeon free Sync technology. No compatibility for VESA Mount Refresh Rate: 75Hz - Using HDMI port Zero-frame design | ultra-thin | 4ms response time | IPS panel Aspect ratio - 16: 9. Color Supported - 16. 7 million colors. Brightness - 250 nit Tilt angle -5 degree to 15 degree. Horizontal viewing angle-178 degree. Vertical viewing angle-178 degree 75 hertz', 119 | category: 'electronics', 120 | image: 'https://fakestoreapi.com/img/81QpkIctqPL._AC_SX679_.jpg', 121 | }, 122 | { 123 | id: 14, 124 | title: 'Samsung Gaming Monitor', 125 | price: 999.99, 126 | description: 127 | '49 INCH SUPER ULTRAWIDE 32:9 CURVED GAMING MONITOR with dual 27 inch screen side by side QUANTUM DOT (QLED) TECHNOLOGY, HDR support and factory calibration provides stunningly realistic and accurate color and contrast 144HZ HIGH REFRESH RATE and 1ms ultra fast response time work to eliminate motion blur, ghosting, and reduce input lag', 128 | category: 'electronics', 129 | image: 'https://fakestoreapi.com/img/81Zt42ioCgL._AC_SX679_.jpg', 130 | }, 131 | { 132 | id: 15, 133 | title: 'Snowboard Jacket', 134 | price: 56.99, 135 | description: 136 | 'Note:The Jackets is US standard size, Please choose size as your usual wear Material: 100% Polyester; Detachable Liner Fabric: Warm Fleece. Detachable Functional Liner: Skin Friendly, Lightweigt and Warm.Stand Collar Liner jacket, keep you warm in cold weather. Zippered Pockets: 2 Zippered Hand Pockets, 2 Zippered Pockets on Chest (enough to keep cards or keys)and 1 Hidden Pocket Inside.Zippered Hand Pockets and Hidden Pocket keep your things secure. Humanized Design: Adjustable and Detachable Hood and Adjustable cuff to prevent the wind and water,for a comfortable fit. 3 in 1 Detachable Design provide more convenience, you can separate the coat and inner as needed, or wear it together. It is suitable for different season and help you adapt to different climates', 137 | category: "women's clothing", 138 | image: 'https://fakestoreapi.com/img/51Y5NI-I5jL._AC_UX679_.jpg', 139 | }, 140 | { 141 | id: 16, 142 | title: 'Leather Biker Jacket', 143 | price: 29.95, 144 | description: 145 | '100% POLYURETHANE(shell) 100% POLYESTER(lining) 75% POLYESTER 25% COTTON (SWEATER), Faux leather material for style and comfort / 2 pockets of front, 2-For-One Hooded denim style faux leather jacket, Button detail on waist / Detail stitching at sides, HAND WASH ONLY / DO NOT BLEACH / LINE DRY / DO NOT IRON', 146 | category: "women's clothing", 147 | image: 'https://fakestoreapi.com/img/81XH0e8fefL._AC_UY879_.jpg', 148 | }, 149 | { 150 | id: 17, 151 | title: 'Rain Jacket', 152 | price: 39.99, 153 | description: 154 | "Lightweight perfet for trip or casual wear---Long sleeve with hooded, adjustable drawstring waist design. Button and zipper front closure raincoat, fully stripes Lined and The Raincoat has 2 side pockets are a good size to hold all kinds of things, it covers the hips, and the hood is generous but doesn't overdo it.Attached Cotton Lined Hood with Adjustable Drawstrings give it a real styled look.", 155 | category: "women's clothing", 156 | image: 'https://fakestoreapi.com/img/71HblAHs5xL._AC_UY879_-2.jpg', 157 | }, 158 | { 159 | id: 18, 160 | title: 'MBJ Short Sleeve', 161 | price: 9.85, 162 | description: 163 | '95% RAYON 5% SPANDEX, Made in USA or Imported, Do Not Bleach, Lightweight fabric with great stretch for comfort, Ribbed on sleeves and neckline / Double stitching on bottom hem', 164 | category: "women's clothing", 165 | image: 'https://fakestoreapi.com/img/71z3kpMAYsL._AC_UY879_.jpg', 166 | }, 167 | { 168 | id: 19, 169 | title: 'Short Sleeve Moisture', 170 | price: 7.95, 171 | description: 172 | '100% Polyester, Machine wash, 100% cationic polyester interlock, Machine Wash & Pre Shrunk for a Great Fit, Lightweight, roomy and highly breathable with moisture wicking fabric which helps to keep moisture away, Soft Lightweight Fabric with comfortable V-neck collar and a slimmer fit, delivers a sleek, more feminine silhouette and Added Comfort', 173 | category: "women's clothing", 174 | image: 'https://fakestoreapi.com/img/51eg55uWmdL._AC_UX679_.jpg', 175 | }, 176 | { 177 | id: 20, 178 | title: 'T-Shirt, Cotton Short', 179 | price: 12.99, 180 | description: 181 | '95%Cotton,5%Spandex, Features: Casual, Short Sleeve, Letter Print,V-Neck,Fashion Tees, The fabric is soft and has some stretch., Occasion: Casual/Office/Beach/School/Home/Street. Season: Spring,Summer,Autumn,Winter.', 182 | category: "women's clothing", 183 | image: 'https://fakestoreapi.com/img/61pHAEJ4NML._AC_UX679_.jpg', 184 | }, 185 | ]; 186 | 187 | export const PopularProducts = [ 188 | { 189 | id: 2, 190 | title: 'Slim Fit T-Shirts ', 191 | price: 22.3, 192 | description: 193 | 'Slim-fitting style, contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable and comfortable wearing. And Solid stitched shirts with round neck made for durability and a great fit for casual fashion wear and diehard baseball fans. The Henley style round neckline includes a three-button placket.', 194 | category: "men's clothing", 195 | image: 196 | 'https://fakestoreapi.com/img/71-3HjGNDUL._AC_SY879._SX._UX._SY._UY_.jpg', 197 | }, 198 | { 199 | id: 1, 200 | title: 'Foldsack No. 1 Backpack', 201 | price: 109.95, 202 | description: 203 | 'Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday', 204 | category: "men's clothing", 205 | image: 'https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg', 206 | }, 207 | { 208 | id: 11, 209 | title: 'Power 256GB SSD', 210 | price: 109, 211 | description: 212 | '3D NAND flash are applied to deliver high transfer speeds Remarkable transfer speeds that enable faster bootup and improved overall system performance. The advanced SLC Cache Technology allows performance boost and longer lifespan 7mm slim design suitable for Ultrabooks and Ultra-slim notebooks. Supports TRIM command, Garbage Collection technology, RAID, and ECC (Error Checking & Correction) to provide the optimized performance and enhanced reliability.', 213 | category: 'electronics', 214 | image: 'https://fakestoreapi.com/img/71kWymZ+c+L._AC_SX679_.jpg', 215 | }, 216 | { 217 | id: 19, 218 | title: 'Short Sleeve Moisture', 219 | price: 7.95, 220 | description: 221 | '100% Polyester, Machine wash, 100% cationic polyester interlock, Machine Wash & Pre Shrunk for a Great Fit, Lightweight, roomy and highly breathable with moisture wicking fabric which helps to keep moisture away, Soft Lightweight Fabric with comfortable V-neck collar and a slimmer fit, delivers a sleek, more feminine silhouette and Added Comfort', 222 | category: "women's clothing", 223 | image: 'https://fakestoreapi.com/img/51eg55uWmdL._AC_UX679_.jpg', 224 | }, 225 | { 226 | id: 5, 227 | title: 'Chain Bracelet', 228 | price: 695, 229 | description: 230 | "From our Legends Collection, the Naga was inspired by the mythical water dragon that protects the ocean's pearl. Wear facing inward to be bestowed with love and abundance, or outward for protection.", 231 | category: 'jewelery', 232 | image: 'https://fakestoreapi.com/img/71pWzhdJNwL._AC_UL640_QL65_ML3_.jpg', 233 | }, 234 | ]; 235 | 236 | export const CATEGORIES = [ 237 | { id: 101, name: "men's clothing", color: COLORS.blueLight }, 238 | { id: 102, name: "women's clothing", color: COLORS.pinkLight }, 239 | { id: 103, name: 'electronics', color: COLORS.orangeLight }, 240 | { id: 104, name: 'jewelery', color: COLORS.blueLight }, 241 | ]; 242 | --------------------------------------------------------------------------------