diff --git a/src/Navigation.js b/src/Navigation.js
index 1794020..39f6c97 100644
--- a/src/Navigation.js
+++ b/src/Navigation.js
@@ -8,8 +8,8 @@ import { createNativeStackNavigator } from '@react-navigation/native-stack';
// import EventListScreen from './screens/EventListScreen';
// import AboutScreen from './screens/AboutScreen';
// import EventDetailScreen from './screens/EventDetailScreen';
-import LoginScreen from './screens/LoginScreen';
-// import MembershipScreen from './screens/MembershipScreen';
+// import LoginScreen from './screens/LoginScreen';
+import MembershipScreen from './screens/MembershipScreen';
// import UserRegisterScreen from './screens/UserRegisterScreen';
// const tabBarRoutes = {
@@ -86,7 +86,8 @@ const DuskenNavigation = () => (
{/* */}
-
+ {/* */}
+
{/* */}
diff --git a/src/hooks.js b/src/hooks.js
new file mode 100644
index 0000000..71b4662
--- /dev/null
+++ b/src/hooks.js
@@ -0,0 +1,14 @@
+/* eslint-disable import/prefer-default-export */
+import { useRef, useEffect } from 'react';
+
+export function usePrevious(value) {
+ const ref = useRef();
+
+ // Store current value in ref
+ useEffect(() => {
+ ref.current = value;
+ }, [value]); // Only re-run if value changes
+
+ // Return previous value (happens before update in useEffect above)
+ return ref.current;
+}
diff --git a/src/modules/membership/Membership.js b/src/modules/membership/Membership.js
index a95be92..27f7d98 100644
--- a/src/modules/membership/Membership.js
+++ b/src/modules/membership/Membership.js
@@ -1,48 +1,33 @@
-import React, { Component } from 'react';
-import { ScrollView, Text, View, StyleSheet } from 'react-native';
-import { Button, Text as NBText, Spinner } from 'native-base';
+import React from 'react';
+import { View, StyleSheet } from 'react-native';
+import { Spinner } from 'native-base';
import theme from '../../theme';
+import useMembership from './useMembership';
+import MembershipInfo from './MembershipInfo';
+import Proof from './Proof';
-export default class Membership extends Component {
- render() {
- if (this.props.isFetchingUserData) {
- return (
-
-
-
- );
- }
+const Membership = () => {
+ const { isFetchingUserData, onRegisterPress, onLoginPress, onLogoutPress, user, isAuthenticated, fetchUser } =
+ useMembership();
+ if (isFetchingUserData) {
return (
-
-
- Hei 👋
-
- Her kan du bli medlem i Det Norske Studentersamfund - Chateau Neuf og ha medlemsbeviset ditt på telefonen
-
-
-
-
- Hva får jeg?
-
- - Minst 25% rabatt på de fleste arrangement{'\n'}- Gratis inngang på enkelte arrangement{'\n'}- Store
- rabatter i barene{'\n'}- Egne medlemsarrangement og -tilbud{'\n'}- Mulighet til å delta i landets eldste
- studentdemokrati
-
- Allerede medlem?
-
-
-
-
-
+
+
+
);
}
-}
+
+ if (isAuthenticated) {
+ return (
+
+ );
+ }
+
+ return ;
+};
+export default Membership;
const styles = StyleSheet.create({
card: theme.card,
diff --git a/src/modules/membership/MembershipContainer.js b/src/modules/membership/MembershipContainer.js
deleted file mode 100644
index 9c7b59c..0000000
--- a/src/modules/membership/MembershipContainer.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-
-import Membership from './Membership';
-import Proof from './Proof';
-import { logout } from '../../actions';
-import { requestUserData } from '../../api';
-
-class MembershipContainer extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- isFetchingUserData: props.isFetchingUserData,
- userToken: props.userToken,
- lastOrder: props.lastOrder,
- };
- }
-
- componentWillReceiveProps(nextProps) {
- if (this.state.userToken !== nextProps.userToken) {
- this.setState({ userToken: nextProps.userToken }, () => {
- if (nextProps.userToken) {
- this.fetchUser();
- }
- });
- }
- if (this.state.lastOrder !== nextProps.lastOrder) {
- this.setState({ lastOrder: nextProps.lastOrder }, () => {
- if (nextProps.userToken) {
- this.fetchUser();
- }
- });
- }
- }
-
- fetchUser = () => {
- this.props.requestUserData(this.state.userToken);
- };
-
- onLoginPress = () => {
- this.props.onLoginPress();
- };
-
- onRegisterPress = () => {
- this.props.onRegisterPress();
- };
-
- onLogoutPress = () => {
- this.props.logout();
- this.props.onLogoutPress();
- };
-
- render() {
- if (this.props.user) {
- return (
-
- );
- }
- return (
-
- );
- }
-}
-
-function storeToProps(store) {
- return {
- isAuthenticated: store.isAuthenticated,
- isFetchingUserData: store.isFetchingUserData,
- userToken: store.userToken,
- user: store.user,
- lastOrder: store.lastOrder,
- };
-}
-
-export default connect(storeToProps, { requestUserData, logout })(MembershipContainer);
diff --git a/src/modules/membership/MembershipInfo.js b/src/modules/membership/MembershipInfo.js
new file mode 100644
index 0000000..1d1c6c9
--- /dev/null
+++ b/src/modules/membership/MembershipInfo.js
@@ -0,0 +1,71 @@
+import React from 'react';
+
+import { ScrollView, Text, View, StyleSheet } from 'react-native';
+import { Button, Text as NBText } from 'native-base';
+import theme from '../../theme';
+
+const MembershipInfo = ({ onRegister, onLogin }) => (
+
+
+ Hei 👋
+
+ Her kan du bli medlem i Det Norske Studentersamfund - Chateau Neuf og ha medlemsbeviset ditt på telefonen
+
+
+
+
+ Hva får jeg?
+
+ - Minst 25% rabatt på de fleste arrangement{'\n'}- Gratis inngang på enkelte arrangement{'\n'}- Store rabatter i
+ barene{'\n'}- Egne medlemsarrangement og -tilbud{'\n'}- Mulighet til å delta i landets eldste studentdemokrati
+
+ Allerede medlem?
+
+
+
+
+
+);
+
+export default MembershipInfo;
+
+const styles = StyleSheet.create({
+ card: theme.card,
+ paragraph: {
+ textAlign: 'center',
+ fontSize: 16,
+ color: '#000',
+ paddingBottom: 10,
+ lineHeight: 25,
+ },
+ button: {
+ marginTop: 6,
+ marginBottom: 16,
+ },
+ em: {
+ fontSize: 16,
+ color: '#000',
+ fontStyle: 'italic',
+ textAlign: 'center',
+ marginVertical: 10,
+ },
+ headerTitle: {
+ textAlign: 'center',
+ fontWeight: 'bold',
+ fontSize: 20,
+ color: '#000',
+ paddingVertical: 10,
+ lineHeight: 25,
+ },
+ header: {
+ fontSize: 16,
+ fontWeight: 'bold',
+ color: '#000',
+ lineHeight: 25,
+ paddingLeft: 2,
+ },
+});
diff --git a/src/modules/membership/Proof.js b/src/modules/membership/Proof.js
index 13400c8..7828371 100644
--- a/src/modules/membership/Proof.js
+++ b/src/modules/membership/Proof.js
@@ -144,6 +144,15 @@ const Proof = ({ onLogoutPress, user, fetchUser, isFetchingUserData }) => {
}, CONFETTI_TIMEOUT);
};
+ if (!user) {
+ console.log('🔥', user);
+ return (
+
+ No user!
+
+ );
+ }
+
return (
diff --git a/src/modules/membership/useMembership.js b/src/modules/membership/useMembership.js
new file mode 100644
index 0000000..246ac5a
--- /dev/null
+++ b/src/modules/membership/useMembership.js
@@ -0,0 +1,52 @@
+import { useNavigation } from '@react-navigation/native';
+import { useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+
+import { logout } from '../../actions';
+import { requestUserData } from '../../api';
+import { usePrevious } from '../../hooks';
+
+const useMembership = () => {
+ const navigation = useNavigation();
+ const dispatch = useDispatch();
+ const { isAuthenticated, isFetchingUserData, userToken, user, lastOrder } = useSelector((store) => ({
+ isAuthenticated: store.isAuthenticated,
+ isFetchingUserData: store.isFetchingUserData,
+ userToken: store.userToken,
+ user: store.user,
+ lastOrder: store.lastOrder,
+ }));
+ const prevUserToken = usePrevious(userToken);
+ const prevLastOrder = usePrevious(lastOrder);
+
+ const onLogoutPress = () => {
+ dispatch(logout());
+ navigation.navigate('Membership');
+ };
+ const onRegisterPress = () => navigation.navigate('UserRegister');
+ const onLoginPress = () => navigation.navigate('Login');
+ const fetchUser = () => {
+ dispatch(requestUserData(userToken));
+ };
+
+ useEffect(() => {
+ if (userToken !== prevUserToken && userToken) {
+ fetchUser();
+ }
+ if (prevLastOrder !== lastOrder && userToken) {
+ fetchUser();
+ }
+ }, [userToken, prevUserToken, lastOrder, prevLastOrder, fetchUser]);
+
+ return {
+ isAuthenticated,
+ isFetchingUserData,
+ userToken,
+ user,
+ lastOrder,
+ onLogoutPress,
+ onRegisterPress,
+ onLoginPress,
+ };
+};
+export default useMembership;
diff --git a/src/modules/membership/useProof.js b/src/modules/membership/useProof.js
index 8fd60ab..806e71a 100644
--- a/src/modules/membership/useProof.js
+++ b/src/modules/membership/useProof.js
@@ -1,14 +1,15 @@
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
-import stripe from 'tipsi-stripe';
+// import stripe from 'tipsi-stripe';
import Config from 'react-native-config';
import { gql, useQuery } from '@apollo/client';
import { requestMembershipCharge } from '../../api';
-stripe.setOptions({
- publishableKey: Config.STRIPE_PUBLISHABLE_KEY || '',
-});
+// TODO: switch to official stripe client
+// stripe.setOptions({
+// publishableKey: Config.STRIPE_PUBLISHABLE_KEY || '',
+// });
const PROOF_QUERY = gql`
{
@@ -44,22 +45,22 @@ const useProof = ({ user, fetchUser }) => {
smsAutofillDisabled: true,
};
- const membershipTypeSlug = data.membershipTypes ? data.membershipTypes[0].slug : 'standard';
+ const membershipTypeSlug = data?.membershipTypes?.[0]?.slug ?? 'standard';
- stripe.paymentRequestWithCardForm(options).then(
- (token) => {
- // returns a token.tokenId which should be saved
- dispatch(requestMembershipCharge(userToken, { id: token.tokenId, email: user.email }, membershipTypeSlug));
- },
- () => {
- /* FIXME: Happens only if card dialog is canceled? */
- }
- );
+ // stripe.paymentRequestWithCardForm(options).then(
+ // (token) => {
+ // // returns a token.tokenId which should be saved
+ // dispatch(requestMembershipCharge(userToken, { id: token.tokenId, email: user.email }, membershipTypeSlug));
+ // },
+ // () => {
+ // /* FIXME: Happens only if card dialog is canceled? */
+ // }
+ // );
};
useEffect(() => {
const todaysDate = new Date().toISOString().substring(0, 10);
- const lastMembership = user.last_membership;
+ const lastMembership = user?.last_membership;
if (lastMembership && lastMembership.membership_type !== 'lifelong' && lastMembership.end_date < todaysDate) {
fetchUser();
}
@@ -69,7 +70,7 @@ const useProof = ({ user, fetchUser }) => {
chargeError: chargeError || '',
isChargingMembership,
isLoadingMembershipType: loading,
- membershipPrice: getPrice(data.membershipTypes),
+ membershipPrice: getPrice(data?.membershipTypes),
onChargePress: openStripe,
};
};
diff --git a/src/screens/LoginScreen.js b/src/screens/LoginScreen.js
index f8812fa..1b97c12 100644
--- a/src/screens/LoginScreen.js
+++ b/src/screens/LoginScreen.js
@@ -2,7 +2,6 @@ import React from 'react';
import Login from '../modules/login/Login';
-// navigation.goBack onLogin works since LoginScreen is allways navigated to from MembershipScreen
const LoginScreen = () => {
return ;
};
diff --git a/src/screens/MembershipScreen.js b/src/screens/MembershipScreen.js
index 72ce1b3..5d659cd 100644
--- a/src/screens/MembershipScreen.js
+++ b/src/screens/MembershipScreen.js
@@ -1,8 +1,6 @@
import React, { Component } from 'react';
import Icon from 'react-native-vector-icons/SimpleLineIcons';
-import { StyleProvider } from 'native-base';
-import MembershipContainer from '../modules/membership/MembershipContainer';
-import getTheme from '../../native-base-theme/components';
+import Membership from '../modules/membership/Membership';
export default class MembershipScreen extends Component {
static navigationOptions = {
@@ -10,27 +8,7 @@ export default class MembershipScreen extends Component {
tabBarIcon: ({ tintColor }) => ,
};
- loginNavigate = () => {
- this.props.navigation.navigate('Login');
- };
-
- logoutNavigate = () => {
- this.props.navigation.navigate('Membership');
- };
-
- registerNavigate = () => {
- this.props.navigation.navigate('UserRegister');
- };
-
render() {
- return (
-
-
-
- );
+ return ;
}
}