├── src ├── screens │ ├── myjobs │ │ ├── myjobsheader.js │ │ └── index.js │ ├── jobs │ │ ├── MainThread.js │ │ ├── WorkAreaNotSet.js │ │ ├── NoOpenJobAlert.js │ │ └── index.js │ ├── home │ │ └── index.js │ ├── menu │ │ ├── userinfo.js │ │ └── index.js │ ├── page │ │ └── index.js │ ├── chatscreen │ │ ├── chatheader.js │ │ └── index.js │ └── login │ │ └── index.js ├── components │ ├── ChatComponents │ │ ├── Chat │ │ │ ├── document.js │ │ │ ├── priceask.js │ │ │ ├── termschanged.js │ │ │ ├── daysask.js │ │ │ └── index.js │ │ ├── label │ │ │ └── index.js │ │ ├── ChatAlert │ │ │ └── index.js │ │ ├── ChangeJobStatus │ │ │ └── index.js │ │ ├── ChatInput │ │ │ └── index.js │ │ └── ChatJobDescription │ │ │ └── index.js │ ├── dumbcomponent.js │ ├── ItemContainer │ │ └── index.js │ ├── Button │ │ └── index.js │ ├── Item │ │ └── index.js │ ├── Alerts │ │ └── index.js │ ├── Card │ │ ├── cardfooter.js │ │ ├── index.js │ │ ├── cardheader.js │ │ └── cardbody.js │ ├── Search │ │ └── index.js │ ├── Input │ │ └── index.js │ ├── BackgroundImage │ │ └── index.js │ └── Header │ │ └── index.js ├── modules │ ├── package.json │ └── account │ │ ├── types.js │ │ ├── index.js │ │ ├── actions.js │ │ └── reducers.js ├── utils │ ├── package.json │ ├── StartAJob.db │ ├── configs.js │ └── Functions.js ├── global.js ├── store.js ├── router.js └── Database.js ├── assets ├── flag │ ├── package.json │ ├── IL.png │ └── RU.png ├── clip.png ├── docx.png ├── flag.png ├── glob.png ├── help.png ├── icon.jpg ├── icon.png ├── logo.jpg ├── logo.png ├── map.png ├── tick.png ├── avatar.png ├── block.png ├── clock.png ├── emoji.png ├── house.png ├── login.png ├── o-icon.png ├── search.png ├── splash.png ├── wallet.png ├── baglogo.png ├── barcode.png ├── cabinet.png ├── download.png ├── home-icon.png ├── ion-menu.png ├── money-bag.png ├── my-work.png ├── no_image.png ├── setting.png ├── sign-in.png ├── star-icon.png ├── arrow-down.png ├── background.png ├── camera-icon.png ├── clock-blue.png ├── clock-green.png ├── double-tick.png ├── left-arrow.png ├── login-black.png ├── my-business.png ├── phone-icon.png ├── right-arrow.png ├── sand-watch.png ├── trust-icon.png ├── trust-white.png ├── wallet-blue.png ├── bag-icon-blue.png ├── bag-icon-gray.png ├── bag-icon-white.png ├── deposit-fund.png ├── facebook_icon.png ├── home-icon-blue.png ├── home-icon-gray.png ├── menu-icon-blue.png ├── menu-icon-gray.png ├── no-jobs-icon.png ├── rate-employe.png ├── withdraw-fund.png ├── blue-double-tick.png ├── hand-shake-green.png ├── hand-shake-white.png ├── home-icon-white.png ├── menu-icon-white.png ├── new-message-icon.png ├── sand-watch-blue.png ├── background-pattern.png ├── fulltime-job-icon.png ├── no-work-area-icon.png ├── one-time-job-icon.png ├── three-vertical-dots.png ├── bag-icon-blue-outline.png ├── background-pattern-gray.png ├── Union.svg └── chat-background.svg ├── startajob.keystore ├── babel.config.js ├── .expo-shared └── assets.json ├── .gitignore ├── app.json ├── App.js └── package.json /src/screens/myjobs/myjobsheader.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/ChatComponents/Chat/document.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/flag/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flag" 3 | } -------------------------------------------------------------------------------- /src/modules/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@modules" 3 | } -------------------------------------------------------------------------------- /src/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@utils" 3 | } -------------------------------------------------------------------------------- /assets/clip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/clip.png -------------------------------------------------------------------------------- /assets/docx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/docx.png -------------------------------------------------------------------------------- /assets/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/flag.png -------------------------------------------------------------------------------- /assets/glob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/glob.png -------------------------------------------------------------------------------- /assets/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/help.png -------------------------------------------------------------------------------- /assets/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/icon.jpg -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/icon.png -------------------------------------------------------------------------------- /assets/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/logo.jpg -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/logo.png -------------------------------------------------------------------------------- /assets/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/map.png -------------------------------------------------------------------------------- /assets/tick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/tick.png -------------------------------------------------------------------------------- /assets/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/avatar.png -------------------------------------------------------------------------------- /assets/block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/block.png -------------------------------------------------------------------------------- /assets/clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/clock.png -------------------------------------------------------------------------------- /assets/emoji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/emoji.png -------------------------------------------------------------------------------- /assets/house.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/house.png -------------------------------------------------------------------------------- /assets/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/login.png -------------------------------------------------------------------------------- /assets/o-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/o-icon.png -------------------------------------------------------------------------------- /assets/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/search.png -------------------------------------------------------------------------------- /assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/splash.png -------------------------------------------------------------------------------- /assets/wallet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/wallet.png -------------------------------------------------------------------------------- /assets/baglogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/baglogo.png -------------------------------------------------------------------------------- /assets/barcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/barcode.png -------------------------------------------------------------------------------- /assets/cabinet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/cabinet.png -------------------------------------------------------------------------------- /assets/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/download.png -------------------------------------------------------------------------------- /assets/flag/IL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/flag/IL.png -------------------------------------------------------------------------------- /assets/flag/RU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/flag/RU.png -------------------------------------------------------------------------------- /assets/home-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/home-icon.png -------------------------------------------------------------------------------- /assets/ion-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/ion-menu.png -------------------------------------------------------------------------------- /assets/money-bag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/money-bag.png -------------------------------------------------------------------------------- /assets/my-work.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/my-work.png -------------------------------------------------------------------------------- /assets/no_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/no_image.png -------------------------------------------------------------------------------- /assets/setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/setting.png -------------------------------------------------------------------------------- /assets/sign-in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/sign-in.png -------------------------------------------------------------------------------- /assets/star-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/star-icon.png -------------------------------------------------------------------------------- /startajob.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/startajob.keystore -------------------------------------------------------------------------------- /assets/arrow-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/arrow-down.png -------------------------------------------------------------------------------- /assets/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/background.png -------------------------------------------------------------------------------- /assets/camera-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/camera-icon.png -------------------------------------------------------------------------------- /assets/clock-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/clock-blue.png -------------------------------------------------------------------------------- /assets/clock-green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/clock-green.png -------------------------------------------------------------------------------- /assets/double-tick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/double-tick.png -------------------------------------------------------------------------------- /assets/left-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/left-arrow.png -------------------------------------------------------------------------------- /assets/login-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/login-black.png -------------------------------------------------------------------------------- /assets/my-business.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/my-business.png -------------------------------------------------------------------------------- /assets/phone-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/phone-icon.png -------------------------------------------------------------------------------- /assets/right-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/right-arrow.png -------------------------------------------------------------------------------- /assets/sand-watch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/sand-watch.png -------------------------------------------------------------------------------- /assets/trust-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/trust-icon.png -------------------------------------------------------------------------------- /assets/trust-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/trust-white.png -------------------------------------------------------------------------------- /assets/wallet-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/wallet-blue.png -------------------------------------------------------------------------------- /src/utils/StartAJob.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/src/utils/StartAJob.db -------------------------------------------------------------------------------- /assets/bag-icon-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/bag-icon-blue.png -------------------------------------------------------------------------------- /assets/bag-icon-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/bag-icon-gray.png -------------------------------------------------------------------------------- /assets/bag-icon-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/bag-icon-white.png -------------------------------------------------------------------------------- /assets/deposit-fund.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/deposit-fund.png -------------------------------------------------------------------------------- /assets/facebook_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/facebook_icon.png -------------------------------------------------------------------------------- /assets/home-icon-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/home-icon-blue.png -------------------------------------------------------------------------------- /assets/home-icon-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/home-icon-gray.png -------------------------------------------------------------------------------- /assets/menu-icon-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/menu-icon-blue.png -------------------------------------------------------------------------------- /assets/menu-icon-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/menu-icon-gray.png -------------------------------------------------------------------------------- /assets/no-jobs-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/no-jobs-icon.png -------------------------------------------------------------------------------- /assets/rate-employe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/rate-employe.png -------------------------------------------------------------------------------- /assets/withdraw-fund.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/withdraw-fund.png -------------------------------------------------------------------------------- /assets/blue-double-tick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/blue-double-tick.png -------------------------------------------------------------------------------- /assets/hand-shake-green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/hand-shake-green.png -------------------------------------------------------------------------------- /assets/hand-shake-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/hand-shake-white.png -------------------------------------------------------------------------------- /assets/home-icon-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/home-icon-white.png -------------------------------------------------------------------------------- /assets/menu-icon-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/menu-icon-white.png -------------------------------------------------------------------------------- /assets/new-message-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/new-message-icon.png -------------------------------------------------------------------------------- /assets/sand-watch-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/sand-watch-blue.png -------------------------------------------------------------------------------- /assets/background-pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/background-pattern.png -------------------------------------------------------------------------------- /assets/fulltime-job-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/fulltime-job-icon.png -------------------------------------------------------------------------------- /assets/no-work-area-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/no-work-area-icon.png -------------------------------------------------------------------------------- /assets/one-time-job-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/one-time-job-icon.png -------------------------------------------------------------------------------- /assets/three-vertical-dots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/three-vertical-dots.png -------------------------------------------------------------------------------- /assets/bag-icon-blue-outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/bag-icon-blue-outline.png -------------------------------------------------------------------------------- /src/modules/account/types.js: -------------------------------------------------------------------------------- 1 | export default { 2 | SET_USER: 'SET_USER', 3 | SIGN_IN: 'SIGN_IN', 4 | SIGN_OUT: 'SIGN_OUT' 5 | } -------------------------------------------------------------------------------- /assets/background-pattern-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnative1126/StartAJob_ReactNative/HEAD/assets/background-pattern-gray.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "f9155ac790fd02fadcdeca367b02581c04a353aa6d5aa84409a59f6804c87acd": true, 3 | "89ed26367cdb9b771858e026f2eb95bfdb90e5ae943e716575327ec325f39c44": true 4 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | *.jks 5 | *.p8 6 | *.p12 7 | *.key 8 | *.mobileprovision 9 | *.orig.* 10 | web-build/ 11 | web-report/ 12 | 13 | # macOS 14 | .DS_Store 15 | -------------------------------------------------------------------------------- /src/utils/configs.js: -------------------------------------------------------------------------------- 1 | export default { 2 | generalURL: "http://isapi.mekashron.com/StartAJob/General.dll/soap/IGeneral", 3 | jobURL: "http://isapi.mekashron.com/StartAJob/JobManagement.dll/soap/IJobManagement", 4 | } -------------------------------------------------------------------------------- /src/modules/account/index.js: -------------------------------------------------------------------------------- 1 | import accountReducer from './reducers'; 2 | 3 | export { default as accountActionTypes } from './types'; 4 | export { default as accountActions } from './actions'; 5 | 6 | export default accountReducer; 7 | -------------------------------------------------------------------------------- /src/screens/jobs/MainThread.js: -------------------------------------------------------------------------------- 1 | import { self } from 'react-native-threads'; 2 | // import { self } from 'react-native-workers'; 3 | 4 | let count = 0; 5 | 6 | self.onmessage = message => { 7 | console.log(`THREAD: got message ${message}`); 8 | 9 | count++; 10 | 11 | self.postMessage(`Message #${count} from worker thread!`); 12 | } -------------------------------------------------------------------------------- /src/modules/account/actions.js: -------------------------------------------------------------------------------- 1 | import types from './types'; 2 | 3 | export const setUser = (data) => ({ 4 | type: types.SET_USER, 5 | payload: data, 6 | }); 7 | 8 | export const signIn = (data) => ({ 9 | type: types.SIGN_IN, 10 | payload: data, 11 | }); 12 | 13 | export const signOut = (data) => ({ 14 | type: types.SIGN_OUT, 15 | payload: data, 16 | }) -------------------------------------------------------------------------------- /src/components/dumbcomponent.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet 6 | } from 'react-native' 7 | 8 | // Local components 9 | import { Color } from './../../global' 10 | 11 | /** 12 | * Card Component 13 | * 14 | * @version 1.0.0 15 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 16 | */ 17 | 18 | class Card extends React.Component { 19 | render(){ 20 | return( 21 | Jobs 22 | ) 23 | } 24 | } 25 | 26 | const styles = StyleSheet.create({ 27 | container : { 28 | paddingHorizontal: 15 29 | } 30 | }) 31 | export default Card -------------------------------------------------------------------------------- /src/components/ItemContainer/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet 6 | } from 'react-native' 7 | 8 | // Local components 9 | import Item from './../Item' 10 | // Config 11 | import { Color } from './../../global' 12 | 13 | /** 14 | * ItemContainer Component 15 | * 16 | * @version 1.0.0 17 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 18 | */ 19 | 20 | class ItemContainer extends React.Component { 21 | render(){ 22 | return( 23 | { this.props.children } 24 | ) 25 | } 26 | } 27 | 28 | const styles = StyleSheet.create({ 29 | container : { 30 | marginBottom: 20 31 | } 32 | }) 33 | export default ItemContainer -------------------------------------------------------------------------------- /src/global.js: -------------------------------------------------------------------------------- 1 | import { Dimensions, Platform, PixelRatio } from 'react-native'; 2 | 3 | export const Color = { 4 | primary: "#02245D", 5 | color2: "#101010", 6 | color3: "#E8ECEF", 7 | color4: "#A4A4A4", 8 | color5: "#EEEEEE", 9 | color6: "#3D3D3D", 10 | color7: "#315FAD", 11 | color8: "#FF9900" 12 | } 13 | 14 | 15 | 16 | const { 17 | width: SCREEN_WIDTH, 18 | height: SCREEN_HEIGHT, 19 | } = Dimensions.get('window'); 20 | // based on iphone 5s's scale 21 | const scale = SCREEN_WIDTH / 320; 22 | 23 | export function normalize(size) { 24 | const newSize = size * scale 25 | if (Platform.OS === 'ios') { 26 | return Math.round(PixelRatio.roundToNearestPixel(newSize)) 27 | } else { 28 | return Math.round(PixelRatio.roundToNearestPixel(newSize)) - 2 29 | } 30 | } -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "Start A Job", 4 | "slug": "start-a-job", 5 | "privacy": "public", 6 | "sdkVersion": "36.0.0", 7 | "platforms": [ 8 | "ios", 9 | "android", 10 | "web" 11 | ], 12 | "android": { 13 | "package": "com.startajob" 14 | }, 15 | "version": "1.0.1", 16 | "orientation": "portrait", 17 | "icon": "./assets/icon.png", 18 | "splash": { 19 | "image": "./assets/splash.png", 20 | "resizeMode": "contain", 21 | "backgroundColor": "#ffffff" 22 | }, 23 | "updates": { 24 | "fallbackToCacheTimeout": 0 25 | }, 26 | "assetBundlePatterns": [ 27 | "**/*" 28 | ], 29 | "ios": { 30 | "supportsTablet": true, 31 | "bundleIdentifier": "com.startajob" 32 | }, 33 | "description": "" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/modules/account/reducers.js: -------------------------------------------------------------------------------- 1 | import types from './types'; 2 | 3 | const initialState = { 4 | logged: false, 5 | user: { 6 | email: '', 7 | password: '', 8 | } 9 | }; 10 | 11 | export default function accountReducer(state = initialState, action) { 12 | switch (action.type) { 13 | case types.SET_USER: 14 | return { 15 | ...state, 16 | logged: true, 17 | user: action.payload, 18 | }; 19 | case types.SIGN_IN: 20 | return { 21 | ...state, 22 | logged: true, 23 | user: action.payload, 24 | }; 25 | case types.SIGN_OUT: 26 | return { 27 | ...state, 28 | logged: false, 29 | user: initialState, 30 | } 31 | default: 32 | return state; 33 | } 34 | } -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react'; 2 | import { StyleSheet, StatusBar } from 'react-native'; 3 | import AppNavigation from './src/router' 4 | 5 | import { Provider } from 'react-redux'; 6 | import { PersistGate } from 'redux-persist/integration/react'; 7 | import { store, persistor } from './src/store'; 8 | 9 | export default function App() { 10 | return ( 11 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | } 24 | 25 | const styles = StyleSheet.create({ 26 | container: { 27 | flex: 1, 28 | backgroundColor: '#fff', 29 | alignItems: 'center', 30 | justifyContent: 'center', 31 | }, 32 | }); 33 | -------------------------------------------------------------------------------- /src/utils/Functions.js: -------------------------------------------------------------------------------- 1 | export const verifyEmail = (value) => { 2 | var emailRex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 3 | if (emailRex.test(value)) { 4 | return true; 5 | } 6 | return false; 7 | } 8 | 9 | export const verifyPhone = (value) => { 10 | var phoneRex = /^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im; 11 | if (phoneRex.test(value)) { 12 | return true; 13 | } 14 | return false; 15 | } 16 | 17 | export const verifyAlias = (value) => { 18 | var aliasRex = /^[a-zA-Z0-9_]{5,}[a-zA-Z]+[0-9]*$/; 19 | if (aliasRex.test(value)) { 20 | return true; 21 | } 22 | return false; 23 | } 24 | 25 | export const verifyLength = (value, length) => { 26 | if (value.length >= length) { 27 | return true; 28 | } 29 | return false; 30 | } -------------------------------------------------------------------------------- /src/store.js: -------------------------------------------------------------------------------- 1 | // import { AsyncStorage } from '@react-native-community/async-storage'; 2 | import { AsyncStorage } from 'react-native'; 3 | import {createStore, combineReducers, applyMiddleware } from 'redux'; 4 | import { createLogger } from 'redux-logger'; 5 | import { persistStore, persistReducer } from 'redux-persist'; 6 | 7 | import accountReducer from '@modules/account/reducers'; 8 | 9 | const peresistConfig = { 10 | key: 'root', 11 | storage: AsyncStorage, 12 | whitelist: [ 13 | 'accountReducer', 14 | ], 15 | blacklist: [ 16 | ] 17 | } 18 | 19 | const rootReducer = combineReducers({ 20 | account: accountReducer, 21 | }); 22 | 23 | const persistedReducer = persistReducer(peresistConfig, rootReducer); 24 | 25 | const store = createStore( 26 | persistedReducer, 27 | applyMiddleware( 28 | createLogger(), 29 | ) 30 | ) 31 | 32 | let persistor = persistStore(store); 33 | 34 | export { 35 | store, persistor, 36 | } -------------------------------------------------------------------------------- /assets/Union.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/screens/home/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { 3 | View, 4 | Text, 5 | Image 6 | } from 'react-native' 7 | 8 | // local component 9 | import CutomButton from './../../components/Button' 10 | import Background from './../../../assets/background.png' 11 | import Chat from './../../components/ChatComponents/Chat' 12 | class Home extends Component { 13 | render(){ 14 | return( 15 | 16 | This is a test based on your requirement. 17 | 18 | { 20 | this.props.navigation.navigate('PageStack') 21 | }} 22 | backgroundColor= "#28A745" 23 | title={'Start Test'}/> 24 | 25 | 26 | 27 | 28 | 29 | ) 30 | } 31 | } 32 | 33 | export default Home -------------------------------------------------------------------------------- /src/components/ChatComponents/label/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Platform 7 | } from 'react-native' 8 | 9 | // Local components 10 | import { Color, normalize } from './../../../global' 11 | 12 | /** 13 | * Label Component 14 | * 15 | * @version 1.0.0 16 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 17 | */ 18 | 19 | class Label extends React.Component { 20 | render(){ 21 | return( 22 | 28 | { this.props.text } 29 | 30 | ) 31 | } 32 | } 33 | 34 | Label.defaultProps = { 35 | text:'' 36 | } 37 | const styles = StyleSheet.create({ 38 | container : { 39 | paddingHorizontal: 15 40 | }, 41 | shadow : Platform.os === "ios" ? { 42 | shadowColor: "#000", 43 | shadowOffset: { 44 | width: 0, 45 | height: 2, 46 | }, 47 | shadowOpacity: 0.25, 48 | shadowRadius: 3.84, 49 | } : { 50 | elevation: 5 51 | }, 52 | }) 53 | export default Label -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "node_modules/expo/AppEntry.js", 3 | "scripts": { 4 | "start": "expo start", 5 | "android": "expo start --android", 6 | "ios": "expo start --ios", 7 | "web": "expo start --web", 8 | "eject": "expo eject" 9 | }, 10 | "dependencies": { 11 | "expo": "~36.0.0", 12 | "expo-device": "~2.0.0", 13 | "expo-sqlite": "~8.0.0", 14 | "react": "~16.9.0", 15 | "react-dom": "~16.9.0", 16 | "react-native": "https://github.com/expo/react-native/archive/sdk-36.0.0.tar.gz", 17 | "react-native-autolink": "^1.9.1", 18 | "react-native-gesture-handler": "~1.5.0", 19 | "react-native-material-menu": "^1.0.0", 20 | "react-native-reanimated": "~1.4.0", 21 | "react-native-sqlite-storage": "^4.1.0", 22 | "react-native-status-bar-height": "^2.4.0", 23 | "react-native-svg": "9.13.3", 24 | "react-native-threads": "0.0.17", 25 | "react-native-web": "~0.11.7", 26 | "react-native-workers": "^0.3.1", 27 | "react-native-xml2js": "^1.0.3", 28 | "react-navigation": "^4.0.10", 29 | "react-navigation-stack": "^1.10.3", 30 | "react-navigation-tabs": "^2.6.2", 31 | "react-redux": "^7.1.3", 32 | "redux": "^4.0.5", 33 | "redux-logger": "^3.0.6", 34 | "redux-persist": "^6.0.0", 35 | "soap-everywhere": "^1.0.7" 36 | }, 37 | "devDependencies": { 38 | "babel-preset-expo": "~8.0.0" 39 | }, 40 | "private": true 41 | } 42 | -------------------------------------------------------------------------------- /src/components/Button/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { 3 | View, 4 | Text, 5 | Button, 6 | TouchableOpacity, 7 | Platform, 8 | Image 9 | } from 'react-native' 10 | 11 | class CutomButton extends Component { 12 | render(){ 13 | return( 14 | 33 | 34 | {this.props.logo && } 35 | {this.props.title} 36 | 37 | ) 38 | } 39 | } 40 | 41 | CutomButton.defaultProps = { 42 | title: 'No name' 43 | } 44 | export default CutomButton 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/components/Item/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Image, 7 | TouchableOpacity, 8 | TouchableNativeFeedback 9 | } from 'react-native' 10 | 11 | // Local components 12 | 13 | // Config 14 | import { Color } from './../../global' 15 | 16 | // Icon 17 | import RightArrow from './../../../assets/right-arrow.png' 18 | 19 | /** 20 | * Item Component 21 | * 22 | * @version 1.0.0 23 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 24 | */ 25 | 26 | class Item extends React.Component { 27 | 28 | componentDidMount(){ 29 | if(Platform.OS === "android") 30 | TouchableNativeFeedback.Ripple() 31 | } 32 | 33 | render(){ 34 | let content = ( 35 | { this.props.icon && 36 | { this.props.icon } 37 | } 38 | 42 | { this.props.text } 43 | 44 | { !this.props.rightComponent && 45 | 51 | } 52 | { this.props.rightComponent && 53 | { this.props.rightComponent } 54 | } 55 | ) 56 | 57 | return ( 61 | { content } 62 | ) 63 | 64 | } 65 | } 66 | 67 | Item.defaultProps = { 68 | text: '', 69 | icon: null, 70 | rightComponent: null 71 | } 72 | const styles = StyleSheet.create({ 73 | container : { 74 | paddingHorizontal: 10, 75 | backgroundColor: 'white', 76 | height: 50, 77 | alignItems: 'center', 78 | flexDirection: 'row', 79 | marginBottom: 1 80 | } 81 | }) 82 | export default Item -------------------------------------------------------------------------------- /assets/chat-background.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/screens/jobs/WorkAreaNotSet.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | TouchableOpacity 7 | } from 'react-native' 8 | 9 | // Local components 10 | import Alert from './../../components/Alerts' 11 | import CutomButton from './../../components/Button' 12 | 13 | // Icons 14 | import NoWorkArea from './../../../assets/no-work-area-icon.png' 15 | 16 | // Config 17 | import { Color, normalize } from './../../global' 18 | /** 19 | * WorkAreaNotSet Component 20 | * 21 | * @version 1.0.0 22 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 23 | */ 24 | 25 | class WorkAreaNotSet extends React.Component { 26 | render(){ 27 | return( 34 | 39 | Please configure your work areas in order to see related jobs 45 | 46 | 52 | 63 | 64 | 65 | } 66 | />) 67 | } 68 | } 69 | 70 | WorkAreaNotSet.defaultProps = { 71 | onPressConfigure: null 72 | } 73 | 74 | const styles = StyleSheet.create({ 75 | container : { 76 | paddingHorizontal: 15 77 | } 78 | }) 79 | export default WorkAreaNotSet -------------------------------------------------------------------------------- /src/components/Alerts/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Image, 7 | Platform 8 | } from 'react-native' 9 | 10 | // Local components 11 | // Config 12 | import { Color, normalize } from './../../global' 13 | 14 | /** 15 | * Alert Component 16 | * 17 | * @version 1.0.0 18 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 19 | */ 20 | 21 | class Alert extends React.Component { 22 | render(){ 23 | return( 24 | 25 | 29 | { this.props.icon && 35 | 42 | } 43 | 44 | 47 | { this.props.title } 54 | 55 | 56 | 57 | 58 | { this.props.body } 59 | 60 | ) 61 | } 62 | } 63 | 64 | Alert.defaultProps = { 65 | icon: null, 66 | body : null, 67 | title: 'No open jobs found' 68 | } 69 | const styles = StyleSheet.create({ 70 | container : { 71 | paddingHorizontal: 15, 72 | paddingVertical: 10, 73 | backgroundColor: 'white', 74 | margin: 10, 75 | borderRadius: 2 76 | }, 77 | shadow : Platform.os === "ios" ? { 78 | shadowColor: "#000", 79 | shadowOffset: { 80 | width: 0, 81 | height: 2, 82 | }, 83 | shadowOpacity: 0.20, 84 | shadowRadius: 1.41, 85 | } : { 86 | elevation: 2 87 | } 88 | }) 89 | export default Alert -------------------------------------------------------------------------------- /src/screens/jobs/NoOpenJobAlert.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet 6 | } from 'react-native' 7 | 8 | // Local components 9 | import Alert from './../../components/Alerts' 10 | import NoJobIcon from './../../../assets/no-jobs-icon.png' 11 | 12 | // Config 13 | import { Color, normalize } from './../../global' 14 | 15 | /** 16 | * NoOpenJobAlert Component 17 | * 18 | * @version 1.0.0 19 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 20 | */ 21 | 22 | class NoOpenJobAlert extends React.Component { 23 | render(){ 24 | return( 31 | 36 | Check us out later - we have new jobs every day! 42 | 43 | 48 | 53 | 54 | Pro tips: Try refining your search keywords, adjusting your existing   60 | work areas or add new ones 67 | 68 | 69 | 70 | } 71 | />) 72 | } 73 | } 74 | 75 | const styles = StyleSheet.create({ 76 | container : { 77 | paddingHorizontal: 15 78 | } 79 | }) 80 | export default NoOpenJobAlert -------------------------------------------------------------------------------- /src/components/Card/cardfooter.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Image 7 | } from 'react-native' 8 | 9 | // Local components 10 | import { Color, normalize } from './../../global' 11 | 12 | // Icons 13 | import Home from './../../../assets/home-icon.png' 14 | import FullTime from './../../../assets/fulltime-job-icon.png' 15 | import OneTime from './../../../assets/one-time-job-icon.png' 16 | 17 | /** 18 | * CardFooter Component 19 | * 20 | * @version 1.0.0 21 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 22 | */ 23 | 24 | class CardFooter extends React.Component { 25 | 26 | render() { 27 | let jobTypeIcon 28 | if (this.props.jobType === 2) { 29 | jobTypeIcon = FullTime 30 | } 31 | else if (this.props.jobType === 1) { 32 | jobTypeIcon = OneTime 33 | } 34 | else { 35 | jobTypeIcon = Home 36 | } 37 | return ( 38 | 39 | 46 | 47 | 54 | 61 | {this.props.category + " > "} 62 | 63 | 64 | {this.props.subCategories.map((item, key) => { 65 | return ( 66 | item.SkillName + ", " 67 | ) 68 | })} 69 | 70 | 71 | ) 72 | } 73 | } 74 | 75 | CardFooter.defaultProps = { 76 | category: 'No Category', 77 | subCategories: 'No Sub Categories', 78 | jobType: 'FULL_TIME' 79 | } 80 | 81 | const styles = StyleSheet.create({ 82 | container: { 83 | paddingHorizontal: 15, 84 | flexDirection: 'row', 85 | marginTop: 15, 86 | marginBottom: 15 87 | } 88 | }) 89 | export default CardFooter -------------------------------------------------------------------------------- /src/components/Search/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { 3 | View, 4 | Text, 5 | Button, 6 | TouchableOpacity, 7 | Platform, 8 | TextInput, 9 | Image 10 | } from 'react-native' 11 | import SearchIcon from './../../../assets/search.png' 12 | import BarCode from './../../../assets/barcode.png' 13 | 14 | // Config 15 | import { Color } from './../../global' 16 | class Search extends Component { 17 | render(){ 18 | return( 19 | 29 | 30 | 31 | 37 | { this.props.SearchIconrightButton && 38 | 47 | 48 | 49 | 50 | 51 | } 52 | 53 | ) 54 | } 55 | } 56 | 57 | Search.defaultProps = { 58 | title: 'No name', 59 | placeholder: '', 60 | rightButton: null, 61 | rightButtonIcon: null, 62 | rightButtonStyle: null 63 | } 64 | export default Search -------------------------------------------------------------------------------- /src/components/ChatComponents/ChatAlert/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Platform 7 | } from 'react-native' 8 | 9 | // Local components 10 | import { Color } from '../../../global' 11 | 12 | /** 13 | * ChatAlert Component 14 | * 15 | * @version 1.0.0 16 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 17 | */ 18 | 19 | class ChatAlert extends React.Component { 20 | 21 | 22 | render(){ 23 | return ( { 28 | if( this.props.type === "warn" ) 29 | return '#ECEACA' 30 | else if( this.props.type === "success" ) 31 | return '#EBFFE8' 32 | else if( this.props.type === "error" ) 33 | return '#ECC8CA' 34 | })() 35 | } 36 | ]}> 37 | 46 | 47 | { this.props.headerIcon } 48 | 49 | 50 | { this.props.title } 56 | 57 | 58 | 63 | { this.props.body } 64 | 65 | ) 66 | 67 | } 68 | } 69 | 70 | ChatAlert.defaultProps = { 71 | // This will take OFFER_APPROVAL, OFFER_ACCEPTED, OFFER_REJECTED 72 | headerIcon: null, 73 | title: '', 74 | body: null, 75 | type: 'warn' 76 | } 77 | 78 | const styles = StyleSheet.create({ 79 | container : { 80 | marginBottom: 5, 81 | borderRadius: 10, 82 | marginHorizontal: 10 83 | }, 84 | shadow : Platform.os === "ios" ? { 85 | shadowColor: "#000", 86 | shadowOffset: { 87 | width: 0, 88 | height: 2, 89 | }, 90 | shadowOpacity: 0.25, 91 | shadowRadius: 3.84, 92 | } : { 93 | elevation: 5 94 | } 95 | }) 96 | export default ChatAlert -------------------------------------------------------------------------------- /src/components/Input/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { 3 | View, 4 | Text, 5 | Button, 6 | TouchableOpacity, 7 | Platform, 8 | TextInput, 9 | Image 10 | } from 'react-native' 11 | import SearchIcon from './../../../assets/search.png' 12 | import BarCode from './../../../assets/barcode.png' 13 | 14 | // Config 15 | import { Color } from './../../global' 16 | class Input extends Component { 17 | render(){ 18 | return( 19 | 27 | 28 | { this.props.icon && 29 | 30 | } 31 | 39 | 50 | { this.props.rightButton && 51 | 60 | 61 | { this.props.rightButtonIcon && 62 | } 68 | 69 | 70 | } 71 | 72 | ) 73 | } 74 | } 75 | 76 | Input.defaultProps = { 77 | title: 'No name', 78 | icon: null, 79 | rightButton: null, 80 | rightButtonIcon: null, 81 | rightButtonStyle: null 82 | } 83 | export default Input -------------------------------------------------------------------------------- /src/components/BackgroundImage/index.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Image, 7 | Dimensions 8 | } from 'react-native' 9 | 10 | // Local components 11 | import { Color } from './../../global' 12 | 13 | // Images 14 | import BackgroundPattern from './../../../assets/background-pattern-gray.png' 15 | 16 | /** 17 | * BackgroundImage Component 18 | * 19 | * @version 1.0.0 20 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 21 | */ 22 | 23 | class BackgroundImage extends React.Component { 24 | row = (num) => { 25 | let content = [] 26 | let precent = this.props.precent || 0.20 27 | let Background = this.props.source || BackgroundPattern 28 | let opacity = this.props.opacity || 0.1 29 | 30 | let screenHeight = Dimensions.get('screen').height 31 | let imageWidth = Dimensions.get('screen').width - ( Dimensions.get('screen').width * precent ) 32 | let imageHeight = Dimensions.get('screen').width - ( Dimensions.get('screen').width * precent ) 33 | let numRows = Math.ceil((screenHeight/imageHeight)) 34 | console.log(numRows) 35 | for(let i = 0 ; i < numRows; i++ ){ 36 | content.push( 40 | 48 | 56 | ) 57 | } 58 | return content 59 | 60 | } 61 | render(){ 62 | return( 67 | 68 | {this.row(2)} 69 | 70 | ) 71 | } 72 | } 73 | 74 | const styles = StyleSheet.create({ 75 | container : { 76 | paddingHorizontal: 15 77 | } 78 | }) 79 | export default BackgroundImage -------------------------------------------------------------------------------- /src/components/Card/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | StyleSheet, 5 | TouchableNativeFeedback, 6 | Platform, 7 | TouchableOpacity 8 | } from 'react-native' 9 | 10 | // Local components 11 | import CardHeader from './cardheader' 12 | import CardBody from './cardbody' 13 | import CardFooter from './cardfooter' 14 | 15 | // Config 16 | import { Color } from './../../global' 17 | 18 | class Card extends React.Component { 19 | 20 | componentDidMount() { 21 | if (Platform.OS === "android") 22 | TouchableNativeFeedback.Ripple() 23 | } 24 | render() { 25 | let content = 29 | 41 | 48 | 53 | 54 | 55 | return ( 56 | 63 | {content} 64 | 65 | ) 66 | 67 | } 68 | } 69 | 70 | // Default Props 71 | Card.defaultProps = { 72 | jobState: null, 73 | jobTitle: '', 74 | userName: '', 75 | timestamp: '', 76 | isRead: null, 77 | jobType: null, 78 | bid: {}, 79 | address: 'No address', 80 | avatarUri: null, 81 | countryFlag: null, 82 | category: "No Category", 83 | subCategories: "No Sub Categories", 84 | description: '', 85 | newMessageCount: 0, 86 | timestampCustom: null, 87 | distance: '', 88 | context: 'JOBS', 89 | separater: true 90 | } 91 | 92 | const styles = StyleSheet.create({ 93 | container: { 94 | backgroundColor: "white" 95 | }, 96 | newJob: { 97 | margin: 5, 98 | borderRadius: 4, 99 | borderWidth: 2, 100 | borderColor: Color.color8, 101 | backgroundColor: "white" 102 | } 103 | }) 104 | export default Card -------------------------------------------------------------------------------- /src/components/ChatComponents/ChangeJobStatus/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | TouchableOpacity, 7 | Image 8 | } from 'react-native' 9 | 10 | // Local components 11 | import { Color } from '../../../global' 12 | 13 | // Icon 14 | import HandShakeWhite from './../../../../assets/hand-shake-white.png' 15 | import Tick from './../../../../assets/tick.png' 16 | 17 | /** 18 | * Overlay Component 19 | * 20 | * @version 1.0.0 21 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 22 | */ 23 | 24 | class Overlay extends React.Component { 25 | render(){ 26 | return( 33 | 43 | 44 | 48 | 54 | 55 | 56 | Mark job completed 63 | 64 | 65 | 66 | 75 | 76 | 80 | 86 | 87 | 88 | Change terms 95 | 96 | 97 | 98 | ) 99 | } 100 | } 101 | 102 | Overlay.defaultProps = { 103 | onPressMarkJobCompleted: null, 104 | onPressChangeTerms: null 105 | } 106 | const styles = StyleSheet.create({ 107 | container : { 108 | paddingHorizontal: 15 109 | } 110 | }) 111 | export default Overlay -------------------------------------------------------------------------------- /src/router.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { createAppContainer, createSwitchNavigator } from 'react-navigation'; 3 | import { createStackNavigator } from 'react-navigation-stack'; 4 | import { createBottomTabNavigator } from 'react-navigation-tabs'; 5 | import { 6 | View, 7 | Text, 8 | Image 9 | } from 'react-native' 10 | 11 | // Screen Component 12 | import Home from './screens/home' 13 | import Page from './screens/page' 14 | import ChatScreen from './screens/chatscreen' 15 | import Login from './screens/login' 16 | import Jobs from './screens/jobs' 17 | import Menu from './screens/menu' 18 | import MyJobs from './screens/myjobs' 19 | 20 | // Icons 21 | import HomeIconBlue from './../assets/home-icon-blue.png' 22 | import HomeIconWhite from './../assets/home-icon-white.png' 23 | import HomeIconGray from './../assets/home-icon-gray.png' 24 | import BagIconBlue from './../assets/bag-icon-blue.png' 25 | import BagIconWhite from './../assets/bag-icon-white.png' 26 | import BagIconGray from './../assets/bag-icon-gray.png' 27 | import MenuIconBlue from './../assets/menu-icon-blue.png' 28 | import MenuIconWhite from './../assets/menu-icon-white.png' 29 | import MenuIconGray from './../assets/menu-icon-gray.png' 30 | 31 | 32 | // Config 33 | import { Color } from './global' 34 | 35 | 36 | // Tab Navigation 37 | const TabNavigator = createBottomTabNavigator( { 38 | Jobs, 39 | MyJobs: { 40 | screen: MyJobs 41 | }, 42 | Menu 43 | 44 | } ,{ 45 | defaultNavigationOptions: ({ navigation }) => ({ 46 | tabBarIcon: ({ focused, horizontal, tintColor }) => { 47 | const { routeName } = navigation.state; 48 | let icon 49 | if (routeName === 'Jobs') { 50 | if( focused ) 51 | icon= 52 | else icon = 53 | } 54 | else if( routeName === 'MyJobs') { 55 | 56 | if( focused ) 57 | icon= 58 | else icon = 59 | 60 | } 61 | else if( routeName === 'Menu') { 62 | 63 | if( focused ) 64 | icon= 65 | else icon = 66 | 67 | } 68 | 69 | // You can return any component that you like here! 70 | return 71 | { icon } 72 | ; 73 | }, 74 | tabBarLabel: ({ focused, horizontal, tintColor }) => { 75 | const { routeName } = navigation.state; 76 | let labelName = null 77 | if (routeName === 'Jobs') { 78 | labelName = "Jobs nearby" 79 | } 80 | else if( routeName === 'MyJobs') { 81 | labelName = "My jobs" 82 | } 83 | else if( routeName === 'Menu') { 84 | labelName = "Menu" 85 | } 86 | // You can return any component that you like here! 87 | return 88 | {labelName} 89 | 90 | }, 91 | }), 92 | tabBarOptions: { 93 | activeTintColor: Color.primary, 94 | style: { 95 | paddingBottom: 4, 96 | backgroundColor: Color.primary 97 | } 98 | }, 99 | } 100 | ); 101 | 102 | const screenStack = createStackNavigator({ 103 | TabNavigator, 104 | ChatScreen 105 | },{ 106 | defaultNavigationOptions: ({ navigation }) => ({ 107 | 108 | header : null 109 | }) 110 | }) 111 | 112 | let AppNavigation = createSwitchNavigator({ 113 | Home: { 114 | screen: Home 115 | }, 116 | Screen: { 117 | screen: screenStack 118 | }, 119 | Login: { 120 | screen: Login 121 | } 122 | },{ 123 | initialRouteName: 'Login' 124 | }) 125 | 126 | export default createAppContainer(AppNavigation) -------------------------------------------------------------------------------- /src/components/ChatComponents/ChatInput/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | TextInput, 7 | Image, 8 | TouchableOpacity, 9 | KeyboardAvoidingView 10 | } from 'react-native' 11 | import PropTypes from 'prop-types' 12 | // Local components 13 | import Input from './../../Input' 14 | import ChangeJobStatus from './../ChangeJobStatus' 15 | 16 | // Icon 17 | import BagIconBlue from './../../../../assets/bag-icon-blue.png' 18 | import BagIconBlueOutline from './../../../../assets/bag-icon-blue-outline.png' 19 | import Clip from './../../../../assets/clip.png' 20 | import Camera from './../../../../assets/camera-icon.png' 21 | 22 | 23 | // Config 24 | import { Color } from './../../../global' 25 | import { Platform } from '@unimodules/core'; 26 | 27 | /** 28 | * ChatInput Component 29 | * 30 | * @version 1.0.0 31 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 32 | */ 33 | 34 | class ChatInput extends React.Component { 35 | state = { 36 | overlay: false 37 | } 38 | 39 | render(){ 40 | return( 41 | 42 | { this.state.overlay && } 46 | 56 | { 58 | this.setState({ overlay: !this.state.overlay }) 59 | }} 60 | style={{ 61 | padding: 5 62 | }} 63 | > 64 | 70 | 71 | 80 | 90 | 91 | 97 | 103 | 104 | 110 | 116 | 117 | 118 | ) 119 | } 120 | } 121 | 122 | /** Default Props */ 123 | ChatInput.defaultProps = { 124 | onChangeChatInput: null, 125 | onPressChangeTerms: null, 126 | onPressMarkJobCompleted: null, 127 | onPressCamera: null, 128 | value: '', 129 | onPressAttachment: null 130 | } 131 | 132 | /** Prop Type */ 133 | ChatInput.propTypes = { 134 | /** Description of prop "baz". */ 135 | value: PropTypes.string, 136 | /** 137 | * Gets called when the user starts typing 138 | * @param {SyntheticEvent} event The react `SyntheticEvent` 139 | */ 140 | onChangeChatInput: PropTypes.func, 141 | /** Called when changed terms button is pressed */ 142 | onPressChangeTerms: PropTypes.func, 143 | /** Called when Mark Job Done button is pressed */ 144 | onPressMarkJobCompleted: PropTypes.func, 145 | /** Called when camera button is pressed */ 146 | onPressCamera: PropTypes.func, 147 | /** Called when attachment button is pressed */ 148 | onPressAttachment: PropTypes.func 149 | } 150 | 151 | const styles = StyleSheet.create({ 152 | container : { 153 | } 154 | }) 155 | export default ChatInput -------------------------------------------------------------------------------- /src/components/ChatComponents/Chat/priceask.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Image, 7 | Dimensions 8 | } from 'react-native' 9 | 10 | // Local components 11 | import Input from './../../Input' 12 | 13 | // Icons 14 | import MoneyBag from './../../../../assets/money-bag.png' 15 | import Tick from './../../../../assets/tick.png' 16 | import BlueDoubleTick from './../../../../assets/blue-double-tick.png' 17 | import DoubleTick from './../../../../assets/double-tick.png' 18 | 19 | // Config 20 | import { Color, normalize } from './../../../global' 21 | 22 | /** 23 | * PriceAsk Component 24 | * 25 | * @version 1.0.0 26 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 27 | */ 28 | 29 | class PriceAsk extends React.Component { 30 | render(){ 31 | return( 41 | 46 | How much are you asking for the job? 52 | 60 | 65 | 73 | 74 | 79 | 101 | 102 | 103 | 104 | 105 | 106 | { this.props.timestamp } 107 | {this.props.isRead === false || this.props.isRead === true ? 108 | 115 | : null } 116 | 117 | 118 | 119 | 120 | ) 121 | } 122 | } 123 | 124 | PriceAsk.defaultProps = { 125 | tail: true, 126 | onChangePrice: null, 127 | onPressDone: null, 128 | isRead: null, 129 | timestamp: '' 130 | 131 | } 132 | const styles = StyleSheet.create({ 133 | container : { 134 | paddingHorizontal: 15 135 | }, 136 | messageContainer: { 137 | padding: 5, 138 | marginVertical: 5, 139 | width: Dimensions.get('window').width-50, 140 | }, 141 | outgoing: { 142 | borderTopLeftRadius: 10, 143 | borderTopRightRadius: 10, 144 | borderBottomLeftRadius: 10, 145 | backgroundColor: '#D5FFCE' 146 | }, 147 | incoming: { 148 | borderTopLeftRadius: 10, 149 | borderTopRightRadius: 10, 150 | borderBottomRightRadius: 10, 151 | backgroundColor: 'white' 152 | }, 153 | chatboxFooterTimeStamp : { 154 | fontSize: 12, 155 | flexDirection: 'row' 156 | } 157 | }) 158 | export default PriceAsk 159 | 160 | 161 | -------------------------------------------------------------------------------- /src/screens/menu/userinfo.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Platform, 7 | Image, 8 | TouchableNativeFeedback, 9 | TouchableOpacity 10 | } from 'react-native' 11 | 12 | // Local components 13 | import { Color } from '../../global' 14 | 15 | // Icon 16 | import Avatar from './../../../assets/avatar.png' 17 | import RightArrow from './../../../assets/right-arrow.png' 18 | import TrustWhite from './../../../assets/trust-white.png' 19 | import Trust from './../../../assets/trust-icon.png' 20 | 21 | 22 | 23 | /** 24 | * UserInfo Component 25 | * 26 | * @version 1.0.0 27 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 28 | */ 29 | 30 | class UserInfo extends React.Component { 31 | 32 | componentDidMount(){ 33 | if(Platform.OS === "android") 34 | TouchableNativeFeedback.Ripple() 35 | } 36 | 37 | render(){ 38 | return ( 44 | 59 | 65 | 66 | 74 | 75 | {/* Seperatpr */} 76 | 81 | 82 | 86 | 92 | { this.props.name } 98 | { this.props.isVarified && } 105 | 106 | 109 | My balance: 115 | ${ this.props.balance } 123 | 124 | 125 | 129 | 135 | 136 | 137 | { !this.props.isVarified && 147 | 152 | 158 | 164 | 165 | 166 | Verify account 173 | 174 | 175 | } 176 | ) 177 | } 178 | } 179 | 180 | UserInfo.defaultProps = { 181 | name: '', 182 | balance: 0, 183 | isVarified: false, 184 | avatar: null 185 | } 186 | const styles = StyleSheet.create({ 187 | container : { 188 | paddingHorizontal: 10 189 | }, 190 | shadow : Platform.os === "ios" ? { 191 | shadowColor: "#000", 192 | shadowOffset: { 193 | width: 0, 194 | height: 2, 195 | }, 196 | shadowOpacity: 0.25, 197 | shadowRadius: 3.84, 198 | } : { 199 | elevation: 5 200 | } 201 | }) 202 | export default UserInfo -------------------------------------------------------------------------------- /src/screens/page/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { 3 | View, 4 | Text, 5 | Button, 6 | ScrollView, 7 | TouchableOpacity, 8 | Image 9 | } from 'react-native' 10 | import CutomButton from './../../components/Button' 11 | import Search from './../../components/Search' 12 | import ItemContainer from './../../components/ItemContainer' 13 | import BagLogo from './../../../assets/baglogo.png' 14 | import IonMenu from './../../../assets/ion-menu.png' 15 | import Avatar from './../../../assets/avatar.png' 16 | import DownArrow from './../../../assets/arrow-down.png' 17 | import Background from './../../../assets/background.png' 18 | import Chat from './../../components/ChatComponents/Chat' 19 | 20 | 21 | 22 | 23 | const items = [ 24 | { 25 | name:"Kendall Jackson Vintner's Reserve Chardonnay", 26 | discount: null, 27 | quantity: 1, 28 | amount: '349.38', 29 | url: null 30 | }, 31 | { 32 | name:"Kendall Jackson Vintner's Reserve Chardonnay Luxury Wine", 33 | discount: null, 34 | quantity: 2, 35 | amount: '2035.67', 36 | url: null 37 | }, 38 | { 39 | name:"Kendall Chardonnay", 40 | discount: null, 41 | quantity: 1, 42 | amount: '349.38', 43 | url: null 44 | }, 45 | { 46 | name:"Kendall Jackson Vintner's Reserve Chardonnay ", 47 | discount: null, 48 | quantity: 1, 49 | amount: '5349.38', 50 | url: null 51 | }, 52 | { 53 | name:"Jackson Luxury Wine", 54 | discount: 10, 55 | quantity: 2, 56 | amount: '439.98', 57 | url: null 58 | } 59 | ] 60 | class Page extends Component { 61 | static navigationOptions = { 62 | headerRight: () => 70 | 71 | 72 | 73 | , 74 | headerLeft: () => 82 | 83 | 84 | 85 | , 86 | headerTitle: () => ( 87 | 88 | alert('This is button')} style={{ flexDirection: 'row', alignItems: 'center' }}> 89 | 90 | Johnissimus Van-Doe 91 | 92 | 93 | 94 | ), 95 | 96 | }; 97 | render(){ 98 | return( 99 | 100 | {/* Buttons Container */} 101 | 102 | { 104 | this.props.navigation.navigate('PageStack') 105 | }} 106 | logo={BagLogo} 107 | backgroundColor= "#28A745" 108 | title={'Club Member'}/> 109 | 110 | 111 | {/* List Container */} 112 | 113 | 114 | 115 | 116 | 117 | 118 | {/* Checkout Container */} 119 | 120 | 121 | { 128 | this.props.navigation.navigate('PageStack') 129 | }} 130 | title={'New Order'}/> 131 | { 140 | this.props.navigation.navigate('PageStack') 141 | }} 142 | title={'Cancel Order'}/> 143 | 144 | 145 | { 151 | this.props.navigation.navigate('PageStack') 152 | }} 153 | backgroundColor= "#002A5C" 154 | title={'Checkout'}/> 155 | 156 | 157 | 158 | ) 159 | } 160 | } 161 | 162 | export default Page -------------------------------------------------------------------------------- /src/components/ChatComponents/Chat/termschanged.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Image, 7 | Dimensions, 8 | Platform, 9 | TouchableOpacity 10 | } from 'react-native' 11 | 12 | // Local components 13 | import Input from './../../Input' 14 | 15 | // Icons 16 | import MoneyBag from './../../../../assets/money-bag.png' 17 | import Tick from './../../../../assets/tick.png' 18 | import ClockGreen from './../../../../assets/clock-green.png' 19 | 20 | // Config 21 | import { Color } from './../../../global' 22 | 23 | /** 24 | * TermsChanged Component 25 | * 26 | * @version 1.0.0 27 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 28 | */ 29 | 30 | class TermsChanged extends React.Component { 31 | render(){ 32 | return( 42 | 47 | 48 | 53 | The employer changed terms to ${ this.props.newPrice } in { this.props.newDuration } day{this.props.newDuration > 1 && 's'}. 58 | 59 | 64 | Do you accept? 70 | 71 | 72 | 77 | 83 | 92 | 93 | 97 | 103 | 104 | 105 | Yes 112 | 113 | 114 | 115 | 116 | 120 | 129 | 130 | 131 | No 137 | 138 | 139 | 140 | 141 | 142 | 143 | ) 144 | } 145 | } 146 | 147 | TermsChanged.defaultProps = { 148 | tail: true, 149 | newPrice: 0, 150 | newDuration: 0 151 | } 152 | const styles = StyleSheet.create({ 153 | container : { 154 | paddingHorizontal: 15 155 | }, 156 | messageContainer: { 157 | padding: 5, 158 | marginVertical: 5, 159 | width: Dimensions.get('window').width-50, 160 | }, 161 | outgoing: { 162 | borderTopLeftRadius: 10, 163 | borderTopRightRadius: 10, 164 | borderBottomLeftRadius: 10, 165 | backgroundColor: '#D5FFCE' 166 | }, 167 | incoming: { 168 | borderTopLeftRadius: 10, 169 | borderTopRightRadius: 10, 170 | borderBottomRightRadius: 10, 171 | backgroundColor: 'white' 172 | }, 173 | shadow : Platform.os === "ios" ? { 174 | shadowColor: "#000", 175 | shadowOffset: { 176 | width: 0, 177 | height: 2, 178 | }, 179 | shadowOpacity: 0.25, 180 | shadowRadius: 3.84, 181 | } : { 182 | elevation: 5 183 | }, 184 | }) 185 | export default TermsChanged 186 | 187 | 188 | -------------------------------------------------------------------------------- /src/components/ChatComponents/Chat/daysask.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Image, 7 | Dimensions, 8 | Platform, 9 | TouchableOpacity 10 | } from 'react-native' 11 | 12 | // Local components 13 | import Input from './../../Input' 14 | 15 | // Icons 16 | import MoneyBag from './../../../../assets/money-bag.png' 17 | import Tick from './../../../../assets/tick.png' 18 | import ClockGreen from './../../../../assets/clock-green.png' 19 | import BlueDoubleTick from './../../../../assets/blue-double-tick.png' 20 | import DoubleTick from './../../../../assets/double-tick.png' 21 | 22 | // Config 23 | import { Color, normalize} from './../../../global' 24 | 25 | /** 26 | * DaysAsk Component 27 | * 28 | * @version 1.0.0 29 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 30 | */ 31 | 32 | class DaysAsk extends React.Component { 33 | render(){ 34 | return( 44 | 49 | How much are you asking for the job? 55 | 62 | 67 | 75 | 76 | 81 | 96 | 97 | 103 | days 109 | 110 | 114 | 123 | 124 | 125 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | { this.props.timestamp } 139 | {this.props.isRead === false || this.props.isRead === true ? 140 | 147 | : null } 148 | 149 | 150 | 151 | 152 | ) 153 | } 154 | } 155 | 156 | DaysAsk.defaultProps = { 157 | tail: true, 158 | onChangePrice: null, 159 | onPressDone: null, 160 | isRead: null, 161 | timestamp: '' 162 | } 163 | const styles = StyleSheet.create({ 164 | container : { 165 | paddingHorizontal: 15 166 | }, 167 | messageContainer: { 168 | padding: 5, 169 | marginVertical: 5, 170 | width: Dimensions.get('window').width-50, 171 | }, 172 | outgoing: { 173 | borderTopLeftRadius: 10, 174 | borderTopRightRadius: 10, 175 | borderBottomLeftRadius: 10, 176 | backgroundColor: '#D5FFCE' 177 | }, 178 | incoming: { 179 | borderTopLeftRadius: 10, 180 | borderTopRightRadius: 10, 181 | borderBottomRightRadius: 10, 182 | backgroundColor: 'white' 183 | }, 184 | shadow : Platform.os === "ios" ? { 185 | shadowColor: "#000", 186 | shadowOffset: { 187 | width: 0, 188 | height: 2, 189 | }, 190 | shadowOpacity: 0.25, 191 | shadowRadius: 3.84, 192 | } : { 193 | elevation: 5 194 | }, 195 | chatboxFooterTimeStamp : { 196 | fontSize: 12, 197 | flexDirection: 'row' 198 | } 199 | }) 200 | export default DaysAsk 201 | 202 | 203 | -------------------------------------------------------------------------------- /src/screens/myjobs/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Image, 7 | Animated 8 | } from 'react-native' 9 | import Menu, { MenuItem, MenuDivider } from 'react-native-material-menu'; 10 | import { getStatusBarHeight } from 'react-native-status-bar-height'; 11 | 12 | // Local components 13 | import Header from './../../components/Header' 14 | import Card from './../../components/Card' 15 | import Search from './../../components/Search' 16 | 17 | // Icon 18 | import ThreeVerticalDots from './../../../assets/three-vertical-dots.png' 19 | // Config 20 | import { Color, normalize } from '../../global' 21 | import { TouchableOpacity } from 'react-native-gesture-handler' 22 | 23 | /** 24 | * Login Component 25 | * 26 | * @version 1.0.0 27 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 28 | */ 29 | class MyJobs extends React.Component { 30 | _menu = null; 31 | 32 | constructor(props) { 33 | super(props) 34 | 35 | const scrollAnim = new Animated.Value(0) 36 | const offsetAnim = new Animated.Value(0) 37 | 38 | this.state = { 39 | scrollAnim, 40 | offsetAnim, 41 | clampedScroll: Animated.diffClamp( 42 | Animated.add( 43 | scrollAnim.interpolate({ 44 | inputRange: [ 0, 1 ], 45 | outputRange: [ 0, 1 ], 46 | extrapolateLeft: 'clamp' 47 | }), 48 | offsetAnim 49 | ), 50 | 0, 51 | 112 52 | ) 53 | }; 54 | } 55 | 56 | setMenuRef = ref => { 57 | this._menu = ref; 58 | }; 59 | 60 | hideMenu = () => { 61 | this._menu.hide(); 62 | }; 63 | 64 | showMenu = () => { 65 | this._menu.show(); 66 | }; 67 | 68 | render(){ 69 | 70 | return( 71 |
} 78 | mainText = "My jobs" 79 | contextMenu={ 80 | [ 81 | { 82 | text: 'Job archive', 83 | onPress: () =>{ 84 | alert('Button') 85 | } 86 | }, 87 | { 88 | text: 'Log out', 89 | onPress: () =>{ 90 | alert('Button') 91 | } 92 | } 93 | ] 94 | } 95 | /> 96 | 116 | { 118 | alert('Job Card') 119 | }} 120 | jobState="JOB_IN_PROGRESS" 121 | bid = {{ 122 | acceptedPrice: 1000, 123 | proposedPrice: 1000, 124 | days: 10 125 | }} 126 | description="Hello John! I have done a couple of similar project on" 127 | jobTitle="Build website on WordPress using PHP" 128 | userName="John Doe" 129 | distance = '0.5 Km' 130 | isRead= { false } 131 | timestampCustom = {Hired 21 days} 132 | jobType= "ONE_TIME" 133 | context= "MY_JOBS" 134 | category= {'Web Design'} 135 | subCategories= "WordPress, HTML/CSS, CRM, JavaScript" 136 | /> 137 | { 139 | alert('Job Card') 140 | }} 141 | jobState="JOB_AWAIT_CONFIRMATION" 142 | bid = {{ 143 | acceptedPrice: 1000, 144 | proposedPrice: 1000, 145 | days: 10 146 | }} 147 | description="Hello John! I have done a couple of similar project on" 148 | jobTitle="Build website on WordPress using PHP" 149 | userName="John Doe" 150 | distance = '0.5 Km' 151 | isRead= { false } 152 | timestampCustom = {Hired 21 hrs 50 m} 153 | jobType= "ONE_TIME" 154 | context= "MY_JOBS" 155 | category= {'Web Design'} 156 | subCategories= "WordPress, HTML/CSS, CRM, JavaScript" 157 | /> 158 | { 160 | alert('Job Card') 161 | }} 162 | jobState="BID_REJECTED" 163 | bid = {{ 164 | acceptedPrice: 1000, 165 | proposedPrice: 1000, 166 | days: 0 167 | }} 168 | onPress={()=>{ 169 | this.props.navigation.navigate('ChatScreen',{ 170 | jobState: "BID_REJECTED", 171 | varified: true, 172 | oIcon: true 173 | }) 174 | }} 175 | description="Hello John! I have done a couple of similar project on" 176 | jobTitle="Build website on WordPress using PHP" 177 | userName="John Doe" 178 | distance = '0.5 Km' 179 | isRead= { false } 180 | timestamp='2 min' 181 | jobType= "ONE_TIME" 182 | context= "MY_JOBS" 183 | category= {'Web Design'} 184 | subCategories= "WordPress, HTML/CSS, CRM, JavaScript" 185 | /> 186 | 187 | ) 188 | } 189 | } 190 | 191 | const styles = StyleSheet.create({ 192 | container: { 193 | backgroundColor: '#fff', 194 | flex: 1 195 | }, 196 | searchContainer : { 197 | paddingHorizontal: 15, 198 | backgroundColor: '#FAFAFA', 199 | zIndex: 40 200 | 201 | }, 202 | shadow : Platform.OS === "ios" ? { 203 | shadowColor: "#000", 204 | shadowOffset: { 205 | width: 0, 206 | height: 2, 207 | }, 208 | shadowOpacity: 0.25, 209 | shadowRadius: 3.84, 210 | } : { 211 | elevation: 5 212 | } 213 | }) 214 | 215 | export default MyJobs -------------------------------------------------------------------------------- /src/components/Card/cardheader.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Image 7 | } from 'react-native' 8 | 9 | // Local components 10 | import { Color } from './../../global' 11 | 12 | // Icons 13 | import MapIcon from './../../../assets/map.png' 14 | import Avatar from './../../../assets/avatar.png' 15 | import RightArrow from './../../../assets/right-arrow.png' 16 | import NewMessage from './../../../assets/new-message-icon.png' 17 | import Flag from './../../../assets/flag.png' 18 | 19 | 20 | /** 21 | * CardHeader Component 22 | * 23 | * @version 1.0.0 24 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 25 | */ 26 | 27 | class CardHeader extends React.Component { 28 | render() { 29 | return ( 30 | 31 | {/* For avatar */} 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | {/* User details */} 41 | 42 | 43 | 44 | 52 | {this.props.userName} 53 | 54 | {!this.props.timestampCustom ? {this.props.timestamp} : this.props.timestampCustom} 55 | 56 | 57 | 58 | 59 | {this.props.jobTitle} 67 | 68 | 69 | 70 | 71 | {/* User's Address Container */} 72 | 73 | 74 | {/* Map logo */} 75 | 76 | 77 | 78 | {/* Distance */} 79 | {this.props.distance} 86 | 87 | 88 | {/* Address */} 89 | 90 | {this.props.address} 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | {this.props.jobState === "NEW_JOB" && 103 | 104 | } 105 | {this.props.jobState === "NEW_MESSAGE" && 106 | 116 | 9 ? 10 : 14 }}>{this.props.newMessageCount} 117 | 118 | } 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | ) 127 | } 128 | } 129 | 130 | // Default Props 131 | CardHeader.defaultProps = { 132 | jobState: null, 133 | userName: 'No name', 134 | jobTitle: 'No job title', 135 | distance: '', 136 | avatarUri: null, 137 | countryFlag: null, 138 | address: 'No address', 139 | timestamp: '', 140 | timestampCustom: null, 141 | newMessageCount: 0, 142 | distance: '0 km' 143 | } 144 | 145 | const styles = StyleSheet.create({ 146 | container: { 147 | paddingHorizontal: 10, 148 | paddingVertical: 10, 149 | flexDirection: 'row', 150 | }, 151 | nameContainer: { 152 | justifyContent: 'space-between', 153 | flexDirection: 'row', 154 | }, 155 | addressContainer: { 156 | flexDirection: 'row', 157 | marginTop: 4 158 | }, 159 | avatarContainer: { 160 | 161 | } 162 | }) 163 | export default CardHeader -------------------------------------------------------------------------------- /src/components/Header/index.js: -------------------------------------------------------------------------------- 1 | import React,{ Fragment } from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Platform, 7 | Animated, 8 | TouchableOpacity, 9 | Image, 10 | Dimensions 11 | } from 'react-native' 12 | import { getStatusBarHeight } from 'react-native-status-bar-height'; 13 | import PropTypes from 'prop-types'; 14 | import Menu, { MenuItem, MenuDivider } from 'react-native-material-menu'; 15 | 16 | // Config 17 | import { Color } from './../../global' 18 | 19 | // Icon 20 | import ThreeVerticalDots from './../../../assets/three-vertical-dots.png' 21 | 22 | /** 23 | * Header Component 24 | * 25 | * @version 1.0.0 26 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 27 | */ 28 | class Header extends React.Component { 29 | _menu = null; 30 | state = { 31 | position: 0 32 | } 33 | 34 | setMenuRef = ref => { 35 | this._menu = ref; 36 | }; 37 | 38 | hideMenu = () => { 39 | this._menu.hide(); 40 | }; 41 | 42 | showMenu = () => { 43 | this._menu.show(); 44 | }; 45 | 46 | renderMenuItems = () => { 47 | return this.props.contextMenu.map(( item, index )=>{ 48 | return 49 | { 50 | this.hideMenu() 51 | item.onPress() 52 | }}>{ item.text } 53 | 54 | 55 | }) 56 | } 57 | 58 | render() { 59 | console.log("======================") 60 | let changeSearch 61 | changeSearch = this.props.clampedScroll && this.props.clampedScroll.interpolate({ 62 | inputRange: [ 0, 112 ], 63 | outputRange: [ 0, -112], 64 | extrapolate: 'clamp' 65 | }) 66 | 67 | let changeTop = this.props.clampedScroll && this.props.clampedScroll.interpolate({ 68 | inputRange: [ 56 , 80 ], 69 | outputRange: [ 1, 0], 70 | extrapolate: 'clamp' 71 | }) 72 | let fadeInOut = this.props.clampedScroll && this.props.clampedScroll.interpolate({ 73 | inputRange: [ 60, 80 ], 74 | outputRange: [ 0, 1 ], 75 | extrapolate: 'clamp' 76 | }) 77 | if( this.props.type === "custom"){ 78 | return 79 | 88 | 89 | { this.props.children } 90 | 91 | } 92 | else 93 | return( 94 | 104 | 105 | 116 | { this.props.mainText } 121 | 122 | 135 | 136 | { this.props.mainText } 141 | {this.props.contextMenu && 156 | 162 | } 163 | > 164 | { this.renderMenuItems() } 165 | } 166 | 167 | 184 | { this.props.bottomComponent } 185 | 186 | 187 | ) 188 | } 189 | } 190 | 191 | // Default props 192 | Header.defaultProps = { 193 | type : null, 194 | style : null, 195 | mainText: '', 196 | bottomComponent: null, 197 | contextMenu: null 198 | } 199 | 200 | // Props types 201 | Header.propTypes = { 202 | // Style config 203 | style : PropTypes.object, 204 | /* 205 | type to custom component 206 | takes 'custom' or null 207 | */ 208 | type: PropTypes.oneOf([ 'custom', null ]), 209 | } 210 | 211 | const styles = StyleSheet.create({ 212 | container: { 213 | marginTop: getStatusBarHeight(), 214 | justifyContent: 'center', 215 | backgroundColor :'#fff' 216 | }, 217 | shadow : Platform.OS === "ios" ? { 218 | shadowColor: "#000", 219 | shadowOffset: { 220 | width: 0, 221 | height: 2, 222 | }, 223 | shadowOpacity: 0.25, 224 | shadowRadius: 3.84, 225 | } : { 226 | elevation: 5 227 | }, 228 | searchContainer : { 229 | paddingHorizontal: 15, 230 | backgroundColor: '#FAFAFA' 231 | } 232 | }) 233 | 234 | 235 | export default Header -------------------------------------------------------------------------------- /src/components/ChatComponents/ChatJobDescription/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Platform, 7 | Image, 8 | TouchableOpacity 9 | } from 'react-native' 10 | 11 | // Local components 12 | import { Color, normalize } from '../../../global' 13 | 14 | // Icon 15 | import BlueDoubleTick from './../../../../assets/blue-double-tick.png' 16 | import DoubleTick from './../../../../assets/double-tick.png' 17 | import DocxIcon from './../../../../assets/docx.png' 18 | import Download from './../../../../assets/download.png' 19 | 20 | /** 21 | * ChatJobDescription Component 22 | * 23 | * @version 1.0.0 24 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 25 | */ 26 | 27 | class ChatJobDescription extends React.Component { 28 | 29 | renderAdditionalInfo = () => { 30 | return this.props.additionalInfo.map( ({ question, answer },index) => { 31 | return( 32 | { question } 33 | { answer} 34 | ) 35 | }) 36 | } 37 | render(){ 38 | return ( 42 | 51 | 52 | { this.props.title } 59 | 60 | 61 | 70 | 71 | { this.props.body } 72 | 73 | 74 | {this.props.additionalInfo.length > 0 && 79 | Additional info 85 | {this.renderAdditionalInfo()} 86 | } 87 | { this.props.document.type && 89 | { this.props.document.previewImage && } 98 | 104 | 105 | 112 | 113 | 114 | { this.props.document.name } 120 | 121 | 122 | 129 | 130 | 131 | } 132 | 133 | 134 | {this.props.document.type && 135 | {this.props.document.pages} page{this.props.document.pages > 1 && 's'} • { this.props.document.type.toUpperCase() } • { this.props.document.size } mb 136 | } 137 | 138 | { this.props.timestamp } 139 | {this.props.isRead === false || this.props.isRead === true ? 140 | 147 | : null } 148 | 149 | 150 | 151 | ) 152 | 153 | } 154 | } 155 | 156 | ChatJobDescription.defaultProps = { 157 | // This will take OFFER_APPROVAL, OFFER_ACCEPTED, OFFER_REJECTED 158 | headerIcon: null, 159 | title: '', 160 | body: null, 161 | type: 'warn', 162 | isRead: null, 163 | additionalInfo:[], 164 | document: { 165 | type: null, 166 | uri: '', 167 | previewImage: null, 168 | pages: 0, 169 | size: 0, 170 | name: '' 171 | }, 172 | onPressDownload: null 173 | } 174 | 175 | const styles = StyleSheet.create({ 176 | container : { 177 | marginVertical: 5, 178 | marginBottom: 0, 179 | borderRadius: 10, 180 | marginHorizontal: 10, 181 | backgroundColor: 'white', 182 | paddingBottom: 5 183 | }, 184 | shadow : Platform.os === "ios" ? { 185 | shadowColor: "#000", 186 | shadowOffset: { 187 | width: 0, 188 | height: 2, 189 | }, 190 | shadowOpacity: 0.25, 191 | shadowRadius: 3.84, 192 | } : { 193 | elevation: 5 194 | }, 195 | chatboxFooterTimeStamp : { 196 | fontSize: 12, 197 | flexDirection: 'row', 198 | paddingHorizontal: 5 199 | } 200 | }) 201 | export default ChatJobDescription -------------------------------------------------------------------------------- /src/components/Card/cardbody.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Image, 7 | Platform 8 | } from 'react-native' 9 | 10 | // Local components 11 | import { Color } from './../../global' 12 | 13 | // Icons 14 | import BlueDoubleTick from './../../../assets/blue-double-tick.png' 15 | import DoubleTick from './../../../assets/double-tick.png' 16 | import RateEmployer from './../../../assets/rate-employe.png' 17 | 18 | /** 19 | * CardBody Component 20 | * 21 | * @version 1.0.0 22 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 23 | */ 24 | 25 | class CardBody extends React.Component { 26 | 27 | render() { 28 | let title = '' 29 | if (this.props.jobState === "BID_PLACED") { 30 | title = 'Set your price:' 31 | } 32 | else if (this.props.jobState === "BID_ACCEPTED") 33 | title = 'Funds in escrow :):' 34 | 35 | 36 | if (this.props.context === "MY_JOBS") 37 | title = "My payment:" 38 | 39 | return ( 40 | 41 | {this.props.isRead === false || this.props.isRead === true ? 42 | 49 | : null} 50 | 51 | {this.props.description} 52 | 53 | 54 | 62 | {(this.props.jobState === "BID_PLACED" || this.props.jobState === "BID_REJECTED") && 63 | 77 | 78 | {title} 79 | 80 | ${this.props.bid.acceptedPrice} 81 | out of 82 | {this.props.bid.proposedPrice > 0 ? `$` + this.props.bid.proposedPrice : '?'} 83 | 84 | 85 | 86 | Complete in: 87 | 88 | {this.props.bid.days > 0 ? this.props.bid.days : '?'} 89 | {this.props.bid.days > 0 && Days} 90 | 91 | 92 | } 93 | {(this.props.jobState === "BID_ACCEPTED" || this.props.jobState === "JOB_AWAIT_CONFIRMATION" || this.props.jobState === "JOB_IN_PROGRESS") && 94 | 108 | 109 | {title} 110 | 111 | ${this.props.bid.acceptedPrice} 112 | out of 113 | ${this.props.bid.proposedPrice > 0 ? this.props.bid.proposedPrice : '?'} 114 | 115 | 116 | 117 | Complete in: 118 | 119 | {this.props.bid.days} 120 | Days 121 | 122 | 123 | } 124 | {this.props.jobState === "BID_COMPLETED_RELEASED" && 125 | 139 | 140 | Paid :) 141 | 142 | +${this.props.bid.acceptedPrice} 143 | 144 | 145 | 146 | Rate employer 147 | 148 | 155 | ? 156 | 157 | 158 | } 159 | 160 | ) 161 | } 162 | } 163 | 164 | CardBody.defaultProps = { 165 | isRead: null, 166 | jobState: null, 167 | bid: { 168 | acceptedPrice: 0, 169 | proposedPrice: 0, 170 | days: 0, 171 | status: '' 172 | }, 173 | description: "No description", 174 | // It will take JOBS or MY_JOBS 175 | context: 'JOBS' 176 | } 177 | const styles = StyleSheet.create({ 178 | container: { 179 | }, 180 | descriptionContainer: { 181 | flexDirection: 'row', 182 | paddingHorizontal: 15 183 | }, 184 | shadow: Platform.os === "ios" ? { 185 | shadowColor: "#000", 186 | shadowOffset: { 187 | width: 0, 188 | height: 1, 189 | }, 190 | shadowOpacity: 0.22, 191 | shadowRadius: 2.22, 192 | } : { 193 | elevation: 3 194 | } 195 | }) 196 | export default CardBody -------------------------------------------------------------------------------- /src/screens/menu/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | ScrollView, 7 | Animated, 8 | Image, 9 | Platform, 10 | AsyncStorage, 11 | Picker 12 | } from 'react-native' 13 | 14 | // Local components 15 | import Header from './../../components/Header' 16 | import ItemContainer from './../../components/ItemContainer' 17 | import Item from './../../components/Item' 18 | import UserInfo from './userinfo' 19 | import BackgroundImage from './../../components/BackgroundImage' 20 | 21 | // Icon 22 | import Avatar from './../../../assets/avatar.png' 23 | import RightArrow from './../../../assets/right-arrow.png' 24 | import MyBusinessIcon from './../../../assets/my-business.png' 25 | import MyWork from './../../../assets/my-work.png' 26 | import WalletBlue from './../../../assets/wallet-blue.png' 27 | import Emoji from './../../../assets/emoji.png' 28 | import WithdrawFund from './../../../assets/withdraw-fund.png' 29 | import DepositFund from './../../../assets/deposit-fund.png' 30 | import Glob from './../../../assets/glob.png' 31 | import Setting from './../../../assets/setting.png' 32 | import Help from './../../../assets/help.png' 33 | import LoginBlack from './../../../assets/login-black.png' 34 | 35 | // Images 36 | import Background from './../../../assets/background-pattern-gray.png' 37 | 38 | // Config 39 | import { Color, normalize } from '../../global' 40 | 41 | class Menu extends React.Component { 42 | 43 | constructor(props) { 44 | super(props) 45 | this.state = { 46 | offsetY: 0, 47 | direction: -1, 48 | offsetAfterScrollEnd: 0, 49 | scrollY: new Animated.Value(0.01), 50 | }; 51 | } 52 | 53 | render() { 54 | return ( 55 | 56 | {/* Header Section */} 57 |
60 | 69 | Settings 74 | 75 |
76 | 77 | 78 | { 83 | alert('Do something') 84 | }} 85 | onPressVarifyAccount={() => { 86 | alert('Go to varification page') 87 | }} 88 | /> 89 | 90 | 98 | } 99 | onPress={() => { 100 | alert('Do Something') 101 | }} 102 | text="My business" 103 | /> 104 | 114 | } 115 | onPress={() => { 116 | alert('Do Something') 117 | }} 118 | text="My work areas" 119 | /> 120 | 121 | 122 | 130 | } 131 | onPress={() => { 132 | alert('Do Something') 133 | }} 134 | text="Financial & Packages" 135 | /> 136 | 144 | } 145 | onPress={() => { 146 | alert('Do Something') 147 | }} 148 | text="Withdraw funds" 149 | /> 150 | 158 | } 159 | onPress={() => { 160 | alert('Do Something') 161 | }} 162 | text="Deposit funds" 163 | /> 164 | 165 | 166 | 175 | } 176 | onPress={() => { 177 | alert('Do Something') 178 | }} 179 | text="Settings" 180 | /> 181 | 190 | } 191 | style={{ 192 | height: 62 193 | }} 194 | text="Language" 195 | rightComponent={ 198 | 202 | this.setState({ language: itemValue }) 203 | }> 204 | 205 | 206 | 207 | 208 | 209 | } 210 | /> 211 | 212 | 213 | 222 | } 223 | onPress={() => { 224 | alert('Do Something') 225 | }} 226 | text="Help" 227 | /> 228 | 237 | } 238 | onPress={() => { 239 | alert('Do Something') 240 | }} 241 | text="Tell a friend" 242 | /> 243 | 244 | 245 | 254 | } 255 | onPress={() => { 256 | AsyncStorage.setItem('LOGGED', "false"); 257 | this.props.navigation.navigate('Login'); 258 | }} 259 | text="Log out" 260 | /> 261 | 262 | 263 |
) 264 | } 265 | } 266 | 267 | const styles = StyleSheet.create({ 268 | container: { 269 | backgroundColor: '#E3E3E3', 270 | flex: 1 271 | }, 272 | searchContainer: { 273 | paddingHorizontal: 15, 274 | }, 275 | shadow: Platform.os === "ios" ? { 276 | shadowColor: "#000", 277 | shadowOffset: { 278 | width: 0, 279 | height: 2, 280 | }, 281 | shadowOpacity: 0.25, 282 | shadowRadius: 3.84, 283 | } : { 284 | elevation: 5 285 | }, 286 | shadow: Platform.OS === "ios" ? { 287 | shadowColor: "#000", 288 | shadowOffset: { 289 | width: 0, 290 | height: 2, 291 | }, 292 | shadowOpacity: 0.25, 293 | shadowRadius: 3.84, 294 | } : { 295 | elevation: 5 296 | } 297 | }) 298 | export default Menu -------------------------------------------------------------------------------- /src/screens/chatscreen/chatheader.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | TouchableOpacity, 7 | Image 8 | } from 'react-native' 9 | 10 | // Local components 11 | import { Color } from './../../global' 12 | import Header from '../../components/Header' 13 | 14 | // Icons 15 | import LeftArrow from './../../../assets/left-arrow.png' 16 | import Phone from './../../../assets/phone-icon.png' 17 | import Avatar from './../../../assets/avatar.png' 18 | import Star from './../../../assets/star-icon.png' 19 | import oIcon from './../../../assets/o-icon.png' 20 | import Trust from './../../../assets/trust-icon.png' 21 | import MapIcon from './../../../assets/map.png' 22 | 23 | /** 24 | * ChatHeader Component 25 | * 26 | * @version 1.0.0 27 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 28 | */ 29 | 30 | class ChatHeader extends React.Component { 31 | render(){ 32 | return(
35 | 36 | 44 | 49 | 55 | 56 | 57 | 58 | 59 | 65 | { this.props.oIcon && 73 | 79 | } 80 | 81 | 84 | 85 | { this.props.username } 92 | { this.props.varified && } 101 | 102 | 103 | { this.props.status } 112 | 121 | { this.props.rating } 127 | 128 | 129 | 130 | 131 | 134 | 145 | 146 | 152 | 153 | 154 | 155 | 156 | 165 | 170 | 176 | 177 | 178 | Saint Mark St 124f, LA, CA, 0421431 179 | 5.5 km 180 | 181 | 182 | { this.props.jobStatus === "BID_NOT_PLACED" && 187 | Open for 192 | bidding 198 | } 199 | { this.props.jobStatus === "BID_PLACED" && 204 | My payment 208 | 213 | ${this.props.bid?.acceptedPrice} 214 | 215 | Out of ${this.props.bid?.proposedPrice} 221 | } 222 | { this.props.jobStatus === "BID_ACCEPTED" && 227 | My payment 231 | 236 | ${this.props.bid?.acceptedPrice} 237 | 238 | Out of ${this.props.bid?.proposedPrice} 244 | } 245 | { this.props.jobStatus === "BID_REJECTED" && 250 | 255 | rejected 256 | 257 | } 258 | 259 | 260 |
) 261 | } 262 | } 263 | 264 | ChatHeader.defaultProps = { 265 | username:'', 266 | status: 'online', 267 | rating: '0', 268 | avatar: null, 269 | oIcon : false, 270 | varified: false, 271 | bid: { 272 | acceptedPrice: 0, 273 | proposedPrice: 0, 274 | }, 275 | jobStatus: 'BID_NOT_PLACED' 276 | } 277 | const styles = StyleSheet.create({ 278 | container : { 279 | paddingHorizontal: 15 280 | }, 281 | shadow : Platform.OS === "ios" ? { 282 | shadowColor: "#000", 283 | shadowOffset: { 284 | width: 0, 285 | height: 1, 286 | }, 287 | shadowOpacity: 0.22, 288 | shadowRadius: 2.22, 289 | } : { 290 | elevation: 3 291 | } 292 | }) 293 | export default ChatHeader -------------------------------------------------------------------------------- /src/screens/jobs/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { FileSystem, Asset } from 'expo'; 3 | import { 4 | View, 5 | StyleSheet, 6 | Animated, 7 | } from 'react-native' 8 | import { getStatusBarHeight } from 'react-native-status-bar-height'; 9 | import * as Device from 'expo-device'; 10 | // import { Thread } from 'react-native-threads'; 11 | // import { Worker } from 'react-native-workers'; 12 | 13 | // Local components 14 | import Header from './../../components/Header' 15 | import Search from './../../components/Search' 16 | import Card from './../../components/Card' 17 | import NoOpenJobAlert from './NoOpenJobAlert' 18 | import WorkAreaNotSet from './WorkAreaNotSet' 19 | import CutomButton from './../../components/Button' 20 | 21 | // Images 22 | import BackgroundImage from './../../components/BackgroundImage' 23 | // Config 24 | import { Color } from './../../global' 25 | import configs from '@utils/configs'; 26 | 27 | import Database from '../../Database.js'; 28 | 29 | const DB = new Database(); 30 | let db = DB.openDatabase(db); 31 | 32 | class Jobs extends React.Component { 33 | 34 | constructor(props) { 35 | super(props) 36 | 37 | const scrollAnim = new Animated.Value(0) 38 | const offsetAnim = new Animated.Value(0) 39 | 40 | this.state = { 41 | jobs: [], 42 | 43 | entityId: 0, 44 | username: '', 45 | password: '', 46 | listKind: 0, 47 | jobId: 0, 48 | jobCategoryId: true, 49 | jobStatus: 0, 50 | searchText: '', 51 | limitForm: 0, 52 | limitCount: 0, 53 | searchBudgetMin: 0, 54 | SearchBudgetMax: 0, 55 | searchSkillId: true, 56 | searchCountryISO: true, 57 | searchStateISO: true, 58 | searchCityId: true, 59 | searchVerificationArray: true, 60 | searchEmploymentType: true, 61 | searchEntityId: 0, 62 | sortByDestination: '', 63 | languageISO: '', 64 | 65 | scrollAnim, 66 | offsetAnim, 67 | clampedScroll: Animated.diffClamp( 68 | Animated.add( 69 | scrollAnim.interpolate({ 70 | inputRange: [0, 1], 71 | outputRange: [0, 1], 72 | extrapolateLeft: 'clamp' 73 | }), 74 | offsetAnim 75 | ), 0, 112 76 | ) 77 | }; 78 | } 79 | 80 | componentDidMount() { 81 | DB.initDatabase(db); 82 | // this.addCategories(); 83 | this.addJobs(); 84 | } 85 | 86 | addCategories() { 87 | const xmlHeader = ''; 88 | const xmlRequest = '00'; 89 | fetch(configs.jobURL, { 90 | method: 'POST', 91 | headers: { 92 | 'Authorization': 'Basic YWRtaW53ZWJzaXRlOk5mbjM5Zm5BQWQyMw==', 93 | 'Content-Type': 'text/xml', 94 | }, 95 | body: xmlHeader + xmlRequest, 96 | }).then((response) => response.text()) 97 | .then((responseText) => { 98 | const responseJson = JSON.parse(responseText.split('')[1].split('')[0]); 99 | DB.addCategories(db, responseJson); 100 | }).catch((error) => { 101 | return 102 | }); 103 | } 104 | 105 | addJobs() { 106 | const { entityId, username, password, listKind, jobId, jobCategoryId, jobStatus, searchText, limitForm, limitCount, searchBudgetMin, SearchBudgetMax, searchSkillId, searchCountryISO, searchStateISO, searchCityId, searchVerificationArray, searchEmploymentType, searchEntityId, sortByDestination, languageISO } = this.state; 107 | const xmlHeader = ''; 108 | const xmlRequest = '' + entityId + '' + username + '' + password + '' + listKind + '' + jobId + '' + jobCategoryId + '' + jobStatus + '' + searchText + '' + limitForm + '' + limitCount + '' + searchBudgetMin + '' + SearchBudgetMax + '' + searchSkillId + '' + searchCountryISO + '' + searchStateISO + '' + searchCityId + '' + searchVerificationArray + '' + searchEmploymentType + '' + searchEntityId + '' + sortByDestination + '' + languageISO + ''; 109 | fetch(configs.jobURL, { 110 | method: 'POST', 111 | headers: { 112 | 'Authorization': 'Basic YWRtaW53ZWJzaXRlOk5mbjM5Zm5BQWQyMw==', 113 | 'Content-Type': 'text/xml', 114 | }, 115 | body: xmlHeader + xmlRequest, 116 | }).then((response) => response.text()) 117 | .then((responseText) => { 118 | const responseJson = JSON.parse(responseText.split('')[1].split('')[0]); 119 | DB.addJobs(db, responseJson); 120 | }).catch((error) => { 121 | return 122 | }); 123 | } 124 | 125 | renderJobCards = () => { 126 | return 127 | { 128 | this.state.jobs.map((item, key) => { 129 | return ( 130 | 0 ? true : false} 145 | timestamp='2 min' 146 | distance={item.Distance + ' Km'} 147 | 148 | onPress={() => { 149 | this.props.navigation.navigate('ChatScreen', { 150 | jobState: "BID_NOT_PLACED", 151 | varified: false 152 | }) 153 | }} 154 | /> 155 | ); 156 | }) 157 | } 158 | 159 | } 160 | 161 | render() { 162 | let changeTop = undefined; 163 | // To animate top header 164 | return ( 165 | 166 | 167 |
} 170 | mainText="Jobs" 171 | /> 172 | {!this.state.noOpenJobs && !this.state.noWorkArea && 173 | { 189 | 190 | }} 191 | > 192 | {this.renderJobCards()} 193 | { 199 | this.setState({ noWorkArea: true }) 200 | }} /> 201 | { 207 | this.setState({ noOpenJobs: true }) 208 | }} /> 209 | 210 | } 211 | {this.state.noOpenJobs && 212 | 217 | { 223 | this.setState({ noOpenJobs: false }) 224 | }} /> 225 | 226 | 227 | } 228 | {this.state.noWorkArea && 234 | { 240 | this.setState({ noWorkArea: false }) 241 | }} /> 242 | { alert('hello') }} 244 | /> 245 | 246 | } 247 | 248 | ) 249 | } 250 | } 251 | 252 | const styles = StyleSheet.create({ 253 | container: { 254 | backgroundColor: '#E3E3E3', 255 | position: 'relative', 256 | flex: 1 257 | }, 258 | searchContainer: { 259 | paddingHorizontal: 15, 260 | backgroundColor: '#FAFAFA' 261 | }, 262 | shadow: Platform.OS === "ios" ? { 263 | shadowColor: "#000", 264 | shadowOffset: { 265 | width: 0, 266 | height: 2, 267 | }, 268 | shadowOpacity: 0.25, 269 | shadowRadius: 3.84, 270 | } : { 271 | elevation: 5 272 | } 273 | }) 274 | export default Jobs 275 | -------------------------------------------------------------------------------- /src/screens/login/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | Image, 7 | TextInput, 8 | KeyboardAvoidingView, 9 | Dimensions, 10 | Linking, 11 | AsyncStorage 12 | } from 'react-native' 13 | import { TouchableOpacity } from 'react-native-gesture-handler' 14 | 15 | // Redux 16 | import { connect } from 'react-redux'; 17 | import { setUser } from '@modules/account/actions'; 18 | 19 | // Icons or Images 20 | import Logo from './../../../assets/logo.png' 21 | import LoginIcon from './../../../assets/login.png' 22 | import FacebookIcon from './../../../assets/facebook_icon.png' 23 | import SignIn from './../../../assets/sign-in.png' 24 | 25 | // Components 26 | import CutomButton from './../../components/Button' 27 | 28 | // Functions 29 | import { verifyEmail, verifyPhone, verifyLength } from '@utils/Functions'; 30 | 31 | // Globals 32 | import { Color } from './../../global' 33 | import { Platform } from '@unimodules/core'; 34 | import configs from '@utils/configs'; 35 | 36 | class Login extends React.Component { 37 | 38 | constructor(props) { 39 | super(props); 40 | 41 | this.state = { 42 | email: '', 43 | password: '', 44 | errorMessage: null 45 | } 46 | } 47 | 48 | onPressAlert = () => { 49 | alert("I am a button") 50 | } 51 | async componentDidMount() { 52 | if (await AsyncStorage.getItem('LOGGED') === "true") { 53 | this.props.navigation.navigate('Screen') 54 | } 55 | } 56 | 57 | onForgotPassword = () => { 58 | const { email } = this.state; 59 | if (!email) { 60 | this.setState({ errorMessage: 'Should not be empty' }) 61 | } else { 62 | if (verifyEmail(email)) { 63 | this.setState({ errorMessage: '' }); 64 | alert("Password reset instruction have been sent to " + email); 65 | } else { 66 | this.setState({ errorMessage: 'Email is invailed' }); 67 | } 68 | } 69 | } 70 | 71 | onLogin = () => { 72 | const { email, password } = this.state; 73 | if (!email) { 74 | this.setState({ errorMessage: 'Enter your email address' }) 75 | } else { 76 | if (verifyEmail(email)) { 77 | this.setState({ errorMessage: '' }); 78 | if (!password) { 79 | this.setState({ errorMessage: 'Enter your password' }) 80 | } else { 81 | if (verifyLength(password, 6)) { 82 | this.setState({ errorMessage: '' }); 83 | this.onSubmit(); 84 | } else { 85 | this.setState({ errorMessage: 'Enter more 6 charactors' }); 86 | } 87 | } 88 | } else { 89 | this.setState({ errorMessage: 'Email is invailed' }); 90 | } 91 | } 92 | } 93 | 94 | onSubmit() { 95 | const { email, password, errorMessage } = this.state; 96 | const xmlHeader = ''; 97 | const xmlRequest = '' + 98 | '' + email + '' + 99 | '' + password + '' + 100 | // '209.95.60.92' + 101 | // 'EN' + 102 | '' 103 | 104 | fetch(configs.generalURL, { 105 | method: 'POST', 106 | headers: { 107 | 'Authorization': 'Basic YWRtaW53ZWJzaXRlOk5mbjM5Zm5BQWQyMw==', 108 | 'Content-Type': 'text/xml', 109 | }, 110 | body: xmlHeader + xmlRequest, 111 | }).then((response) => response.text()) 112 | .then((responseText) => { 113 | const responseJson = JSON.parse(responseText.split('')[1].split('')[0]); 114 | const ResultCode = responseJson.ResultCode; 115 | if(ResultCode == -1){ 116 | alert(responseJson.ResultMessage); 117 | } 118 | else if(ResultCode == -2){ 119 | alert("Description of database error"); 120 | } 121 | else if(ResultCode > 0){ 122 | AsyncStorage.setItem('LOGGED', "true"); 123 | this.props.navigation.navigate('Screen'); 124 | } 125 | }).catch((error) => { 126 | return 127 | }); 128 | 129 | } 130 | 131 | render() { 132 | const { email, password, errorMessage } = this.state; 133 | return ( 134 | 135 | 136 | 137 | 141 | 142 | Start 143 | A 144 | Job 145 | 146 | 147 | 148 | 149 | 150 | Please enter your login credentials 151 | 152 | 153 | this.setState({ email })} 162 | /> 163 | this.setState({ password })} 171 | /> 172 | {errorMessage ? {errorMessage} : null} 173 | 174 | 175 | this.onLogin()} 180 | logo={LoginIcon} 181 | fontWidth={'100'} 182 | fontSize={17} 183 | backgroundColor={Color.primary} 184 | title={'Login'} /> 185 | 186 | 187 | 188 | 189 | this.onForgotPassword()} 191 | style={{ justifyContent: 'center' }}> 192 | Forgot your password? 196 | 197 | 198 | 206 | | 212 | 219 | Login via 224 | {/* Facebook login button */} 225 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 236 | 237 | 238 | New Here? 244 | 245 | 246 | 247 | 248 | Linking.openURL('https://www.startajob.com/signin?t=1&vt=0')}> 251 | Create an Account 258 | 259 | 260 | 261 | 262 | 263 | 264 | ) 265 | } 266 | } 267 | 268 | // Props Types 269 | Login.propTypes = { 270 | 271 | } 272 | 273 | // Default Props 274 | Login.defaultProps = { 275 | title: 'No name' 276 | } 277 | 278 | const styles = StyleSheet.create({ 279 | container: { 280 | flex: 1, 281 | backgroundColor: 'white' 282 | }, 283 | top: { 284 | flex: 2, 285 | justifyContent: 'center', 286 | alignItems: 'center' 287 | }, 288 | middle: { 289 | flex: 3, 290 | paddingHorizontal: 15 291 | }, 292 | bottom: { 293 | alignItems: 'center', 294 | justifyContent: 'center' 295 | }, 296 | logoImage: { 297 | height: 84, 298 | width: 84 299 | }, 300 | textInput: { 301 | borderWidth: 2, 302 | borderColor: '#E3E3E3', 303 | borderRadius: 4, 304 | paddingHorizontal: 15, 305 | paddingVertical: Platform.OS === "ios" ? 12 : 8, 306 | fontSize: 13, 307 | color: '#121212', 308 | marginBottom: 10, 309 | backgroundColor: '#E3E3E3' 310 | }, 311 | signinContainer: { 312 | marginTop: Dimensions.get("window").height > 600 ? 40 : 10, 313 | alignItems: 'center', 314 | justifyContent: 'center' 315 | } 316 | }); 317 | 318 | export default Login -------------------------------------------------------------------------------- /src/screens/chatscreen/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | ScrollView, 7 | Animated, 8 | Image, 9 | TouchableOpacity, 10 | KeyboardAvoidingView, 11 | SafeAreaView 12 | } from 'react-native' 13 | 14 | // Local components 15 | import Chat from './../../components/ChatComponents/Chat' 16 | import ChatAlert from '../../components/ChatComponents/ChatAlert' 17 | import ChatJobDescription from './../../components/ChatComponents/ChatJobDescription' 18 | import Label from './../../components/ChatComponents/label' 19 | import ChatInput from './../../components/ChatComponents/ChatInput' 20 | import ChatHeader from './chatheader' 21 | 22 | // Icons 23 | import SandWatch from './../../../assets/sand-watch-blue.png' 24 | import HandShake from './../../../assets/hand-shake-green.png' 25 | import Block from './../../../assets/block.png' 26 | 27 | // Images 28 | import Background from './../../../assets/background-pattern.png' 29 | 30 | // Config 31 | import { Color, normalize } from '../../global' 32 | 33 | /** 34 | * ChatScreen Component 35 | * 36 | * @version 1.0.0 37 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 38 | */ 39 | 40 | class ChatScreen extends React.Component { 41 | 42 | constructor(props) { 43 | super(props) 44 | this.state = { 45 | value: '', 46 | offsetY: 0, 47 | inputDays: '', 48 | inputPrice: '', 49 | direction:-1 , 50 | offsetAfterScrollEnd: 0, 51 | scrollY: new Animated.Value(0.01), 52 | }; 53 | } 54 | 55 | render(){ 56 | return( 58 | { 70 | alert('Call me') 71 | }} 72 | onPressBack = {() => { 73 | this.props.navigation.goBack() 74 | }} 75 | /> 76 | {/* Background */} 77 | 84 | 97 | 355 | {/* Chat input */} 356 | 357 | 361 | 362 | ) 363 | } 364 | } 365 | 366 | const styles = StyleSheet.create({ 367 | container: { 368 | backgroundColor: Color.color4, 369 | flex: 1 370 | }, 371 | searchContainer : { 372 | paddingHorizontal: 15 373 | } 374 | }) 375 | export default ChatScreen -------------------------------------------------------------------------------- /src/Database.js: -------------------------------------------------------------------------------- 1 | import * as SQLite from 'expo-sqlite'; 2 | 3 | const database_name = "StartAJob.db"; 4 | const database_version = "1.0"; 5 | const database_description = "SQLite React Offline Database"; 6 | const database_size = 200000; 7 | 8 | 9 | 10 | 11 | export default class Database { 12 | openDatabase() { 13 | return SQLite.openDatabase( 14 | database_name, 15 | database_version, 16 | database_description, 17 | database_size 18 | ); 19 | } 20 | initDatabase(db) { 21 | if (db) { 22 | db.transaction((tx) => { 23 | tx.executeSql(`DROP TABLE IF EXISTS categories`, []); 24 | tx.executeSql(`CREATE TABLE IF NOT EXISTS categories (` + 25 | `JobCategoryID INTEGER NOT NULL, ` + 26 | `ParentID INTEGER DEFAULT NULL, ` + 27 | `Level INTEGER DEFAULT NULL, ` + 28 | `JobCategoryName TEXT DEFAULT NULL, ` + 29 | `JobCategoryName_he TEXT DEFAULT NULL, ` + 30 | `JobCategoryName_ru TEXT DEFAULT NULL, ` + 31 | `JobsCount INTEGER DEFAULT 0, ` + 32 | `proCount INTEGER DEFAULT 0, ` + 33 | `isLocal INTEGER DEFAULT 0, ` + 34 | `TabIndex INTEGER NOT NULL DEFAULT 0, ` + 35 | `isDeleted INTEGER DEFAULT 0, ` + 36 | `CostToBid NUMERIC DEFAULT 0.00, ` + 37 | `CostPerNotification NUMERIC DEFAULT 2.00, ` + 38 | `LastUsed NUMERIC DEFAULT NULL, ` + 39 | `classified INTEGER NOT NULL DEFAULT 0, ` + 40 | `SEO_title TEXT DEFAULT NULL, ` + 41 | `SEO_title_he TEXT DEFAULT NULL, ` + 42 | `SEO_title_ru TEXT DEFAULT NULL, ` + 43 | `SEO_Description TEXT DEFAULT NULL, ` + 44 | `SEO_description_he TEXT DEFAULT NULL, ` + 45 | `SEO_description_ru TEXT DEFAULT NULL, ` + 46 | `UpdateDate TEXT DEFAULT NULL` + 47 | `);`); 48 | // tx.executeSql(`CREATE TABLE IF NOT EXISTS categories_skills (` + 49 | // `JobCategoryID INTEGER DEFAULT NULL, ` + 50 | // `SkillID INTEGER DEFAULT NULL, ` + 51 | // `CreatedDate TEXT, ` + 52 | // `status INTEGER DEFAULT 1, ` + 53 | // `SuggestedCount INTEGER DEFAULT 0, ` + 54 | // `SuggestedEntityID TEXT DEFAULT NULL, ` + 55 | // `last_used_date NUMERIC DEFAULT NULL, ` + 56 | // `selected_count INTEGER NOT NULL DEFAULT 0` + 57 | // ');'); 58 | // tx.executeSql(`CREATE TABLE IF NOT EXISTS entities_skills (` + 59 | // `ratingType INTEGER DEFAULT 1, ` + 60 | // `skillID INTEGER DEFAULT NULL, ` + 61 | // `entityID INTEGER DEFAULT NULL, ` + 62 | // `jobID INTEGER DEFAULT 0, ` + 63 | // `experienceID INTEGER DEFAULT 0, ` + 64 | // `createdDate TEXT, ` + 65 | // `completedjobs INTEGER DEFAULT 0, ` + 66 | // `ratingLevel INTEGER DEFAULT 0` + 67 | // `);`); 68 | tx.executeSql(`DROP TABLE IF EXISTS jobs`, []); 69 | tx.executeSql(`CREATE TABLE IF NOT EXISTS jobs (` + 70 | `JobID INTEGER NOT NULL, ` + 71 | `MainJobCategoryID INTEGER NOT NULL, ` + 72 | `JobCategoryID INTEGER NOT NULL, ` + 73 | `classified INTEGER DEFAULT 0, ` + 74 | `EntityID INTEGER NOT NULL, ` + 75 | `EntityFirstName TEXT DEFAULT NULL, ` + 76 | `EntityLastName TEXT DEFAULT NULL, ` + 77 | `EntityCity TEXT DEFAULT NULL, ` + 78 | `EntityCountry TEXT DEFAULT NULL, ` + 79 | `ISO3166 TEXT DEFAULT NULL, ` + 80 | `Title TEXT DEFAULT NULL, ` + 81 | `Description TEXT DEFAULT NULL, ` + 82 | `Budget NUMERIC DEFAULT NULL, ` + 83 | `CurrencyID INTEGER DEFAULT NULL, ` + 84 | `EmploymentType INTEGER DEFAULT NULL, ` + 85 | `PrefferedCountryISO3166 TEXT DEFAULT NULL, ` + 86 | `PrefferedStateISO TEXT DEFAULT NULL, ` + 87 | `PrefferedCityId INTEGER DEFAULT NULL, ` + 88 | `HiredEntityID INTEGER DEFAULT 0, ` + 89 | `isShowPhone INTEGER NOT NULL DEFAULT 0, ` + 90 | `MinOffer INTEGER DEFAULT 0, ` + 91 | `MaxOffer INTEGER DEFAULT 0, ` + 92 | `BidsCount INTEGER DEFAULT 0, ` + 93 | `JobLocation_altitude REAL DEFAULT 0, ` + 94 | `JobLocation_latitude REAL DEFAULT 0, ` + 95 | `CostToBidUSD REAL NOT NULL DEFAULT 0.00, ` + 96 | `CostToBidLocal REAL NOT NULL DEFAULT 0.00, ` + 97 | `CostToBidSymbol TEXT DEFAULT NULL, ` + 98 | `NewMessages INTEGER DEFAULT 0, ` + 99 | `CreateDate TEXT DEFAULT NULL, ` + 100 | `UpdateDate NUMERIC DEFAULT NULL, ` + 101 | `JobStatus INTEGER NOT NULL DEFAULT 0, ` + 102 | `JobLocation_address TEXT DEFAULT NULL, ` + 103 | `JobLocation_cityID INTEGER DEFAULT NULL, ` + 104 | `cityname TEXT DEFAULT NULL, ` + 105 | `JobLocation_districtID INTEGER DEFAULT NULL, ` + 106 | `JobLocation_districtID2 INTEGER DEFAULT NULL, ` + 107 | `JobLocation_stateISO TEXT DEFAULT NULL, ` + 108 | `JobLocation_countryISO3166 TEXT DEFAULT NULL, ` + 109 | `CountryId INTEGER DEFAULT NULL, ` + 110 | `CountryName TEXT DEFAULT '', ` + 111 | `ExpiredDate NUMERIC DEFAULT NULL, ` + 112 | `WorkingHour_Start NUMERIC DEFAULT NULL, ` + 113 | `WorkingHour_HoursPerDay INTEGER DEFAULT NULL, ` + 114 | `WorkingHour_DayPerWeek INTEGER DEFAULT NULL, ` + 115 | `CancelDate NUMERIC DEFAULT NULL, ` + 116 | `CancelReason INTEGER unsigned DEFAULT NULL, ` + 117 | `CancelReasonRemark TEXT DEFAULT NULL, ` + 118 | `DisputeExpiryDate NUMERIC DEFAULT NULL, ` + 119 | `employerEscrowId INTEGER DEFAULT NULL, ` + 120 | `employeeEscrowId INTEGER DEFAULT NULL, ` + 121 | `RequestedEntityId INTEGER DEFAULT NULL, ` + 122 | `Distance INTEGER DEFAULT NULL, ` + 123 | `Company TEXT DEFAULT NULL, ` + 124 | `PlacedBid INTEGER DEFAULT NULL,` + 125 | `Phone TEXT DEFAULT NULL, ` + 126 | `Rating REAL DEFAULT NULL` + 127 | `);`); 128 | 129 | // tx.executeSql(`CREATE TABLE IF NOT EXISTS jobs (` + 130 | // `JobID INTEGER NOT NULL, ` + 131 | // `JobCategoryID INTEGER NOT NULL, ` + 132 | // `EntityID INTEGER NOT NULL, ` + 133 | // `HiredEntityID INTEGER DEFAULT 0, ` + 134 | // `JobStatus INTEGER NOT NULL DEFAULT 0, ` + 135 | // `Title TEXT DEFAULT NULL, ` + 136 | // `Description TEXT DEFAULT NULL, ` + 137 | // `Budget NUMERIC DEFAULT NULL, ` + 138 | // `CurrencyID INTEGER DEFAULT NULL, ` + 139 | // `EmploymentType INTEGER DEFAULT NULL, ` + 140 | // `JobLocation_address TEXT DEFAULT NULL, ` + 141 | // `JobLocation_cityID INTEGER DEFAULT NULL, ` + 142 | // `JobLocation_districtID INTEGER DEFAULT NULL, ` + 143 | // `JobLocation_districtID2 INTEGER DEFAULT NULL, ` + 144 | // `JobLocation_stateISO TEXT DEFAULT NULL, ` + 145 | // `JobLocation_countryISO3166 TEXT DEFAULT NULL, ` + 146 | // `JobLocation_altitude REAL DEFAULT 0, ` + 147 | // `JobLocation_latitude REAL DEFAULT 0, ` + 148 | // `WorkingHour_Start NUMERIC DEFAULT NULL, ` + 149 | // `WorkingHour_HoursPerDay INTEGER DEFAULT NULL, ` + 150 | // `WorkingHour_DayPerWeek INTEGER DEFAULT NULL, ` + 151 | // `PrefferedRegionID TEXT DEFAULT NULL, ` + 152 | // `PrefferedCityId INTEGER DEFAULT NULL, ` + 153 | // `PrefferedCountryISO3166 TEXT DEFAULT NULL, ` + 154 | // `PrefferedStateISO TEXT DEFAULT NULL, ` + 155 | // `CreateDate TEXT, ` + 156 | // `HiredDate NUMERIC DEFAULT NULL, ` + 157 | // `UpdateDate NUMERIC DEFAULT NULL, ` + 158 | // `ExpiredDate NUMERIC DEFAULT NULL, ` + 159 | // `CancelDate NUMERIC DEFAULT NULL, ` + 160 | // `CancelReason INTEGER unsigned DEFAULT NULL, ` + 161 | // `CancelReasonRemark TEXT DEFAULT NULL, ` + 162 | // `NewMessages INTEGER DEFAULT 0, ` + 163 | // `MinBid INTEGER DEFAULT 0, ` + 164 | // `MaxBid INTEGER DEFAULT 0, ` + 165 | // `TotalBids INTEGER DEFAULT 0, ` + 166 | // `costtobidUSD REAL NOT NULL DEFAULT 0.00, ` + 167 | // `isMailed INTEGER NOT NULL DEFAULT 0, ` + 168 | // `isShowPhone INTEGER NOT NULL DEFAULT 0, ` + 169 | // `PrivateJob INTEGER NOT NULL DEFAULT 0, ` + 170 | // `isDonation INTEGER NOT NULL DEFAULT 0, ` + 171 | // `DonationDonners INTEGER NOT NULL DEFAULT 0, ` + 172 | // `DonationAmountCollected REAL NOT NULL DEFAULT 0.00, ` + 173 | // `Published_on_FB INTEGER NOT NULL DEFAULT 0, ` + 174 | // `Published_on_twttr INTEGER NOT NULL DEFAULT 0, ` + 175 | // `Published_on_Ig INTEGER NOT NULL DEFAULT 0` + 176 | // `);`); 177 | // tx.executeSql(`CREATE TABLE IF NOT EXISTS jobs_bids (` + 178 | // `BidID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ` + 179 | // `EntityID INTEGER DEFAULT NULL, ` + 180 | // `JobID INTEGER DEFAULT NULL, ` + 181 | // `DesiredSalaryREAL DEFAULT 0.00, ` + 182 | // `CurrencyID INTEGER DEFAULT NULL, ` + 183 | // `ComplateWithin INTEGER DEFAULT 0, ` + 184 | // `BidStatus INTEGER DEFAULT 0, ` + 185 | // `CreateDate TEXT DEFAULT NULL, ` + 186 | // `UpdateDate NUMERIC DEFAULT NULL, ` + 187 | // `deadline NUMERIC DEFAULT NULL, ` + 188 | // `BidOwnerNewMessages INTEGER DEFAULT 0, ` + 189 | // `JobOwnerNewMessages INTEGER DEFAULT 0, ` + 190 | // `UncoverPhoneDate NUMERIC DEFAULT NULL` + 191 | // `);`); 192 | // tx.executeSql(`CREATE TABLE IF NOT EXISTS jobs_bids_messages (` + 193 | // `MessageID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ` + 194 | // `EntityID INTEGER DEFAULT NULL, ` + 195 | // `BidID INTEGER DEFAULT NULL, ` + 196 | // `JobID INTEGER DEFAULT NULL, ` + 197 | // `MessageText TEXT DEFAULT NULL, ` + 198 | // `CreateDate TEXT NULL DEFAULT NULL, ` + 199 | // `Status INTEGER DEFAULT 0, ` + 200 | // `type INTEGER DEFAULT 0` + 201 | // `);`); 202 | // tx.executeSql(`CREATE TABLE IF NOT EXISTS jobs_bids_terms (` + 203 | // `termID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ` + 204 | // `jobID INTEGER NOT NULL, ` + 205 | // `bidID INTEGER DEFAULT NULL, ` + 206 | // `requestedDate TEXT DEFAULT NULL, ` + 207 | // `requestedEntityID INTEGER NOT NULL, ` + 208 | // `salary REAL DEFAULT NULL, ` + 209 | // `deadline NUMERIC DEFAULT NULL, ` + 210 | // `employerApprove INTEGER DEFAULT 0, ` + 211 | // `employeeApprove INTEGER DEFAULT 0, ` + 212 | // `ExpiryDate NUMERIC DEFAULT NULL` + 213 | // `);`); 214 | // tx.executeSql(`CREATE TABLE IF NOT EXISTS jobs_complete_request (` + 215 | // `requestsID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ` + 216 | // `CreatedDate TEXT NOT NULL DEFAULT NULL, ` + 217 | // `statusID INTEGER NOT NULL DEFAULT 0, ` + 218 | // `StatusDate NUMERIC NOT NULL, ` + 219 | // `jobID INTEGER NOT NULL, ` + 220 | // `bidID INTEGER NOT NULL, ` + 221 | // `entityID INTEGER NOT NULL, ` + 222 | // `salary REAL NOT NULL` + 223 | // `);`); 224 | // tx.executeSql(`CREATE TABLE IF NOT EXISTS jobs_skills (` + 225 | // `JobSkillID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ` + 226 | // `OwnerEntityID INTEGER DEFAULT 0, ` + 227 | // `JobID INTEGER DEFAULT 0, ` + 228 | // `SkillID INTEGER NOT NULL, ` + 229 | // `RatingLevel INTEGER DEFAULT 0, ` + 230 | // `HiredEntityID INTEGER DEFAULT 0` + 231 | // `);`); 232 | tx.executeSql(`CREATE TABLE IF NOT EXISTS skills (` + 233 | `SkillID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ` + 234 | `SkillName TEXT DEFAULT NULL, ` + 235 | `SkillName_he TEXT DEFAULT NULL, ` + 236 | `SkillName_ru TEXT DEFAULT NULL, ` + 237 | `status INTEGER DEFAULT 0, ` + 238 | `costToBidUSD REAL DEFAULT 0, ` + 239 | `SEO_title TEXT DEFAULT NULL, ` + 240 | `SEO_title_he TEXT DEFAULT NULL, ` + 241 | `SEO_title_ru TEXT DEFAULT NULL, ` + 242 | `SEO_description TEXT DEFAULT NULL, ` + 243 | `SEO_description_he TEXT DEFAULT NULL, ` + 244 | `SEO_description_ru TEXT DEFAULT NULL, ` + 245 | `UpdateDate TEXT DEFAULT NULL, ` + 246 | `allow_photo_upload INTEGER DEFAULT 1` + 247 | `);`); 248 | }); 249 | } else { 250 | console.log("None Database in InitDatabase"); 251 | } 252 | }; 253 | 254 | addCategories(db, categories) { 255 | if (db) { 256 | db.transaction((tx) => { 257 | categories.map((category) => { 258 | tx.executeSql(`INSERT INTO categories ( JobCategoryID, ParentID, Level, JobCategoryName, JobsCount, proCount, isLocal, classified, SEO_title, SEO_description) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? );`, [ category.JobCategoryID, category.ParentID, category.Level, category.JobCategoryName, category.JobsCount, category.proCount, category.isLocal, category.classified, category.SEO_title, category.SEO_description ]); 259 | }); 260 | }); 261 | this.getCategories(db); 262 | } else { 263 | console.log("None Database in InitDatabase"); 264 | } 265 | } 266 | 267 | getCategories(db) { 268 | if (db) { 269 | db.transaction((tx) => { 270 | tx.executeSql(`SELECT * FROM categories;`, [], (trans, { rows }) => { 271 | console.log(rows); 272 | }); 273 | }); 274 | } else { 275 | console.log("None Database in InitDatabase"); 276 | } 277 | } 278 | 279 | addJobs(db, jobs) { 280 | if (db) { 281 | db.transaction((tx) => { 282 | jobs.map((job) => { 283 | tx.executeSql(`INSERT INTO categories ( JobID, JobCategoryID, EntityID, JobCategoryName, JobsCount, proCount, isLocal, classified, SEO_title, SEO_description) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? );`, [ category.JobCategoryID, category.ParentID, category.Level, category.JobCategoryName, category.JobsCount, category.proCount, category.isLocal, category.classified, category.SEO_title, category.SEO_description ]); 284 | }); 285 | }); 286 | // this.getJobs(db); 287 | } else { 288 | console.log("None Database in InitDatabase"); 289 | } 290 | } 291 | } -------------------------------------------------------------------------------- /src/components/ChatComponents/Chat/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { 3 | View, 4 | Text, 5 | Image, 6 | StyleSheet, 7 | Platform, 8 | Dimensions, 9 | TouchableOpacity, 10 | TouchableHighlight 11 | } from 'react-native' 12 | import PropTypes from 'prop-types' 13 | import Autolink from 'react-native-autolink' 14 | 15 | // local components 16 | import Header from './../../Header' 17 | import Input from './../../Input' 18 | import PriceAsk from './priceask' 19 | import DaysAsk from './daysask' 20 | import TermsChanged from './termschanged' 21 | 22 | 23 | // Icons 24 | import BlueDoubleTick from './../../../../assets/blue-double-tick.png' 25 | import DoubleTick from './../../../../assets/double-tick.png' 26 | import DocxIcon from './../../../../assets/docx.png' 27 | import Download from './../../../../assets/download.png' 28 | import Camera from './../../../../assets/camera-icon.png' 29 | import Clock from './../../../../assets/clock.png' 30 | import Wallet from './../../../../assets/wallet.png' 31 | import SandWatch from './../../../../assets/sand-watch.png' 32 | 33 | // Config 34 | import { normalize, Color } from '../../../global' 35 | 36 | /** 37 | * Chat Component 38 | * 39 | * @version 1.0.0 40 | * @author [Ashwani Arya](https://github.com/ashwaniarya) 41 | */ 42 | 43 | class Chat extends Component { 44 | 45 | state = { 46 | imgWidth: 0, 47 | imgHeight: 0, 48 | } 49 | componentDidMount() { 50 | 51 | if(this.props.image ) 52 | Image.getSize(this.props.image, (width, height) => { 53 | // calculate image width and height 54 | const screenWidth = Dimensions.get('window').width 55 | const scaleFactor = width / screenWidth 56 | const imageHeight = height / scaleFactor 57 | this.setState({imgWidth: screenWidth, imgHeight: imageHeight}) 58 | }) 59 | } 60 | 61 | render(){ 62 | 63 | return({ 65 | 66 | }} 67 | style={[ 68 | styles.container, 69 | styles.shadow, 70 | this.props.context === "outgoing" && { alignItems: 'flex-end' }, 71 | this.props.tail && { marginBottom: 5 }, 72 | this.props.selected && { backgroundColor: Color.color7, opacity: 0.6 } 73 | ]}> 74 | 77 | { this.props.type === "NORMAL" && 82 | 83 | {/* Reply Segment */} 84 | {/* Reply on image */} 85 | { this.props.reply.type === "CHAT_IMAGE" && 91 | 104 | 105 | { this.props.reply.title } 106 | 107 | 108 | 117 |      { this.props.reply.description } 124 | 125 | 126 | { this.props.reply.previewImage && 127 | 138 | } 139 | } 140 | {/* Reply on Chat_Bid */} 141 | { this.props.reply.type === "CHAT_BID" && 147 | 161 | 167 | 168 | { this.props.reply.title } 169 | 170 | 175 | 181 | 188 | 189 | { this.props.reply.bidStatus } 190 | 191 | 192 | 197 | 198 | 203 | 210 | 211 |   { this.props.reply.duration } 218 | 219 | 220 | 226 | 233 | 234 |   ${ this.props.reply.proposedPrice } 241 | 242 | 243 | 244 | { this.props.reply.previewImage && 245 | 256 | } 257 | } 258 | {/* To display link info based on props */} 259 | { this.props.link.url && 267 | 268 | 276 | 277 | 282 | Dribbble 288 | dribbble.com 294 | 295 | } 296 | {/* To display image */} 297 | { this.props.image && 298 | 308 | } 309 | {/* To display document */} 310 | { this.props.document.type && 312 | { this.props.document.previewImage && } 320 | 326 | 327 | 334 | 335 | 336 | { this.props.document.name } 342 | 343 | 344 | 351 | 352 | 353 | } 354 | {/* To display chat text */} 355 | {this.props.text !== '' && 358 | 361 | } 362 | {/* To display timesamp and doc information */} 363 | 364 | 365 | {this.props.document.type && 366 | {this.props.document.pages} page{this.props.document.pages > 1 && 's'} • { this.props.document.type.toUpperCase() } • { this.props.document.size } mb 367 | } 368 | 369 | { this.props.timestamp } 370 | {this.props.isRead === false || this.props.isRead === true ? 371 | 378 | : null } 379 | 380 | 381 | 382 | } 383 | { this.props.type === "PRICE_ASK" && } 389 | { this.props.type === "DAYS_ASK" && } 395 | { this.props.type === "TERMS_CHANGED" && } 401 | 402 | ) 403 | } 404 | } 405 | 406 | // Default Props 407 | Chat.defaultProps = { 408 | context: 'outgoing', 409 | reply: { 410 | // Can be CHAT_IMAGE, CHAT_BID, CHAT_NORMAL or null 411 | type: null, 412 | title: '', 413 | bidStatus: '', 414 | proposedPrice : 0, 415 | description: '', 416 | days: 0, 417 | previewImage : null 418 | }, 419 | text: '', 420 | timestamp: '', 421 | image : null, 422 | link: { 423 | previewImage: null, 424 | title: '', 425 | domain: '', 426 | url: null 427 | }, 428 | document: { 429 | type: null, 430 | uri: '', 431 | previewImage: null, 432 | pages: 0, 433 | size: 0, 434 | name: '' 435 | }, 436 | tail: false, 437 | isRead: null, 438 | inputPrice: '', 439 | inputDays: '', 440 | newPrice: 0, 441 | newDuration: 0, 442 | // Will take 'NORMAL', 'PRICE_ASK', 'DAYS_ASK', 'TERMS_CHANGED' as value 443 | type: 'NORMAL', 444 | onPressDone: null, 445 | onChangePrice: null, 446 | onChangeDays: null, 447 | onPressYes: null, 448 | onPressNo: null 449 | } 450 | 451 | // Prop types 452 | Chat.propTypes = { 453 | /** 454 | * Make chat component left or right based on context 455 | */ 456 | context: PropTypes.oneOf([ 'outgoing', 'incoming' ]), 457 | /** Message to be rendered */ 458 | text: PropTypes.string, 459 | /** To show time 460 | * You must pass the time as string like 12 min, 5h 461 | */ 462 | timestamp: PropTypes.string, 463 | /** Used when image is attached */ 464 | image: PropTypes.string, 465 | /** Used to replay a message. Check default Props for more info 466 | */ 467 | reply: PropTypes.object, 468 | /** Whether to show tail or not */ 469 | tail: PropTypes.bool, 470 | /** What to do when download button is pressed */ 471 | onPressDownload : PropTypes.func, 472 | isRead: PropTypes.oneOf([ true, false, null ]), 473 | type: PropTypes.oneOf([ 'NORMAL', 'PRICE_ASK', 'DAYS_ASK', 'TERMS_CHANGED' ]) 474 | } 475 | 476 | const styles = StyleSheet.create({ 477 | container: { 478 | marginBottom: 0, 479 | paddingHorizontal: 10 480 | }, 481 | messageContainer: { 482 | padding: 5, 483 | marginVertical: 5, 484 | width: Dimensions.get('window').width-50, 485 | }, 486 | outgoing: { 487 | borderTopLeftRadius: 10, 488 | borderTopRightRadius: 10, 489 | borderBottomLeftRadius: 10, 490 | backgroundColor: '#D5FFCE' 491 | }, 492 | incoming: { 493 | borderTopLeftRadius: 10, 494 | borderTopRightRadius: 10, 495 | borderBottomRightRadius: 10, 496 | backgroundColor: 'white' 497 | }, 498 | shadow : Platform.os === "ios" ? { 499 | shadowColor: "#000", 500 | shadowOffset: { 501 | width: 0, 502 | height: 2, 503 | }, 504 | shadowOpacity: 0.25, 505 | shadowRadius: 3.84, 506 | } : { 507 | elevation: 5 508 | }, 509 | chatboxText: { 510 | fontSize: 16, 511 | color: "#3D3D3D", 512 | lineHeight: 21 513 | }, 514 | chatboxFooterAbsolute: { 515 | position: 'absolute', 516 | bottom: 10, 517 | right: 10 518 | }, 519 | chatboxFooterTimeStamp : { 520 | fontSize: 12, 521 | flexDirection: 'row' 522 | } 523 | }); 524 | 525 | export default Chat --------------------------------------------------------------------------------