Merge pull request #3 from Ninjas-Code-official/feature1

Feature1 (Enatega single vendor Customer App Upgrade successfully)
This commit is contained in:
Sharan 2023-03-29 12:48:58 +05:00 committed by GitHub
commit 4370f69272
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
274 changed files with 59084 additions and 47164 deletions

View File

@ -0,0 +1,8 @@
NODE_PATH=./src
SKIP_PREFLIGHT_CHECK=true
REACT_APP_CLOUDINARY_UPLOAD_URL = https://api.cloudinary.com/v1_1/dimjm4ald/image/upload
REACT_APP_SERVER_URL = http://localhost:8000/
REACT_APP_WS_SERVER_URL = ws://localhost:8000/
REACT_APP_CLOUDINARY_CATEGORY = hmtkg7s5
REACT_APP_CLOUDINARY_FOOD = wdgvyas8
REACT_APP_ENV = “dev”

View File

@ -0,0 +1,10 @@
All variables should be appended by REACT_APP_
NODE_PATH=./src
SKIP_PREFLIGHT_CHECK=true
REACT_APP_CLOUDINARY_UPLOAD_URL = <Cloudinary URL>
REACT_APP_SERVER_URL = <Your SERVER URL>
REACT_APP_WS_SERVER_URL = <SERVER URL with appending "ws" for local or "wss" for remote>
REACT_APP_CLOUDINARY_CATEGORY = <Folder ID from Cloudinary>
REACT_APP_CLOUDINARY_FOOD = <Folder ID from Cloudinary>
REACT_APP_ENV = <Alias that is mentioned in package.json script>

View File

@ -0,0 +1,8 @@
NODE_PATH=./src
SKIP_PREFLIGHT_CHECK=true
REACT_APP_CLOUDINARY_UPLOAD_URL = https://api.cloudinary.com/v1_1/dimjm4ald/image/upload
REACT_APP_SERVER_URL = https://prod-enatega-single-api.herokuapp.com/
REACT_APP_WS_SERVER_URL = wss://prod-enatega-single-api.herokuapp.com/
REACT_APP_CLOUDINARY_CATEGORY = hmtkg7s5
REACT_APP_CLOUDINARY_FOOD = wdgvyas8
REACT_APP_ENV = "prod"

View File

@ -0,0 +1,8 @@
NODE_PATH=./src
SKIP_PREFLIGHT_CHECK=true
REACT_APP_CLOUDINARY_UPLOAD_URL = https://api.cloudinary.com/v1_1/dimjm4ald/image/upload
REACT_APP_SERVER_URL = https://staging-enatega-single-api.herokuapp.com/
REACT_APP_WS_SERVER_URL = wss://staging-enatega-single-api.herokuapp.com/
REACT_APP_CLOUDINARY_CATEGORY = hmtkg7s5
REACT_APP_CLOUDINARY_FOOD = wdgvyas8
REACT_APP_ENV = “staging”

View File

@ -0,0 +1,5 @@
src/assets/*
public/*
./node_modules
./patches
./history

View File

@ -0,0 +1,28 @@
{
"env": {
"browser": true,
"es6": true
},
"extends": [
"plugin:react/recommended",
"standard"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 11,
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"space-before-function-paren": ["error", "never"],
"react/prop-types": 0
}
}

4
Admin Dashboard/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/build
/node_modules
package-lock.json
yarn.lock

View File

@ -3,11 +3,11 @@ import { Route, Switch } from 'react-router-dom'
// reactstrap components // reactstrap components
import { Container } from 'reactstrap' import { Container } from 'reactstrap'
// core components // core components
import AdminNavbar from 'components/Navbars/AdminNavbar.jsx' import AdminNavbar from '../components/Navbars/AdminNavbar.jsx'
import AdminFooter from 'components/Footers/AdminFooter.jsx' import AdminFooter from '../components/Footers/AdminFooter.jsx'
import Sidebar from 'components/Sidebar/Sidebar.jsx' import Sidebar from '../components/Sidebar/Sidebar.jsx'
import routes from 'routes.js' import routes from './../routes.js'
const Admin = props => { const Admin = props => {
var divRef = useRef(null) var divRef = useRef(null)
@ -49,7 +49,7 @@ const Admin = props => {
routes={routes} routes={routes}
logo={{ logo={{
innerLink: '/admin/dashboard', innerLink: '/admin/dashboard',
imgSrc: require('assets/img/brand/logo.png'), imgSrc: require('../assets/img/brand/logo.png'),
imgAlt: '...' imgAlt: '...'
}} }}
/> />

View File

@ -4,10 +4,10 @@ import { Route, Switch } from 'react-router-dom'
import { Container, Row } from 'reactstrap' import { Container, Row } from 'reactstrap'
// core components // core components
import AuthNavbar from 'components/Navbars/AuthNavbar.jsx' import AuthNavbar from '../components/Navbars/AuthNavbar.jsx'
import AuthFooter from 'components/Footers/AuthFooter.jsx' import AuthFooter from '../components/Footers/AuthFooter.jsx'
import routes from 'routes.js' import routes from '../routes.js'
function Auth(props) { function Auth(props) {
useEffect(() => { useEffect(() => {

View File

@ -1,7 +1,7 @@
/* eslint-disable react/display-name */ /* eslint-disable react/display-name */
import React, { useState } from 'react' import React, { useState } from 'react'
import { Container, Badge, Row, Card, Modal } from 'reactstrap' import { Container, Badge, Row, Card, Modal } from 'reactstrap'
import Header from 'components/Headers/Header.jsx' import Header from '../components/Headers/Header.jsx'
import AddonComponent from '../components/Addon/Addon' import AddonComponent from '../components/Addon/Addon'
import { addons, deleteAddon } from '../apollo/server' import { addons, deleteAddon } from '../apollo/server'
import CustomLoader from '../components/Loader/CustomLoader' import CustomLoader from '../components/Loader/CustomLoader'

View File

@ -8,7 +8,7 @@ import CustomLoader from '../components/Loader/CustomLoader'
// reactstrap components // reactstrap components
import { Badge, Card, Container, Row, Modal } from 'reactstrap' import { Badge, Card, Container, Row, Modal } from 'reactstrap'
// core components // core components
import Header from 'components/Headers/Header.jsx' import Header from '../components/Headers/Header.jsx'
import { categories, deleteCategory, getFoods } from '../apollo/server' import { categories, deleteCategory, getFoods } from '../apollo/server'
import DataTable from 'react-data-table-component' import DataTable from 'react-data-table-component'
import orderBy from 'lodash/orderBy' import orderBy from 'lodash/orderBy'

View File

@ -3,7 +3,7 @@ import { withTranslation } from 'react-i18next'
import { Container } from 'reactstrap' import { Container } from 'reactstrap'
import { Query } from 'react-apollo' import { Query } from 'react-apollo'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import Header from 'components/Headers/Header.jsx' import Header from '../components/Headers/Header.jsx'
import { getConfiguration } from '../apollo/server' import { getConfiguration } from '../apollo/server'
import OrderConfiguration from '../components/Configuration/Order/Order' import OrderConfiguration from '../components/Configuration/Order/Order'
import EmailConfiguration from '../components/Configuration/Email/Email' import EmailConfiguration from '../components/Configuration/Email/Email'

View File

@ -8,7 +8,7 @@ import CouponComponent from '../components/Coupon/Coupon'
import { Badge, Card, Container, Row, Modal } from 'reactstrap' import { Badge, Card, Container, Row, Modal } from 'reactstrap'
// core components // core components
import Header from 'components/Headers/Header.jsx' import Header from '../components/Headers/Header.jsx'
import CustomLoader from '../components/Loader/CustomLoader' import CustomLoader from '../components/Loader/CustomLoader'
import DataTable from 'react-data-table-component' import DataTable from 'react-data-table-component'
import orderBy from 'lodash/orderBy' import orderBy from 'lodash/orderBy'

View File

