diff --git a/.eslintrc.js b/.eslintrc.js index 0a68f4c..2b0bf29 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,19 +9,35 @@ module.exports = { 'plugin:import/warnings', ], rules: { + 'class-methods-use-this': 'error', // FIXME: refactor + 'max-len': 'off', 'no-plusplus': 'off', 'no-console': 'off', 'no-underscore-dangle': 'off', 'no-param-reassign': 'off', 'no-unused-vars': 'off', + 'no-use-before-define': ['error', { functions: true, classes: true, variables: false }], // disable the rule for variables, but enable it for functions and classes + 'react/prefer-stateless-function': 1, 'react/prop-types': 'off', // FIXME: typescript - 'class-methods-use-this': 'error', // FIXME: refactor 'react/jsx-filename-extension': ['error', { extensions: ['.js', '.jsx'] }], 'react/sort-comp': 'off', - 'max-len': 'off', - 'no-use-before-define': ['error', { functions: true, classes: true, variables: false }], // disable the rule for variables, but enable it for functions and classes 'react-native/no-inline-styles': 'off', // FIXME: refactor + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: ['**/*.test.js', '**/*.spec.js', '**/__tests__/**'], + }, + ], + 'import/prefer-default-export': 'off', + 'import/order': [ + 'error', + { + groups: ['builtin', 'external', 'internal', ['parent', 'sibling', 'index']], + 'newlines-between': 'always', + alphabetize: { order: 'asc' }, + }, + ], 'unused-imports/no-unused-imports': 'error', }, plugins: ['prettier', 'unused-imports'], diff --git a/index.js b/index.js index 452430f..d6c810f 100644 --- a/index.js +++ b/index.js @@ -2,9 +2,8 @@ import { AppRegistry } from 'react-native'; // import * as Sentry from '@sentry/react-native'; -import App from './src/App'; - import { name as appName } from './app.json'; +import App from './src/App'; // if (Config.SENTRY_DSN) { // Sentry.init({ dsn: Config.SENTRY_DSN }); diff --git a/package.json b/package.json index 552e19a..2d51369 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "android": "expo start --android", "ios": "expo start --ios", "web": "expo start --web", - "lint": "eslint ." + "lint": "eslint .", + "format": "eslint --fix ." }, "dependencies": { "@apollo/client": "^3.7.17", diff --git a/src/App.js b/src/App.js index 54c61e4..688b672 100644 --- a/src/App.js +++ b/src/App.js @@ -1,17 +1,16 @@ -import React from 'react'; -import { Provider } from 'react-redux'; -import { PersistGate } from 'redux-persist/integration/react'; import { ApolloClient, HttpLink, InMemoryCache, ApolloProvider } from '@apollo/client'; import { StripeProvider } from '@stripe/stripe-react-native'; -import { GestureHandlerRootView } from 'react-native-gesture-handler'; -import { LogBox } from 'react-native'; - import Constants from 'expo-constants'; -import { loadTheme } from './theme'; -import { useDeepLinking } from './hooks'; +import React from 'react'; +import { LogBox } from 'react-native'; +import { GestureHandlerRootView } from 'react-native-gesture-handler'; +import { Provider } from 'react-redux'; +import { PersistGate } from 'redux-persist/integration/react'; import Dusken from './Dusken'; +import { useDeepLinking } from './hooks'; import { store, persistor } from './reduxStore'; +import { loadTheme } from './theme'; const apolloClient = new ApolloClient({ link: new HttpLink({ uri: `${process.env.EXPO_PUBLIC_DUSKEN_API_URL}/api/graphql/` }), diff --git a/src/Dusken.js b/src/Dusken.js index 2822c51..cd766f9 100644 --- a/src/Dusken.js +++ b/src/Dusken.js @@ -1,6 +1,6 @@ +import { NativeBaseProvider } from 'native-base'; import React, { useEffect } from 'react'; import { connect } from 'react-redux'; -import { NativeBaseProvider } from 'native-base'; import Navigation from './Navigation'; import { logout as logoutAction, registerUserSuccess as registerUserSuccessAction } from './actions'; diff --git a/src/Navigation.js b/src/Navigation.js index 066018d..b960dfa 100644 --- a/src/Navigation.js +++ b/src/Navigation.js @@ -1,17 +1,15 @@ -import React from 'react'; +import { SimpleLineIcons as Icon } from '@expo/vector-icons'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; -import { SimpleLineIcons as Icon } from '@expo/vector-icons'; +import React from 'react'; -import EventList from './modules/events/EventList'; -import EventDetail from './modules/events/EventDetail'; - -import Membership from './modules/membership/Membership'; -import Login from './modules/login/Login'; import About from './modules/about/About'; +import EventDetail from './modules/events/EventDetail'; +import EventList from './modules/events/EventList'; +import Login from './modules/login/Login'; +import Membership from './modules/membership/Membership'; import UserRegister from './modules/register/UserRegister'; - import theme from './theme'; // This looks ugly, even though it's a recommended style from the branding profile. diff --git a/src/__tests__/app.js b/src/__tests__/app.js index 832a109..7fcf427 100644 --- a/src/__tests__/app.js +++ b/src/__tests__/app.js @@ -1,6 +1,6 @@ import 'react-native'; -import React from 'react'; import { render } from '@testing-library/react-native'; +import React from 'react'; import App from '../App'; diff --git a/src/components/FormErrors.js b/src/components/FormErrors.js index eeeb4ae..1a2cc29 100644 --- a/src/components/FormErrors.js +++ b/src/components/FormErrors.js @@ -1,6 +1,6 @@ +import { Alert, HStack } from 'native-base'; import React from 'react'; import { Text } from 'react-native'; -import { Alert, HStack } from 'native-base'; const FormErrors = ({ errors }) => { if (!Object.keys(errors).length || !['non_field_errors', 'detail'].some((errorField) => errorField in errors)) { diff --git a/src/components/FormInput.js b/src/components/FormInput.js index 93e0e36..5298ed9 100644 --- a/src/components/FormInput.js +++ b/src/components/FormInput.js @@ -1,8 +1,7 @@ +import { Input, Text, WarningOutlineIcon, FormControl } from 'native-base'; import React from 'react'; import { Controller } from 'react-hook-form'; -import { Input, Text, WarningOutlineIcon, FormControl } from 'native-base'; - const FormInput = ({ control, errors, diff --git a/src/hooks.js b/src/hooks.js index 1e0cc7b..70f171f 100644 --- a/src/hooks.js +++ b/src/hooks.js @@ -1,6 +1,6 @@ +import { useStripe } from '@stripe/stripe-react-native'; import { useCallback, useRef, useEffect } from 'react'; import { Linking } from 'react-native'; -import { useStripe } from '@stripe/stripe-react-native'; export function usePrevious(value) { const ref = useRef(); diff --git a/src/modules/about/About.js b/src/modules/about/About.js index cc44359..eff5c0c 100644 --- a/src/modules/about/About.js +++ b/src/modules/about/About.js @@ -1,3 +1,4 @@ +import { SimpleLineIcons as SimpleIcon, FontAwesome5 as FAIcon } from '@expo/vector-icons'; import React from 'react'; import { Text, @@ -10,12 +11,10 @@ import { ScrollView, Dimensions, } from 'react-native'; - -import { SimpleLineIcons as SimpleIcon, FontAwesome5 as FAIcon } from '@expo/vector-icons'; import { Button } from 'react-native-ui-lib'; -import theme from '../../theme'; import logo from '../../../assets/DNS-logo-svart.png'; +import theme from '../../theme'; const CHATEAU_NEUF_ADDRESS = 'Det Norske Studentersamfund, Slemdalsveien 15, 0369 Oslo'; diff --git a/src/modules/events/EventDetail.js b/src/modules/events/EventDetail.js index 9eb2c62..eb1b755 100644 --- a/src/modules/events/EventDetail.js +++ b/src/modules/events/EventDetail.js @@ -1,3 +1,5 @@ +import { FontAwesome } from '@expo/vector-icons'; +import moment from 'moment'; import React from 'react'; import { Linking, @@ -11,8 +13,6 @@ import { useWindowDimensions, } from 'react-native'; import RenderHtml from 'react-native-render-html'; -import moment from 'moment'; -import { FontAwesome } from '@expo/vector-icons'; import theme from '../../theme'; diff --git a/src/modules/events/EventList.js b/src/modules/events/EventList.js index 7e761f6..d8c8aeb 100644 --- a/src/modules/events/EventList.js +++ b/src/modules/events/EventList.js @@ -1,9 +1,8 @@ -import { StyleSheet, View, Platform, SectionList, TouchableOpacity } from 'react-native'; -import { Card, Text, Spinner, ArrowForwardIcon, HStack } from 'native-base'; -import { Button } from 'react-native-ui-lib'; - -import React from 'react'; import moment from 'moment'; +import { Card, Text, Spinner, ArrowForwardIcon, HStack } from 'native-base'; +import React from 'react'; +import { StyleSheet, View, Platform, SectionList, TouchableOpacity } from 'react-native'; +import { Button } from 'react-native-ui-lib'; import 'moment/locale/nb'; import useEventList from './useEventList'; diff --git a/src/modules/events/useEventList.js b/src/modules/events/useEventList.js index 3b5b59b..727512f 100644 --- a/src/modules/events/useEventList.js +++ b/src/modules/events/useEventList.js @@ -1,8 +1,8 @@ -import { useEffect, useState } from 'react'; +import { useNavigation } from '@react-navigation/native'; import moment from 'moment'; +import { useEffect, useState } from 'react'; import 'moment/locale/nb'; -import { useNavigation } from '@react-navigation/native'; import { fetchWithTimeout } from '../../utils'; moment.locale('nb'); diff --git a/src/modules/login/Login.js b/src/modules/login/Login.js index da434a1..3db790a 100644 --- a/src/modules/login/Login.js +++ b/src/modules/login/Login.js @@ -1,12 +1,12 @@ +import { ScrollView } from 'native-base'; import React from 'react'; import { ActivityIndicator, Linking, StyleSheet, View, Text } from 'react-native'; -import { ScrollView } from 'native-base'; import { Button } from 'react-native-ui-lib'; -import theme from '../../theme'; import useLogin from './useLogin'; -import FormInput from '../../components/FormInput'; import FormErrors from '../../components/FormErrors'; +import FormInput from '../../components/FormInput'; +import theme from '../../theme'; const Login = () => { const { isLoggingIn, errors, control, setFocus, onSubmit } = useLogin(); diff --git a/src/modules/login/useLogin.js b/src/modules/login/useLogin.js index 4c492be..ea15dc8 100644 --- a/src/modules/login/useLogin.js +++ b/src/modules/login/useLogin.js @@ -1,7 +1,7 @@ import { useNavigation } from '@react-navigation/native'; import { useEffect } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; import { useForm } from 'react-hook-form'; +import { useDispatch, useSelector } from 'react-redux'; import { requestLogin } from '../../api'; diff --git a/src/modules/membership/Membership.js b/src/modules/membership/Membership.js index 7b32403..f0ab45d 100644 --- a/src/modules/membership/Membership.js +++ b/src/modules/membership/Membership.js @@ -1,10 +1,10 @@ import React from 'react'; import { View, StyleSheet, ActivityIndicator } from 'react-native'; -import theme from '../../theme'; -import useMembership from './useMembership'; 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 } = diff --git a/src/modules/membership/MembershipInfo.js b/src/modules/membership/MembershipInfo.js index 1f393a9..8c7f4f0 100644 --- a/src/modules/membership/MembershipInfo.js +++ b/src/modules/membership/MembershipInfo.js @@ -1,7 +1,7 @@ import React from 'react'; - import { ScrollView, Text, View, StyleSheet } from 'react-native'; import { Button } from 'react-native-ui-lib'; + import theme from '../../theme'; const MembershipInfo = ({ onRegister, onLogin }) => ( diff --git a/src/modules/membership/Proof.js b/src/modules/membership/Proof.js index 6428b68..b71b9a2 100644 --- a/src/modules/membership/Proof.js +++ b/src/modules/membership/Proof.js @@ -10,13 +10,12 @@ import { ActivityIndicator, Dimensions, } from 'react-native'; -import { Button, Incubator } from 'react-native-ui-lib'; import Confetti from 'react-native-confetti'; +import { Button, Incubator } from 'react-native-ui-lib'; -import theme from '../../theme'; import useProof from './useProof'; - import logo from '../../../assets/DNS-logo-svart.png'; +import theme from '../../theme'; const { Toast } = Incubator; diff --git a/src/modules/membership/useProof.js b/src/modules/membership/useProof.js index c323d27..c6de667 100644 --- a/src/modules/membership/useProof.js +++ b/src/modules/membership/useProof.js @@ -1,8 +1,8 @@ -import { useEffect, useState } from 'react'; -import { useSelector } from 'react-redux'; import { gql, useQuery } from '@apollo/client'; import { useStripe } from '@stripe/stripe-react-native'; import Constants from 'expo-constants'; +import { useEffect, useState } from 'react'; +import { useSelector } from 'react-redux'; import { requestStripePaymentSheet } from '../../api'; diff --git a/src/modules/register/UserRegister.js b/src/modules/register/UserRegister.js index c7de3c7..88ae328 100644 --- a/src/modules/register/UserRegister.js +++ b/src/modules/register/UserRegister.js @@ -1,13 +1,12 @@ +import * as EmailValidator from 'email-validator'; import React from 'react'; +import { ActivityIndicator, StyleSheet, View, Text, ScrollView } from 'react-native'; import { Button, Incubator } from 'react-native-ui-lib'; -import { ActivityIndicator, StyleSheet, View, Text, ScrollView } from 'react-native'; -import * as EmailValidator from 'email-validator'; - -import theme from '../../theme'; import useUserRegister from './useUserRegister'; -import FormInput from '../../components/FormInput'; import FormErrors from '../../components/FormErrors'; +import FormInput from '../../components/FormInput'; +import theme from '../../theme'; const { Toast } = Incubator; diff --git a/src/modules/register/useUserRegister.js b/src/modules/register/useUserRegister.js index bee8692..6a4d2e7 100644 --- a/src/modules/register/useUserRegister.js +++ b/src/modules/register/useUserRegister.js @@ -1,10 +1,10 @@ import { useNavigation } from '@react-navigation/native'; import { useEffect, useState } from 'react'; -import { useSelector, useDispatch } from 'react-redux'; import { useForm } from 'react-hook-form'; +import { useSelector, useDispatch } from 'react-redux'; -import { usePrevious } from '../../hooks'; import { requestRegisterUser } from '../../api'; +import { usePrevious } from '../../hooks'; const useUserRegister = () => { const dispatch = useDispatch(); diff --git a/src/reducers.js b/src/reducers.js index aaba177..c54c5c2 100644 --- a/src/reducers.js +++ b/src/reducers.js @@ -13,7 +13,6 @@ import { MEMBERSHIP_CHARGE_FAILURE, MEMBERSHIP_CHARGE_SUCCESS, } from './actions'; - import { snakeToCamelCase } from './utils'; const initialState = { diff --git a/src/reduxStore.js b/src/reduxStore.js index d6e5682..322f904 100644 --- a/src/reduxStore.js +++ b/src/reduxStore.js @@ -1,6 +1,6 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; import { applyMiddleware, createStore } from 'redux'; import { persistStore, persistReducer } from 'redux-persist'; -import AsyncStorage from '@react-native-async-storage/async-storage'; import thunk from 'redux-thunk'; import rootReducer from './reducers';