Migrate to typescript 💥
This commit is contained in:
36 files changed
+392
-131
No files matched your search
@@ -13,8 +13,9 @@ import {
|
||||
} from 'react-native';
|
||||
import { Button } from 'react-native-ui-lib';
|
||||
|
||||
import theme from 'src/theme';
|
||||
|
||||
import logo from '../../../assets/DNS-logo-svart.png';
|
||||
import theme from '../../theme';
|
||||
|
||||
const CHATEAU_NEUF_ADDRESS = 'Det Norske Studentersamfund, Slemdalsveien 15, 0369 Oslo';
|
||||
|
||||
@@ -14,7 +14,8 @@ import {
|
||||
} from 'react-native';
|
||||
import RenderHtml from 'react-native-render-html';
|
||||
|
||||
import theme from '../../theme';
|
||||
import theme from 'src/theme';
|
||||
import type { EventDetailProps } from 'src/types/navigation';
|
||||
|
||||
moment.locale('nb');
|
||||
|
||||
@@ -157,7 +158,7 @@ const EventDetail = ({
|
||||
route: {
|
||||
params: { event },
|
||||
},
|
||||
}) => {
|
||||
}: EventDetailProps) => {
|
||||
const { width } = useWindowDimensions();
|
||||
return (
|
||||
<ScrollView>
|
||||
@@ -5,12 +5,13 @@ import { StyleSheet, View, Platform, SectionList, TouchableOpacity } from 'react
|
||||
import { Button } from 'react-native-ui-lib';
|
||||
import 'moment/locale/nb';
|
||||
|
||||
import theme from 'src/theme';
|
||||
|
||||
import useEventList from './useEventList';
|
||||
import theme from '../../theme';
|
||||
|
||||
moment.locale('nb');
|
||||
|
||||
const _formatTime = (time) => {
|
||||
const formatTime = (time: string) => {
|
||||
return moment(time).format('llll');
|
||||
};
|
||||
|
||||
@@ -36,7 +37,7 @@ const EventList = () => {
|
||||
<Text style={styles.listItemTitle} numberOfLines={1}>
|
||||
{item.title.decoded}
|
||||
</Text>
|
||||
<Text style={styles.listItemTime}>{_formatTime(item.start_time)}</Text>
|
||||
<Text style={styles.listItemTime}>{formatTime(item.start_time)}</Text>
|
||||
</View>
|
||||
<View style={styles.arrow}>
|
||||
<ArrowForwardIcon size={4} color={theme.colors.neufBlack} marginTop={3} />
|
||||
@@ -80,7 +81,7 @@ const EventList = () => {
|
||||
refreshing={refreshing}
|
||||
onRefresh={handleRefresh}
|
||||
onEndReached={handleLoadMore}
|
||||
onEndReachedThreshould={10}
|
||||
onEndReachedThreshold={10}
|
||||
initialNumToRender={10}
|
||||
ListFooterComponent={Footer}
|
||||
style={[styles.card, styles.list]}
|
||||
@@ -1,9 +1,10 @@
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import moment from 'moment';
|
||||
import { useEffect, useState } from 'react';
|
||||
import 'moment/locale/nb';
|
||||
|
||||
import { fetchWithTimeout } from '../../utils';
|
||||
import 'moment/locale/nb';
|
||||
import type { EventType } from 'src/types/data';
|
||||
import { fetchWithTimeout } from 'src/utils';
|
||||
|
||||
moment.locale('nb');
|
||||
|
||||
@@ -81,8 +82,8 @@ const useEventList = () => {
|
||||
}, []);
|
||||
|
||||
return {
|
||||
showEvent: (event) => {
|
||||
navigate('EventDetail', { event });
|
||||
showEvent: (event: EventType) => {
|
||||
navigate('EventStack', { screen: 'EventDetail', params: { event } });
|
||||
},
|
||||
handleRefresh,
|
||||
handleLoadMore,
|
||||
@@ -3,13 +3,14 @@ import React from 'react';
|
||||
import { ActivityIndicator, Linking, StyleSheet, View, Text } from 'react-native';
|
||||
import { Button } from 'react-native-ui-lib';
|
||||
|
||||
import FormErrors from 'src/components/FormErrors';
|
||||
import FormInput from 'src/components/FormInput';
|
||||
import theme from 'src/theme';
|
||||
|
||||
import useLogin from './useLogin';
|
||||
import FormErrors from '../../components/FormErrors';
|
||||
import FormInput from '../../components/FormInput';
|
||||
import theme from '../../theme';
|
||||
|
||||
const Login = () => {
|
||||
const { isLoggingIn, errors, control, setFocus, onSubmit } = useLogin();
|
||||
const { isLoggingIn, errors, setFocus, onSubmit } = useLogin();
|
||||
|
||||
return (
|
||||
<ScrollView>
|
||||
@@ -19,8 +20,6 @@ const Login = () => {
|
||||
name="email"
|
||||
label="E-post / Brukernavn"
|
||||
keyboardType="email-address"
|
||||
control={control}
|
||||
errors={errors}
|
||||
autoFocus
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
@@ -30,8 +29,6 @@ const Login = () => {
|
||||
name="password"
|
||||
label="Passord"
|
||||
secureTextEntry
|
||||
control={control}
|
||||
errors={errors}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
onSubmitEditing={onSubmit}
|
||||
@@ -1,25 +1,29 @@
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { useEffect } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { requestLogin } from '../../api';
|
||||
import { requestLogin } from 'src/api';
|
||||
import { useAppDispatch, useAppSelector } from 'src/hooks';
|
||||
|
||||
interface LoginFormValues {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
const useLogin = () => {
|
||||
const navigation = useNavigation();
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const isAuthenticated = useSelector((store) => store.isAuthenticated);
|
||||
const isLoggingIn = useSelector((store) => store.isLoggingIn);
|
||||
const loginError = useSelector((store) => store.loginError);
|
||||
const isAuthenticated = useAppSelector((store) => store.isAuthenticated);
|
||||
const isLoggingIn = useAppSelector((store) => store.isLoggingIn);
|
||||
const loginError = useAppSelector((store) => store.loginError);
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
setFocus,
|
||||
} = useForm();
|
||||
} = useForm<LoginFormValues>();
|
||||
|
||||
const onSubmit = handleSubmit(({ email, password }) => {
|
||||
dispatch(requestLogin(email, password));
|
||||
@@ -32,7 +36,7 @@ const useLogin = () => {
|
||||
}
|
||||
}, [isAuthenticated, navigation]);
|
||||
|
||||
return { onSubmit, isLoggingIn, control, setFocus, errors: { ...errors, ...loginError } };
|
||||
return { onSubmit, isLoggingIn, setFocus, errors: { ...errors, ...loginError } };
|
||||
};
|
||||
|
||||
export default useLogin;
|
||||
@@ -1,10 +1,11 @@
|
||||
import React from 'react';
|
||||
import { View, StyleSheet, ActivityIndicator } from 'react-native';
|
||||
|
||||
import theme from 'src/theme';
|
||||
|
||||
import MembershipInfo from './MembershipInfo';
|
||||
import Proof from './Proof';
|
||||
import useMembership from './useMembership';
|
||||
import theme from '../../theme';
|
||||
|
||||
const Membership = () => {
|
||||
const { isFetchingUserData, onRegisterPress, onLoginPress, onLogoutPress, user, isAuthenticated, fetchUser } =
|
||||
+1
-1
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { ScrollView, Text, View, StyleSheet } from 'react-native';
|
||||
import { Button } from 'react-native-ui-lib';
|
||||
|
||||
import theme from '../../theme';
|
||||
import theme from 'src/theme';
|
||||
|
||||
const MembershipInfo = ({ onRegister, onLogin }) => (
|
||||
<ScrollView>
|
||||
@@ -13,9 +13,10 @@ import {
|
||||
import Confetti from 'react-native-confetti';
|
||||
import { Button, Incubator } from 'react-native-ui-lib';
|
||||
|
||||
import theme from 'src/theme';
|
||||
|
||||
import useProof from './useProof';
|
||||
import logo from '../../../assets/DNS-logo-svart.png';
|
||||
import theme from '../../theme';
|
||||
|
||||
const { Toast } = Incubator;
|
||||
|
||||
+12
-13
@@ -1,28 +1,27 @@
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { useEffect, useCallback } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { logout } from '../../actions';
|
||||
import { requestUserData } from '../../api';
|
||||
import { usePrevious } from '../../hooks';
|
||||
import { logout } from 'src/actions';
|
||||
import { requestUserData } from 'src/api';
|
||||
import { useAppDispatch, useAppSelector, usePrevious } from 'src/hooks';
|
||||
|
||||
const useMembership = () => {
|
||||
const navigation = useNavigation();
|
||||
const dispatch = useDispatch();
|
||||
const isAuthenticated = useSelector((store) => store.isAuthenticated);
|
||||
const isFetchingUserData = useSelector((store) => store.isFetchingUserData);
|
||||
const lastOrder = useSelector((store) => store.lastOrder);
|
||||
const user = useSelector((store) => store.user);
|
||||
const userToken = useSelector((store) => store.userToken);
|
||||
const dispatch = useAppDispatch();
|
||||
const isAuthenticated = useAppSelector((store) => store.isAuthenticated);
|
||||
const isFetchingUserData = useAppSelector((store) => store.isFetchingUserData);
|
||||
const lastOrder = useAppSelector((store) => store.lastOrder);
|
||||
const user = useAppSelector((store) => store.user);
|
||||
const userToken = useAppSelector((store) => store.userToken);
|
||||
const prevUserToken = usePrevious(userToken);
|
||||
const prevLastOrder = usePrevious(lastOrder);
|
||||
|
||||
const onLogoutPress = () => {
|
||||
dispatch(logout());
|
||||
navigation.navigate('Membership');
|
||||
navigation.navigate('UserStack', { screen: 'Membership' });
|
||||
};
|
||||
const onRegisterPress = () => navigation.navigate('UserRegister');
|
||||
const onLoginPress = () => navigation.navigate('Login');
|
||||
const onRegisterPress = () => navigation.navigate('UserStack', { screen: 'UserRegister' });
|
||||
const onLoginPress = () => navigation.navigate('UserStack', { screen: 'Login' });
|
||||
const fetchUser = useCallback(() => {
|
||||
dispatch(requestUserData(userToken));
|
||||
}, [dispatch, userToken]);
|
||||
@@ -4,7 +4,8 @@ import Constants from 'expo-constants';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { requestStripePaymentSheet } from '../../api';
|
||||
import { requestStripePaymentSheet } from 'src/api';
|
||||
import { RootState } from 'src/reduxStore';
|
||||
|
||||
const PROOF_QUERY = gql`
|
||||
{
|
||||
@@ -24,8 +25,8 @@ function getPrice(membershipTypes) {
|
||||
}
|
||||
|
||||
const useProof = ({ user, fetchUser }) => {
|
||||
const userToken = useSelector((state) => state.userToken);
|
||||
const chargeError = useSelector((state) => state.chargeError);
|
||||
const userToken = useSelector((state: RootState) => state.userToken);
|
||||
const chargeError = useSelector((state: RootState) => state.chargeError);
|
||||
const { data, loading } = useQuery(PROOF_QUERY);
|
||||
const { initPaymentSheet, presentPaymentSheet } = useStripe();
|
||||
const [paymentLoading, setPaymentLoading] = useState(false);
|
||||
@@ -3,16 +3,16 @@ import React from 'react';
|
||||
import { ActivityIndicator, StyleSheet, View, Text, ScrollView } from 'react-native';
|
||||
import { Button, Incubator } from 'react-native-ui-lib';
|
||||
|
||||
import FormErrors from 'src/components/FormErrors';
|
||||
import FormInput from 'src/components/FormInput';
|
||||
import theme from 'src/theme';
|
||||
|
||||
import useUserRegister from './useUserRegister';
|
||||
import FormErrors from '../../components/FormErrors';
|
||||
import FormInput from '../../components/FormInput';
|
||||
import theme from '../../theme';
|
||||
|
||||
const { Toast } = Incubator;
|
||||
|
||||
const UserRegister = () => {
|
||||
const { isRegisteringUser, onSubmit, control, isValid, errors, registerError, setFocus, toast, setToast } =
|
||||
useUserRegister();
|
||||
const { isRegisteringUser, onSubmit, isValid, errors, registerError, setFocus, toast, setToast } = useUserRegister();
|
||||
const isDisabled = isRegisteringUser || !isValid;
|
||||
// TODO: validate on type
|
||||
// TODO: highlight errorfields
|
||||
@@ -21,26 +21,11 @@ const UserRegister = () => {
|
||||
<>
|
||||
<View style={styles.card}>
|
||||
<ScrollView>
|
||||
<FormInput
|
||||
name="firstName"
|
||||
label="Fornavn"
|
||||
control={control}
|
||||
errors={errors}
|
||||
autoFocus={true}
|
||||
onSubmitEditing={() => setFocus('lastName')}
|
||||
/>
|
||||
<FormInput
|
||||
name="lastName"
|
||||
label="Etternavn"
|
||||
control={control}
|
||||
errors={errors}
|
||||
onSubmitEditing={() => setFocus('email')}
|
||||
/>
|
||||
<FormInput name="firstName" label="Fornavn" autoFocus onSubmitEditing={() => setFocus('lastName')} />
|
||||
<FormInput name="lastName" label="Etternavn" onSubmitEditing={() => setFocus('email')} />
|
||||
<FormInput
|
||||
name="email"
|
||||
label="E-post"
|
||||
control={control}
|
||||
errors={errors}
|
||||
keyboardType="email-address"
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
@@ -53,17 +38,13 @@ const UserRegister = () => {
|
||||
<FormInput
|
||||
name="phoneNumber"
|
||||
label="Mobilnummer"
|
||||
control={control}
|
||||
errors={errors}
|
||||
keyboardType="phone-pad"
|
||||
onSubmitEditing={() => setFocus('password')}
|
||||
/>
|
||||
<FormInput
|
||||
name="password"
|
||||
label="Passord"
|
||||
control={control}
|
||||
errors={errors}
|
||||
secureTextEntry={true}
|
||||
secureTextEntry
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
returnKeyType="send"
|
||||
+17
-11
@@ -1,28 +1,34 @@
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
|
||||
import { requestRegisterUser } from '../../api';
|
||||
import { usePrevious } from '../../hooks';
|
||||
import { requestRegisterUser } from 'src/api';
|
||||
import { useAppDispatch, useAppSelector, usePrevious } from 'src/hooks';
|
||||
|
||||
export interface UserRegisterFormValues {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
email: string;
|
||||
phoneNumber: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
const useUserRegister = () => {
|
||||
const dispatch = useDispatch();
|
||||
const dispatch = useAppDispatch();
|
||||
const navigation = useNavigation();
|
||||
const isAuthenticated = useSelector((store) => store.isAuthenticated);
|
||||
const isRegisteringUser = useSelector((store) => store.isRegisteringUser);
|
||||
const registerError = useSelector((store) => store.registerError) || {};
|
||||
const isAuthenticated = useAppSelector((store) => store.isAuthenticated);
|
||||
const isRegisteringUser = useAppSelector((store) => store.isRegisteringUser);
|
||||
const registerError = useAppSelector((store) => store.registerError) || {};
|
||||
const [toast, setToast] = useState(null);
|
||||
|
||||
const isAuthenticatedPrev = usePrevious(isAuthenticated);
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { errors, isValid },
|
||||
setFocus,
|
||||
setError,
|
||||
} = useForm();
|
||||
} = useForm<UserRegisterFormValues>();
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
if (!isValid) {
|
||||
setToast({
|
||||
@@ -38,7 +44,7 @@ const useUserRegister = () => {
|
||||
|
||||
// Display error messages from API on form fields
|
||||
Object.keys(registerError).forEach((key) => {
|
||||
setError(key, { type: 'manual', message: registerError[key] });
|
||||
setError(key as keyof UserRegisterFormValues, { type: 'manual', message: registerError[key] });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -48,6 +54,6 @@ const useUserRegister = () => {
|
||||
}
|
||||
}, [isAuthenticatedPrev, isAuthenticated, navigation]);
|
||||
|
||||
return { isRegisteringUser, onSubmit, control, isValid, registerError, errors, setFocus, toast, setToast };
|
||||
return { isRegisteringUser, onSubmit, isValid, registerError, errors, setFocus, toast, setToast };
|
||||
};
|
||||
export default useUserRegister;
|
||||
Reference in new issue
Block a user