Add login. Fetch user data. Learned basic React + Redux. Needs work.
This commit is contained in:
1 parent
cc6c9e4973
commit
d4d3f12aea
13 files changed
+433
-47
No files matched your search
+5
-2
@@ -16,7 +16,8 @@
|
|||||||
"react-native-htmlview": "^0.12.0",
|
"react-native-htmlview": "^0.12.0",
|
||||||
"react-navigation": "^1.0.0-beta.11",
|
"react-navigation": "^1.0.0-beta.11",
|
||||||
"react-redux": "^5.0.5",
|
"react-redux": "^5.0.5",
|
||||||
"redux": "^3.7.2"
|
"redux": "^3.7.2",
|
||||||
|
"redux-thunk": "^2.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-jest": "20.0.3",
|
"babel-jest": "20.0.3",
|
||||||
@@ -26,7 +27,9 @@
|
|||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"preset": "react-native",
|
"preset": "react-native",
|
||||||
"setupFiles": ["<rootDir>/jest/setup.js"],
|
"setupFiles": [
|
||||||
|
"<rootDir>/jest/setup.js"
|
||||||
|
],
|
||||||
"transformIgnorePatterns": [
|
"transformIgnorePatterns": [
|
||||||
"node_modules/(?!(jest-)?react-native|react-clone-referenced-element|react-navigation|native-base|@shoutem)"
|
"node_modules/(?!(jest-)?react-native|react-clone-referenced-element|react-navigation|native-base|@shoutem)"
|
||||||
]
|
]
|
||||||
|
|||||||
+3
-3
@@ -1,11 +1,11 @@
|
|||||||
import Dusken from "./Dusken";
|
import Dusken from "./Dusken";
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { createStore } from 'redux'
|
import { createStore, applyMiddleware } from 'redux';
|
||||||
|
import thunk from 'redux-thunk';
|
||||||
import duskenApp from "./reducers";
|
import duskenApp from "./reducers";
|
||||||
|
|
||||||
let store = createStore(duskenApp);
|
let store = createStore(duskenApp, applyMiddleware(thunk));
|
||||||
|
|
||||||
|
|
||||||
export default class App extends Component {
|
export default class App extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
+3
-1
@@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
import {connect} from "react-redux";
|
import {connect} from "react-redux";
|
||||||
import {TabNavigator, StackNavigator} from "react-navigation";
|
import {TabNavigator, StackNavigator} from "react-navigation";
|
||||||
|
|
||||||
|
import LoginScreen from "./screens/LoginScreen";
|
||||||
import EventsScreen from "./screens/EventScreen";
|
import EventsScreen from "./screens/EventScreen";
|
||||||
import EventDetailsScreen from "./screens/EventDetailsScreen";
|
import EventDetailsScreen from "./screens/EventDetailsScreen";
|
||||||
import AboutScreen from "./screens/AboutScreen";
|
import AboutScreen from "./screens/AboutScreen";
|
||||||
@@ -22,7 +23,8 @@ const tabBarOptions = {
|
|||||||
const tabNav = TabNavigator(tabBarRoutes, tabBarOptions);
|
const tabNav = TabNavigator(tabBarRoutes, tabBarOptions);
|
||||||
|
|
||||||
const DuskenContainer = StackNavigator({
|
const DuskenContainer = StackNavigator({
|
||||||
Root: { screen: tabNav},
|
Root: { screen: tabNav },
|
||||||
|
Login: { screen: LoginScreen },
|
||||||
EventDetails: { screen: EventDetailsScreen },
|
EventDetails: { screen: EventDetailsScreen },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+124
-6
@@ -1,11 +1,129 @@
|
|||||||
const LOGIN_START = 'LOGIN_START';
|
const LOGIN_REQUEST = 'LOGIN_REQUEST';
|
||||||
|
const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
|
||||||
|
const LOGIN_FAILURE = 'LOGIN_FAILURE';
|
||||||
|
const LOGOUT = 'LOGOUT';
|
||||||
|
const USER_DATA_REQUEST = 'USER_DATA_REQUEST';
|
||||||
|
const USER_DATA_SUCCESS = 'USER_DATA_SUCCESS';
|
||||||
|
const USER_DATA_FAILURE = 'USER_DATA_FAILURE';
|
||||||
|
|
||||||
function loginStart() {
|
function loginRequest() {
|
||||||
return {
|
return {
|
||||||
type: LOGIN_START
|
type: LOGIN_REQUEST
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loginSuccess(username, token) {
|
||||||
|
return {
|
||||||
|
type: LOGIN_SUCCESS,
|
||||||
|
username,
|
||||||
|
token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loginFailure(errorMessage) {
|
||||||
|
return {
|
||||||
|
type: LOGIN_FAILURE,
|
||||||
|
errorMessage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function logout() {
|
||||||
|
return {
|
||||||
|
type: LOGOUT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function userDataRequest() {
|
||||||
|
return {
|
||||||
|
type: USER_DATA_REQUEST
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function userDataSuccess(data) {
|
||||||
|
return {
|
||||||
|
type: USER_DATA_SUCCESS,
|
||||||
|
data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function userDataFailure(errorMessage) {
|
||||||
|
return {
|
||||||
|
type: USER_DATA_FAILURE,
|
||||||
|
errorMessage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
LOGIN_START,
|
LOGIN_REQUEST, loginRequest,
|
||||||
loginStart
|
LOGIN_SUCCESS, loginSuccess,
|
||||||
};
|
LOGIN_FAILURE, loginFailure,
|
||||||
|
LOGOUT, logout,
|
||||||
|
USER_DATA_REQUEST, userDataRequest,
|
||||||
|
USER_DATA_SUCCESS, userDataSuccess,
|
||||||
|
USER_DATA_FAILURE, userDataFailure,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function requestLogin(username, password) {
|
||||||
|
return (dispatch) => {
|
||||||
|
// We are now logging in
|
||||||
|
dispatch(loginRequest())
|
||||||
|
|
||||||
|
return fetch('http://10.0.0.10:3000/auth/obtain-token/', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
'username': username,
|
||||||
|
'password': password
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(response => response.json().then(json => ({ json, response })))
|
||||||
|
.then(({json, response}) => {
|
||||||
|
if (response.ok === false) {
|
||||||
|
return Promise.reject(json)
|
||||||
|
}
|
||||||
|
return json
|
||||||
|
})
|
||||||
|
.then(
|
||||||
|
data => {
|
||||||
|
dispatch(loginSuccess(username, data.token))
|
||||||
|
},
|
||||||
|
data => {
|
||||||
|
dispatch(loginFailure(data.error || 'Log in failed'))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function requestUserData(token) {
|
||||||
|
return (dispatch) => {
|
||||||
|
// We are now fetching user data
|
||||||
|
dispatch(userDataRequest())
|
||||||
|
|
||||||
|
return fetch('http://10.0.0.10:3000/api/me/', {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': 'Token ' + token
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => response.json().then(json => ({ json, response })))
|
||||||
|
.then(({json, response}) => {
|
||||||
|
if (response.ok === false) {
|
||||||
|
return Promise.reject(json)
|
||||||
|
}
|
||||||
|
return json
|
||||||
|
})
|
||||||
|
.then(
|
||||||
|
data => {
|
||||||
|
dispatch(userDataSuccess(data))
|
||||||
|
},
|
||||||
|
data => {
|
||||||
|
dispatch(userDataFailure('Det funka ikke :-('))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+48
-18
@@ -1,20 +1,38 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import {Button, Image, StyleSheet, Text, TextInput, View} from 'react-native';
|
import {Button, Image, StyleSheet, Text, TextInput, View} from 'react-native';
|
||||||
|
import { Spinner } from 'native-base';
|
||||||
|
|
||||||
import { loginStart } from "../../actions";
|
// import { login } from "../../actions";
|
||||||
|
|
||||||
export default class Login extends Component {
|
export default class Login extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
loggedIn: false
|
isAuthenticated: false,
|
||||||
|
isLoggingIn: false,
|
||||||
|
errorMessage: null,
|
||||||
|
email: '',
|
||||||
|
password: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if(this.state.loggedIn !== nextProps.loggedIn) {
|
if(this.state.isAuthenticated !== nextProps.isAuthenticated) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loggedIn: nextProps.loggedIn
|
isAuthenticated: nextProps.isAuthenticated
|
||||||
|
})
|
||||||
|
if (nextProps.isAuthenticated) {
|
||||||
|
this.onLogin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(this.state.isLoggingIn !== nextProps.isLoggingIn) {
|
||||||
|
this.setState({
|
||||||
|
isLoggingIn: nextProps.isLoggingIn
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(this.state.errorMessage !== nextProps.errorMessage) {
|
||||||
|
this.setState({
|
||||||
|
errorMessage: nextProps.errorMessage
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,48 +43,60 @@ export default class Login extends Component {
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Text style={styles.text}>The Norwegian Student Society</Text>
|
<Text style={styles.text}>Det Norske Studentersamfund</Text>
|
||||||
<Text style={styles.text}>Chateau Neuf</Text>
|
<Text style={styles.text}>Chateau Neuf</Text>
|
||||||
<Image source={pic} style={{width: 200, height: 150, marginBottom: 40}} resizeMode='contain' />
|
<Image source={pic} style={{width: 200, height: 150, marginBottom: 40}} resizeMode='contain' />
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder="Email"
|
placeholder="E-post"
|
||||||
style={styles.input}
|
style={styles.input}
|
||||||
keyboardType="email-address"
|
keyboardType="email-address"
|
||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
returnKeyType="next"
|
returnKeyType="next"
|
||||||
|
onChangeText={this.handleEmail}
|
||||||
onSubmitEditing={(event) => {
|
onSubmitEditing={(event) => {
|
||||||
this.refs.passwordInput.focus();
|
this.refs.passwordInput.focus();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder="Password"
|
placeholder="Passord"
|
||||||
style={styles.input}
|
style={styles.input}
|
||||||
secureTextEntry={true}
|
secureTextEntry={true}
|
||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
ref='passwordInput'
|
ref='passwordInput'
|
||||||
|
onChangeText={this.handlePassword}
|
||||||
onSubmitEditing={this.onLoginPress}
|
onSubmitEditing={this.onLoginPress}
|
||||||
/>
|
/>
|
||||||
<View style={styles.button}>
|
<View style={styles.button}>
|
||||||
<Button
|
<Button
|
||||||
title="Log in"
|
title="Logg inn"
|
||||||
onPress={this.onLoginPress}
|
onPress={this.onLoginPress}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<Text style={{paddingTop: 10}}>{this.loginState()}</Text>
|
{this.spinIfLoggingIn}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoginPress = () => {
|
spinIfLoggingIn = () => {
|
||||||
console.log("YO from onLoginPress");
|
if (this.state.isLoggingIn) {
|
||||||
this.props.dispatch(loginStart())
|
return <Spinner color="#f58220"></Spinner>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleEmail = (text) => {
|
||||||
|
this.setState({ email: text })
|
||||||
};
|
};
|
||||||
|
|
||||||
loginState() {
|
handlePassword = (text) => {
|
||||||
if(this.state.loggedIn) {
|
this.setState({ password: text })
|
||||||
return 'LOGGED IN'
|
};
|
||||||
}
|
|
||||||
return 'NOT YET'
|
onLoginPress = () => {
|
||||||
|
this.props.requestLogin(this.state.email, this.state.password)
|
||||||
|
};
|
||||||
|
|
||||||
|
onLogin = () => {
|
||||||
|
this.props.onLogin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +108,7 @@ const styles = StyleSheet.create({
|
|||||||
backgroundColor: '#F5FCFF',
|
backgroundColor: '#F5FCFF',
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
width: 240,
|
width: 320,
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
height: 52,
|
height: 52,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
import {connect} from "react-redux";
|
import {connect} from "react-redux";
|
||||||
|
import { bindActionCreators } from "redux";
|
||||||
import Login from "./Login";
|
import Login from "./Login";
|
||||||
|
import { requestLogin } from "../../actions";
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
state => ({
|
(state) => ({
|
||||||
loggedIn: state.loggedIn
|
isAuthenticated: state.isAuthenticated,
|
||||||
})
|
isLoggingIn: state.isLoggingIn,
|
||||||
)(Login);
|
errorMessage: state.errorMessage,
|
||||||
|
}),
|
||||||
|
{ requestLogin }
|
||||||
|
)(Login);
|
||||||
@@ -7,6 +7,10 @@ export default class Membership extends Component {
|
|||||||
return (
|
return (
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<View style={styles.card}>
|
<View style={styles.card}>
|
||||||
|
<View style={styles.button}>
|
||||||
|
<Button onPress={this.onLoginPress} full><NBText>Logg inn</NBText></Button>
|
||||||
|
</View>
|
||||||
|
|
||||||
<Text style={styles.paragraph}>Siden 1813 har Det Norske Studentersamfund samlet studenter til kulturell, politisk, faglig og ikke minst sosial aktivitet. Som medlem i DNS er du med på å understreke viktigheten til en felles møteplass for alle Oslos studenter, uavhengig av utdanningsinstitusjon, studie og hvem de er.</Text>
|
<Text style={styles.paragraph}>Siden 1813 har Det Norske Studentersamfund samlet studenter til kulturell, politisk, faglig og ikke minst sosial aktivitet. Som medlem i DNS er du med på å understreke viktigheten til en felles møteplass for alle Oslos studenter, uavhengig av utdanningsinstitusjon, studie og hvem de er.</Text>
|
||||||
<Text style={styles.paragraph}>Vi setter pris på felleskapet som er med på å bygge Chateau Neuf. DNS er en organisasjon av og for medlemmene. Derfor sørger vi for at det blir litt lettere å være student ved å ta en del av kaka for medlemmene våre. Med medlemskap får billigere inngang og servering på alt som skjer på Chateau Neuf.</Text>
|
<Text style={styles.paragraph}>Vi setter pris på felleskapet som er med på å bygge Chateau Neuf. DNS er en organisasjon av og for medlemmene. Derfor sørger vi for at det blir litt lettere å være student ved å ta en del av kaka for medlemmene våre. Med medlemskap får billigere inngang og servering på alt som skjer på Chateau Neuf.</Text>
|
||||||
|
|
||||||
@@ -23,12 +27,16 @@ export default class Membership extends Component {
|
|||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
|
|
||||||
onPurchasePress() {
|
onPurchasePress() {
|
||||||
// FIXME: Move this to process.env.DUSKEN_URL and use babel thing to do search replace
|
// FIXME: Move this to process.env.DUSKEN_URL and use babel thing to do search replace
|
||||||
Linking.openURL('https://medlem.neuf.no');
|
Linking.openURL('https://medlem.neuf.no');
|
||||||
}
|
};
|
||||||
|
|
||||||
|
onLoginPress = () => {
|
||||||
|
this.props.onLoginPress();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,62 @@
|
|||||||
|
import React from 'react';
|
||||||
import {connect} from "react-redux";
|
import {connect} from "react-redux";
|
||||||
|
|
||||||
import Membership from "./Membership";
|
import Membership from "./Membership";
|
||||||
|
import MembershipProof from "./MembershipProof";
|
||||||
|
import { requestUserData } from "../../actions";
|
||||||
|
|
||||||
export default connect()(Membership);
|
class MembershipContainer extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
isAuthenticated: props.isAuthenticated,
|
||||||
|
userToken: props.userToken,
|
||||||
|
isFetchingUserData: props.isFetchingUserData,
|
||||||
|
user: props.user,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.fetchUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if(this.state.isAuthenticated !== nextProps.isAuthenticated) {
|
||||||
|
this.setState({isAuthenticated: nextProps.isAuthenticated})
|
||||||
|
}
|
||||||
|
if(this.state.userToken !== nextProps.userToken) {
|
||||||
|
this.setState({userToken: nextProps.userToken})
|
||||||
|
this.fetchUser();
|
||||||
|
}
|
||||||
|
if(this.state.user !== nextProps.user) {
|
||||||
|
this.setState({user: nextProps.user})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchUser = () => {
|
||||||
|
if (!this.state.userToken) { return; }
|
||||||
|
this.props.requestUserData(this.state.userToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
onLoginPress = () => {
|
||||||
|
this.props.onLoginPress();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.user) {
|
||||||
|
return (<MembershipProof user={this.state.user} fetchUser={this.fetchUser}/>)
|
||||||
|
}
|
||||||
|
return (<Membership onLoginPress={this.onLoginPress}/>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
(state) => ({
|
||||||
|
isAuthenticated: state.isAuthenticated,
|
||||||
|
isFetchingUserData: state.isFetchingUserData,
|
||||||
|
userToken: state.userToken,
|
||||||
|
user: state.user,
|
||||||
|
}),
|
||||||
|
{ requestUserData }
|
||||||
|
)(MembershipContainer);
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import {StyleSheet, Platform, RefreshControl} from "react-native";
|
||||||
|
import {Card, CardItem, Text, Content} from 'native-base';
|
||||||
|
|
||||||
|
export default class MembershipProof extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
user: props.user,
|
||||||
|
refreshing: false,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if(this.state.user !== nextProps.user) {
|
||||||
|
this.setState({user: nextProps.user})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
validTo() {
|
||||||
|
if (this.state.user.last_membership.membership_type == 'lifelong') {
|
||||||
|
return 'Livsvarig'
|
||||||
|
}
|
||||||
|
return this.state.user.last_membership.end_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
statusText() {
|
||||||
|
if (!this.state.user.is_member) {
|
||||||
|
if (!this.state.user.last_membership) {
|
||||||
|
return 'Ikke medlem'
|
||||||
|
}
|
||||||
|
return 'Utløpt'
|
||||||
|
}
|
||||||
|
if (this.state.user.is_volunteer) {
|
||||||
|
return 'Aktiv'
|
||||||
|
}
|
||||||
|
return 'Medlem'
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchUser = () => {
|
||||||
|
this.props.fetchUser()
|
||||||
|
};
|
||||||
|
|
||||||
|
// fetchUser = () => {
|
||||||
|
// this.props.fetchUser().then(() => {
|
||||||
|
// this.setState({refreshing: false});
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
|
||||||
|
// _onRefresh() {
|
||||||
|
// console.log('onRefresh')
|
||||||
|
// this.setState({refreshing: true});
|
||||||
|
// this.fetchUser()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// refreshControl() {
|
||||||
|
// return (
|
||||||
|
// <RefreshControl
|
||||||
|
// refreshing={this.state.refreshing}
|
||||||
|
// onRefresh={this._onRefresh.bind(this)}
|
||||||
|
// />)
|
||||||
|
// }
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Content>
|
||||||
|
<Card>
|
||||||
|
<CardItem>
|
||||||
|
<Text style={styles.nameText}>{this.state.user.first_name} {this.state.user.last_name}</Text>
|
||||||
|
</CardItem>
|
||||||
|
<CardItem>
|
||||||
|
<Text>{this.statusText()}</Text>
|
||||||
|
</CardItem>
|
||||||
|
<CardItem>
|
||||||
|
<Text>Gyldig til: {this.validTo()}</Text>
|
||||||
|
</CardItem>
|
||||||
|
</Card>
|
||||||
|
</Content>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
nameText: {
|
||||||
|
flex: 1,
|
||||||
|
textAlign: 'center',
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
});
|
||||||
+51
-5
@@ -1,16 +1,62 @@
|
|||||||
import {LOGIN_START} from './actions';
|
import {
|
||||||
|
LOGIN_REQUEST,
|
||||||
|
LOGIN_SUCCESS,
|
||||||
|
LOGIN_FAILURE,
|
||||||
|
LOGOUT,
|
||||||
|
USER_DATA_REQUEST,
|
||||||
|
USER_DATA_SUCCESS,
|
||||||
|
USER_DATA_FAILURE,
|
||||||
|
} from './actions';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
loggedIn: false,
|
isAuthenticated: false,
|
||||||
|
isLoggingIn: false,
|
||||||
|
isFetchingUserData: false,
|
||||||
|
userToken: null,
|
||||||
|
user: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function duskenApp(state = initialState, action) {
|
export default function duskenApp(state = initialState, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case LOGIN_START:
|
case LOGIN_REQUEST:
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
loggedIn: true // INSTANT LOGIN!
|
isLoggingIn: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
case LOGIN_FAILURE:
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
isLoggingIn: false,
|
||||||
|
errorMessage: action.errorMessage
|
||||||
|
});
|
||||||
|
|
||||||
|
case LOGIN_SUCCESS:
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
isLoggingIn: false,
|
||||||
|
isAuthenticated: true,
|
||||||
|
userToken: action.token
|
||||||
|
});
|
||||||
|
|
||||||
|
case LOGOUT:
|
||||||
|
return initialState
|
||||||
|
|
||||||
|
case USER_DATA_REQUEST:
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
isFetchingUserData: true
|
||||||
|
});
|
||||||
|
|
||||||
|
case USER_DATA_FAILURE:
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
isFetchingUserData: false,
|
||||||
|
errorMessage: action.errorMessage
|
||||||
|
});
|
||||||
|
|
||||||
|
case USER_DATA_SUCCESS:
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
isFetchingUserData: false,
|
||||||
|
user: action.data
|
||||||
|
});
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import LoginContainer from "../modules/login/LoginContainer";
|
||||||
|
import Icon from 'react-native-vector-icons/SimpleLineIcons';
|
||||||
|
|
||||||
|
export default class LoginScreen extends Component {
|
||||||
|
static navigationOptions = {
|
||||||
|
title: 'Innlogging',
|
||||||
|
};
|
||||||
|
|
||||||
|
onLogin = () => {
|
||||||
|
this.props.navigation.navigate('Membership');
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<LoginContainer onLogin={this.onLogin} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,9 +10,13 @@ export default class MembershipScreen extends Component {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onLoginPress = () => {
|
||||||
|
this.props.navigation.navigate('Login');
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<MembershipContainer />
|
<MembershipContainer onLoginPress={this.onLoginPress} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3258,9 +3258,9 @@ react-native-drawer-layout@1.3.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
react-native-dismiss-keyboard "1.0.0"
|
react-native-dismiss-keyboard "1.0.0"
|
||||||
|
|
||||||
"react-native-drawer@git+https://github.com/GeekyAnts/react-native-drawer.git":
|
"react-native-drawer@https://github.com/GeekyAnts/react-native-drawer":
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "git+https://github.com/GeekyAnts/react-native-drawer.git#8d9078516d177c9cb02d2579a6860706d2370d25"
|
resolved "https://github.com/GeekyAnts/react-native-drawer#8d9078516d177c9cb02d2579a6860706d2370d25"
|
||||||
dependencies:
|
dependencies:
|
||||||
prop-types "^15.5.8"
|
prop-types "^15.5.8"
|
||||||
tween-functions "^1.0.1"
|
tween-functions "^1.0.1"
|
||||||
@@ -3278,9 +3278,9 @@ react-native-htmlview@^0.12.0:
|
|||||||
entities "^1.1.1"
|
entities "^1.1.1"
|
||||||
htmlparser2-without-node-native "^3.9.0"
|
htmlparser2-without-node-native "^3.9.0"
|
||||||
|
|
||||||
"react-native-keyboard-aware-scroll-view@git+https://github.com/GeekyAnts/react-native-keyboard-aware-scroll-view.git":
|
"react-native-keyboard-aware-scroll-view@https://github.com/GeekyAnts/react-native-keyboard-aware-scroll-view":
|
||||||
version "0.2.9"
|
version "0.2.9"
|
||||||
resolved "git+https://github.com/GeekyAnts/react-native-keyboard-aware-scroll-view.git#f4805f254d6cc8e3329f5fb224944401f66655db"
|
resolved "https://github.com/GeekyAnts/react-native-keyboard-aware-scroll-view#f4805f254d6cc8e3329f5fb224944401f66655db"
|
||||||
dependencies:
|
dependencies:
|
||||||
create-react-class "^15.6.0"
|
create-react-class "^15.6.0"
|
||||||
prop-types "^15.5.10"
|
prop-types "^15.5.10"
|
||||||
@@ -3507,6 +3507,10 @@ rebound@^0.0.13:
|
|||||||
version "0.0.13"
|
version "0.0.13"
|
||||||
resolved "https://registry.yarnpkg.com/rebound/-/rebound-0.0.13.tgz#4a225254caf7da756797b19c5817bf7a7941fac1"
|
resolved "https://registry.yarnpkg.com/rebound/-/rebound-0.0.13.tgz#4a225254caf7da756797b19c5817bf7a7941fac1"
|
||||||
|
|
||||||
|
redux-thunk@^2.2.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5"
|
||||||
|
|
||||||
redux@^3.7.2:
|
redux@^3.7.2:
|
||||||
version "3.7.2"
|
version "3.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b"
|
resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b"
|
||||||
|
|||||||
Reference in new issue
Block a user