Browse Source

Merge branch 'main' of github.com:IGSD-UoW/WPD-MobileApp into main

master
GabrielTrettel 4 years ago
parent
commit
da7c5a6dce
  1. 17
      src/app.json
  2. 73
      src/app/components/ImageInput.js
  3. 10
      src/app/hooks/useLocation.js
  4. 195
      src/app/screens/PluviometerSharingDataScreen.js
  5. 2155
      src/package-lock.json

17
src/app.json

@ -1,7 +1,7 @@
{ {
"expo": { "expo": {
"name": "src",
"slug": "src",
"name": "wpd-mobileapp",
"slug": "wpd-mobileapp",
"version": "1.0.0", "version": "1.0.0",
"orientation": "portrait", "orientation": "portrait",
"icon": "./app/assets/icon.png", "icon": "./app/assets/icon.png",
@ -13,9 +13,15 @@
"updates": { "updates": {
"fallbackToCacheTimeout": 0 "fallbackToCacheTimeout": 0
}, },
"assetBundlePatterns": ["**/*"],
"assetBundlePatterns": [
"**/*"
],
"ios": { "ios": {
"supportsTablet": true
"supportsTablet": true,
"infoPlist": {
"NSCameraUsageDescription": "Enable Camera Acess so that you can record Videos",
"NSPhotoLibraryUsageDescription": "Enable Camera Roll Access so that you can select Other Videos from Camera Roll"
}
}, },
"android": { "android": {
"adaptiveIcon": { "adaptiveIcon": {
@ -25,6 +31,7 @@
}, },
"web": { "web": {
"favicon": "./app/assets/favicon.png" "favicon": "./app/assets/favicon.png"
}
},
"description": ""
} }
} }

73
src/app/components/ImageInput.js

@ -11,6 +11,7 @@ import {
} from "react-native"; } from "react-native";
import { MaterialCommunityIcons } from "@expo/vector-icons"; import { MaterialCommunityIcons } from "@expo/vector-icons";
import * as ImagePicker from "expo-image-picker"; import * as ImagePicker from "expo-image-picker";
import * as Permissions from "expo-permissions";
import colors from "../config/colors"; import colors from "../config/colors";
function ImageInput({ imageUri, onChangeImage }) { function ImageInput({ imageUri, onChangeImage }) {
@ -18,22 +19,34 @@ function ImageInput({ imageUri, onChangeImage }) {
requestPermission(); requestPermission();
//requestPermissionCamera(); //requestPermissionCamera();
}, []); }, []);
const [modalVisible, setModalVisible] = useState(false);
const requestPermission = async () => {
const { granted } = await ImagePicker.requestCameraRollPermissionsAsync();
if (!granted) alert("Você precisa habilitar permissão para acessar a biblioteca.");
};
const requestPermissionCamera = async () => {
const { granted } = await ImagePicker.requestCameraPermissionsAsync();
/* const requestPermissionCamera = async () => {
const { granted } = await Permissions.askAsync(Permissions.CAMERA);
if(granted) { if(granted) {
launchCamera(); launchCamera();
} }
else if (!granted) alert("Você precisa habilitar permissão para acessar a câmera."); else if (!granted) alert("Você precisa habilitar permissão para acessar a câmera.");
}; };
const launchCamera = async () => {
setModalVisible(false);
try {
const result = await ImagePicker.launchCameraAsync({
allowsEditing: false,
});
if (!result.cancelled) onChangeImage(result.uri)
} catch (error) {
console.log("Erro ao ler imagem", error);
}
};*/
const requestPermission = async () => {
const { granted } = await ImagePicker.requestCameraRollPermissionsAsync();
if (!granted) alert("Você precisa habilitar permissão para acessar a biblioteca.");
};
const handlePress = () => { const handlePress = () => {
if (!imageUri) setModalVisible(true);
if (!imageUri) launchImageLibrary();
else else
Alert.alert("Deletar", "Deseja deletar esta imagem?", [ Alert.alert("Deletar", "Deseja deletar esta imagem?", [
{ text: "Sim", onPress: () => onChangeImage(null) }, { text: "Sim", onPress: () => onChangeImage(null) },
@ -42,7 +55,6 @@ function ImageInput({ imageUri, onChangeImage }) {
}; };
const launchImageLibrary = async () => { const launchImageLibrary = async () => {
setModalVisible(false);
try { try {
const result = await ImagePicker.launchImageLibraryAsync({ const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images, mediaTypes: ImagePicker.MediaTypeOptions.Images,
@ -54,19 +66,6 @@ function ImageInput({ imageUri, onChangeImage }) {
} }
}; };
const launchCamera = async () => {
setModalVisible(false);
try {
const result = await ImagePicker.launchCameraAsync({
allowsEditing: false,
});
if (!result.cancelled) onChangeImage(result.uri)
} catch (error) {
console.log("Erro ao ler imagem", error);
}
};
return ( return (
<View> <View>
<TouchableWithoutFeedback onPress={handlePress}> <TouchableWithoutFeedback onPress={handlePress}>
@ -81,36 +80,6 @@ function ImageInput({ imageUri, onChangeImage }) {
{imageUri && <Image source={{ uri: imageUri }} style={styles.image} />} {imageUri && <Image source={{ uri: imageUri }} style={styles.image} />}
</View> </View>
</TouchableWithoutFeedback> </TouchableWithoutFeedback>
<View >
<Modal style={styles.centeredView}
animationType="slide"
transparent={true}
visible={modalVisible}>
<TouchableWithoutFeedback onPress={() => {
setModalVisible(!setModalVisible);
}}>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<View>
<Text style={styles.modalLabel}>Selecione uma imagem</Text>
<TouchableOpacity style={{ width: 300 }} onPress={requestPermissionCamera}>
<Text style={styles.modalText}>Câmera</Text>
</TouchableOpacity>
<TouchableOpacity style={{ width: 300 }} onPress={launchImageLibrary}>
<Text style={styles.modalText}>Galeria</Text>
</TouchableOpacity>
</View>
<TouchableOpacity style={{ width: 300 }} onPress={() => { setModalVisible(false) }}>
<Text style={{ fontWeight: 'bold', marginTop: 20, fontSize: 14, textAlign: 'center' }}>
Cancelar
</Text>
</TouchableOpacity>
</View>
</View>
</TouchableWithoutFeedback>
</Modal>
</View>
</View> </View>
); );
} }

10
src/app/hooks/useLocation.js

@ -1,20 +1,22 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import * as Location from "expo-location"; import * as Location from "expo-location";
export default function useLocation(
defaultLocation = { longitude: 0.0, latitude: 0.0 }
) {
export default function useLocation(defaultLocation = { longitude: 0.0, latitude: 0.0 }) {
const [location, setLocation] = useState(defaultLocation); const [location, setLocation] = useState(defaultLocation);
const getLocation = async () => { const getLocation = async () => {
try { try {
const { granted } = await Location.requestPermissionsAsync(); const { granted } = await Location.requestPermissionsAsync();
if (!granted) return; if (!granted) return;
const { const {
coords: { latitude, longitude }, coords: { latitude, longitude },
} = await Location.getLastKnownPositionAsync(); } = await Location.getLastKnownPositionAsync();
setLocation({ latitude, longitude }); setLocation({ latitude, longitude });
} catch (error) {
}
catch (error) {
console.log(error); console.log(error);
} }
}; };

195
src/app/screens/PluviometerSharingDataScreen.js

@ -1,6 +1,6 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { StyleSheet, Text, View, Image, ScrollView } from "react-native";
import { StyleSheet, Text, View, Image, ScrollView, Modal, Platform } from "react-native";
import * as Yup from "yup"; import * as Yup from "yup";
import { import {
@ -13,7 +13,7 @@ import Screen from "../components/Screen";
import useLocation from "../hooks/useLocation"; import useLocation from "../hooks/useLocation";
import FormImagePicker from "../components/forms/FormImagePicker"; import FormImagePicker from "../components/forms/FormImagePicker";
import { insertPluviometerData } from "../database/databaseLoader"; import { insertPluviometerData } from "../database/databaseLoader";
import { TouchableOpacity } from "react-native-gesture-handler";
import { TouchableHighlight, TouchableOpacity } from "react-native-gesture-handler";
import DateTimePicker from '@react-native-community/datetimepicker'; import DateTimePicker from '@react-native-community/datetimepicker';
import { FontAwesome5 } from '@expo/vector-icons'; import { FontAwesome5 } from '@expo/vector-icons';
import { showMessage } from "react-native-flash-message"; import { showMessage } from "react-native-flash-message";
@ -33,6 +33,22 @@ function PluviometerSharingDataScreen(props) {
const [date, setDate] = useState(moment(defaultDate)) const [date, setDate] = useState(moment(defaultDate))
const [show, setShow] = useState(false); const [show, setShow] = useState(false);
let dateTime = new Date().toString(); let dateTime = new Date().toString();
//---------------ios------------------------
const onChange = (e, selectedDate) => {
setShow(false);
if (selectedDate) {
setDate(moment(defaultDate));
}
}
const onCancelPress = () => {
setDate(moment(defaultDate));
setShow(false);
}
const onDonePress = () => {
setDate(moment(date));
setShow(false);
}
//-------------------------------------------
const onAndroidChange = (e, selectedDate) => { const onAndroidChange = (e, selectedDate) => {
setShow(false); setShow(false);
@ -42,6 +58,7 @@ function PluviometerSharingDataScreen(props) {
//props.onDateChange(selectedDate); //props.onDateChange(selectedDate);
} }
} }
const renderDatePicker = () => { const renderDatePicker = () => {
return ( return (
<DateTimePicker <DateTimePicker
@ -49,7 +66,7 @@ function PluviometerSharingDataScreen(props) {
value={new Date(date)} value={new Date(date)}
mode="date" mode="date"
maximumDate={new Date()} maximumDate={new Date()}
onChange={onAndroidChange}
onChange={Platform.OS === 'ios' ? onChange : onAndroidChange}
/> />
) )
} }
@ -67,60 +84,113 @@ function PluviometerSharingDataScreen(props) {
</Text> </Text>
</View> </View>
<ScrollView style={styles.container}> <ScrollView style={styles.container}>
<Form
initialValues={{
pluviometer: "",
images: [],
}}
onSubmit={(values) => {
insertPluviometerData({ ...values, dateTime, location });
showMessage({
message: "Informação enviada!",
duration: 1950,
icon: "success",
type: "success",
});
props.navigation.goBack(null);
}}
validationSchema={validationSchema}
>
<View style={{ marginTop: 30 }}>
<Text style={styles.labelStyle}>
Quantidade de chuva:
<Form
initialValues={{
pluviometer: "",
images: [],
}}
onSubmit={(values) => {
insertPluviometerData({ ...values, dateTime, location });
showMessage({
message: "Informação enviada!",
duration: 1950,
icon: "success",
type: "success",
});
props.navigation.goBack(null);
}}
validationSchema={validationSchema}
>
<View style={{ marginTop: 30 }}>
<Text style={styles.labelStyle}>
Quantidade de chuva:
</Text> </Text>
<FormField
keyboardType="number-pad"
maxLength={200}
name="pluviometer"
placeholder="Digite a quantidade de chuva"
width={280}
/>
</View>
<FormField
keyboardType="number-pad"
maxLength={200}
name="pluviometer"
placeholder="Digite a quantidade de chuva"
width={280}
/>
</View>
<View style={{ marginTop: 10, width: 220, borderRadius: 25 }}>
<Text style={styles.labelStyle}>
Data da coleta:
<View style={{ marginTop: 10, width: 220, borderRadius: 25 }}>
<Text style={styles.labelStyle}>
Data da coleta:
</Text> </Text>
<TouchableOpacity style={styles.datepickerStyle}
onPress={() => setShow(true)}>
<View style={styles.datePickerView}>
<Text style={{ fontSize: 16, marginLeft: 15 }}>
{date.format('DD/MM/YYYY')}
</Text>
<FontAwesome5 style={styles.dateIcon} name="calendar-day" size={24} color="grey" />
{show && renderDatePicker()}
</View>
</TouchableOpacity>
</View>
<FormImagePicker
backgroundColor="#1976D2"
name="images"
styles={{ width: 50 }}
/>
<SubmitButton title="Enviar" style={{marginBottom:100}}/>
<View style={{ flex: 1 }}>
</View>
</Form>
<TouchableOpacity style={styles.datepickerStyle}
onPress={() => setShow(true)}>
<View style={styles.datePickerView}>
<View style={{ flexDirection:"row", justifyContent:"space-between", width: 280 }}>
<Text style={{fontSize: 16, marginLeft: 15}}>{date.format('DD/MM/YYYY')}</Text>
<FontAwesome5 style={styles.dateIcon} name="calendar-day" size={24} color="grey" />
</View>
{Platform.OS !== 'ios' && show && renderDatePicker()}
{Platform.OS === 'ios' && show && (
<Modal
transparent={true}
animationType="slide"
visible={show}
supportedOrientations={['portrait']}
onRequestClose={() => setShow(false)}>
<View style={{ flex: 1 }}>
<TouchableHighlight
style={{
flex: 1,
alignItems: 'flex-end',
flexDirection: 'row',
}}
activeOpacity={1}
visible={show}>
onPress={() => setShow(false)}
<TouchableHighlight
underlayColor={''}
style={{
flex: 1,
borderTopColor: 'primary',
borderTopWidth: 1,
}}
onPress={() => console.log('Datepicker press')}>
<View
style={{
backgroundColor: '#f8f8ff',
height: 256,
overflow: 'hidden',
}}>
<View style={{ marginTop:20 }}>
{ renderDatePicker }
</View>
<TouchableHighlight
underlayColor={'transparent'}
onPress={() => onCancelPress()}
style={(styles.btnText, styles.btnCancel)}>
<Text>Cancelar</Text>
</TouchableHighlight>
<TouchableHighlight
underlayColor={'transparent'}
onPress={() => onDonePress()}
style={(styles.btnText, styles.btnDone)}>
<Text>OK</Text>
</TouchableHighlight>
</View>
</TouchableHighlight>
</TouchableHighlight>
</View>
</Modal>
)}
</View>
</TouchableOpacity>
</View>
<FormImagePicker
backgroundColor="#1976D2"
name="images"
styles={{ width: 50 }}
/>
<SubmitButton title="Enviar" style={{ marginBottom: 100 }} />
<View style={{ flex: 1 }}>
</View>
</Form>
</ScrollView> </ScrollView>
</Screen> </Screen>
); );
@ -148,7 +218,7 @@ const styles = StyleSheet.create({
backgroundColor: "#f8f4f4", backgroundColor: "#f8f4f4",
}, },
dateIcon: { dateIcon: {
marginRight: 15,
marginRight: 25,
}, },
labelStyle: { labelStyle: {
fontSize: 16, fontSize: 16,
@ -157,6 +227,21 @@ const styles = StyleSheet.create({
color: "#1976D2", color: "#1976D2",
marginBottom: 5, marginBottom: 5,
}, },
btnText: {
position: "absolute",
top: 0,
height: 42,
paddingHorizontal: 20,
flexDirection: "row",
alignItems: "center",
justifyContent: "center"
},
btnCancel: {
left: 0,
},
btnDone: {
right: 0,
},
}); });
export default PluviometerSharingDataScreen; export default PluviometerSharingDataScreen;

2155
src/package-lock.json
File diff suppressed because it is too large
View File

Loading…
Cancel
Save