├── .eslintignore
├── tsconfig.json
├── models
├── Brands.ts
├── Category.ts
├── SearchCategory.ts
├── UsersInfo.ts
└── item.ts
├── assets
├── icon.png
├── splash.png
├── favicon.png
└── adaptive-icon.png
├── database
├── images
│ ├── products
│ │ ├── 001.jpg
│ │ ├── 002.jpg
│ │ ├── 003.jpg
│ │ ├── Mi1.png
│ │ ├── Mi2.png
│ │ ├── Mi3.png
│ │ ├── boat1.png
│ │ ├── boat2.png
│ │ ├── boat3.png
│ │ ├── boult1.png
│ │ ├── boult2.png
│ │ └── boult3.png
│ └── accessories
│ │ ├── boatairpods1.png
│ │ ├── boatairpods2.png
│ │ ├── boatairpods3.png
│ │ ├── boatrockerz1.png
│ │ ├── boatrockerz2.png
│ │ ├── boatrockerz3.png
│ │ ├── boultairbass1.png
│ │ ├── boultairbass2.png
│ │ ├── boultairbass3.png
│ │ ├── boatbassheads1.png
│ │ ├── boatbassheads2.png
│ │ └── boatbassheads3.png
└── Database.ts
├── babel.config.js
├── .gitignore
├── metro.config.js
├── .prettierrc.json
├── index.js
├── react-native.config.js
├── eas.json
├── utils
└── sanitizeUrlParams.ts
├── .eslintrc.json
├── App.tsx
├── components
├── BrandCard.tsx
├── Message.tsx
├── Converstaion.tsx
├── ImageCard.tsx
└── ScrollCard.tsx
├── app.json
├── firebaseConfig.js
├── router
├── routes.ts
├── MainNavigator.tsx
└── TabNavigator.tsx
├── package.json
├── screens
├── Chat.tsx
├── AddItems.tsx
├── Inbox.tsx
├── Search.tsx
├── Settings.tsx
├── Profile.tsx
├── Home.tsx
├── OnBoarding.tsx
├── LogIn.tsx
└── ProductInfo.tsx
└── hooks
└── useHttpApi.ts
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@tsconfig/react-native/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/models/Brands.ts:
--------------------------------------------------------------------------------
1 | export interface Brands {
2 | id:string,
3 | name:string
4 | }
--------------------------------------------------------------------------------
/models/Category.ts:
--------------------------------------------------------------------------------
1 | export interface Category {
2 | label: string;
3 | value: string;
4 | }
5 |
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/assets/icon.png
--------------------------------------------------------------------------------
/assets/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/assets/splash.png
--------------------------------------------------------------------------------
/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/assets/favicon.png
--------------------------------------------------------------------------------
/assets/adaptive-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/assets/adaptive-icon.png
--------------------------------------------------------------------------------
/models/SearchCategory.ts:
--------------------------------------------------------------------------------
1 | export interface SearchCategory {
2 | id:string,
3 | name: string,
4 | icon: string
5 |
6 | }
--------------------------------------------------------------------------------
/database/images/products/001.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/products/001.jpg
--------------------------------------------------------------------------------
/database/images/products/002.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/products/002.jpg
--------------------------------------------------------------------------------
/database/images/products/003.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/products/003.jpg
--------------------------------------------------------------------------------
/database/images/products/Mi1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/products/Mi1.png
--------------------------------------------------------------------------------
/database/images/products/Mi2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/products/Mi2.png
--------------------------------------------------------------------------------
/database/images/products/Mi3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/products/Mi3.png
--------------------------------------------------------------------------------
/database/images/products/boat1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/products/boat1.png
--------------------------------------------------------------------------------
/database/images/products/boat2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/products/boat2.png
--------------------------------------------------------------------------------
/database/images/products/boat3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/products/boat3.png
--------------------------------------------------------------------------------
/database/images/products/boult1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/products/boult1.png
--------------------------------------------------------------------------------
/database/images/products/boult2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/products/boult2.png
--------------------------------------------------------------------------------
/database/images/products/boult3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/products/boult3.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function(api) {
2 | api.cache(true);
3 | return {
4 | presets: ['babel-preset-expo'],
5 | };
6 | };
7 |
--------------------------------------------------------------------------------
/database/images/accessories/boatairpods1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/accessories/boatairpods1.png
--------------------------------------------------------------------------------
/database/images/accessories/boatairpods2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/accessories/boatairpods2.png
--------------------------------------------------------------------------------
/database/images/accessories/boatairpods3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/accessories/boatairpods3.png
--------------------------------------------------------------------------------
/database/images/accessories/boatrockerz1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/accessories/boatrockerz1.png
--------------------------------------------------------------------------------
/database/images/accessories/boatrockerz2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/accessories/boatrockerz2.png
--------------------------------------------------------------------------------
/database/images/accessories/boatrockerz3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/accessories/boatrockerz3.png
--------------------------------------------------------------------------------
/database/images/accessories/boultairbass1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/accessories/boultairbass1.png
--------------------------------------------------------------------------------
/database/images/accessories/boultairbass2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/accessories/boultairbass2.png
--------------------------------------------------------------------------------
/database/images/accessories/boultairbass3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/accessories/boultairbass3.png
--------------------------------------------------------------------------------
/database/images/accessories/boatbassheads1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/accessories/boatbassheads1.png
--------------------------------------------------------------------------------
/database/images/accessories/boatbassheads2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/accessories/boatbassheads2.png
--------------------------------------------------------------------------------
/database/images/accessories/boatbassheads3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ilesoviy/solana_online_store-FrontEnd/HEAD/database/images/accessories/boatbassheads3.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .expo/
3 | dist/
4 | npm-debug.*
5 | *.jks
6 | *.p8
7 | *.p12
8 | *.key
9 | *.mobileprovision
10 | *.orig.*
11 | web-build/
12 |
13 | # macOS
14 | .DS_Store
15 |
--------------------------------------------------------------------------------
/models/UsersInfo.ts:
--------------------------------------------------------------------------------
1 | export interface UsersInfo {
2 | id:string,
3 | name:string,
4 | surname:string,
5 | email:string,
6 | source:string,
7 | bio:string,
8 | starRating:number,
9 | numberReviews:number
10 | }
--------------------------------------------------------------------------------
/metro.config.js:
--------------------------------------------------------------------------------
1 | // Learn more https://docs.expo.io/guides/customizing-metro
2 | const { getDefaultConfig } = require('expo/metro-config');
3 |
4 | const defaultConfig = getDefaultConfig(__dirname);
5 | defaultConfig.resolver.assetExts.push('cjs');
6 |
7 | module.exports = defaultConfig;
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "arrowParens": "always",
3 | "bracketSpacing": true,
4 | "jsxBracketSameLine": false,
5 | "jsxSingleQuote": false,
6 | "quoteProps": "as-needed",
7 | "singleQuote": true,
8 | "semi": true,
9 | "printWidth": 100,
10 | "useTabs": false,
11 | "tabWidth": 2,
12 | "trailingComma": "es5"
13 | }
14 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import { registerRootComponent } from 'expo';
2 |
3 | import App from './App';
4 |
5 | // registerRootComponent calls AppRegistry.registerComponent('main', () => App);
6 | // It also ensures that whether you load the app in Expo Go or in a native build,
7 | // the environment is set up appropriately
8 | registerRootComponent(App);
9 |
--------------------------------------------------------------------------------
/models/item.ts:
--------------------------------------------------------------------------------
1 | export interface Item {
2 | id: string;
3 | category: string;
4 | productName: string;
5 | productPrice: number;
6 | description: string;
7 | detail: number;
8 | offPercentage?: number;
9 | userVendor?: string;
10 | productImage: string;
11 | likes: number;
12 | productImageList: string[];
13 | }
14 |
--------------------------------------------------------------------------------
/react-native.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | dependency: {
3 | platforms: {
4 | // iOS specific properties go here
5 | ios: {},
6 | // Android specific properties go here
7 | android: {},
8 | },
9 | },
10 | 'react-native-google-signin': {
11 | platforms: {
12 | android: null
13 | }
14 | }
15 | };
16 |
--------------------------------------------------------------------------------
/eas.json:
--------------------------------------------------------------------------------
1 | {
2 | "build": {
3 | "preview": {
4 | "android": {
5 | "buildType": "apk"
6 | }
7 | },
8 | "preview2": {
9 | "android": {
10 | "gradleCommand": ":app:assembleRelease"
11 | }
12 | },
13 | "preview3": {
14 | "developmentClient": true
15 | },
16 | "production": {}
17 | }
18 | }
--------------------------------------------------------------------------------
/utils/sanitizeUrlParams.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Sanitizes url params deleting null or undefined values
3 | * @param queryParams an objcet to be turned in url params
4 | * @returns
5 | */
6 | export default function sanitizeUrlParams(queryParams: { [x: string]: any }) {
7 | const qp = Object.entries(queryParams).filter(
8 | (entry) => entry[1] !== null && entry[1] !== undefined
9 | );
10 | return Object.fromEntries(qp);
11 | }
12 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "es2021": true,
4 | "node": true
5 | },
6 | "extends": ["plugin:react/recommended", "airbnb", "airbnb/hooks", "prettier", "prettier/react"],
7 | "parserOptions": {
8 | "ecmaFeatures": {
9 | "jsx": true
10 | },
11 | "ecmaVersion": 12,
12 | "sourceType": "module"
13 | },
14 | "plugins": ["react", "react-native"],
15 | "rules": {},
16 | "overrides": [{ "files": ["*.ts", "*.tsx"] }]
17 | }
18 |
--------------------------------------------------------------------------------
/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { NavigationContainer } from '@react-navigation/native';
3 | import MainNavigator from './router/MainNavigator';
4 | import { extendTheme, NativeBaseProvider } from 'native-base';
5 |
6 | const theme = extendTheme({});
7 |
8 | const App = () => {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 | );
16 | };
17 |
18 | export default App;
19 |
--------------------------------------------------------------------------------
/components/BrandCard.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { View, Text, TouchableOpacity } from 'react-native';
3 | import { COLOURS } from '../database/Database';
4 |
5 | const ScrollBrand = ({ data }: { data: any }) => {
6 | return (
7 |
25 |
26 | {data.name}
27 |
28 |
29 | );
30 | };
31 |
32 | export default ScrollBrand;
33 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "expo": {
3 | "name": "FrontApp",
4 | "slug": "FrontApp",
5 | "version": "1.0.0",
6 | "orientation": "portrait",
7 | "icon": "./assets/icon.png",
8 | "userInterfaceStyle": "light",
9 | "splash": {
10 | "image": "./assets/splash.png",
11 | "resizeMode": "contain",
12 | "backgroundColor": "#ffffff"
13 | },
14 | "updates": {
15 | "fallbackToCacheTimeout": 0
16 | },
17 | "assetBundlePatterns": [
18 | "**/*"
19 | ],
20 | "ios": {
21 | "supportsTablet": true
22 | },
23 | "android": {
24 | "adaptiveIcon": {
25 | "foregroundImage": "./assets/adaptive-icon.png",
26 | "backgroundColor": "#FFFFFF"
27 | },
28 | "package": "com.newstar121.FrontApp"
29 | },
30 | "web": {
31 | "favicon": "./assets/favicon.png"
32 | },
33 | "extra": {
34 | "eas": {
35 | "projectId": "2e75b1aa-6f1b-4041-832b-0e11720e1781"
36 | }
37 | },
38 | "scheme": "mycoolredirect"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/firebaseConfig.js:
--------------------------------------------------------------------------------
1 | import { initializeApp } from 'firebase/app';
2 |
3 | // Optionally import the services that you want to use
4 | // import {...} from "firebase/auth";
5 | // import {...} from "firebase/database";
6 | // import {...} from "firebase/firestore";
7 | // import {...} from "firebase/functions";
8 | // import {...} from "firebase/storage";
9 |
10 | // Initialize Firebase
11 | const firebaseConfig = {
12 | apiKey: 'AIzaSyBveNCE-zzLYVnXsfA3eA-EaFN25e2Vr0A',
13 | authDomain: "frontapp-28f45.firebaseapp.com",
14 | projectId: "frontapp-28f45",
15 | storageBucket: "frontapp-28f45.appspot.com",
16 | messagingSenderId: "1064351666274",
17 | appId: "1:1064351666274:web:25e862ad6cf31e4639813b",
18 | databaseURL: 'https://frontapp-28f45.firebaseio.com',
19 | };
20 |
21 | const firebase = initializeApp(firebaseConfig);
22 | // For more information on how to access Firebase in your project,
23 | // see the Firebase documentation: https://firebase.google.com/docs/web/setup#access-firebase
24 | // export const firebaseAuth = getAuth(app);
25 | export default firebase;
--------------------------------------------------------------------------------
/router/routes.ts:
--------------------------------------------------------------------------------
1 | import { NativeStackScreenProps } from '@react-navigation/native-stack';
2 | import { BottomTabScreenProps } from '@react-navigation/bottom-tabs';
3 | import { CompositeScreenProps } from '@react-navigation/native';
4 | import { Item } from '../models/Item';
5 |
6 | export type MainStackParamList = {
7 | OnBoarding: undefined;
8 | LogIn: undefined;
9 | Settings: undefined;
10 | HomeTabs: undefined;
11 | Product: { product: Item };
12 | AddItems: undefined;
13 | Chat: undefined;
14 | };
15 |
16 | export type HomeTabsParamList = {
17 | Home: undefined;
18 | Search: undefined;
19 | AddItems: undefined;
20 | Inbox: undefined;
21 | Profile: undefined;
22 | };
23 |
24 | export type MainStackScreenProps = NativeStackScreenProps<
25 | MainStackParamList,
26 | T
27 | >;
28 |
29 | export type HomeTabsScreenProps = CompositeScreenProps<
30 | BottomTabScreenProps,
31 | MainStackScreenProps
32 | >;
33 |
34 | declare global {
35 | namespace ReactNavigation {
36 | interface RootParamList extends MainStackParamList {}
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/router/MainNavigator.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createNativeStackNavigator } from '@react-navigation/native-stack';
3 | import { MainStackParamList } from './routes';
4 | import Settings from '../screens/Settings';
5 | import AddItems from '../screens/AddItems';
6 | import ProductInfo from '../screens/ProductInfo';
7 | import Chat from '../screens/Chat';
8 | import HomeTabsNavigator from './TabNavigator';
9 | import OnBoarding from '../screens/OnBoarding';
10 | import LogIn from '../screens/LogIn';
11 |
12 | const MainStack = createNativeStackNavigator();
13 | export default function MainNavigator() {
14 | return (
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/components/Message.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { View, Text, TouchableOpacity, Image } from 'react-native';
3 | import { COLOURS } from '../database/Database';
4 |
5 | const labelStyles = {
6 | };
7 |
8 | const Message = ({ data }: { data: any; }) => {
9 | return (
10 |
16 |
17 |
21 |
22 |
42 | {data.message}
43 |
44 |
45 |
46 | );
47 | };
48 |
49 | export default Message;
50 |
--------------------------------------------------------------------------------
/components/Converstaion.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { View, Text, TouchableOpacity, Image } from 'react-native';
3 | import { COLOURS } from '../database/Database';
4 |
5 | const labelStyles = {
6 | };
7 |
8 | const Conversation = ({ data, onPress }: { data: any; onPress: (id: string) => void }) => {
9 | return (
10 | onPress(data.id)}
12 | style={{
13 | margin: 14,
14 | }}
15 |
16 | >
17 |
21 |
22 |
30 |
31 |
35 | {data.fullname || 'John'}
36 | {data.time || 'now'}
37 |
38 | {data.message || 'This is a test message'}
39 |
40 |
41 |
42 |
43 | );
44 | };
45 |
46 | export default Conversation;
47 |
--------------------------------------------------------------------------------
/components/ImageCard.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { View, TouchableOpacity, Image } from 'react-native';
3 | import { COLOURS } from '../database/Database';
4 |
5 | const ImageCard = ({ data, onPress }: { data: any; onPress: (id: string) => void }) => {
6 | return (
7 | onPress(data.id)}
9 | style={{
10 | width: '8rem',
11 | height: '8rem',
12 | margin: '0.5rem',
13 | // backgroundColor: COLOURS.white,
14 | // borderRadius: 30,
15 | // borderColor: '#000',
16 | // shadowColor: '#000',
17 | // shadowOffset: {
18 | // width: 0,
19 | // height: 5,
20 | // },
21 | // shadowOpacity: 0.6,
22 | // shadowRadius: 16.0,
23 | elevation: 15,
24 | }}
25 | >
26 |
37 |
47 |
48 |
49 | );
50 | };
51 | export default ImageCard;
52 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontapp",
3 | "version": "1.0.0",
4 | "main": "node_modules/expo/AppEntry.js",
5 | "scripts": {
6 | "start": "expo start",
7 | "android": "cross-env ENVFILE=.env.dev expo start --android",
8 | "ios": "cross-env ENVFILE=.env.dev expo start --ios",
9 | "web": "expo start --web"
10 | },
11 | "dependencies": {
12 | "@aws-sdk/client-s3": "^3.272.0",
13 | "@expo/webpack-config": "^0.17.2",
14 | "@heroicons/react": "^2.0.14",
15 | "@react-native-async-storage/async-storage": "^1.17.11",
16 | "@react-navigation/bottom-tabs": "^6.5.3",
17 | "@react-navigation/native": "^6.1.2",
18 | "@react-navigation/native-stack": "^6.9.8",
19 | "axios": "^1.3.4",
20 | "cross-env": "^7.0.3",
21 | "expo": "^47.0.13",
22 | "expo-status-bar": "~1.4.2",
23 | "native-base": "^3.4.28",
24 | "react": "18.1.0",
25 | "react-dom": "18.1.0",
26 | "react-native": "0.70.5",
27 | "react-native-config": "^1.5.0",
28 | "react-native-dynamic-vector-icons": "^1.3.0",
29 | "react-native-element-dropdown": "^2.6.0",
30 | "react-native-elements": "^3.4.3",
31 | "react-native-form-component": "^2.6.8",
32 | "react-native-linear-gradient": "^2.6.2",
33 | "react-native-navigation": "^7.31.1",
34 | "react-native-safe-area-context": "3.3.2",
35 | "react-native-screens": "^3.19.0",
36 | "react-native-svg": "12.1.1",
37 | "react-native-svg-transformer": "^1.0.0",
38 | "react-native-vector-icons": "^9.2.0",
39 | "react-native-web": "~0.18.9",
40 | "react-navigation": "^4.4.4",
41 | "react-number-format": "^5.1.3"
42 | },
43 | "devDependencies": {
44 | "@babel/core": "^7.12.9",
45 | "@tsconfig/react-native": "^2.0.3",
46 | "@types/jest": "^29.4.0",
47 | "@types/react": "^18.0.28",
48 | "@types/react-test-renderer": "^18.0.0",
49 | "eslint": "^8.35.0",
50 | "eslint-config-prettier": "^8.6.0",
51 | "eslint-plugin-react-native": "^4.0.0",
52 | "prettier": "^2.8.4",
53 | "typescript": "^4.9.5"
54 | },
55 | "private": true
56 | }
57 |
--------------------------------------------------------------------------------
/components/ScrollCard.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { View, Text, TouchableOpacity, Image } from 'react-native';
3 | import { COLOURS } from '../database/Database';
4 | import Ionicons from 'react-native-vector-icons/Ionicons';
5 |
6 | const ScrollCard = ({ data, onPress }: { data: any; onPress: (id: string) => void }) => {
7 | return (
8 | onPress(data.id)}
10 | style={{
11 | width: 140,
12 | marginVertical: 14,
13 | marginRight: 10,
14 | backgroundColor: COLOURS.white,
15 | padding: 10,
16 | borderRadius: 30,
17 |
18 | shadowColor: '#000',
19 | shadowOffset: {
20 | width: 0,
21 | height: 5,
22 | },
23 | shadowOpacity: 0.6,
24 | shadowRadius: 16.0,
25 |
26 | elevation: 15,
27 | }}
28 | >
29 |
40 |
48 |
49 |
58 | $ {data.productPrice}
59 |
66 | {data.likes}
67 |
68 |
69 |
70 |
80 |
85 | Size: {data.detail}
86 |
87 |
88 |
89 | );
90 | };
91 | export default ScrollCard;
92 |
--------------------------------------------------------------------------------
/screens/Chat.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { View, Text, StatusBar, TextInput, Button, FlatList, StyleSheet, TouchableOpacity } from 'react-native';
3 |
4 | import Entypo from 'react-native-vector-icons/Entypo';
5 | import { COLOURS } from '../database/Database';
6 | import { MainStackScreenProps } from '../router/routes';
7 | import Message from '../components/Message';
8 |
9 | const Chat = ({ route, navigation }: MainStackScreenProps<'Chat'>) => {
10 | const [messages, setMessages] = useState([]);
11 | const [newMessage, setNewMessage] = useState('');
12 |
13 | const handleSubmit = () => {
14 | setMessages([{isMe: Math.random() * 10 > 5, message:newMessage }, ]);
15 | setNewMessage('');
16 | };
17 |
18 | return (
19 |
26 |
27 |
28 |
35 |
36 | navigation.goBack()}>
37 |
47 |
48 |
55 | Messages
56 |
57 |
58 |
59 |
60 |
61 | }
70 | />
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | );
79 | };
80 |
81 | const styles = StyleSheet.create({
82 | container: {
83 | flex: 1,
84 | padding: 20,
85 | },
86 | message: {
87 | fontSize: 20,
88 | marginBottom: 10,
89 | },
90 | form: {
91 | flexDirection: 'row',
92 | padding: 10,
93 | },
94 | input: {
95 | flex: 1,
96 | height: 40,
97 | padding: 10,
98 | borderWidth: 1,
99 | borderColor: 'gray',
100 | },
101 | });
102 |
103 | export default Chat;
104 |
--------------------------------------------------------------------------------
/router/TabNavigator.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
3 | import { HomeTabsParamList } from './routes';
4 | import { COLOURS, UsersInfo } from '../database/Database';
5 | import { StyleSheet, View } from 'react-native';
6 | import { Avatar } from 'react-native-elements';
7 | import Ionicons from 'react-native-vector-icons/Ionicons';
8 | import Home from '../screens/Home';
9 | import Search from '../screens/Search';
10 | import AddItems from '../screens/AddItems';
11 | import Inbox from '../screens/Inbox';
12 | import Profile from '../screens/Profile';
13 |
14 | const HomeTabs = createBottomTabNavigator();
15 |
16 | export default function HomeTabsNavigator() {
17 | return (
18 | ({
21 | headerShown: false,
22 | tabBarShowLabel: false,
23 | tabBarStyle: {
24 | backgroundColor: COLOURS.white,
25 | height: 60,
26 | },
27 | tabBarActiveTintColor: COLOURS.lighterPurple,
28 | tabBarInactiveTintColor: COLOURS.lightGray,
29 | })}
30 | >
31 | (
36 |
37 | ),
38 | }}
39 | />
40 | (
45 |
46 | ),
47 | }}
48 | />
49 | ,
54 | }}
55 | />
56 | (
61 |
62 | ),
63 | }}
64 | />
65 | (
70 |
71 |
77 |
78 | ),
79 | }}
80 | />
81 |
82 | );
83 | }
84 |
85 | const styles = StyleSheet.create({
86 | selected: {
87 | borderRadius: 50,
88 | borderWidth: 3,
89 | borderColor: COLOURS.lighterPurple,
90 | },
91 | notSelected: {
92 | borderWidth: 0,
93 | },
94 | });
--------------------------------------------------------------------------------
/screens/AddItems.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | View,
4 | Text,
5 | StatusBar,
6 | ScrollView,
7 | TouchableOpacity,
8 | StyleSheet,
9 | TextInput,
10 | } from 'react-native';
11 | import { COLOURS, Categorys } from '../database/Database';
12 | import Ionicons from 'react-native-vector-icons/Ionicons';
13 | import { HomeTabsScreenProps } from '../router/routes';
14 |
15 | const AddItems = ({ navigation }: HomeTabsScreenProps<'AddItems'>) => {
16 | const [data, setData] = React.useState({
17 | title: '',
18 | description: '',
19 | category: '',
20 | brand: '',
21 | });
22 |
23 | const titleChange = (val: string) => {
24 | setData({ ...data, title: val });
25 | };
26 |
27 | const descriptionChange = (val: string) => {
28 | setData({ ...data, description: val });
29 | };
30 |
31 | const categoryChange = (val: string) => {
32 | setData({ ...data, category: val });
33 | };
34 |
35 | const brandChange = (val: string) => {
36 | setData({ ...data, brand: val });
37 | };
38 |
39 | return (
40 | <>
41 |
49 |
50 |
51 |
59 |
60 | navigation.goBack()}>
61 |
62 |
63 |
64 |
65 |
73 | Sell an item
74 |
75 |
76 |
77 |
85 |
86 |
94 |
95 |
96 |
97 |
98 | >
99 | );
100 | };
101 |
102 | const styles = StyleSheet.create({
103 | icon: {
104 | width: '10%',
105 | color: COLOURS.lighterPurple,
106 | },
107 | input: {
108 | backgroundColor: COLOURS.white,
109 | borderWidth: 1,
110 | borderColor: COLOURS.lightGray,
111 | borderRadius: 30,
112 | width: '100%',
113 | marginBottom: '5%',
114 | paddingHorizontal: 15,
115 | paddingVertical: 10,
116 |
117 | shadowColor: '#000',
118 | shadowOffset: {
119 | width: 0,
120 | height: 1,
121 | },
122 | shadowOpacity: 1,
123 | shadowRadius: 10.0,
124 | elevation: 5,
125 | },
126 | });
127 |
128 | export default AddItems;
129 |
--------------------------------------------------------------------------------
/screens/Inbox.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { View, Text, StatusBar, StyleSheet, ScrollView, TouchableOpacity } from 'react-native';
3 | import { COLOURS, Items, Brands } from '../database/Database';
4 | import { Button, SearchBar } from 'react-native-elements';
5 | import Ionicons from 'react-native-vector-icons/Ionicons';
6 | import ConverstionElem from '../components/Converstaion';
7 | import Chat from './Chat';
8 | import { HomeTabsScreenProps } from '../router/routes';
9 | import { FlatList } from 'react-native';
10 | import Entypo from 'react-native-vector-icons/Entypo';
11 |
12 | const convs = [
13 | { avatar: 'https://avatars.githubusercontent.com/u/131432648?s=64&v=4', fullname: 'sddds', time: 'now', message: 'There are no major defects or damages. Only tiny scratches' },
14 | { avatar: 'https://avatars.githubusercontent.com/u/131432648?s=64&v=4', fullname: 'sdf', time: '3m ago', message: 'There are no major defects or damages. Only tiny scratches' },
15 | { avatar: 'https://avatars.githubusercontent.com/u/131432648?s=64&v=4', fullname: 'gge', time: '2h ago', message: 'There are no major defects or damages. Only tiny scratches' },
16 | { avatar: 'https://avatars.githubusercontent.com/u/131432648?s=64&v=4', fullname: 'beffg', time: '9h ago', message: 'There are no major defects or damages. Only tiny scratches' },
17 | { avatar: 'https://avatars.githubusercontent.com/u/131432648?s=64&v=4', fullname: 'lwkekf', time: 'past', message: 'There are no major defects or damages. Only tiny scratches' },
18 | ];
19 |
20 | const Inbox = ({ navigation }: HomeTabsScreenProps<'Inbox'>) => {
21 | return (
22 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
51 | Messages
52 |
53 |
54 |
55 | {/* SearchBar */}
56 |
61 | {/*@ts-ignore */}
62 |
88 |
89 |
90 | navigation.navigate('Chat')}
95 | />}
96 | />
97 |
98 |
99 |
100 | );
101 | };
102 |
103 | export default Inbox;
104 |
--------------------------------------------------------------------------------
/screens/Search.tsx:
--------------------------------------------------------------------------------
1 | import { View, StatusBar, ScrollView, Text, TouchableOpacity } from 'react-native';
2 | import { COLOURS, SearchCategory } from '../database/Database';
3 | import Ionicons from 'react-native-vector-icons/Ionicons';
4 | import { SearchBar } from 'react-native-elements';
5 |
6 | const Search = () => {
7 | // create an category reusable card
8 | const CategoryCard = ({ data }: { data: any }) => {
9 | return (
10 |
28 |
34 |
43 | {data.name}
44 |
45 |
46 | );
47 | };
48 |
49 | return (
50 |
57 |
58 |
59 |
60 |
69 |
76 | Search
77 |
78 |
79 |
98 |
99 |
100 |
101 | {/* SearchBar */}
102 |
107 | {/* */}
134 |
135 |
136 |
145 | {SearchCategory.map((data) => {
146 | return ;
147 | })}
148 |
149 |
150 |
151 | );
152 | };
153 |
154 | export default Search;
155 |
--------------------------------------------------------------------------------
/screens/Settings.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { View, Text, StatusBar, ScrollView, TouchableOpacity, StyleSheet } from 'react-native';
3 | import { COLOURS } from '../database/Database';
4 | import Ionicons from 'react-native-vector-icons/Ionicons';
5 | import { MainStackScreenProps } from '../router/routes';
6 |
7 | const Settings = ({ navigation }: MainStackScreenProps<'Settings'>) => {
8 | return (
9 |
16 |
17 |
18 |
19 |
27 |
28 | navigation.goBack()}>
29 |
30 |
31 |
32 |
33 |
41 | Settings
42 |
43 |
44 |
45 |
63 |
64 |
65 | Favourite items
66 |
67 |
68 |
69 | Personalization
70 |
71 |
72 |
73 | Dark mode
74 |
75 |
76 |
77 | Balance
78 |
79 |
80 |
81 | My orders
82 |
83 |
84 |
85 | Bundle discounts
86 |
87 |
88 |
89 | Donations
90 |
91 |
92 |
93 | CO2 Saved
94 |
95 |
96 |
97 |
115 |
116 |
117 | Forum
118 |
119 |
120 |
121 | Yout guide to Solvent
122 |
123 |
124 |
125 |
126 | );
127 | };
128 |
129 | const styles = StyleSheet.create({
130 | settingsItemsViewTop: {
131 | borderWidth: 1,
132 | borderColor: COLOURS.white,
133 | borderBottomColor: COLOURS.lightGray,
134 | flexDirection: 'row',
135 | paddingHorizontal: 10,
136 | paddingBottom: '5%',
137 | },
138 | settingsItemsView: {
139 | borderWidth: 1,
140 | borderColor: COLOURS.white,
141 | borderBottomColor: COLOURS.lightGray,
142 | flexDirection: 'row',
143 | paddingHorizontal: 10,
144 | paddingVertical: '5%',
145 | },
146 | icon: {
147 | width: '10%',
148 | color: COLOURS.lighterPurple,
149 | },
150 | settingsItemsViewBottom: {
151 | flexDirection: 'row',
152 | paddingHorizontal: 10,
153 | paddingTop: '5%',
154 | },
155 | });
156 |
157 | export default Settings;
158 |
--------------------------------------------------------------------------------
/hooks/useHttpApi.ts:
--------------------------------------------------------------------------------
1 | import sanitizeUrlParams from '../utils/sanitizeUrlParams';
2 | import axios, { AxiosError } from 'axios';
3 |
4 | const API_URL="http://65.108.20.232:4000/v0";
5 |
6 | interface ApiCallMethods {
7 | apiGet: (url: string, queryParams?: { [x: string]: any }) => Promise;
8 | apiPost: (url: string, data: any) => Promise;
9 | apiPut: (url: string, data: any) => Promise;
10 | apiDelete: (url: string) => Promise;
11 | }
12 |
13 | class NotFoundError extends Error {
14 | constructor(message?: string) {
15 | super(message ?? 'Not found');
16 | this.name = 'NotFound';
17 | }
18 | }
19 |
20 | /**
21 | * Hook to be used for all apis which don't require
22 | * authentication. If the user is signed in, automatically
23 | * adds a Bearer token to the headers
24 | * @returns ApiCallMethods
25 | *
26 | * To use it:
27 | * const httpApi = useHttpApi();
28 | * const queryParams = {}
29 | *
30 | * const response = await httpApi.apiGet('/url', queryParams);
31 | *
32 | * Example for Brands:
33 | * const httpApi = useHttpApi();
34 | *
35 | * const response = await httpApi.apiGet('/items/brands');
36 | */
37 | export default function useHttpApi(): ApiCallMethods {
38 | //const { getAccessToken, signOut } = useAuth();
39 |
40 | /**
41 | * Makes a GET request
42 | * @param url url for the api resource
43 | * @param queryParams query params as an object
44 | * @returns
45 | */
46 | async function apiGet(url: string, queryParams?: { [x: string]: any }) {
47 | //const h = authHeader();
48 | const token = 'unknown'; //getAccessToken();
49 | console.log(token);
50 | let headers: any = {
51 | 'Content-Type': 'application/json',
52 | };
53 | const q = queryParams
54 | ? `?${new URLSearchParams(sanitizeUrlParams(queryParams)).toString()}`
55 | : '';
56 | if (token) {
57 | headers = {
58 | ...headers,
59 | Authorization: `Bearer ${token}`,
60 | };
61 | }
62 | const api_url = `${API_URL}${url}${q}`;
63 | return axios
64 | .get(api_url, {
65 | headers,
66 | })
67 | .then((response) => {
68 | if (!response.data) {
69 | throw new NotFoundError();
70 | } else {
71 | return response.data;
72 | }
73 | })
74 | .catch((error: Error | AxiosError) => {
75 | if (axios.isAxiosError(error)) {
76 | const e = error as AxiosError;
77 | if (e.response?.status == 401) {
78 | //TODO - handle signout if token is not valid
79 | //signOut();
80 | throw error;
81 | } else {
82 | throw error;
83 | }
84 | } else {
85 | throw error;
86 | }
87 | });
88 | }
89 |
90 | /**
91 | * Makes a POST request
92 | * @param url url for the api resource
93 | * @param data data to post
94 | * @param queryParams query params as an object
95 | * @returns
96 | */
97 | async function apiPost(url: string, data: any, queryParams?: { [x: string]: any }) {
98 | const token = 'unknown'; //getAccessToken();
99 | console.log(token);
100 | let headers: any = {
101 | 'Content-Type': 'application/json',
102 | };
103 | const q = queryParams
104 | ? `?${new URLSearchParams(sanitizeUrlParams(queryParams)).toString()}`
105 | : '';
106 | if (token) {
107 | headers = {
108 | ...headers,
109 | Authorization: `Bearer ${token}`,
110 | };
111 | }
112 | return axios
113 | .post(`${API_URL}${url}`, data, {
114 | headers,
115 | })
116 | .then((response) => response.data)
117 | .catch((error: Error | AxiosError) => {
118 | if (axios.isAxiosError(error)) {
119 | const e = error as AxiosError;
120 | if (e.response?.status == 401) {
121 | //signOut();
122 | throw error;
123 | } else {
124 | throw error;
125 | }
126 | } else {
127 | throw error;
128 | }
129 | });
130 | }
131 | /**
132 | * Makes a PUT request
133 | * @param url url for the api resource
134 | * @param data data to put
135 | * @param queryParams query params as an object
136 | * @returns
137 | */
138 | async function apiPut(url: string, data: any, queryParams?: { [x: string]: any }) {
139 | const token = 'unknown'; //getAccessToken();
140 | console.log(token);
141 | let headers: any = {
142 | 'Content-Type': 'application/json',
143 | };
144 | const q = queryParams
145 | ? `?${new URLSearchParams(sanitizeUrlParams(queryParams)).toString()}`
146 | : '';
147 | if (token) {
148 | headers = {
149 | ...headers,
150 | Authorization: `Bearer ${token}`,
151 | };
152 | }
153 | return axios
154 | .put(`${API_URL}${url}`, data, {
155 | headers,
156 | })
157 | .then((response) => response.data)
158 | .catch((error: Error | AxiosError) => {
159 | if (axios.isAxiosError(error)) {
160 | const e = error as AxiosError;
161 | if (e.response?.status == 401) {
162 | //signOut();
163 | throw error;
164 | } else {
165 | throw error;
166 | }
167 | } else {
168 | throw error;
169 | }
170 | });
171 | }
172 |
173 | /**
174 | * Makes a DELETE request
175 | * @param url url for the api resource
176 | * @param queryParams query params as an object
177 | * @returns
178 | */
179 | async function apiDelete(url: string, queryParams?: { [x: string]: any }) {
180 | const token = 'unknown'; //getAccessToken();
181 | console.log(token);
182 | let headers: any = {
183 | 'Content-Type': 'application/json',
184 | };
185 | const q = queryParams
186 | ? `?${new URLSearchParams(sanitizeUrlParams(queryParams)).toString()}`
187 | : '';
188 | if (token) {
189 | headers = {
190 | ...headers,
191 | Authorization: `Bearer ${token}`,
192 | };
193 | }
194 | return axios
195 | .delete(`${API_URL}${url}`, {
196 | headers,
197 | })
198 | .then((response) => response.data)
199 | .catch((error: Error | AxiosError) => {
200 | if (axios.isAxiosError(error)) {
201 | const e = error as AxiosError;
202 | if (e.response?.status == 401) {
203 | //signOut();
204 | throw error;
205 | } else {
206 | throw error;
207 | }
208 | } else {
209 | throw error;
210 | }
211 | });
212 | }
213 | return { apiGet, apiPost, apiPut, apiDelete };
214 | }
215 |
--------------------------------------------------------------------------------
/screens/Profile.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { View, Text, StatusBar, ScrollView, TouchableOpacity } from 'react-native';
3 | import { COLOURS, UsersInfo, Items } from '../database/Database';
4 | import Ionicons from 'react-native-vector-icons/Ionicons';
5 | import { Avatar } from 'react-native-elements';
6 | import ScrollCard from '../components/ScrollCard';
7 | import Settings from './Settings';
8 | import { HomeTabsScreenProps, MainStackScreenProps } from '../router/routes';
9 | import { Item } from '../models/Item';
10 |
11 | const Profile = ({ navigation }: HomeTabsScreenProps<'Profile'>) => {
12 | const [products, setProducts] = useState- ([]);
13 | const [size, setSize] = useState([]);
14 |
15 | //get called on screen loads
16 | useEffect(() => {
17 | const unsubscribe = navigation.addListener('focus', () => {
18 | getDataFromDB();
19 | });
20 |
21 | return unsubscribe;
22 | }, [navigation]);
23 |
24 | //get data from DB
25 | const getDataFromDB = () => {
26 | let productList = [];
27 | for (let index = 0; index < Items.length; index++) {
28 | if (Items[index].category == 'product' && Items[index].userVendor === UsersInfo.email) {
29 | productList.push(Items[index]);
30 | }
31 | }
32 | setProducts(productList);
33 | };
34 |
35 | return (
36 |
43 |
44 |
45 |
46 |
55 |
62 | Profile
63 |
64 |
65 |
72 |
73 |
92 |
93 |
94 | navigation.navigate('Settings')}>
95 |
114 |
115 |
116 |
117 |
118 |
124 |
131 |
132 |
133 | {UsersInfo.name}
134 |
135 |
136 | {UsersInfo.bio}
137 |
138 |
139 |
140 |
141 |
163 | {/* StarRating */}
164 |
172 | {UsersInfo.starRating}/5
173 |
174 |
175 |
176 |
181 | {UsersInfo.numberReviews} Reviews
182 |
183 |
184 |
185 | {/* Items */}
186 |
193 |
200 | Your items
201 |
202 |
203 |
204 |
210 |
217 |
224 | {products.map((data) => {
225 | return (
226 | navigation.navigate('Product', { product: data })}
230 | />
231 | );
232 | })}
233 |
234 |
235 |
236 |
237 |
238 | );
239 | };
240 |
241 | export default Profile;
242 |
--------------------------------------------------------------------------------
/screens/Home.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { View, Text, StatusBar, ScrollView, TouchableOpacity } from 'react-native';
3 | import { COLOURS, Items } from '../database/Database';
4 | import { SearchBar } from 'react-native-elements';
5 | import Ionicons from 'react-native-vector-icons/Ionicons';
6 | import ScrollCard from '../components/ScrollCard';
7 | import { HomeTabsScreenProps } from '../router/routes';
8 | import ScrollBrand from '../components/BrandCard';
9 | import { Item } from '../models/Item';
10 | import { Brands } from '../models/Brands';
11 | import axios from 'axios';
12 | import { Row } from 'native-base';
13 | import useHttpApi from '../hooks/useHttpApi';
14 |
15 | interface BrandsState {
16 | data: Brands[] | undefined;
17 | loading: boolean;
18 | error: boolean;
19 | }
20 |
21 | const Home = ({ navigation }: HomeTabsScreenProps<'Home'>) => {
22 | const [products, setProducts] = useState
- ([]);
23 | const [accessory, setAccessory] = useState([]);
24 | const httpApi = useHttpApi();
25 | const [brands, setBrands] = useState({
26 | data: undefined,
27 | loading: true,
28 | error: false,
29 | });
30 |
31 | // get called on screen loads
32 | // useEffect(() => {
33 | // const fetchData = async () =>{
34 |
35 | // }
36 | // navigation.addListener('focus', fetchData);
37 | // return navigation.removeListener('focus', fetchData);
38 | // }, [navigation]);
39 |
40 | useEffect(() => {
41 | const fetchBrands = async () => {
42 | try {
43 | setBrands({ data: undefined, loading: true, error: false });
44 | const response = await httpApi.apiGet('/items/brands');
45 | setBrands({ data: response, loading: false, error: false });
46 | } catch (error) {
47 | console.log(error);
48 | setBrands({ data: undefined, loading: false, error: true });
49 | }
50 | };
51 | fetchBrands();
52 | getDataFromDB();
53 | }, []);
54 |
55 | // get data from DB
56 | const getDataFromDB = () => {
57 | let productList = [];
58 | let accessoryList = [];
59 | for (let index = 0; index < Items.length; index++) {
60 | if (Items[index].category == 'product') {
61 | productList.push(Items[index]);
62 | } else if (Items[index].category == 'accessory') {
63 | accessoryList.push(Items[index]);
64 | }
65 | }
66 | setProducts(productList);
67 | };
68 |
69 | return (
70 |
77 |
78 |
79 |
88 |
95 | Home
96 |
97 |
98 |
117 |
118 |
119 |
120 | {/* SearchBar */}
121 |
126 | {/* @ts-ignore */}
127 | {/* */}
153 |
154 |
155 | {/* Products */}
156 |
164 |
171 | Products
172 |
173 |
174 |
175 |
181 |
188 |
195 | {products.map((data) => {
196 | return (
197 | navigation.navigate('Product', { product: data })}
201 | />
202 | );
203 | })}
204 |
205 |
206 |
207 |
208 | {/* Shop by brand */}
209 |
216 |
223 | Shop by brand
224 |
225 |
226 | {brands.loading && (
227 |
228 | Caricamento...
229 |
230 | )}
231 | {!brands.loading && brands.error && (
232 |
233 | Errore
234 |
235 | )}
236 | {!brands.loading && !brands.error && brands.data && (
237 |
238 |
244 |
251 |
258 | {brands.data.map((data) => {
259 | return ;
260 | })}
261 |
262 |
263 |
264 | )}
265 |
266 | {/* Recommended */}
267 |
274 |
281 | Recommended{' '}
282 |
283 |
284 |
285 |
291 |
298 |
299 | {products.map((data) => {
300 | return (
301 | navigation.navigate('Product', { product: data })}
305 | />
306 | );
307 | })}
308 |
309 |
310 |
311 |
312 |
313 | );
314 | };
315 |
316 | export default Home;
317 |
--------------------------------------------------------------------------------
/screens/OnBoarding.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { View, Text, Image, Button, StatusBar, ScrollView, TouchableOpacity } from 'react-native';
3 | import { COLOURS, _Items } from '../database/Database';
4 | import { SearchBar } from 'react-native-elements';
5 | import Ionicons from 'react-native-vector-icons/Ionicons';
6 | import ScrollCard from '../components/ScrollCard';
7 | import { HomeTabsScreenProps } from '../router/routes';
8 | import ScrollBrand from '../components/BrandCard';
9 | import { Item } from '../models/Item';
10 | import { Brands } from '../models/Brands';
11 | import axios from 'axios';
12 | import { Row } from 'native-base';
13 | import useHttpApi from '../hooks/useHttpApi';
14 | import { MainStackScreenProps } from '../router/routes';
15 | import ImageCard from '../components/ImageCard';
16 |
17 | interface BrandsState {
18 | data: Brands[] | undefined;
19 | loading: boolean;
20 | error: boolean;
21 | }
22 |
23 | const OnBoarding = ({ navigation }: MainStackScreenProps<'OnBoarding'>) => {
24 | const [products, setProducts] = useState- ([]);
25 | const [accessory, setAccessory] = useState([]);
26 | const httpApi = useHttpApi();
27 | const [brands, setBrands] = useState({
28 | data: undefined,
29 | loading: true,
30 | error: false,
31 | });
32 |
33 | useEffect(() => {
34 | const fetchBrands = async () => {
35 | try {
36 | setBrands({ data: undefined, loading: true, error: false });
37 | const response = await httpApi.apiGet('/items/brands');
38 | setBrands({ data: response, loading: false, error: false });
39 | } catch (error) {
40 | console.log(error);
41 | setBrands({ data: undefined, loading: false, error: true });
42 | }
43 | };
44 | fetchBrands();
45 | getDataFromDB();
46 | }, []);
47 |
48 | // get data from DB
49 | const getDataFromDB = () => {
50 | let productList = [];
51 | let accessoryList = [];
52 | for (let index = 0; index < _Items.length; index++) {
53 | if (_Items[index].category == 'product') {
54 | productList.push(_Items[index]);
55 | } else if (_Items[index].category == 'accessory') {
56 | accessoryList.push(_Items[index]);
57 | }
58 | }
59 | setProducts(productList);
60 | };
61 |
62 | return (
63 |
70 |
71 |
72 |
80 |
81 |
82 |
83 |
84 |
92 |
100 | {products.map((data) => {
101 | return (
102 | null}
106 | />
107 | );
108 | })}
109 |
110 |
111 |
112 |
113 |
119 |
127 | {products.map((data) => {
128 | return (
129 | null}
133 | />
134 | );
135 | })}
136 |
137 |
138 |
139 |
140 |
147 |
155 | {products.map((data) => {
156 | return (
157 | null}
161 | />
162 | );
163 | })}
164 |
165 |
166 |
167 |
175 |
182 | Sell pre-loved clothes
183 |
184 |
185 |
192 |
199 | completely free!
200 |
201 |
202 | {/* Next Button */}
203 |
212 | navigation.navigate('LogIn')}
214 | style={{
215 | flexDirection: 'row',
216 | alignItems: 'center',
217 | justifyContent: 'center',
218 | backgroundColor: COLOURS.purple,
219 | borderRadius: 30,
220 | marginHorizontal: '10%',
221 | width: '80%',
222 | height: '3rem'
223 | }}
224 | activeOpacity={0.5}>
225 |
233 | Next
234 |
235 |
243 |
244 |
245 | {/* Ignore Text */}
246 |
254 | navigation.navigate('HomeTabs')}
256 | style={{
257 | fontSize: 16,
258 | color: COLOURS.black,
259 | fontWeight: '500',
260 | }}
261 | >
262 | Ignore
263 |
264 |
265 | {brands.loading && (
266 |
267 | Caricamento...
268 |
269 | )}
270 |
271 |
272 | );
273 | };
274 |
275 | export default OnBoarding;
276 |
--------------------------------------------------------------------------------
/screens/LogIn.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { View, Text, Image, Button, StatusBar, ScrollView, TouchableOpacity, TextInput } from 'react-native';
3 | import { COLOURS, _Items } from '../database/Database';
4 | import Ionicons from 'react-native-vector-icons/Ionicons';
5 | import { MainStackScreenProps } from '../router/routes';
6 | // import { AppleButton, appleAuth } from '@invertase/react-native-apple-authentication';
7 |
8 | // import auth from '@react-native-firebase/auth';
9 | // import { LoginManager, AccessToken } from 'react-native-fbsdk-next';
10 | // import { GoogleSignin, GoogleSigninButton } from '@react-native-google-signin/google-signin';
11 | // import firebase from '../firebaseConfig';
12 | // import * as Crypto from "expo-crypto";
13 | // import * as AppleAuthentication from "expo-apple-authentication";
14 |
15 | // GoogleSignin.configure({
16 | // webClientId: '1064351666274-6o7vm84q9bab6upvs0vvhqg70ltuio24.apps.googleusercontent.com',
17 | // offlineAccess: true
18 | // });
19 |
20 | // async function onAppleButtonPress() {
21 | // // Start the sign-in request
22 | // const appleAuthRequestResponse = await appleAuth.performRequest({
23 | // requestedOperation: appleAuth.Operation.LOGIN,
24 | // requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
25 | // });
26 |
27 | // // Ensure Apple returned a user identityToken
28 | // if (!appleAuthRequestResponse.identityToken) {
29 | // throw new Error('Apple Sign-In failed - no identify token returned');
30 | // }
31 |
32 | // // Create a Firebase credential from the response
33 | // const { identityToken, nonce } = appleAuthRequestResponse;
34 | // const appleCredential = auth.AppleAuthProvider.credential(identityToken, nonce);
35 |
36 | // // Sign the user in with the credential
37 | // return auth().signInWithCredential(appleCredential);
38 | // }
39 |
40 | // async function onFacebookButtonPress() {
41 | // // Attempt login with permissions
42 | // const result = await LoginManager.logInWithPermissions(['public_profile', 'email']);
43 |
44 | // if (result.isCancelled) {
45 | // throw 'User cancelled the login process';
46 | // }
47 |
48 | // // Once signed in, get the users AccesToken
49 | // const data = await AccessToken.getCurrentAccessToken();
50 |
51 | // if (!data) {
52 | // throw 'Something went wrong obtaining access token';
53 | // }
54 |
55 | // // Create a Firebase credential with the AccessToken
56 | // const facebookCredential = auth.FacebookAuthProvider.credential(data.accessToken);
57 |
58 | // // Sign-in the user with the credential
59 | // return auth().signInWithCredential(facebookCredential);
60 | // }
61 |
62 | // async function onGoogleButtonPress () {
63 | // // Get the users ID token
64 | // const { idToken, accessToken } = await GoogleSignin.signIn();
65 |
66 | // // Create a Google credential with the token
67 | // const googleCredential = auth.GoogleAuthProvider.credential(idToken, accessToken);
68 |
69 | // // Sign-in the user with the credential
70 | // return auth().signInWithCredential(googleCredential);
71 | // }
72 |
73 | // const loginWithApple = async () => {
74 | // const csrf = Math.random().toString(36).substring(2, 15);
75 | // const nonce = Math.random().toString(36).substring(2, 10);
76 | // const hashedNonce = await Crypto.digestStringAsync(
77 | // Crypto.CryptoDigestAlgorithm.SHA256, nonce);
78 | // const appleCredential = await AppleAuthentication.signInAsync({
79 | // requestedScopes: [
80 | // AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
81 | // AppleAuthentication.AppleAuthenticationScope.EMAIL
82 | // ],
83 | // state: csrf,
84 | // nonce: hashedNonce
85 | // });
86 | // const { identityToken, email, state } = appleCredential;
87 | // }
88 |
89 | // const sendVerification = (phoneNumber: string, recaptchaVerifier: any, setVerificationId: any) => {
90 |
91 | // const phoneProvider = new firebase.auth().PhoneAuthProvider();
92 | // phoneProvider
93 | // .verifyPhoneNumber(phoneNumber, recaptchaVerifier.current)
94 | // .then(setVerificationId);
95 | // };
96 |
97 | // Function to be called when confirming the verification code that we received
98 | // from Firebase via SMS
99 | // const confirmCode = (verificationId: string, code: string) => {
100 | // const credential = firebase.auth.PhoneAuthProvider.credential(
101 | // verificationId,
102 | // code
103 | // );
104 | // firebase.auth()
105 | // .signInWithCredential(credential)
106 | // .then((result: any) => {
107 | // // Do something with the results here
108 | // console.log(result);
109 | // });
110 | // }
111 |
112 | const LogIn = ({ navigation }: MainStackScreenProps<'LogIn'>) => {
113 |
114 | return (
115 |
123 | {/* Back Button */}
124 |
131 | navigation.navigate('OnBoarding')}
133 | name="arrow-back-outline"
134 | size={36}
135 | style={{
136 | color: COLOURS.black
137 | }}
138 | />
139 |
140 | {/* Welcome Text */}
141 |
149 |
156 | Welcome!
157 |
158 |
159 |
160 | {/* Email Input */}
161 |
170 |
180 |
181 |
182 |
183 |
184 | {/* Log in / Sign up */}
185 |
193 | navigation.navigate('HomeTabs')}
195 | style={{
196 | flexDirection: 'row',
197 | alignItems: 'center',
198 | justifyContent: 'center',
199 | backgroundColor: COLOURS.purple,
200 | borderRadius: 30,
201 | width: '40%',
202 | height: '3rem'
203 | }}
204 | activeOpacity={0.5}>
205 |
213 | Log in
214 |
215 |
216 |
217 | navigation.navigate('HomeTabs')}
219 | style={{
220 | flexDirection: 'row',
221 | alignItems: 'center',
222 | justifyContent: 'center',
223 | backgroundColor: COLOURS.purple,
224 | borderRadius: 30,
225 | width: '40%',
226 | height: '3rem'
227 | }}
228 | activeOpacity={0.5}>
229 |
237 | Sign up
238 |
239 |
240 |
241 | {/* Or Text */}
242 |
250 |
257 | or
258 |
259 |
260 | {/* Icons */}
261 |
270 |
275 |
276 | {/* onAppleButtonPress().then(() => navigation.navigate('HomeTabs'))}
284 | /> */}
285 | onAppleButtonPress().then(() => navigation.navigate('HomeTabs'))}
289 | />
290 |
291 | {/* */}
298 | onGoogleButtonPress().then(() => navigation.navigate('HomeTabs'))}
302 | />
303 | onFacebookButtonPress().then(() => navigation.navigate('HomeTabs'))}
307 | />
308 |
309 |
310 | {/* Connect wallet */}
311 |
319 | navigation.navigate('Home')}
321 | style={{
322 | flexDirection: 'row',
323 | alignItems: 'center',
324 | justifyContent: 'center',
325 | backgroundColor: COLOURS.purple,
326 | borderRadius: 30,
327 | width: '100%',
328 | height: '3rem'
329 | }}
330 | activeOpacity={0.5}>
331 |
339 |
347 | Connect wallet
348 |
349 |
350 |
351 |
352 | );
353 | };
354 |
355 | export default LogIn;
356 |
--------------------------------------------------------------------------------
/screens/ProductInfo.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import {
3 | View,
4 | Text,
5 | StatusBar,
6 | ScrollView,
7 | TouchableOpacity,
8 | FlatList,
9 | Image,
10 | Dimensions,
11 | Animated,
12 | ToastAndroid,
13 | NativeSyntheticEvent,
14 | NativeScrollEvent,
15 | } from 'react-native';
16 | import { COLOURS, Items, UsersInfo } from '../database/Database';
17 | import Entypo from 'react-native-vector-icons/Entypo';
18 | import Ionicons from 'react-native-vector-icons/Ionicons';
19 | import { Avatar } from 'react-native-elements';
20 | import { MainStackScreenProps } from '../router/routes';
21 | import { Item } from '../models/Item';
22 |
23 | const ProductInfo = ({ route, navigation }: MainStackScreenProps<'Product'>) => {
24 | const { product } = route.params;
25 |
26 | //const [product, setProduct] = useState
- (undefined);
27 |
28 | const width = Dimensions.get('window').width;
29 |
30 | const height = Dimensions.get('window').height;
31 |
32 | const scrollX = new Animated.Value(0);
33 |
34 | let position = Animated.divide(scrollX, width);
35 |
36 | const [currentImage, setCurrentImage] = useState(0);
37 |
38 | const handleScroll = (event: NativeSyntheticEvent) => {
39 | const offset = event.nativeEvent.contentOffset.x;
40 | const currentIndex = Math.round(offset / width);
41 | setCurrentImage(currentIndex);
42 | };
43 |
44 | // useEffect(() => {
45 | // const getData = () => {
46 | // getDataFromDB();
47 | // };
48 | // navigation.addListener('focus', getData);
49 |
50 | // return navigation.removeListener('focus', getData);
51 | // }, [navigation]);
52 |
53 | //get product data by productId
54 |
55 | // const getDataFromDB = async () => {
56 | // for (let index = 0; index < Items.length; index++) {
57 | // if (Items[index].id === productId) {
58 | // await setProduct(Items[index]);
59 | // return;
60 | // }
61 | // }
62 | // };
63 |
64 | //product horizontal scroll product card
65 | const renderProduct = ({ item }: { item: string }) => {
66 | return (
67 |
75 |
83 |
84 | );
85 | };
86 |
87 | function makeAnOffert(id: string): void {
88 | console.log('make an offert');
89 | }
90 |
91 | function buyNow(id: string): void {
92 | console.log('buy now');
93 | }
94 |
95 | return (
96 |
104 |
105 |
106 |
114 |
123 | navigation.goBack()}>
124 |
134 |
135 |
136 | {/*
146 |
147 | {currentImage + 1}/{Object(product.productImageList).length}
148 |
149 | */}
150 |
151 |
164 |
174 | {/* {product.productImageList
175 | ? product.productImageList.map((data, index) => {
176 | let opacity = position.interpolate({
177 | inputRange: [index - 1, index, index + 1],
178 | outputRange: [0.2, 1, 0.2],
179 | extrapolate: "clamp",
180 | });
181 | return (
182 |
193 | );
194 | })
195 | : null} */}
196 |
197 |
198 | {/* SECONDA META */}
199 |
216 |
224 |
230 | Sold by:
231 |
232 |
233 | {/* INFO USER SECOND HALF */}
234 |
235 |
245 |
252 |
259 |
260 |
266 | {UsersInfo.name}
267 |
268 | {/* */}
274 |
275 |
276 |
277 |
296 |
297 | {/* END INFO USER */}
298 | {/* 222222222222222222222222222222222222222222222222222222222 */}
299 |
300 |
301 |
308 | {product.productName}
309 |
310 |
317 |
327 | {product.description}
328 |
329 |
338 | $ {product.productPrice}
339 |
340 |
341 |
342 |
343 |
351 |
352 | {/* 33333333333333333333333333333333333333333333 */}
353 |
362 | makeAnOffert(product.id)}
364 | style={{
365 | backgroundColor: COLOURS.white,
366 | borderWidth: 1,
367 | borderRadius: 50,
368 | justifyContent: 'center',
369 | alignItems: 'center',
370 | padding: '3%',
371 | width: '45%',
372 | }}
373 | >
374 |
380 | Make an offert
381 |
382 |
383 |
384 | buyNow(product.id)}
386 | style={{
387 | backgroundColor: COLOURS.lighterPurple,
388 | borderRadius: 50,
389 | flexDirection: 'row',
390 | justifyContent: 'space-around',
391 | alignItems: 'center',
392 | padding: '3%',
393 | width: '45%',
394 | }}
395 | >
396 |
403 |
404 |
412 | Buy Now
413 |
414 |
415 |
416 |
417 |
423 |
424 |
430 | Description:
431 |
432 |
433 |
434 |
441 | {product.description}
442 |
443 |
444 |
445 |
446 |
447 | );
448 | };
449 |
450 | export default ProductInfo;
451 |
--------------------------------------------------------------------------------
/database/Database.ts:
--------------------------------------------------------------------------------
1 | import { Item } from '../models/Item';
2 |
3 | export const COLOURS = {
4 | white: '#ffffff',
5 | black: '#000000',
6 | lighterPurple: '#933FE6',
7 | lightGray: '#999999',
8 | paleGrey: '#F0F3F8',
9 | darkGrey: '#262626',
10 | charcoalGrey: '#676767',
11 | silver: '#B3B3B3',
12 | golden: '#FFD02C',
13 | purple: '#933FE7'
14 | };
15 |
16 | export const Categorys = [
17 | {
18 | label: 'cat-1',
19 | value: 'cat-1',
20 | },
21 | {
22 | label: 'cat-2',
23 | value: 'cat-2',
24 | },
25 | ];
26 |
27 | export const SearchCategory = [
28 | {
29 | id: 1,
30 | name: 'Clothing',
31 | icon: 'shirt-outline',
32 | },
33 | {
34 | id: 2,
35 | name: 'Games',
36 | icon: 'game-controller-outline',
37 | },
38 | {
39 | id: 3,
40 | name: 'Entertainment',
41 | icon: 'tv-outline',
42 | },
43 | {
44 | id: 4,
45 | name: 'Home',
46 | icon: 'home-outline',
47 | },
48 | {
49 | id: 5,
50 | name: 'Green',
51 | icon: 'leaf-outline',
52 | },
53 | {
54 | id: 6,
55 | name: 'Technology',
56 | icon: 'headset-outline',
57 | },
58 | ];
59 |
60 | export const Brands = [
61 | {
62 | id: 1,
63 | name: 'brand_one',
64 | },
65 | {
66 | id: 2,
67 | name: 'brand_two',
68 | },
69 | {
70 | id: 3,
71 | name: 'brand_three',
72 | },
73 | {
74 | id: 4,
75 | name: 'brand_four',
76 | },
77 | {
78 | id: 5,
79 | name: 'brand_five',
80 | },
81 | {
82 | id: 6,
83 | name: 'brand_six',
84 | },
85 | ];
86 |
87 | export const Items: Item[] = [
88 | {
89 | id: '1',
90 | category: 'product',
91 | productName: 'MI Super Bass Bluetooth Wireless Headphones',
92 | productPrice: 1799,
93 | description:
94 | 'Up to 20 hours battery life | Super powerful Bass | 40mm dynamic driver | Pressure less ear muffs | Bluetooth 5.0 | Voice control',
95 | detail: 36,
96 | offPercentage: 10,
97 | productImage: require('./images/products/Mi1.png'),
98 | likes: 12,
99 | productImageList: [
100 | require('./images/products/Mi1.png'),
101 | require('./images/products/Mi2.png'),
102 | require('./images/products/Mi3.png'),
103 | ],
104 | },
105 | {
106 | id: '2',
107 | category: 'product',
108 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
109 | productPrice: 1499,
110 | description:
111 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
112 | detail: 44,
113 | productImage: require('./images/products/boat1.png'),
114 | likes: 0,
115 | productImageList: [
116 | require('./images/products/boat1.png'),
117 | require('./images/products/boat2.png'),
118 | require('./images/products/boat3.png'),
119 | ],
120 | },
121 | {
122 | id: '3',
123 | category: 'accessory',
124 | productName: 'boAt Airdopes 441',
125 | productPrice: 1999,
126 | description:
127 | 'Bluetooth: It has Bluetooth v5.0 with a range of 10m and is compatible with Android & iOS',
128 | detail: 34,
129 | offPercentage: 18,
130 | productImage: require('./images/accessories/boatairpods1.png'),
131 | likes: 55,
132 | productImageList: [
133 | require('./images/accessories/boatairpods1.png'),
134 | require('./images/accessories/boatairpods2.png'),
135 | require('./images/accessories/boatairpods3.png'),
136 | ],
137 | },
138 | {
139 | id: '4',
140 | category: 'accessory',
141 | productName: 'boAt Bassheads 242',
142 | productPrice: 399,
143 | description:
144 | 'Fly into your workouts with precise tones that inspire and energize your system with its HD sound, all the time.',
145 | detail: 32,
146 | productImage: require('./images/accessories/boatbassheads1.png'),
147 | likes: 657,
148 | productImageList: [
149 | require('./images/accessories/boatbassheads1.png'),
150 | require('./images/accessories/boatbassheads2.png'),
151 | require('./images/accessories/boatbassheads3.png'),
152 | ],
153 | },
154 | {
155 | id: '5',
156 | category: 'accessory',
157 | productName: 'boAt Rockerz 255 Pro+',
158 | productPrice: 1499,
159 | description:
160 | 'The unbeatable boAt signature sound shines through no matter what are you playing courtesy its 10mm drivers.',
161 | detail: 47,
162 | productImage: require('./images/accessories/boatrockerz1.png'),
163 | likes: 234,
164 | productImageList: [
165 | require('./images/accessories/boatrockerz1.png'),
166 | require('./images/accessories/boatrockerz2.png'),
167 | require('./images/accessories/boatrockerz3.png'),
168 | ],
169 | },
170 | {
171 | id: '6',
172 | userVendor: 'diletta.leotta@domain.com',
173 | category: 'accessory',
174 | productName: 'Boult Audio AirBass Propods TWS',
175 | productPrice: 1299,
176 | description:
177 | 'One Touch Control & Voice Assistant: With one multifunction button, you can play/pause, previous/next track and answer/hang-up calls.Voice assistant function lets you access siri/Google Assistant',
178 | detail: 31,
179 | productImage: require('./images/accessories/boultairbass1.png'),
180 | likes: 0,
181 | productImageList: [
182 | require('./images/accessories/boultairbass1.png'),
183 | require('./images/accessories/boultairbass2.png'),
184 | require('./images/accessories/boultairbass3.png'),
185 | ],
186 | },
187 | {
188 | id: '7',
189 | category: 'product',
190 | productName: 'MI Super Bass Bluetooth Wireless Headphones',
191 | productPrice: 1799,
192 | description:
193 | 'Up to 20 hours battery life | Super powerful Bass | 40mm dynamic driver | Pressure less ear muffs | Bluetooth 5.0 | Voice control',
194 | detail: 38,
195 | offPercentage: 32,
196 | productImage: require('./images/products/Mi1.png'),
197 | likes: 87,
198 | productImageList: [
199 | require('./images/products/Mi1.png'),
200 | require('./images/products/Mi2.png'),
201 | require('./images/products/Mi3.png'),
202 | ],
203 | },
204 | {
205 | id: '8',
206 | category: 'product',
207 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
208 | productPrice: 1499,
209 | description:
210 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
211 | detail: 38,
212 | productImage: require('./images/products/boat1.png'),
213 | likes: 66,
214 | productImageList: [
215 | require('./images/products/boat1.png'),
216 | require('./images/products/boat2.png'),
217 | require('./images/products/boat3.png'),
218 | ],
219 | },
220 | {
221 | id: '9',
222 | category: 'product',
223 | productName: 'MI Super Bass Bluetooth Wireless Headphones',
224 | productPrice: 1799,
225 | description:
226 | 'Up to 20 hours battery life | Super powerful Bass | 40mm dynamic driver | Pressure less ear muffs | Bluetooth 5.0 | Voice control',
227 | detail: 43,
228 | offPercentage: 5,
229 | productImage: require('./images/products/Mi1.png'),
230 | likes: 78,
231 | productImageList: [
232 | require('./images/products/Mi1.png'),
233 | require('./images/products/Mi2.png'),
234 | require('./images/products/Mi3.png'),
235 | ],
236 | },
237 | {
238 | id: '10',
239 | userVendor: 'diletta.leotta@domain.com',
240 | category: 'product',
241 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
242 | productPrice: 1499,
243 | description:
244 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
245 | detail: 45,
246 | productImage: require('./images/products/boat1.png'),
247 | likes: 11,
248 | productImageList: [
249 | require('./images/products/boat1.png'),
250 | require('./images/products/boat2.png'),
251 | require('./images/products/boat3.png'),
252 | ],
253 | },
254 | {
255 | id: '11',
256 | category: 'product',
257 | productName: 'MI Super Bass Bluetooth Wireless Headphones',
258 | productPrice: 1799,
259 | description:
260 | 'Up to 20 hours battery life | Super powerful Bass | 40mm dynamic driver | Pressure less ear muffs | Bluetooth 5.0 | Voice control',
261 | detail: 32,
262 | offPercentage: 15,
263 | productImage: require('./images/products/Mi1.png'),
264 | likes: 1,
265 | productImageList: [
266 | require('./images/products/Mi1.png'),
267 | require('./images/products/Mi2.png'),
268 | require('./images/products/Mi3.png'),
269 | ],
270 | },
271 | {
272 | id: '12',
273 | category: 'product',
274 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
275 | productPrice: 1499,
276 | description:
277 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
278 | detail: 34,
279 | productImage: require('./images/products/boat1.png'),
280 | likes: 0,
281 | productImageList: [
282 | require('./images/products/boat1.png'),
283 | require('./images/products/boat2.png'),
284 | require('./images/products/boat3.png'),
285 | ],
286 | },
287 | {
288 | id: '13',
289 | userVendor: 'diletta.leotta@domain.com',
290 | category: 'product',
291 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
292 | productPrice: 1499,
293 | description:
294 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
295 | detail: 34,
296 | productImage: require('./images/products/boat1.png'),
297 | likes: 0,
298 | productImageList: [require('./images/products/001.jpg')],
299 | },
300 | {
301 | id: '14',
302 | category: 'product',
303 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
304 | productPrice: 1499,
305 | description:
306 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
307 | detail: 34,
308 | productImage: require('./images/products/boat1.png'),
309 | likes: 0,
310 | productImageList: [require('./images/products/002.jpg')],
311 | },
312 | {
313 | id: '15',
314 | userVendor: 'diletta.leotta@domain.com',
315 | category: 'product',
316 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
317 | productPrice: 1499,
318 | description:
319 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
320 | detail: 34,
321 | productImage: require('./images/products/boat1.png'),
322 | likes: 0,
323 | productImageList: [require('./images/products/003.jpg')],
324 | },
325 | ];
326 |
327 | export const UsersInfo = {
328 | id: 1,
329 | name: 'Diletta',
330 | surname: 'Leotta',
331 | email: 'diletta.leotta@domain.com',
332 | source: require('./images/users/photo.png'),
333 | bio: 'Hey! Here to sell stuff that I forgot they exist.',
334 | starRating: 3.5,
335 | numberReviews: 41,
336 | };
337 |
338 | export const _Items: Item[] = [
339 | {
340 | id: '1',
341 | category: 'product',
342 | productName: 'MI Super Bass Bluetooth Wireless Headphones',
343 | productPrice: 1799,
344 | description:
345 | 'Up to 20 hours battery life | Super powerful Bass | 40mm dynamic driver | Pressure less ear muffs | Bluetooth 5.0 | Voice control',
346 | detail: 36,
347 | offPercentage: 10,
348 | productImage: require('./images/products/001.jpg'),
349 | likes: 12,
350 | productImageList: [
351 | require('./images/products/Mi1.png'),
352 | require('./images/products/Mi2.png'),
353 | require('./images/products/Mi3.png'),
354 | ],
355 | },
356 | {
357 | id: '2',
358 | category: 'product',
359 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
360 | productPrice: 1499,
361 | description:
362 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
363 | detail: 44,
364 | productImage: require('./images/products/002.jpg'),
365 | likes: 0,
366 | productImageList: [
367 | require('./images/products/boat1.png'),
368 | require('./images/products/boat2.png'),
369 | require('./images/products/boat3.png'),
370 | ],
371 | },
372 | {
373 | id: '3',
374 | category: 'accessory',
375 | productName: 'boAt Airdopes 441',
376 | productPrice: 1999,
377 | description:
378 | 'Bluetooth: It has Bluetooth v5.0 with a range of 10m and is compatible with Android & iOS',
379 | detail: 34,
380 | offPercentage: 18,
381 | productImage: require('./images/accessories/boatairpods1.png'),
382 | likes: 55,
383 | productImageList: [
384 | require('./images/accessories/boatairpods1.png'),
385 | require('./images/accessories/boatairpods2.png'),
386 | require('./images/accessories/boatairpods3.png'),
387 | ],
388 | },
389 | {
390 | id: '4',
391 | category: 'accessory',
392 | productName: 'boAt Bassheads 242',
393 | productPrice: 399,
394 | description:
395 | 'Fly into your workouts with precise tones that inspire and energize your system with its HD sound, all the time.',
396 | detail: 32,
397 | productImage: require('./images/accessories/boatbassheads1.png'),
398 | likes: 657,
399 | productImageList: [
400 | require('./images/accessories/boatbassheads1.png'),
401 | require('./images/accessories/boatbassheads2.png'),
402 | require('./images/accessories/boatbassheads3.png'),
403 | ],
404 | },
405 | {
406 | id: '5',
407 | category: 'accessory',
408 | productName: 'boAt Rockerz 255 Pro+',
409 | productPrice: 1499,
410 | description:
411 | 'The unbeatable boAt signature sound shines through no matter what are you playing courtesy its 10mm drivers.',
412 | detail: 47,
413 | productImage: require('./images/accessories/boatrockerz1.png'),
414 | likes: 234,
415 | productImageList: [
416 | require('./images/accessories/boatrockerz1.png'),
417 | require('./images/accessories/boatrockerz2.png'),
418 | require('./images/accessories/boatrockerz3.png'),
419 | ],
420 | },
421 | {
422 | id: '6',
423 | userVendor: 'diletta.leotta@domain.com',
424 | category: 'accessory',
425 | productName: 'Boult Audio AirBass Propods TWS',
426 | productPrice: 1299,
427 | description:
428 | 'One Touch Control & Voice Assistant: With one multifunction button, you can play/pause, previous/next track and answer/hang-up calls.Voice assistant function lets you access siri/Google Assistant',
429 | detail: 31,
430 | productImage: require('./images/accessories/boultairbass1.png'),
431 | likes: 0,
432 | productImageList: [
433 | require('./images/accessories/boultairbass1.png'),
434 | require('./images/accessories/boultairbass2.png'),
435 | require('./images/accessories/boultairbass3.png'),
436 | ],
437 | },
438 | {
439 | id: '7',
440 | category: 'product',
441 | productName: 'MI Super Bass Bluetooth Wireless Headphones',
442 | productPrice: 1799,
443 | description:
444 | 'Up to 20 hours battery life | Super powerful Bass | 40mm dynamic driver | Pressure less ear muffs | Bluetooth 5.0 | Voice control',
445 | detail: 38,
446 | offPercentage: 32,
447 | productImage: require('./images/products/001.jpg'),
448 | likes: 87,
449 | productImageList: [
450 | require('./images/products/Mi1.png'),
451 | require('./images/products/Mi2.png'),
452 | require('./images/products/Mi3.png'),
453 | ],
454 | },
455 | {
456 | id: '8',
457 | category: 'product',
458 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
459 | productPrice: 1499,
460 | description:
461 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
462 | detail: 38,
463 | productImage: require('./images/products/002.jpg'),
464 | likes: 66,
465 | productImageList: [
466 | require('./images/products/boat1.png'),
467 | require('./images/products/boat2.png'),
468 | require('./images/products/boat3.png'),
469 | ],
470 | },
471 | {
472 | id: '9',
473 | category: 'product',
474 | productName: 'MI Super Bass Bluetooth Wireless Headphones',
475 | productPrice: 1799,
476 | description:
477 | 'Up to 20 hours battery life | Super powerful Bass | 40mm dynamic driver | Pressure less ear muffs | Bluetooth 5.0 | Voice control',
478 | detail: 43,
479 | offPercentage: 5,
480 | productImage: require('./images/products/003.jpg'),
481 | likes: 78,
482 | productImageList: [
483 | require('./images/products/Mi1.png'),
484 | require('./images/products/Mi2.png'),
485 | require('./images/products/Mi3.png'),
486 | ],
487 | },
488 | {
489 | id: '10',
490 | userVendor: 'diletta.leotta@domain.com',
491 | category: 'product',
492 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
493 | productPrice: 1499,
494 | description:
495 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
496 | detail: 45,
497 | productImage: require('./images/products/001.jpg'),
498 | likes: 11,
499 | productImageList: [
500 | require('./images/products/boat1.png'),
501 | require('./images/products/boat2.png'),
502 | require('./images/products/boat3.png'),
503 | ],
504 | },
505 | {
506 | id: '11',
507 | category: 'product',
508 | productName: 'MI Super Bass Bluetooth Wireless Headphones',
509 | productPrice: 1799,
510 | description:
511 | 'Up to 20 hours battery life | Super powerful Bass | 40mm dynamic driver | Pressure less ear muffs | Bluetooth 5.0 | Voice control',
512 | detail: 32,
513 | offPercentage: 15,
514 | productImage: require('./images/products/002.jpg'),
515 | likes: 1,
516 | productImageList: [
517 | require('./images/products/Mi1.png'),
518 | require('./images/products/Mi2.png'),
519 | require('./images/products/Mi3.png'),
520 | ],
521 | },
522 | {
523 | id: '12',
524 | category: 'product',
525 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
526 | productPrice: 1499,
527 | description:
528 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
529 | detail: 34,
530 | productImage: require('./images/products/003.jpg'),
531 | likes: 0,
532 | productImageList: [
533 | require('./images/products/boat1.png'),
534 | require('./images/products/boat2.png'),
535 | require('./images/products/boat3.png'),
536 | ],
537 | },
538 | {
539 | id: '13',
540 | userVendor: 'diletta.leotta@domain.com',
541 | category: 'product',
542 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
543 | productPrice: 1499,
544 | description:
545 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
546 | detail: 34,
547 | productImage: require('./images/products/boat1.png'),
548 | likes: 0,
549 | productImageList: [require('./images/products/001.jpg')],
550 | },
551 | {
552 | id: '14',
553 | category: 'product',
554 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
555 | productPrice: 1499,
556 | description:
557 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
558 | detail: 34,
559 | productImage: require('./images/products/boat1.png'),
560 | likes: 0,
561 | productImageList: [require('./images/products/002.jpg')],
562 | },
563 | {
564 | id: '15',
565 | userVendor: 'diletta.leotta@domain.com',
566 | category: 'product',
567 | productName: 'boAt Rockerz 450 Bluetooth Headphone',
568 | productPrice: 1499,
569 | description:
570 | 'boAt Rockerz 450 M is an on-ear wireless headset that has been ergonomically designed to meet the needs of music lovers.',
571 | detail: 34,
572 | productImage: require('./images/products/boat1.png'),
573 | likes: 0,
574 | productImageList: [require('./images/products/003.jpg')],
575 | },
576 | ];
577 |
--------------------------------------------------------------------------------