Archived
Mostly working user registration
Refactor a bit Up next: card purchase
This commit is contained in:
1 parent
be5c49fa04
commit
2d4d0b2cf4
19 files changed
+223
-71
No files matched your search
@@ -8,6 +8,8 @@ import EventDetailScreen from "./screens/EventDetailScreen";
|
||||
import EventListScreen from "./screens/EventListScreen";
|
||||
import LoginScreen from "./screens/LoginScreen";
|
||||
import MembershipScreen from "./screens/MembershipScreen";
|
||||
import UserRegisterScreen from "./screens/UserRegisterScreen";
|
||||
import ChargeScreen from "./screens/ChargeScreen";
|
||||
|
||||
|
||||
/* Navigation */
|
||||
@@ -46,6 +48,8 @@ const tabNav = TabNavigator(tabBarRoutes, tabBarOptions);
|
||||
const DuskenContainer = StackNavigator({
|
||||
Root: { screen: tabNav },
|
||||
Login: { screen: LoginScreen },
|
||||
UserRegister: { screen: UserRegisterScreen },
|
||||
Charge: { screen: ChargeScreen },
|
||||
EventDetail: { screen: EventDetailScreen },
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -161,7 +161,7 @@ export function requestRegisterUser(firstName, lastName, email, phoneNumber, pas
|
||||
return (dispatch) => {
|
||||
dispatch(registerUserRequest());
|
||||
|
||||
return fetch(`${Config.DUSKEN_API_URL}/api/user/register`, {
|
||||
return fetch(`${Config.DUSKEN_API_URL}/api/user/register/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
|
||||
@@ -10,6 +10,7 @@ stripe.init({
|
||||
});
|
||||
|
||||
export default class Charge extends Component {
|
||||
// TODO: You are here
|
||||
render() {
|
||||
return <View>
|
||||
<Text>In charge view</Text>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import React, {Component} from 'react';
|
||||
import {ScrollView, Text, View, Linking, StyleSheet, Platform} from "react-native";
|
||||
import {Button, Text as NBText} from "native-base";
|
||||
import Config from 'react-native-config';
|
||||
|
||||
export default class Membership extends Component {
|
||||
render() {
|
||||
return (
|
||||
@@ -11,7 +9,7 @@ export default class Membership extends Component {
|
||||
<Text style={styles.headerTitle}>Hei 👋</Text>
|
||||
<Text style={styles.paragraph}>Her kan du bli medlem i Det Norske Studentersamfund - Chateau Neuf og ha medlemsbeviset ditt på telefonen</Text>
|
||||
<View style={styles.button}>
|
||||
<Button onPress={() => { Linking.openURL(Config.DUSKEN_PURCHASE_URL); } } full><NBText>Bli medlem</NBText></Button>
|
||||
<Button onPress={this.props.onRegisterPress} full><NBText>Bli medlem</NBText></Button>
|
||||
</View>
|
||||
<Text style={styles.header}>Hva får jeg?</Text>
|
||||
<Text style={[styles.paragraph, {textAlign: 'left', paddingLeft: 4}]}>
|
||||
@@ -22,16 +20,13 @@ export default class Membership extends Component {
|
||||
- Mulighet til å delta i landets eldste studentdemokrati</Text>
|
||||
<Text style={styles.em}>Allerede medlem?</Text>
|
||||
<View style={styles.button}>
|
||||
<Button onPress={this.onLoginPress} full><NBText>Logg inn</NBText></Button>
|
||||
<Button onPress={this.props.onLoginPress} full><NBText>Logg inn</NBText></Button>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
)
|
||||
};
|
||||
|
||||
onLoginPress = () => {
|
||||
this.props.onLoginPress();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, {Component} from 'react';
|
||||
import {connect} from "react-redux";
|
||||
|
||||
import Membership from "./Membership";
|
||||
import MembershipProof from "./MembershipProof";
|
||||
import Proof from "./Proof";
|
||||
import { requestUserData, logout } from "../../actions";
|
||||
|
||||
class MembershipContainer extends Component {
|
||||
@@ -42,20 +42,29 @@ class MembershipContainer extends Component {
|
||||
this.props.onLoginPress();
|
||||
};
|
||||
|
||||
onRegisterPress = () => {
|
||||
this.props.onRegisterPress();
|
||||
};
|
||||
|
||||
onChargePress = () => {
|
||||
this.props.onChargePress();
|
||||
};
|
||||
|
||||
onLogoutPress = () => {
|
||||
this.props.logout();
|
||||
this.props.logoutNavigate();
|
||||
this.props.onLogoutPress();
|
||||
};
|
||||
|
||||
render() {
|
||||
if (this.state.user) {
|
||||
return <MembershipProof
|
||||
return <Proof
|
||||
user={this.state.user}
|
||||
fetchUser={this.fetchUser}
|
||||
onLogoutPress={this.onLogoutPress}
|
||||
onChargePress={this.onChargePress}
|
||||
/>;
|
||||
}
|
||||
return <Membership onLoginPress={this.onLoginPress}/>;
|
||||
return <Membership onLoginPress={this.onLoginPress} onRegisterPress={this.onRegisterPress} />;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Image, Linking, StyleSheet, Platform, RefreshControl, TouchableOpacity, View} from "react-native";
|
||||
import {Button, Body, Card, CardItem, Text, Content} from 'native-base';
|
||||
import Config from 'react-native-config';
|
||||
import Confetti from 'react-native-confetti';
|
||||
|
||||
export default class MembershipProof extends Component {
|
||||
export default class Proof extends Component {
|
||||
// FIXME: Move logic to container
|
||||
CONFETTI_TIMEOUT = 15000;
|
||||
|
||||
constructor(props) {
|
||||
@@ -120,9 +120,7 @@ export default class MembershipProof extends Component {
|
||||
return <CardItem>
|
||||
<Body>
|
||||
<Button
|
||||
onPress={() => {
|
||||
Linking.openURL(Config.DUSKEN_PURCHASE_URL);
|
||||
}}
|
||||
onPress={this.props.onChargePress}
|
||||
full
|
||||
style={styles.purchaseButton}
|
||||
>
|
||||
@@ -0,0 +1,15 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from "react-redux";
|
||||
|
||||
import Proof from "./Proof";
|
||||
|
||||
class ProofContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
render() {
|
||||
return <Proof />
|
||||
}
|
||||
}
|
||||
|
||||
export default connect()(ProofContainer);
|
||||
@@ -1,25 +0,0 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from "react-redux";
|
||||
import UserRegister from "./UserRegister";
|
||||
import {requestRegisterUser} from "../../actions";
|
||||
|
||||
class UserRegisterContainer extends Component {
|
||||
onRegisterPress = (firstName, lastName, email, phoneNumber, password) => {
|
||||
this.props.requestRegisterUser(firstName, lastName, email, phoneNumber, password);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <UserRegister {...this.props} onRegisterPress={this.onRegisterPress} />;
|
||||
}
|
||||
}
|
||||
|
||||
function stateToProps(state) {
|
||||
return {
|
||||
isRegisteringUser: state.isRegisteringUser,
|
||||
registerError: state.registerError
|
||||
};
|
||||
}
|
||||
export default connect(
|
||||
stateToProps,
|
||||
{requestRegisterUser}
|
||||
)(UserRegisterContainer);
|
||||
@@ -14,6 +14,18 @@ export default class UserRegister extends Component {
|
||||
password: ''
|
||||
}
|
||||
}
|
||||
|
||||
canSubmitForm() {
|
||||
/* No empty fields */
|
||||
for([key, value] of Object.entries(this.state)) {
|
||||
if(value === '') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
emailInput() {
|
||||
return <Item stackedLabel last>
|
||||
<Label>E-post</Label>
|
||||
@@ -51,10 +63,10 @@ export default class UserRegister extends Component {
|
||||
}
|
||||
|
||||
showError = () => {
|
||||
if (this.props.registerError) {
|
||||
// TODO: Format these and highlight error fields
|
||||
if (this.props.registerError && Object.keys(this.props.registerError).length !== 0) {
|
||||
const err = this.props.registerError.non_field_errors;
|
||||
let errorFormatted = err ? err[0] : 'Generell feil, prøv igjen...';
|
||||
// TODO: Format these and highlight error fields
|
||||
let errorFormatted = err ? err[0] : 'Kunne ikke registrere bruker, prøv igjen...';
|
||||
return <View style={styles.errorBox}><Text style={styles.errorMessage}>{errorFormatted}</Text></View>
|
||||
}
|
||||
else {
|
||||
@@ -116,13 +128,7 @@ export default class UserRegister extends Component {
|
||||
</Item>
|
||||
{this.passwordInput()}
|
||||
{this.showError()}
|
||||
<Button
|
||||
full
|
||||
onPress={this.onRegisterPress}
|
||||
style={styles.registerButton}
|
||||
>
|
||||
<Text>Registrer</Text>
|
||||
</Button>
|
||||
{this.registerbutton()}
|
||||
{this.showSpinner()}
|
||||
</Form>
|
||||
</Content>
|
||||
@@ -138,6 +144,27 @@ export default class UserRegister extends Component {
|
||||
this.state.phoneNumber,
|
||||
this.state.password,
|
||||
);
|
||||
};
|
||||
|
||||
registerbutton() {
|
||||
if( this.props.isRegisteringUser || !this.canSubmitForm() ) {
|
||||
return (
|
||||
<Button
|
||||
full
|
||||
disabled
|
||||
style={styles.registerButton}
|
||||
>
|
||||
<Text>Registrer</Text>
|
||||
</Button>);
|
||||
}
|
||||
|
||||
return (<Button
|
||||
full
|
||||
onPress={this.onRegisterPress}
|
||||
style={styles.registerButton}
|
||||
>
|
||||
<Text>Registrer</Text>
|
||||
</Button>);
|
||||
}
|
||||
}
|
||||
const styles = StyleSheet.create({
|
||||
@@ -0,0 +1,50 @@
|
||||
import React, {Component} from 'react';
|
||||
import {connect} from "react-redux";
|
||||
import UserRegister from "./UserRegister";
|
||||
import {requestRegisterUser} from "../../actions";
|
||||
|
||||
class UserRegisterContainer extends Component {
|
||||
|
||||
constructor(state) {
|
||||
super(state);
|
||||
this.state = {
|
||||
isAuthenticated: false,
|
||||
isRegisteringUser: false,
|
||||
registerError: null
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.state.isAuthenticated !== nextProps.isAuthenticated) {
|
||||
if (nextProps.isAuthenticated) {
|
||||
this.props.onRegister();
|
||||
}
|
||||
}
|
||||
if (this.state.isRegisteringUser !== nextProps.isRegisteringUser) {
|
||||
this.setState({isRegisteringUser: nextProps.isRegisteringUser});
|
||||
}
|
||||
if (this.state.registerError !== nextProps.registerError) {
|
||||
this.setState({registerError: nextProps.registerError});
|
||||
}
|
||||
}
|
||||
|
||||
onRegisterPress = (firstName, lastName, email, phoneNumber, password) => {
|
||||
this.props.requestRegisterUser(firstName, lastName, email, phoneNumber, password);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <UserRegister {...this.state} onRegisterPress={this.onRegisterPress} />;
|
||||
}
|
||||
}
|
||||
|
||||
function stateToProps(state) {
|
||||
return {
|
||||
isAuthenticated: state.isAuthenticated,
|
||||
isRegisteringUser: state.isRegisteringUser,
|
||||
registerError: state.registerError
|
||||
};
|
||||
}
|
||||
export default connect(
|
||||
stateToProps,
|
||||
{requestRegisterUser}
|
||||
)(UserRegisterContainer);
|
||||
+12
-4
@@ -51,7 +51,8 @@ export default function duskenApp(state = initialState, action) {
|
||||
/* User data */
|
||||
case USER_DATA_REQUEST:
|
||||
return Object.assign({}, state, {
|
||||
isFetchingUserData: true
|
||||
isFetchingUserData: true,
|
||||
userError: null
|
||||
});
|
||||
|
||||
case USER_DATA_FAILURE:
|
||||
@@ -63,13 +64,14 @@ export default function duskenApp(state = initialState, action) {
|
||||
case USER_DATA_SUCCESS:
|
||||
return Object.assign({}, state, {
|
||||
isFetchingUserData: false,
|
||||
user: action.data
|
||||
user: action.data,
|
||||
});
|
||||
|
||||
/* Register user */
|
||||
case REGISTER_USER_REQUEST:
|
||||
return Object.assign({}, state, {
|
||||
isRegisteringUser: true
|
||||
isRegisteringUser: true,
|
||||
registerError: null,
|
||||
});
|
||||
|
||||
case REGISTER_USER_FAILURE:
|
||||
@@ -79,9 +81,15 @@ export default function duskenApp(state = initialState, action) {
|
||||
});
|
||||
|
||||
case REGISTER_USER_SUCCESS:
|
||||
let userData = action.data;
|
||||
const token = action.data.auth_token;
|
||||
delete userData['auth_token'];
|
||||
|
||||
return Object.assign({}, state, {
|
||||
isRegisteringUser: false,
|
||||
user: action.data
|
||||
isAuthenticated: true,
|
||||
user: userData,
|
||||
userToken: token,
|
||||
});
|
||||
|
||||
default:
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import React, { Component } from 'react';
|
||||
import Charge from "../modules/membership/Charge";
|
||||
import {StyleProvider} from "native-base";
|
||||
import getTheme from '../../native-base-theme/components';
|
||||
|
||||
export default class ChargeScreen extends Component {
|
||||
static navigationOptions = {
|
||||
title: 'Kjøp medlemskap',
|
||||
headerStyle: {
|
||||
backgroundColor: '#f58220',
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: 'white',
|
||||
},
|
||||
headerTintColor: 'white',
|
||||
};
|
||||
|
||||
onCharged = () => {
|
||||
// This works since ChargeScreen is allways navigated to from MembershipScreen
|
||||
this.props.navigation.goBack();
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<StyleProvider style={getTheme()}>
|
||||
<Charge onCharged={this.onCharged} />
|
||||
</StyleProvider>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,8 @@ export default class LoginScreen extends Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<StyleProvider style={getTheme()}><LoginContainer onLogin={this.onLogin} />
|
||||
<StyleProvider style={getTheme()}>
|
||||
<LoginContainer onLogin={this.onLogin} />
|
||||
</StyleProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import MembershipContainer from "../modules/membership/MembershipContainer";
|
||||
import Icon from 'react-native-vector-icons/SimpleLineIcons';
|
||||
import {StyleProvider} from "native-base";
|
||||
import getTheme from '../../native-base-theme/components';
|
||||
import UserRegisterContainer from "../modules/membership/UserRegisterContainer";
|
||||
|
||||
export default class MembershipScreen extends Component {
|
||||
static navigationOptions = {
|
||||
@@ -20,7 +19,7 @@ export default class MembershipScreen extends Component {
|
||||
),
|
||||
};
|
||||
|
||||
onLoginPress = () => {
|
||||
loginNavigate = () => {
|
||||
this.props.navigation.navigate('Login');
|
||||
};
|
||||
|
||||
@@ -28,11 +27,22 @@ export default class MembershipScreen extends Component {
|
||||
this.props.navigation.navigate('Membership');
|
||||
};
|
||||
|
||||
registerNavigate = () => {
|
||||
this.props.navigation.navigate('UserRegister');
|
||||
};
|
||||
|
||||
chargeNavigate = () => {
|
||||
this.props.navigation.navigate('Charge');
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<StyleProvider style={getTheme()}>
|
||||
<UserRegisterContainer/>
|
||||
{/*<MembershipContainer onLoginPress={this.onLoginPress} logoutNavigate={this.logoutNavigate} />*/}
|
||||
<MembershipContainer
|
||||
onLoginPress={this.loginNavigate}
|
||||
onLogoutPress={this.logoutNavigate}
|
||||
onRegisterPress={this.registerNavigate}
|
||||
onChargePress={this.chargeNavigate} />
|
||||
</StyleProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import React, { Component } from 'react';
|
||||
import UserRegisterContainer from "../modules/register/UserRegisterContainer";
|
||||
import {StyleProvider} from "native-base";
|
||||
import getTheme from '../../native-base-theme/components';
|
||||
|
||||
export default class UserRegisterScreen extends Component {
|
||||
static navigationOptions = {
|
||||
title: 'Registrer',
|
||||
headerStyle: {
|
||||
backgroundColor: '#f58220',
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: 'white',
|
||||
},
|
||||
headerTintColor: 'white',
|
||||
};
|
||||
|
||||
onRegister = () => {
|
||||
// This works since UserRegisterScreen is allways navigated to from MembershipScreen
|
||||
this.props.navigation.goBack();
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<StyleProvider style={getTheme()}>
|
||||
<UserRegisterContainer onRegister={this.onRegister} />
|
||||
</StyleProvider>
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user