diff --git a/babel.config.js b/babel.config.js
index 5396d80..161beda 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -15,7 +15,8 @@ module.exports = {
'@config': './src/config',
'@utils': './src/utils',
'@styles': './src/styles',
- '@context': './src/context'
+ '@context': './src/context',
+ '@interfaces': './src/interfaces'
}
}
]
diff --git a/package-lock.json b/package-lock.json
index 61f5853..f2a5b98 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1276,12 +1276,171 @@
"@types/istanbul-lib-report": "*"
}
},
+ "@types/jest": {
+ "version": "25.2.1",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-25.2.1.tgz",
+ "integrity": "sha512-msra1bCaAeEdkSyA0CZ6gW1ukMIvZ5YoJkdXw/qhQdsuuDlFTcEUrUw8CLCPt2rVRUfXlClVvK2gvPs9IokZaA==",
+ "dev": true,
+ "requires": {
+ "jest-diff": "^25.2.1",
+ "pretty-format": "^25.2.1"
+ },
+ "dependencies": {
+ "@jest/types": {
+ "version": "25.2.6",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.2.6.tgz",
+ "integrity": "sha512-myJTTV37bxK7+3NgKc4Y/DlQ5q92/NOwZsZ+Uch7OXdElxOg61QYc72fPYNAjlvbnJ2YvbXLamIsa9tj48BmyQ==",
+ "dev": true,
+ "requires": {
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^1.1.1",
+ "@types/yargs": "^15.0.0",
+ "chalk": "^3.0.0"
+ }
+ },
+ "@types/yargs": {
+ "version": "15.0.4",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz",
+ "integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==",
+ "dev": true,
+ "requires": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "diff-sequences": {
+ "version": "25.2.6",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz",
+ "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "jest-diff": {
+ "version": "25.2.6",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.2.6.tgz",
+ "integrity": "sha512-KuadXImtRghTFga+/adnNrv9s61HudRMR7gVSbP35UKZdn4IK2/0N0PpGZIqtmllK9aUyye54I3nu28OYSnqOg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^3.0.0",
+ "diff-sequences": "^25.2.6",
+ "jest-get-type": "^25.2.6",
+ "pretty-format": "^25.2.6"
+ }
+ },
+ "jest-get-type": {
+ "version": "25.2.6",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz",
+ "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==",
+ "dev": true
+ },
+ "pretty-format": {
+ "version": "25.2.6",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.2.6.tgz",
+ "integrity": "sha512-DEiWxLBaCHneffrIT4B+TpMvkV9RNvvJrd3lY9ew1CEQobDzEXmYT1mg0hJhljZty7kCc10z13ohOFAE8jrUDg==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^25.2.6",
+ "ansi-regex": "^5.0.0",
+ "ansi-styles": "^4.0.0",
+ "react-is": "^16.12.0"
+ }
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
"@types/json-schema": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz",
"integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==",
"dev": true
},
+ "@types/prop-types": {
+ "version": "15.7.3",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
+ "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
+ "dev": true
+ },
+ "@types/react": {
+ "version": "16.9.32",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.32.tgz",
+ "integrity": "sha512-fmejdp0CTH00mOJmxUPPbWCEBWPvRIL4m8r0qD+BSDUqmutPyGQCHifzMpMzdvZwROdEdL78IuZItntFWgPXHQ==",
+ "dev": true,
+ "requires": {
+ "@types/prop-types": "*",
+ "csstype": "^2.2.0"
+ }
+ },
+ "@types/react-native": {
+ "version": "0.62.1",
+ "resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.62.1.tgz",
+ "integrity": "sha512-4uKqYGek9/OstJWW0hEfF/6fx8BzNkzdAFxeY+VOxec+SPKK/hvGEjnX6+0jV1MnJDBHYKdWfWA4sYCQ8G3sqA==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*"
+ }
+ },
+ "@types/react-test-renderer": {
+ "version": "16.9.2",
+ "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-16.9.2.tgz",
+ "integrity": "sha512-4eJr1JFLIAlWhzDkBCkhrOIWOvOxcCAfQh+jiKg7l/nNZcCIL2MHl2dZhogIFKyHzedVWHaVP1Yydq/Ruu4agw==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*"
+ }
+ },
"@types/stack-utils": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
@@ -2466,6 +2625,12 @@
"cssom": "0.3.x"
}
},
+ "csstype": {
+ "version": "2.6.10",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.10.tgz",
+ "integrity": "sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w==",
+ "dev": true
+ },
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -3500,6 +3665,76 @@
}
}
},
+ "eslint-import-resolver-babel-module": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-babel-module/-/eslint-import-resolver-babel-module-5.1.2.tgz",
+ "integrity": "sha512-pzKE6UzXgT1Opp4N2P2yoE7OY29+LX3FNX6bqAjmGV+btR/ZYnE/oQFoGzL2/3RkLYRTBYRFwvrphRy5wEAUwg==",
+ "dev": true,
+ "requires": {
+ "pkg-up": "^2.0.0",
+ "resolve": "^1.10.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "pkg-up": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
+ "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.1.0"
+ }
+ }
+ }
+ },
"eslint-import-resolver-node": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz",
diff --git a/package.json b/package.json
index f6dfa98..d3d56ac 100644
--- a/package.json
+++ b/package.json
@@ -29,11 +29,16 @@
"@babel/core": "^7.6.2",
"@babel/runtime": "^7.6.2",
"@react-native-community/eslint-config": "^0.0.5",
+ "@types/jest": "^25.2.1",
+ "@types/react": "^16.9.32",
+ "@types/react-native": "^0.62.1",
+ "@types/react-test-renderer": "^16.9.2",
"babel-jest": "^24.9.0",
"babel-plugin-module-resolver": "^4.0.0",
"eslint": "^6.5.1",
"eslint-config-prettier": "^6.10.0",
"eslint-config-wolox-react-native": "^1.0.1",
+ "eslint-import-resolver-babel-module": "^5.1.2",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-prettier": "^3.1.2",
"install": "^0.13.0",
@@ -41,7 +46,8 @@
"metro-react-native-babel-preset": "^0.56.0",
"npm": "^6.14.2",
"prettier": "^1.19.1",
- "react-test-renderer": "16.9.0"
+ "react-test-renderer": "16.9.0",
+ "typescript": "^3.8.3"
},
"jest": {
"preset": "react-native"
diff --git a/src/app/components/Header/components/BackButton/index.js b/src/app/components/Header/components/BackButton/index.js
deleted file mode 100644
index 4536bad..0000000
--- a/src/app/components/Header/components/BackButton/index.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react';
-import { func, number } from 'prop-types';
-import { TouchableOpacity, Image } from 'react-native';
-
-import defaultBackBtn from '@assets/ic_back.png';
-
-import styles from './styles';
-
-function BackButton({ onPress, backButton }) {
- return (
-
-
-
- );
-}
-
-BackButton.propTypes = {
- onPress: func.isRequired,
- backButton: number
-};
-
-export default BackButton;
diff --git a/src/app/components/Header/components/BackButton/index.tsx b/src/app/components/Header/components/BackButton/index.tsx
new file mode 100644
index 0000000..fec4bf7
--- /dev/null
+++ b/src/app/components/Header/components/BackButton/index.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import { TouchableOpacity, Image } from 'react-native';
+
+import styles from './styles';
+
+interface Props {
+ onPress: () => void;
+ backButton: number;
+}
+
+function BackButton({ onPress, backButton }: Props) {
+ return (
+
+
+
+ );
+}
+
+export default BackButton;
diff --git a/src/app/components/Header/components/BackButton/styles.js b/src/app/components/Header/components/BackButton/styles.ts
similarity index 100%
rename from src/app/components/Header/components/BackButton/styles.js
rename to src/app/components/Header/components/BackButton/styles.ts
diff --git a/src/app/components/Header/components/LogoutButton/index.js b/src/app/components/Header/components/LogoutButton/index.tsx
similarity index 59%
rename from src/app/components/Header/components/LogoutButton/index.js
rename to src/app/components/Header/components/LogoutButton/index.tsx
index 02ad602..6610d82 100644
--- a/src/app/components/Header/components/LogoutButton/index.js
+++ b/src/app/components/Header/components/LogoutButton/index.tsx
@@ -1,17 +1,17 @@
import React, { useState } from 'react';
-import { Image, ActivityIndicator, TouchableWithoutFeedback, View } from 'react-native';
+import { Image, ActivityIndicator, TouchableOpacity, View } from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
-import { useGlobalValue } from '@context';
+import { useGlobalValue } from '@context/index';
import { actionsCreator } from '@context/user/actions';
import logout from '@assets/logout.png';
-import { WHITE } from '@constants/colors';
+import COLORS from '@constants/colors';
import styles from './styles';
function LogoutButton() {
const [, dispatch] = useGlobalValue();
- const [loading, setLoading] = useState();
+ const [loading, setLoading] = useState();
const handleLogoutBtn = async () => {
setLoading(true);
try {
@@ -24,11 +24,11 @@ function LogoutButton() {
};
return (
-
+
- {loading ? : }
+ {loading ? : }
-
+
);
}
diff --git a/src/app/components/Header/components/LogoutButton/styles.js b/src/app/components/Header/components/LogoutButton/styles.ts
similarity index 100%
rename from src/app/components/Header/components/LogoutButton/styles.js
rename to src/app/components/Header/components/LogoutButton/styles.ts
diff --git a/src/app/components/Header/index.js b/src/app/components/Header/index.js
deleted file mode 100644
index ac33f42..0000000
--- a/src/app/components/Header/index.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from 'react';
-import { Text, ImageBackground } from 'react-native';
-
-import navBg from '@assets/bc_navbar.png';
-
-import BackButton from './components/BackButton';
-import LogoutButton from './components/LogoutButton';
-import styles from './styles';
-
-function Header({ scene, navigation }) {
- const {
- options: {
- backButton,
- title,
- headerStyle: { height },
- hasBackBtn = false,
- hasLogoutBtn = false
- }
- } = scene.descriptor;
- return (
-
- {hasBackBtn && }
- {hasLogoutBtn && }
- {title}
-
- );
-}
-
-export default Header;
diff --git a/src/app/components/Header/index.tsx b/src/app/components/Header/index.tsx
new file mode 100644
index 0000000..a224d74
--- /dev/null
+++ b/src/app/components/Header/index.tsx
@@ -0,0 +1,44 @@
+import React from 'react';
+import { Text, ImageBackground, View } from 'react-native';
+
+import navBg from '@assets/bc_navbar.png';
+import defaultBackBtn from '@assets/ic_back.png';
+
+import BackButton from './components/BackButton';
+import LogoutButton from './components/LogoutButton';
+import styles from './styles';
+
+interface Props {
+ scene: {
+ descriptor: { options: { title?: string; headerStyle?: { height: number }; hasBackBtn?: boolean } };
+ };
+ navigation: { goBack(): void };
+}
+
+interface CustomProps {
+ backButton?: number;
+ hasLogoutBtn?: boolean;
+}
+
+const withCustomHeader = ({ backButton, hasLogoutBtn = false }: CustomProps) =>
+ function PropsProxy({ scene, navigation }: Props) {
+ const {
+ options: { title, headerStyle }
+ } = scene.descriptor;
+ const { height } = headerStyle!;
+
+ return (
+
+
+ {hasLogoutBtn ? (
+
+ ) : (
+
+ )}
+
+ {title}
+
+ );
+ };
+
+export default withCustomHeader;
diff --git a/src/app/components/Header/styles.js b/src/app/components/Header/styles.ts
similarity index 67%
rename from src/app/components/Header/styles.js
rename to src/app/components/Header/styles.ts
index 64579bd..b5d042c 100644
--- a/src/app/components/Header/styles.js
+++ b/src/app/components/Header/styles.ts
@@ -1,6 +1,10 @@
import { StyleSheet, Platform } from 'react-native';
-import { WHITE } from '@constants/colors';
+import COLORS from '@constants/colors';
+
+type OS = 'ios' | 'android';
+
+const system = Platform.OS as OS;
const OS_STYLES = {
headerTitle: {
@@ -14,7 +18,7 @@ const OS_STYLES = {
textAlign: 'left'
}
}
-};
+} as const;
export const styles = StyleSheet.create({
headerBg: {
@@ -24,10 +28,14 @@ export const styles = StyleSheet.create({
position: 'relative'
},
headerTitle: {
- ...OS_STYLES[Platform.OS],
- color: WHITE,
+ ...OS_STYLES.headerTitle[system],
+ color: COLORS.WHITE,
fontSize: 16,
fontWeight: '700'
+ },
+ headerButton: {
+ position: 'relative',
+ zIndex: 5
}
});
diff --git a/src/app/components/Loader/constants.js b/src/app/components/Loader/constants.js
deleted file mode 100644
index b96e262..0000000
--- a/src/app/components/Loader/constants.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export const LOADER_SIZE = {
- large: 'large',
- small: 'small'
-};
diff --git a/src/app/components/Loader/constants.ts b/src/app/components/Loader/constants.ts
new file mode 100644
index 0000000..ed8346e
--- /dev/null
+++ b/src/app/components/Loader/constants.ts
@@ -0,0 +1,4 @@
+export enum LOADER_SIZE {
+ large = 'large',
+ small = 'small'
+}
diff --git a/src/app/components/Loader/index.js b/src/app/components/Loader/index.tsx
similarity index 53%
rename from src/app/components/Loader/index.js
rename to src/app/components/Loader/index.tsx
index 24b4b19..17f3799 100644
--- a/src/app/components/Loader/index.js
+++ b/src/app/components/Loader/index.tsx
@@ -1,23 +1,29 @@
import React from 'react';
import { View, ActivityIndicator } from 'react-native';
-import { BLUE, TRANSPARENT } from '@constants/colors';
+import COLORS from '@constants/colors';
import styles from './styles';
import { LOADER_SIZE } from './constants';
+interface Props {
+ isLoading: boolean;
+}
+
+type FunctionComponent = (param: T) => JSX.Element;
+
const withLoader = ({
- loaderColor = BLUE,
+ loaderColor = COLORS.BLUE,
loaderSize = LOADER_SIZE.large,
- bgColor = TRANSPARENT
-}) => WrappedComponent =>
- function PropsProxy({ isLoading, ...props }) {
+ bgColor = COLORS.TRANSPARENT
+}) => (WrappedComponent: FunctionComponent) =>
+ function PropsProxy({ isLoading, ...props }: U) {
return isLoading ? (
) : (
-
+
);
};
diff --git a/src/app/components/Loader/styles.js b/src/app/components/Loader/styles.ts
similarity index 100%
rename from src/app/components/Loader/styles.js
rename to src/app/components/Loader/styles.ts
diff --git a/src/app/components/Routes/constants.js b/src/app/components/Routes/constants.ts
similarity index 67%
rename from src/app/components/Routes/constants.js
rename to src/app/components/Routes/constants.ts
index 7575cbf..ff861b3 100644
--- a/src/app/components/Routes/constants.js
+++ b/src/app/components/Routes/constants.ts
@@ -1,7 +1,7 @@
-import Header from '@components/Header';
+import withCustomHeader from '@components/Header';
export const APP_OPTIONS = {
- header: Header,
+ header: withCustomHeader({}),
headerMode: 'float',
headerTransparent: true,
headerStyle: { height: 114 }
diff --git a/src/app/components/Routes/index.js b/src/app/components/Routes/index.tsx
similarity index 70%
rename from src/app/components/Routes/index.js
rename to src/app/components/Routes/index.tsx
index d3624c0..fb7bb26 100644
--- a/src/app/components/Routes/index.js
+++ b/src/app/components/Routes/index.tsx
@@ -1,18 +1,24 @@
import React, { useEffect } from 'react';
-import { useGlobalValue } from '@context';
+import { useGlobalValue } from '@context/index';
+import { useRequest } from '@hooks/index';
+import { AuthHeaders } from '@interfaces/api';
import { actionsCreator } from '@context/user/actions';
-import { useRequest } from '@hooks';
import { getAuthHeaders } from '@services/UserService';
import api from '@config/api';
import AppRoutes from './layout';
+interface Response {
+ data: AuthHeaders;
+}
+
function RoutesContainer() {
- const { data: response, loading } = useRequest(getAuthHeaders);
+ const { data: response, loading } = useRequest(getAuthHeaders);
const [{ userState }, dispatch] = useGlobalValue();
const headers = response?.data;
const token = userState?.token;
+
useEffect(() => {
if (headers) {
api.setHeaders(headers);
diff --git a/src/app/components/Routes/layout.js b/src/app/components/Routes/layout.tsx
similarity index 68%
rename from src/app/components/Routes/layout.js
rename to src/app/components/Routes/layout.tsx
index f20125d..96ed5d7 100644
--- a/src/app/components/Routes/layout.js
+++ b/src/app/components/Routes/layout.tsx
@@ -1,17 +1,21 @@
import React from 'react';
-import { bool, string } from 'prop-types';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
-import { Library, BookDetail, Login } from '@screens';
+import { Library, BookDetail, Login } from '@screens/index';
import withLoader from '@components/Loader';
+import withCustomHeader from '@components/Header';
import * as Routes from '@constants/routes';
import { APP_OPTIONS, LOGIN_OPTIONS } from './constants';
+interface Props {
+ token: string | null;
+}
+
const { Navigator, Screen } = createStackNavigator();
-function AppRoutes({ token }) {
+function AppRoutes({ token }: Props) {
const screenOptions = token ? APP_OPTIONS : LOGIN_OPTIONS;
return (
@@ -21,12 +25,15 @@ function AppRoutes({ token }) {
>
) : (
@@ -37,9 +44,4 @@ function AppRoutes({ token }) {
);
}
-AppRoutes.propTypes = {
- isLoading: bool,
- token: string
-};
-
export default withLoader({})(AppRoutes);
diff --git a/src/app/constants.js b/src/app/constants.js
deleted file mode 100644
index da90ce0..0000000
--- a/src/app/constants.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export const HEADER_MODE = {
- ios: 'float',
- android: 'screen'
-};
diff --git a/src/app/constants.ts b/src/app/constants.ts
new file mode 100644
index 0000000..71ff51c
--- /dev/null
+++ b/src/app/constants.ts
@@ -0,0 +1,4 @@
+export enum HEADER_MODE {
+ ios = 'float',
+ android = 'screen'
+}
diff --git a/src/app/index.js b/src/app/index.tsx
similarity index 96%
rename from src/app/index.js
rename to src/app/index.tsx
index 4d8bd9c..96b3f83 100644
--- a/src/app/index.js
+++ b/src/app/index.tsx
@@ -2,7 +2,7 @@ import 'react-native-gesture-handler';
import React, { useReducer } from 'react';
import Routes from '@components/Routes';
-import { GlobalContext, globalState, globalReducer } from '@context';
+import { GlobalContext, globalState, globalReducer } from '@context/index';
function App() {
return (
diff --git a/src/app/screens/BookDetail/index.js b/src/app/screens/BookDetail/index.js
deleted file mode 100644
index 14e011a..0000000
--- a/src/app/screens/BookDetail/index.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from 'react';
-import { shape, number } from 'prop-types';
-
-import { useRequest } from '@hooks';
-import { serializeBook } from '@utils/serializers';
-import { getBook } from '@services/BookService';
-import { DEFAULT_BOOK } from '@constants/book';
-
-import BookDetail from './layout';
-
-function BookDetailContainer({ route }) {
- const { id } = route.params;
- const { data: response, loading } = useRequest(getBook, { id });
- const { image, title, author, year, genre } = serializeBook(response?.data) || DEFAULT_BOOK;
- return (
-
- );
-}
-
-BookDetailContainer.propTypes = {
- route: shape({
- params: shape({
- id: number
- })
- })
-};
-
-export default BookDetailContainer;
diff --git a/src/app/screens/BookDetail/index.tsx b/src/app/screens/BookDetail/index.tsx
new file mode 100644
index 0000000..c53326b
--- /dev/null
+++ b/src/app/screens/BookDetail/index.tsx
@@ -0,0 +1,27 @@
+import React from 'react';
+
+import { useRequest } from '@hooks/index';
+import { getBook } from '@services/BookService';
+import { Book } from '@interfaces/book';
+import { DEFAULT_BOOK } from '@constants/book';
+
+import BookDetail from './layout';
+
+interface Props {
+ route: { params: { id: number } };
+}
+
+interface Response {
+ data: Book;
+}
+
+function BookDetailContainer({ route }: Props) {
+ const { id } = route.params;
+ const { data: response, loading } = useRequest(getBook, { id });
+ const { image, title, author, year, genre } = response?.data || DEFAULT_BOOK;
+ return (
+
+ );
+}
+
+export default BookDetailContainer;
diff --git a/src/app/screens/BookDetail/layout.js b/src/app/screens/BookDetail/layout.tsx
similarity index 81%
rename from src/app/screens/BookDetail/layout.js
rename to src/app/screens/BookDetail/layout.tsx
index 54eb4b4..f18973b 100644
--- a/src/app/screens/BookDetail/layout.js
+++ b/src/app/screens/BookDetail/layout.tsx
@@ -1,23 +1,30 @@
import React from 'react';
-import { string } from 'prop-types';
import { Text, TouchableOpacity, View, Image } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import { useHeaderHeight } from '@react-navigation/stack';
import withLoader from '@components/Loader';
-import { CERULEAN, JAVA, SCOOTER, POLAR } from '@constants/colors';
+import COLORS from '@constants/colors';
import { DEFAULT_BOOK } from '@constants/book';
import styles from './styles';
-function BookDetail({ title, author, year, genre, image: { url } }) {
+interface Props {
+ title: string;
+ author: string;
+ year: string;
+ genre: string;
+ image: { url: string };
+}
+
+function BookDetail({ title, author, year, genre, image: { url } }: Props) {
const headerHeight = useHeaderHeight();
const padding = styles.bookDetail.paddingTop;
return (
-
+
{title}
@@ -34,7 +41,7 @@ function BookDetail({ title, author, year, genre, image: { url } }) {
Rent
@@ -44,12 +51,4 @@ function BookDetail({ title, author, year, genre, image: { url } }) {
);
}
-BookDetail.propTypes = {
- title: string,
- author: string,
- year: string,
- genre: string,
- imageUrl: string
-};
-
-export default withLoader({ bgColor: POLAR })(BookDetail);
+export default withLoader({ bgColor: COLORS.POLAR })(BookDetail);
diff --git a/src/app/screens/BookDetail/styles.js b/src/app/screens/BookDetail/styles.ts
similarity index 76%
rename from src/app/screens/BookDetail/styles.js
rename to src/app/screens/BookDetail/styles.ts
index dd928dd..a492f5e 100644
--- a/src/app/screens/BookDetail/styles.js
+++ b/src/app/screens/BookDetail/styles.ts
@@ -1,12 +1,12 @@
import { StyleSheet } from 'react-native';
-import { WHITE, POLAR, GRAY, CERULEAN, TUNDORA, TRANSPARENT } from '@constants/colors';
+import COLORS from '@constants/colors';
import { BOX_SHADOW } from '@styles/shadows';
const COMMON_STYLES = {
button: {
alignItems: 'center',
- borderColor: CERULEAN,
+ borderColor: COLORS.CERULEAN,
borderRadius: 100,
borderStyle: 'solid',
borderWidth: 2,
@@ -19,11 +19,11 @@ const COMMON_STYLES = {
fontWeight: '900',
textTransform: 'uppercase'
}
-};
+} as const;
export const styles = StyleSheet.create({
bookDetail: {
- backgroundColor: POLAR,
+ backgroundColor: COLORS.POLAR,
flex: 1,
flexDirection: 'column',
paddingHorizontal: 20,
@@ -31,7 +31,7 @@ export const styles = StyleSheet.create({
},
bookContainer: {
...BOX_SHADOW.type1,
- backgroundColor: WHITE,
+ backgroundColor: COLORS.WHITE,
borderRadius: 4,
flexDirection: 'column',
paddingHorizontal: 30,
@@ -46,38 +46,38 @@ export const styles = StyleSheet.create({
flexDirection: 'column'
},
bookCover: {
- backgroundColor: GRAY,
+ backgroundColor: COLORS.GRAY,
height: 105,
marginRight: 20,
width: 70
},
bookTitle: {
- color: TUNDORA,
+ color: COLORS.TUNDORA,
fontSize: 22,
fontWeight: '700',
marginBottom: 30
},
bookProp: {
- color: GRAY,
+ color: COLORS.GRAY,
fontWeight: '600'
},
buttonReturn: {
...COMMON_STYLES.button,
- backgroundColor: CERULEAN,
- borderColor: TRANSPARENT
+ backgroundColor: COLORS.CERULEAN,
+ borderColor: COLORS.TRANSPARENT
},
buttonComments: {
...COMMON_STYLES.button,
- backgroundColor: WHITE,
+ backgroundColor: COLORS.WHITE,
marginBottom: 12
},
buttonReturnTitle: {
...COMMON_STYLES.buttonTitle,
- color: WHITE
+ color: COLORS.WHITE
},
buttonCommentsTitle: {
...COMMON_STYLES.buttonTitle,
- color: CERULEAN
+ color: COLORS.CERULEAN
}
});
diff --git a/src/app/screens/Library/components/Book/index.js b/src/app/screens/Library/components/Book/index.tsx
similarity index 79%
rename from src/app/screens/Library/components/Book/index.js
rename to src/app/screens/Library/components/Book/index.tsx
index 339063e..fe3f069 100644
--- a/src/app/screens/Library/components/Book/index.js
+++ b/src/app/screens/Library/components/Book/index.tsx
@@ -1,6 +1,4 @@
import React from 'react';
-import { string, number } from 'prop-types';
-
import { View, Image, Text, TouchableOpacity } from 'react-native';
import { useNavigation } from '@react-navigation/native';
@@ -9,13 +7,20 @@ import { DEFAULT_BOOK } from '@constants/book';
import styles from './styles';
-function Book({ id, title, author, image: { url } }) {
+interface Props {
+ id: number;
+ title: string;
+ author: string;
+ image: { url: string };
+}
+
+function Book({ id, title, author, image: { url } }: Props) {
const navigation = useNavigation();
const handleClick = () => navigation.navigate(Routes.BOOK_DETAIL.NAME, { id });
return (
-
+
{title}
@@ -26,11 +31,4 @@ function Book({ id, title, author, image: { url } }) {
);
}
-Book.propTypes = {
- id: number,
- title: string,
- author: string,
- url: string
-};
-
export default Book;
diff --git a/src/app/screens/Library/components/Book/styles.js b/src/app/screens/Library/components/Book/styles.ts
similarity index 79%
rename from src/app/screens/Library/components/Book/styles.js
rename to src/app/screens/Library/components/Book/styles.ts
index dd7b594..490a3bb 100644
--- a/src/app/screens/Library/components/Book/styles.js
+++ b/src/app/screens/Library/components/Book/styles.ts
@@ -1,13 +1,13 @@
import { StyleSheet } from 'react-native';
-import { SCORPION, WHITE, GRAY } from '@constants/colors';
+import COLORS from '@constants/colors';
import { BOX_SHADOW } from '@styles/shadows';
export default StyleSheet.create({
bookContainer: {
...BOX_SHADOW.type1,
- backgroundColor: WHITE,
+ backgroundColor: COLORS.WHITE,
borderRadius: 5,
flexDirection: 'row',
marginBottom: 10,
@@ -15,7 +15,7 @@ export default StyleSheet.create({
paddingVertical: 20
},
bookCover: {
- backgroundColor: GRAY,
+ backgroundColor: COLORS.GRAY,
height: 75,
marginRight: 20,
width: 50
@@ -29,6 +29,6 @@ export default StyleSheet.create({
marginBottom: 5
},
bookAuthor: {
- color: SCORPION
+ color: COLORS.SCORPION
}
});
diff --git a/src/app/screens/Library/index.js b/src/app/screens/Library/index.js
deleted file mode 100644
index ed66bb9..0000000
--- a/src/app/screens/Library/index.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import React from 'react';
-
-import { getBooksList } from '@services/BookService';
-import { useRequest } from '@hooks';
-import { serializeBooks } from '@utils/serializers';
-
-import Library from './layout';
-
-function LibraryContainer() {
- const { data: response, loading } = useRequest(getBooksList);
- const books = serializeBooks(response?.data) || [];
- return ;
-}
-
-export default LibraryContainer;
diff --git a/src/app/screens/Library/index.tsx b/src/app/screens/Library/index.tsx
new file mode 100644
index 0000000..e8840f6
--- /dev/null
+++ b/src/app/screens/Library/index.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+
+import { getBooksList } from '@services/BookService';
+import { useRequest } from '@hooks/index';
+import { Book } from '@interfaces/book';
+
+import Library from './layout';
+
+interface Response {
+ data: Book[];
+}
+
+function LibraryContainer() {
+ const { data: response, loading } = useRequest(getBooksList);
+ console.log(response);
+ const books = response?.data || [];
+ return ;
+}
+
+export default LibraryContainer;
diff --git a/src/app/screens/Library/layout.js b/src/app/screens/Library/layout.tsx
similarity index 74%
rename from src/app/screens/Library/layout.js
rename to src/app/screens/Library/layout.tsx
index 647682b..3ee5f99 100644
--- a/src/app/screens/Library/layout.js
+++ b/src/app/screens/Library/layout.tsx
@@ -1,16 +1,20 @@
import React from 'react';
-import { array } from 'prop-types';
import { FlatList } from 'react-native';
import { useHeaderHeight } from '@react-navigation/stack';
import withLoader from '@components/Loader';
import { keyExtractor } from '@utils/renders';
-import { POLAR } from '@constants/colors';
+import COLORS from '@constants/colors';
+import { Book } from '@interfaces/book';
import { renderListItem } from './utils';
import styles from './styles';
-function Library({ books }) {
+interface Props {
+ books: Book[];
+}
+
+function Library({ books }: Props) {
const headerHeight = useHeaderHeight();
const padding = styles.bookList.paddingTop;
@@ -25,8 +29,4 @@ function Library({ books }) {
);
}
-Library.propTypes = {
- books: array
-};
-
-export default withLoader({ bgColor: POLAR })(Library);
+export default withLoader({ bgColor: COLORS.POLAR })(Library);
diff --git a/src/app/screens/Library/styles.js b/src/app/screens/Library/styles.ts
similarity index 73%
rename from src/app/screens/Library/styles.js
rename to src/app/screens/Library/styles.ts
index fe36357..2fa7495 100644
--- a/src/app/screens/Library/styles.js
+++ b/src/app/screens/Library/styles.ts
@@ -1,10 +1,10 @@
import { StyleSheet } from 'react-native';
-import { POLAR } from '@constants/colors';
+import COLORS from '@constants/colors';
export default StyleSheet.create({
bookList: {
- backgroundColor: POLAR,
+ backgroundColor: COLORS.POLAR,
flex: 1,
paddingHorizontal: 40,
paddingTop: 10
diff --git a/src/app/screens/Library/utils.js b/src/app/screens/Library/utils.js
deleted file mode 100644
index 479a963..0000000
--- a/src/app/screens/Library/utils.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import React from 'react';
-
-import Book from './components/Book';
-
-export const renderListItem = ({ item }) => ;
diff --git a/src/app/screens/Library/utils.tsx b/src/app/screens/Library/utils.tsx
new file mode 100644
index 0000000..d1c69f7
--- /dev/null
+++ b/src/app/screens/Library/utils.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+
+import { Book as BookType } from '@interfaces/book';
+
+import Book from './components/Book';
+
+interface ItemProps {
+ item: BookType;
+}
+
+export const renderListItem = ({ item }: ItemProps) => ;
diff --git a/src/app/screens/Login/constants.js b/src/app/screens/Login/constants.ts
similarity index 100%
rename from src/app/screens/Login/constants.js
rename to src/app/screens/Login/constants.ts
diff --git a/src/app/screens/Login/index.js b/src/app/screens/Login/index.tsx
similarity index 71%
rename from src/app/screens/Login/index.js
rename to src/app/screens/Login/index.tsx
index 5f2703e..4ed5b2b 100644
--- a/src/app/screens/Login/index.js
+++ b/src/app/screens/Login/index.tsx
@@ -9,30 +9,35 @@ import {
View
} from 'react-native';
-import { useGlobalValue } from '@context';
+import { useGlobalValue } from '@context/index';
import { actionsCreator } from '@context/user/actions';
-import { useLazyRequest } from '@hooks';
+import { useLazyRequest } from '@hooks/index';
import { authUser, setAuthHeaders } from '@services/UserService';
import LoginBg from '@assets/bc_inicio.png';
import LoginLogo from '@assets/Group.png';
import api from '@config/api';
-import { WHITE } from '@constants/colors';
+import COLORS from '@constants/colors';
+import { AuthHeaders } from '@interfaces/api';
import styles from './styles';
import { DEFAULT_ERROR_MSG } from './constants';
+interface Response {
+ headers: AuthHeaders;
+}
+
function Login() {
- const [email, setEmail] = useState();
- const [password, setPassword] = useState();
- const [error, setError] = useState();
- const [auth, { data: response, error: requestError, loading }] = useLazyRequest(authUser);
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [error, setError] = useState('');
+ const [auth, { data, error: requestError, loading }] = useLazyRequest(authUser);
const [, dispatch] = useGlobalValue();
useEffect(() => {
- if (response) {
+ if (data) {
(async () => {
try {
- const { 'access-token': userToken, uid, client } = response?.headers;
+ const { 'access-token': userToken, uid, client } = data?.headers;
const headers = { 'access-token': userToken, uid, client };
await setAuthHeaders(headers);
api.setHeaders(headers);
@@ -44,10 +49,10 @@ function Login() {
} else if (requestError) {
setError(DEFAULT_ERROR_MSG);
}
- }, [response, requestError, dispatch]);
+ }, [data, requestError, dispatch]);
- const handleEmail = value => setEmail(value);
- const handlePassword = value => setPassword(value);
+ const handleEmail = (value: string) => setEmail(value);
+ const handlePassword = (value: string) => setPassword(value);
const handleSubmit = () => auth({ email, password });
@@ -64,7 +69,7 @@ function Login() {
{loading ? (
-
+
) : (
Log In
)}
diff --git a/src/app/screens/Login/styles.js b/src/app/screens/Login/styles.ts
similarity index 85%
rename from src/app/screens/Login/styles.js
rename to src/app/screens/Login/styles.ts
index 56abf03..ea62f31 100644
--- a/src/app/screens/Login/styles.js
+++ b/src/app/screens/Login/styles.ts
@@ -1,6 +1,6 @@
import { StyleSheet } from 'react-native';
-import { WHITE, RED } from '@constants/colors';
+import COLORS from '@constants/colors';
const COMMON_STYLES = {
button: {
@@ -26,24 +26,24 @@ export const styles = StyleSheet.create({
},
loginInput: {
...COMMON_STYLES.button,
- backgroundColor: WHITE,
+ backgroundColor: COLORS.WHITE,
padding: 10
},
loginSubmit: {
...COMMON_STYLES.button,
alignItems: 'center',
- borderColor: WHITE,
+ borderColor: COLORS.WHITE,
borderStyle: 'solid',
borderWidth: 1,
justifyContent: 'center'
},
loginSubmitText: {
- color: WHITE,
+ color: COLORS.WHITE,
fontWeight: '700',
textTransform: 'uppercase'
},
loginError: {
- color: RED,
+ color: COLORS.RED,
height: 20
},
loginFooter: {
diff --git a/src/app/screens/index.js b/src/app/screens/index.ts
similarity index 100%
rename from src/app/screens/index.js
rename to src/app/screens/index.ts
diff --git a/src/config/api.js b/src/config/api.ts
similarity index 100%
rename from src/config/api.js
rename to src/config/api.ts
diff --git a/src/constants/book.js b/src/constants/book.ts
similarity index 56%
rename from src/constants/book.js
rename to src/constants/book.ts
index 600eabd..f33eb12 100644
--- a/src/constants/book.js
+++ b/src/constants/book.ts
@@ -1,7 +1,7 @@
export const DEFAULT_BOOK = {
- image: 'http://wolox-training.s3.amazonaws.com/uploads/6942334-M.jpg',
+ image: { url: 'http://wolox-training.s3.amazonaws.com/uploads/6942334-M.jpg' },
title: 'Ring of Bright Water',
author: 'Emme Thief',
year: '1968',
genre: 'terror'
-};
+} as const;
diff --git a/src/constants/colors.js b/src/constants/colors.js
deleted file mode 100644
index cf78063..0000000
--- a/src/constants/colors.js
+++ /dev/null
@@ -1,12 +0,0 @@
-export const POLAR = '#E9F6FA';
-export const WHITE = '#FFF';
-export const BLACK = '#000';
-export const SCORPION = '#5B5B5B';
-export const GRAY = '#8D8D8D';
-export const CERULEAN = '#04ACEC';
-export const TUNDORA = '#4A4A4A';
-export const JAVA = '#16B3D9';
-export const SCOOTER = '#32C4C6';
-export const TRANSPARENT = 'transparent';
-export const RED = '#FF0000';
-export const BLUE = '#0000FF';
diff --git a/src/constants/colors.ts b/src/constants/colors.ts
new file mode 100644
index 0000000..affa064
--- /dev/null
+++ b/src/constants/colors.ts
@@ -0,0 +1,16 @@
+enum COLORS {
+ POLAR = '#E9F6FA',
+ WHITE = '#FFF',
+ BLACK = '#000',
+ SCORPION = '#5B5B5B',
+ GRAY = '#8D8D8D',
+ CERULEAN = '#04ACEC',
+ TUNDORA = '#4A4A4A',
+ JAVA = '#16B3D9',
+ SCOOTER = '#32C4C6',
+ TRANSPARENT = 'transparent',
+ RED = '#FF0000',
+ BLUE = '#0000FF'
+}
+
+export default COLORS;
diff --git a/src/constants/routes.js b/src/constants/routes.js
deleted file mode 100644
index 5e2e35c..0000000
--- a/src/constants/routes.js
+++ /dev/null
@@ -1,14 +0,0 @@
-export const LIBRARY = {
- NAME: 'Library',
- TITLE: 'LIBRARY'
-};
-
-export const BOOK_DETAIL = {
- NAME: 'BookDetail',
- TITLE: 'BOOK DETAIL'
-};
-
-export const LOGIN = {
- NAME: 'Login',
- TITLE: 'LOGIN'
-};
diff --git a/src/constants/routes.ts b/src/constants/routes.ts
new file mode 100644
index 0000000..e071e19
--- /dev/null
+++ b/src/constants/routes.ts
@@ -0,0 +1,14 @@
+export enum LIBRARY {
+ NAME = 'Library',
+ TITLE = 'LIBRARY'
+}
+
+export enum BOOK_DETAIL {
+ NAME = 'BookDetail',
+ TITLE = 'BOOK DETAIL'
+}
+
+export enum LOGIN {
+ NAME = 'Login',
+ TITLE = 'LOGIN'
+}
diff --git a/src/constants/types.js b/src/constants/types.js
deleted file mode 100644
index 486961d..0000000
--- a/src/constants/types.js
+++ /dev/null
@@ -1,7 +0,0 @@
-export const DATA_TYPES = {
- number: 'number',
- string: 'string',
- object: 'object',
- fn: 'function',
- undef: 'undefined'
-};
diff --git a/src/constants/types.ts b/src/constants/types.ts
new file mode 100644
index 0000000..feef930
--- /dev/null
+++ b/src/constants/types.ts
@@ -0,0 +1,7 @@
+export enum DATA_TYPES {
+ number = 'number',
+ string = 'string',
+ object = 'object',
+ fn = 'function',
+ undef = 'undefined'
+}
diff --git a/src/context/index.js b/src/context/index.js
deleted file mode 100644
index a807799..0000000
--- a/src/context/index.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { useContext, createContext } from 'react';
-
-import { userReducer, userState } from './user';
-
-export const globalState = {
- userState
-};
-
-export const globalReducer = (state, action) => ({
- userState: userReducer(state.userState, action)
-});
-
-export const GlobalContext = createContext();
-
-export const useGlobalValue = () => useContext(GlobalContext);
diff --git a/src/context/index.ts b/src/context/index.ts
new file mode 100644
index 0000000..4b3403f
--- /dev/null
+++ b/src/context/index.ts
@@ -0,0 +1,20 @@
+import React, { useContext, createContext } from 'react';
+
+import { userReducer, userState } from './user';
+import { UserAction } from './user/types';
+
+export const globalState = {
+ userState
+};
+
+const dispatch: React.Dispatch = () => ({});
+
+export const globalReducer = (state: typeof globalState, action: unknown) => ({
+ userState: userReducer(state.userState, action as UserAction)
+});
+
+const defaultValue = [globalState, dispatch] as const;
+
+export const GlobalContext = createContext(defaultValue);
+
+export const useGlobalValue = () => useContext(GlobalContext);
diff --git a/src/context/user/actions.js b/src/context/user/actions.js
deleted file mode 100644
index 12c2f92..0000000
--- a/src/context/user/actions.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import { stringArrayToObject } from '@utils/arrays';
-
-export const actions = stringArrayToObject(['LOG_IN', 'LOG_OUT']);
-
-export const actionsCreator = {
- logIn: token => ({
- type: actions.LOG_IN,
- payload: token
- }),
- logOut: () => ({
- type: actions.LOG_OUT
- })
-};
diff --git a/src/context/user/actions.ts b/src/context/user/actions.ts
new file mode 100644
index 0000000..50faee1
--- /dev/null
+++ b/src/context/user/actions.ts
@@ -0,0 +1,11 @@
+import { ActionsCreator, ActionTypes } from './types';
+
+export const actionsCreator: ActionsCreator = {
+ logIn: token => ({
+ type: ActionTypes.LOG_IN,
+ payload: token
+ }),
+ logOut: () => ({
+ type: ActionTypes.LOG_OUT
+ })
+};
diff --git a/src/context/user/index.js b/src/context/user/index.js
deleted file mode 100644
index a0f693a..0000000
--- a/src/context/user/index.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import { actions } from './actions';
-
-export const userState = {
- token: null
-};
-
-const reducer = {
- [actions.LOG_IN]: (state, action) => ({
- ...state,
- token: action.payload
- }),
- [actions.LOG_OUT]: state => ({
- ...state,
- token: null
- })
-};
-
-export const userReducer = (state = userState, action) =>
- reducer[action.type] ? reducer[action.type](state, action) : state;
diff --git a/src/context/user/index.ts b/src/context/user/index.ts
new file mode 100644
index 0000000..c38e7c5
--- /dev/null
+++ b/src/context/user/index.ts
@@ -0,0 +1,22 @@
+import { UserState, UserAction, ActionTypes } from './types';
+
+export const userState: UserState = {
+ token: null
+};
+
+export const userReducer = (state: UserState, action: UserAction): UserState => {
+ switch (action.type) {
+ case ActionTypes.LOG_IN:
+ return {
+ ...state,
+ token: action.payload
+ };
+ case ActionTypes.LOG_OUT:
+ return {
+ ...state,
+ token: null
+ };
+ default:
+ return state;
+ }
+};
diff --git a/src/context/user/types.ts b/src/context/user/types.ts
new file mode 100644
index 0000000..3b1a2e9
--- /dev/null
+++ b/src/context/user/types.ts
@@ -0,0 +1,15 @@
+export enum ActionTypes {
+ LOG_IN = 'LOG_IN',
+ LOG_OUT = 'LOG_OUT'
+}
+
+export interface ActionsCreator {
+ logIn(token: string): UserAction;
+ logOut(): UserAction;
+}
+
+export interface UserState {
+ token: string | null;
+}
+
+export type UserAction = { type: ActionTypes.LOG_IN; payload: string } | { type: ActionTypes.LOG_OUT };
diff --git a/src/hooks/index.js b/src/hooks/index.ts
similarity index 100%
rename from src/hooks/index.js
rename to src/hooks/index.ts
diff --git a/src/hooks/useLazyRequest.js b/src/hooks/useLazyRequest.js
deleted file mode 100644
index 42c9aa5..0000000
--- a/src/hooks/useLazyRequest.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import { useState } from 'react';
-
-function useLazyRequest(query) {
- const [data, setData] = useState();
- const [loading, setLoading] = useState();
- const [error, setError] = useState();
-
- const request = async values => {
- try {
- setLoading(true);
- const response = await query(values);
- if (response?.ok) {
- setLoading(false);
- setData(response);
- } else {
- throw Error();
- }
- } catch {
- setError(true);
- setLoading(false);
- }
- };
-
- return [request, { data, loading, error }];
-}
-
-export default useLazyRequest;
diff --git a/src/hooks/useLazyRequest.ts b/src/hooks/useLazyRequest.ts
new file mode 100644
index 0000000..5b2f5f5
--- /dev/null
+++ b/src/hooks/useLazyRequest.ts
@@ -0,0 +1,29 @@
+import { useState } from 'react';
+
+import { Query, QueryParams } from '@interfaces/api';
+
+function useLazyRequest(query: Query) {
+ const [data, setData] = useState();
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(false);
+
+ const request = async (params: QueryParams) => {
+ try {
+ setLoading(true);
+ const response = await query(params);
+ if (response?.ok) {
+ setLoading(false);
+ setData(response);
+ } else {
+ throw Error();
+ }
+ } catch {
+ setError(true);
+ setLoading(false);
+ }
+ };
+
+ return [request, { data, loading, error }] as const;
+}
+
+export default useLazyRequest;
diff --git a/src/hooks/useRequest.js b/src/hooks/useRequest.ts
similarity index 66%
rename from src/hooks/useRequest.js
rename to src/hooks/useRequest.ts
index 593153e..6cbcf90 100644
--- a/src/hooks/useRequest.js
+++ b/src/hooks/useRequest.ts
@@ -1,14 +1,15 @@
import { useState, useEffect } from 'react';
-function useRequest(query, params) {
+import { Query, QueryParams } from '@interfaces/api';
+
+function useRequest(query: Query, params?: QueryParams) {
const [reqParams] = useState(params);
- const [loading, setLoading] = useState();
- const [data, setData] = useState();
- const [error, setError] = useState();
+ const [data, setData] = useState();
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(false);
useEffect(() => {
(async () => {
- setLoading(true);
try {
const response = await query(reqParams);
if (response?.ok) {
diff --git a/src/index.d.ts b/src/index.d.ts
new file mode 100644
index 0000000..e2937d4
--- /dev/null
+++ b/src/index.d.ts
@@ -0,0 +1 @@
+declare module '*.png';
diff --git a/src/interfaces/api.ts b/src/interfaces/api.ts
new file mode 100644
index 0000000..dfed1ee
--- /dev/null
+++ b/src/interfaces/api.ts
@@ -0,0 +1,11 @@
+export type AuthHeaders = {
+ 'access-token': string;
+ uid: string;
+ client: string;
+};
+
+export type QueryParams = {
+ [key: string]: any;
+};
+
+export type Query = (...args: any[]) => Promise;
diff --git a/src/interfaces/book.ts b/src/interfaces/book.ts
new file mode 100644
index 0000000..dd96996
--- /dev/null
+++ b/src/interfaces/book.ts
@@ -0,0 +1,13 @@
+export interface Book {
+ id: number;
+ author: string;
+ title: string;
+ image: { url: string };
+ year: string;
+ genre: string;
+ // eslint-disable-next-line camelcase
+ created_at: string;
+ // eslint-disable-next-line camelcase
+ updated_at: string;
+ rents: [];
+}
diff --git a/src/services/BookService.js b/src/services/BookService.js
deleted file mode 100644
index 50aa4da..0000000
--- a/src/services/BookService.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import api from '@config/api';
-
-export const getBooksList = () => api.get('/books');
-
-export const getBook = ({ id }) => api.get(`/books/${id}`);
diff --git a/src/services/BookService.ts b/src/services/BookService.ts
new file mode 100644
index 0000000..dc2a802
--- /dev/null
+++ b/src/services/BookService.ts
@@ -0,0 +1,6 @@
+import api from '@config/api';
+import { Book } from '@interfaces/book';
+
+export const getBooksList = () => api.get('/books');
+
+export const getBook = ({ id }: { id: number }) => api.get(`/books/${id}`);
diff --git a/src/services/UserService.js b/src/services/UserService.js
deleted file mode 100644
index 678b9f6..0000000
--- a/src/services/UserService.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import api from '@config/api';
-
-import { setStorageItem, getStorageItem } from '@utils/storage';
-
-export const authUser = user => api.post('/auth/sign_in', user);
-
-export const getAuthHeaders = () => getStorageItem('authHeaders');
-
-export const setAuthHeaders = data => data && setStorageItem('authHeaders', data);
diff --git a/src/services/UserService.ts b/src/services/UserService.ts
new file mode 100644
index 0000000..fa68398
--- /dev/null
+++ b/src/services/UserService.ts
@@ -0,0 +1,15 @@
+import api from '@config/api';
+
+import { setStorageItem, getStorageItem } from '@utils/storage';
+import { AuthHeaders } from '@interfaces/api';
+
+interface User {
+ email: string;
+ password: string;
+}
+
+export const authUser = (user: User) => api.post('/auth/sign_in', user);
+
+export const getAuthHeaders = () => getStorageItem('authHeaders');
+
+export const setAuthHeaders = (data: AuthHeaders) => setStorageItem('authHeaders', data);
diff --git a/src/styles/shadows.js b/src/styles/shadows.ts
similarity index 75%
rename from src/styles/shadows.js
rename to src/styles/shadows.ts
index 37a60bb..7576053 100644
--- a/src/styles/shadows.js
+++ b/src/styles/shadows.ts
@@ -1,10 +1,10 @@
import { StyleSheet } from 'react-native';
-import { BLACK } from '@constants/colors';
+import COLORS from '@constants/colors';
export const BOX_SHADOW = StyleSheet.create({
type1: {
- shadowColor: BLACK,
+ shadowColor: COLORS.BLACK,
shadowOffset: {
width: 0,
height: 1
diff --git a/src/utils/arrays.js b/src/utils/arrays.js
deleted file mode 100644
index 3eda025..0000000
--- a/src/utils/arrays.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export const isNotEmptyArray = array => Array.isArray(array) && !!array.length;
-
-export const stringArrayToObject = array =>
- isNotEmptyArray(array) && array.reduce((result, value) => ({ ...result, [value]: value }), {});
diff --git a/src/utils/objects.js b/src/utils/objects.js
deleted file mode 100644
index 8088eac..0000000
--- a/src/utils/objects.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import { DATA_TYPES } from '@constants/types';
-
-export const isNotEmptyObject = obj =>
- obj && !Array.isArray(obj) && typeof obj === DATA_TYPES.object && !!Object.keys(obj).length;
diff --git a/src/utils/renders.js b/src/utils/renders.js
deleted file mode 100644
index eeeba42..0000000
--- a/src/utils/renders.js
+++ /dev/null
@@ -1 +0,0 @@
-export const keyExtractor = ({ id }) => id.toString();
diff --git a/src/utils/renders.ts b/src/utils/renders.ts
new file mode 100644
index 0000000..b9fcf43
--- /dev/null
+++ b/src/utils/renders.ts
@@ -0,0 +1 @@
+export const keyExtractor = ({ id }: { id: number }): string => id.toString();
diff --git a/src/utils/serializers.js b/src/utils/serializers.js
deleted file mode 100644
index 6933a39..0000000
--- a/src/utils/serializers.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/* eslint-disable camelcase */
-import { Serializer } from 'cerealizr';
-
-import { isNotEmptyObject } from './objects';
-import { isNotEmptyArray } from './arrays';
-
-const bookSerializer = new Serializer({
- descriptor: {
- image_url: 'imageUrl'
- },
- mapAllValues: true
-});
-
-export const serializeBook = book => isNotEmptyObject(book) && bookSerializer.serialize(book);
-
-export const serializeBooks = books =>
- isNotEmptyArray(books) && books.map(book => bookSerializer.serialize(book));
diff --git a/src/utils/storage.js b/src/utils/storage.ts
similarity index 55%
rename from src/utils/storage.js
rename to src/utils/storage.ts
index e176eb3..1ee6e56 100644
--- a/src/utils/storage.js
+++ b/src/utils/storage.ts
@@ -1,8 +1,13 @@
import AsyncStorage from '@react-native-community/async-storage';
-export const setStorageItem = (key, data) => AsyncStorage.setItem(key, JSON.stringify(data));
+export const setStorageItem = (key: string, data: T) => AsyncStorage.setItem(key, JSON.stringify(data));
-export const getStorageItem = async key => {
+interface Response {
+ data: T | null;
+ ok: boolean;
+}
+
+export const getStorageItem = async (key: string): Promise> => {
try {
const response = await AsyncStorage.getItem(key);
if (response) return Promise.resolve({ data: JSON.parse(response), ok: true });
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..604f56d
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "allowJs": true,
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "isolatedModules": true,
+ "jsx": "react",
+ "lib": ["es6"],
+ "moduleResolution": "node",
+ "noEmit": true,
+ "strict": true,
+ "target": "esnext"
+ },
+ "exclude": [
+ "node_modules",
+ "babel.config.js",
+ "metro.config.js",
+ "jest.config.js"
+ ],
+ "include": ["src"],
+ "extends": "./tsconfig.paths.json"
+}
diff --git a/tsconfig.paths.json b/tsconfig.paths.json
new file mode 100644
index 0000000..1b779fa
--- /dev/null
+++ b/tsconfig.paths.json
@@ -0,0 +1,18 @@
+{
+ "compilerOptions": {
+ "baseUrl": "src",
+ "paths": {
+ "@constants/*": ["constants/*"],
+ "@assets/*": ["assets/*"],
+ "@screens/*": ["app/screens/*"],
+ "@components/*": ["app/components/*"],
+ "@hooks/*": ["hooks/*"],
+ "@services/*": ["services/*"],
+ "@config/*": ["config/*"],
+ "@utils/*": ["utils/*"],
+ "@styles/*": ["styles/*"],
+ "@context/*": ["context/*"],
+ "@interfaces/*": ["interfaces/*"]
+ }
+ }
+}