Added swipable list to work items list
This commit is contained in:
3
.prettierrc
Normal file
3
.prettierrc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"semi": false,
|
||||||
|
}
|
||||||
5
mobile/package-lock.json
generated
5
mobile/package-lock.json
generated
@@ -5520,6 +5520,11 @@
|
|||||||
"react-native-animatable": "1.2.4"
|
"react-native-animatable": "1.2.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-native-swipe-list-view": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-swipe-list-view/-/react-native-swipe-list-view-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-JVWEoFFEn/qSWHlWaPyz7HdoCCyHr/ifxOOmOhs/s4rmm+d3C7suJucBhllbYcwSG7s19WqtV2Ia0iEl+pK4Gg=="
|
||||||
|
},
|
||||||
"react-proxy": {
|
"react-proxy": {
|
||||||
"version": "1.1.8",
|
"version": "1.1.8",
|
||||||
"resolved": "https://registry.npmjs.org/react-proxy/-/react-proxy-1.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/react-proxy/-/react-proxy-1.1.8.tgz",
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
"react-native-keyboard-spacer": "^0.4.1",
|
"react-native-keyboard-spacer": "^0.4.1",
|
||||||
"react-native-maps": "^0.20.1",
|
"react-native-maps": "^0.20.1",
|
||||||
"react-native-modal": "^5.4.0",
|
"react-native-modal": "^5.4.0",
|
||||||
|
"react-native-swipe-list-view": "^1.0.7",
|
||||||
"react-router-native": "^4.2.0",
|
"react-router-native": "^4.2.0",
|
||||||
"react-viro": "^2.4.0",
|
"react-viro": "^2.4.0",
|
||||||
"socket.io-client": "^2.0.4"
|
"socket.io-client": "^2.0.4"
|
||||||
|
|||||||
@@ -57,7 +57,8 @@ class API extends EventEmitter {
|
|||||||
this.user = user
|
this.user = user
|
||||||
this.connectSocket()
|
this.connectSocket()
|
||||||
this.emit('login')
|
this.emit('login')
|
||||||
}).catch(() => {
|
}).catch((err) => {
|
||||||
|
console.error(err)
|
||||||
AsyncStorage.removeItem(authTokenName)
|
AsyncStorage.removeItem(authTokenName)
|
||||||
this.token = null
|
this.token = null
|
||||||
this.user = {}
|
this.user = {}
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ import { Route, Redirect } from 'react-router-native'
|
|||||||
|
|
||||||
export const DefaultRoute = () => {
|
export const DefaultRoute = () => {
|
||||||
// NOTE: When working on the app, change this to the page you are working on
|
// NOTE: When working on the app, change this to the page you are working on
|
||||||
return <Route render={() => (<Redirect to={'/workitem'} />)} />
|
return <Route render={() => (<Redirect to={'/workitemlist'} />)} />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,31 @@
|
|||||||
import React from 'react';
|
import React from "react"
|
||||||
import { Platform, StyleSheet, Text, Image, Switch, TextInput,
|
import {
|
||||||
KeyboardAvoidingView, View, Button } from 'react-native'
|
Platform,
|
||||||
import { MessageModal } from '../Modal'
|
StyleSheet,
|
||||||
import logoImage from './images/deighton.png'
|
Text,
|
||||||
import { FormBinder } from 'react-form-binder'
|
Image,
|
||||||
import { api } from '../API'
|
Switch,
|
||||||
import { BoundSwitch, BoundInput, BoundButton } from '../ui'
|
TextInput,
|
||||||
import autobind from 'autobind-decorator'
|
View,
|
||||||
|
Button
|
||||||
|
} from "react-native"
|
||||||
|
import { MessageModal } from "../Modal"
|
||||||
|
import logoImage from "./images/deighton.png"
|
||||||
|
import { FormBinder } from "react-form-binder"
|
||||||
|
import { api } from "../API"
|
||||||
|
import { BoundSwitch, BoundInput, BoundButton } from "../ui"
|
||||||
|
import KeyboardSpacer from "react-native-keyboard-spacer"
|
||||||
|
import autobind from "autobind-decorator"
|
||||||
|
|
||||||
export class Login extends React.Component {
|
export class Login extends React.Component {
|
||||||
static bindings = {
|
static bindings = {
|
||||||
email: {
|
email: {
|
||||||
alwaysGet: true,
|
alwaysGet: true,
|
||||||
isValid: (r, v) => (v !== '')
|
isValid: (r, v) => v !== ""
|
||||||
},
|
},
|
||||||
password: {
|
password: {
|
||||||
alwaysGet: true,
|
alwaysGet: true,
|
||||||
isValid: (r, v) => (v !== '')
|
isValid: (r, v) => v !== ""
|
||||||
},
|
},
|
||||||
rememberMe: {
|
rememberMe: {
|
||||||
alwaysGet: true,
|
alwaysGet: true,
|
||||||
@@ -25,49 +34,49 @@ export class Login extends React.Component {
|
|||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
noValue: true,
|
noValue: true,
|
||||||
isDisabled: (r) => (!(r.anyModified && r.allValid))
|
isDisabled: r => !(r.anyModified && r.allValid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = StyleSheet.create({
|
static styles = StyleSheet.create({
|
||||||
page: {
|
page: {
|
||||||
minHeight: '50%',
|
minHeight: "50%",
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: '#fff',
|
backgroundColor: "#fff",
|
||||||
alignItems: 'center',
|
alignItems: "center",
|
||||||
justifyContent: 'center',
|
justifyContent: "center"
|
||||||
},
|
},
|
||||||
logo: {
|
logo: {
|
||||||
width: '50%'
|
width: "50%"
|
||||||
},
|
},
|
||||||
inputRow: {
|
inputRow: {
|
||||||
paddingTop: 10,
|
paddingTop: 10,
|
||||||
width: '60%',
|
width: "60%",
|
||||||
flexDirection: 'column',
|
flexDirection: "column",
|
||||||
justifyContent: 'flex-end',
|
justifyContent: "flex-end",
|
||||||
alignItems: 'flex-start',
|
alignItems: "flex-start"
|
||||||
},
|
},
|
||||||
switchRow: {
|
switchRow: {
|
||||||
paddingTop: 10,
|
paddingTop: 10,
|
||||||
width: '60%',
|
width: "60%",
|
||||||
flexDirection: 'row',
|
flexDirection: "row",
|
||||||
justifyContent: 'flex-end',
|
justifyContent: "flex-end",
|
||||||
alignItems: 'center'
|
alignItems: "center"
|
||||||
},
|
},
|
||||||
buttonRow: {
|
buttonRow: {
|
||||||
paddingTop: 10,
|
paddingTop: 10,
|
||||||
width: '60%',
|
width: "60%",
|
||||||
flexDirection: 'row',
|
flexDirection: "row",
|
||||||
justifyContent: 'flex-end',
|
justifyContent: "flex-end",
|
||||||
alignItems: 'center'
|
alignItems: "center"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
binder: new FormBinder({email: 'john@lyon-smith.org'}, Login.bindings),
|
binder: new FormBinder({ email: "john@lyon-smith.org" }, Login.bindings),
|
||||||
messageModal: null,
|
messageModal: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,14 +86,19 @@ export class Login extends React.Component {
|
|||||||
let { history } = this.props
|
let { history } = this.props
|
||||||
|
|
||||||
if (obj) {
|
if (obj) {
|
||||||
api.login(obj.email, obj.password, obj.rememberMe).then((user) => {
|
api
|
||||||
history.replace('/home')
|
.login(obj.email, obj.password, obj.rememberMe)
|
||||||
}).catch((error) => {
|
.then(user => {
|
||||||
this.setState({ messageModal: {
|
history.replace("/home")
|
||||||
icon: 'hand',
|
})
|
||||||
message: 'Unable to login',
|
.catch(error => {
|
||||||
detail: error.message,
|
this.setState({
|
||||||
}})
|
messageModal: {
|
||||||
|
icon: "hand",
|
||||||
|
message: "Unable to login",
|
||||||
|
detail: error.message
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,28 +112,55 @@ export class Login extends React.Component {
|
|||||||
const { messageModal } = this.state
|
const { messageModal } = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KeyboardAvoidingView style={Login.styles.page} behavior='padding'
|
<View style={Login.styles.page} behavior="padding">
|
||||||
keyboardVerticalOffset={Platform.select({ios: 0, android: -220})}>
|
<Image
|
||||||
<Image style={Login.styles.logo} source={logoImage} resizeMode='contain' />
|
style={Login.styles.logo}
|
||||||
|
source={logoImage}
|
||||||
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
<View style={Login.styles.inputRow}>
|
<View style={Login.styles.inputRow}>
|
||||||
<BoundInput name='email' label='Email:' placeholder='name@xyz.com' message='Must enter a valid email' binder={this.state.binder} />
|
<BoundInput
|
||||||
|
name="email"
|
||||||
|
label="Email:"
|
||||||
|
placeholder="name@xyz.com"
|
||||||
|
message="Must enter a valid email"
|
||||||
|
binder={this.state.binder}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={Login.styles.inputRow}>
|
<View style={Login.styles.inputRow}>
|
||||||
<BoundInput name='password' password label='Password:' message='Must supply a password' binder={this.state.binder} />
|
<BoundInput
|
||||||
|
name="password"
|
||||||
|
password
|
||||||
|
label="Password:"
|
||||||
|
message="Must supply a password"
|
||||||
|
binder={this.state.binder}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={Login.styles.switchRow}>
|
<View style={Login.styles.switchRow}>
|
||||||
<BoundSwitch name='rememberMe' binder={this.state.binder} label='Remember Me'/>
|
<BoundSwitch
|
||||||
|
name="rememberMe"
|
||||||
|
binder={this.state.binder}
|
||||||
|
label="Remember Me"
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={Login.styles.buttonRow}>
|
<View style={Login.styles.buttonRow}>
|
||||||
<BoundButton title='Login' name='login' width='100%' onPress={this.handleLogin} binder={this.state.binder} />
|
<BoundButton
|
||||||
|
title="Login"
|
||||||
|
name="login"
|
||||||
|
width="100%"
|
||||||
|
onPress={this.handleLogin}
|
||||||
|
binder={this.state.binder}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
<MessageModal
|
<MessageModal
|
||||||
open={!!messageModal}
|
open={!!messageModal}
|
||||||
icon={messageModal ? messageModal.icon : ''}
|
icon={messageModal ? messageModal.icon : ""}
|
||||||
message={messageModal ? messageModal.message : ''}
|
message={messageModal ? messageModal.message : ""}
|
||||||
detail={messageModal ? messageModal.detail : ''}
|
detail={messageModal ? messageModal.detail : ""}
|
||||||
onDismiss={messageModal && this.handleMessageDismiss} />
|
onDismiss={messageModal && this.handleMessageDismiss}
|
||||||
</KeyboardAvoidingView>
|
/>
|
||||||
|
<KeyboardSpacer />
|
||||||
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React from 'react'
|
import React from "react"
|
||||||
import {
|
import {
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
View,
|
View,
|
||||||
@@ -9,9 +9,9 @@ import {
|
|||||||
KeyboardAvoidingView,
|
KeyboardAvoidingView,
|
||||||
Platform,
|
Platform,
|
||||||
TouchableOpacity
|
TouchableOpacity
|
||||||
} from 'react-native'
|
} from "react-native"
|
||||||
import MapView, { Marker } from 'react-native-maps'
|
import MapView, { Marker } from "react-native-maps"
|
||||||
import { FormBinder } from 'react-form-binder'
|
import { FormBinder } from "react-form-binder"
|
||||||
import {
|
import {
|
||||||
BoundInput,
|
BoundInput,
|
||||||
BoundButton,
|
BoundButton,
|
||||||
@@ -19,51 +19,54 @@ import {
|
|||||||
Icon,
|
Icon,
|
||||||
Header,
|
Header,
|
||||||
PhotoButton,
|
PhotoButton,
|
||||||
BoundOptionStrip,
|
BoundOptionStrip
|
||||||
} from '../ui'
|
} from "../ui"
|
||||||
import { MessageModal } from '../Modal'
|
import { MessageModal } from "../Modal"
|
||||||
import autobind from 'autobind-decorator'
|
import autobind from "autobind-decorator"
|
||||||
import { ifIphoneX, isIphoneX } from 'react-native-iphone-x-helper'
|
import { ifIphoneX, isIphoneX } from "react-native-iphone-x-helper"
|
||||||
import KeyboardSpacer from 'react-native-keyboard-spacer'
|
import KeyboardSpacer from "react-native-keyboard-spacer"
|
||||||
import { api } from '../API'
|
import { api } from "../API"
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flexDirection: 'column',
|
flexDirection: "column",
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
backgroundColor: '#DDDDDD',
|
backgroundColor: "#DDDDDD"
|
||||||
},
|
},
|
||||||
panel: {
|
panel: {
|
||||||
width: '94%',
|
width: "94%",
|
||||||
backgroundColor: 'white',
|
backgroundColor: "white",
|
||||||
alignSelf: 'center',
|
alignSelf: "center",
|
||||||
marginTop: '3%',
|
marginTop: "3%",
|
||||||
shadowColor: 'gray',
|
shadowColor: "gray",
|
||||||
shadowOffset: { width: 2, height: 2 },
|
shadowOffset: { width: 2, height: 2 },
|
||||||
shadowRadius: 2,
|
shadowRadius: 2,
|
||||||
shadowOpacity: .5,
|
shadowOpacity: 0.5,
|
||||||
padding: 10,
|
padding: 10
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
marginBottom: 4,
|
marginBottom: 4
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const workItemOptions = [
|
const workItemOptions = [
|
||||||
{ value: 'order', text: 'Work Order' },
|
{ value: "order", text: "Work Order" },
|
||||||
{ value: 'inspection', text: 'Inspection' },
|
{ value: "inspection", text: "Inspection" },
|
||||||
{ value: 'complaint', text: 'Complaint' }
|
{ value: "complaint", text: "Complaint" }
|
||||||
]
|
]
|
||||||
|
|
||||||
const latLngToString = (lat, lng) => (`${Math.abs(lng).toFixed(4)}°${lng > 0 ? 'S' : 'N'}, ${Math.abs(lat).toFixed(4)}°${lat > 0 ? 'W' : 'E'}`)
|
const latLngToString = (lat, lng) =>
|
||||||
const latLngStringToPoint = (str) => {
|
`${Math.abs(lng).toFixed(4)}°${lng > 0 ? "S" : "N"}, ${Math.abs(lat).toFixed(
|
||||||
const parts = str.split(', ')
|
4
|
||||||
|
)}°${lat > 0 ? "W" : "E"}`
|
||||||
|
const latLngStringToPoint = str => {
|
||||||
|
const parts = str.split(", ")
|
||||||
return {
|
return {
|
||||||
type: 'Point',
|
type: "Point",
|
||||||
coordinates: [
|
coordinates: [
|
||||||
new Number(parts[0].substring(0, parts[0].length - 2)),
|
new Number(parts[0].substring(0, parts[0].length - 2)),
|
||||||
new Number(parts[1].substring(0, parts[1].length - 2)),
|
new Number(parts[1].substring(0, parts[1].length - 2))
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,19 +75,19 @@ export class WorkItem extends React.Component {
|
|||||||
static bindings = {
|
static bindings = {
|
||||||
header: {
|
header: {
|
||||||
noValue: true,
|
noValue: true,
|
||||||
isDisabled: (r) => (!(r.anyModified && r.allValid)),
|
isDisabled: r => !(r.anyModified && r.allValid)
|
||||||
},
|
},
|
||||||
location: {
|
location: {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
isDisabled: true,
|
isDisabled: true
|
||||||
},
|
},
|
||||||
details: {
|
details: {
|
||||||
isValid: (r, v) => (v !== ''),
|
isValid: (r, v) => v !== ""
|
||||||
},
|
},
|
||||||
workItemType: {
|
workItemType: {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
initValue: 'order',
|
initValue: "order",
|
||||||
alwaysGet: true,
|
alwaysGet: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +95,7 @@ export class WorkItem extends React.Component {
|
|||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
binder: new FormBinder({}, WorkItem.bindings),
|
binder: new FormBinder({}, WorkItem.bindings),
|
||||||
messageModal: null,
|
messageModal: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +106,7 @@ export class WorkItem extends React.Component {
|
|||||||
if (history.length > 1) {
|
if (history.length > 1) {
|
||||||
history.goBack()
|
history.goBack()
|
||||||
} else {
|
} else {
|
||||||
history.replace('/home')
|
history.replace("/home")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,24 +118,34 @@ export class WorkItem extends React.Component {
|
|||||||
obj.location = latLngStringToPoint(obj.location)
|
obj.location = latLngStringToPoint(obj.location)
|
||||||
|
|
||||||
if (!obj._id) {
|
if (!obj._id) {
|
||||||
api.createWorkItem(obj).then((workItem) => {
|
api
|
||||||
|
.createWorkItem(obj)
|
||||||
|
.then(workItem => {
|
||||||
this.handleBackPress()
|
this.handleBackPress()
|
||||||
}).catch((error) => {
|
})
|
||||||
this.setState({ messageModal: {
|
.catch(error => {
|
||||||
icon: 'hand',
|
this.setState({
|
||||||
message: 'Unable to create work item',
|
messageModal: {
|
||||||
detail: error.message,
|
icon: "hand",
|
||||||
}})
|
message: "Unable to create work item",
|
||||||
|
detail: error.message
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
api.updateWorkItem(obj).then((workItem) => {
|
api
|
||||||
|
.updateWorkItem(obj)
|
||||||
|
.then(workItem => {
|
||||||
this.handleBackPress()
|
this.handleBackPress()
|
||||||
}).catch((error) => {
|
})
|
||||||
this.setState({ messageModal: {
|
.catch(error => {
|
||||||
icon: 'hand',
|
this.setState({
|
||||||
message: 'Unable to update work item',
|
messageModal: {
|
||||||
detail: error.message,
|
icon: "hand",
|
||||||
}})
|
message: "Unable to update work item",
|
||||||
|
detail: error.message
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,7 +159,12 @@ export class WorkItem extends React.Component {
|
|||||||
handleRegionChange(region) {
|
handleRegionChange(region) {
|
||||||
const { binder } = this.state
|
const { binder } = this.state
|
||||||
|
|
||||||
this.setState(binder.updateFieldValue('location', latLngToString(region.latitude, region.longitude)))
|
this.setState(
|
||||||
|
binder.updateFieldValue(
|
||||||
|
"location",
|
||||||
|
latLngToString(region.latitude, region.longitude)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -156,54 +174,75 @@ export class WorkItem extends React.Component {
|
|||||||
<View style={{ flex: 1 }}>
|
<View style={{ flex: 1 }}>
|
||||||
<BoundHeader
|
<BoundHeader
|
||||||
binder={binder}
|
binder={binder}
|
||||||
name='header'
|
name="header"
|
||||||
title='Work Item'
|
title="Work Item"
|
||||||
leftButton={{ icon: 'back', onPress: this.handleBackPress }}
|
leftButton={{ icon: "back", onPress: this.handleBackPress }}
|
||||||
rightButton={{ icon: 'done', onPress: this.handleDonePress }} />
|
rightButton={{ icon: "done", onPress: this.handleDonePress }}
|
||||||
|
/>
|
||||||
<ScrollView style={styles.container}>
|
<ScrollView style={styles.container}>
|
||||||
<View style={styles.panel}>
|
<View style={styles.panel}>
|
||||||
<BoundOptionStrip binder={binder} name='workItemType' label='Work Item Type:' options={workItemOptions} />
|
<BoundOptionStrip
|
||||||
|
binder={binder}
|
||||||
|
name="workItemType"
|
||||||
|
label="Work Item Type:"
|
||||||
|
options={workItemOptions}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.panel}>
|
<View style={styles.panel}>
|
||||||
<BoundInput binder={binder} name='details' lines={4} label='Details:' message='You must supply details for the work item' />
|
<BoundInput
|
||||||
|
binder={binder}
|
||||||
|
name="details"
|
||||||
|
lines={4}
|
||||||
|
label="Details:"
|
||||||
|
message="You must supply details for the work item"
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.panel}>
|
<View style={styles.panel}>
|
||||||
<MapView
|
<MapView
|
||||||
style={{
|
style={{
|
||||||
flexDirection: 'column',
|
flexDirection: "column",
|
||||||
justifyContent: 'center',
|
justifyContent: "center",
|
||||||
width: '100%',
|
width: "100%",
|
||||||
height: 400,
|
height: 400,
|
||||||
marginBottom: 10,
|
marginBottom: 10
|
||||||
}}
|
}}
|
||||||
zoomControlEnabled
|
zoomControlEnabled
|
||||||
initialRegion={{
|
initialRegion={{
|
||||||
latitude: 43.653908,
|
latitude: 43.653908,
|
||||||
longitude: -79.384293,
|
longitude: -79.384293,
|
||||||
latitudeDelta: 0.0922,
|
latitudeDelta: 0.0922,
|
||||||
longitudeDelta: 0.0421,
|
longitudeDelta: 0.0421
|
||||||
}}
|
}}
|
||||||
onRegionChange={this.handleRegionChange}>
|
onRegionChange={this.handleRegionChange}
|
||||||
<Icon name='target' size={24} style={{ alignSelf: 'center' }} pointerEvents={false} />
|
>
|
||||||
|
<Icon
|
||||||
|
name="target"
|
||||||
|
size={24}
|
||||||
|
style={{ alignSelf: "center" }}
|
||||||
|
pointerEvents={false}
|
||||||
|
/>
|
||||||
</MapView>
|
</MapView>
|
||||||
<BoundInput binder={binder} name='location' label='Location:' />
|
<BoundInput binder={binder} name="location" label="Location:" />
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.panel}>
|
<View style={styles.panel}>
|
||||||
<Text style={styles.label}>Pictures:</Text>
|
<Text style={styles.label}>Pictures:</Text>
|
||||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
<View
|
||||||
|
style={{ flexDirection: "row", justifyContent: "space-between" }}
|
||||||
|
>
|
||||||
<PhotoButton />
|
<PhotoButton />
|
||||||
<PhotoButton />
|
<PhotoButton />
|
||||||
<PhotoButton />
|
<PhotoButton />
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{ isIphoneX ? <View style={{ height: 30, width: '100%' }} /> : null }
|
{isIphoneX ? <View style={{ height: 30, width: "100%" }} /> : null}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<MessageModal
|
<MessageModal
|
||||||
open={!!messageModal}
|
open={!!messageModal}
|
||||||
icon={messageModal ? messageModal.icon : ''}
|
icon={messageModal ? messageModal.icon : ""}
|
||||||
message={messageModal ? messageModal.message : ''}
|
message={messageModal ? messageModal.message : ""}
|
||||||
detail={messageModal ? messageModal.detail : ''}
|
detail={messageModal ? messageModal.detail : ""}
|
||||||
onDismiss={messageModal && this.handleMessageDismiss} />
|
onDismiss={messageModal && this.handleMessageDismiss}
|
||||||
|
/>
|
||||||
<KeyboardSpacer />
|
<KeyboardSpacer />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,53 +1,136 @@
|
|||||||
import React from 'react'
|
import React from "react"
|
||||||
import { StyleSheet, View, TouchableOpacity, Image, FlatList, Text} from 'react-native'
|
import {
|
||||||
import { Icon, Header } from '../ui'
|
StyleSheet,
|
||||||
import autobind from 'autobind-decorator'
|
View,
|
||||||
|
TouchableHighlight,
|
||||||
|
TouchableOpacity,
|
||||||
|
Image,
|
||||||
|
FlatList,
|
||||||
|
Text
|
||||||
|
} from "react-native"
|
||||||
|
import { Icon, Header } from "../ui"
|
||||||
|
import { MessageModal } from "../Modal"
|
||||||
|
import autobind from "autobind-decorator"
|
||||||
|
import { SwipeListView } from "react-native-swipe-list-view"
|
||||||
|
import { api } from "../API"
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
height: '100%',
|
height: "100%",
|
||||||
width: '100%',
|
width: "100%",
|
||||||
justifyContent: 'flex-start',
|
justifyContent: "flex-start",
|
||||||
backgroundColor: '#FFFFFF',
|
backgroundColor: "#FFFFFF"
|
||||||
},
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
{key: '1', type: 'work', location: 'Ossington Ave. | 0.2 mi.', state: 'open', latlng: { latitude: 43.653226, longitude: -79.383184 } },
|
{
|
||||||
{key: '2', type: 'inspection', location: 'Alexandre St. | 0.7 mi.', state: 'open', latlng: { latitude: 43.648118, longitude: 79.392636 }},
|
key: "1",
|
||||||
{key: '3', type: 'complaint', location: 'Bay St. | 0.8 mi.', state: 'open', latlng: { latitude: 43.640168, longitude: -79.409373 }},
|
type: "work",
|
||||||
{key: '4', type: 'work', location: 'Bloor St. | 1.2 mi.', state: 'open', latlng: { latitude: 43.633110, longitude: -79.415880 }},
|
location: "Ossington Ave. | 0.2 mi.",
|
||||||
{key: '5', type: 'inspection', location: 'Blue Jays Way | 2.2 mi.', state: 'open', latlng: { latitude: 43.653526, longitude: -79.361385 }},
|
state: "open",
|
||||||
{key: '6', type: 'complaint', location: 'Christie St. | 3.0 mi.', state: 'open', latlng: { latitude: 43.663870, longitude: -79.383705 }},
|
latlng: { latitude: 43.653226, longitude: -79.383184 }
|
||||||
{key: '7', type: 'work', location: 'Cummer Ave. | 4.2 mi.', state: 'open', latlng: { latitude: 43.659166, longitude: -79.391350 }},
|
},
|
||||||
{key: '8', type: 'complaint', location: 'Danforth Ave. | 4.7 mi.', state: 'open', latlng: { latitude: 43.663538, longitude: -79.423212 }},
|
{
|
||||||
|
key: "2",
|
||||||
|
type: "inspection",
|
||||||
|
location: "Alexandre St. | 0.7 mi.",
|
||||||
|
state: "open",
|
||||||
|
latlng: { latitude: 43.648118, longitude: 79.392636 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "3",
|
||||||
|
type: "complaint",
|
||||||
|
location: "Bay St. | 0.8 mi.",
|
||||||
|
state: "open",
|
||||||
|
latlng: { latitude: 43.640168, longitude: -79.409373 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "4",
|
||||||
|
type: "work",
|
||||||
|
location: "Bloor St. | 1.2 mi.",
|
||||||
|
state: "open",
|
||||||
|
latlng: { latitude: 43.63311, longitude: -79.41588 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "5",
|
||||||
|
type: "inspection",
|
||||||
|
location: "Blue Jays Way | 2.2 mi.",
|
||||||
|
state: "open",
|
||||||
|
latlng: { latitude: 43.653526, longitude: -79.361385 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "6",
|
||||||
|
type: "complaint",
|
||||||
|
location: "Christie St. | 3.0 mi.",
|
||||||
|
state: "open",
|
||||||
|
latlng: { latitude: 43.66387, longitude: -79.383705 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "7",
|
||||||
|
type: "work",
|
||||||
|
location: "Cummer Ave. | 4.2 mi.",
|
||||||
|
state: "open",
|
||||||
|
latlng: { latitude: 43.659166, longitude: -79.39135 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "8",
|
||||||
|
type: "complaint",
|
||||||
|
location: "Danforth Ave. | 4.7 mi.",
|
||||||
|
state: "open",
|
||||||
|
latlng: { latitude: 43.663538, longitude: -79.423212 }
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const inspectionTypes = {
|
const inspectionTypes = {
|
||||||
work: {
|
work: {
|
||||||
title: 'Work Order'
|
title: "Work Order"
|
||||||
},
|
},
|
||||||
inspection: {
|
inspection: {
|
||||||
title: 'Inspection',
|
title: "Inspection"
|
||||||
},
|
},
|
||||||
complaint: {
|
complaint: {
|
||||||
title: 'Complaint',
|
title: "Complaint"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class WorkItemList extends React.Component {
|
export class WorkItemList extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
messageModal: null
|
||||||
|
}
|
||||||
|
api
|
||||||
|
.listWorkItems()
|
||||||
|
.then(list => {})
|
||||||
|
.catch(() => {
|
||||||
|
this.setState({
|
||||||
|
messageModal: {
|
||||||
|
icon: "hand",
|
||||||
|
message: "Unable to get list of work items",
|
||||||
|
detail: error.message
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
handleItemSelect(item, index) {
|
handleItemSelect(item, index) {
|
||||||
this.props.history.push('/activity')
|
this.props.history.push("/workitem")
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleItemDelete(item, index) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleMessageDismiss() {
|
||||||
|
this.setState({ messageModal: null })
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
handleAddPress(item, index) {
|
handleAddPress(item, index) {
|
||||||
this.props.history.push('/workitem')
|
this.props.history.push("/workitem")
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
@@ -57,31 +140,85 @@ export class WorkItemList extends React.Component {
|
|||||||
if (history.length > 1) {
|
if (history.length > 1) {
|
||||||
history.goBack()
|
history.goBack()
|
||||||
} else {
|
} else {
|
||||||
history.replace('/home')
|
history.replace("/home")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { messageModal } = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Header title='Work Items' leftButton={{ icon: 'back', onPress: this.handleBackPress }} rightButton={{ icon: 'add', onPress: this.handleAddPress }} />
|
<Header
|
||||||
<FlatList
|
title="Work Items"
|
||||||
style={{ width: '100%', flexGrow: 1, paddingTop: 20, paddingBottom: 20 }}
|
leftButton={{ icon: "back", onPress: this.handleBackPress }}
|
||||||
|
rightButton={{ icon: "add", onPress: this.handleAddPress }}
|
||||||
|
/>
|
||||||
|
<SwipeListView
|
||||||
|
useFlatList
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
flexGrow: 1,
|
||||||
|
paddingTop: 20,
|
||||||
|
paddingBottom: 20
|
||||||
|
}}
|
||||||
data={data}
|
data={data}
|
||||||
renderItem={({item, index}) => {
|
renderItem={({ item, index }) => (
|
||||||
return (
|
<TouchableHighlight
|
||||||
<View style={{ flexDirection: 'row', height: 50 }}>
|
style={{
|
||||||
<Text style={{ fontSize: 8, width: 45, marginLeft: 15, alignSelf: 'center' }}>{item.state.toUpperCase()}</Text>
|
height: 50,
|
||||||
<View style={{ flexDirection: 'column', width: '75%' }}>
|
paddingLeft: 20,
|
||||||
<Text style={{ fontSize: 20 }}>{inspectionTypes[item.type].title}</Text>
|
paddingRight: 20,
|
||||||
<Text style={{ fontSize: 14, color: 'gray' }}>{item.location}</Text>
|
backgroundColor: "white",
|
||||||
|
}}
|
||||||
|
underlayColor='#EEEEEE'
|
||||||
|
onPress={() => this.handleItemSelect(item, index)}
|
||||||
|
>
|
||||||
|
<View style={{ height: '100%', width: '100%', flexDirection: 'row' }}>
|
||||||
|
<View style={{ flexGrow: 1, flexDirection: "column", justifyContent: 'center' }}>
|
||||||
|
<Text style={{ fontSize: 20 }}>
|
||||||
|
{inspectionTypes[item.type].title}
|
||||||
|
</Text>
|
||||||
|
<Text style={{ fontSize: 14, color: "gray" }}>
|
||||||
|
{item.location}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<Icon
|
||||||
|
name="rightArrow"
|
||||||
|
size={16}
|
||||||
|
style={{ alignSelf: "center" }}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</TouchableHighlight>
|
||||||
|
)}
|
||||||
|
renderHiddenItem={({ item, index }) => (
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
height: 50,
|
||||||
|
backgroundColor: "red",
|
||||||
|
}}
|
||||||
|
onPress={() => this.handleItemDelete(item, index)}
|
||||||
|
>
|
||||||
|
<View style={{ flexDirection: 'column', justifyContent: 'center', backgroundColor: "red", width: 75 }}>
|
||||||
|
<Text style={{ fontSize: 20, alignSelf: "center" }}>
|
||||||
|
Delete
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<TouchableOpacity style={{ alignSelf: 'center' }} onPress={() => (this._handleItemSelect(item, index))} >
|
|
||||||
<Icon name='rightArrow' size={16} />
|
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
)}
|
||||||
)
|
rightOpenValue={-80}
|
||||||
}} />
|
stopLeftSwipe={100}
|
||||||
|
disableRightSwipe
|
||||||
|
/>
|
||||||
|
<MessageModal
|
||||||
|
open={!!messageModal}
|
||||||
|
icon={messageModal ? messageModal.icon : ""}
|
||||||
|
message={messageModal ? messageModal.message : ""}
|
||||||
|
detail={messageModal ? messageModal.detail : ""}
|
||||||
|
onDismiss={messageModal && this.handleMessageDismiss}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,7 +172,6 @@ export class Login extends Component {
|
|||||||
</Column.Item>
|
</Column.Item>
|
||||||
<Column.Item grow>
|
<Column.Item grow>
|
||||||
<WaitModal active={waitModal} message='Logging in...' />
|
<WaitModal active={waitModal} message='Logging in...' />
|
||||||
|
|
||||||
<MessageModal error open={!!messageModal}
|
<MessageModal error open={!!messageModal}
|
||||||
icon={messageModal ? messageModal.icon : ''}
|
icon={messageModal ? messageModal.icon : ''}
|
||||||
message={messageModal ? messageModal.message : ''}
|
message={messageModal ? messageModal.message : ''}
|
||||||
|
|||||||
Reference in New Issue
Block a user