김성연

최종보고서 ,소스코드 제출

Showing 127 changed files with 2028 additions and 351 deletions
......@@ -3,4 +3,7 @@
<component name="JavaScriptSettings">
<option name="languageLevel" value="JSX" />
</component>
<component name="ProjectPlainTextFileTypeManager">
<file url="file://$PROJECT_DIR$/render_server_react_native/components/CardComponent.js" />
</component>
</project>
\ No newline at end of file
......
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
<mapping directory="$PROJECT_DIR$/locationTest/expo-location-example" vcs="Git" />
<mapping directory="$PROJECT_DIR$/my-project" vcs="Git" />
<mapping directory="$PROJECT_DIR$/render_server_react_native" vcs="Git" />
......
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WebServers">
<option name="servers">
<webServer id="1b403629-1b05-48f5-aa8c-1b92f496c1d2" name="2019-BigData" url="http://133.186.211.42">
<fileTransfer host="133.186.211.42" port="22" accessType="SFTP">
<advancedOptions>
<advancedOptions dataProtectionLevel="Private" passiveMode="true" shareSSLContext="true" />
</advancedOptions>
<option name="port" value="22" />
</fileTransfer>
</webServer>
</option>
</component>
</project>
\ No newline at end of file
This diff is collapsed. Click to expand it.
PORT=4001
COOKIE_SECRET=test
\ No newline at end of file
This diff is collapsed. Click to expand it.
import React, {useState, useContext, useEffect, useCallback} from 'react';
import {View, Text, Button, TextInput, TouchableOpacity, StyleSheet} from 'react-native';
import {useDispatch, useSelector} from "react-redux";
import {LOG_IN_REQUEST, LOG_OUT_REQUEST} from "../reducers/user";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import {useNavigation} from '@react-navigation/native';
import LoadingComponent from "../components/LoadingComponent";
const MyProfileComponent = () => {
const navigation = useNavigation();
const [loading, setLoading] = useState(true);
const {me} = useSelector(state => state.user);
const {isLoggingIn} = useSelector(state => state.user);
const dispatch = useDispatch();
const onLogout = async () => {
await dispatch({
type: LOG_OUT_REQUEST
});
console.log('onLogout');
};
return (
<View>
<View style={styles.containerStyle}>
<Text style={styles.TextStyle}>마이페이지</Text>
<Text style={styles.TextStyle}>{me.email}</Text>
<Text style={styles.TextStyle}>{me.nickName}</Text>
<TouchableOpacity onPress={onLogout}>
<MaterialCommunityIcons color={'green'} name={'logout'} size={30}/>
</TouchableOpacity>
</View>
</View>
)
};
const styles = StyleSheet.create({
containerStyle: {
marginTop: 10,
alignItems: 'center',
justifyContent: 'center',
},
TextStyle: {
width: 200,
height: 44,
padding: 10,
borderWidth: 1,
borderColor: '#778899',
marginBottom: 10,
}
});
export default MyProfileComponent;
\ No newline at end of file
export const host = '172.20.10.3';
export const coordAPIKEY = 'CDCF07BD-2CE4-33D9-BA13-D6CE4360A2B3';
export const initialState = {
startLocation: null,
finishLocation: null,
settingLocation: false,
info: '',
};
export const SET_LOC_REQUEST = 'SET_LOC_REQUEST';
export const SET_LOC_SUCCESS = 'SET_LOC_SUCCESS';
export const SET_LOC_FAILURE = 'SET_LOC_FAILURE';
export default (state = initialState, action) => {
switch (action.type) {
case SET_LOC_REQUEST: {
return {
...state,
settingLocation: true,
}
}
case SET_LOC_SUCCESS: {
const {startLocation, finishLocation} = action.data;
return {
...state,
startLocation,
finishLocation,
isLoggingIn: false,
};
}
case SET_LOC_FAILURE: {
const {info} = action.data;
return {
...state,
settingLocation: false,
info,
}
}
default: {
return {
...state,
};
}
}
};
\ No newline at end of file
import {all, call, fork, delay, put, takeEvery, takeLatest} from 'redux-saga/effects';
import axios from 'axios';
import {coordAPIKEY} from '../env';
import {
SET_LOC_REQUEST,
SET_LOC_SUCCESS,
SET_LOC_FAILURE,
} from "../reducers/location";
function setLocationAPI(data) {
const {startTextLocation, finishTextLocation} = data;
console.log(startTextLocation, finishTextLocation);
const startRes = axios.get(`http://api.vworld.kr/req/address?service=address&request=getcoord&version=2.0&crs=epsg:4326&address=${startTextLocation}&refine=true&simple=false&format=xml&type=road&key=${coordAPIKEY}`);
const finishRes = axios.get(`http://api.vworld.kr/req/address?service=address&request=getcoord&version=2.0&crs=epsg:4326&address=${finishTextLocation}&refine=true&simple=false&format=xml&type=road&key=${coordAPIKEY}`);
return {startRes, finishRes};
}
function* setLocation(action) {
try {
console.log('saga의 setLocation', action.data);
const res = yield call(setLocationAPI, action.data);
console.log(res.startRes, res.finishRes);
const {result} = res.startRes;
console.log(result);
} catch (e) {
console.error(e);
}
};
function* watchSetLocation() {
console.log('watchSetLocation');
yield takeLatest(SET_LOC_REQUEST, setLocation);
}
export default function* locationSaga() {
yield all([
fork(watchSetLocation),
]);
};
\ No newline at end of file
import React, {useState, useContext, useEffect, useCallback} from 'react';
import {View, Text, Button, TextInput, TouchableOpacity} from 'react-native';
import {useDispatch, useSelector} from "react-redux";
import {LOG_IN_REQUEST, LOG_OUT_REQUEST} from "../reducers/user";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import styled from "styled-components";
import {useNavigation} from '@react-navigation/native';
import LoadingComponent from "../components/LoadingComponent";
import MyProfileComponent from "../components/MyProfileComponent";
import LoginComponent from "../components/LoginComponent";
const Login = () => {
const navigation = useNavigation();
const [loading, setLoading] = useState(true);
const {me} = useSelector(state => state.user);
const {isLoggingIn} = useSelector(state => state.user);
useEffect(() => {
setLoading(false);
}, [me]);
return (
<View>
{me ?
<MyProfileComponent/>
:
<LoginComponent/>
}
</View>
)
};
export default Login;
\ No newline at end of file
import React, {useState, useEffect} from 'react';
import MapView, {Marker} from 'react-native-maps';
import {StyleSheet, Text, View, Dimensions} from 'react-native';
import screen from '../constants/layout';
import StartAndFinishLocationComponent from "../components/CurrentUserLocationComponent";
const Maps = () => {
const [initialRegion, setInitialRegion] = useState(
{
latitude: 37.56647,
longitude: 126.977963,
latitudeDelta: 0.3922,
longitudeDelta: 0.3421
});
return (
<View style={styles.container}>
<Text style={styles.textStyle}>Current User Location</Text>
<StartAndFinishLocationComponent/>
<MapView
style={styles.mapStyle}
initialRegion={initialRegion}
>
<Marker
coordinate={initialRegion}
title="this is a marker"
description="this is a marker example">
</Marker>
</MapView>
</View>
)
};
export default Maps;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
},
mapStyle: {
width: screen.width,
height: screen.height / 2,
},
textStyle: {
fontWeight: 'bold',
fontSize: 20,
color: 'grey',
marginBottom: 20,
}
});
......@@ -9,7 +9,8 @@ npm-debug.*
*.orig.*
web-build/
web-report/
node_modules/
# macOS
.DS_Store
env.js
.env
......
......@@ -9,7 +9,7 @@ import {NavigationContainer} from "@react-navigation/native";
import store from './store';
import StackNavigation from "./navigations/StackNavigation";
import {AuthProvider} from "./AuthContext";
import host from './env';
import {host} from './env';
import axios from "axios";
const cacheImages = (images) => {
......@@ -38,6 +38,7 @@ const App = () => {
);
const fonts = cacheFonts([Ionicons.font]);
// await AsyncStorage.removeItem('cookie');
const cookie = await AsyncStorage.getItem('cookie');
console.log('cookie', cookie);
if (cookie) {
......@@ -66,12 +67,6 @@ const App = () => {
<>
{isReady
?
// <Provider store={store}>
// <NavigationContainer>
// <StatusBar barstyle={'light-content'}/>
// <StackNavigation/>
// </NavigationContainer>
// </Provider>
<Provider store={store}>
<AuthProvider user={user}>
<NavigationContainer>
......
import { Platform, StyleSheet, Dimensions } from "react-native";
const { width, height } = Dimensions.get("window");
const SCREEN_WIDTH = width < height ? width : height;
const numColumns = 2;
export const AppStyles = {
color: {
main: "#5ea23a",
text: "#696969",
title: "#464646",
subtitle: "#545454",
categoryTitle: "#161616",
tint: "#ff5a66",
description: "#bbbbbb",
filterTitle: "#8a8a8a",
starRating: "#2bdf85",
location: "#a9a9a9",
white: "white",
facebook: "#4267b2",
grey: "grey",
greenBlue: "#00aea8",
placeholder: "#a0a0a0",
background: "#f2f2f2",
blue: "#3293fe"
},
fontSize: {
title: 30,
content: 20,
normal: 16
},
buttonWidth: {
main: "70%"
},
textInputWidth: {
main: "80%"
},
fontName: {
main: "Noto Sans",
bold: "Noto Sans"
},
borderRadius: {
main: 25,
small: 5
}
};
export const AppIcon = {
container: {
backgroundColor: "white",
borderRadius: 20,
padding: 8,
marginRight: 10
},
style: {
tintColor: AppStyles.color.tint,
width: 25,
height: 25
},
images: {
home: require("./assets/icons/home.png"),
defaultUser: require("./assets/icons/default_user.jpg"),
logout: require("./assets/icons/shutdown.png")
}
};
export const HeaderButtonStyle = StyleSheet.create({
multi: {
flexDirection: "row"
},
container: {
padding: 10
},
image: {
justifyContent: "center",
width: 35,
height: 35,
margin: 6
},
rightButton: {
color: AppStyles.color.tint,
marginRight: 10,
fontWeight: "normal",
fontFamily: AppStyles.fontName.main
}
});
export const ListStyle = StyleSheet.create({
title: {
fontSize: 16,
color: AppStyles.color.subtitle,
fontFamily: AppStyles.fontName.bold,
fontWeight: "bold"
},
subtitleView: {
minHeight: 55,
flexDirection: "row",
paddingTop: 5,
marginLeft: 10
},
leftSubtitle: {
flex: 2
},
avatarStyle: {
height: 80,
width: 80
}
});
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
[{"index":1,"avgSpeed": 53},{"index":2,"avgSpeed":60}]
\ No newline at end of file
import React, {useState, useContext, useEffect, useCallback} from 'react';
import {Text, View, StyleSheet, TouchableOpacity, ScrollView} from 'react-native';
import {useDispatch, useSelector} from "react-redux";
import {useNavigation} from '@react-navigation/native';
import styled from "styled-components";
import {AntDesign, MaterialCommunityIcons} from "@expo/vector-icons";
const Banner = styled.View`
flex: 1;
margin-left: 15px;
margin-bottom: 5px;
width: 3px;
height: 3px;
border-radius: 20px;
border: 3px solid #88c600;
`;
const BusPathComponent = (props) => {
const navigation = useNavigation();
const [busPath, setBusPath] = useState(null);
const [seeStaList, setSeeStaList] = useState(false);
const {pathDetail} = props;
const changeSeeStaList = () => {
setSeeStaList(!seeStaList);
console.log(seeStaList)
};
useEffect(() => {
console.log(props.pathDetail);
setBusPath(props.pathDetail);
}, []);
return (
<ScrollView>
<View style={{flexDirection: 'row', flex: 5}}>
<View style={styles.pathType}>
<MaterialCommunityIcons style={{flex: 1}} color={'#88c600'} name={'bus'} size={20}/>
<Text style={{flex: 1, fontSize: 13}}>{pathDetail.time}</Text>
</View>
<View style={{flex: 1}}>
<Banner/>
<Banner/>
<Banner/>
<Banner/>
<Banner/>
<Banner/>
<Banner/>
</View>
<View style={styles.inputTile}>
<Text style={styles.stationStyle}>{pathDetail.startName}</Text>
<Text style={styles.idStyle}>{pathDetail.startID}</Text>
{pathDetail.arrivalInfo.map((bus, index) => {
return (
<View>
<Text style={styles.busStyle}>{bus.busNo}</Text>
{bus.msg.msg1.indexOf('undefined') !== -1 ?
null
:
<>
<Text style={styles.busSubStyle}>{bus.msg.msg1}</Text>
</>
}
{bus.msg.msg2.indexOf('undefined') !== -1 ?
null
:
<>
<Text style={styles.busSubStyle}>{bus.msg.msg2}</Text>
</>
}
</View>
)
})}
<View style={styles.stationListStyle}>
<Text style={styles.cntStyle}>{pathDetail.stationCnt} 정류소 이동</Text>
<TouchableOpacity style={{flex: 1, marginTop: 17}} onPress={changeSeeStaList}>
<AntDesign color={'darkgrey'} name={'caretdown'} size={15}/>
</TouchableOpacity>
</View>
<View>
{seeStaList === true ?
<View>
{pathDetail.stationList.map((bus, index) => {
return (
<>
<Text>{bus.stationName}</Text>
</>
)
})}
</View>
:
null
}
</View>
<Text style={styles.stationStyle}>{pathDetail.endName}</Text>
</View>
</View>
</ScrollView>
);
}
export default BusPathComponent;
const styles = StyleSheet.create({
inputTile: {
marginLeft: 6,
flex: 4,
color: 'grey',
},
inputText: {
fontWeight: 'normal',
fontSize: 15,
},
pathType: {
flexDirection: 'column',
flex: 0.4,
alignItems: 'center',
justifyContent: 'center',
marginLeft: 5,
marginTop: 10,
},
stationStyle: {
fontWeight: 'bold',
fontSize: 15,
},
idStyle: {
marginTop: 3,
marginBottom: 20,
color: 'grey',
fontSize: 14
},
busStyle: {
fontWeight: 'bold',
fontSize: 14,
color: '#88c600'
},
cntStyle: {
flex: 1,
marginTop: 20,
marginBottom: 3,
color: 'grey',
fontSize: 14
},
stationListStyle: {
flexDirection: 'row',
flex: 1,
},
busSubStyle: {
marginTop: 2,
fontSize: 12,
color: 'red',
}
})
\ No newline at end of file
import React, {useState, useContext, useEffect, useCallback} from 'react';
import {View, Text, Button, Image, TouchableOpacity, StyleSheet, Platform} from 'react-native';
import {useDispatch, useSelector} from "react-redux";
import {LOG_IN_REQUEST, LOG_OUT_REQUEST} from "../reducers/user";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import {useNavigation} from '@react-navigation/native';
import DateTimePicker from '@react-native-community/datetimepicker';
import {SET_TIME_SUCCESS} from "../reducers/location";
import moment from "moment";
const DateTimePickerComponent = (props) => {
const [date, setDate] = useState(new Date());
const [mode, setMode] = useState('time');
const {goToMapsClick} = props;
const onChange = (event, selectedDate) => {
const currentDate = selectedDate || date;
console.log(currentDate);
setDate(currentDate);
};
// SET FINISH TIME
const dispatch = useDispatch();
const onSubmit = async () => {
if (!date) {
return
}
console.log('SET_TIME_SUCCESS GO!!', date);
await dispatch({
type: SET_TIME_SUCCESS,
data: {
date
}
});
};
useEffect(() => {
if (goToMapsClick === true) {
console.log(goToMapsClick);
console.log('goToMapsClick!');
onSubmit();
}
setDate(date);
}, [goToMapsClick, date]);
return (
<View>
<DateTimePicker
testID="dateTimePicker"
value={date}
mode={mode}
is24Hour={true}
display="default"
onChange={onChange}
style={styles.TextStyle}
/>
</View>
);
};
const styles = StyleSheet.create({
containerStyle: {
marginTop: 10,
alignItems: 'center',
justifyContent: 'center',
},
TextStyle: {
flex: 1,
marginBottom: 240,
}
});
export default DateTimePickerComponent;
import React, {useState, useEffect} from 'react';
import {Text, View, StyleSheet, TouchableOpacity, ScrollView} from 'react-native';
import styled from 'styled-components';
import {MaterialCommunityIcons, AntDesign} from '@expo/vector-icons';
import {useNavigation} from '@react-navigation/native';
const ShowDetail = styled.TouchableOpacity`
flex: 2;
position: absolute;
right: 6px;
bottom: 2px;
width: 30px;
height: 30px;
border-radius: 50px;
`;
const Banner = styled.View`
flex: 1;
margin-left: 15px;
margin-bottom: 5px;
width: 3px;
height: 3px;
border-radius: 20px;
border: 3px solid #273b96;
`;
const GoPathSummary = (props) => {
const navigation = useNavigation();
const [pathSummary, setPathSummary] = useState(null);
const goPathDetail = () => {
navigation.navigate('GoPathDetail', {'detail': props.detail});
};
useEffect
(() => {
console.log(props.summary);
setPathSummary(props.summary);
}, []);
return (
<View>
{pathSummary ?
<>
<View style={styles.container}>
<View style={styles.titleParagraph}>
<Text style={styles.hourStyle}>{pathSummary.hour1} {pathSummary.min1} 출발
<Text style={styles.conditionStyle}>정확</Text>
</Text>
<Text style={styles.hourStyle}>{pathSummary.hour2} {pathSummary.min2} 출발
<Text style={styles.conditionStyle}>여유</Text>
</Text>
</View>
<View style={{flexDirection: 'row', flex: 2, marginLeft: 70}}>
<Text style={{flex: 1, fontSize: 13, fontWeight: 'bold'}}>총소요시간: {pathSummary.totalTime}</Text>
<Text style={{flex: 1, fontSize: 13, fontWeight: 'bold'}}>비용: {pathSummary.payment}</Text>
</View>
<View style={{flexDirection: 'row', flex: 5, marginLeft: 70, marginTop: 20}}>
<View style={styles.pathType}>
<MaterialCommunityIcons style={{flex: 1}} color={'#273b96'} name={'train'} size={20}/>
</View>
<View style={styles.inputTile}>
<Text style={styles.stationStyle}>{pathSummary.firstStartStation}</Text>
<Text style={styles.stationStyle}>{pathSummary.lastEndStation}</Text>
</View>
</View>
<View style={{position: 'absolute', right: 10}}>
<ShowDetail onPress={goPathDetail}>
<AntDesign color={'darkgrey'} name={'caretright'} size={32}/>
</ShowDetail>
</View>
</View>
</>
:
null
}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
paddingTop: 40,
paddingBottom: 30,
backgroundColor: '#ecf0f1',
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: 'darkgrey',
},
paragraph: {
flex: 1,
fontSize: 14,
fontWeight: 'bold',
textAlign: 'center',
color: '#34495e',
},
titleParagraph: {
flexDirection: 'column',
flex: 1,
},
inputTile: {
marginLeft: 6,
flex: 4,
color: 'grey',
},
inputText: {
fontWeight: 'normal',
fontSize: 15,
},
pathType: {
flexDirection: 'column',
flex: 0.4,
alignItems: 'center',
justifyContent: 'center',
marginLeft: 5,
marginTop: 10,
},
stationStyle: {
fontWeight: 'bold',
fontSize: 15,
},
idStyle: {
marginTop: 3,
marginBottom: 20,
color: 'grey',
fontSize: 14
},
laneStyle: {
fontWeight: 'bold',
fontSize: 15,
color: '#EBA900'
},
cntStyle: {
flex: 1,
marginTop: 20,
marginBottom: 3,
color: 'grey',
fontSize: 14
},
stationListStyle: {
flexDirection: 'row',
flex: 1,
},
hourStyle: {
flexDirection: 'row',
flex: 1,
fontSize: 18,
fontWeight: 'bold',
marginBottom: 20,
},
conditionStyle: {
paddingLeft: 10,
fontSize: 15,
color: 'red',
}
});
export default GoPathSummary;
\ No newline at end of file
import React, {useState, useContext, useEffect, useCallback} from 'react';
import {Text, View, StyleSheet, TouchableOpacity, ScrollView} from 'react-native';
import {useDispatch, useSelector} from "react-redux";
import {useNavigation} from '@react-navigation/native';
import styled from "styled-components";
import {AntDesign, MaterialCommunityIcons} from "@expo/vector-icons";
const Banner = styled.View`
flex: 1;
margin-left: 15px;
margin-bottom: 5px;
width: 3px;
height: 3px;
border-radius: 20px;
border: 3px solid #EBA900;
`;
const LanePathComponent = (props) => {
const navigation = useNavigation();
const [lanePath, setLanePath] = useState(null);
const [seeLaneList, setSeeLaneList] = useState(false);
const {pathDetail} = props;
const changeSeeLaneList = () => {
setSeeLaneList(!seeLaneList);
console.log(seeLaneList)
};
useEffect(() => {
console.log(props.pathDetail);
setLanePath(props.pathDetail);
}, []);
return (
<ScrollView>
<View style={{flexDirection: 'row', flex: 5}}>
<View style={styles.pathType}>
<MaterialCommunityIcons style={{flex: 1}} color={'#EBA900'} name={'train'} size={20}/>
<Text style={{flex: 1, fontSize: 13}}>{pathDetail.time}</Text>
</View>
<View style={{flex: 1}}>
<Banner/>
<Banner/>
<Banner/>
<Banner/>
<Banner/>
<Banner/>
<Banner/>
</View>
<View style={styles.inputTile}>
<Text style={styles.stationStyle}>{pathDetail.startName}</Text>
<Text style={styles.idStyle}>{pathDetail.startID}</Text>
{pathDetail.laneList.map((lane, index) => {
return (
<Text style={styles.laneStyle}>{lane.name}</Text>
)
})}
<View style={styles.stationListStyle}>
<Text style={styles.cntStyle}>{pathDetail.stationCnt} 정류소 이동</Text>
<TouchableOpacity style={{flex: 1, marginTop: 17}} onPress={changeSeeLaneList}>
<AntDesign color={'darkgrey'} name={'caretdown'} size={15}/>
</TouchableOpacity>
</View>
{seeLaneList === true ?
<View>
{pathDetail.stationList.map((lane, index) => {
return (
<Text>{lane}</Text>
)
})}
</View>
:
null
}
<Text style={styles.stationStyle}>{pathDetail.endName}</Text>
</View>
</View>
</ScrollView>
);
}
export default LanePathComponent;
const styles = StyleSheet.create({
inputTile: {
marginLeft: 6,
flex: 4,
color: 'grey',
},
inputText: {
fontWeight: 'normal',
fontSize: 15,
},
pathType: {
flexDirection: 'column',
flex: 0.4,
alignItems: 'center',
justifyContent: 'center',
marginLeft: 5,
marginTop: 10,
},
stationStyle: {
fontWeight: 'bold',
fontSize: 15,
},
idStyle: {
marginTop: 3,
marginBottom: 20,
color: 'grey',
fontSize: 14
},
laneStyle: {
fontWeight: 'bold',
fontSize: 15,
color: '#EBA900'
},
cntStyle: {
flex: 1,
marginTop: 20,
marginBottom: 3,
color: 'grey',
fontSize: 14
},
stationListStyle: {
flexDirection: 'row',
flex: 1,
}
})
\ No newline at end of file
......@@ -13,4 +13,6 @@ const LoadingComponent = () => {
)
};
export default LoadingComponent;
\ No newline at end of file
......
......@@ -2,11 +2,9 @@ import React, {useState, useContext, useEffect, useCallback} from 'react';
import {View, Text, Button, StyleSheet, TextInput, TouchableOpacity} from 'react-native';
import {useDispatch, useSelector} from "react-redux";
import {LOG_IN_REQUEST, LOG_OUT_REQUEST} from "../reducers/user";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import styled from "styled-components";
import {useNavigation} from '@react-navigation/native';
import LoadingComponent from "../components/LoadingComponent";
import SignUpComponent from "./SignUpComponent";
import Profile from "../screens/Profile";
const LoginButton = styled.TouchableOpacity`
......@@ -16,6 +14,20 @@ const LoginButton = styled.TouchableOpacity`
height: 40px;
background-color: #e6e6fa;
border: 1px;
marginBottom: 10px;
border-radius: 50px;
`;
const SignUpButton = styled.TouchableOpacity`
align-items: center;
justify-content: center;
width: 60px;
height: 40px;
background-color: #e6e6fa;
border: 1px;
border-radius: 50px;
`;
......@@ -49,8 +61,17 @@ const LoginComponent = () => {
password
}
});
};
const goSignUp = () => {
navigation.navigate('SignUp');
}
useEffect(() => {
if (me) {
navigation.navigate('Profile');
}
}, [me]);
useEffect(() => {
setLoading(false);
......@@ -77,17 +98,22 @@ const LoginComponent = () => {
onPress={onSubmit}>
<Text style={{color: '#696969'}}>Login</Text>
</LoginButton>
<SignUpButton
title={'Login'}
onPress={goSignUp}>
<Text style={{color: '#696969'}}>SignUp</Text>
</SignUpButton>
</View>
)
};
const styles = StyleSheet.create({
containerStyle: {
flex: 1,
// flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ecf0f1',
marginTop: 100,
// justifyContent: 'center',
// backgroundColor: '#ecf0f1',
// marginTop: 100,
},
input: {
width: 200,
......
import React, {useState, useContext, useEffect, useCallback} from 'react';
import {View, Text, Button, Image, TouchableOpacity, StyleSheet, Alert} from 'react-native';
import {useDispatch, useSelector} from "react-redux";
import {LOG_IN_REQUEST, LOG_OUT_REQUEST} from "../reducers/user";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import {useNavigation} from '@react-navigation/native';
import {SET_PERVELOCITY_SUCCESS} from "../reducers/location";
import Login from "../screens/Login";
import Papa from 'papaparse';
const MyProfileComponent = () => {
const navigation = useNavigation();
const [loading, setLoading] = useState(true);
const [numRecord, setNumRecord] = useState(0);
const {me} = useSelector(state => state.user);
const {isLoggingIn} = useSelector(state => state.user);
//
// const downloadFile = async () => {
// const uri = "https://www.mapmyfitness.com/workout/export/csv";
// let fileUri = FileSystem.documentDirectory + "userVelocity.txt";
// FileSystem.downloadAsync(uri, fileUri)
// .then(({uri}) => {
// saveFile(uri);
// })
// .catch(error => {
// console.error(error);
// })
// }
//
// const saveFile = async (fileUri) => {
// const {status} = await Permissions.askAsync(Permissions.CAMERA_ROLL);
// if (status === "granted") {
// const asset = await MediaLibrary.createAssetAsync(fileUri)
// await MediaLibrary.createAlbumAsync("Download", asset, false)
// }
// }
const dispatch = useDispatch();
const loadPersonalVelocity = async () => {
try {
const userVelocity = require('../assets/userFile/userVelocity');
var allAvgSpeed = 0;
setNumRecord(userVelocity.length);
userVelocity.map((i, index) => {
allAvgSpeed = allAvgSpeed + i.avgSpeed;
});
var personalVelocity = parseInt(allAvgSpeed / userVelocity.length);
await dispatch({
type: SET_PERVELOCITY_SUCCESS,
data: {
personalVelocity: personalVelocity
}
});
Alert.alert(
'MAP 사용자 평균 속도 설정',
` 사용자 평균 속도를 설정하였습니다. `,
[
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
style: 'cancel',
},
{text: 'OK', onPress: () => console.log('OK Pressed')},
],
{cancelable: false}
);
} catch (e) {
console.log(e);
}
};
useEffect(() => {
setNumRecord(0);
}, []);
useEffect(() => {
console.log(numRecord)
}, [numRecord]);
const onLogout = async () => {
await dispatch({
type: LOG_OUT_REQUEST
});
console.log('onLogout');
};
return (
<View>
{me ?
<View>
<View style={{flexDirection: 'row', paddingTop: 15}}>
<View style={{flex: 1, alignItems: 'center'}}>
<Image source={{url: 'https://steemitimages.com/u/anpigon/avatar'}}
style={{width: 75, height: 75, borderRadius: 37.5}}/>
</View>
<View style={{flex: 3}}>
<View style={{flexDirection: 'row', justifyContent: 'space-around', marginTop: 12}}>
<View style={{alignItems: 'center'}}>
<Text style={{fontSize: 15, fontWeight: 'bold'}}>{me.email}</Text>
<Text style={{fontSize: 10, color: 'gray'}}>email</Text>
</View>
<View style={{alignItems: 'center'}}>
<Text style={{fontSize: 15, fontWeight: 'bold'}}>{me.nickName}</Text>
<Text style={{fontSize: 10, color: 'gray'}}>nickName</Text>
</View>
<View style={{alignItems: 'center'}}>
<Text style={{fontSize: 15, fontWeight: 'bold'}}>{numRecord}</Text>
<Text style={{fontSize: 10, color: 'gray'}}>numRecord</Text>
</View>
</View>
<View style={{flexDirection: 'row'}}>
<TouchableOpacity
onPress={loadPersonalVelocity}
style={{
flex: 4,
marginLeft: 10,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
borderColor: 'black',
height: 30,
marginTop: 17
}}>
<Text style={{fontSize: 13}}>load personal velocity</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={onLogout}
style={{
borderColor: 'black',
borderWidth: 1,
flex: 1,
marginRight: 10,
marginLeft: 5,
justifyContent: 'center',
alignItems: 'center',
height: 30,
marginTop: 17
}}>
<MaterialCommunityIcons color={'black'} name={'logout'} size={20}/>
</TouchableOpacity>
</View>
</View>
</View>
< View style={{paddingHorizontal: 20, paddingVertical: 10}}>
</View>
</View>
:
<View style={{alignItems: 'center', justifyContent: 'center', marginTop: 200}}>
<Text style={{fontSize: 30, textAlign: 'center', fontWeight: 'bold'}}>유저 정보가 없습니다.</Text>
</View>
}
</View>
)
};
const styles = StyleSheet.create({
containerStyle: {
marginTop: 10,
alignItems: 'center',
justifyContent: 'center',
},
TextStyle: {
width: 200,
height: 44,
padding: 10,
borderWidth: 1,
borderColor: '#778899',
marginBottom: 10,
}
});
export default MyProfileComponent;
\ No newline at end of file
import React, {useState, useContext, useEffect, useCallback} from 'react';
import {View, Text, Button, TextInput, TouchableOpacity} from 'react-native';
import {View, Text, Button, TextInput, TouchableOpacity, StyleSheet} from 'react-native';
import {useDispatch, useSelector} from "react-redux";
import {SIGN_UP_REQUEST} from "../reducers/user";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import styled from "styled-components";
import {useNavigation} from '@react-navigation/native';
import LoadingComponent from "../components/LoadingComponent";
import Profile from "../screens/Profile";
const SignUpButton = styled.TouchableOpacity`
align-items: center;
justify-content: center;
width: 60px;
height: 60px;
background-color: #ffffff;
height: 40px;
background-color: #e6e6fa;
border: 1px;
marginBottom: 10px;
border-radius: 50px;
`;
const GoLoginButton = styled.TouchableOpacity`
align-items: center;
justify-content: center;
width: 60px;
height: 40px;
background-color: #e6e6fa;
border: 1px;
border-radius: 50px;
`;
const SignUpComponent = () => {
const navigation = useNavigation();
const [email, setEmail] = useState('');
......@@ -49,39 +61,59 @@ const SignUpComponent = () => {
password
}
});
if (me !== null) {
navigation.navigate('Profile');
}
};
return (
<>
<View>
<View>
<TextInput
style={{height: 40, marginLeft: 10}}
placeholder="Type here to Email!"
onChangeText={onChangeEmail}
/>
</View>
<View>
<TextInput
style={{height: 40, marginLeft: 10}}
placeholder="Type here to nickname!"
onChangeText={onChangeNickName}
/>
</View>
<View>
<TextInput
style={{height: 40, marginLeft: 10}}
placeholder="Type here to password!"
type="password"
onChangeText={onChangePassword}
/>
</View>
<SignUpButton title={'회원가입'} onPress={onSubmit}>
<Text>회원가입</Text>
</SignUpButton>
</View>
</>
<View styles={styles.containerStyle}>
<TextInput
style={styles.input}
placeholder="Type here to Email!"
onChangeText={onChangeEmail}
/>
<TextInput
style={styles.input}
placeholder="Type here to nickname!"
onChangeText={onChangeNickName}
/>
<TextInput
style={styles.input}
placeholder="Type here to password!"
type="password"
onChangeText={onChangePassword}
/>
<SignUpButton
title={'signUp'}
onPress={onSubmit}>
<Text style={{color: '#696969'}}>signUp</Text>
</SignUpButton>
<GoLoginButton
title={'signUp'}
onPress={onSubmit}>
<Text style={{color: '#696969'}}>Login</Text>
</GoLoginButton>
</View>
)
};
export default SignUpComponent;
\ No newline at end of file
export default SignUpComponent;
const styles = StyleSheet.create({
containerStyle: {
// flex: 1,
alignItems: 'center',
// justifyContent: 'center',
// backgroundColor: '#ecf0f1',
// marginTop: 100,
},
input: {
width: 200,
height: 44,
padding: 10,
borderWidth: 1,
borderColor: '#778899',
marginBottom: 10,
}
});
\ No newline at end of file
......
import React, {useState, useEffect} from 'react';
import MapView, {Marker} from 'react-native-maps';
import {StyleSheet, Text, TextInput, View, TouchableOpacity} from 'react-native';
import {StyleSheet, Text, TextInput, View, TouchableOpacity, Alert} from 'react-native';
import screen from '../constants/layout';
import {useSelector, useDispatch} from "react-redux";
import * as Location from 'expo-location';
import {set} from "react-native-reanimated";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import {SET_LOC_REQUEST} from "../reducers/location";
import {SET_ELOC_REQUEST, SET_LOC_REQUEST, SET_SLOC_REQUEST, SET_USER_LOC} from "../reducers/location";
import axios from 'axios';
const StartAndFinishLocationComponent = () => {
const [hasPermission, setHasPermission] = useState(false);
const [startTextLocation, setStartTextLocation] = useState('');
const [finishTextLocation, setFinishTextLocation] = useState('');
const [endTextLocation, setEndTextLocation] = useState('');
const [userLocation, setUserLocation] = useState(null);
const [errorMsg, setErrorMsg] = useState(null);
const onChangeStartLocation = async (startTextLocation) => {
const onChangeStartLocation = (startTextLocation) => {
setStartTextLocation(startTextLocation);
};
const onChangeFinishLocation = (finishTextLocation) => {
setFinishTextLocation(finishTextLocation);
const onChangeFinishLocation = (endTextLocation) => {
setEndTextLocation(endTextLocation);
};
const dispatch = useDispatch();
const setLocation = async () => {
if (!startTextLocation || !finishTextLocation) {
return
const onSetUserLocation = async () => {
const {status} = await Location.requestPermissionsAsync();
if (status !== 'granted') {
setErrorMsg('Permission to access location was denied')
}
console.log(startTextLocation, finishTextLocation);
const location = await Location.getCurrentPositionAsync({});
setStartTextLocation('현위치');
setUserLocation(location);
console.log(location);
await dispatch({
type: SET_LOC_REQUEST,
type: SET_USER_LOC,
data: {
userLocation
}
});
};
const setLocation = async () => {
if (startTextLocation && startTextLocation !== '현위치') {
console.log(startTextLocation);
await dispatch({
type: SET_SLOC_REQUEST,
data: {
startTextLocation,
finishTextLocation
startTextLocation
}
}
)
})
}
if (endTextLocation) {
console.log(endTextLocation);
await dispatch({
type: SET_ELOC_REQUEST,
data: {
endTextLocation
}
}
)
}
Alert.alert(
'MAP ROUTE 설정',
` 출발지 ${startTextLocation}, 목적지 ${endTextLocation} 맞습니까? `,
[
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
style: 'cancel',
},
{text: 'OK', onPress: () => console.log('OK Pressed')},
],
{cancelable: false}
);
};
return (
<View style={styles.container}>
<View style={styles.input}>
<Text style={styles.textStyle}>출발지</Text>
<MaterialCommunityIcons color={'red'} name={'map-marker'} size={26}/>
<TextInput
style={styles.inputText}
onChangeText={onChangeStartLocation}
value={startTextLocation}
/>
<TouchableOpacity>
<MaterialCommunityIcons color={'grey'} name={'map-marker'} size={30}/>
<TouchableOpacity onPress={onSetUserLocation}>
<MaterialCommunityIcons color={'grey'} name={'crosshairs-gps'} size={30}/>
</TouchableOpacity>
</View>
<View style={styles.input}>
<Text style={styles.textStyle}>도착지</Text>
<MaterialCommunityIcons color={'blue'} name={'map-marker'} size={26}/>
<TextInput
style={styles.inputText}
onChangeText={onChangeFinishLocation}
value={endTextLocation}
/>
</View>
<View style={{flexDirection: 'row'}}>
<View style={{flexDirection: 'row', alignItems: 'center'}}>
<TouchableOpacity style={styles.buttonStyle} onPress={setLocation}>
<Text>MAP설정</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonStyle}>
<Text>사용자최적경로검색</Text>
<Text>Map설정</Text>
</TouchableOpacity>
</View>
</View>
......@@ -76,20 +115,23 @@ export default StartAndFinishLocationComponent;
const styles = StyleSheet.create({
container: {
alignItems: 'center',
marginTop: 50,
marginLeft: 20,
marginRight: 20,
opacity: 0.5,
},
input: {
borderRadius: 10,
backgroundColor: 'lightgrey',
backgroundColor: '#f0f8ff',
paddingLeft: 10,
paddingRight: 10,
width: 300,
height: 40,
height: 50,
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'space-between',
borderBottomColor: '#bbb',
borderBottomColor: '#f0f8ff',
marginBottom: 10
// borderBottomWidth: StyleSheet.hairlineWidth,
},
......@@ -102,15 +144,15 @@ const styles = StyleSheet.create({
marginRight: 15,
},
buttonStyle: {
flex: 1,
backgroundColor: '#ecf0f1',
flex: 0.5,
backgroundColor: '#f0f8ff',
alignItems: 'center',
justifyContent: 'center',
width: 30,
width: 10,
height: 30,
borderWidth: 1,
borderColor: 'black',
marginBottom: 20
borderColor: 'grey',
marginBottom: 20,
borderRadius: 30
}
});
......
import React, {useState, useContext, useEffect, useCallback} from 'react';
import {Text, View, StyleSheet, TouchableOpacity, ScrollView, TextInput} from 'react-native';
import {useDispatch, useSelector} from "react-redux";
import {useNavigation} from '@react-navigation/native';
import styled from "styled-components";
import {MaterialCommunityIcons, AntDesign} from '@expo/vector-icons';
const Banner = styled.View`
flex: 1;
margin-left: 15px;
margin-bottom: 5px;
width: 3px;
height: 3px;
border-radius: 20px;
border: 3px solid grey;
`;
const WalkPathComponent = (props) => {
const navigation = useNavigation();
const [walkPath, setWalkPath] = useState(null);
const {pathDetail} = props;
useEffect(() => {
console.log(props.pathDetail.distance);
setWalkPath(props.pathDetail);
}, []);
return (
<ScrollView>
<View style={{flexDirection: 'row', flex: 5}}>
<View style={styles.pathType}>
<MaterialCommunityIcons style={{flex: 1}} color={'darkgrey'} name={'walk'} size={20}/>
<Text style={{flex: 1, fontSize: 13}}>{pathDetail.time}</Text>
</View>
<View style={{flex: 1}}>
<Banner/>
<Banner/>
<Banner/>
<Banner/>
<Banner/>
<Banner/>
<Banner/>
</View>
<View style={styles.inputTile}>
<Text style={styles.inputText}> 도보 {pathDetail.distance}m 이동</Text>
</View>
</View>
</ScrollView>
);
}
export default WalkPathComponent;
const styles = StyleSheet.create({
inputTile: {
flex: 4,
justifyContent: 'center',
color: 'grey',
},
inputText: {
fontWeight: 'normal',
fontSize: 15,
},
pathType: {
flexDirection: 'column',
flex: 0.4,
alignItems: 'center',
justifyContent: 'center',
marginLeft: 5,
marginTop: 10,
}
})
\ No newline at end of file
import React, {userLayoutEffect} from 'react';
import {createStackNavigator} from "@react-navigation/stack";
import TabNavigation from "./TabNavigation";
import SelectOrTakePhotoTabNavigation from "./SelectOrTakePhotoTabNavigation";
import UploadPhoto from "../screens/UploadPhoto";
const Stack = createStackNavigator();
const SelectOrTakePhotoStackNavigation = () =>{
const SelectOrTakePhotoStackNavigation = () => {
return (
<Stack.Navigator
mode='card'
screenOptions={{
headerShown: false
}}
>
<Stack.Screen
name='SelectOrTakePhotoTabNavigation'
component={SelectOrTakePhotoTabNavigation}
/>
name='SelectOrTakePhotoTabNavigation'
component={SelectOrTakePhotoTabNavigation}
/>
<Stack.Screen
name='UploadPhoto'
component={UploadPhoto}
......
import React, {userLayoutEffect} from 'react';
import {createStackNavigator} from "@react-navigation/stack";
import SetLocationTabNavigation from "./SetLocationTabNavigation";
import GoPathDetail from "../screens/GoPathDetail";
import OptRoutePath from "../screens/OptRoutePath";
const Stack = createStackNavigator();
const SetLocationStackNavigation = () => {
return (
<Stack.Navigator
mode='card'
screenOptions={{
headerShown: false
}}
>
<Stack.Screen
name='SetLocationTabNavigation'
component={SetLocationTabNavigation}
/>
<Stack.Screen
name='GoPathDetail'
component={GoPathDetail}
/>
</Stack.Navigator>
)
};
export default SetLocationStackNavigation;
\ No newline at end of file
import React, {useLayoutEffect} from 'react';
import {Ionicons} from "@expo/vector-icons";
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import Maps from "../screens/Maps";
import OptRoutePath from "../screens/OptRoutePath";
const Tab = createBottomTabNavigator();
const SetLocationTabNavigation = (props) => {
const {navigation, route} = props;
// useLayoutEffect(() => {}, [route]);
return (
<Tab.Navigator
tabBarOptions={{}}
>
<Tab.Screen
name='Maps'
component={Maps}
/>
<Tab.Screen
name='OptRoutePath'
component={OptRoutePath}
/>
</Tab.Navigator>
)
};
export default SetLocationTabNavigation;
\ No newline at end of file
import React from 'react';
import {createStackNavigator} from "@react-navigation/stack";
import Gallery from "../screens/Gallery";
import Maps from "../screens/Maps";
import Main from "../screens/Main";
import TabNavigation from "./TabNavigation";
import {TouchableOpacity} from "react-native";
// import * as WebBrowser from 'expo-web-browser';
import {Ionicons} from "@expo/vector-icons";
import {MaterialCommunityIcons} from "@expo/vector-icons";
import SelectOrTakePhotoStackNavigation from "./SelectOrTakePhotoStackNavigation";
import SetLocationStackNavigation from "./SetLocationStackNavigation";
import Profile from "../screens/Profile";
import Login from "../screens/Login";
import SignUp from "../screens/SignUp";
const Stack = createStackNavigator();
//
......@@ -15,15 +18,16 @@ const Stack = createStackNavigator();
// await WebBrowser.openBrowserAsync(url);
// };
const StackNavigation = () =>{
const StackNavigation = () => {
return (
<Stack.Navigator
mode='card'
screenOptions = {{
screenOptions={{
headerTitle: 'SGGO',
headerRight: () => {
return (
<TouchableOpacity>
<Ionicons name={'logo-youtube'} color={'red'} size={25}/>
<TouchableOpacity style={{marginRight: 5}}>
<MaterialCommunityIcons color={'grey'} name={'send'} size={24}/>
</TouchableOpacity>
)
}
......@@ -38,9 +42,27 @@ const StackNavigation = () =>{
component={SelectOrTakePhotoStackNavigation}
/>
<Stack.Screen
name='SetLocationStackNavigation'
component={SetLocationStackNavigation}
/>
<Stack.Screen
name='Maps'
component={Maps}
/>
<Stack.Screen
name='Gallery'
component={Gallery}
/>
<Stack.Screen
name='Login'
component={Login}
/>
<Stack.Screen
name='SignUp'
component={SignUp}
/>
</Stack.Navigator>
)
};
......
......@@ -4,14 +4,11 @@ import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import Main from "../screens/Main";
import Login from "../screens/Login";
import Profile from "../screens/Profile";
import LocationTimeSet from "../screens/LocationTimeSet";
import Maps from "../screens/Maps";
const Tab = createBottomTabNavigator();
const getHeaderName = (route) => {
};
const TabNavigation = (props) => {
const {navigation, route} = props;
// useLayoutEffect(() => {}, [route]);
......@@ -19,12 +16,8 @@ const TabNavigation = (props) => {
return (
<Tab.Navigator
// screenOptions = {({route})=>{}}
tabBarOptions = {{}}
tabBarOptions={{}}
>
<Tab.Screen
name='main'
component={Main}
/>
<Tab.Screen
name='login'
......@@ -32,8 +25,8 @@ const TabNavigation = (props) => {
/>
<Tab.Screen
name='maps'
component={Maps}
name='LocationTimeSet'
component={LocationTimeSet}
/>
<Tab.Screen
......
......@@ -8,6 +8,7 @@
"eject": "expo eject"
},
"dependencies": {
"@react-native-community/datetimepicker": "2.2.2",
"@react-native-community/masked-view": "0.1.6",
"@react-navigation/bottom-tabs": "^5.4.1",
"@react-navigation/native": "^5.3.0",
......@@ -16,14 +17,21 @@
"expo": "~37.0.3",
"expo-asset": "^8.1.4",
"expo-camera": "~8.2.0",
"expo-file-system": "~8.1.0",
"expo-font": "^8.1.1",
"expo-location": "~8.1.0",
"expo-media-library": "~8.1.0",
"expo-permissions": "~8.1.0",
"expo-web-browser": "^8.2.1",
"moment": "^2.26.0",
"native-base": "^2.13.12",
"node-nikerunclub": "^1.0.0",
"papaparse": "^5.2.0",
"react": "~16.9.0",
"react-dom": "~16.9.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-37.0.1.tar.gz",
"react-native-bottom-action-sheet": "^2.0.1",
"react-native-fast-image": "^8.1.5",
"react-native-gesture-handler": "~1.6.0",
"react-native-maps": "0.26.1",
"react-native-reanimated": "~1.7.0",
......
export const initialState = {
startLocation: null,
endLocation: null,
endTime: '',
optRoute: null,
settingLocation: false,
settingTime: false,
settingOptRoute: false,
settingVelocity: false,
personalVelocity: 60,
info: '',
};
export const SET_SLOC_REQUEST = 'SET_SLOC_REQUEST';
export const SET_SLOC_SUCCESS = 'SET_SLOC_SUCCESS';
export const SET_SLOC_FAILURE = 'SET_SLOC_FAILURE';
export const SET_ELOC_REQUEST = 'SET_ELOC_REQUEST';
export const SET_ELOC_SUCCESS = 'SET_ELOC_SUCCESS';
export const SET_ELOC_FAILURE = 'SET_ELOC_FAILURE';
export const SET_USER_LOC = 'SET_USER_LOC';
export const SET_TIME_REQUEST = 'SET_TIME_REQUEST';
export const SET_TIME_SUCCESS = 'SET_TIME_SUCCESS';
export const SET_TIME_FAILURE = 'SET_TIME_FAILURE';
export const SET_OPTROUTE_REQUEST = 'SET_OPTROUTE_REQUEST';
export const SET_OPTROUTE_SUCCESS = 'SET_OPTROUTE_SUCCESS';
export const SET_OPTROUTE_FAILURE = 'SET_OPTROUTE_FAILURE';
export const SET_PERVELOCITY_REQUEST = 'SET_PERVELOCITY_REQUEST';
export const SET_PERVELOCITY_SUCCESS = 'SET_PERVELOCITY_SUCCESS';
export const SET_PERVELOCITY_FAILURE = 'SET_PERVELOCITY_FAILURE';
export default (state = initialState, action) => {
switch (action.type) {
case SET_SLOC_REQUEST: {
return {
...state,
settingLocation: true,
}
}
case SET_SLOC_SUCCESS: {
const {startLocation} = action.data;
return {
...state,
startLocation,
isLoggingIn: false,
};
}
case SET_SLOC_FAILURE: {
const {info} = action.data;
return {
...state,
settingLocation: false,
info,
}
}
case SET_ELOC_REQUEST: {
return {
...state,
settingLocation: true,
}
}
case SET_ELOC_SUCCESS: {
const {endLocation} = action.data;
return {
...state,
endLocation,
isLoggingIn: false,
};
}
case SET_ELOC_FAILURE: {
const {info} = action.data;
return {
...state,
settingLocation: false,
info,
}
}
case SET_USER_LOC: {
var {userLocation} = action.data;
userLocation = {
title: '현위치',
latitude: userLocation.coords.latitude,
longitude: userLocation.coords.longitude,
latitudeDelta: 0.0039,
longitudeDelta: 0.0039,
description: 'start point',
};
console.log(userLocation.coords);
return {
...state,
startLocation: userLocation,
settingLocation: false
}
}
case SET_TIME_REQUEST: {
return {
...state,
settingTime: true,
}
}
case SET_TIME_SUCCESS: {
const {date} = action.data;
console.log('reducer SET_TIME_SUCCESS', date);
return {
...state,
endTime: date,
settingTime: false,
}
}
case SET_TIME_FAILURE: {
const {info} = action.data;
return {
...state,
settingTime: false,
}
}
case SET_OPTROUTE_REQUEST: {
return {
...state,
settingOptRoute: true,
}
}
case SET_OPTROUTE_SUCCESS: {
var {optRoute} = action.data;
console.log('SET_OPTROUTE_SUCCESST', optRoute);
return {
...state,
optRoute: optRoute,
settingOptRoute: false,
}
}
case SET_OPTROUTE_FAILURE: {
const {info} = action.data;
return {
...state,
settingOptRoute: false,
}
}
case SET_PERVELOCITY_REQUEST: {
return {
...state,
settingVelocity: true,
}
}
case SET_PERVELOCITY_SUCCESS: {
var {personalVelocity} = action.data;
console.log('SET_PERVELOCITY_SUCCESS', personalVelocity);
return {
...state,
personalVelocity,
settingVelocity: true,
}
}
case SET_PERVELOCITY_FAILURE: {
const {info} = action.data;
return {
...state,
settingVelocity: false,
}
}
default: {
return {
...state,
};
}
}
};
\ No newline at end of file
export const initialState = {
me: null,
nikeRecord: null,
isLoggingIn: false,
isSigningUp: false,
......
import {all, call, fork, delay, put, takeEvery, takeLatest} from 'redux-saga/effects';
import axios from 'axios';
import {coordAPIKEY, host} from '../env';
import {
SET_ELOC_REQUEST,
SET_SLOC_REQUEST,
SET_SLOC_SUCCESS,
SET_ELOC_SUCCESS,
SET_SLOC_FAILURE,
SET_ELOC_FAILURE,
SET_OPTROUTE_REQUEST,
SET_OPTROUTE_SUCCESS,
SET_OPTROUTE_FAILURE,
} from "../reducers/location";
function setStartLocationAPI(data) {
const {startTextLocation} = data;
console.log(startTextLocation);
return axios.get(`http://api.vworld.kr/req/address?service=address&request=getcoord&version=1.0&crs=epsg:4326&address=${startTextLocation}&refine=true&simple=false&format=json&type=road&key=${coordAPIKEY}`);
}
function setEndLocationAPI(data) {
const {endTextLocation} = data;
console.log(endTextLocation);
return axios.get(`http://api.vworld.kr/req/address?service=address&request=getcoord&version=1.0&crs=epsg:4326&address=${endTextLocation}&refine=true&simple=false&format=json&type=road&key=${coordAPIKEY}`);
}
function setOptRouteAPI(data) {
const {startLocation, endLocation, endTime, personalVelocity} = data;
console.log('제발 좀 되라', startLocation, endLocation, endTime, personalVelocity);
return axios.post(`http://${host}:4001/api/setOptRoute`, {
startLocation,
endLocation,
endTime,
personalVelocity
}, {withCredentials: true});
}
function* setStartLocation(action) {
try {
console.log('saga의 setLocation', action.data);
let res = yield call(setStartLocationAPI, action.data);
let longitude, latitude = null;
if (res.data.response.status === "OK") {
longitude = parseFloat(res.data.response.result.point.x);
latitude = parseFloat(res.data.response.result.point.y);
}
//
// if (res.data.status === "OK") {
// latitude = res.data.results[0].geometry.location.lat;
// longitude = res.data.results[0].geometry.location.lng;
// console.log(latitude, longitude)
// }
console.log('startRes: ', longitude, latitude);
yield put({
type: SET_SLOC_SUCCESS,
data: {
startLocation: {
title: action.data.startTextLocation,
description: 'start point',
longitude: longitude,
latitude: latitude,
latitudeDelta: 1.2,
longitudeDelta: 1.2
}
}
})
} catch (e) {
console.error(e);
yield put({
type: SET_SLOC_FAILURE,
data: {
info: e.response.data.info
}
});
}
}
function* setEndLocation(action) {
try {
let res = yield call(setEndLocationAPI, action.data);
let longitude, latitude = null;
//
// if (res.data.status === "OK") {
// latitude = res.data.results[0].geometry.location.lat;
// longitude = res.data.results[0].geometry.location.lng;
// console.log(latitude, longitude)
// }
if (res.data.response.status === "OK") {
longitude = parseFloat(res.data.response.result.point.x);
latitude = parseFloat(res.data.response.result.point.y);
}
console.log('finishRes: ', longitude, latitude);
yield put({
type: SET_ELOC_SUCCESS,
data: {
endLocation: {
title: action.data.endTextLocation,
description: 'end point',
longitude: longitude,
latitude: latitude,
latitudeDelta: 1.2,
longitudeDelta: 1.2
}
}
});
} catch (e) {
console.error(e);
yield put({
type: SET_ELOC_FAILURE,
data: {
info: e.response.data.info
}
})
}
}
function* setOptRoute(action) {
try {
let res = yield call(setOptRouteAPI, action.data);
const {optRoute} = res.data;
yield put({
type: SET_OPTROUTE_SUCCESS,
data: {
optRoute: optRoute
}
});
} catch (e) {
console.error(e);
yield put({
type: SET_OPTROUTE_FAILURE,
data: {
info: e.response.data.info
}
})
}
}
function* watchSetStartLocation() {
console.log('watchSetStartLocation');
yield takeLatest(SET_SLOC_REQUEST, setStartLocation);
}
function* watchSetEndLocation() {
console.log('watchSetEndLocation');
yield takeLatest(SET_ELOC_REQUEST, setEndLocation)
}
function* watchSetOptRoute() {
console.log('watchSetOptimalRoute');
yield takeLatest(SET_OPTROUTE_REQUEST, setOptRoute)
}
export default function* locationSaga() {
yield all([
fork(watchSetStartLocation),
fork(watchSetEndLocation),
fork(watchSetOptRoute),
]);
};
\ No newline at end of file
import {all, call, fork, delay, put, takeEvery, takeLatest} from 'redux-saga/effects';
import axios from 'axios';
import host from '../env';
import {host} from '../env';
import {
LOG_IN_FAILURE,
LOG_IN_REQUEST,
......@@ -37,9 +37,7 @@ function loginAPI(data) {
const {email, password} = data;
console.log(email, password);
console.log(`http://${host}:4001/user/login`);
// const res1 = axios.get(`http://${host}:4001/user/test`, {
// withCredentials: true
// });
return axios.post(`http://${host}:4001/user/login`, {
email, password
}, {
......
import React, {useState, useContext, useEffect, useCallback} from 'react';
import {Text, View, StyleSheet, TouchableOpacity, ScrollView, TextInput} from 'react-native';
import {useDispatch, useSelector} from "react-redux";
import {useNavigation} from '@react-navigation/native';
import WalkPathComponent from "../components/WalkPathComponent";
import BusPathComponent from "../components/BusPathComponent";
import LanePathComponent from "../components/LanePathComponent";
import {MaterialCommunityIcons} from "@expo/vector-icons";
const GoPathDetail = (props) => {
const navigation = useNavigation();
const {route} = props;
const {detail} = route.params;
const [pathDetails, setPathDetails] = useState(null);
const {startLocation, endLocation, optRoute} = useSelector(state => state.location);
useEffect(() => {
setPathDetails(detail);
console.log(detail)
}, []);
return (
<ScrollView>
<View style={styles.input}>
<MaterialCommunityIcons color={'red'} name={'map-marker'} size={26}/>
<TextInput
style={styles.inputText}
value={startLocation.title}
/>
</View>
{pathDetails ?
pathDetails.map((detail, index) => {
if (detail.trafficType === '도보') {
return (
<WalkPathComponent pathDetail={detail}/>
)
} else if (detail.trafficType === '버스') {
return (
<BusPathComponent pathDetail={detail}/>
)
} else (detail.trafficType === '지하철')
{
return (
<LanePathComponent pathDetail={detail}/>
)
}
})
:
null
}
<View style={styles.input}>
<MaterialCommunityIcons color={'blue'} name={'map-marker'} size={26}/>
<TextInput
style={styles.inputText}
value={endLocation.title}
/>
</View>
</ScrollView>
);
}
export default GoPathDetail;
const styles = StyleSheet.create({
input: {
borderRadius: 20,
paddingLeft: 10,
paddingTop: 5,
paddingRight: 10,
width: 350,
height: 30,
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'space-between',
borderBottomColor: '#f0f8ff',
marginBottom: 10,
// borderBottomWidth: StyleSheet.hairlineWidth,
},
inputText: {
flex: 1,
fontWeight: 'bold',
}
})
\ No newline at end of file
import React, {useState, useEffect} from 'react';
import {View, Text, Button, StyleSheet} from 'react-native';
import StartAndFinishLocationComponent from "../components/StartAndFinishLocationComponent";
import DateTimePickerComponent from "../components/DateTimePickerComponent";
import styled from "styled-components";
import {useNavigation} from "@react-navigation/native";
import {useDispatch, useSelector} from "react-redux";
import {SET_OPTROUTE_REQUEST} from "../reducers/location";
const GoToMaps = styled.TouchableOpacity`
flex: 0.5;
backgroundColor: #f0f8ff;
align-items: center;
justify-content: center;
width: 180px;
height: 30px;
border-radius: 30px;
border-width: 1px;
border-color: #a9a9a9;
position: absolute;
left: 55
`;
const LocationTimeSet = () => {
const navigation = useNavigation();
const [goToMapsClick, setGoToMapsClick] = useState(false);
const {startLocation} = useSelector(state => state.location);
const {endLocation} = useSelector(state => state.location);
const dispatch = useDispatch();
const goToMaps = async () => {
setGoToMapsClick(true);
navigation.navigate('SetLocationStackNavigation');
setTimeout(() => {
setGoToMapsClick(false)
}, 2000)
};
useEffect(() => {
}, []);
return (
<View>
<StartAndFinishLocationComponent/>
<DateTimePickerComponent goToMapsClick={goToMapsClick}/>
<View style={{flexDirection: 'row', marginLeft: 50}}>
<GoToMaps onPress={goToMaps}>
<Text>도착 시간 설정</Text>
</GoToMaps>
</View>
</View>
)
};
const styles = StyleSheet.create({
containerStyle: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ecf0f1',
marginTop: 100,
},
input: {
width: 200,
height: 44,
padding: 10,
borderWidth: 1,
borderColor: '#778899',
marginBottom: 10,
}
});
export default LocationTimeSet;
\ No newline at end of file
import React, {useState, useContext, useEffect, useCallback} from 'react';
import {View, Text, Image, TextInput, TouchableOpacity, StyleSheet} from 'react-native';
import {useDispatch, useSelector} from "react-redux";
import {useNavigation} from '@react-navigation/native';
import LoginComponent from "../components/LoginComponent";
import styled from "styled-components";
const Login = (props) => {
const navigation = useNavigation();
const [loading, setLoading] = useState(true);
const [isLogin, setIsLogin] = useState(true);
const {me} = useSelector(state => state.user);
const {isLoggingIn} = useSelector(state => state.user);
const changeIsLogin = () => {
return setIsLogin(!isLogin);
}
useEffect(() => {
setLoading(false);
}, [me]);
return (
<View style={styles.changeStyle}>
{me ?
<View style={{flex: 2}}>
<Image
style={{width: 500, height: 600, flex: 1}}
source={require('../assets/nike.png')}
/>
<TouchableOpacity
title={'SGGO'}
style={{flex: 1, fontSize: 100}}
>
</TouchableOpacity>
</View>
:
<View style={styles.loginStyle}>
<Text style={styles.inputText}>로그인</Text>
<LoginComponent/>
</View>
}
</View>
)
};
export default Login;
const styles = StyleSheet.create({
changeStyle: {
flex: 2,
alignItems: 'center',
justifyContent: 'center',
borderColor: 'darkgrey',
},
loginStyle: {
flex: 1,
marginTop: 30,
},
inputText: {
borderColor: 'darkgrey',
fontWeight: 'bold',
fontSize: 20,
marginBottom: 10
}
});
\ No newline at end of file
......@@ -29,7 +29,6 @@ const Main = () => {
const navigation = useNavigation();
const goToGallery = () => {
console.log(navigation.navigate);
navigation.navigate('Gallery');
};
......
import React from 'react';
import {View, Text, TouchableOpacity, Image, StyleSheet} from 'react-native';
import styled from "styled-components";
import {useNavigation} from "@react-navigation/native";
import {useSelector} from "react-redux";
const MainImage = (props) => {
const navigation = useNavigation();
const {me} = useSelector(state => state.user);
return (
<>
<View style={styles.containerStyle}>
<Text>로그인에 성공하였습니다</Text>
</View>
</>
)
};
export default MainImage;
const styles = StyleSheet.create({
containerStyle: {
flex: 1,
},
});
import React, {useState, useEffect} from 'react';
import MapView, {Marker, Polygon, AnimatedRegion} from 'react-native-maps';
import {StyleSheet, Text, TextInput, TouchableOpacity, View} from 'react-native';
import screen from '../constants/layout';
import {useDispatch, useSelector} from "react-redux";
import {useNavigation} from "@react-navigation/native";
import {AntDesign, MaterialCommunityIcons} from "@expo/vector-icons";
import {SET_OPTROUTE_REQUEST} from "../reducers/location";
import styled from "styled-components";
import OptRoutePath from "./OptRoutePath";
const GoToOptRoutePath = styled.TouchableOpacity`
flex: 2;
position: absolute;
right: 8px;
bottom: 20px;
width: 30px;
height: 30px;
border-radius: 50px;
`;
const Maps = (props) => {
const navigation = useNavigation();
const [region, setRegion] = useState(null);
const [markers, setMarkers] = useState([]);
const [pathList, setPathList] = useState([]);
const {startLocation, endLocation, optRoute, endTime, personalVelocity} = useSelector(state => state.location);
const onRegionChange = (region) => {
setRegion(region);
};
useEffect(() => {
setRegion({
latitude: 37.56647,
longitude: 126.977963,
latitudeDelta: 1.5,
longitudeDelta: 1.5
});
if (startLocation || endLocation) {
setMarkers([startLocation, endLocation]);
}
}, []);
const dispatch = useDispatch();
const goToOptRoutePath = async () => {
try {
console.log('set optroute request');
await dispatch({
type: SET_OPTROUTE_REQUEST,
data: {
startLocation,
endLocation,
endTime,
personalVelocity
}
});
setTimeout(() => {
if (optRoute !== null) {
navigation.navigate('OptRoutePath', {optRoute: optRoute})
}
}, 3000);
} catch (e) {
console.error(e);
}
};
useEffect(() => {
setMarkers([startLocation, endLocation]);
}, [startLocation, endLocation]);
return (
<View style={styles.container}>
<View style={styles.input}>
<MaterialCommunityIcons color={'red'} name={'map-marker'} size={26}/>
<TextInput
style={styles.inputText}
value={startLocation.title}
/>
</View>
<View style={styles.input}>
<MaterialCommunityIcons color={'blue'} name={'map-marker'} size={26}/>
<TextInput
style={styles.inputText}
value={endLocation.title}
/>
</View>
<MapView
style={styles.mapStyle}
initialRegion={region}
onRegionChange={onRegionChange}
textStyle={{color: '#bc8b00'}}
showsUserLocation={true}
>
{markers ?
markers.map((marker, index) => {
return (
<MapView.Marker draggable
key={index}
coordinate={marker}
title={marker.title}
/>
)
})
:
null
}
</MapView>
<GoToOptRoutePath onPress={goToOptRoutePath}>
<AntDesign color={'darkgrey'} name={'caretright'} size={32}/>
</GoToOptRoutePath>
</View>
)
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
},
mapStyle: {
width: screen.width,
height: screen.height,
},
textStyle: {
flex: 1,
fontWeight: 'bold',
fontSize: 20,
color: 'grey',
marginBottom: 20,
},
input: {
borderRadius: 10,
backgroundColor: '#f0f8ff',
paddingLeft: 10,
paddingTop: 5,
paddingRight: 10,
width: 350,
height: 30,
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'space-between',
borderBottomColor: '#f0f8ff',
marginBottom: 10
// borderBottomWidth: StyleSheet.hairlineWidth,
},
inputText: {
flex: 1,
},
});
export default Maps;
import React, {useState, useEffect} from 'react';
import {View, Text, Button, ScrollView} from 'react-native';
import {useNavigation} from '@react-navigation/native';
import {useDispatch, useSelector} from "react-redux";
import GoPathSummary from '../components/GoPathSummary';
const OptRoutePath = (props) => {
const navigation = useNavigation();
const {route} = props;
const {optRoute} = route.params;
const [pathList, setPathList] = useState([]);
const {startLocation} = useSelector(state => state.location);
const {endLocation} = useSelector(state => state.location);
const dispatch = useDispatch();
const setOptRouteRequest = async () => {
try {
console.log('set optroute request');
setTimeout(() => {
if (optRoute.pathList) {
for (var i = 0; i < optRoute.pathList.length; i++) {
setPathList(oldPath => [...oldPath, optRoute.pathList[i]]);
}
}
}, 3000);
} catch (e) {
console.error(e);
}
};
useEffect(() => {
setOptRouteRequest();
}, []);
return (
<ScrollView>
{pathList ?
pathList.map((path, index) => {
return (
<>
<GoPathSummary summary={path.info} detail={path.subPathList}/>
</>
)
})
:
null
}
</ScrollView>
)
};
export default OptRoutePath;
\ No newline at end of file
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
No preview for this file type
No preview for this file type