diff --git a/.gitignore b/.gitignore index 499a56f..055b6e7 100644 --- a/.gitignore +++ b/.gitignore @@ -52,7 +52,7 @@ fastlane/report.xml fastlane/Preview.html fastlane/screenshots -.env +.env* *.swp # Sentry diff --git a/env-example b/env-example index af40e08..f0cd498 100644 --- a/env-example +++ b/env-example @@ -1,6 +1,5 @@ EVENT_API_URL=https://studentersamfundet.no DUSKEN_API_URL=https://galtinn.neuf.no -DUSKEN_PURCHASE_URL=https://galtinn.neuf.no/?utm_source=purchase-button&utm_medium=app DUSKEN_FORGOT_PASSWORD_URL=https://galtinn.neuf.no/auth/password_reset/ SENTRY_DSN= STRIPE_PUBLISHABLE_KEY= \ No newline at end of file diff --git a/package.json b/package.json index 6255e02..d68841d 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "react-native-confetti": "^0.0.6", "react-native-config": "^0.6.1", "react-native-htmlview": "^0.12.0", - "react-native-sentry": "^0.23.2", + "react-native-sentry": "^0.25.0", "react-navigation": "^1.0.0-beta.11", "react-redux": "^5.0.6", "redux": "^3.7.2", diff --git a/src/Dusken.js b/src/Dusken.js index 1007d35..aa5c26a 100644 --- a/src/Dusken.js +++ b/src/Dusken.js @@ -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 }, }); diff --git a/src/actions.js b/src/actions.js index 930845c..b2cf622 100644 --- a/src/actions.js +++ b/src/actions.js @@ -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', diff --git a/src/modules/membership/Charge.js b/src/modules/membership/Charge.js index e5b5a69..eda16e2 100644 --- a/src/modules/membership/Charge.js +++ b/src/modules/membership/Charge.js @@ -10,6 +10,7 @@ stripe.init({ }); export default class Charge extends Component { + // TODO: You are here render() { return In charge view diff --git a/src/modules/membership/Membership.js b/src/modules/membership/Membership.js index 8aed2f0..7925a69 100644 --- a/src/modules/membership/Membership.js +++ b/src/modules/membership/Membership.js @@ -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 { Hei 👋 Her kan du bli medlem i Det Norske Studentersamfund - Chateau Neuf og ha medlemsbeviset ditt på telefonen - + Hva får jeg? @@ -22,16 +20,13 @@ export default class Membership extends Component { - Mulighet til å delta i landets eldste studentdemokrati Allerede medlem? - + ) }; - onLoginPress = () => { - this.props.onLoginPress(); - }; } diff --git a/src/modules/membership/MembershipContainer.js b/src/modules/membership/MembershipContainer.js index d68b98c..729d403 100644 --- a/src/modules/membership/MembershipContainer.js +++ b/src/modules/membership/MembershipContainer.js @@ -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 ; } - return ; + return ; } } diff --git a/src/modules/membership/MembershipProof.js b/src/modules/membership/Proof.js similarity index 96% rename from src/modules/membership/MembershipProof.js rename to src/modules/membership/Proof.js index 7b6cdb2..3894c66 100644 --- a/src/modules/membership/MembershipProof.js +++ b/src/modules/membership/Proof.js @@ -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 + {this.registerbutton()} {this.showSpinner()} @@ -138,6 +144,27 @@ export default class UserRegister extends Component { this.state.phoneNumber, this.state.password, ); + }; + + registerbutton() { + if( this.props.isRegisteringUser || !this.canSubmitForm() ) { + return ( + ); + } + + return (); } } const styles = StyleSheet.create({ diff --git a/src/modules/register/UserRegisterContainer.js b/src/modules/register/UserRegisterContainer.js new file mode 100644 index 0000000..ff85fcf --- /dev/null +++ b/src/modules/register/UserRegisterContainer.js @@ -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 ; + } +} + +function stateToProps(state) { + return { + isAuthenticated: state.isAuthenticated, + isRegisteringUser: state.isRegisteringUser, + registerError: state.registerError + }; +} +export default connect( + stateToProps, + {requestRegisterUser} +)(UserRegisterContainer); \ No newline at end of file diff --git a/src/reducers.js b/src/reducers.js index 5040895..943d4bc 100644 --- a/src/reducers.js +++ b/src/reducers.js @@ -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: diff --git a/src/screens/ChargeScreen.js b/src/screens/ChargeScreen.js new file mode 100644 index 0000000..ab9d586 --- /dev/null +++ b/src/screens/ChargeScreen.js @@ -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 ( + + + + ) + } +} \ No newline at end of file diff --git a/src/screens/LoginScreen.js b/src/screens/LoginScreen.js index 37fbf56..8bbe737 100644 --- a/src/screens/LoginScreen.js +++ b/src/screens/LoginScreen.js @@ -22,7 +22,8 @@ export default class LoginScreen extends Component { render() { return ( - + + ) } diff --git a/src/screens/MembershipScreen.js b/src/screens/MembershipScreen.js index 6c51d52..e46b6ce 100644 --- a/src/screens/MembershipScreen.js +++ b/src/screens/MembershipScreen.js @@ -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 ( - - {/**/} + ) } diff --git a/src/screens/UserRegisterScreen.js b/src/screens/UserRegisterScreen.js new file mode 100644 index 0000000..315a57d --- /dev/null +++ b/src/screens/UserRegisterScreen.js @@ -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 ( + + + + ) + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 509d8eb..5670795 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3582,15 +3582,15 @@ react-native-htmlview@^0.12.0: prop-types "^15.5.10" react-timer-mixin "^0.13.3" -react-native-sentry@^0.23.2: - version "0.23.2" - resolved "https://registry.yarnpkg.com/react-native-sentry/-/react-native-sentry-0.23.2.tgz#f9859263d5d274faa6d17604deae2adc94568234" +react-native-sentry@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/react-native-sentry/-/react-native-sentry-0.25.0.tgz#f7530aa2fc48d71e0088f808a83d72c356e2abd5" dependencies: chalk "^1.1.1" glob "7.1.1" inquirer "3.0.6" raven-js "^3.17.0" - sentry-cli-binary "^1.19.1" + sentry-cli-binary "^1.20.0" xcode "0.9.3" react-native-tab-view@^0.0.65: @@ -4110,9 +4110,9 @@ send@0.13.2: range-parser "~1.0.3" statuses "~1.2.1" -sentry-cli-binary@^1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/sentry-cli-binary/-/sentry-cli-binary-1.19.1.tgz#0abc210ed7f35d7ec0680963e612b15bd2bc14c0" +sentry-cli-binary@^1.20.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/sentry-cli-binary/-/sentry-cli-binary-1.20.0.tgz#a620145863fde98c398adcc2166cf17c0738d513" dependencies: progress "2.0.0"