@ -16,7 +16,7 @@ import {
Col Col
} from 'reactstrap' } from 'reactstrap'
import Header from 'components/Headers/Header.jsx' import Header from '../components/Headers/Header.jsx'
import { Query } from 'react-apollo' import { Query } from 'react-apollo'
import { import {
getDashboardTotal, getDashboardTotal,

View File

@ -6,7 +6,7 @@ import { withTranslation } from 'react-i18next'
// reactstrap components // reactstrap components
import { Badge, Card, Container, Row, Media, Modal } from 'reactstrap' import { Badge, Card, Container, Row, Media, Modal } from 'reactstrap'
// core components // core components
import Header from 'components/Headers/Header.jsx' import Header from '../components/Headers/Header.jsx'
import { getFoods, deleteFood } from '../apollo/server' import { getFoods, deleteFood } from '../apollo/server'
import FoodComponent from '../components/Food/Food' import FoodComponent from '../components/Food/Food'
import CustomLoader from '../components/Loader/CustomLoader' import CustomLoader from '../components/Loader/CustomLoader'

View File

@ -2,7 +2,7 @@ import React, { useState } from 'react'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import { Mutation } from 'react-apollo' import { Mutation } from 'react-apollo'
import { withTranslation } from 'react-i18next' import { withTranslation } from 'react-i18next'
import Header from 'components/Headers/Header.jsx' import Header from '../components/Headers/Header.jsx'
import { sendNotificationUser } from '../apollo/server' import { sendNotificationUser } from '../apollo/server'
import CustomLoader from '../components/Loader/CustomLoader' import CustomLoader from '../components/Loader/CustomLoader'
import { validateFunc } from '../constraints/constraints' import { validateFunc } from '../constraints/constraints'

View File

@ -1,7 +1,7 @@
/* eslint-disable react/display-name */ /* eslint-disable react/display-name */
import React, { useState } from 'react' import React, { useState } from 'react'
import { Badge, Container, Row, Card, Modal } from 'reactstrap' import { Badge, Container, Row, Card, Modal } from 'reactstrap'
import Header from 'components/Headers/Header.jsx' import Header from '../components/Headers/Header.jsx'
import OptionComponent from '../components/Option/Option' import OptionComponent from '../components/Option/Option'
import CustomLoader from '../components/Loader/CustomLoader' import CustomLoader from '../components/Loader/CustomLoader'
import DataTable from 'react-data-table-component' import DataTable from 'react-data-table-component'

View File

@ -3,7 +3,7 @@ import { withTranslation } from 'react-i18next'
import { Container, Row, Card, Modal } from 'reactstrap' import { Container, Row, Card, Modal } from 'reactstrap'
import OrderComponent from '../components/Order/Order' import OrderComponent from '../components/Order/Order'
import OrdersData from '../components/Order/OrderData' import OrdersData from '../components/Order/OrderData'
import Header from 'components/Headers/Header.jsx' import Header from '../components/Headers/Header.jsx'
import { Query, compose, withApollo } from 'react-apollo' import { Query, compose, withApollo } from 'react-apollo'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import { getOrders } from '../apollo/server' import { getOrders } from '../apollo/server'

View File

@ -2,7 +2,7 @@
import React from 'react' import React from 'react'
import { withTranslation } from 'react-i18next' import { withTranslation } from 'react-i18next'
import { Container, Row, Card } from 'reactstrap' import { Container, Row, Card } from 'reactstrap'
import Header from 'components/Headers/Header.jsx' import Header from '../components/Headers/Header.jsx'
import CustomLoader from '../components/Loader/CustomLoader' import CustomLoader from '../components/Loader/CustomLoader'
import { Query, compose, withApollo } from 'react-apollo' import { Query, compose, withApollo } from 'react-apollo'
import gql from 'graphql-tag' import gql from 'graphql-tag'

1
Customer App/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/node_modules

1
Customer App/.npmrc Normal file
View File

@ -0,0 +1 @@
legacy-peer-deps=true

View File

@ -47,6 +47,7 @@ export default function App() {
setupClient(client) setupClient(client)
await i18n.initAsync() await i18n.initAsync()
// load fonts
await Font.loadAsync({ await Font.loadAsync({
Poppin300: require('./src/assets/font/Poppin/Poppins-Light.ttf'), Poppin300: require('./src/assets/font/Poppin/Poppins-Light.ttf'),
Poppin400: require('./src/assets/font/Poppin/Poppins-Regular.ttf'), Poppin400: require('./src/assets/font/Poppin/Poppins-Regular.ttf'),

View File

@ -2,6 +2,7 @@
"expo": { "expo": {
"name": "Enatega", "name": "Enatega",
"version": "1.0.16", "version": "1.0.16",
"scheme": "enategasinglevendor",
"description": "Enatega is a starter kit food ordering app built in React Native using Expo for IOS and Android. It's made keeping good aesthetics in mind as well keeping the best coding practices in mind. Its fully customisable to easily help you in your next food delivery project. https://market.nativebase.io/view/react-native-food-delivery-backend-app", "description": "Enatega is a starter kit food ordering app built in React Native using Expo for IOS and Android. It's made keeping good aesthetics in mind as well keeping the best coding practices in mind. Its fully customisable to easily help you in your next food delivery project. https://market.nativebase.io/view/react-native-food-delivery-backend-app",
"slug": "enategasinglevendor", "slug": "enategasinglevendor",
"privacy": "public", "privacy": "public",
@ -33,7 +34,8 @@
}, },
"usesAppleSignIn": true, "usesAppleSignIn": true,
"infoPlist": { "infoPlist": {
"NSLocationWhenInUseUsageDescription": "This app uses the location to determine the delivery address for your orders." "NSLocationWhenInUseUsageDescription": "This app uses the location to determine the delivery address for your orders.",
"NSUserTrackingUsageDescription": "Allow this app to collect app-related data that can be used for tracking you or your device."
} }
}, },
"notification": { "notification": {
@ -47,7 +49,6 @@
"versionCode": 22, "versionCode": 22,
"package": "com.enatega.vendor", "package": "com.enatega.vendor",
"googleServicesFile": "./google-services-prod.json", "googleServicesFile": "./google-services-prod.json",
"useNextNotificationsApi": true,
"config": { "config": {
"googleMaps": { "googleMaps": {
"apiKey": "" "apiKey": ""
@ -72,6 +73,11 @@
], ],
"facebookScheme": "fb3017447961609878", "facebookScheme": "fb3017447961609878",
"facebookAppId": "3017447961609878", "facebookAppId": "3017447961609878",
"facebookDisplayName": "Food delivery" "facebookDisplayName": "Food delivery",
"extra": {
"eas": {
"projectId": "0b51ea6b-d9fd-48e2-9480-54149ca73a7a"
}
}
} }
} }

View File

@ -1,7 +1,10 @@
module.exports = function(api) { module.exports = function (api) {
api.cache(true) api.cache(true);
return { return {
presets: ['babel-preset-expo'], presets: ["babel-preset-expo"],
plugins: ['react-native-reanimated/plugin'] plugins: [
} "react-native-reanimated/plugin",
} "@babel/plugin-syntax-dynamic-import",
],
};
};

36
Customer App/eas.json Normal file
View File

@ -0,0 +1,36 @@
{
"cli": {
"version": ">= 3.8.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"android": {
"buildType": "apk"
},
"ios": {
"resourceClass": "m-medium"
}
},
"preview": {
"distribution": "internal",
"ios": {
"resourceClass": "m-medium"
}
},
"production": {
"developmentClient": false,
"releaseChannel": "production",
"android": {
"buildType": "apk"
},
"ios": {
"resourceClass": "m-medium"
}
}
},
"submit": {
"production": {}
}
}

View File

@ -3,54 +3,48 @@
* path: '/environment.js' (root of your project) * path: '/environment.js' (root of your project)
******************************/ ******************************/
import Constants from 'expo-constants' import Constants from "expo-constants";
const ENV = { const ENV = {
development: { development: {
GRAPHQL_URL: 'http://192.168.100.90:8000/graphql', GRAPHQL_URL: "http://10.97.28.88.90:8000/graphql",
WS_GRAPHQL_URL: 'ws://192.168.100.90:8000/graphql', WS_GRAPHQL_URL: "ws://10.97.28.88.90:8000/graphql",
SERVER_URL: 'http://192.168.100.90:8000/', // put / at the end of server url SERVER_URL: "http://10.97.28.88.90:8000/", // put / at the end of server url
IOS_CLIENT_ID_GOOGLE: IOS_CLIENT_ID_GOOGLE: "",
'', ANDROID_CLIENT_ID_GOOGLE: "",
ANDROID_CLIENT_ID_GOOGLE: FACEBOOK_APP_ID: "404956210315749",
'', AMPLITUDE_API_KEY: "",
FACEBOOK_APP_ID: '404956210315749', STRIPE_PUBLIC_KEY: "",
AMPLITUDE_API_KEY: '', STRIPE_IMAGE_URL: "http://10.97.28.88.90:8000/assets/images/logo.png",
STRIPE_PUBLIC_KEY: '', STRIPE_STORE_NAME: "Enatega",
STRIPE_IMAGE_URL: 'http://192.168.100.90:8000/assets/images/logo.png',
STRIPE_STORE_NAME: 'Enatega'
}, },
staging: { staging: {
GRAPHQL_URL: 'https://staging-enatega-single-api.herokuapp.com/graphql', GRAPHQL_URL: "https://staging-enatega-single-api.herokuapp.com/graphql",
WS_GRAPHQL_URL: 'wss://staging-enatega-single-api.herokuapp.com/graphql', WS_GRAPHQL_URL: "wss://staging-enatega-single-api.herokuapp.com/graphql",
SERVER_URL: 'https://staging-enatega-single-api.herokuapp.com/', // put / at the end of server url SERVER_URL: "https://staging-enatega-single-api.herokuapp.com/", // put / at the end of server url
IOS_CLIENT_ID_GOOGLE: IOS_CLIENT_ID_GOOGLE: "",
'', ANDROID_CLIENT_ID_GOOGLE: "",
ANDROID_CLIENT_ID_GOOGLE: FACEBOOK_APP_ID: "404956210315749",
'', AMPLITUDE_API_KEY: "",
FACEBOOK_APP_ID: '404956210315749', STRIPE_PUBLIC_KEY: "",
AMPLITUDE_API_KEY: '',
STRIPE_PUBLIC_KEY: '',
STRIPE_IMAGE_URL: STRIPE_IMAGE_URL:
'https://staging-enatega-single-api.herokuapp.com/assets/images/logo.png', "https://staging-enatega-single-api.herokuapp.com/assets/images/logo.png",
STRIPE_STORE_NAME: 'Enatega' STRIPE_STORE_NAME: "Enatega",
}, },
production: { production: {
GRAPHQL_URL: 'https://prod-enatega-single-api.herokuapp.com/graphql', GRAPHQL_URL: "https://prod-enatega-single-api.herokuapp.com/graphql",
WS_GRAPHQL_URL: 'wss://prod-enatega-single-api.herokuapp.com/graphql', WS_GRAPHQL_URL: "wss://prod-enatega-single-api.herokuapp.com/graphql",
SERVER_URL: 'https://prod-enatega-single-api.herokuapp.com/', // put / at the end of server url SERVER_URL: "https://prod-enatega-single-api.herokuapp.com/", // put / at the end of server url
IOS_CLIENT_ID_GOOGLE: IOS_CLIENT_ID_GOOGLE: "",
'', ANDROID_CLIENT_ID_GOOGLE: "",
ANDROID_CLIENT_ID_GOOGLE: FACEBOOK_APP_ID: "3017447961609878",
'', AMPLITUDE_API_KEY: "",
FACEBOOK_APP_ID: '3017447961609878', STRIPE_PUBLIC_KEY: "",
AMPLITUDE_API_KEY: '',
STRIPE_PUBLIC_KEY: '',
STRIPE_IMAGE_URL: STRIPE_IMAGE_URL:
'https://prod-enatega-single-api.herokuapp.com/assets/images/logo.png', "https://prod-enatega-single-api.herokuapp.com/assets/images/logo.png",
STRIPE_STORE_NAME: 'Enatega' STRIPE_STORE_NAME: "Enatega",
} },
} };
const getEnvVars = (env = Constants.manifest.releaseChannel) => { const getEnvVars = (env = Constants.manifest.releaseChannel) => {
// What is __DEV__ ? // What is __DEV__ ?
@ -58,14 +52,14 @@ const getEnvVars = (env = Constants.manifest.releaseChannel) => {
// __DEV__ is true when run locally, but false when published. // __DEV__ is true when run locally, but false when published.
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
if (__DEV__) { if (__DEV__) {
return ENV.development return ENV.development;
} else if (env === 'production') { } else if (env === "production") {
return ENV.production return ENV.production;
} else if (env === 'staging') { } else if (env === "staging") {
return ENV.staging return ENV.staging;
} else { } else {
return ENV.production return ENV.production;
} }
} };
export default getEnvVars export default getEnvVars;

8
Customer App/index.js Normal file
View File

@ -0,0 +1,8 @@
import { registerRootComponent } from 'expo';
import App from './App';
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in Expo Go or in a native build,
// the environment is set up appropriately
registerRootComponent(App);

View File

@ -0,0 +1,4 @@
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require('expo/metro-config');
module.exports = getDefaultConfig(__dirname);

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
{ {
"name": "enatega-full-app", "name": "enatega-full-app",
"version": "5.0.0", "version": "5.0.0",
"main": "node_modules/expo/AppEntry.js",
"scripts": { "scripts": {
"start": "expo start", "start": "expo start",
"android": "expo start --android", "android": "expo start --android",
@ -24,15 +23,17 @@
] ]
}, },
"dependencies": { "dependencies": {
"@amplitude/analytics-react-native": "^1.1.1",
"@apollo/react-hooks": "^3.1.3", "@apollo/react-hooks": "^3.1.3",
"@expo/vector-icons": "^12.0.0", "@expo/vector-icons": "^13.0.0",
"@ptomasroos/react-native-multi-slider": "^2.2.2", "@ptomasroos/react-native-multi-slider": "^2.2.2",
"@react-native-async-storage/async-storage": "~1.15.0", "@react-native-async-storage/async-storage": "~1.17.3",
"@react-native-community/masked-view": "0.1.10", "@react-native-community/masked-view": "0.1.11",
"@react-navigation/drawer": "^5.12.5", "@react-navigation/drawer": "^6.6.0",
"@react-navigation/native": "^5.9.4", "@react-navigation/native": "^6.1.4",
"@react-navigation/stack": "^5.14.5", "@react-navigation/native-stack": "^6.9.10",
"apollo-boost": "^0.3.1", "@react-navigation/stack": "^6.3.14",
"apollo-boost": "^0.4.9",
"apollo-cache-inmemory": "^1.5.1", "apollo-cache-inmemory": "^1.5.1",
"apollo-cache-persist": "^0.1.1", "apollo-cache-persist": "^0.1.1",
"apollo-client": "^2.5.1", "apollo-client": "^2.5.1",
@ -41,78 +42,83 @@
"apollo-link-state": "^0.4.2", "apollo-link-state": "^0.4.2",
"apollo-link-ws": "^1.0.20", "apollo-link-ws": "^1.0.20",
"apollo-upload-client": "^10.0.0", "apollo-upload-client": "^10.0.0",
"expo": "^44.0.0", "apollo-utilities": "^1.3.4",
"expo-analytics-amplitude": "~11.1.0", "deprecated-react-native-prop-types": "^4.0.0",
"expo": "~47.0.12",
"expo-app-auth": "~11.1.0", "expo-app-auth": "~11.1.0",
"expo-app-loading": "~1.3.0", "expo-app-loading": "~2.1.1",
"expo-apple-authentication": "~4.1.0", "expo-apple-authentication": "~5.0.1",
"expo-application": "~4.0.1", "expo-application": "~5.0.1",
"expo-asset": "~8.4.6", "expo-asset": "~8.7.0",
"expo-constants": "~13.0.1", "expo-auth-session": "~3.8.0",
"expo-device": "~4.1.0", "expo-camera": "~13.1.0",
"expo-facebook": "~12.1.0", "expo-constants": "~14.0.2",
"expo-font": "~10.0.4", "expo-contacts": "~11.0.1",
"expo-google-app-auth": "~8.3.0", "expo-device": "~5.0.0",
"expo-image-picker": "~12.0.1", "expo-font": "~11.0.1",
"expo-linking": "~3.0.0", "expo-google-app-auth": "^8.3.0",
"expo-localization": "~12.0.0", "expo-image-picker": "~14.0.2",
"expo-location": "~14.0.1", "expo-linking": "~3.3.1",
"expo-notifications": "~0.14.0", "expo-localization": "~14.0.0",
"expo-splash-screen": "~0.14.1", "expo-location": "~15.0.1",
"expo-tracking-transparency": "~2.1.0", "expo-notifications": "~0.17.0",
"expo-updates": "~0.11.6", "expo-random": "~13.0.0",
"graphql": "^14.5.8", "expo-sensors": "~12.0.1",
"expo-splash-screen": "~0.17.5",
"expo-status-bar": "~1.4.2",
"expo-tracking-transparency": "~3.0.1",
"expo-updates": "~0.15.6",
"graphql": "^16.6.0",
"graphql-tag": "^2.10.1", "graphql-tag": "^2.10.1",
"i18n-js": "^3.2.2", "i18n-js": "^3.2.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"patch-package": "^6.2.2", "patch-package": "^6.5.1",
"react": "17.0.1", "react": "18.1.0",
"react-apollo": "^2.5.8", "react-apollo": "^3.1.5",
"react-native": "0.64.3", "react-native": "0.70.5",
"react-native-flash-message": "^0.1.23", "react-native-button": "^3.0.1",
"react-native-flash-message": "^0.4.0",
"react-native-flatlist-slider": "^1.0.5", "react-native-flatlist-slider": "^1.0.5",
"react-native-gesture-handler": "~2.1.0", "react-native-gesture-handler": "~2.8.0",
"react-native-gifted-chat": "^0.16.3", "react-native-gifted-chat": "^1.1.1",
"react-native-maps": "0.29.4", "react-native-maps": "1.3.2",
"react-native-material-textfield": "^0.16.1", "react-native-material-textfield": "^0.16.1",
"react-native-modal": "^11.10.0", "react-native-modal": "^13.0.1",
"react-native-modalize": "^2.0.8", "react-native-modalize": "^2.0.8",
"react-native-reanimated": "~2.3.1", "react-native-reanimated": "~2.12.0",
"react-native-safe-area-context": "3.3.2", "react-native-safe-area-context": "4.4.1",
"react-native-screens": "~3.10.1", "react-native-screens": "~3.18.0",
"react-native-star-rating": "^1.1.0", "react-native-star-rating": "^1.1.0",
"react-native-svg": "12.1.1", "react-native-svg": "13.4.0",
"react-native-timeline-flatlist": "^0.7.2", "react-native-timeline-flatlist": "^0.8.0",
"react-native-webview": "11.15.0", "react-native-webview": "11.23.1",
"subscriptions-transport-ws": "^0.9.16", "subscriptions-transport-ws": "^0.11.0",
"uuid": "^3.3.2", "uuid": "^3.3.2",
"validate.js": "^0.12.0" "validate.js": "^0.13.1"
}, },
"devDependencies": { "devDependencies": {
"babel-jest": "^24.8.0", "@babel/core": "^7.12.9",
"babel-preset-expo": "9.0.2", "babel-jest": "^29.4.3",
"babel-preset-expo": "~9.2.1",
"babel-preset-react-native": "^4.0.1", "babel-preset-react-native": "^4.0.1",
"eslint": "^7.28.0", "eslint": "^8.34.0",
"eslint-config-standard": "^14.1.1", "eslint-config-standard": "^17.0.0",
"eslint-plugin-import": "^2.20.2", "eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1", "eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.20.0", "eslint-plugin-react": "^7.20.0",
"eslint-plugin-standard": "^4.0.1", "eslint-plugin-standard": "^5.0.0",
"husky": "^4.3.8", "husky": "^8.0.3",
"jest": "^26.6.3", "jest": "^29.4.3",
"jest-react-native": "^18.0.0", "jest-react-native": "^18.0.0",
"lint-staged": "^10.5.4", "lint-staged": "^13.1.2",
"metro-react-native-babel-preset": "^0.54.1", "metro-react-native-babel-preset": "^0.75.0",
"prettier": "^2.3.1", "prettier": "^2.3.1",
"prettier-config-standard": "^1.0.1", "prettier-config-standard": "^5.0.0",
"react-test-renderer": "^16.8.6" "react-test-renderer": "^18.2.0"
}, },
"jest": { "jest": {
"preset": "react-native", "preset": "react-native"
"transformIgnorePatterns": [
"node_modules/(?!(react-native|expo|@expo|apollo-boost|apollo-cache-inmemory|apollo-client|apollo-link-context|apollo-link-http|apollo-link-state|apollo-upload-client|graphql|graphql-tag|react-apollo|react-native-animatable|react-native-material-buttons|react-native-material-ripple|react-native-material-textfield|react-native-ratings|react-native-swiper-flatlist|react-native-timeline-listview|react-navigation|validate.js)/)"
]
}, },
"private": true "private": true
} }

View File

@ -0,0 +1,38 @@
diff --git a/node_modules/react-native-button/Button.js b/node_modules/react-native-button/Button.js
index b248176..3c6aefa 100644
--- a/node_modules/react-native-button/Button.js
+++ b/node_modules/react-native-button/Button.js
@@ -1,4 +1,5 @@
import PropTypes from 'prop-types';
+import {TextPropTypes,ViewPropTypes} from 'deprecated-react-native-prop-types'
import React, { Component } from 'react';
import {
Platform,
@@ -7,7 +8,7 @@ import {
TouchableOpacity,
TouchableNativeFeedback,
View,
- ViewPropTypes
+ //ViewPropTypes
} from 'react-native';
import coalesceNonElementChildren from './coalesceNonElementChildren';
@@ -18,12 +19,15 @@ export default class Button extends Component {
static propTypes = {
...TouchableOpacity.propTypes,
accessibilityLabel: PropTypes.string,
- allowFontScaling: Text.propTypes.allowFontScaling,
+ // allowFontScaling: Text.propTypes.allowFontScaling,
+ allowFontScaling: TextPropTypes.allowFontScaling,
containerStyle: ViewPropTypes.style,
disabledContainerStyle: ViewPropTypes.style,
disabled: PropTypes.bool,
- style: Text.propTypes.style,
- styleDisabled: Text.propTypes.style,
+ style: TextPropTypes.style,
+ styleDisabled: TextPropTypes.style,
+ // style: Text.propTypes.style,
+ // styleDisabled: Text.propTypes.style,
childGroupStyle: ViewPropTypes.style,
androidBackground: PropTypes.object,
};

View File

@ -1,21 +1,197 @@
diff --git a/node_modules/react-native-material-textfield/src/components/affix/index.js b/node_modules/react-native-material-textfield/src/components/affix/index.js diff --git a/node_modules/react-native-material-textfield/src/components/affix/index.js b/node_modules/react-native-material-textfield/src/components/affix/index.js
index 0f85022..c12b3a6 100644 index 0f85022..e467adb 100644
--- a/node_modules/react-native-material-textfield/src/components/affix/index.js --- a/node_modules/react-native-material-textfield/src/components/affix/index.js
+++ b/node_modules/react-native-material-textfield/src/components/affix/index.js +++ b/node_modules/react-native-material-textfield/src/components/affix/index.js
@@ -11,7 +11,7 @@ export default class Affix extends PureComponent { @@ -9,26 +9,26 @@ export default class Affix extends PureComponent {
numberOfLines: 1,
};
static propTypes = { - static propTypes = {
numberOfLines: PropTypes.number, - numberOfLines: PropTypes.number,
- style: Animated.Text.propTypes.style, - style: Animated.Text.propTypes.style,
+ style: PropTypes.object, + // static propTypes = {
+ // numberOfLines: PropTypes.number,
+ // style: PropTypes.object,
color: PropTypes.string.isRequired, - color: PropTypes.string.isRequired,
fontSize: PropTypes.number.isRequired, - fontSize: PropTypes.number.isRequired,
+ // color: PropTypes.string.isRequired,
+ // fontSize: PropTypes.number.isRequired,
- type: PropTypes
- .oneOf(['prefix', 'suffix'])
- .isRequired,
+ // type: PropTypes
+ // .oneOf(['prefix', 'suffix'])
+ // .isRequired,
- labelAnimation: PropTypes
- .instanceOf(Animated.Value)
- .isRequired,
+ // labelAnimation: PropTypes
+ // .instanceOf(Animated.Value)
+ // .isRequired,
- children: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.node),
- PropTypes.node,
- ]),
- };
+ // children: PropTypes.oneOfType([
+ // PropTypes.arrayOf(PropTypes.node),
+ // PropTypes.node,
+ // ]),
+ // };
render() {
let { labelAnimation, style, children, type, fontSize, color } = this.props;
diff --git a/node_modules/react-native-material-textfield/src/components/counter/index.js b/node_modules/react-native-material-textfield/src/components/counter/index.js
index 35d3264..089b871 100644
--- a/node_modules/react-native-material-textfield/src/components/counter/index.js
+++ b/node_modules/react-native-material-textfield/src/components/counter/index.js
@@ -5,15 +5,15 @@ import { Text } from 'react-native';
import styles from './styles';
export default class Counter extends PureComponent {
- static propTypes = {
- count: PropTypes.number.isRequired,
- limit: PropTypes.number,
+ // static propTypes = {
+ // count: PropTypes.number.isRequired,
+ // limit: PropTypes.number,
- baseColor: PropTypes.string.isRequired,
- errorColor: PropTypes.string.isRequired,
+ // baseColor: PropTypes.string.isRequired,
+ // errorColor: PropTypes.string.isRequired,
- style: Text.propTypes.style,
- };
+ // style: PropTypes.object,
+ // };
render() {
let { count, limit, baseColor, errorColor, style } = this.props;
diff --git a/node_modules/react-native-material-textfield/src/components/field/index.js b/node_modules/react-native-material-textfield/src/components/field/index.js diff --git a/node_modules/react-native-material-textfield/src/components/field/index.js b/node_modules/react-native-material-textfield/src/components/field/index.js
index 494bbaa..9bbf2e2 100644 index 494bbaa..2a71c82 100644
--- a/node_modules/react-native-material-textfield/src/components/field/index.js --- a/node_modules/react-native-material-textfield/src/components/field/index.js
+++ b/node_modules/react-native-material-textfield/src/components/field/index.js +++ b/node_modules/react-native-material-textfield/src/components/field/index.js
@@ -221,6 +221,7 @@ export default class TextField extends PureComponent { @@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import React, { PureComponent } from 'react';
+import {ViewPropTypes} from 'deprecated-react-native-prop-types';
import {
View,
Text,
@@ -7,7 +8,7 @@ import {
Animated,
StyleSheet,
Platform,
- ViewPropTypes,
+ //ViewPropTypes,
} from 'react-native';
import Line from '../line';
@@ -65,60 +66,60 @@ export default class TextField extends PureComponent {
disabled: false,
};
- static propTypes = {
- ...TextInput.propTypes,
+ // static propTypes = {
+ // ...TextInput.propTypes,
- animationDuration: PropTypes.number,
+ // animationDuration: PropTypes.number,
- fontSize: PropTypes.number,
- labelFontSize: PropTypes.number,
+ // fontSize: PropTypes.number,
+ // labelFontSize: PropTypes.number,
- contentInset: PropTypes.shape({
- top: PropTypes.number,
- label: PropTypes.number,
- input: PropTypes.number,
- left: PropTypes.number,
- right: PropTypes.number,
- }),
+ // contentInset: PropTypes.shape({
+ // top: PropTypes.number,
+ // label: PropTypes.number,
+ // input: PropTypes.number,
+ // left: PropTypes.number,
+ // right: PropTypes.number,
+ // }),
- labelOffset: Label.propTypes.offset,
+ // labelOffset: Label.propTypes.offset,
- labelTextStyle: Text.propTypes.style,
- titleTextStyle: Text.propTypes.style,
- affixTextStyle: Text.propTypes.style,
+ // labelTextStyle: PropTypes.object.style,
+ // // titleTextStyle: PropTypes.object.style,
+ // // affixTextStyle: PropTypes.object.style,
- tintColor: PropTypes.string,
- textColor: PropTypes.string,
- baseColor: PropTypes.string,
+ // tintColor: PropTypes.string,
+ // textColor: PropTypes.string,
+ // baseColor: PropTypes.string,
- label: PropTypes.string,
- title: PropTypes.string,
+ // label: PropTypes.string,
+ // title: PropTypes.string,
- characterRestriction: PropTypes.number,
+ // characterRestriction: PropTypes.number,
- error: PropTypes.string,
- errorColor: PropTypes.string,
+ // error: PropTypes.string,
+ // errorColor: PropTypes.string,
- lineWidth: PropTypes.number,
- activeLineWidth: PropTypes.number,
- disabledLineWidth: PropTypes.number,
+ // lineWidth: PropTypes.number,
+ // activeLineWidth: PropTypes.number,
+ // disabledLineWidth: PropTypes.number,
- lineType: Line.propTypes.lineType,
- disabledLineType: Line.propTypes.lineType,
+ // lineType: Line.propTypes.lineType,
+ // disabledLineType: Line.propTypes.lineType,
- disabled: PropTypes.bool,
+ // disabled: PropTypes.bool,
- formatText: PropTypes.func,
+ // formatText: PropTypes.func,
- renderLeftAccessory: PropTypes.func,
- renderRightAccessory: PropTypes.func,
+ // renderLeftAccessory: PropTypes.func,
+ // renderRightAccessory: PropTypes.func,
- prefix: PropTypes.string,
- suffix: PropTypes.string,
+ // prefix: PropTypes.string,
+ // suffix: PropTypes.string,
- containerStyle: (ViewPropTypes || View.propTypes).style,
- inputContainerStyle: (ViewPropTypes || View.propTypes).style,
- };
+ // containerStyle: (ViewPropTypes || View.propTypes).style,
+ // inputContainerStyle: (ViewPropTypes || View.propTypes).style,
+ // };
static inputContainerStyle = styles.inputContainer;
@@ -221,6 +222,7 @@ export default class TextField extends PureComponent {
let options = { let options = {
toValue: this.focusState(), toValue: this.focusState(),
@ -24,28 +200,206 @@ index 494bbaa..9bbf2e2 100644
}; };
diff --git a/node_modules/react-native-material-textfield/src/components/helper/index.js b/node_modules/react-native-material-textfield/src/components/helper/index.js diff --git a/node_modules/react-native-material-textfield/src/components/helper/index.js b/node_modules/react-native-material-textfield/src/components/helper/index.js
index 6060f9f..fe9d9c4 100644 index 6060f9f..86ac2c0 100644
--- a/node_modules/react-native-material-textfield/src/components/helper/index.js --- a/node_modules/react-native-material-textfield/src/components/helper/index.js
+++ b/node_modules/react-native-material-textfield/src/components/helper/index.js +++ b/node_modules/react-native-material-textfield/src/components/helper/index.js
@@ -11,7 +11,7 @@ export default class Helper extends PureComponent { @@ -1,23 +1,24 @@
import PropTypes from 'prop-types';
+
import React, { PureComponent } from 'react';
import { Animated } from 'react-native';
disabled: PropTypes.bool, import styles from './styles';
export default class Helper extends PureComponent {
- static propTypes = {
- title: PropTypes.string,
- error: PropTypes.string,
+ // static propTypes = {
+ // title: PropTypes.string,
+ // error: PropTypes.string,
- disabled: PropTypes.bool,
+ // disabled: PropTypes.bool,
- style: Animated.Text.propTypes.style, - style: Animated.Text.propTypes.style,
+ style: PropTypes.object, + // style: PropTypes.object,
baseColor: PropTypes.string, - baseColor: PropTypes.string,
errorColor: PropTypes.string, - errorColor: PropTypes.string,
+ // baseColor: PropTypes.string,
+ // errorColor: PropTypes.string,
- focusAnimation: PropTypes.instanceOf(Animated.Value),
- };
+ // focusAnimation: PropTypes.instanceOf(Animated.Value),
+ // };
constructor(props) {
super(props);
diff --git a/node_modules/react-native-material-textfield/src/components/label/index.js b/node_modules/react-native-material-textfield/src/components/label/index.js diff --git a/node_modules/react-native-material-textfield/src/components/label/index.js b/node_modules/react-native-material-textfield/src/components/label/index.js
index 82eaf03..809fcdd 100644 index 82eaf03..1ad9a93 100644
--- a/node_modules/react-native-material-textfield/src/components/label/index.js --- a/node_modules/react-native-material-textfield/src/components/label/index.js
+++ b/node_modules/react-native-material-textfield/src/components/label/index.js +++ b/node_modules/react-native-material-textfield/src/components/label/index.js
@@ -43,7 +43,7 @@ export default class Label extends PureComponent { @@ -11,41 +11,41 @@ export default class Label extends PureComponent {
y1: PropTypes.number, restricted: false,
}),
- style: Animated.Text.propTypes.style,
+ style: PropTypes.object,
label: PropTypes.string,
}; };
- static propTypes = {
- numberOfLines: PropTypes.number,
+ // static propTypes = {
+ // numberOfLines: PropTypes.number,
- disabled: PropTypes.bool,
- restricted: PropTypes.bool,
+ // disabled: PropTypes.bool,
+ // restricted: PropTypes.bool,
- fontSize: PropTypes.number.isRequired,
- activeFontSize: PropTypes.number.isRequired,
+ // fontSize: PropTypes.number.isRequired,
+ // activeFontSize: PropTypes.number.isRequired,
- baseColor: PropTypes.string.isRequired,
- tintColor: PropTypes.string.isRequired,
- errorColor: PropTypes.string.isRequired,
+ // baseColor: PropTypes.string.isRequired,
+ // tintColor: PropTypes.string.isRequired,
+ // errorColor: PropTypes.string.isRequired,
- focusAnimation: PropTypes
- .instanceOf(Animated.Value)
- .isRequired,
+ // focusAnimation: PropTypes
+ // .instanceOf(Animated.Value)
+ // .isRequired,
- labelAnimation: PropTypes
- .instanceOf(Animated.Value)
- .isRequired,
+ // labelAnimation: PropTypes
+ // .instanceOf(Animated.Value)
+ // .isRequired,
- contentInset: PropTypes.shape({
- label: PropTypes.number,
- }),
+ // contentInset: PropTypes.shape({
+ // label: PropTypes.number,
+ // }),
- offset: PropTypes.shape({
- x0: PropTypes.number,
- y0: PropTypes.number,
- x1: PropTypes.number,
- y1: PropTypes.number,
- }),
+ // offset: PropTypes.shape({
+ // x0: PropTypes.number,
+ // y0: PropTypes.number,
+ // x1: PropTypes.number,
+ // y1: PropTypes.number,
+ // }),
- style: Animated.Text.propTypes.style,
- label: PropTypes.string,
- };
+ // style: PropTypes.object,
+ // label: PropTypes.string,
+ // };
render() {
let {
diff --git a/node_modules/react-native-material-textfield/src/components/line/index.js b/node_modules/react-native-material-textfield/src/components/line/index.js
index 44995e9..b689387 100644
--- a/node_modules/react-native-material-textfield/src/components/line/index.js
+++ b/node_modules/react-native-material-textfield/src/components/line/index.js
@@ -16,23 +16,23 @@ export default class Line extends PureComponent {
restricted: false,
};
- static propTypes = {
- lineType: lineTypes,
- disabledLineType: lineTypes,
+ // static propTypes = {
+ // lineType: lineTypes,
+ // disabledLineType: lineTypes,
- disabled: PropTypes.bool,
- restricted: PropTypes.bool,
+ // disabled: PropTypes.bool,
+ // restricted: PropTypes.bool,
- tintColor: PropTypes.string,
- baseColor: PropTypes.string,
- errorColor: PropTypes.string,
+ // tintColor: PropTypes.string,
+ // baseColor: PropTypes.string,
+ // errorColor: PropTypes.string,
- lineWidth: PropTypes.number,
- activeLineWidth: PropTypes.number,
- disabledLineWidth: PropTypes.number,
+ // lineWidth: PropTypes.number,
+ // activeLineWidth: PropTypes.number,
+ // disabledLineWidth: PropTypes.number,
- focusAnimation: PropTypes.instanceOf(Animated.Value),
- };
+ // focusAnimation: PropTypes.instanceOf(Animated.Value),
+ // };
static getDerivedStateFromProps(props, state) {
let { lineWidth, activeLineWidth, disabledLineWidth } = props;
diff --git a/node_modules/react-native-material-textfield/src/components/outline/index.js b/node_modules/react-native-material-textfield/src/components/outline/index.js
index 9347a99..9c3e8a3 100644
--- a/node_modules/react-native-material-textfield/src/components/outline/index.js
+++ b/node_modules/react-native-material-textfield/src/components/outline/index.js
@@ -11,29 +11,29 @@ export default class Line extends PureComponent {
restricted: false,
};
- static propTypes = {
- lineType: PropTypes.oneOf(['solid', 'none']),
+ // static propTypes = {
+ // lineType: PropTypes.oneOf(['solid', 'none']),
- disabled: PropTypes.bool,
- restricted: PropTypes.bool,
+ // disabled: PropTypes.bool,
+ // restricted: PropTypes.bool,
- tintColor: PropTypes.string,
- baseColor: PropTypes.string,
- errorColor: PropTypes.string,
+ // tintColor: PropTypes.string,
+ // baseColor: PropTypes.string,
+ // errorColor: PropTypes.string,
- lineWidth: PropTypes.number,
- activeLineWidth: PropTypes.number,
- disabledLineWidth: PropTypes.number,
+ // lineWidth: PropTypes.number,
+ // activeLineWidth: PropTypes.number,
+ // disabledLineWidth: PropTypes.number,
- focusAnimation: PropTypes.instanceOf(Animated.Value),
- labelAnimation: PropTypes.instanceOf(Animated.Value),
- labelWidth: PropTypes.instanceOf(Animated.Value),
+ // focusAnimation: PropTypes.instanceOf(Animated.Value),
+ // labelAnimation: PropTypes.instanceOf(Animated.Value),
+ // labelWidth: PropTypes.instanceOf(Animated.Value),
- contentInset: PropTypes.shape({
- left: PropTypes.number,
- right: PropTypes.number,
- }),
- };
+ // contentInset: PropTypes.shape({
+ // left: PropTypes.number,
+ // right: PropTypes.number,
+ // }),
+ // };
borderProps() {
let {

View File

@ -0,0 +1,34 @@
diff --git a/node_modules/react-native-star-rating/node_modules/react-native-button/Button.js b/node_modules/react-native-star-rating/node_modules/react-native-button/Button.js
index fb7cf46..8e4c522 100644
--- a/node_modules/react-native-star-rating/node_modules/react-native-button/Button.js
+++ b/node_modules/react-native-star-rating/node_modules/react-native-button/Button.js
@@ -1,11 +1,12 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
+import {TextPropTypes,ViewPropTypes} from 'deprecated-react-native-prop-types'
import {
StyleSheet,
Text,
TouchableOpacity,
View,
- ViewPropTypes,
+ //ViewPropTypes,
} from 'react-native';
import coalesceNonElementChildren from './coalesceNonElementChildren';
@@ -16,12 +17,12 @@ export default class Button extends Component {
static propTypes = {
...TouchableOpacity.propTypes,
accessibilityLabel: PropTypes.string,
- allowFontScaling: Text.propTypes.allowFontScaling,
+ allowFontScaling: TextPropTypes.allowFontScaling,
containerStyle: ViewPropTypes.style,
disabledContainerStyle: ViewPropTypes.style,
disabled: PropTypes.bool,
- style: Text.propTypes.style,
- styleDisabled: Text.propTypes.style,
+ style: TextPropTypes.style,
+ styleDisabled: TextPropTypes.style,
childGroupStyle: ViewPropTypes.style,
};

View File

@ -0,0 +1,26 @@
diff --git a/node_modules/react-native-star-rating/StarButton.js b/node_modules/react-native-star-rating/StarButton.js
index b6db613..8a62f5a 100644
--- a/node_modules/react-native-star-rating/StarButton.js
+++ b/node_modules/react-native-star-rating/StarButton.js
@@ -1,6 +1,7 @@
// React and react native imports
import React, { Component } from 'react';
-import { Image, StyleSheet, ViewPropTypes } from 'react-native';
+import { Image, StyleSheet } from 'react-native';
+import {ViewPropTypes} from 'deprecated-react-native-prop-types';
import PropTypes from 'prop-types';
import { createIconSetFromIcoMoon } from 'react-native-vector-icons';
diff --git a/node_modules/react-native-star-rating/StarRating.js b/node_modules/react-native-star-rating/StarRating.js
index 7aecc95..de6397c 100644
--- a/node_modules/react-native-star-rating/StarRating.js
+++ b/node_modules/react-native-star-rating/StarRating.js
@@ -1,6 +1,7 @@
// React and react native imports
import React, { Component } from 'react';
-import { View, ViewPropTypes, StyleSheet } from 'react-native';
+import { View, StyleSheet } from 'react-native';
+import {ViewPropTypes} from 'deprecated-react-native-prop-types';
import PropTypes from 'prop-types';
import { View as AnimatableView } from 'react-native-animatable';

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,5 +1,5 @@
import FdEmailBtn from './FdEmailBtn/FdEmailBtn' import FdEmailBtn from "./FdEmailBtn/FdEmailBtn";
import FdFacebookBtn from './FdFacebookBtn/FdFacebookBtn'
import FdGoogleBtn from './FdGoogleBtn/FdGoogleBtn'
export { FdEmailBtn, FdFacebookBtn, FdGoogleBtn } import FdGoogleBtn from "./FdGoogleBtn/FdGoogleBtn";
export { FdEmailBtn, FdGoogleBtn };

View File

@ -1,67 +1,67 @@
import { useNavigation, useTheme } from '@react-navigation/native' import { useNavigation, useTheme } from "@react-navigation/native";
import React, { useContext } from 'react' import React, { useContext } from "react";
import { FlatList, TouchableOpacity, View } from 'react-native' import { FlatList, TouchableOpacity, View } from "react-native";
import ConfigurationContext from '../../../context/Configuration' import ConfigurationContext from "../../../context/Configuration";
import UserContext from '../../../context/User' import UserContext from "../../../context/User";
import { alignment } from '../../../utils/alignment' import { alignment } from "../../../utils/alignment";
import { NAVIGATION_SCREEN } from '../../../utils/constant' import { NAVIGATION_SCREEN } from "../../../utils/constant";
import Spinner from '../../Spinner/Spinner' import Spinner from "../../Spinner/Spinner";
import TextDefault from '../../Text/TextDefault/TextDefault' import TextDefault from "../../Text/TextDefault/TextDefault";
import TextError from '../../Text/TextError/TextError' import TextError from "../../Text/TextError/TextError";
import useStyle from './styles' import useStyle from "./styles";
export const orderStatuses = [ export const orderStatuses = [
{ {
key: 'PENDING', key: "PENDING",
status: 1, status: 1,
statusText: 'Your order is still pending.' statusText: "Your order is still pending.",
}, },
{ {
key: 'ACCEPTED', key: "ACCEPTED",
status: 2, status: 2,
statusText: 'Restaurant is preparing Food.' statusText: "Restaurant is preparing Food.",
}, },
{ {
key: 'PICKED', key: "PICKED",
status: 3, status: 3,
statusText: 'Rider is on the way.' statusText: "Rider is on the way.",
}, },
{ {
key: 'DELIVERED', key: "DELIVERED",
status: 4, status: 4,
statusText: 'Order is delivered.' statusText: "Order is delivered.",
}, },
{ {
key: 'COMPLETED', key: "COMPLETED",
status: 5, status: 5,
statusText: 'Order is completed.' statusText: "Order is completed.",
} },
] ];
const orderStatusActive = ['PENDING', 'PICKED', 'ACCEPTED'] const orderStatusActive = ["PENDING", "PICKED", "ACCEPTED"];
const StatusCard = () => { const StatusCard = () => {
const { colors } = useTheme() const { colors } = useTheme();
const styles = useStyle() const styles = useStyle();
const navigation = useNavigation() const navigation = useNavigation();
const { const {
loadingOrders, loadingOrders,
errorOrders, errorOrders,
orders, orders,
networkStatusOrders, networkStatusOrders,
fetchOrders fetchOrders,
} = useContext(UserContext) } = useContext(UserContext);
const configuration = useContext(ConfigurationContext) const configuration = useContext(ConfigurationContext);
const checkStatus = status => { const checkStatus = (status) => {
const obj = orderStatuses.filter(x => { const obj = orderStatuses.filter((x) => {
return x.key === status return x.key === status;
}) });
return obj[0] return obj[0];
} };
if (loadingOrders) return <Spinner /> if (loadingOrders) return <Spinner />;
if (errorOrders) return <TextError>{errorOrders.message}</TextError> if (errorOrders) return <TextError>{errorOrders.message}</TextError>;
return ( return (
<FlatList <FlatList
@ -71,8 +71,9 @@ const StatusCard = () => {
horizontal={true} horizontal={true}
refreshing={networkStatusOrders === 4} refreshing={networkStatusOrders === 4}
onRefresh={() => networkStatusOrders === 7 && fetchOrders()} onRefresh={() => networkStatusOrders === 7 && fetchOrders()}
data={orders.filter(o => orderStatusActive.includes(o.order_status))} data={orders.filter((o) => orderStatusActive.includes(o.order_status))}
keyExtractor={item => item._id} //keyExtractor={(item) => item._id}
keyExtractor={(item, index) => String(index)}
renderItem={({ item, index }) => ( renderItem={({ item, index }) => (
<TouchableOpacity <TouchableOpacity
activeOpacity={0.8} activeOpacity={0.8}
@ -80,9 +81,10 @@ const StatusCard = () => {
onPress={() => onPress={() =>
navigation.navigate(NAVIGATION_SCREEN.OrderDetail, { navigation.navigate(NAVIGATION_SCREEN.OrderDetail, {
_id: item._id, _id: item._id,
currency_symbol: configuration.currency_symbol currency_symbol: configuration.currency_symbol,
}) })
}> }
>
<View key={index} style={styles.statusContainer}> <View key={index} style={styles.statusContainer}>
<View style={styles.textContainer}> <View style={styles.textContainer}>
<TextDefault H5 medium textColor={styles.lightText.color}> <TextDefault H5 medium textColor={styles.lightText.color}>
@ -95,8 +97,8 @@ const StatusCard = () => {
Status Status
</TextDefault> </TextDefault>
<TextDefault textColor={'#00b9c6'} H5 medium> <TextDefault textColor={"#00b9c6"} H5 medium>
{item.order_status}{' '} {item.order_status}{" "}
<TextDefault numberOfLines={2} medium> <TextDefault numberOfLines={2} medium>
{/* {checkStatus(item.order_status).status}.{' '} */}( {/* {checkStatus(item.order_status).status}.{' '} */}(
{checkStatus(item.order_status).statusText}) {checkStatus(item.order_status).statusText})
@ -107,7 +109,7 @@ const StatusCard = () => {
</TouchableOpacity> </TouchableOpacity>
)} )}
/> />
) );
} };
export default StatusCard export default StatusCard;

View File

@ -1,25 +1,25 @@
import { useTheme } from '@react-navigation/native' import { useTheme } from "@react-navigation/native";
import { useHeaderHeight } from '@react-navigation/stack' import { useHeaderHeight } from "@react-navigation/elements";
import { StyleSheet } from 'react-native' import { StyleSheet } from "react-native";
import { useSafeAreaInsets } from 'react-native-safe-area-context' import { useSafeAreaInsets } from "react-native-safe-area-context";
import { scale } from '../../utils/scaling' import { scale } from "../../utils/scaling";
const useStyle = () => { const useStyle = () => {
const { colors } = useTheme() const { colors } = useTheme();
const inset = useSafeAreaInsets() const inset = useSafeAreaInsets();
const headerHeight = useHeaderHeight() const headerHeight = useHeaderHeight();
return StyleSheet.create({ return StyleSheet.create({
flex: { flex: {
flex: 1 flex: 1,
}, },
wrapperView: { wrapperView: {
backgroundColor: colors.background, backgroundColor: colors.background,
paddingTop: headerHeight, paddingTop: headerHeight,
paddingBottom: inset.bottom paddingBottom: inset.bottom,
}, },
topCurve: { topCurve: {
position: 'absolute', position: "absolute",
opacity: 0.2, opacity: 0.2,
left: -75, left: -75,
borderTopRightRadius: scale(90), borderTopRightRadius: scale(90),
@ -28,10 +28,10 @@ const useStyle = () => {
width: scale(250), width: scale(250),
height: scale(260), height: scale(260),
borderRadius: 100, borderRadius: 100,
backgroundColor: colors.curve backgroundColor: colors.curve,
}, },
bottomCurve: { bottomCurve: {
position: 'absolute', position: "absolute",
height: scale(185), height: scale(185),
width: scale(170), width: scale(170),
borderTopRightRadius: scale(110), borderTopRightRadius: scale(110),
@ -42,9 +42,9 @@ const useStyle = () => {
backgroundColor: colors.curve, backgroundColor: colors.curve,
opacity: 0.2, opacity: 0.2,
bottom: -80, bottom: -80,
zIndex: -1 zIndex: -1,
} },
}) });
} };
export default useStyle export default useStyle;

View File

@ -1,34 +1,34 @@
import CartItem from './CartItem/CartItem' import CartItem from "./CartItem/CartItem";
import { import {
CartComponent, CartComponent,
CheckComponent, CheckComponent,
HeadingComponent, HeadingComponent,
ImageHeader, ImageHeader,
RadioComponent, RadioComponent,
TitleComponent TitleComponent,
} from './CustomizeComponents' } from "./CustomizeComponents";
import { DrawerProfile } from './Drawer' import { DrawerProfile } from "./Drawer";
import CheckboxBtn from './FdCheckbox/CheckboxBtn' import CheckboxBtn from "./FdCheckbox/CheckboxBtn";
import RadioBtn from './FdRadioBtn/RadioBtn' import RadioBtn from "./FdRadioBtn/RadioBtn";
import { FdEmailBtn, FdFacebookBtn, FdGoogleBtn } from './FdSocialBtn' import { FdEmailBtn, FdGoogleBtn } from "./FdSocialBtn";
import { FlashMessage } from './FlashMessage/FlashMessage' import { FlashMessage } from "./FlashMessage/FlashMessage";
import { import {
BackButton, BackButton,
LeftButton, LeftButton,
RightButton, RightButton,
RegistrationHeader RegistrationHeader,
} from './Header' } from "./Header";
import { MenuCard, StatusCard } from './Menu' import { MenuCard, StatusCard } from "./Menu";
import { FilterModal } from './Modals' import { FilterModal } from "./Modals";
import ActiveOrders from './MyOrders/ActiveOrders' import ActiveOrders from "./MyOrders/ActiveOrders";
import { TrackingRider } from './OrderDetail' import { TrackingRider } from "./OrderDetail";
import Sidebar from './Sidebar/Sidebar' import Sidebar from "./Sidebar/Sidebar";
import Spinner from './Spinner/Spinner' import Spinner from "./Spinner/Spinner";
import { TextDefault, TextError, TextLine } from './Text' import { TextDefault, TextError, TextLine } from "./Text";
import Triangle from './Triangle/Triangle' import Triangle from "./Triangle/Triangle";
import EnategaImage from './EnategaImage/EnategaImage' import EnategaImage from "./EnategaImage/EnategaImage";
import WrapperView from './WrapperView/WrapperView' import WrapperView from "./WrapperView/WrapperView";
import { CustomIcon } from './CustomIcon' import { CustomIcon } from "./CustomIcon";
export { export {
WrapperView, WrapperView,
@ -45,7 +45,6 @@ export {
RadioBtn, RadioBtn,
CheckboxBtn, CheckboxBtn,
FdEmailBtn, FdEmailBtn,
FdFacebookBtn,
FdGoogleBtn, FdGoogleBtn,
FlashMessage, FlashMessage,
BackButton, BackButton,
@ -62,5 +61,5 @@ export {
TextError, TextError,
TextLine, TextLine,
Spinner, Spinner,
TrackingRider TrackingRider,
} };

View File

@ -1,100 +1,141 @@
/* eslint-disable react/prop-types */ /* eslint-disable react/prop-types */
import { createDrawerNavigator } from '@react-navigation/drawer' import { createDrawerNavigator } from "@react-navigation/drawer";
import { NavigationContainer, useTheme } from '@react-navigation/native' import { NavigationContainer, useTheme } from "@react-navigation/native";
import { createStackNavigator } from '@react-navigation/stack' import { createStackNavigator } from "@react-navigation/stack";
import * as Notifications from 'expo-notifications' import * as Notifications from "expo-notifications";
import React, { useEffect } from 'react' import React, { useEffect } from "react";
import { useColorScheme } from 'react-native' import { Text, useColorScheme, View } from "react-native";
import Animated from 'react-native-reanimated' import Animated from "react-native-reanimated";
import { import {
initialWindowMetrics, initialWindowMetrics,
SafeAreaProvider SafeAreaProvider,
} from 'react-native-safe-area-context' } from "react-native-safe-area-context";
import { TextDefault, LeftButton, Sidebar } from '../components' import { TextDefault, LeftButton, Sidebar } from "../components";
import { import Menu from "../screens/Menu/Menu";
Addresses, import MenuItems from "../screens/MenuItems/MenuItems";
Cart, import Addresses from "../screens/Addresses/Addresses";
CartAddress, import NewAddress from "../screens/NewAddress/NewAddress";
Chat, import EditAddress from "../screens/EditAddress/EditAddress";
CreateAccount, import Cart from "../screens/Cart/Cart";
EditAddress, import Profile from "../screens/Profile/Profile";
ForgotPassword, import FullMap from "../screens/FullMap/FullMap";
FullMap, import CartAddress from "../screens/CartAddress/CartAddress";
Help, import SelectVoucher from "../screens/Coupon/Coupon";
HelpBrowser, import Help from "../screens/Help/Help";
ItemDetail, import HelpBrowser from "../screens/HelpBrowser/HelpBrowser";
Login, import Chat from "../screens/Chat/Chat";
Menu, import Settings from "../screens/Settings/Settings";
MenuItems, import Paypal from "../screens/Paypal/Paypal";
MyOrders, import ItemDetail from "../screens/ItemDetail/ItemDetail";
NewAddress, import MyOrders from "../screens/MyOrders/MyOrders";
OrderDetail, import OrderDetail from "../screens/OrderDetail/OrderDetail";
Paypal, import StripeCheckout from "../screens/Stripe/StripeCheckout";
Profile, import RateAndReview from "../screens/RateAndReview/RateAndReview";
RateAndReview, import CreateAccount from "../screens/CreateAccount/CreateAccount";
Register, import Login from "../screens/Login/Login";
SelectVoucher, import Register from "../screens/Register/Register";
Settings, import ForgotPassword from "../screens/ForgotPassword/ForgotPassword";
StripeCheckout
} from '../screens'
import { THEME } from '../Theme'
import { ICONS_NAME, NAVIGATION_SCREEN } from '../utils/constant'
import navigationService from './navigationService'
import screenOptions from './screenOptions'
import styles from './styles'
const NavigationStack = createStackNavigator() // import {
const MainStack = createStackNavigator() // Addresses,
const SideDrawer = createDrawerNavigator() // Cart,
// CartAddress,
// Chat,
// CreateAccount,
// EditAddress,
// ForgotPassword,
// FullMap,
// Help,
// HelpBrowser,
// ItemDetail,
// Login,
// MenuItems,
// MyOrders,
// NewAddress,
// OrderDetail,
// Paypal,
// Profile,
// RateAndReview,
// Register,
// SelectVoucher,
// Settings,
// StripeCheckout,
// Menu,
// } from "../screens";
import { THEME } from "../Theme";
import { ICONS_NAME, NAVIGATION_SCREEN } from "../utils/constant";
import navigationService from "./navigationService";
import screenOptions from "./screenOptions";
import styles from "./styles";
const NavigationStack = createStackNavigator();
const MainStack = createStackNavigator();
const SideDrawer = createDrawerNavigator();
function Drawer() { function Drawer() {
const { colors } = useTheme() const { colors } = useTheme();
let animatedStyle = {} let animatedStyle = {};
let opacity let opacity;
let OuterWindowSlide, InnerWindowSlide let OuterWindowSlide, InnerWindowSlide;
return ( return (
<SideDrawer.Navigator <SideDrawer.Navigator
drawerType="slide" drawerType="slide"
overlayColor="transparent" overlayColor="transparent"
drawerStyle={{ screenOptions={{
flex: 1, drawerStyle: {
backgroundColor: colors.drawerBackground, flex: 1,
width: '60%', backgroundColor: colors.drawerBackground,
justifyContent: 'space-between', width: "60%",
borderRightWidth: 0, justifyContent: "space-between",
shadowOpacity: 0, borderRightWidth: 0,
elevation: 0 shadowOpacity: 0,
elevation: 0,
},
sceneContainerStyle: { backgroundColor: colors.drawerBackground },
}} }}
sceneContainerStyle={{ backgroundColor: colors.drawerBackground }} // drawerStyle={{
drawerContent={props => { // flex: 1,
// backgroundColor: colors.drawerBackground,
// width: "60%",
// justifyContent: "space-between",
// borderRightWidth: 0,
// shadowOpacity: 0,
// elevation: 0,
// }}
// sceneContainerStyle={{ backgroundColor: colors.drawerBackground }}
drawerContent={(props) => {
const scale = Animated.interpolateNode(props.progress, { const scale = Animated.interpolateNode(props.progress, {
inputRange: [0, 1], inputRange: [0, 1],
outputRange: [1, 0.7] outputRange: [1, 0.7],
}) });
const Animatedopacity = Animated.interpolateNode(props.progress, { const Animatedopacity = Animated.interpolateNode(props.progress, {
inputRange: [0, 0.6, 1], inputRange: [0, 0.6, 1],
outputRange: [0, 0, 1] outputRange: [0, 0, 1],
}) });
const AnimatedOuterSlide = Animated.interpolateNode(props.progress, { const AnimatedOuterSlide = Animated.interpolateNode(props.progress, {
inputRange: [0, 1], inputRange: [0, 1],
outputRange: [0, -35] outputRange: [0, -35],
}) });
const AnimatedInnerSlide = Animated.interpolateNode(props.progress, { const AnimatedInnerSlide = Animated.interpolateNode(props.progress, {
inputRange: [0, 1], inputRange: [0, 1],
outputRange: [0, -15] outputRange: [0, -15],
}) });
const borderRadius = Animated.interpolateNode(props.progress, { const borderRadius = Animated.interpolateNode(props.progress, {
inputRange: [0, 1], inputRange: [0, 1],
outputRange: [0, 20] outputRange: [0, 20],
}) });
animatedStyle = { borderRadius, transform: [{ scale }] } animatedStyle = { borderRadius, transform: [{ scale }] };
opacity = Animatedopacity opacity = Animatedopacity;
OuterWindowSlide = AnimatedOuterSlide OuterWindowSlide = AnimatedOuterSlide;
InnerWindowSlide = AnimatedInnerSlide InnerWindowSlide = AnimatedInnerSlide;
return <Sidebar {...props} />
}}> return <Sidebar {...props} />;
<SideDrawer.Screen name="noDrawer"> }}
{props => ( >
<SideDrawer.Screen name="noDrawer" options={{ headerShown: false }}>
{(props) => (
<NoDrawer <NoDrawer
{...props} {...props}
style={animatedStyle} style={animatedStyle}
@ -105,10 +146,11 @@ function Drawer() {
)} )}
</SideDrawer.Screen> </SideDrawer.Screen>
</SideDrawer.Navigator> </SideDrawer.Navigator>
) );
} }
function NoDrawer({ style, opacity = 1, OuterWindowSlide, InnerWindowSlide }) { function NoDrawer({ style, opacity = 1, OuterWindowSlide, InnerWindowSlide }) {
const { colors } = useTheme() const { colors } = useTheme();
return ( return (
<React.Fragment> <React.Fragment>
@ -120,15 +162,17 @@ function NoDrawer({ style, opacity = 1, OuterWindowSlide, InnerWindowSlide }) {
/> />
<Animated.View style={[styles.animatedView, style]}> <Animated.View style={[styles.animatedView, style]}>
<NavigationStack.Navigator <NavigationStack.Navigator
mode="modal" //mode="modal"
presentation="modal"
screenOptions={screenOptions({ screenOptions={screenOptions({
textColor: colors.headerTextColor textColor: colors.headerTextColor,
})}> })}
>
<NavigationStack.Screen <NavigationStack.Screen
name={NAVIGATION_SCREEN.Menu} name={NAVIGATION_SCREEN.Menu}
component={Menu} component={Menu}
options={{ options={{
headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} /> headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} />,
}} }}
/> />
<NavigationStack.Screen <NavigationStack.Screen
@ -143,14 +187,14 @@ function NoDrawer({ style, opacity = 1, OuterWindowSlide, InnerWindowSlide }) {
name={NAVIGATION_SCREEN.Profile} name={NAVIGATION_SCREEN.Profile}
component={Profile} component={Profile}
options={{ options={{
headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} /> headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} />,
}} }}
/> />
<NavigationStack.Screen <NavigationStack.Screen
name={NAVIGATION_SCREEN.Addresses} name={NAVIGATION_SCREEN.Addresses}
component={Addresses} component={Addresses}
options={{ options={{
headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} /> headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} />,
}} }}
/> />
<NavigationStack.Screen <NavigationStack.Screen
@ -177,14 +221,14 @@ function NoDrawer({ style, opacity = 1, OuterWindowSlide, InnerWindowSlide }) {
name={NAVIGATION_SCREEN.Help} name={NAVIGATION_SCREEN.Help}
component={Help} component={Help}
options={{ options={{
headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} /> headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} />,
}} }}
/> />
<NavigationStack.Screen <NavigationStack.Screen
name={NAVIGATION_SCREEN.Chat} name={NAVIGATION_SCREEN.Chat}
component={Chat} component={Chat}
options={{ options={{
headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} /> headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} />,
}} }}
/> />
<NavigationStack.Screen <NavigationStack.Screen
@ -195,7 +239,7 @@ function NoDrawer({ style, opacity = 1, OuterWindowSlide, InnerWindowSlide }) {
name={NAVIGATION_SCREEN.Settings} name={NAVIGATION_SCREEN.Settings}
component={Settings} component={Settings}
options={{ options={{
headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} /> headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} />,
}} }}
/> />
<NavigationStack.Screen <NavigationStack.Screen
@ -210,7 +254,7 @@ function NoDrawer({ style, opacity = 1, OuterWindowSlide, InnerWindowSlide }) {
name={NAVIGATION_SCREEN.MyOrders} name={NAVIGATION_SCREEN.MyOrders}
component={MyOrders} component={MyOrders}
options={{ options={{
headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} /> headerLeft: () => <LeftButton icon={ICONS_NAME.Menu} />,
}} }}
/> />
<NavigationStack.Screen <NavigationStack.Screen
@ -249,51 +293,60 @@ function NoDrawer({ style, opacity = 1, OuterWindowSlide, InnerWindowSlide }) {
</Animated.View> </Animated.View>
<Animated.View style={[styles.closeView, { opacity: opacity }]}> <Animated.View style={[styles.closeView, { opacity: opacity }]}>
<TextDefault H4 medium> <TextDefault H4 medium>
{'Close X'} {"Close X"}
</TextDefault> </TextDefault>
</Animated.View> </Animated.View>
</React.Fragment> </React.Fragment>
) );
} }
function AppContainer() { function AppContainer() {
const colorScheme = useColorScheme() console.log("AppContainer Working");
const colorScheme = useColorScheme();
function _handleNotification(notification) { function _handleNotification(notification) {
try { try {
if (notification.origin === 'selected') { if (notification.origin === "selected") {
if (notification.data.order) { if (notification.data.order) {
navigationService.navigate(NAVIGATION_SCREEN.OrderDetail, { navigationService.navigate(NAVIGATION_SCREEN.OrderDetail, {
_id: notification.data._id _id: notification.data._id,
}) });
} }
} }
} catch (e) { } catch (e) {
console.log(e) console.log(e);
} }
} }
useEffect(() => { useEffect(() => {
Notifications.setNotificationHandler({ Notifications.setNotificationHandler({
handleNotification: async() => ({ handleNotification: async () => ({
shouldShowAlert: true, shouldShowAlert: true,
shouldPlaySound: false, shouldPlaySound: false,
shouldSetBadge: false shouldSetBadge: false,
}) }),
}) });
const subscription = const subscription =
Notifications.addNotificationResponseReceivedListener(_handleNotification) Notifications.addNotificationResponseReceivedListener(
return () => subscription.remove() _handleNotification
}, []) );
return () => subscription.remove();
}, []);
return ( return (
<SafeAreaProvider initialMetrics={initialWindowMetrics}> <SafeAreaProvider initialMetrics={initialWindowMetrics}>
<NavigationContainer <NavigationContainer
theme={colorScheme === 'dark' ? THEME.Dark : THEME.Light} theme={colorScheme === "dark" ? THEME.Dark : THEME.Light}
ref={ref => { ref={(ref) => {
navigationService.setGlobalRef(ref) navigationService.setGlobalRef(ref);
Notifications.addNotificationReceivedListener(_handleNotification) Notifications.addNotificationReceivedListener(_handleNotification);
}}> }}
>
<MainStack.Navigator <MainStack.Navigator
headerMode="none" screenOptions={{
initialRouteName={NAVIGATION_SCREEN.Drawer}> headerShown: false,
}}
//headerMode="none"
initialRouteName={NAVIGATION_SCREEN.Drawer}
>
<MainStack.Screen <MainStack.Screen
name={NAVIGATION_SCREEN.Drawer} name={NAVIGATION_SCREEN.Drawer}
component={Drawer} component={Drawer}
@ -301,7 +354,7 @@ function AppContainer() {
</MainStack.Navigator> </MainStack.Navigator>
</NavigationContainer> </NavigationContainer>
</SafeAreaProvider> </SafeAreaProvider>
) );
} }
export default AppContainer export default AppContainer;

View File

@ -1,59 +1,59 @@
import { useMutation } from '@apollo/react-hooks' import { useMutation } from "@apollo/react-hooks";
import { useNavigation, useTheme } from '@react-navigation/native' import { useNavigation, useTheme } from "@react-navigation/native";
import gql from 'graphql-tag' import gql from "graphql-tag";
import React, { useContext, useLayoutEffect } from 'react' import React, { useContext, useLayoutEffect } from "react";
import { FlatList, TouchableOpacity, View } from 'react-native' import { FlatList, TouchableOpacity, View } from "react-native";
import i18n from '../../../i18n' import i18n from "../../../i18n";
import { deleteAddress } from '../../apollo/server' import { deleteAddress } from "../../apollo/server";
import EmptyAddress from '../../assets/images/SVG/imageComponents/EmptyAddress' import EmptyAddress from "../../assets/images/SVG/imageComponents/EmptyAddress";
import { import {
CustomIcon, CustomIcon,
RightButton, RightButton,
TextDefault, TextDefault,
WrapperView WrapperView,
} from '../../components' } from "../../components";
import UserContext from '../../context/User' import UserContext from "../../context/User";
import { COLORS } from '../../Theme' import { COLORS } from "../../Theme";
import { alignment } from '../../utils/alignment' import { alignment } from "../../utils/alignment";
import { ICONS_NAME, NAVIGATION_SCREEN } from '../../utils/constant' import { ICONS_NAME, NAVIGATION_SCREEN } from "../../utils/constant";
import { scale } from '../../utils/scaling' import { scale } from "../../utils/scaling";
import useStyle from './styles' import useStyle from "./styles";
const DELETE_ADDRESS = gql` const DELETE_ADDRESS = gql`
${deleteAddress} ${deleteAddress}
` `;
function Addresses() { function Addresses() {
const styles = useStyle() const styles = useStyle();
const { colors } = useTheme() const { colors } = useTheme();
const navigation = useNavigation() const navigation = useNavigation();
const { profile } = useContext(UserContext) const { profile } = useContext(UserContext);
const [mutate, { loading: loadingMutation }] = useMutation(DELETE_ADDRESS) const [mutate, { loading: loadingMutation }] = useMutation(DELETE_ADDRESS);
useLayoutEffect(() => { useLayoutEffect(() => {
navigation.setOptions({ navigation.setOptions({
title: i18n.t('myAddresses'), title: i18n.t("myAddresses"),
headerRight: () => ( headerRight: () => (
<RightButton <RightButton
icon={ICONS_NAME.Plus} icon={ICONS_NAME.Plus}
iconSize={scale(18)} iconSize={scale(18)}
onPress={() => navigation.navigate(NAVIGATION_SCREEN.NewAddress)} onPress={() => navigation.navigate(NAVIGATION_SCREEN.NewAddress)}
/> />
) ),
}) });
}, [navigation]) }, [navigation]);
const addressIcons = { const addressIcons = {
Home: ICONS_NAME.Home, Home: ICONS_NAME.Home,
Work: ICONS_NAME.Cart, Work: ICONS_NAME.Cart,
Other: ICONS_NAME.Location Other: ICONS_NAME.Location,
} };
const colorIcons = { const colorIcons = {
Other: COLORS.primary, Other: COLORS.primary,
Home: COLORS.redishPink, Home: COLORS.redishPink,
Work: COLORS.primaryLightBlue Work: COLORS.primaryLightBlue,
} };
const emptyView = React.memo(() => { const emptyView = React.memo(() => {
return ( return (
@ -66,28 +66,30 @@ function Addresses() {
textColor={colors.fontMainColor} textColor={colors.fontMainColor}
bold bold
H5 H5
style={alignment.Msmall}> style={alignment.Msmall}
>
No Addresses found. No Addresses found.
</TextDefault> </TextDefault>
<View> <View>
<TextDefault textColor={colors.fontSecondColor}> <TextDefault textColor={colors.fontSecondColor}>
You haven&#39;t saved any address yet. You haven&#39;t saved any address yet.
{'\n'} {"\n"}
Click Add New Address to get started Click Add New Address to get started
</TextDefault> </TextDefault>
</View> </View>
<TouchableOpacity <TouchableOpacity
activeOpacity={0.8} activeOpacity={0.8}
style={styles.adressBtn} style={styles.adressBtn}
onPress={() => navigation.navigate(NAVIGATION_SCREEN.NewAddress)}> onPress={() => navigation.navigate(NAVIGATION_SCREEN.NewAddress)}
>
<TextDefault textColor={colors.white} H5 bold> <TextDefault textColor={colors.white} H5 bold>
Add New Address Add New Address
</TextDefault> </TextDefault>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</View> </View>
) );
}) });
return ( return (
<WrapperView> <WrapperView>
<View style={styles.containerInfo}> <View style={styles.containerInfo}>
@ -101,7 +103,8 @@ function Addresses() {
: { flexGrow: 1 } : { flexGrow: 1 }
} }
ListEmptyComponent={emptyView} ListEmptyComponent={emptyView}
keyExtractor={item => item._id} // keyExtractor={(item) => item._id}
keyExtractor={(item, index) => String(index)}
ItemSeparatorComponent={() => <View style={styles.line} />} ItemSeparatorComponent={() => <View style={styles.line} />}
ListHeaderComponent={() => <View style={alignment.MTmedium} />} ListHeaderComponent={() => <View style={alignment.MTmedium} />}
renderItem={({ item: address }) => ( renderItem={({ item: address }) => (
@ -110,16 +113,18 @@ function Addresses() {
style={styles.width100} style={styles.width100}
onPress={() => { onPress={() => {
navigation.navigate(NAVIGATION_SCREEN.EditAddress, { navigation.navigate(NAVIGATION_SCREEN.EditAddress, {
...address ...address,
}) });
}}> }}
>
<View style={[styles.titleAddress, styles.width100]}> <View style={[styles.titleAddress, styles.width100]}>
<View <View
style={{ style={{
alignItems: 'center', alignItems: "center",
flexDirection: 'row', flexDirection: "row",
flex: 1 flex: 1,
}}> }}
>
<CustomIcon <CustomIcon
name={addressIcons[address.label]} name={addressIcons[address.label]}
size={scale(20)} size={scale(20)}
@ -128,7 +133,8 @@ function Addresses() {
<TextDefault <TextDefault
bold bold
H5 H5
style={[alignment.MTxSmall, alignment.MLsmall]}> style={[alignment.MTxSmall, alignment.MLsmall]}
>
{address.label} {address.label}
</TextDefault> </TextDefault>
</View> </View>
@ -139,9 +145,10 @@ function Addresses() {
style={[styles.iconButton, alignment.MRsmall]} style={[styles.iconButton, alignment.MRsmall]}
onPress={() => { onPress={() => {
navigation.navigate(NAVIGATION_SCREEN.EditAddress, { navigation.navigate(NAVIGATION_SCREEN.EditAddress, {
...address ...address,
}) });
}}> }}
>
<CustomIcon <CustomIcon
name={ICONS_NAME.Pencil} name={ICONS_NAME.Pencil}
size={scale(20)} size={scale(20)}
@ -154,8 +161,9 @@ function Addresses() {
disabled={loadingMutation} disabled={loadingMutation}
style={styles.iconButton} style={styles.iconButton}
onPress={() => { onPress={() => {
mutate({ variables: { id: address._id } }) mutate({ variables: { id: address._id } });
}}> }}
>
<CustomIcon <CustomIcon
name={ICONS_NAME.Trash} name={ICONS_NAME.Trash}
size={scale(20)} size={scale(20)}
@ -175,11 +183,12 @@ function Addresses() {
/> />
<TextDefault <TextDefault
textColor={colors.fontSecondColor} textColor={colors.fontSecondColor}
style={alignment.MBsmall}> style={alignment.MBsmall}
>
All rights are reserved by Enatega All rights are reserved by Enatega
</TextDefault> </TextDefault>
</View> </View>
</WrapperView> </WrapperView>
) );
} }
export default React.memo(Addresses) export default React.memo(Addresses);

View File

@ -1,56 +1,56 @@
import { useMutation } from '@apollo/react-hooks' import { useMutation } from "@apollo/react-hooks";
import { useNavigation, useTheme } from '@react-navigation/native' import { useNavigation, useTheme } from "@react-navigation/native";
import gql from 'graphql-tag' import gql from "graphql-tag";
import React, { useContext, useLayoutEffect } from 'react' import React, { useContext, useLayoutEffect } from "react";
import { FlatList, TouchableOpacity, View } from 'react-native' import { FlatList, TouchableOpacity, View } from "react-native";
import i18n from '../../../i18n' import i18n from "../../../i18n";
import { selectAddress } from '../../apollo/server' import { selectAddress } from "../../apollo/server";
import { import {
CustomIcon, CustomIcon,
RightButton, RightButton,
TextDefault, TextDefault,
WrapperView WrapperView,
} from '../../components' } from "../../components";
import RadioButton from '../../components/FdRadioBtn/RadioBtn' import RadioButton from "../../components/FdRadioBtn/RadioBtn";
import UserContext from '../../context/User' import UserContext from "../../context/User";
import { alignment } from '../../utils/alignment' import { alignment } from "../../utils/alignment";
import { ICONS_NAME, NAVIGATION_SCREEN } from '../../utils/constant' import { ICONS_NAME, NAVIGATION_SCREEN } from "../../utils/constant";
import { scale } from '../../utils/scaling' import { scale } from "../../utils/scaling";
import useStyle from './styles' import useStyle from "./styles";
const SELECT_ADDRESS = gql` const SELECT_ADDRESS = gql`
${selectAddress} ${selectAddress}
` `;
function CartAddresses() { function CartAddresses() {
const { colors } = useTheme() const { colors } = useTheme();
const styles = useStyle() const styles = useStyle();
const navigation = useNavigation() const navigation = useNavigation();
const { profile } = useContext(UserContext) const { profile } = useContext(UserContext);
const [mutate] = useMutation(SELECT_ADDRESS, { onError }) const [mutate] = useMutation(SELECT_ADDRESS, { onError });
useLayoutEffect(() => { useLayoutEffect(() => {
navigation.setOptions({ navigation.setOptions({
title: i18n.t('myAddresses'), title: i18n.t("myAddresses"),
headerRight: () => ( headerRight: () => (
<RightButton <RightButton
icon={ICONS_NAME.Plus} icon={ICONS_NAME.Plus}
iconSize={scale(18)} iconSize={scale(18)}
onPress={() => navigation.navigate(NAVIGATION_SCREEN.NewAddress)} onPress={() => navigation.navigate(NAVIGATION_SCREEN.NewAddress)}
/> />
) ),
}) });
}, [navigation]) }, [navigation]);
function onError(error) { function onError(error) {
console.log(error) console.log(error);
} }
const onSelectAddress = address => { const onSelectAddress = (address) => {
mutate({ variables: { id: address._id } }) mutate({ variables: { id: address._id } });
navigation.goBack() navigation.goBack();
} };
return ( return (
<WrapperView> <WrapperView>
@ -59,7 +59,7 @@ function CartAddresses() {
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
style={styles.flex} style={styles.flex}
data={profile.addresses} data={profile.addresses}
keyExtractor={item => item._id} keyExtractor={(item, index) => String(index)}
contentContainerStyle={styles.contentContainer} contentContainerStyle={styles.contentContainer}
ItemSeparatorComponent={() => <View style={styles.line} />} ItemSeparatorComponent={() => <View style={styles.line} />}
ListHeaderComponent={() => <View style={{ ...alignment.MTmedium }} />} ListHeaderComponent={() => <View style={{ ...alignment.MTmedium }} />}
@ -69,8 +69,9 @@ function CartAddresses() {
activeOpacity={0.7} activeOpacity={0.7}
style={styles.width100} style={styles.width100}
onPress={() => { onPress={() => {
onSelectAddress(address) onSelectAddress(address);
}}> }}
>
<View style={styles.width100}> <View style={styles.width100}>
<View style={[styles.titleAddress, styles.width100]}> <View style={[styles.titleAddress, styles.width100]}>
<View style={[styles.homeIcon]}> <View style={[styles.homeIcon]}>
@ -78,14 +79,14 @@ function CartAddresses() {
size={10} size={10}
outerColor={colors.radioOuterColor} outerColor={colors.radioOuterColor}
innerColor={colors.radioColor} innerColor={colors.radioColor}
animation={'bounceIn'} animation={"bounceIn"}
isSelected={address.selected} isSelected={address.selected}
onPress={() => { onPress={() => {
onSelectAddress(address) onSelectAddress(address);
}} }}
/> />
</View> </View>
<TextDefault style={{ width: '70%' }} H5 bold> <TextDefault style={{ width: "70%" }} H5 bold>
{address.label} {address.label}
</TextDefault> </TextDefault>
<TouchableOpacity <TouchableOpacity
@ -93,9 +94,10 @@ function CartAddresses() {
style={styles.editButton} style={styles.editButton}
onPress={() => onPress={() =>
navigation.navigate(NAVIGATION_SCREEN.EditAddress, { navigation.navigate(NAVIGATION_SCREEN.EditAddress, {
...address ...address,
}) })
}> }
>
<CustomIcon <CustomIcon
name={ICONS_NAME.Pencil} name={ICONS_NAME.Pencil}
size={scale(20)} size={scale(20)}
@ -108,13 +110,15 @@ function CartAddresses() {
<TextDefault <TextDefault
line={4} line={4}
textColor={colors.fontSecondColor} textColor={colors.fontSecondColor}
bold> bold
>
{address.delivery_address} {address.delivery_address}
</TextDefault> </TextDefault>
<TextDefault <TextDefault
line={3} line={3}
textColor={colors.fontSecondColor} textColor={colors.fontSecondColor}
bold> bold
>
{address.details} {address.details}
</TextDefault> </TextDefault>
</View> </View>
@ -125,7 +129,7 @@ function CartAddresses() {
/> />
</View> </View>
</WrapperView> </WrapperView>
) );
} }
export default CartAddresses export default CartAddresses;

View File

@ -1,90 +1,90 @@
import { Feather, FontAwesome } from '@expo/vector-icons' import { Feather, FontAwesome } from "@expo/vector-icons";
import { useNavigation, useTheme } from '@react-navigation/native' import { useNavigation, useTheme } from "@react-navigation/native";
import React, { useCallback, useEffect, useState } from 'react' import React, { useCallback, useEffect, useState } from "react";
import { Keyboard, View } from 'react-native' import { Keyboard, View } from "react-native";
import { import {
Bubble, Bubble,
GiftedChat, GiftedChat,
InputToolbar, InputToolbar,
Send Send,
} from 'react-native-gifted-chat' } from "react-native-gifted-chat";
import { TextDefault, WrapperView } from '../../components' import { TextDefault, WrapperView } from "../../components";
import { alignment } from '../../utils/alignment' import { alignment } from "../../utils/alignment";
import { scale } from '../../utils/scaling' import { scale } from "../../utils/scaling";
import useStyle from './styles' import useStyle from "./styles";
const UserInfo = { const UserInfo = {
_id: 1, _id: 1,
name: 'Jason', name: "Jason",
active: true active: true,
} };
function Chat() { function Chat() {
const styles = useStyle() const styles = useStyle();
const { colors } = useTheme() const { colors } = useTheme();
const navigation = useNavigation() const navigation = useNavigation();
const [messages, setMessages] = useState([]) const [messages, setMessages] = useState([]);
const [isTyping, setIsTyping] = useState(false) const [isTyping, setIsTyping] = useState(false);
useEffect(() => { useEffect(() => {
Keyboard.addListener('keyboardDidShow', _keyboardDidShow) Keyboard.addListener("keyboardDidShow", _keyboardDidShow);
Keyboard.addListener('keyboardDidHide', _keyboardDidHide) Keyboard.addListener("keyboardDidHide", _keyboardDidHide);
// cleanup function // cleanup function
return () => { return () => {
Keyboard.removeListener('keyboardDidShow', _keyboardDidShow) Keyboard.remove("keyboardDidShow", _keyboardDidShow);
Keyboard.removeListener('keyboardDidHide', _keyboardDidHide) Keyboard.remove("keyboardDidHide", _keyboardDidHide);
} };
}, []) }, []);
const _keyboardDidShow = () => setIsTyping(true) const _keyboardDidShow = () => setIsTyping(true);
const _keyboardDidHide = () => setIsTyping(false) const _keyboardDidHide = () => setIsTyping(false);
useEffect(() => { useEffect(() => {
navigation.setOptions({ navigation.setOptions({
title: 'Chat' title: "Chat",
}) });
setMessages([ setMessages([
{ {
_id: 1, _id: 1,
text: 'How can I help you?', text: "How can I help you?",
sent: true, sent: true,
received: true, received: true,
createdAt: new Date(), createdAt: new Date(),
user: { user: {
_id: 2, _id: 2,
name: 'React Native', name: "React Native",
avatar: 'https://placeimg.com/140/140/any' avatar: "https://placeimg.com/140/140/any",
} },
} },
]) ]);
}, [navigation]) }, [navigation]);
const onSend = useCallback((messages = []) => { const onSend = useCallback((messages = []) => {
setMessages(previousMessages => setMessages((previousMessages) =>
GiftedChat.append(previousMessages, messages) GiftedChat.append(previousMessages, messages)
) );
}, []) }, []);
const renderBubble = props => { const renderBubble = (props) => {
return ( return (
<Bubble <Bubble
{...props} {...props}
textStyle={{ textStyle={{
right: { right: {
color: colors.fontMainColor color: colors.fontMainColor,
}, },
left: { left: {
color: colors.fontMainColor color: colors.fontMainColor,
} },
}} }}
bottomContainerStyle={{ bottomContainerStyle={{
right: { right: {
...alignment.PTxSmall ...alignment.PTxSmall,
}, },
left: { left: {
...alignment.PTxSmall ...alignment.PTxSmall,
} },
}} }}
wrapperStyle={{ wrapperStyle={{
right: { right: {
@ -99,11 +99,11 @@ function Chat() {
shadowColor: colors.shadowColor, shadowColor: colors.shadowColor,
shadowOffset: { shadowOffset: {
width: 0, width: 0,
height: 1 height: 1,
}, },
shadowOpacity: 0.2, shadowOpacity: 0.2,
shadowRadius: 2, shadowRadius: 2,
elevation: 3 elevation: 3,
}, },
left: { left: {
minWidth: 150, minWidth: 150,
@ -117,36 +117,36 @@ function Chat() {
shadowColor: colors.shadowColor, shadowColor: colors.shadowColor,
shadowOffset: { shadowOffset: {
width: 0, width: 0,
height: 1 height: 1,
}, },
shadowOpacity: 0.2, shadowOpacity: 0.2,
shadowRadius: 2, shadowRadius: 2,
elevation: 3 elevation: 3,
} },
}} }}
/> />
) );
} };
const renderSend = props => ( const renderSend = (props) => (
<Send {...props} containerStyle={styles.sendBtn}> <Send {...props} containerStyle={styles.sendBtn}>
<View style={styles.rightBtn}> <View style={styles.rightBtn}>
<Feather <Feather
name={'send'} name={"send"}
color={colors.buttonText} color={colors.buttonText}
size={scale(17)} size={scale(17)}
style={{ style={{
transform: [ transform: [
{ rotateZ: '45deg' }, { rotateZ: "45deg" },
{ translateY: 2 }, { translateY: 2 },
{ translateX: -1 } { translateX: -1 },
] ],
}} }}
/> />
</View> </View>
</Send> </Send>
) );
const customtInputToolbar = props => { const customtInputToolbar = (props) => {
return ( return (
<InputToolbar <InputToolbar
{...props} {...props}
@ -154,8 +154,8 @@ function Chat() {
renderSend={renderSend} renderSend={renderSend}
render render
/> />
) );
} };
return ( return (
<WrapperView> <WrapperView>
@ -166,7 +166,7 @@ function Chat() {
color={UserInfo.active ? colors.active : colors.fontSecondColor} color={UserInfo.active ? colors.active : colors.fontSecondColor}
/> />
<TextDefault medium H5 style={alignment.PLsmall}> <TextDefault medium H5 style={alignment.PLsmall}>
{UserInfo.active ? UserInfo.name : 'Offline'} {UserInfo.active ? UserInfo.name : "Offline"}
</TextDefault> </TextDefault>
</View> </View>
<GiftedChat <GiftedChat
@ -175,7 +175,7 @@ function Chat() {
user={UserInfo} user={UserInfo}
isTyping={isTyping} isTyping={isTyping}
messages={messages} messages={messages}
onSend={messages => onSend(messages)} onSend={(messages) => onSend(messages)}
renderAvatar={() => null} renderAvatar={() => null}
renderBubble={renderBubble} renderBubble={renderBubble}
renderInputToolbar={customtInputToolbar} renderInputToolbar={customtInputToolbar}
@ -192,20 +192,20 @@ function Chat() {
// } // }
timeTextStyle={{ timeTextStyle={{
left: { left: {
width: '100%', width: "100%",
color: colors.fontMainColor, color: colors.fontMainColor,
fontSize: 11, fontSize: 11,
textAlign: 'right' textAlign: "right",
}, },
right: { right: {
color: colors.fontMainColor, color: colors.fontMainColor,
fontSize: 11 fontSize: 11,
} },
}} }}
/> />
</View> </View>
</WrapperView> </WrapperView>
) );
} }
export default Chat export default Chat;

View File

@ -1,152 +1,158 @@
import { useMutation } from '@apollo/react-hooks' import { useMutation } from "@apollo/react-hooks";
import { FontAwesome } from '@expo/vector-icons' import { FontAwesome } from "@expo/vector-icons";
import { useNavigation, useTheme } from '@react-navigation/native' import { useNavigation, useTheme } from "@react-navigation/native";
import * as AppAuth from 'expo-app-auth'
import * as AppleAuthentication from 'expo-apple-authentication' import * as AppleAuthentication from "expo-apple-authentication";
import Constants from 'expo-constants' import Constants from "expo-constants";
import * as Facebook from 'expo-facebook'
import * as Google from 'expo-google-app-auth' //import * as Google from 'expo-google-app-auth'
import * as Notifications from 'expo-notifications' import * as Google from "expo-auth-session/providers/google";
import gql from 'graphql-tag' import * as Notifications from "expo-notifications";
import React, { useContext, useEffect, useState } from 'react' import gql from "graphql-tag";
import { Platform, TouchableOpacity, View } from 'react-native' import React, { useContext, useEffect, useState } from "react";
import getEnvVars from '../../../environment' import { Platform, TouchableOpacity, View } from "react-native";
import { login } from '../../apollo/server' import getEnvVars from "../../../environment";
import { login } from "../../apollo/server";
import { import {
EnategaImage, EnategaImage,
FdEmailBtn, FdEmailBtn,
FdFacebookBtn,
FdGoogleBtn, FdGoogleBtn,
FlashMessage, FlashMessage,
RegistrationHeader, RegistrationHeader,
Spinner, Spinner,
TextDefault, TextDefault,
WrapperView WrapperView,
} from '../../components' } from "../../components";
import UserContext from '../../context/User' import UserContext from "../../context/User";
import { alignment } from '../../utils/alignment' import { alignment } from "../../utils/alignment";
import Analytics from '../../utils/analytics' import Analytics from "../../utils/analytics";
import { NAVIGATION_SCREEN } from '../../utils/constant' import { NAVIGATION_SCREEN } from "../../utils/constant";
import { scale } from '../../utils/scaling' import { scale } from "../../utils/scaling";
import useStyle from './styles' import useStyle from "./styles";
import ApolloClient from "apollo-client";
const { IOS_CLIENT_ID_GOOGLE, ANDROID_CLIENT_ID_GOOGLE, FACEBOOK_APP_ID } = const {
getEnvVars() IOS_CLIENT_ID_GOOGLE,
ANDROID_CLIENT_ID_GOOGLE,
Expo_CLIENT_ID_GOOGLE,
} = getEnvVars();
const LOGIN = gql` const LOGIN = gql`
${login} ${login}
` `;
const Logo = require('../../../assets/logo.png') const Logo = require("../../../assets/logo.png");
const CreateAccount = () => { const CreateAccount = () => {
const styles = useStyle() const styles = useStyle();
const { colors } = useTheme() const { colors } = useTheme();
const navigation = useNavigation() const navigation = useNavigation();
const [enableApple, setEnableApple] = useState(false) const [enableApple, setEnableApple] = useState(false);
const [loginButton, loginButtonSetter] = useState(null) const [loginButton, loginButtonSetter] = useState(null);
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false);
const { setTokenAsync } = useContext(UserContext) const { setTokenAsync } = useContext(UserContext);
useEffect(() => { useEffect(() => {
checkIfSupportsAppleAuthentication() checkIfSupportsAppleAuthentication();
}, []) }, []);
const [mutate] = useMutation(LOGIN, { onCompleted, onError }) const [mutate] = useMutation(LOGIN, { onCompleted, onError });
async function checkIfSupportsAppleAuthentication() { async function checkIfSupportsAppleAuthentication() {
setEnableApple(await AppleAuthentication.isAvailableAsync()) setEnableApple(await AppleAuthentication.isAvailableAsync());
} }
async function onCompleted(data) { async function onCompleted(data) {
try { try {
const trackingOpts = { const trackingOpts = {
id: data.login.userId, id: data.login.userId,
usernameOrEmail: data.login.email usernameOrEmail: data.login.email,
} };
Analytics.identify(data.login.userId, trackingOpts) Analytics.identify(data.login.userId, trackingOpts);
Analytics.track(Analytics.events.USER_CREATED_ACCOUNT, trackingOpts) Analytics.track(Analytics.events.USER_CREATED_ACCOUNT, trackingOpts);
setTokenAsync(data.login.token) setTokenAsync(data.login.token);
navigation.navigate(NAVIGATION_SCREEN.Menu) navigation.navigate(NAVIGATION_SCREEN.Menu);
} catch (e) { } catch (e) {
console.log(e) console.log(e);
} finally { } finally {
setLoading(false) setLoading(false);
} }
} }
function onError(error) { function onError(error) {
try { try {
console.log(JSON.stringify(error)) console.log(JSON.stringify(error));
FlashMessage({ FlashMessage({
message: error.graphQLErrors[0].message message: error.graphQLErrors[0].message,
}) });
loginButtonSetter(null) loginButtonSetter(null);
} catch (e) { } catch (e) {
console.log(e) console.log(e);
} finally { } finally {
setLoading(false) setLoading(false);
} }
} }
async function mutateLogin(user) { async function mutateLogin(user) {
setLoading(true) setLoading(true);
let notificationToken = null let notificationToken = null;
if (Constants.isDevice) { if (Constants.isDevice) {
const { status: existingStatus } = const { status: existingStatus } =
await Notifications.getPermissionsAsync() await Notifications.getPermissionsAsync();
if (existingStatus === 'granted') { if (existingStatus === "granted") {
notificationToken = (await Notifications.getExpoPushTokenAsync()).data notificationToken = (await Notifications.getExpoPushTokenAsync()).data;
} }
} }
mutate({ variables: { ...user, notificationToken } }) mutate({ variables: { ...user, notificationToken } });
} }
function renderAppleAction() { function renderAppleAction() {
if (loading && loginButton === 'Apple') { if (loading && loginButton === "Apple") {
return ( return (
<View style={styles.buttonBackground}> <View style={styles.buttonBackground}>
<Spinner backColor="rgba(0,0,0,0.1)" spinnerColor={colors.tagColor} /> <Spinner backColor="rgba(0,0,0,0.1)" spinnerColor={colors.tagColor} />
</View> </View>
) );
} }
return ( return (
<TouchableOpacity <TouchableOpacity
style={styles.appleBtn} style={styles.appleBtn}
onPress={async() => { onPress={async () => {
try { try {
const credential = await AppleAuthentication.signInAsync({ const credential = await AppleAuthentication.signInAsync({
requestedScopes: [ requestedScopes: [
AppleAuthentication.AppleAuthenticationScope.FULL_NAME, AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
AppleAuthentication.AppleAuthenticationScope.EMAIL AppleAuthentication.AppleAuthenticationScope.EMAIL,
] ],
}) });
console.log(credential);
if (credential) { if (credential) {
const user = { const user = {
appleId: credential.user, appleId: credential.user,
phone: '', phone: "",
email: credential.email, email: credential.email,
password: '', password: "",
name: name:
credential.fullName.givenName + credential.fullName.givenName +
' ' + " " +
credential.fullName.familyName, credential.fullName.familyName,
picture: '', picture: "",
type: 'apple' type: "apple",
} };
mutateLogin(user) mutateLogin(user);
} }
loginButtonSetter('Apple') loginButtonSetter("Apple");
// signed in // signed in
} catch (e) { } catch (e) {
if (e.code === 'ERR_CANCELLED') { if (e.code === "ERR_CANCELLED") {
// handle that the user canceled the sign-in flow // handle that the user canceled the sign-in flow
loginButtonSetter(null) loginButtonSetter(null);
} else { } else {
// handle other errors // handle other errors
loginButtonSetter(null) loginButtonSetter(null);
} }
} }
}}> }}
>
<FontAwesome <FontAwesome
style={styles.marginLeft5} style={styles.marginLeft5}
name="apple" name="apple"
@ -157,116 +163,78 @@ const CreateAccount = () => {
Signup with Apple Signup with Apple
</TextDefault> </TextDefault>
</TouchableOpacity> </TouchableOpacity>
) );
} }
async function _facebookSignup() { const [googleRequest, googleResponse, googlePromptAsync] =
try { Google.useAuthRequest({
await Facebook.initializeAsync({ appId: FACEBOOK_APP_ID }) expoClientId: Expo_CLIENT_ID_GOOGLE,
} catch (err) { iosClientId: IOS_CLIENT_ID_GOOGLE,
console.log('err', err) iosStandaloneAppClientId: IOS_CLIENT_ID_GOOGLE,
} androidClientId: ANDROID_CLIENT_ID_GOOGLE,
androidStandaloneAppClientId: ANDROID_CLIENT_ID_GOOGLE,
//redirectUrl: `${AuthSession.OAuthRedirect}:/oauth2redirect/google`,
scopes: ["profile", "email"],
...{ useProxy: true },
});
try { const googleSignUp = () => {
const { type, token } = await Facebook.logInWithReadPermissionsAsync({ if (googleResponse?.type === "success") {
permissions: ['public_profile', 'email'] const { authentication } = googleResponse;
}) console.log(authentication.accessToken);
if (type === 'success') { (async () => {
// Get the user's name using Facebook's Graph API const userInfoResponse = await fetch(
const response = await fetch( "https://www.googleapis.com/oauth2/v1/userinfo?alt=json",
`https://graph.facebook.com/me?access_token=${token}&fields=email,name` {
) headers: { Authorization: `Bearer ${authentication.accessToken}` },
const user = await response.json()
return user
}
} catch (err) {
console.log('error', err)
}
}
async function _googleSignup() {
try {
const { type, user } = await Google.logInAsync({
iosClientId: IOS_CLIENT_ID_GOOGLE,
iosStandaloneAppClientId: IOS_CLIENT_ID_GOOGLE,
androidClientId: ANDROID_CLIENT_ID_GOOGLE,
androidStandaloneAppClientId: ANDROID_CLIENT_ID_GOOGLE,
redirectUrl: `${AppAuth.OAuthRedirect}:/oauth2redirect/google`,
scopes: ['profile', 'email']
})
if (type === 'success') {
/* `accessToken` is now valid and can be used to get data from the Google API with HTTP requests */
return user
}
} catch (err) {
console.log('err', err)
}
}
function renderFacebookAction() {
return (
<FdFacebookBtn
loadingIcon={loading && loginButton === 'Facebook'}
onPressIn={() => {
loginButtonSetter('Facebook')
}}
onPress={async() => {
const facebookUser = await _facebookSignup()
if (facebookUser) {
const user = {
facebookId: facebookUser.id,
phone: '',
email: facebookUser.email,
password: '',
name: facebookUser.name,
picture: '',
type: 'facebook'
}
mutateLogin(user)
} }
}} );
/> const googleUser = await userInfoResponse.json();
) const user = {
} phone: "",
email: googleUser.email,
password: "",
name: googleUser.name,
picture: googleUser.picture,
type: "google",
};
mutateLogin(user);
})();
}
};
useEffect(() => {
googleSignUp();
}, [googleResponse]);
function renderGoogleAction() { function renderGoogleAction() {
return ( return (
<FdGoogleBtn <FdGoogleBtn
loadingIcon={loading && loginButton === 'Google'} loadingIcon={loading && loginButton === "Google"}
onPressIn={() => { onPressIn={() => {
loginButtonSetter('Google') loginButtonSetter("Google");
}}
onPress={async() => {
const googleUser = await _googleSignup()
if (googleUser) {
const user = {
phone: '',
email: googleUser.email,
password: '',
name: googleUser.name,
picture: googleUser.photoUrl,
type: 'google'
}
mutateLogin(user)
}
}} }}
disabled={!googleRequest}
onPress={() => googlePromptAsync()}
/> />
) );
} }
function renderEmailAction() { function renderEmailAction() {
return ( return (
<FdEmailBtn <FdEmailBtn
loadingIcon={loading && loginButton === 'Email'} loadingIcon={loading && loginButton === "Email"}
onPress={() => { onPress={() => {
loginButtonSetter('Email') loginButtonSetter("Email");
navigation.navigate(NAVIGATION_SCREEN.Register) navigation.navigate(NAVIGATION_SCREEN.Register);
}} }}
/> />
) );
} }
return ( return (
<WrapperView> <WrapperView>
<View style={[styles.mainContainer, styles.flex]}> <View style={[styles.mainContainer, styles.flex]}>
<RegistrationHeader title={'Get Started'} /> <RegistrationHeader title={"Get Started"} />
<View style={styles.subContainer}> <View style={styles.subContainer}>
<View style={[styles.flex, styles.upperContainer]}> <View style={[styles.flex, styles.upperContainer]}>
<EnategaImage <EnategaImage
@ -276,7 +244,6 @@ const CreateAccount = () => {
/> />
</View> </View>
<View style={styles.width100}> <View style={styles.width100}>
{Platform.OS === 'ios' && renderFacebookAction()}
<View style={alignment.MTmedium}>{renderGoogleAction()}</View> <View style={alignment.MTmedium}>{renderGoogleAction()}</View>
{enableApple && ( {enableApple && (
<View style={alignment.MTmedium}>{renderAppleAction()}</View> <View style={alignment.MTmedium}>{renderAppleAction()}</View>
@ -286,7 +253,8 @@ const CreateAccount = () => {
<TouchableOpacity <TouchableOpacity
activeOpacity={0.7} activeOpacity={0.7}
style={styles.alreadyBtn} style={styles.alreadyBtn}
onPress={() => navigation.navigate(NAVIGATION_SCREEN.Login)}> onPress={() => navigation.navigate(NAVIGATION_SCREEN.Login)}
>
<TextDefault style={[alignment.MLsmall]} bold> <TextDefault style={[alignment.MLsmall]} bold>
Already a member? Log in Already a member? Log in
</TextDefault> </TextDefault>
@ -295,6 +263,6 @@ const CreateAccount = () => {
</View> </View>
</View> </View>
</WrapperView> </WrapperView>
) );
} };
export default CreateAccount export default CreateAccount;

View File

@ -1,51 +1,51 @@
import { useQuery } from '@apollo/react-hooks' import { useQuery } from "@apollo/react-hooks";
import { useNavigation } from '@react-navigation/native' import { useNavigation } from "@react-navigation/native";
import gql from 'graphql-tag' import gql from "graphql-tag";
import React, { useContext, useLayoutEffect } from 'react' import React, { useContext, useLayoutEffect } from "react";
import { FlatList, View } from 'react-native' import { FlatList, View } from "react-native";
import { categories } from '../../apollo/server' import { categories } from "../../apollo/server";
import EmptyFood from '../../assets/images/SVG/imageComponents/EmptyFood' import EmptyFood from "../../assets/images/SVG/imageComponents/EmptyFood";
import { import {
MenuCard, MenuCard,
Spinner, Spinner,
StatusCard, StatusCard,
TextDefault, TextDefault,
TextError, TextError,
WrapperView WrapperView,
} from '../../components' } from "../../components";
import UserContext from '../../context/User' import UserContext from "../../context/User";
import { alignment } from '../../utils/alignment' import { alignment } from "../../utils/alignment";
import { NAVIGATION_SCREEN } from '../../utils/constant' import { NAVIGATION_SCREEN } from "../../utils/constant";
import { scale } from '../../utils/scaling' import { scale } from "../../utils/scaling";
import useStyle from './styles' import useStyle from "./styles";
// constants // constants
const CATEGORIES = gql` const CATEGORIES = gql`
${categories} ${categories}
` `;
function Menu() { function Menu() {
const styles = useStyle() const styles = useStyle();
const navigation = useNavigation() const navigation = useNavigation();
const { isLoggedIn, profile } = useContext(UserContext) const { isLoggedIn, profile } = useContext(UserContext);
const { data, refetch, networkStatus, loading, error } = useQuery(CATEGORIES) const { data, refetch, networkStatus, loading, error } = useQuery(CATEGORIES);
useLayoutEffect(() => { useLayoutEffect(() => {
navigation.setOptions({ navigation.setOptions({
title: 'Home' title: "Home",
}) });
}, []) }, []);
function emptyView() { function emptyView() {
if (loading) { if (loading) {
return <Spinner /> return <Spinner />;
} else if (error) { } else if (error) {
return ( return (
<TextError <TextError
text={error ? error.message : 'No Foods'} text={error ? error.message : "No Foods"}
backColor="transparent" backColor="transparent"
/> />
) );
} else { } else {
return ( return (
<View style={styles.emptyContainer}> <View style={styles.emptyContainer}>
@ -54,7 +54,7 @@ function Menu() {
No item found No item found
</TextDefault> </TextDefault>
</View> </View>
) );
} }
} }
@ -65,7 +65,7 @@ function Menu() {
style={styles.flex} style={styles.flex}
contentContainerStyle={styles.contentContainer} contentContainerStyle={styles.contentContainer}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
keyExtractor={item => item._id} keyExtractor={(item, index) => String(index)}
ListEmptyComponent={emptyView()} ListEmptyComponent={emptyView()}
data={loading ? [] : error ? [] : data.categories} data={loading ? [] : error ? [] : data.categories}
refreshing={networkStatus === 4} refreshing={networkStatus === 4}
@ -80,28 +80,28 @@ function Menu() {
Featured Featured
</TextDefault> </TextDefault>
</> </>
) );
} }
return null return null;
}} }}
renderItem={({ item }) => ( renderItem={({ item }) => (
<View key={item._id} style={styles.cardViewContainer}> <View key={item._id} style={styles.cardViewContainer}>
<MenuCard <MenuCard
onPress={() => onPress={() =>
navigation.navigate(NAVIGATION_SCREEN.MenuItems, { navigation.navigate(NAVIGATION_SCREEN.MenuItems, {
...item ...item,
}) })
} }
title={item.title} title={item.title}
description={item.description} description={item.description}
image={item.img_menu || ''} image={item.img_menu || ""}
/> />
</View> </View>
)} )}
/> />
</View> </View>
</WrapperView> </WrapperView>
) );
} }
export default React.memo(Menu) export default React.memo(Menu);

View File

@ -1,19 +1,20 @@
import { useQuery } from '@apollo/react-hooks' import { useQuery } from "@apollo/react-hooks";
import { useNavigation, useRoute } from '@react-navigation/native' import { useNavigation, useRoute } from "@react-navigation/native";
import { useHeaderHeight } from '@react-navigation/stack' //import { useHeaderHeight } from '@react-navigation/stack'
import gql from 'graphql-tag' import { useHeaderHeight } from "@react-navigation/elements";
import { get } from 'lodash' import gql from "graphql-tag";
import React, { useContext, useLayoutEffect, useRef, useState } from 'react' import { get } from "lodash";
import React, { useContext, useLayoutEffect, useRef, useState } from "react";
import { import {
FlatList, FlatList,
ImageBackground, ImageBackground,
Platform, Platform,
TouchableOpacity, TouchableOpacity,
View View,
} from 'react-native' } from "react-native";
import { Modalize } from 'react-native-modalize' import { Modalize } from "react-native-modalize";
import { foods } from '../../apollo/server' import { foods } from "../../apollo/server";
import EmptyFood from '../../assets/images/SVG/imageComponents/EmptyFood' import EmptyFood from "../../assets/images/SVG/imageComponents/EmptyFood";
import { import {
EnategaImage, EnategaImage,
FilterModal, FilterModal,
@ -22,40 +23,40 @@ import {
Spinner, Spinner,
TextDefault, TextDefault,
TextError, TextError,
WrapperView WrapperView,
} from '../../components' } from "../../components";
import ConfigurationContext from '../../context/Configuration' import ConfigurationContext from "../../context/Configuration";
import UserContext from '../../context/User' import UserContext from "../../context/User";
import { alignment } from '../../utils/alignment' import { alignment } from "../../utils/alignment";
import { ICONS_NAME, NAVIGATION_SCREEN, SORT_DATA } from '../../utils/constant' import { ICONS_NAME, NAVIGATION_SCREEN, SORT_DATA } from "../../utils/constant";
import { moderateScale, scale } from '../../utils/scaling' import { moderateScale, scale } from "../../utils/scaling";
import useStyle from './styles' import useStyle from "./styles";
// constants // constants
const FOODS = gql` const FOODS = gql`
${foods} ${foods}
` `;
function MenuItems() { function MenuItems() {
const route = useRoute() const route = useRoute();
const styles = useStyle() const styles = useStyle();
const headerHeight = useHeaderHeight() const headerHeight = useHeaderHeight();
const navigation = useNavigation() const navigation = useNavigation();
const _id = route.params._id ?? null const _id = route.params._id ?? null;
const imgMenu = route.params.img_menu ?? null const imgMenu = route.params.img_menu ?? null;
const title = route.params.title ?? null const title = route.params.title ?? null;
const description = route.params.description ?? null const description = route.params.description ?? null;
const [filters, setFilters] = useState({}) const [filters, setFilters] = useState({});
const { loading, error, data, refetch, networkStatus } = useQuery(FOODS, { const { loading, error, data, refetch, networkStatus } = useQuery(FOODS, {
variables: { category: _id, ...filters } variables: { category: _id, ...filters },
}) });
const { addCartItem } = useContext(UserContext) const { addCartItem } = useContext(UserContext);
const configuration = useContext(ConfigurationContext) const configuration = useContext(ConfigurationContext);
const modalizeRef = useRef(null) const modalizeRef = useRef(null);
const closeModal = () => { const closeModal = () => {
modalizeRef.current.close() modalizeRef.current.close();
} };
useLayoutEffect(() => { useLayoutEffect(() => {
navigation.setOptions({ navigation.setOptions({
@ -65,26 +66,26 @@ function MenuItems() {
icon={ICONS_NAME.Filter} icon={ICONS_NAME.Filter}
onPress={() => modalizeRef.current.open()} onPress={() => modalizeRef.current.open()}
/> />
) ),
}) });
}, [navigation]) }, [navigation]);
async function onAddToCart(food) { async function onAddToCart(food) {
if (food.stock < 1) { if (food.stock < 1) {
FlashMessage({ FlashMessage({
message: 'Item out of stock' message: "Item out of stock",
}) });
return return;
} }
if ( if (
food.variations.length === 1 && food.variations.length === 1 &&
food.variations[0].addons.length === 0 food.variations[0].addons.length === 0
) { ) {
await addCartItem(food._id, food.variations[0]._id) await addCartItem(food._id, food.variations[0]._id);
navigation.navigate(NAVIGATION_SCREEN.Cart) navigation.navigate(NAVIGATION_SCREEN.Cart);
} else { } else {
navigation.navigate(NAVIGATION_SCREEN.ItemDetail, { food }) navigation.navigate(NAVIGATION_SCREEN.ItemDetail, { food });
} }
} }
@ -92,19 +93,20 @@ function MenuItems() {
return ( return (
<TouchableOpacity <TouchableOpacity
onPress={() => { onPress={() => {
onAddToCart(item) onAddToCart(item);
}} }}
activeOpacity={0.7} activeOpacity={0.7}
style={styles.cardContainer}> style={styles.cardContainer}
>
<View style={styles.cardImageContainer}> <View style={styles.cardImageContainer}>
<EnategaImage <EnategaImage
imgStyle={styles.imgResponsive} imgStyle={styles.imgResponsive}
imgSource={ imgSource={
item.img_url item.img_url
? { uri: item.img_url } ? { uri: item.img_url }
: require('../../assets/images/food_placeholder.png') : require("../../assets/images/food_placeholder.png")
} }
resizeMode={'cover'} resizeMode={"cover"}
spinnerProps={{ style: styles.loadingView }} spinnerProps={{ style: styles.loadingView }}
/> />
{item.stock < 1 && ( {item.stock < 1 && (
@ -123,10 +125,11 @@ function MenuItems() {
numberOfLines={2} numberOfLines={2}
textColor={styles.lightColor.color} textColor={styles.lightColor.color}
small small
medium> medium
>
{item.description} {item.description}
</TextDefault> </TextDefault>
<View style={{ flexDirection: 'row', alignItems: 'center' }}> <View style={{ flexDirection: "row", alignItems: "center" }}>
{item.variations[0].discounted > 0 && ( {item.variations[0].discounted > 0 && (
<TextDefault <TextDefault
textColor={styles.lightColor.color} textColor={styles.lightColor.color}
@ -134,61 +137,62 @@ function MenuItems() {
small small
bold bold
H5 H5
lineOver> lineOver
{configuration.currency_symbol}{' '} >
{configuration.currency_symbol}{" "}
{( {(
item.variations[0].price + item.variations[0].discounted item.variations[0].price + item.variations[0].discounted
).toFixed(2)} ).toFixed(2)}
</TextDefault> </TextDefault>
)} )}
<TextDefault textColor={styles.tagColor.color} H4 bolder> <TextDefault textColor={styles.tagColor.color} H4 bolder>
{configuration.currency_symbol}{' '} {configuration.currency_symbol}{" "}
{item.variations[0].price.toFixed(2)} {item.variations[0].price.toFixed(2)}
</TextDefault> </TextDefault>
</View> </View>
</View> </View>
</TouchableOpacity> </TouchableOpacity>
) );
} }
function sortData(foods) { function sortData(foods) {
const VALUE = get(SORT_DATA, get(filters, 'sort')) const VALUE = get(SORT_DATA, get(filters, "sort"));
switch (VALUE) { switch (VALUE) {
case SORT_DATA.NameAsc: case SORT_DATA.NameAsc:
return foods.sort((a, b) => return foods.sort((a, b) =>
a.title.toLowerCase() > b.title.toLowerCase() ? 1 : -1 a.title.toLowerCase() > b.title.toLowerCase() ? 1 : -1
) );
case SORT_DATA.NameDesc: case SORT_DATA.NameDesc:
return foods.sort((a, b) => return foods.sort((a, b) =>
a.title.toLowerCase() < b.title.toLowerCase() ? 1 : -1 a.title.toLowerCase() < b.title.toLowerCase() ? 1 : -1
) );
case SORT_DATA.PriceAsc: case SORT_DATA.PriceAsc:
return foods.sort((a, b) => return foods.sort((a, b) =>
a.variations[0].price > b.variations[0].price ? 1 : -1 a.variations[0].price > b.variations[0].price ? 1 : -1
) );
case SORT_DATA.PriceDesc: case SORT_DATA.PriceDesc:
return foods.sort((a, b) => return foods.sort((a, b) =>
a.variations[0].price < b.variations[0].price ? 1 : -1 a.variations[0].price < b.variations[0].price ? 1 : -1
) );
default: default:
return foods.sort((a, b) => (a.img_url < b.img_url ? 1 : -1)) return foods.sort((a, b) => (a.img_url < b.img_url ? 1 : -1));
} }
} }
const setFilterss = filterObj => { const setFilterss = (filterObj) => {
setFilters(filterObj) setFilters(filterObj);
} };
function emptyView() { function emptyView() {
if (loading) { if (loading) {
return <Spinner /> return <Spinner />;
} else if (error) { } else if (error) {
return ( return (
<TextError <TextError
text={error ? error.message : 'No Foods'} text={error ? error.message : "No Foods"}
backColor="transparent" backColor="transparent"
/> />
) );
} else { } else {
return ( return (
<View style={styles.emptyContainer}> <View style={styles.emptyContainer}>
@ -197,7 +201,7 @@ function MenuItems() {
No food item found No food item found
</TextDefault> </TextDefault>
</View> </View>
) );
} }
} }
@ -210,27 +214,30 @@ function MenuItems() {
source={ source={
imgMenu imgMenu
? { uri: imgMenu } ? { uri: imgMenu }
: require('../../assets/images/food_placeholder.png') : require("../../assets/images/food_placeholder.png")
}> }
>
<View style={styles.shadeContainer}></View> <View style={styles.shadeContainer}></View>
<View style={styles.backgroundImageTextContainer}> <View style={styles.backgroundImageTextContainer}>
<TextDefault <TextDefault
numberOfLines={1} numberOfLines={1}
textColor={styles.whiteFont.color} textColor={styles.whiteFont.color}
H4 H4
bolder> bolder
>
{title} {title}
</TextDefault> </TextDefault>
<TextDefault <TextDefault
numberOfLines={1} numberOfLines={1}
textColor={styles.whiteFont.color} textColor={styles.whiteFont.color}
bold> bold
>
{description} {description}
</TextDefault> </TextDefault>
</View> </View>
</ImageBackground> </ImageBackground>
</View> </View>
) );
} }
return ( return (
<WrapperView> <WrapperView>
@ -240,13 +247,13 @@ function MenuItems() {
contentContainerStyle={styles.contentContaienr} contentContainerStyle={styles.contentContaienr}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
ListHeaderComponent={renderListHeader()} ListHeaderComponent={renderListHeader()}
keyExtractor={item => item._id} keyExtractor={(item, index) => String(index)}
ListEmptyComponent={emptyView} ListEmptyComponent={emptyView}
data={loading ? [] : error ? [] : sortData(data.foodByCategory)} data={loading ? [] : error ? [] : sortData(data.foodByCategory)}
refreshing={networkStatus === 4} refreshing={networkStatus === 4}
onRefresh={() => onRefresh={() =>
refetch({ refetch({
variables: { category: _id, ...filters } variables: { category: _id, ...filters },
}) })
} }
renderItem={({ item }) => renderGridCards(item)} renderItem={({ item }) => renderGridCards(item)}
@ -259,10 +266,11 @@ function MenuItems() {
modalTopOffset={headerHeight} modalTopOffset={headerHeight}
avoidKeyboardLikeIOS={Platform.select({ avoidKeyboardLikeIOS={Platform.select({
ios: true, ios: true,
android: false android: false,
})} })}
keyboardAvoidingOffset={2} keyboardAvoidingOffset={2}
keyboardAvoidingBehavior="height"> keyboardAvoidingBehavior="height"
>
<FilterModal <FilterModal
filterObj={filters} filterObj={filters}
setFilters={setFilterss} setFilters={setFilterss}
@ -270,6 +278,6 @@ function MenuItems() {
/> />
</Modalize> </Modalize>
</WrapperView> </WrapperView>
) );
} }
export default MenuItems export default MenuItems;

View File

@ -1,10 +1,10 @@
import { useApolloClient } from '@apollo/react-hooks' import { useApolloClient } from "@apollo/react-hooks";
import { useNavigation, useTheme } from '@react-navigation/native' import { useNavigation, useTheme } from "@react-navigation/native";
import React, { useContext, useLayoutEffect } from 'react' import React, { useContext, useLayoutEffect } from "react";
import { FlatList, TouchableOpacity, View } from 'react-native' import { FlatList, TouchableOpacity, View } from "react-native";
import uuid from 'uuid' import uuid from "uuid";
import i18n from '../../../i18n' import i18n from "../../../i18n";
import EmptyOrder from '../../assets/images/SVG/imageComponents/EmptyOrder' import EmptyOrder from "../../assets/images/SVG/imageComponents/EmptyOrder";
import { import {
ActiveOrders, ActiveOrders,
CustomIcon, CustomIcon,
@ -12,24 +12,24 @@ import {
Spinner, Spinner,
TextDefault, TextDefault,
TextError, TextError,
WrapperView WrapperView,
} from '../../components' } from "../../components";
import ConfigurationContext from '../../context/Configuration' import ConfigurationContext from "../../context/Configuration";
import UserContext from '../../context/User' import UserContext from "../../context/User";
import { alignment } from '../../utils/alignment' import { alignment } from "../../utils/alignment";
import { ICONS_NAME, NAVIGATION_SCREEN } from '../../utils/constant' import { ICONS_NAME, NAVIGATION_SCREEN } from "../../utils/constant";
import { scale } from '../../utils/scaling' import { scale } from "../../utils/scaling";
import useStyle from './style' import useStyle from "./style";
const orderStatusActive = ['PENDING', 'PICKED', 'ACCEPTED'] const orderStatusActive = ["PENDING", "PICKED", "ACCEPTED"];
const orderStatusInactive = ['DELIVERED', 'COMPLETED'] const orderStatusInactive = ["DELIVERED", "COMPLETED"];
function MyOrders() { function MyOrders() {
const styles = useStyle() const styles = useStyle();
const { colors } = useTheme() const { colors } = useTheme();
const client = useApolloClient() const client = useApolloClient();
const navigation = useNavigation() const navigation = useNavigation();
const configuration = useContext(ConfigurationContext) const configuration = useContext(ConfigurationContext);
const { const {
orders, orders,
loadingOrders, loadingOrders,
@ -37,47 +37,47 @@ function MyOrders() {
fetchOrders, fetchOrders,
fetchMoreOrdersFunc, fetchMoreOrdersFunc,
networkStatusOrders, networkStatusOrders,
updateCart updateCart,
} = useContext(UserContext) } = useContext(UserContext);
useLayoutEffect(() => { useLayoutEffect(() => {
navigation.setOptions({ navigation.setOptions({
headerTitle: i18n.t('titleOrders'), headerTitle: i18n.t("titleOrders"),
headerRight: null headerRight: null,
}) });
}, [navigation]) }, [navigation]);
// add items to cart and navigate to cart screen // add items to cart and navigate to cart screen
async function onReOrder({ order }) { async function onReOrder({ order }) {
const data = { const data = {
cartItems: order.items.map(item => { cartItems: order.items.map((item) => {
return { return {
...item.food, ...item.food,
key: uuid.v4(), key: uuid.v4(),
__typename: 'CartItem', __typename: "CartItem",
variation: { variation: {
__typename: 'ItemVariation', __typename: "ItemVariation",
_id: item.variation._id _id: item.variation._id,
}, },
quantity: item.quantity, quantity: item.quantity,
addons: item.addons.map(addon => ({ addons: item.addons.map((addon) => ({
...addon, ...addon,
__typename: 'ItemAddon', __typename: "ItemAddon",
options: addon.options.map(({ _id }) => ({ options: addon.options.map(({ _id }) => ({
_id, _id,
__typename: 'ItemOption' __typename: "ItemOption",
})) })),
})) })),
} };
}) }),
} };
await updateCart(data.cartItems) await updateCart(data.cartItems);
navigation.navigate(NAVIGATION_SCREEN.Cart) navigation.navigate(NAVIGATION_SCREEN.Cart);
} }
function emptyView() { function emptyView() {
if (loadingOrders) return <Spinner visible={loadingOrders} /> if (loadingOrders) return <Spinner visible={loadingOrders} />;
if (errorOrders) return <TextError text={errorOrders.message} /> if (errorOrders) return <TextError text={errorOrders.message} />;
else { else {
return ( return (
<View style={styles.subContainerImage}> <View style={styles.subContainerImage}>
@ -92,13 +92,14 @@ function MyOrders() {
<TouchableOpacity <TouchableOpacity
activeOpacity={0.7} activeOpacity={0.7}
style={styles.emptyButton} style={styles.emptyButton}
onPress={() => navigation.navigate(NAVIGATION_SCREEN.Menu)}> onPress={() => navigation.navigate(NAVIGATION_SCREEN.Menu)}
>
<TextDefault textColor={colors.buttonText} bold H5 center> <TextDefault textColor={colors.buttonText} bold H5 center>
Start Shopping Start Shopping
</TextDefault> </TextDefault>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
) );
} }
} }
@ -108,7 +109,7 @@ function MyOrders() {
data={ data={
loadingOrders || errorOrders loadingOrders || errorOrders
? [] ? []
: orders.filter(o => orderStatusInactive.includes(o.order_status)) : orders.filter((o) => orderStatusInactive.includes(o.order_status))
} }
style={styles.container} style={styles.container}
contentContainerStyle={styles.contentContainer} contentContainerStyle={styles.contentContainer}
@ -116,17 +117,18 @@ function MyOrders() {
ListHeaderComponent={ ListHeaderComponent={
<ActiveOrders <ActiveOrders
navigation={navigation} navigation={navigation}
activeOrders={orders.filter(o => activeOrders={orders.filter((o) =>
orderStatusActive.includes(o.order_status) orderStatusActive.includes(o.order_status)
)} )}
pastOrders={orders.filter(o => pastOrders={orders.filter((o) =>
orderStatusInactive.includes(o.order_status) orderStatusInactive.includes(o.order_status)
)} )}
loading={loadingOrders} loading={loadingOrders}
error={errorOrders} error={errorOrders}
/> />
} }
keyExtractor={item => item._id} //keyExtractor={(item) => item._id}
keyExtractor={(item, index) => String(index)}
refreshing={networkStatusOrders === 4} refreshing={networkStatusOrders === 4}
onRefresh={() => networkStatusOrders === 7 && fetchOrders()} onRefresh={() => networkStatusOrders === 7 && fetchOrders()}
renderItem={({ item }) => ( renderItem={({ item }) => (
@ -135,9 +137,10 @@ function MyOrders() {
onPress={() => onPress={() =>
navigation.navigate(NAVIGATION_SCREEN.OrderDetail, { navigation.navigate(NAVIGATION_SCREEN.OrderDetail, {
_id: item._id, _id: item._id,
currency_symbol: configuration.currency_symbol currency_symbol: configuration.currency_symbol,
}) })
}> }
>
<View style={styles.subContainer}> <View style={styles.subContainer}>
<View style={styles.imgContainer}> <View style={styles.imgContainer}>
<EnategaImage <EnategaImage
@ -148,7 +151,7 @@ function MyOrders() {
</View> </View>
<View style={styles.infoContainer}> <View style={styles.infoContainer}>
<TextDefault H5 bold style={alignment.MBxSmall}> <TextDefault H5 bold style={alignment.MBxSmall}>
{'ID: '} {"ID: "}
{item.order_id} {item.order_id}
</TextDefault> </TextDefault>
<TextDefault line={3} textColor={colors.tagColor} H5 medium> <TextDefault line={3} textColor={colors.tagColor} H5 medium>
@ -163,9 +166,10 @@ function MyOrders() {
<TouchableOpacity <TouchableOpacity
activeOpacity={0.8} activeOpacity={0.8}
onPress={() => onReOrder({ order: item, client })} onPress={() => onReOrder({ order: item, client })}
style={styles.subContainerRight}> style={styles.subContainerRight}
>
<View> <View>
<View style={{ alignSelf: 'center' }}> <View style={{ alignSelf: "center" }}>
<CustomIcon <CustomIcon
name={ICONS_NAME.Refresh} name={ICONS_NAME.Refresh}
size={scale(28)} size={scale(28)}
@ -176,8 +180,9 @@ function MyOrders() {
textColor={colors.text} textColor={colors.text}
style={alignment.MTxSmall} style={alignment.MTxSmall}
bold bold
center> center
{'Re-Order'} >
{"Re-Order"}
</TextDefault> </TextDefault>
</View> </View>
</TouchableOpacity> </TouchableOpacity>
@ -187,7 +192,7 @@ function MyOrders() {
onEndReached={fetchMoreOrdersFunc} onEndReached={fetchMoreOrdersFunc}
/> />
</WrapperView> </WrapperView>
) );
} }
export default MyOrders export default MyOrders;

View File

@ -1,207 +1,207 @@
import { useMutation } from '@apollo/react-hooks' import { useMutation } from "@apollo/react-hooks";
import AsyncStorage from '@react-native-async-storage/async-storage' import AsyncStorage from "@react-native-async-storage/async-storage";
import { useNavigation, useTheme } from '@react-navigation/native' import { useNavigation, useTheme } from "@react-navigation/native";
import Constants from 'expo-constants' import Constants from "expo-constants";
import * as Device from 'expo-device' import * as Device from "expo-device";
import * as Localization from 'expo-localization' import * as Localization from "expo-localization";
import * as Notifications from 'expo-notifications' import * as Notifications from "expo-notifications";
import * as Updates from 'expo-updates' import * as Updates from "expo-updates";
import gql from 'graphql-tag' import gql from "graphql-tag";
import React, { useContext, useEffect, useRef, useState } from 'react' import React, { useContext, useEffect, useRef, useState } from "react";
import { import {
AppState, AppState,
Linking, Linking,
Platform, Platform,
StyleSheet, StyleSheet,
TouchableOpacity, TouchableOpacity,
View View,
} from 'react-native' } from "react-native";
import { Modalize } from 'react-native-modalize' import { Modalize } from "react-native-modalize";
import i18n from '../../../i18n' import i18n from "../../../i18n";
import { import {
profile, profile,
pushToken, pushToken,
updateNotificationStatus updateNotificationStatus,
} from '../../apollo/server' } from "../../apollo/server";
import { import {
CustomIcon, CustomIcon,
FlashMessage, FlashMessage,
Spinner, Spinner,
TextDefault, TextDefault,
WrapperView WrapperView,
} from '../../components' } from "../../components";
import SwitchBtn from '../../components/FdSwitch/SwitchBtn' import SwitchBtn from "../../components/FdSwitch/SwitchBtn";
import UserContext from '../../context/User' import UserContext from "../../context/User";
import { alignment } from '../../utils/alignment' import { alignment } from "../../utils/alignment";
import { ICONS_NAME } from '../../utils/constant' import { ICONS_NAME } from "../../utils/constant";
import { scale } from '../../utils/scaling' import { scale } from "../../utils/scaling";
import SettingModal from './components/SettingModal' import SettingModal from "./components/SettingModal";
import useStyle from './styles' import useStyle from "./styles";
const languageTypes = [ const languageTypes = [
{ value: 'English', code: 'en', index: 0 }, { value: "English", code: "en", index: 0 },
{ value: 'français', code: 'fr', index: 1 }, { value: "français", code: "fr", index: 1 },
{ value: 'ភាសាខ្មែរ', code: 'km', index: 2 }, { value: "ភាសាខ្មែរ", code: "km", index: 2 },
{ value: '中文', code: 'zh', index: 3 }, { value: "中文", code: "zh", index: 3 },
{ value: 'Deutsche', code: 'de', index: 4 } { value: "Deutsche", code: "de", index: 4 },
] ];
const PUSH_TOKEN = gql` const PUSH_TOKEN = gql`
${pushToken} ${pushToken}
` `;
const UPDATE_NOTIFICATION_TOKEN = gql` const UPDATE_NOTIFICATION_TOKEN = gql`
${updateNotificationStatus} ${updateNotificationStatus}
` `;
const PROFILE = gql` const PROFILE = gql`
${profile} ${profile}
` `;
function Settings() { function Settings() {
const styles = useStyle() const styles = useStyle();
const { colors } = useTheme() const { colors } = useTheme();
const navigation = useNavigation() const navigation = useNavigation();
const { profile } = useContext(UserContext) const { profile } = useContext(UserContext);
const [languageName, languageNameSetter] = useState('English') const [languageName, languageNameSetter] = useState("English");
const [offerNotification, offerNotificationSetter] = useState( const [offerNotification, offerNotificationSetter] = useState(
profile.is_offer_notification profile.is_offer_notification
) );
const [orderNotification, orderNotificationSetter] = useState( const [orderNotification, orderNotificationSetter] = useState(
profile.is_order_notification profile.is_order_notification
) );
const [activeRadio, activeRadioSetter] = useState(languageTypes[0].index) const [activeRadio, activeRadioSetter] = useState(languageTypes[0].index);
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const [appState, setAppState] = useState(AppState.currentState) const [appState, setAppState] = useState(AppState.currentState);
const [uploadToken] = useMutation(PUSH_TOKEN) const [uploadToken] = useMutation(PUSH_TOKEN);
const [mutate, { loading }] = useMutation(UPDATE_NOTIFICATION_TOKEN, { const [mutate, { loading }] = useMutation(UPDATE_NOTIFICATION_TOKEN, {
onCompleted, onCompleted,
onError, onError,
refetchQueries: [{ query: PROFILE }] refetchQueries: [{ query: PROFILE }],
}) });
const modalizeRef = useRef(null) const modalizeRef = useRef(null);
useEffect(() => { useEffect(() => {
navigation.setOptions({ navigation.setOptions({
headerTitle: i18n.t('titleSettings'), headerTitle: i18n.t("titleSettings"),
headerRight: null headerRight: null,
}) });
selectLanguage() selectLanguage();
checkPermission() checkPermission();
}, [navigation]) }, [navigation]);
const _handleAppStateChange = async nextAppState => { const _handleAppStateChange = async (nextAppState) => {
if (nextAppState === 'active') { if (nextAppState === "active") {
let token = null let token = null;
const permission = await getPermission() const permission = await getPermission();
if (permission === 'granted') { if (permission === "granted") {
if (!profile.notificationToken) { if (!profile.notificationToken) {
token = (await Notifications.getExpoPushTokenAsync()).data token = (await Notifications.getExpoPushTokenAsync()).data;
uploadToken({ variables: { token } }) uploadToken({ variables: { token } });
} }
offerNotificationSetter(profile.is_offer_notification) offerNotificationSetter(profile.is_offer_notification);
orderNotificationSetter(profile.is_order_notification) orderNotificationSetter(profile.is_order_notification);
} else { } else {
offerNotificationSetter(false) offerNotificationSetter(false);
orderNotificationSetter(false) orderNotificationSetter(false);
} }
} }
setAppState(nextAppState) setAppState(nextAppState);
} };
useEffect(() => { useEffect(() => {
AppState.addEventListener('change', _handleAppStateChange) AppState.addEventListener("change", _handleAppStateChange);
return () => { return () => {
AppState.removeEventListener('change', _handleAppStateChange) AppState.remove("change", _handleAppStateChange);
} };
}, []) }, []);
async function checkPermission() { async function checkPermission() {
const permission = await getPermission() const permission = await getPermission();
if (permission !== 'granted') { if (permission !== "granted") {
offerNotificationSetter(false) offerNotificationSetter(false);
orderNotificationSetter(false) orderNotificationSetter(false);
} else { } else {
offerNotificationSetter(profile.is_offer_notification) offerNotificationSetter(profile.is_offer_notification);
orderNotificationSetter(profile.is_order_notification) orderNotificationSetter(profile.is_order_notification);
} }
} }
async function getPermission() { async function getPermission() {
const { status } = await Notifications.getPermissionsAsync() const { status } = await Notifications.getPermissionsAsync();
return status return status;
} }
async function selectLanguage() { async function selectLanguage() {
const lang = await AsyncStorage.getItem('enatega-language') const lang = await AsyncStorage.getItem("enatega-language");
if (lang) { if (lang) {
const defLang = languageTypes.findIndex(el => el.code === lang) const defLang = languageTypes.findIndex((el) => el.code === lang);
const langName = languageTypes[defLang].value const langName = languageTypes[defLang].value;
activeRadioSetter(defLang) activeRadioSetter(defLang);
languageNameSetter(langName) languageNameSetter(langName);
} }
} }
const onSelectedLanguage = async active => { const onSelectedLanguage = async (active) => {
const languageInd = active const languageInd = active;
if (Platform.OS === 'android') { if (Platform.OS === "android") {
const localization = await Localization.getLocalizationAsync() const localization = await Localization.getLocalizationAsync();
localization.locale = languageTypes[languageInd].code localization.locale = languageTypes[languageInd].code;
await AsyncStorage.setItem( await AsyncStorage.setItem(
'enatega-language', "enatega-language",
languageTypes[languageInd].code languageTypes[languageInd].code
) );
Updates.reloadAsync() Updates.reloadAsync();
} }
} };
const onClose = () => { const onClose = () => {
modalizeRef.current.close() modalizeRef.current.close();
} };
function onCompleted() { function onCompleted() {
FlashMessage({ FlashMessage({
message: 'Notification Status Updated' message: "Notification Status Updated",
}) });
} }
function onError(error) { function onError(error) {
try { try {
FlashMessage({ FlashMessage({
message: error.networkError.result.errors[0].message message: error.networkError.result.errors[0].message,
}) });
} catch (err) {} } catch (err) {}
} }
async function updateNotificationStatus(notificationCheck) { async function updateNotificationStatus(notificationCheck) {
let orderNotify, offerNotify let orderNotify, offerNotify;
if (!Device.isDevice) { if (!Device.isDevice) {
FlashMessage({ FlashMessage({
message: 'Notification do not work on simulator' message: "Notification do not work on simulator",
}) });
return return;
} }
const permission = await getPermission() const permission = await getPermission();
if (!profile.notificationToken || permission !== 'granted') { if (!profile.notificationToken || permission !== "granted") {
Linking.openSettings() Linking.openSettings();
} }
if (notificationCheck === 'offer') { if (notificationCheck === "offer") {
offerNotificationSetter(!offerNotification) offerNotificationSetter(!offerNotification);
orderNotify = orderNotification orderNotify = orderNotification;
offerNotify = !offerNotification offerNotify = !offerNotification;
} }
if (notificationCheck === 'order') { if (notificationCheck === "order") {
orderNotificationSetter(!orderNotification) orderNotificationSetter(!orderNotification);
orderNotify = !orderNotification orderNotify = !orderNotification;
offerNotify = offerNotification offerNotify = offerNotification;
} }
mutate({ mutate({
variables: { variables: {
offerNotification: offerNotify, offerNotification: offerNotify,
orderNotification: orderNotify orderNotification: orderNotify,
} },
}) });
} }
return ( return (
@ -213,7 +213,7 @@ function Settings() {
)} )}
<View style={[styles.flex, styles.mainContainer]}> <View style={[styles.flex, styles.mainContainer]}>
<View style={alignment.Plarge}> <View style={alignment.Plarge}>
{Platform.OS === 'android' && ( {Platform.OS === "android" && (
<View style={[styles.languageContainer, styles.shadow]}> <View style={[styles.languageContainer, styles.shadow]}>
<View style={styles.changeLanguage}> <View style={styles.changeLanguage}>
<View style={styles.headingLanguage}> <View style={styles.headingLanguage}>
@ -221,7 +221,8 @@ function Settings() {
numberOfLines={1} numberOfLines={1}
textColor={colors.fontSecondColor} textColor={colors.fontSecondColor}
medium medium
H5> H5
>
Language Language
</TextDefault> </TextDefault>
<TextDefault medium H5> <TextDefault medium H5>
@ -230,8 +231,9 @@ function Settings() {
</View> </View>
<TouchableOpacity <TouchableOpacity
activeOpacity={0.5} activeOpacity={0.5}
onPress={() => modalizeRef.current.open('top')} onPress={() => modalizeRef.current.open("top")}
style={styles.button}> style={styles.button}
>
<CustomIcon <CustomIcon
name={ICONS_NAME.Pencil} name={ICONS_NAME.Pencil}
size={scale(22)} size={scale(22)}
@ -244,20 +246,22 @@ function Settings() {
<TouchableOpacity <TouchableOpacity
activeOpacity={0.7} activeOpacity={0.7}
onPress={() => { onPress={() => {
updateNotificationStatus('offer') updateNotificationStatus("offer");
}} }}
style={[styles.notificationContainer, styles.shadow]}> style={[styles.notificationContainer, styles.shadow]}
>
<View style={styles.notificationChekboxContainer}> <View style={styles.notificationChekboxContainer}>
<TextDefault <TextDefault
numberOfLines={1} numberOfLines={1}
textColor={colors.statusSecondColor}> textColor={colors.statusSecondColor}
{' '} >
Receive Special Offers{' '} {" "}
Receive Special Offers{" "}
</TextDefault> </TextDefault>
<SwitchBtn <SwitchBtn
isEnabled={offerNotification} isEnabled={offerNotification}
onPress={() => { onPress={() => {
updateNotificationStatus('offer') updateNotificationStatus("offer");
}} }}
/> />
</View> </View>
@ -265,20 +269,22 @@ function Settings() {
<TouchableOpacity <TouchableOpacity
activeOpacity={0.7} activeOpacity={0.7}
onPress={() => { onPress={() => {
updateNotificationStatus('order') updateNotificationStatus("order");
}} }}
style={[styles.notificationContainer, styles.shadow]}> style={[styles.notificationContainer, styles.shadow]}
>
<View style={styles.notificationChekboxContainer}> <View style={styles.notificationChekboxContainer}>
<TextDefault <TextDefault
numberOfLines={1} numberOfLines={1}
textColor={colors.statusSecondColor}> textColor={colors.statusSecondColor}
{' '} >
Get updates on your order status!{' '} {" "}
Get updates on your order status!{" "}
</TextDefault> </TextDefault>
<SwitchBtn <SwitchBtn
isEnabled={orderNotification} isEnabled={orderNotification}
onPress={() => { onPress={() => {
updateNotificationStatus('order') updateNotificationStatus("order");
}} }}
/> />
</View> </View>
@ -293,7 +299,8 @@ function Settings() {
<TextDefault <TextDefault
textColor={colors.fontSecondColor} textColor={colors.fontSecondColor}
style={alignment.MBsmall} style={alignment.MBsmall}
center> center
>
All rights are reserved by Enatega All rights are reserved by Enatega
</TextDefault> </TextDefault>
@ -304,10 +311,11 @@ function Settings() {
handlePosition="inside" handlePosition="inside"
avoidKeyboardLikeIOS={Platform.select({ avoidKeyboardLikeIOS={Platform.select({
ios: true, ios: true,
android: false android: false,
})} })}
keyboardAvoidingOffset={2} keyboardAvoidingOffset={2}
keyboardAvoidingBehavior="height"> keyboardAvoidingBehavior="height"
>
<SettingModal <SettingModal
onClose={onClose} onClose={onClose}
onSelectedLanguage={onSelectedLanguage} onSelectedLanguage={onSelectedLanguage}
@ -315,6 +323,6 @@ function Settings() {
/> />
</Modalize> </Modalize>
</WrapperView> </WrapperView>
) );
} }
export default Settings export default Settings;

View File

@ -1,15 +1,15 @@
import * as Amplitude from 'expo-analytics-amplitude' import * as Amplitude from "@amplitude/analytics-react-native";
import { normalizeTrackingOptions } from './analyticsUtils' import { normalizeTrackingOptions } from "./analyticsUtils";
import getEnvVars from '../../environment' import getEnvVars from "../../environment";
import { getTrackingPermissions } from './useAppTrackingTransparency' import { getTrackingPermissions } from "./useAppTrackingTransparency";
const { AMPLITUDE_API_KEY } = getEnvVars() const { AMPLITUDE_API_KEY } = getEnvVars();
let isInitialized = false let isInitialized = false;
export const events = { export const events = {
USER_LOGGED_IN: 'USER_LOGGED_IN', USER_LOGGED_IN: "USER_LOGGED_IN",
USER_LOGGED_OUT: 'USER_LOGGED_OUT', USER_LOGGED_OUT: "USER_LOGGED_OUT",
USER_CREATED_ACCOUNT: 'USER_CREATED_ACCOUNT', USER_CREATED_ACCOUNT: "USER_CREATED_ACCOUNT",
// USER_RESET_PASSWORD: 'USER_RESET_PASSWORD', // USER_RESET_PASSWORD: 'USER_RESET_PASSWORD',
// USER_LINKED_SOCIAL: 'USER_LINKED_SOCIAL', // USER_LINKED_SOCIAL: 'USER_LINKED_SOCIAL',
// USER_UPDATED_EMAIL: 'USER_UPDATED_EMAIL', // USER_UPDATED_EMAIL: 'USER_UPDATED_EMAIL',
@ -20,40 +20,41 @@ export const events = {
// USER_REMOVED_PROJECT: 'USER_REMOVED_PROJECT', // USER_REMOVED_PROJECT: 'USER_REMOVED_PROJECT',
// USER_OPENED_CREATION: 'USER_OPENED_CREATION', // USER_OPENED_CREATION: 'USER_OPENED_CREATION',
// USER_UPDATED_SETTINGS: 'USER_UPDATED_SETTINGS', // USER_UPDATED_SETTINGS: 'USER_UPDATED_SETTINGS',
USER_PLACED_ORDER: 'USER_PLACED_ORDER' USER_PLACED_ORDER: "USER_PLACED_ORDER",
} };
export async function initialize() { export async function initialize() {
const trackingStatus = await getTrackingPermissions() const trackingStatus = await getTrackingPermissions();
if (isInitialized || !AMPLITUDE_API_KEY || trackingStatus !== 'granted') { if (isInitialized || !AMPLITUDE_API_KEY || trackingStatus !== "granted") {
return return;
} }
await Amplitude.initializeAsync(AMPLITUDE_API_KEY) Amplitude.init(AMPLITUDE_API_KEY);
isInitialized = true isInitialized = true;
} }
export async function identify(id, options) { export async function identify(id, options) {
initialize() initialize();
const properties = normalizeTrackingOptions(options) const properties = normalizeTrackingOptions(options);
if (id) { if (properties) {
await Amplitude.setUserIdAsync(id) Amplitude.Identify(properties);
if (properties) { //await Amplitude.setUserPropertiesAsync(properties)
await Amplitude.setUserPropertiesAsync(properties)
}
} else { } else {
await Amplitude.clearUserPropertiesAsync() //await Amplitude.clearUserPropertiesAsync()
const identifyObj = new Amplitude.Identify();
identifyObj.remove(properties);
Amplitude.Identify(identifyObj);
} }
} }
export async function track(event, options) { export async function track(event, options) {
initialize() initialize();
const properties = normalizeTrackingOptions(options) const properties = normalizeTrackingOptions(options);
if (properties) { if (properties) {
await Amplitude.logEventWithPropertiesAsync(event, properties) Amplitude.track(event, properties);
} else { } else {
await Amplitude.logEventAsync(event) Amplitude.track(event);
} }
} }
@ -61,5 +62,5 @@ export default {
events, events,
initialize, initialize,
identify, identify,
track track,
} };

View File

@ -1,34 +1,35 @@
// packages // packages
import { BackHandler, Alert } from 'react-native' import { BackHandler, Alert } from "react-native";
/** /**
* Attaches an event listener that handles the android-only hardware * Attaches an event listener that handles the android-only hardware
* back button * back button
* @param {Function} callback The function to call on click * @param {Function} callback The function to call on click
*/ */
const handleAndroidBackButton = callback => { const handleAndroidBackButton = (callback) => {
BackHandler.addEventListener('hardwareBackPress', () => { BackHandler.addEventListener("hardwareBackPress", () => {
callback() callback();
return true return true;
}) });
} };
/** /**
* Removes the event listener in order not to add a new one * Removes the event listener in order not to add a new one
* every time the view component re-mounts * every time the view component re-mounts
*/ */
const removeAndroidBackButtonHandler = () => { const removeAndroidBackButtonHandler = () => {
BackHandler.removeEventListener('hardwareBackPress') // BackHandler.removeEventListener('hardwareBackPress')
} BackHandler.remove("hardwareBackPress");
};
const exitAlert = () => { const exitAlert = () => {
Alert.alert('Confirm exit', 'Do you want to quit the app?', [ Alert.alert("Confirm exit", "Do you want to quit the app?", [
{ text: 'CANCEL', style: 'cancel' }, { text: "CANCEL", style: "cancel" },
{ {
text: 'OK', text: "OK",
onPress: () => { onPress: () => {
BackHandler.exitApp() BackHandler.exitApp();
} },
} },
]) ]);
return true return true;
} };
export { handleAndroidBackButton, removeAndroidBackButtonHandler, exitAlert } export { handleAndroidBackButton, removeAndroidBackButtonHandler, exitAlert };

BIN
CustomerApp/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,15 @@
> Why do I have a folder named ".expo" in my project?
The ".expo" folder is created when an Expo project is started using "expo start" command.
> What do the files contain?
- "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds.
- "packager-info.json": contains port numbers and process PIDs that are used to serve the application to the mobile device/simulator.
- "settings.json": contains the server configuration that is used to serve the application manifest.
> Should I commit the ".expo" folder?
No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine.
Upon project creation, the ".expo" folder is already added to your ".gitignore" file.

View File

@ -0,0 +1,3 @@
{
"devices": []
}

View File

@ -0,0 +1,8 @@
{
"hostType": "lan",
"lanType": "ip",
"dev": true,
"minify": false,
"urlRandomness": null,
"https": false
}

1
CustomerApp/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/node_modules

1
CustomerApp/.npmrc Normal file
View File

@ -0,0 +1 @@
legacy-peer-deps=true

151
CustomerApp/App.js Normal file
View File

@ -0,0 +1,151 @@
import { ApolloProvider } from '@apollo/react-hooks'
import * as Font from 'expo-font'
import * as Location from 'expo-location'
import * as Notifications from 'expo-notifications'
import * as SplashScreen from 'expo-splash-screen'
import React, { useEffect, useState } from 'react'
import {
ActivityIndicator,
BackHandler,
Platform,
StatusBar,
StyleSheet,
useColorScheme,
View
} from 'react-native'
import FlashMessage from 'react-native-flash-message'
import i18n from './i18n'
import setupApolloClient from './src/apollo/index'
import { ConfigurationProvider } from './src/context/Configuration'
import { UserProvider } from './src/context/User'
import AppContainer from './src/routes'
import { AnimatedSplash } from './src/screens'
import { COLORS, THEME } from './src/Theme'
import { exitAlert } from './src/utils/androidBackButton'
import { requestTrackingPermissions } from './src/utils/useAppTrackingTransparency'
SplashScreen.preventAutoHideAsync().catch(() => {})
export default function App() {
const colorScheme = useColorScheme()
const isDark = colorScheme === 'dark'
const [fontLoaded, setFontLoaded] = useState(false)
const [client, setupClient] = useState(null)
useEffect(() => {
requestTrackingPermissions()
}, [])
useEffect(() => {
loadAppData()
return () => {
BackHandler.removeEventListener('hardwareBackPress', exitAlert)
}
}, [])
async function loadAppData() {
const client = await setupApolloClient()
setupClient(client)
await i18n.initAsync()
// load fonts
await Font.loadAsync({
Poppin300: require('./src/assets/font/Poppin/Poppins-Light.ttf'),
Poppin400: require('./src/assets/font/Poppin/Poppins-Regular.ttf'),
Poppin500: require('./src/assets/font/Poppin/Poppins-Medium.ttf'),
Poppin600: require('./src/assets/font/Poppin/Poppins-SemiBold.ttf'),
Poppin700: require('./src/assets/font/Poppin/Poppins-Bold.ttf'),
icomoon: require('./src/assets/font/icomoon.ttf')
})
await permissionForLocationAsync()
await permissionForPushNotificationsAsync()
BackHandler.addEventListener('hardwareBackPress', exitAlert)
setFontLoaded(true)
}
async function permissionForPushNotificationsAsync() {
const { status: existingStatus } = await Notifications.getPermissionsAsync()
let finalStatus = existingStatus
// only ask if permissions have not already been determined, because
// iOS won't necessarily prompt the user a second time.
if (existingStatus !== 'granted') {
// Android remote notification permissions are granted during the app
// install, so this will only ask on iOS
const { status } = await Notifications.requestPermissionsAsync()
finalStatus = status
}
// Stop here if the user did not grant permissions
if (finalStatus !== 'granted') {
return
}
if (Platform.OS === 'android') {
Notifications.setNotificationChannelAsync('default', {
name: 'default',
sound: true,
priority: 'max',
importance: Notifications.AndroidImportance.HIGH,
vibrate: [0, 250, 250, 250],
lightColor: COLORS.primary
})
}
}
async function permissionForLocationAsync() {
const { status: existingStatus } =
await Location.getForegroundPermissionsAsync()
// only ask if permissions have not already been determined, because
// iOS won't necessarily prompt the user a second time.
if (existingStatus !== 'granted') {
// Android location permissions are granted during the app
// install, so this will only ask on iOS
const { status } = await Location.requestForegroundPermissionsAsync()
// eslint-disable-next-line no-undef
finalStatus = status
}
}
if (fontLoaded && client) {
return (
<ApolloProvider client={client}>
<StatusBar
translucent
backgroundColor={'transparent'}
barStyle={isDark ? 'light-content' : 'dark-content'}
/>
<ConfigurationProvider>
<UserProvider>
<AnimatedSplash image={require('./assets/splash.png')}>
<AppContainer />
</AnimatedSplash>
</UserProvider>
</ConfigurationProvider>
<FlashMessage duration={2000} position="center" />
</ApolloProvider>
)
} else {
return (
<View style={[styles.flex, styles.mainContainer]}>
<ActivityIndicator
size="large"
color={
isDark
? THEME.Dark.colors.spinnerColor
: THEME.Light.colors.spinnerColor
}
/>
</View>
)
}
}
const styles = StyleSheet.create({
flex: {
flex: 1
},
mainContainer: {
justifyContent: 'center',
alignItems: 'center'
}
})

83
CustomerApp/app.json Normal file
View File

@ -0,0 +1,83 @@
{
"expo": {
"name": "Enatega",
"version": "1.0.18",
"scheme": "enategasinglevendor",
"description": "Enatega is a starter kit food ordering app built in React Native using Expo for IOS and Android. It's made keeping good aesthetics in mind as well keeping the best coding practices in mind. Its fully customisable to easily help you in your next food delivery project. https://market.nativebase.io/view/react-native-food-delivery-backend-app",
"slug": "enategasinglevendor",
"privacy": "public",
"androidStatusBar": {
"backgroundColor": "#000"
},
"platforms": [
"ios",
"android"
],
"orientation": "portrait",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "cover",
"backgroundColor": "#febb2c"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.enatega.vendor",
"config": {
"googleMapsApiKey": ""
},
"usesAppleSignIn": true,
"infoPlist": {
"NSLocationWhenInUseUsageDescription": "This app uses the location to determine the delivery address for your orders.",
"NSUserTrackingUsageDescription": "Allow this app to collect app-related data that can be used for tracking you or your device."
}
},
"notification": {
"iosDisplayInForeground": true,
"color": "#d83765",
"icon": "./assets/not-icon.png",
"androidMode": "default",
"androidCollapsedTitle": "Enatega"
},
"android": {
"versionCode": 23,
"package": "com.enatega.vendor",
"googleServicesFile": "./google-services-prod.json",
"config": {
"googleMaps": {
"apiKey": ""
}
},
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#febb2c"
},
"permissions": [
"ACCESS_FINE_LOCATION",
"ACCESS_COARSE_LOCATION"
]
},
"plugins": [
[
"expo-tracking-transparency",
{
"userTrackingPermission": "Allow this app to collect app-related data that can be used for tracking you or your device."
}
]
],
"facebookScheme": "fb3017447961609878",
"facebookAppId": "3017447961609878",
"facebookDisplayName": "Food delivery",
"extra": {
"eas": {
"projectId": "0b51ea6b-d9fd-48e2-9480-54149ca73a7a"
}
}
}
}

BIN
CustomerApp/assets/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 KiB

BIN
CustomerApp/assets/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
CustomerApp/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View File

@ -0,0 +1,10 @@
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: [
"react-native-reanimated/plugin",
"@babel/plugin-syntax-dynamic-import",
],
};
};

41
CustomerApp/eas.json Normal file
View File

@ -0,0 +1,41 @@
{
"cli": {
"version": ">= 3.8.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"ios": {
"resourceClass": "m-medium"
}
},
"preview": {
"distribution": "internal",
"ios": {
"resourceClass": "m-medium"
}
},
"production": {
"developmentClient": false,
"releaseChannel": "production",
"distribution": "store",
"ios": {
"resourceClass": "m-medium"
}
}
},
"submit": {
"production": {
"android": {
"serviceAccountKeyPath": "./google-service-account.json",
"track": "production"
},
"ios": {
"appleId": "sharan.gohar@icloud.com",
"ascAppId": "1526488093",
"appleTeamId": "GDFK7MVY6P"
}
}
}
}

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDRTCCAi2gAwIBAgIERu0DYTANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJV
UzEJMAcGA1UECBMAMQkwBwYDVQQHEwAxCTAHBgNVBAoTADEJMAcGA1UECxMAMRgw
FgYDVQQDEw9jb20uZW5hdGVnYS5hcHAwHhcNMTkwNzI2MDg0NzEyWhcNNDYxMjEx
MDg0NzEyWjBTMQswCQYDVQQGEwJVUzEJMAcGA1UECBMAMQkwBwYDVQQHEwAxCTAH
BgNVBAoTADEJMAcGA1UECxMAMRgwFgYDVQQDEw9jb20uZW5hdGVnYS5hcHAwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQChW6yOHftMY4PZYS/1VK72o0mj
TMxVrolnwN46QrCkwX3MTC5Rf014MCOfWjRpbeCnL/ZFW5hMu1gfZhI3cU6n8kKi
3xkhIgtxoaGecC594WzOJfFNhNuHbdJTp4KlPli8k1CiWSxzddnxDaJX1zLh4vbp
Z1czC0k7HY6Muhpd7WCC1uwcp0UzCm1ej7LZqYPuUzwieW0V/ASMdS9yWri4LyIO
DA6nFbDdvCJrupL0C8RQjACCRMLwGx2l3zMlWe3nDa4ZyMRW6cdSsQA6QvlwxVeK
6I40S8fYsUf68/QZrnBwTV9yyJ78bIpF+9zF3b7kcv7tXAKkcuoQcd/70e79AgMB
AAGjITAfMB0GA1UdDgQWBBQ71L/oHvSkF0v65nI4B1iVLSFcfDANBgkqhkiG9w0B
AQsFAAOCAQEAlzMU9jy1oCtrxeucJcx5LU2+4Np/pdhfofivK3W6cLJ6yqAvKxNC
cmO+4mwG8O9s5bYtscB7+n9u1JYNOGMtyzAbjW2tzysaPU9EPatD+oAQznU1ur28
v5YCTmS1tv4wRsYkjYGI+S+XQ+qi/wuNith2te1qoUfdl4/JCIA8kw7XPU9eLkDE
r3RrsZXV7NTIo2f2nnTeJWz9QFtERevQlgpwOnCqmqvPKV3n52sH5R/8g3xjiL1W
wP1JHGErSFGVbctYH6HTsHQkAfmzPeK7UOfB+kR70dXkPKdw3u+pdv8jzaRO9gpq
H97r6aLCoyB53CJ+6w51DSl1eAKMGK7Tcg==
-----END CERTIFICATE-----

View File

@ -0,0 +1,71 @@
/*****************************
* environment.js
* path: '/environment.js' (root of your project)
******************************/
import Constants from "expo-constants";
const ENV = {
development: {
GRAPHQL_URL: "http://10.97.28.88.90:8000/graphql",
WS_GRAPHQL_URL: "ws://10.97.28.88.90:8000/graphql",
SERVER_URL: "http://10.97.28.88.90:8000/", // put / at the end of server url
IOS_CLIENT_ID_GOOGLE:
"967541328677-uq7f7odvmeea2pb2sq0l7q320ds86536.apps.googleusercontent.com",
ANDROID_CLIENT_ID_GOOGLE:
"967541328677-u9lbhmiesp67j3md9b8nk6mkhooeljur.apps.googleusercontent.com",
AMPLITUDE_API_KEY: "358ef0deb443586e2cc4ddd4380151f0",
STRIPE_PUBLIC_KEY: "pk_test_lEaBbVGnTkzja2FyFiNlbqtw",
STRIPE_IMAGE_URL: "http://192.168.100.90:8000/assets/images/logo.png",
STRIPE_STORE_NAME: "Enatega",
},
staging: {
GRAPHQL_URL: "https://staging-enatega-single-api.herokuapp.com/graphql",
WS_GRAPHQL_URL: "wss://staging-enatega-single-api.herokuapp.com/graphql",
SERVER_URL: "https://staging-enatega-single-api.herokuapp.com/", // put / at the end of server url
IOS_CLIENT_ID_GOOGLE:
"967541328677-nf8h4ou7rhmq9fahs87p057rggo95eah.apps.googleusercontent.com",
ANDROID_CLIENT_ID_GOOGLE:
"967541328677-7264tf7tkdtoufk844rck9mimrve135c.apps.googleusercontent.com",
FACEBOOK_APP_ID: "404956210315749",
AMPLITUDE_API_KEY: "358ef0deb443586e2cc4ddd4380151f0",
STRIPE_PUBLIC_KEY: "pk_test_lEaBbVGnTkzja2FyFiNlbqtw",
STRIPE_IMAGE_URL:
"https://staging-enatega-single-api.herokuapp.com/assets/images/logo.png",
STRIPE_STORE_NAME: "Enatega",
},
production: {
GRAPHQL_URL: "https://prod-enatega-single-api.herokuapp.com/graphql",
WS_GRAPHQL_URL: "wss://prod-enatega-single-api.herokuapp.com/graphql",
SERVER_URL: "https://prod-enatega-single-api.herokuapp.com/", // put / at the end of server url
IOS_CLIENT_ID_GOOGLE:
"94983896797-irt6u2cmq2sjcp7j1rj9m9pqptjd12ue.apps.googleusercontent.com",
ANDROID_CLIENT_ID_GOOGLE:
"94983896797-omp6mi32rl3126siafgnskrqql0rdk5c.apps.googleusercontent.com",
FACEBOOK_APP_ID: "3017447961609878",
AMPLITUDE_API_KEY: "358ef0deb443586e2cc4ddd4380151f0",
STRIPE_PUBLIC_KEY: "pk_test_lEaBbVGnTkzja2FyFiNlbqtw",
STRIPE_IMAGE_URL:
"https://prod-enatega-single-api.herokuapp.com/assets/images/logo.png",
STRIPE_STORE_NAME: "Enatega",
},
};
const getEnvVars = (env = Constants.manifest.releaseChannel) => {
// What is __DEV__ ?
// This variable is set to true when react-native is running in Dev mode.
// __DEV__ is true when run locally, but false when published.
// eslint-disable-next-line no-undef
if (__DEV__) {
return ENV.development;
} else if (env === "production") {
return ENV.production;
} else if (env === "staging") {
return ENV.staging;
} else {
return ENV.production;
}
};
export default getEnvVars;

View File

@ -0,0 +1,46 @@
/*****************************
* environment.js
* path: '/environment.js' (root of your project)
******************************/
import Constants from 'expo-constants';
const ENV = {
development: {
GRAPHQL_URL:'' ,
SERVER_URL: '', // put / at the end of server url
IOS_CLIENT_ID_GOOGLE: "",
ANDROID_CLIENT_ID_GOOGLE: "",
FACEBOOK_APP_ID: "",
AMPLITUDE_API_KEY: "",
STRIPE_PUBLIC_KEY: "",
STRIPE_IMAGE_URL: "",
STRIPE_STORE_NAME: ""
},
production: {
GRAPHQL_URL:'' ,
SERVER_URL: '', // put / at the end of server url
IOS_CLIENT_ID_GOOGLE: "",
ANDROID_CLIENT_ID_GOOGLE: "",
FACEBOOK_APP_ID: "",
AMPLITUDE_API_KEY: "",
STRIPE_PUBLIC_KEY: "",
STRIPE_IMAGE_URL: "",
STRIPE_STORE_NAME: ""
}
};
const getEnvVars = (env = Constants.manifest.releaseChannel) => {
// What is __DEV__ ?
// This variable is set to true when react-native is running in Dev mode.
// __DEV__ is true when run locally, but false when published.
if (__DEV__) {
return ENV.development;
} else if (env === 'production') {
return ENV.production;
} else {
return ENV.development;
}
};
export default getEnvVars;

View File

@ -0,0 +1,47 @@
{
"project_info": {
"project_number": "94983896797",
"firebase_url": "https://enatega-production.firebaseio.com",
"project_id": "enatega-production",
"storage_bucket": "enatega-production.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:94983896797:android:537c4eadfd11cf33",
"android_client_info": {
"package_name": "com.enatega.app"
}
},
"oauth_client": [
{
"client_id": "94983896797-9e36v3edasjt9t9r5q9uvkth700nn0nn.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyBt9S6e7ig5EkNiSXw3sCyX7kgo1gzPxl4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "94983896797-9e36v3edasjt9t9r5q9uvkth700nn0nn.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "94983896797-irt6u2cmq2sjcp7j1rj9m9pqptjd12ue.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.enatega.app"
}
}
]
}
}
}
],
"configuration_version": "1"
}

View File

@ -0,0 +1,47 @@
{
"project_info": {
"project_number": "94983896797",
"firebase_url": "https://enatega-production.firebaseio.com",
"project_id": "enatega-production",
"storage_bucket": "enatega-production.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:94983896797:android:5b28fe2925a51512112534",
"android_client_info": {
"package_name": "com.enatega.vendor"
}
},
"oauth_client": [
{
"client_id": "94983896797-9e36v3edasjt9t9r5q9uvkth700nn0nn.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyBt9S6e7ig5EkNiSXw3sCyX7kgo1gzPxl4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "94983896797-9e36v3edasjt9t9r5q9uvkth700nn0nn.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "94983896797-osn1lglcn3f03a4dqpf1vl2rcogca8vp.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.enatega.app"
}
}
]
}
}
}
],
"configuration_version": "1"
}

View File

@ -0,0 +1,40 @@
{
"project_info": {
"project_number": "346954645996",
"firebase_url": "https://enatega-4d403.firebaseio.com",
"project_id": "enatega-4d403",
"storage_bucket": "enatega-4d403.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:346954645996:android:f968efbb41d1fa7a",
"android_client_info": {
"package_name": "host.exp.exponent"
}
},
"oauth_client": [
{
"client_id": "346954645996-a2t28in6j98u33hnd4evb45m5d34lvjp.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCFfJ4RHfakMqvp_QsIHkfWcpeYrxtk8j0"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "346954645996-a2t28in6j98u33hnd4evb45m5d34lvjp.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}
],
"configuration_version": "1"
}

23
CustomerApp/i18n.js Normal file
View File

@ -0,0 +1,23 @@
import AsyncStorage from '@react-native-async-storage/async-storage'
import * as Localization from 'expo-localization'
import i18n from 'i18n-js'
import { Platform } from 'react-native'
import { de } from './translations/de'
import { en } from './translations/en'
import { fr } from './translations/fr'
import { km } from './translations/km'
import { zh } from './translations/zh'
i18n.initAsync = async() => {
i18n.fallbacks = true
i18n.translations = { fr, en, km, zh, de }
// i18n.locale = 'km'
if (Platform.OS === 'android') {
const lang = await AsyncStorage.getItem('enatega-language')
i18n.locale = lang || 'en'
} else {
i18n.locale = Localization.locale
}
}
export default i18n

8
CustomerApp/index.js Normal file
View File

@ -0,0 +1,8 @@
import { registerRootComponent } from 'expo';
import App from './App';
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in Expo Go or in a native build,
// the environment is set up appropriately
registerRootComponent(App);

View File

@ -0,0 +1,4 @@
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require('expo/metro-config');
module.exports = getDefaultConfig(__dirname);

22646
CustomerApp/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

125
CustomerApp/package.json Normal file
View File

@ -0,0 +1,125 @@
{
"name": "enatega-full-app",
"version": "5.0.0",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"eject": "expo eject",
"test": "jest",
"format": "prettier --write '**/*.js'",
"lint:fix": "eslint . --ext .js --fix",
"postinstall": "patch-package"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": [
"npm run format",
"npm run lint:fix"
]
},
"dependencies": {
"@amplitude/analytics-react-native": "^1.1.1",
"@apollo/react-hooks": "^3.1.3",
"@expo/vector-icons": "^13.0.0",
"@ptomasroos/react-native-multi-slider": "^2.2.2",
"@react-native-async-storage/async-storage": "~1.17.3",
"@react-native-community/masked-view": "0.1.11",
"@react-navigation/drawer": "^6.6.0",
"@react-navigation/native": "^6.1.4",
"@react-navigation/native-stack": "^6.9.10",
"@react-navigation/stack": "^6.3.14",
"apollo-boost": "^0.4.9",
"apollo-cache-inmemory": "^1.5.1",
"apollo-cache-persist": "^0.1.1",
"apollo-client": "^2.5.1",
"apollo-link-context": "^1.0.17",
"apollo-link-http": "^1.5.14",
"apollo-link-state": "^0.4.2",
"apollo-link-ws": "^1.0.20",
"apollo-upload-client": "^10.0.0",
"apollo-utilities": "^1.3.4",
"deprecated-react-native-prop-types": "^4.0.0",
"expo": "^47.0.12",
"expo-app-loading": "~2.1.1",
"expo-apple-authentication": "~5.0.1",
"expo-application": "~5.0.1",
"expo-asset": "~8.7.0",
"expo-auth-session": "^3.8.0",
"expo-camera": "~13.1.0",
"expo-constants": "~14.0.2",
"expo-contacts": "~11.0.1",
"expo-device": "~5.0.0",
"expo-font": "~11.0.1",
"expo-image-picker": "~14.0.2",
"expo-linking": "~3.3.1",
"expo-localization": "~14.0.0",
"expo-location": "~15.0.1",
"expo-notifications": "~0.17.0",
"expo-random": "~13.0.0",
"expo-sensors": "~12.0.1",
"expo-splash-screen": "~0.17.5",
"expo-status-bar": "~1.4.2",
"expo-tracking-transparency": "~3.0.1",
"expo-updates": "~0.15.6",
"graphql": "^16.6.0",
"graphql-tag": "^2.10.1",
"i18n-js": "^3.2.2",
"lodash": "^4.17.21",
"patch-package": "^6.5.1",
"react": "18.1.0",
"react-apollo": "^3.1.5",
"react-native": "0.70.5",
"react-native-button": "^3.0.1",
"react-native-flash-message": "^0.4.0",
"react-native-flatlist-slider": "^1.0.5",
"react-native-gesture-handler": "~2.8.0",
"react-native-gifted-chat": "^1.1.1",
"react-native-maps": "1.3.2",
"react-native-material-textfield": "^0.16.1",
"react-native-modal": "^13.0.1",
"react-native-modalize": "^2.0.8",
"react-native-reanimated": "~2.12.0",
"react-native-safe-area-context": "4.4.1",
"react-native-screens": "~3.18.0",
"react-native-star-rating": "^1.1.0",
"react-native-svg": "13.4.0",
"react-native-timeline-flatlist": "^0.8.0",
"react-native-webview": "11.23.1",
"subscriptions-transport-ws": "^0.11.0",
"uuid": "^3.3.2",
"validate.js": "^0.13.1"
},
"devDependencies": {
"@babel/core": "^7.12.9",
"babel-jest": "^29.4.3",
"babel-preset-expo": "~9.2.1",
"babel-preset-react-native": "^4.0.1",
"eslint": "^8.34.0",
"eslint-config-standard": "^17.0.0",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.20.0",
"eslint-plugin-standard": "^5.0.0",
"husky": "^8.0.3",
"jest": "^29.4.3",
"jest-react-native": "^18.0.0",
"lint-staged": "^13.1.2",
"metro-react-native-babel-preset": "^0.75.0",
"prettier": "^2.3.1",
"prettier-config-standard": "^5.0.0",
"react-test-renderer": "^18.2.0"
},
"jest": {
"preset": "react-native"
},
"private": true,
"resolutions": {
"standard-version-expo/**/@expo/config-plugins": "5.0.2"
}
}

View File

@ -0,0 +1,38 @@
diff --git a/node_modules/react-native-button/Button.js b/node_modules/react-native-button/Button.js
index b248176..3c6aefa 100644
--- a/node_modules/react-native-button/Button.js
+++ b/node_modules/react-native-button/Button.js
@@ -1,4 +1,5 @@
import PropTypes from 'prop-types';
+import {TextPropTypes,ViewPropTypes} from 'deprecated-react-native-prop-types'
import React, { Component } from 'react';
import {
Platform,
@@ -7,7 +8,7 @@ import {
TouchableOpacity,
TouchableNativeFeedback,
View,
- ViewPropTypes
+ //ViewPropTypes
} from 'react-native';
import coalesceNonElementChildren from './coalesceNonElementChildren';
@@ -18,12 +19,15 @@ export default class Button extends Component {
static propTypes = {
...TouchableOpacity.propTypes,
accessibilityLabel: PropTypes.string,
- allowFontScaling: Text.propTypes.allowFontScaling,
+ // allowFontScaling: Text.propTypes.allowFontScaling,
+ allowFontScaling: TextPropTypes.allowFontScaling,
containerStyle: ViewPropTypes.style,
disabledContainerStyle: ViewPropTypes.style,
disabled: PropTypes.bool,
- style: Text.propTypes.style,
- styleDisabled: Text.propTypes.style,
+ style: TextPropTypes.style,
+ styleDisabled: TextPropTypes.style,
+ // style: Text.propTypes.style,
+ // styleDisabled: Text.propTypes.style,
childGroupStyle: ViewPropTypes.style,
androidBackground: PropTypes.object,
};

View File

@ -0,0 +1,405 @@
diff --git a/node_modules/react-native-material-textfield/src/components/affix/index.js b/node_modules/react-native-material-textfield/src/components/affix/index.js
index 0f85022..e467adb 100644
--- a/node_modules/react-native-material-textfield/src/components/affix/index.js
+++ b/node_modules/react-native-material-textfield/src/components/affix/index.js
@@ -9,26 +9,26 @@ export default class Affix extends PureComponent {
numberOfLines: 1,
};
- static propTypes = {
- numberOfLines: PropTypes.number,
- style: Animated.Text.propTypes.style,
+ // static propTypes = {
+ // numberOfLines: PropTypes.number,
+ // style: PropTypes.object,
- color: PropTypes.string.isRequired,
- fontSize: PropTypes.number.isRequired,
+ // color: PropTypes.string.isRequired,
+ // fontSize: PropTypes.number.isRequired,
- type: PropTypes
- .oneOf(['prefix', 'suffix'])
- .isRequired,
+ // type: PropTypes
+ // .oneOf(['prefix', 'suffix'])
+ // .isRequired,
- labelAnimation: PropTypes
- .instanceOf(Animated.Value)
- .isRequired,
+ // labelAnimation: PropTypes
+ // .instanceOf(Animated.Value)
+ // .isRequired,
- children: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.node),
- PropTypes.node,
- ]),
- };
+ // children: PropTypes.oneOfType([
+ // PropTypes.arrayOf(PropTypes.node),
+ // PropTypes.node,
+ // ]),
+ // };
render() {
let { labelAnimation, style, children, type, fontSize, color } = this.props;
diff --git a/node_modules/react-native-material-textfield/src/components/counter/index.js b/node_modules/react-native-material-textfield/src/components/counter/index.js
index 35d3264..089b871 100644
--- a/node_modules/react-native-material-textfield/src/components/counter/index.js
+++ b/node_modules/react-native-material-textfield/src/components/counter/index.js
@@ -5,15 +5,15 @@ import { Text } from 'react-native';
import styles from './styles';
export default class Counter extends PureComponent {
- static propTypes = {
- count: PropTypes.number.isRequired,
- limit: PropTypes.number,
+ // static propTypes = {
+ // count: PropTypes.number.isRequired,
+ // limit: PropTypes.number,
- baseColor: PropTypes.string.isRequired,
- errorColor: PropTypes.string.isRequired,
+ // baseColor: PropTypes.string.isRequired,
+ // errorColor: PropTypes.string.isRequired,
- style: Text.propTypes.style,
- };
+ // style: PropTypes.object,
+ // };
render() {
let { count, limit, baseColor, errorColor, style } = this.props;
diff --git a/node_modules/react-native-material-textfield/src/components/field/index.js b/node_modules/react-native-material-textfield/src/components/field/index.js
index 494bbaa..2a71c82 100644
--- a/node_modules/react-native-material-textfield/src/components/field/index.js
+++ b/node_modules/react-native-material-textfield/src/components/field/index.js
@@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import React, { PureComponent } from 'react';
+import {ViewPropTypes} from 'deprecated-react-native-prop-types';
import {
View,
Text,
@@ -7,7 +8,7 @@ import {
Animated,
StyleSheet,
Platform,
- ViewPropTypes,
+ //ViewPropTypes,
} from 'react-native';
import Line from '../line';
@@ -65,60 +66,60 @@ export default class TextField extends PureComponent {
disabled: false,
};
- static propTypes = {
- ...TextInput.propTypes,
+ // static propTypes = {
+ // ...TextInput.propTypes,
- animationDuration: PropTypes.number,
+ // animationDuration: PropTypes.number,
- fontSize: PropTypes.number,
- labelFontSize: PropTypes.number,
+ // fontSize: PropTypes.number,
+ // labelFontSize: PropTypes.number,
- contentInset: PropTypes.shape({
- top: PropTypes.number,
- label: PropTypes.number,
- input: PropTypes.number,
- left: PropTypes.number,
- right: PropTypes.number,
- }),
+ // contentInset: PropTypes.shape({
+ // top: PropTypes.number,
+ // label: PropTypes.number,
+ // input: PropTypes.number,
+ // left: PropTypes.number,
+ // right: PropTypes.number,
+ // }),
- labelOffset: Label.propTypes.offset,
+ // labelOffset: Label.propTypes.offset,
- labelTextStyle: Text.propTypes.style,
- titleTextStyle: Text.propTypes.style,
- affixTextStyle: Text.propTypes.style,
+ // labelTextStyle: PropTypes.object.style,
+ // // titleTextStyle: PropTypes.object.style,
+ // // affixTextStyle: PropTypes.object.style,
- tintColor: PropTypes.string,
- textColor: PropTypes.string,
- baseColor: PropTypes.string,
+ // tintColor: PropTypes.string,
+ // textColor: PropTypes.string,
+ // baseColor: PropTypes.string,
- label: PropTypes.string,
- title: PropTypes.string,
+ // label: PropTypes.string,
+ // title: PropTypes.string,
- characterRestriction: PropTypes.number,
+ // characterRestriction: PropTypes.number,
- error: PropTypes.string,
- errorColor: PropTypes.string,
+ // error: PropTypes.string,
+ // errorColor: PropTypes.string,
- lineWidth: PropTypes.number,
- activeLineWidth: PropTypes.number,
- disabledLineWidth: PropTypes.number,
+ // lineWidth: PropTypes.number,
+ // activeLineWidth: PropTypes.number,
+ // disabledLineWidth: PropTypes.number,
- lineType: Line.propTypes.lineType,
- disabledLineType: Line.propTypes.lineType,
+ // lineType: Line.propTypes.lineType,
+ // disabledLineType: Line.propTypes.lineType,
- disabled: PropTypes.bool,
+ // disabled: PropTypes.bool,
- formatText: PropTypes.func,
+ // formatText: PropTypes.func,
- renderLeftAccessory: PropTypes.func,
- renderRightAccessory: PropTypes.func,
+ // renderLeftAccessory: PropTypes.func,
+ // renderRightAccessory: PropTypes.func,
- prefix: PropTypes.string,
- suffix: PropTypes.string,
+ // prefix: PropTypes.string,
+ // suffix: PropTypes.string,
- containerStyle: (ViewPropTypes || View.propTypes).style,
- inputContainerStyle: (ViewPropTypes || View.propTypes).style,
- };
+ // containerStyle: (ViewPropTypes || View.propTypes).style,
+ // inputContainerStyle: (ViewPropTypes || View.propTypes).style,
+ // };
static inputContainerStyle = styles.inputContainer;
@@ -221,6 +222,7 @@ export default class TextField extends PureComponent {
let options = {
toValue: this.focusState(),
+ useNativeDriver: false,
duration,
};
diff --git a/node_modules/react-native-material-textfield/src/components/helper/index.js b/node_modules/react-native-material-textfield/src/components/helper/index.js
index 6060f9f..86ac2c0 100644
--- a/node_modules/react-native-material-textfield/src/components/helper/index.js
+++ b/node_modules/react-native-material-textfield/src/components/helper/index.js
@@ -1,23 +1,24 @@
import PropTypes from 'prop-types';
+
import React, { PureComponent } from 'react';
import { Animated } from 'react-native';
import styles from './styles';
export default class Helper extends PureComponent {
- static propTypes = {
- title: PropTypes.string,
- error: PropTypes.string,
+ // static propTypes = {
+ // title: PropTypes.string,
+ // error: PropTypes.string,
- disabled: PropTypes.bool,
+ // disabled: PropTypes.bool,
- style: Animated.Text.propTypes.style,
+ // style: PropTypes.object,
- baseColor: PropTypes.string,
- errorColor: PropTypes.string,
+ // baseColor: PropTypes.string,
+ // errorColor: PropTypes.string,
- focusAnimation: PropTypes.instanceOf(Animated.Value),
- };
+ // focusAnimation: PropTypes.instanceOf(Animated.Value),
+ // };
constructor(props) {
super(props);
diff --git a/node_modules/react-native-material-textfield/src/components/label/index.js b/node_modules/react-native-material-textfield/src/components/label/index.js
index 82eaf03..1ad9a93 100644
--- a/node_modules/react-native-material-textfield/src/components/label/index.js
+++ b/node_modules/react-native-material-textfield/src/components/label/index.js
@@ -11,41 +11,41 @@ export default class Label extends PureComponent {
restricted: false,
};
- static propTypes = {
- numberOfLines: PropTypes.number,
+ // static propTypes = {
+ // numberOfLines: PropTypes.number,
- disabled: PropTypes.bool,
- restricted: PropTypes.bool,
+ // disabled: PropTypes.bool,
+ // restricted: PropTypes.bool,
- fontSize: PropTypes.number.isRequired,
- activeFontSize: PropTypes.number.isRequired,
+ // fontSize: PropTypes.number.isRequired,
+ // activeFontSize: PropTypes.number.isRequired,
- baseColor: PropTypes.string.isRequired,
- tintColor: PropTypes.string.isRequired,
- errorColor: PropTypes.string.isRequired,
+ // baseColor: PropTypes.string.isRequired,
+ // tintColor: PropTypes.string.isRequired,
+ // errorColor: PropTypes.string.isRequired,
- focusAnimation: PropTypes
- .instanceOf(Animated.Value)
- .isRequired,
+ // focusAnimation: PropTypes
+ // .instanceOf(Animated.Value)
+ // .isRequired,
- labelAnimation: PropTypes
- .instanceOf(Animated.Value)
- .isRequired,
+ // labelAnimation: PropTypes
+ // .instanceOf(Animated.Value)
+ // .isRequired,
- contentInset: PropTypes.shape({
- label: PropTypes.number,
- }),
+ // contentInset: PropTypes.shape({
+ // label: PropTypes.number,
+ // }),
- offset: PropTypes.shape({
- x0: PropTypes.number,
- y0: PropTypes.number,
- x1: PropTypes.number,
- y1: PropTypes.number,
- }),
+ // offset: PropTypes.shape({
+ // x0: PropTypes.number,
+ // y0: PropTypes.number,
+ // x1: PropTypes.number,
+ // y1: PropTypes.number,
+ // }),
- style: Animated.Text.propTypes.style,
- label: PropTypes.string,
- };
+ // style: PropTypes.object,
+ // label: PropTypes.string,
+ // };
render() {
let {
diff --git a/node_modules/react-native-material-textfield/src/components/line/index.js b/node_modules/react-native-material-textfield/src/components/line/index.js
index 44995e9..b689387 100644
--- a/node_modules/react-native-material-textfield/src/components/line/index.js
+++ b/node_modules/react-native-material-textfield/src/components/line/index.js
@@ -16,23 +16,23 @@ export default class Line extends PureComponent {
restricted: false,
};
- static propTypes = {
- lineType: lineTypes,
- disabledLineType: lineTypes,
+ // static propTypes = {
+ // lineType: lineTypes,
+ // disabledLineType: lineTypes,
- disabled: PropTypes.bool,
- restricted: PropTypes.bool,
+ // disabled: PropTypes.bool,
+ // restricted: PropTypes.bool,
- tintColor: PropTypes.string,
- baseColor: PropTypes.string,
- errorColor: PropTypes.string,
+ // tintColor: PropTypes.string,
+ // baseColor: PropTypes.string,
+ // errorColor: PropTypes.string,
- lineWidth: PropTypes.number,
- activeLineWidth: PropTypes.number,
- disabledLineWidth: PropTypes.number,
+ // lineWidth: PropTypes.number,
+ // activeLineWidth: PropTypes.number,
+ // disabledLineWidth: PropTypes.number,
- focusAnimation: PropTypes.instanceOf(Animated.Value),
- };
+ // focusAnimation: PropTypes.instanceOf(Animated.Value),
+ // };
static getDerivedStateFromProps(props, state) {
let { lineWidth, activeLineWidth, disabledLineWidth } = props;
diff --git a/node_modules/react-native-material-textfield/src/components/outline/index.js b/node_modules/react-native-material-textfield/src/components/outline/index.js
index 9347a99..9c3e8a3 100644
--- a/node_modules/react-native-material-textfield/src/components/outline/index.js
+++ b/node_modules/react-native-material-textfield/src/components/outline/index.js
@@ -11,29 +11,29 @@ export default class Line extends PureComponent {
restricted: false,
};
- static propTypes = {
- lineType: PropTypes.oneOf(['solid', 'none']),
+ // static propTypes = {
+ // lineType: PropTypes.oneOf(['solid', 'none']),
- disabled: PropTypes.bool,
- restricted: PropTypes.bool,
+ // disabled: PropTypes.bool,
+ // restricted: PropTypes.bool,
- tintColor: PropTypes.string,
- baseColor: PropTypes.string,
- errorColor: PropTypes.string,
+ // tintColor: PropTypes.string,
+ // baseColor: PropTypes.string,
+ // errorColor: PropTypes.string,
- lineWidth: PropTypes.number,
- activeLineWidth: PropTypes.number,
- disabledLineWidth: PropTypes.number,
+ // lineWidth: PropTypes.number,
+ // activeLineWidth: PropTypes.number,
+ // disabledLineWidth: PropTypes.number,
- focusAnimation: PropTypes.instanceOf(Animated.Value),
- labelAnimation: PropTypes.instanceOf(Animated.Value),
- labelWidth: PropTypes.instanceOf(Animated.Value),
+ // focusAnimation: PropTypes.instanceOf(Animated.Value),
+ // labelAnimation: PropTypes.instanceOf(Animated.Value),
+ // labelWidth: PropTypes.instanceOf(Animated.Value),
- contentInset: PropTypes.shape({
- left: PropTypes.number,
- right: PropTypes.number,
- }),
- };
+ // contentInset: PropTypes.shape({
+ // left: PropTypes.number,
+ // right: PropTypes.number,
+ // }),
+ // };
borderProps() {
let {

View File

@ -0,0 +1,34 @@
diff --git a/node_modules/react-native-star-rating/node_modules/react-native-button/Button.js b/node_modules/react-native-star-rating/node_modules/react-native-button/Button.js
index fb7cf46..8e4c522 100644
--- a/node_modules/react-native-star-rating/node_modules/react-native-button/Button.js
+++ b/node_modules/react-native-star-rating/node_modules/react-native-button/Button.js
@@ -1,11 +1,12 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
+import {TextPropTypes,ViewPropTypes} from 'deprecated-react-native-prop-types'
import {
StyleSheet,
Text,
TouchableOpacity,
View,
- ViewPropTypes,
+ //ViewPropTypes,
} from 'react-native';
import coalesceNonElementChildren from './coalesceNonElementChildren';
@@ -16,12 +17,12 @@ export default class Button extends Component {
static propTypes = {
...TouchableOpacity.propTypes,
accessibilityLabel: PropTypes.string,
- allowFontScaling: Text.propTypes.allowFontScaling,
+ allowFontScaling: TextPropTypes.allowFontScaling,
containerStyle: ViewPropTypes.style,
disabledContainerStyle: ViewPropTypes.style,
disabled: PropTypes.bool,
- style: Text.propTypes.style,
- styleDisabled: Text.propTypes.style,
+ style: TextPropTypes.style,
+ styleDisabled: TextPropTypes.style,
childGroupStyle: ViewPropTypes.style,
};

View File

@ -0,0 +1,26 @@
diff --git a/node_modules/react-native-star-rating/StarButton.js b/node_modules/react-native-star-rating/StarButton.js
index b6db613..8a62f5a 100644
--- a/node_modules/react-native-star-rating/StarButton.js
+++ b/node_modules/react-native-star-rating/StarButton.js
@@ -1,6 +1,7 @@
// React and react native imports
import React, { Component } from 'react';
-import { Image, StyleSheet, ViewPropTypes } from 'react-native';
+import { Image, StyleSheet } from 'react-native';
+import {ViewPropTypes} from 'deprecated-react-native-prop-types';
import PropTypes from 'prop-types';
import { createIconSetFromIcoMoon } from 'react-native-vector-icons';
diff --git a/node_modules/react-native-star-rating/StarRating.js b/node_modules/react-native-star-rating/StarRating.js
index 7aecc95..de6397c 100644
--- a/node_modules/react-native-star-rating/StarRating.js
+++ b/node_modules/react-native-star-rating/StarRating.js
@@ -1,6 +1,7 @@
// React and react native imports
import React, { Component } from 'react';
-import { View, ViewPropTypes, StyleSheet } from 'react-native';
+import { View, StyleSheet } from 'react-native';
+import {ViewPropTypes} from 'deprecated-react-native-prop-types';
import PropTypes from 'prop-types';
import { View as AnimatableView } from 'react-native-animatable';

BIN
CustomerApp/src/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,26 @@
const COLORS = {
white: '#FFFFFF',
black: '#000000',
black02: 'rgba(0, 0, 0, 0.2)',
primary: '#febb2c',
darkGrey: '#333333',
offWhite: '#FAFAFA',
lineGrey: '#e7e5e4',
lightGrey: '#a5a5a5',
lightWhite: '#FCFCFC',
whitishGrey: '#7F7F7F',
lightBlack: '#292929',
redishPink: '#ff4866',
primaryBlue: '#00b9c6',
primaryBlack: '#0b0b0b',
blueShadeGrey: '#f7f7fb',
primaryLightBlue: '#0cc8d5',
lightBlueShadeGrey: '#f8f9fa',
mediumBlueShadeGrey: '#f2f4f5',
black06: 'rgba(0,0,0,0.6)',
white06: 'rgba(255,255,255,0.6)',
redishOrange: '#FA7751',
blueColor: '#00b9c6',
yellowishOrange: '#fff1d4'
}
export { COLORS }

View File

@ -0,0 +1,82 @@
import { DarkTheme, DefaultTheme } from '@react-navigation/native'
import { COLORS } from './Colors'
const Theme = {
Light: {
...DefaultTheme,
colors: {
...DefaultTheme.colors,
black: COLORS.black,
white: COLORS.white,
curve: COLORS.primary,
selected: COLORS.primary,
fontWhite: COLORS.white,
tagColor: COLORS.primary,
iconColor: COLORS.darkGrey,
iconColorPrimary: COLORS.primary,
cardContainer: COLORS.white,
rippleColor: COLORS.black02,
background: COLORS.white,
lightBackground: COLORS.lightBlueShadeGrey,
headerbackground: COLORS.primary,
headerbackground2: COLORS.offWhite,
headerTextColor: COLORS.primaryBlack,
fontMainColor: COLORS.primaryBlack,
fontSecondColor: COLORS.lightGrey,
placeHolderColor: COLORS.lightGrey,
buttonBackground: COLORS.primary,
buttonBackgroundLight: COLORS.mediumBlueShadeGrey,
buttonBackgroundBlue: COLORS.primaryLightBlue,
active: COLORS.primaryLightBlue,
buttonText: COLORS.white,
horizontalLine: COLORS.lineGrey,
shadowColor: COLORS.black06,
drawerBackground: COLORS.primary,
spinnerColor: COLORS.primary,
errorColor: COLORS.redishOrange,
radioColor: COLORS.white,
radioOuterColor: COLORS.primary,
blueColor: COLORS.blueColor,
chatBubblePrimary: COLORS.yellowishOrange
}
},
Dark: {
...DarkTheme,
colors: {
...DarkTheme.colors,
white: COLORS.white,
black: COLORS.black,
curve: COLORS.primary,
selected: COLORS.primary,
fontWhite: COLORS.white,
tagColor: COLORS.primary,
rippleColor: COLORS.black02,
background: COLORS.lightBlack,
lightBackground: COLORS.lightBlueShadeGrey,
cardContainer: COLORS.darkGrey,
iconColor: COLORS.lightWhite,
iconColorPrimary: COLORS.primary,
headerbackground: COLORS.black,
headerbackground2: COLORS.black,
headerTextColor: COLORS.primaryBlack,
fontMainColor: COLORS.lightWhite,
fontSecondColor: COLORS.whitishGrey,
placeHolderColor: COLORS.lightGrey,
buttonBackground: COLORS.primary,
buttonBackgroundLight: COLORS.mediumBlueShadeGrey,
buttonBackgroundBlue: COLORS.primaryLightBlue,
active: COLORS.primaryLightBlue,
buttonText: COLORS.white,
horizontalLine: COLORS.lineGrey,
shadowColor: COLORS.white06,
drawerBackground: COLORS.primary,
spinnerColor: COLORS.primary,
errorColor: COLORS.redishOrange,
radioColor: COLORS.white,
radioOuterColor: COLORS.primary,
blueColor: COLORS.blueColor,
chatBubblePrimary: COLORS.yellowishOrange
}
}
}
export default Theme

View File

@ -0,0 +1,4 @@
import { COLORS } from './Colors'
import THEME from './Theme'
export { COLORS, THEME }

View File

@ -0,0 +1,92 @@
import AsyncStorage from '@react-native-async-storage/async-storage'
import { defaultDataIdFromObject, InMemoryCache } from 'apollo-cache-inmemory'
import { persistCache } from 'apollo-cache-persist'
import { ApolloClient } from 'apollo-client'
import { ApolloLink, concat, Observable, split } from 'apollo-link'
import { createHttpLink } from 'apollo-link-http'
import { WebSocketLink } from 'apollo-link-ws'
import { getMainDefinition } from 'apollo-utilities'
import getEnvVars from '../../environment'
const { GRAPHQL_URL, WS_GRAPHQL_URL } = getEnvVars()
const cache = new InMemoryCache({
dataIdFromObject: object => {
switch (object.__typename) {
case 'CartItem':
return object.key // use `key` as the primary key
default:
return defaultDataIdFromObject(object) // fall back to default handling
}
}
})
const httpLink = createHttpLink({
uri: GRAPHQL_URL
})
const wsLink = new WebSocketLink({
uri: WS_GRAPHQL_URL,
options: {
reconnect: true
}
})
const request = async operation => {
const token = await AsyncStorage.getItem('token')
operation.setContext({
// get the authentication token from local storage if it exists
// return the headers to the context so httpLink can read them
headers: {
authorization: token ? `Bearer ${token}` : ''
}
})
}
const requestLink = new ApolloLink(
(operation, forward) =>
new Observable(observer => {
// console.log(observer)
let handle
Promise.resolve(operation)
.then(oper => request(oper))
.then(() => {
handle = forward(operation).subscribe({
next: observer.next.bind(observer),
error: observer.error.bind(observer),
complete: observer.complete.bind(observer)
})
})
.catch(observer.error.bind(observer))
return () => {
if (handle) handle.unsubscribe()
}
})
)
const terminatingLink = split(({ query }) => {
const { kind, operation } = getMainDefinition(query)
return kind === 'OperationDefinition' && operation === 'subscription'
}, wsLink)
const setupApollo = async() => {
await persistCache({
cache,
storage: AsyncStorage
})
const client = new ApolloClient({
link: concat(ApolloLink.from([terminatingLink, requestLink]), httpLink),
cache,
resolvers: {}
})
// set ref for global use
// eslint-disable-next-line no-undef
clientRef = client
return client
}
export default setupApollo

View File

@ -0,0 +1,590 @@
export const login = `
mutation Login($facebookId:String,$email:String,$password:String,$type:String!,$appleId:String,$name:String,$notificationToken:String){
login(facebookId:$facebookId,email:$email,password:$password,type:$type,appleId:$appleId,name:$name,notificationToken:$notificationToken){
userId
token
tokenExpiration
name
email
phone
}
}
`
export const categories = `
{
categories{
_id
title
description
img_menu
}
}`
export const foods = `
query FoodByCategory($category:String!,$onSale:Boolean,$inStock:Boolean,$min:Float,$max:Float,$search:String){
foodByCategory(category:$category,onSale:$onSale,inStock:$inStock,min:$min,max:$max,search:$search){
_id
title
description
variations{
_id
title
price
discounted
addons{
_id
title
description
quantity_minimum
quantity_maximum
options{
_id
title
description
price
}
}
}
category{_id}
img_url
stock
}
}`
export const createUser = `
mutation CreateUser($facebookId:String,$phone:String,$email:String,$password:String,$name:String,$notificationToken:String,$appleId:String){
createUser(userInput:{
facebookId:$facebookId,
phone:$phone,
email:$email,
password:$password,
name:$name,
notificationToken:$notificationToken,
appleId:$appleId
}){
userId
token
tokenExpiration
name
email
phone
notificationToken
}
}`
export const updateUser = `
mutation UpdateUser($name:String!,$phone:String!){
updateUser(updateUserInput:{name:$name,phone:$phone}){
_id
name
phone
}
}`
export const updateNotificationStatus = `
mutation UpdateNotificationStatus($offerNotification:Boolean!,$orderNotification:Boolean!){
updateNotificationStatus(offerNotification:$offerNotification,orderNotification:$orderNotification){
_id
notificationToken
is_order_notification
is_offer_notification
}
}`
export const profile = `
query{
profile{
_id
name
phone
email
notificationToken
is_order_notification
is_offer_notification
addresses{
_id
label
delivery_address
details
longitude
latitude
selected
}
}
}`
export const order = `query Order($id:String!){
order(id:$id){
_id
delivery_address{
latitude
longitude
delivery_address
details
label
}
delivery_charges
order_id
user{
_id
phone
}
items{
_id
food{
_id
title
category{
_id
}
description
img_url
}
variation{
_id
title
price
}
addons{
_id
title
description
quantity_minimum
quantity_maximum
options{
_id
title
description
price
}
}
quantity
}
payment_status
payment_method
order_amount
paid_amount
order_status
status_queue{
pending
preparing
picked
delivered
cancelled
}
createdAt
review{
_id
rating
description
}
rider{
_id
}
}
}
`
export const myOrders = `query Orders($offset:Int){
orders(offset:$offset){
_id
delivery_address{
latitude
longitude
delivery_address
details
label
}
delivery_charges
order_id
user{
_id
phone
}
items{
_id
food{
_id
title
category{
_id
}
description
img_url
}
variation{
_id
title
price
}
addons{
_id
title
description
quantity_minimum
quantity_maximum
options{
_id
title
description
price
}
}
quantity
}
payment_status
payment_method
order_amount
paid_amount
order_status
status_queue{
pending
preparing
picked
delivered
cancelled
}
createdAt
review{
_id
rating
description
}
rider{
_id
}
}
}
`
//
// can we get userId from request instead??
// needs research
//
export const orderStatusChanged = `subscription OrderStatusChanged($userId:String!){
orderStatusChanged(userId:$userId)
{
userId
origin
order{
_id
delivery_address{
latitude
longitude
delivery_address
details
label
}
delivery_charges
order_id
user{
_id
phone
}
items{
_id
food{
_id
title
category{
_id
}
description
img_url
}
variation{
_id
title
price
}
addons{
_id
title
description
quantity_minimum
quantity_maximum
options{
_id
title
description
price
}
}
quantity
}
payment_status
payment_method
order_amount
paid_amount
order_status
status_queue{
pending
preparing
picked
delivered
cancelled
}
createdAt
review{
_id
rating
description
}
rider{
_id
}
}
}
}
`
//
// status queue??
// can we use address id instead of address object, then get the address on backend??
//
export const placeOrder = `
mutation PlaceOrder($orderInput:[OrderInput!]!,$paymentMethod:String!,$couponCode:String,$address:AddressInput!){
placeOrder(orderInput: $orderInput,paymentMethod:$paymentMethod,couponCode:$couponCode,address:$address) {
_id
order_id
delivery_address{
latitude
longitude
delivery_address
details
label
}
delivery_charges
items{
_id
food{
_id
title
category{
_id
}
description
img_url
}
variation{
_id
title
price
}
addons{
_id
title
description
quantity_minimum
quantity_maximum
options{
_id
title
description
price
}
}
quantity
}
user {
_id
phone
email
}
rider{
_id
}
payment_status
payment_method
paid_amount
order_amount
order_status
status_queue{
pending
preparing
picked
delivered
cancelled
}
createdAt
review{
_id
rating
description
}
}
}`
export const reviewOrder = `mutation ReviewOrder(
$orderId:String!,
$rating:Int!,
$description:String
){
reviewOrder(reviewInput:{
orderId:$orderId,
rating:$rating,
description:$description
}){
_id
order_id
review{
_id
rating
description
}
createdAt
updatedAt
is_active
}
}`
//
// use this to push token instead of login, signup mutation?
// needs research
//
export const pushToken = `mutation PushToken($token:String!){
pushToken(token:$token){
_id
notificationToken
}
}`
export const getConfiguration = `query Configuration{
configuration{
_id
currency
currency_symbol
delivery_charges
}
}`
export const foodByIds = `query FoodByIds($ids:[String!]!){
foodByIds(ids: $ids) {
_id
title
description
img_url
stock
category {
_id
}
variations {
_id
title
price
discounted
addons {
_id
title
description
quantity_minimum
quantity_maximum
options {
_id
title
description
price
}
}
}
}
}`
export const getCoupon = `mutation Coupon($coupon:String!){
coupon(coupon:$coupon){
_id
code
discount
enabled
}
}`
export const deleteAddress = `mutation DeleteAddress($id:ID!){
deleteAddress(id:$id){
_id
addresses{
_id
label
delivery_address
details
longitude
latitude
selected
}
}
}`
export const createAddress = `mutation CreateAddress($addressInput:AddressInput!){
createAddress(addressInput:$addressInput){
_id
addresses{
_id
label
delivery_address
details
longitude
latitude
selected
}
}
}`
export const editAddress = `mutation EditAddress($addressInput:AddressInput!){
editAddress(addressInput:$addressInput){
_id
label
delivery_address
details
longitude
latitude
}
}`
export const changePassword = `mutation ChangePassword($oldPassword:String!,$newPassword:String!){
changePassword(oldPassword:$oldPassword,newPassword:$newPassword)
}`
export const forgotPassword = `mutation ForgotPassword($email:String!){
forgotPassword(email:$email){
result
}
}`
export const selectAddress = `mutation SelectAddress($id:String!){
selectAddress(id:$id){
_id
addresses{
_id
label
delivery_address
details
longitude
latitude
selected
}
}
}`
export const subscriptionRiderLocation = `subscription SubscriptionRiderLocation($riderId:String!){
subscriptionRiderLocation(riderId:$riderId) {
_id
location {
latitude
longitude
}
}
}`
export const rider = `query Rider($id:String){
rider(id:$id){
_id
location {
latitude
longitude
}
}
}`

BIN
CustomerApp/src/assets/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
CustomerApp/src/assets/images/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,20 @@
import * as React from 'react'
import Svg, { Path } from 'react-native-svg'
function LogoAlphabet(props) {
return (
<Svg
xmlns="http://www.w3.org/2000/svg"
width={71.456}
height={69.504}
viewBox="0 0 71.456 69.504"
{...props}>
<Path
fill="#0b0b0b"
d="M36.914 69.503a83.004 83.004 0 01-3.529-.106C15.33 68.497.674 54.169.027 36.773a35.8 35.8 0 018.081-24.387A35.35 35.35 0 0130.626.199a28.342 28.342 0 013.9-.192h.237Q42.995-.001 51.227 0h15.658a4.54 4.54 0 013.9 2.193 4.525 4.525 0 01.161 4.459l-1.9 3.675-3.007 5.793c-3.808 7.333-7.746 14.914-11.558 22.4a6.11 6.11 0 01-5.984 3.75h-.124c-4.9-.053-10.119-.077-16.925-.077q-4.46 0-8.922.009l-6.04.007a26.533 26.533 0 002.291 4.166 18.962 18.962 0 0015.822 8.18c1.459.03 3 .043 4.862.043q1.175 0 2.363-.005h.012a2.7 2.7 0 012.307 1.291 2.707 2.707 0 01.1 2.652l-4.9 9.505a2.705 2.705 0 01-2.4 1.466zM24.305 27.258c6.041 0 12.52-.009 19.069-.078a2.429 2.429 0 00.263-.382c1.73-3.181 3.417-6.466 5.05-9.641l1.141-2.219-2.237-.013c-2.088-.013-4.143-.026-6.18-.026-3.162 0-5.75.031-8.142.1a18.038 18.038 0 00-11.515 4.771 18.807 18.807 0 00-5.338 7.484z"
/>
</Svg>
)
}
export default React.memo(LogoAlphabet)

Some files were not shown because too many files have changed in this diff Show More