diff --git a/.babelrc.js b/.babelrc.js new file mode 100644 index 0000000..b77d8de --- /dev/null +++ b/.babelrc.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: [ + 'babel-plugin-jsx-control-statements', + ], +} diff --git a/.eslintrc.js b/.eslintrc.js index 0be69c1..1bfe626 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,26 +3,36 @@ module.exports = { extends: [ 'react-app', 'plugin:jest/recommended', + 'plugin:jsx-control-statements/recommended', '@lacussoft', 'plugin:@typescript-eslint/recommended', ], + ignorePatterns: [ + 'build/', + 'dist/', + '!.babelrc*', + ], plugins: [ - 'react', '@typescript-eslint', 'jest', + 'jsx-control-statements', + 'react', ], parser: '@typescript-eslint/parser', parserOptions: { - sourceType: 'module', - ecmaVersion: 2020, ecmaFeatures: { jsx: true, }, + ecmaVersion: 2020, + sourceType: 'module', }, rules: { '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-use-before-define': 'off', 'no-console': 'off', 'no-use-before-define': 'off', + 'react/jsx-indent-props': ['error', 2], + 'react/jsx-closing-bracket-location': 'error', + 'react/jsx-no-undef': [2, { allowGlobals: true }], }, } diff --git a/config-overrides.js b/config-overrides.js new file mode 100644 index 0000000..71c6783 --- /dev/null +++ b/config-overrides.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +const { useBabelRc, override } = require('customize-cra') + +module.exports = override(useBabelRc()) diff --git a/package-lock.json b/package-lock.json index d42f31d..53ecc3a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3757,6 +3757,15 @@ "@types/babel__traverse": "^7.0.6" } }, + "babel-plugin-jsx-control-statements": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jsx-control-statements/-/babel-plugin-jsx-control-statements-4.1.0.tgz", + "integrity": "sha512-YNHX/yJ79cjZ5ZOZ6oiixoihm1SfhQKIcMfxDT+t8Olpd9NyNBrxjYjwJKxYQVZrfMBnCLxC4Mqj5Ru+OXtQ0w==", + "dev": true, + "requires": { + "@babel/core": "^7.1.2" + } + }, "babel-plugin-macros": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", @@ -5616,6 +5625,15 @@ "array-find-index": "^1.0.1" } }, + "customize-cra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/customize-cra/-/customize-cra-1.0.0.tgz", + "integrity": "sha512-DbtaLuy59224U+xCiukkxSq8clq++MOtJ1Et7LED1fLszWe88EoblEYFBJ895sB1mC6B4uu3xPT/IjClELhMbA==", + "dev": true, + "requires": { + "lodash.flow": "^3.5.0" + } + }, "cyclist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", @@ -6810,6 +6828,12 @@ } } }, + "eslint-plugin-jsx-control-statements": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-control-statements/-/eslint-plugin-jsx-control-statements-2.2.1.tgz", + "integrity": "sha512-BkqbYSu7KuOwsmxmmD9mi1KLz3cAXqXvDSN/Re+yKnIAO6SGRAx3aiUmsjOWAAGJonfhtNZCCTN9jfzQ5hto+Q==", + "dev": true + }, "eslint-plugin-react": { "version": "7.22.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz", @@ -11459,6 +11483,12 @@ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", "dev": true }, + "lodash.flow": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", + "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=", + "dev": true + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -14587,6 +14617,23 @@ "whatwg-fetch": "^3.4.1" } }, + "react-app-rewired": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.1.8.tgz", + "integrity": "sha512-wjXPdKPLscA7mn0I1de1NHrbfWdXz4S1ladaGgHVKdn1hTgKK5N6EdGIJM0KrS6bKnJBj7WuqJroDTsPKKr66Q==", + "dev": true, + "requires": { + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "react-dev-utils": { "version": "11.0.2", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.2.tgz", diff --git a/package.json b/package.json index a5d628d..24430d5 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,9 @@ "author": "Julio L. Muller", "homepage": "https://juliolmuller.github.io/marvel-characters", "scripts": { - "start": "react-scripts start", - "build": "rm -rf docs/ && react-scripts build && mv build/ docs/", - "test": "react-scripts test", + "start": "react-app-rewired start", + "build": "rm -rf docs/ && react-app-rewired build && mv build/ docs/", + "test": "react-app-rewired test", "eject": "react-scripts eject" }, "dependencies": { @@ -33,8 +33,12 @@ "@types/react-dom": "^17.0.0", "@typescript-eslint/eslint-plugin": "^4.14.2", "@typescript-eslint/parser": "^4.14.2", + "babel-plugin-jsx-control-statements": "^4.1.0", + "customize-cra": "^1.0.0", "eslint-plugin-jest": "^24.1.3", + "eslint-plugin-jsx-control-statements": "^2.2.1", "node-sass": "^4.14.1", + "react-app-rewired": "^2.1.8", "react-scripts": "^4.0.2", "typescript": "^4.1.3" }, diff --git a/src/@types/index.d.ts b/src/@types/index.d.ts index a4d0905..3a15247 100644 --- a/src/@types/index.d.ts +++ b/src/@types/index.d.ts @@ -1,4 +1,19 @@ +declare function If(props: { condition: boolean }): any +declare function Choose(): any +declare function When(props: { condition: boolean }): any +declare function Otherwise(): any +declare function For(props: { each: string, of: Iterable, index?: string }): any +declare function With(props: { [id: string]: any }): any + +declare namespace JSX { + type TChildren = Element | string | number | boolean | null | typeof undefined + + interface IntrinsicAttributes { + children?: TChildren | TChildren[] + } +} + interface JQuery { modal: (action: 'hide' | 'show' | 'toggle') => any } diff --git a/src/components/App.tsx b/src/components/App.tsx index 6047b75..8ee8903 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -1,4 +1,4 @@ -import React, { FC, useState } from 'react' +import { FC, useState } from 'react' import Header from './Header' import SearchBox from './SearchBox' import CharactersList from './CharactersList' @@ -35,20 +35,23 @@ const App: FC = () => {
+

- {loading ? ( +
Loading animation
- ) : ( +
+ + submitSearch(lastSearch, page)} /> - )} +
diff --git a/src/components/CharacterCard/index.tsx b/src/components/CharacterCard/index.tsx index e0c97ea..e3b6af9 100644 --- a/src/components/CharacterCard/index.tsx +++ b/src/components/CharacterCard/index.tsx @@ -1,4 +1,4 @@ -import React, { FC } from 'react' +import { FC } from 'react' import './styles.scss' interface CharacterCardProps { @@ -15,6 +15,7 @@ const CharacterCard: FC = ({ character, showDetails }) => ( className="figure-fluid float-left" alt="Character thumbnail" /> +

{character.name} diff --git a/src/components/CharacterModal/index.tsx b/src/components/CharacterModal/index.tsx index fcd7895..0d915b0 100644 --- a/src/components/CharacterModal/index.tsx +++ b/src/components/CharacterModal/index.tsx @@ -1,4 +1,4 @@ -import React, { FC, useEffect } from 'react' +import { FC, useEffect } from 'react' import $ from 'jquery' import './styles.scss' @@ -41,10 +41,13 @@ const CharacterModal: FC = ({ character, hideDetails }) => {character.name}

+
-

{character.description || ( - No description - )}

+

+ {character.description || ( + No description + )} +

{character.stories.available} stories
{character.comics.available} comics
@@ -52,6 +55,7 @@ const CharacterModal: FC = ({ character, hideDetails }) =>
{character.events.available} events
+
- {props.displayCounter && ( + + Page {props.current} of {last} - )} + +