From 00cde8c8f7c4deb31ff409c2ae2e87fd74f6cdf2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carl=20Sch=C3=B6nfelder?= <carsc272@student.liu.se>
Date: Tue, 16 Feb 2021 14:55:50 +0100
Subject: [PATCH] Issue/4 add format on save

---
 .vscode/extensions.json       |   3 +-
 .vscode/settings.json         |  21 +-
 client/.eslintrc              |  34 +++
 client/.prettierrc            |   6 +
 client/package-lock.json      | 395 ++++++++++++++++++++++++++++++++--
 client/package.json           |  24 ++-
 client/src/App.test.tsx       |  14 +-
 client/src/App.tsx            |  27 ++-
 client/src/index.tsx          |  14 +-
 client/src/reportWebVitals.ts |  18 +-
 client/src/setupTests.ts      |   2 +-
 11 files changed, 499 insertions(+), 59 deletions(-)
 create mode 100644 client/.eslintrc
 create mode 100644 client/.prettierrc

diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index d849a6db..9421e18e 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -5,6 +5,7 @@
         "pranaygp.vscode-css-peek",
         "dbaeumer.vscode-eslint",
         "ms-vsliveshare.vsliveshare",
-        "cssho.vscode-svgviewer"
+        "cssho.vscode-svgviewer",
+        "esbenp.prettier-vscode"
     ]
 }
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 81f7de10..896cb947 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,7 +1,13 @@
 {
+    //editor
     "editor.formatOnSave": true,
     "editor.formatOnPaste": false,
     "editor.tabCompletion": "on",
+    "editor.codeActionsOnSave": {
+        "source.fixAll.eslint": true,
+        "source.organizeImports": true
+    },
+    //python
     "python.venvPath": "${workspaceFolder}\\server",
     "python.analysis.extraPaths": ["server"],
     "python.terminal.activateEnvironment": true,
@@ -11,5 +17,18 @@
         "--line-length",
         "119"
     ],
-    "git.ignoreLimitWarning": true
+    //eslint
+    "eslint.workingDirectories": ["./client"],
+    "eslint.options": {
+        "configFile":"./.eslintrc"
+    },
+    //git
+    "git.ignoreLimitWarning": true,
+    //language specific
+    "[typescript]": {
+        "editor.defaultFormatter": "esbenp.prettier-vscode"
+    },
+    "[typescriptreact]": {
+        "editor.defaultFormatter": "esbenp.prettier-vscode"
+    },
 }
\ No newline at end of file
diff --git a/client/.eslintrc b/client/.eslintrc
new file mode 100644
index 00000000..193fae78
--- /dev/null
+++ b/client/.eslintrc
@@ -0,0 +1,34 @@
+  {
+    "env": {
+        "browser": true,
+        "es6": true,
+        "node": true
+    },
+    "parser": "@typescript-eslint/parser",
+    "parserOptions": {
+        "ecmaFeatures": {
+            "jsx": true
+        },
+        "project": ["tsconfig.json"],
+        "ecmaVersion": 2021,
+        "sourceType": "module"
+    },
+    
+    "settings": {
+        "react": {
+          "version": "detect"
+        }
+    },
+    "extends": [
+        "airbnb-typescript",
+        "plugin:@typescript-eslint/recommended",
+        "plugin:react/recommended",
+        "prettier/@typescript-eslint",
+        "plugin:prettier/recommended"
+    ],
+    "rules": {
+        "semi":"off",
+        "react/jsx-one-expression-per-line": "off"
+
+    }
+}
diff --git a/client/.prettierrc b/client/.prettierrc
new file mode 100644
index 00000000..76ee677f
--- /dev/null
+++ b/client/.prettierrc
@@ -0,0 +1,6 @@
+{
+    "semi": false,
+    "trailingComma": "none",
+    "singleQuote": true,
+    "printWidth": 80
+  }
\ No newline at end of file
diff --git a/client/package-lock.json b/client/package-lock.json
index 24b4bff5..597032d7 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -2393,18 +2393,76 @@
       "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA=="
     },
     "@typescript-eslint/eslint-plugin": {
-      "version": "4.15.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.0.tgz",
-      "integrity": "sha512-DJgdGZW+8CFUTz5C/dnn4ONcUm2h2T0itWD85Ob5/V27Ndie8hUoX5HKyGssvR8sUMkAIlUc/AMK67Lqa3kBIQ==",
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.2.0.tgz",
+      "integrity": "sha512-zBNRkzvLSwo6y5TG0DVcmshZIYBHKtmzD4N+LYnfTFpzc4bc79o8jNRSb728WV7A4Cegbs+MV5IRAj8BKBgOVQ==",
+      "dev": true,
       "requires": {
-        "@typescript-eslint/experimental-utils": "4.15.0",
-        "@typescript-eslint/scope-manager": "4.15.0",
+        "@typescript-eslint/experimental-utils": "4.2.0",
+        "@typescript-eslint/scope-manager": "4.2.0",
         "debug": "^4.1.1",
         "functional-red-black-tree": "^1.0.1",
-        "lodash": "^4.17.15",
         "regexpp": "^3.0.0",
         "semver": "^7.3.2",
         "tsutils": "^3.17.1"
+      },
+      "dependencies": {
+        "@typescript-eslint/experimental-utils": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.2.0.tgz",
+          "integrity": "sha512-5BBj6BjgHEndBaQQpUVzRIPERz03LBc0MCQkHwUaH044FJFL08SwWv/sQftk7gf0ShZ2xZysz0LTwCwNt4Xu3w==",
+          "dev": true,
+          "requires": {
+            "@types/json-schema": "^7.0.3",
+            "@typescript-eslint/scope-manager": "4.2.0",
+            "@typescript-eslint/types": "4.2.0",
+            "@typescript-eslint/typescript-estree": "4.2.0",
+            "eslint-scope": "^5.0.0",
+            "eslint-utils": "^2.0.0"
+          }
+        },
+        "@typescript-eslint/scope-manager": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.2.0.tgz",
+          "integrity": "sha512-Tb402cxxObSxWIVT+PnBp5ruT2V/36yj6gG4C9AjkgRlZpxrLAzWDk3neen6ToMBGeGdxtnfFLoJRUecGz9mYQ==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "4.2.0",
+            "@typescript-eslint/visitor-keys": "4.2.0"
+          }
+        },
+        "@typescript-eslint/types": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.2.0.tgz",
+          "integrity": "sha512-xkv5nIsxfI/Di9eVwN+G9reWl7Me9R5jpzmZUch58uQ7g0/hHVuGUbbn4NcxcM5y/R4wuJIIEPKPDb5l4Fdmwg==",
+          "dev": true
+        },
+        "@typescript-eslint/typescript-estree": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.2.0.tgz",
+          "integrity": "sha512-iWDLCB7z4MGkLipduF6EOotdHNtgxuNKnYD54nMS/oitFnsk4S3S/TE/UYXQTra550lHtlv9eGmp+dvN9pUDtA==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "4.2.0",
+            "@typescript-eslint/visitor-keys": "4.2.0",
+            "debug": "^4.1.1",
+            "globby": "^11.0.1",
+            "is-glob": "^4.0.1",
+            "lodash": "^4.17.15",
+            "semver": "^7.3.2",
+            "tsutils": "^3.17.1"
+          }
+        },
+        "@typescript-eslint/visitor-keys": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.2.0.tgz",
+          "integrity": "sha512-WIf4BNOlFOH2W+YqGWa6YKLcK/EB3gEj2apCrqLw6mme1RzBy0jtJ9ewJgnrZDB640zfnv8L+/gwGH5sYp/rGw==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "4.2.0",
+            "eslint-visitor-keys": "^2.0.0"
+          }
+        }
       }
     },
     "@typescript-eslint/experimental-utils": {
@@ -2421,14 +2479,59 @@
       }
     },
     "@typescript-eslint/parser": {
-      "version": "4.15.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.0.tgz",
-      "integrity": "sha512-L6Dtbq8Bc7g2aZwnIBETpmUa9XDKCMzKVwAArnGp5Mn7PRNFjf3mUzq8UeBjL3K8t311hvevnyqXAMSmxO8Gpg==",
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.2.0.tgz",
+      "integrity": "sha512-54jJ6MwkOtowpE48C0QJF9iTz2/NZxfKVJzv1ha5imigzHbNSLN9yvbxFFH1KdlRPQrlR8qxqyOvLHHxd397VA==",
+      "dev": true,
       "requires": {
-        "@typescript-eslint/scope-manager": "4.15.0",
-        "@typescript-eslint/types": "4.15.0",
-        "@typescript-eslint/typescript-estree": "4.15.0",
+        "@typescript-eslint/scope-manager": "4.2.0",
+        "@typescript-eslint/types": "4.2.0",
+        "@typescript-eslint/typescript-estree": "4.2.0",
         "debug": "^4.1.1"
+      },
+      "dependencies": {
+        "@typescript-eslint/scope-manager": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.2.0.tgz",
+          "integrity": "sha512-Tb402cxxObSxWIVT+PnBp5ruT2V/36yj6gG4C9AjkgRlZpxrLAzWDk3neen6ToMBGeGdxtnfFLoJRUecGz9mYQ==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "4.2.0",
+            "@typescript-eslint/visitor-keys": "4.2.0"
+          }
+        },
+        "@typescript-eslint/types": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.2.0.tgz",
+          "integrity": "sha512-xkv5nIsxfI/Di9eVwN+G9reWl7Me9R5jpzmZUch58uQ7g0/hHVuGUbbn4NcxcM5y/R4wuJIIEPKPDb5l4Fdmwg==",
+          "dev": true
+        },
+        "@typescript-eslint/typescript-estree": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.2.0.tgz",
+          "integrity": "sha512-iWDLCB7z4MGkLipduF6EOotdHNtgxuNKnYD54nMS/oitFnsk4S3S/TE/UYXQTra550lHtlv9eGmp+dvN9pUDtA==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "4.2.0",
+            "@typescript-eslint/visitor-keys": "4.2.0",
+            "debug": "^4.1.1",
+            "globby": "^11.0.1",
+            "is-glob": "^4.0.1",
+            "lodash": "^4.17.15",
+            "semver": "^7.3.2",
+            "tsutils": "^3.17.1"
+          }
+        },
+        "@typescript-eslint/visitor-keys": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.2.0.tgz",
+          "integrity": "sha512-WIf4BNOlFOH2W+YqGWa6YKLcK/EB3gEj2apCrqLw6mme1RzBy0jtJ9ewJgnrZDB640zfnv8L+/gwGH5sYp/rGw==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "4.2.0",
+            "eslint-visitor-keys": "^2.0.0"
+          }
+        }
       }
     },
     "@typescript-eslint/scope-manager": {
@@ -5601,6 +5704,100 @@
         }
       }
     },
+    "eslint-config-airbnb": {
+      "version": "18.2.1",
+      "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-18.2.1.tgz",
+      "integrity": "sha512-glZNDEZ36VdlZWoxn/bUR1r/sdFKPd1mHPbqUtkctgNG4yT2DLLtJ3D+yCV+jzZCc2V1nBVkmdknOJBZ5Hc0fg==",
+      "dev": true,
+      "requires": {
+        "eslint-config-airbnb-base": "^14.2.1",
+        "object.assign": "^4.1.2",
+        "object.entries": "^1.1.2"
+      }
+    },
+    "eslint-config-airbnb-base": {
+      "version": "14.2.1",
+      "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz",
+      "integrity": "sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==",
+      "dev": true,
+      "requires": {
+        "confusing-browser-globals": "^1.0.10",
+        "object.assign": "^4.1.2",
+        "object.entries": "^1.1.2"
+      }
+    },
+    "eslint-config-airbnb-typescript": {
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-12.3.1.tgz",
+      "integrity": "sha512-ql/Pe6/hppYuRp4m3iPaHJqkBB7dgeEmGPQ6X0UNmrQOfTF+dXw29/ZjU2kQ6RDoLxaxOA+Xqv07Vbef6oVTWw==",
+      "dev": true,
+      "requires": {
+        "@typescript-eslint/parser": "^4.4.1",
+        "eslint-config-airbnb": "^18.2.0",
+        "eslint-config-airbnb-base": "^14.2.0"
+      },
+      "dependencies": {
+        "@typescript-eslint/parser": {
+          "version": "4.15.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.1.tgz",
+          "integrity": "sha512-V8eXYxNJ9QmXi5ETDguB7O9diAXlIyS+e3xzLoP/oVE4WCAjssxLIa0mqCLsCGXulYJUfT+GV70Jv1vHsdKwtA==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/scope-manager": "4.15.1",
+            "@typescript-eslint/types": "4.15.1",
+            "@typescript-eslint/typescript-estree": "4.15.1",
+            "debug": "^4.1.1"
+          }
+        },
+        "@typescript-eslint/scope-manager": {
+          "version": "4.15.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.1.tgz",
+          "integrity": "sha512-ibQrTFcAm7yG4C1iwpIYK7vDnFg+fKaZVfvyOm3sNsGAerKfwPVFtYft5EbjzByDJ4dj1WD8/34REJfw/9wdVA==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "4.15.1",
+            "@typescript-eslint/visitor-keys": "4.15.1"
+          }
+        },
+        "@typescript-eslint/types": {
+          "version": "4.15.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.1.tgz",
+          "integrity": "sha512-iGsaUyWFyLz0mHfXhX4zO6P7O3sExQpBJ2dgXB0G5g/8PRVfBBsmQIc3r83ranEQTALLR3Vko/fnCIVqmH+mPw==",
+          "dev": true
+        },
+        "@typescript-eslint/typescript-estree": {
+          "version": "4.15.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.1.tgz",
+          "integrity": "sha512-z8MN3CicTEumrWAEB2e2CcoZa3KP9+SMYLIA2aM49XW3cWIaiVSOAGq30ffR5XHxRirqE90fgLw3e6WmNx5uNw==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "4.15.1",
+            "@typescript-eslint/visitor-keys": "4.15.1",
+            "debug": "^4.1.1",
+            "globby": "^11.0.1",
+            "is-glob": "^4.0.1",
+            "semver": "^7.3.2",
+            "tsutils": "^3.17.1"
+          }
+        },
+        "@typescript-eslint/visitor-keys": {
+          "version": "4.15.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.1.tgz",
+          "integrity": "sha512-tYzaTP9plooRJY8eNlpAewTOqtWW/4ff/5wBjNVaJ0S0wC4Gpq/zDVRTJa5bq2v1pCNQ08xxMCndcvR+h7lMww==",
+          "dev": true,
+          "requires": {
+            "@typescript-eslint/types": "4.15.1",
+            "eslint-visitor-keys": "^2.0.0"
+          }
+        }
+      }
+    },
+    "eslint-config-prettier": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz",
+      "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==",
+      "dev": true
+    },
     "eslint-config-react-app": {
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz",
@@ -5633,6 +5830,19 @@
         }
       }
     },
+    "eslint-import-resolver-typescript": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.4.0.tgz",
+      "integrity": "sha512-useJKURidCcldRLCNKWemr1fFQL1SzB3G4a0li6lFGvlc5xGe1hY343bvG07cbpCzPuM/lK19FIJB3XGFSkplA==",
+      "dev": true,
+      "requires": {
+        "debug": "^4.1.1",
+        "glob": "^7.1.6",
+        "is-glob": "^4.0.1",
+        "resolve": "^1.17.0",
+        "tsconfig-paths": "^3.9.0"
+      }
+    },
     "eslint-module-utils": {
       "version": "2.6.0",
       "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz",
@@ -5769,6 +5979,16 @@
         "@typescript-eslint/experimental-utils": "^4.0.1"
       }
     },
+    "eslint-plugin-json": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-json/-/eslint-plugin-json-2.1.2.tgz",
+      "integrity": "sha512-isM/fsUxS4wN1+nLsWoV5T4gLgBQnsql3nMTr8u+cEls1bL8rRQO5CP5GtxJxaOfbcKqnz401styw+H/P+e78Q==",
+      "dev": true,
+      "requires": {
+        "lodash": "^4.17.19",
+        "vscode-json-languageservice": "^3.7.0"
+      }
+    },
     "eslint-plugin-jsx-a11y": {
       "version": "6.4.1",
       "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz",
@@ -5794,6 +6014,15 @@
         }
       }
     },
+    "eslint-plugin-prettier": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz",
+      "integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==",
+      "dev": true,
+      "requires": {
+        "prettier-linter-helpers": "^1.0.0"
+      }
+    },
     "eslint-plugin-react": {
       "version": "7.22.0",
       "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz",
@@ -6309,6 +6538,12 @@
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
     },
+    "fast-diff": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
+      "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
+      "dev": true
+    },
     "fast-glob": {
       "version": "3.2.5",
       "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
@@ -9470,6 +9705,12 @@
         "minimist": "^1.2.5"
       }
     },
+    "jsonc-parser": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz",
+      "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==",
+      "dev": true
+    },
     "jsonfile": {
       "version": "6.1.0",
       "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
@@ -11899,6 +12140,21 @@
       "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
       "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
     },
+    "prettier": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz",
+      "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==",
+      "dev": true
+    },
+    "prettier-linter-helpers": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+      "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+      "dev": true,
+      "requires": {
+        "fast-diff": "^1.1.2"
+      }
+    },
     "pretty-bytes": {
       "version": "5.5.0",
       "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.5.0.tgz",
@@ -12372,6 +12628,84 @@
         "webpack-dev-server": "3.11.0",
         "webpack-manifest-plugin": "2.2.0",
         "workbox-webpack-plugin": "5.1.4"
+      },
+      "dependencies": {
+        "@typescript-eslint/eslint-plugin": {
+          "version": "4.15.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.1.tgz",
+          "integrity": "sha512-yW2epMYZSpNJXZy22Biu+fLdTG8Mn6b22kR3TqblVk50HGNV8Zya15WAXuQCr8tKw4Qf1BL4QtI6kv6PCkLoJw==",
+          "requires": {
+            "@typescript-eslint/experimental-utils": "4.15.1",
+            "@typescript-eslint/scope-manager": "4.15.1",
+            "debug": "^4.1.1",
+            "functional-red-black-tree": "^1.0.1",
+            "lodash": "^4.17.15",
+            "regexpp": "^3.0.0",
+            "semver": "^7.3.2",
+            "tsutils": "^3.17.1"
+          }
+        },
+        "@typescript-eslint/experimental-utils": {
+          "version": "4.15.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.1.tgz",
+          "integrity": "sha512-9LQRmOzBRI1iOdJorr4jEnQhadxK4c9R2aEAsm7WE/7dq8wkKD1suaV0S/JucTL8QlYUPU1y2yjqg+aGC0IQBQ==",
+          "requires": {
+            "@types/json-schema": "^7.0.3",
+            "@typescript-eslint/scope-manager": "4.15.1",
+            "@typescript-eslint/types": "4.15.1",
+            "@typescript-eslint/typescript-estree": "4.15.1",
+            "eslint-scope": "^5.0.0",
+            "eslint-utils": "^2.0.0"
+          }
+        },
+        "@typescript-eslint/parser": {
+          "version": "4.15.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.1.tgz",
+          "integrity": "sha512-V8eXYxNJ9QmXi5ETDguB7O9diAXlIyS+e3xzLoP/oVE4WCAjssxLIa0mqCLsCGXulYJUfT+GV70Jv1vHsdKwtA==",
+          "requires": {
+            "@typescript-eslint/scope-manager": "4.15.1",
+            "@typescript-eslint/types": "4.15.1",
+            "@typescript-eslint/typescript-estree": "4.15.1",
+            "debug": "^4.1.1"
+          }
+        },
+        "@typescript-eslint/scope-manager": {
+          "version": "4.15.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.1.tgz",
+          "integrity": "sha512-ibQrTFcAm7yG4C1iwpIYK7vDnFg+fKaZVfvyOm3sNsGAerKfwPVFtYft5EbjzByDJ4dj1WD8/34REJfw/9wdVA==",
+          "requires": {
+            "@typescript-eslint/types": "4.15.1",
+            "@typescript-eslint/visitor-keys": "4.15.1"
+          }
+        },
+        "@typescript-eslint/types": {
+          "version": "4.15.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.1.tgz",
+          "integrity": "sha512-iGsaUyWFyLz0mHfXhX4zO6P7O3sExQpBJ2dgXB0G5g/8PRVfBBsmQIc3r83ranEQTALLR3Vko/fnCIVqmH+mPw=="
+        },
+        "@typescript-eslint/typescript-estree": {
+          "version": "4.15.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.1.tgz",
+          "integrity": "sha512-z8MN3CicTEumrWAEB2e2CcoZa3KP9+SMYLIA2aM49XW3cWIaiVSOAGq30ffR5XHxRirqE90fgLw3e6WmNx5uNw==",
+          "requires": {
+            "@typescript-eslint/types": "4.15.1",
+            "@typescript-eslint/visitor-keys": "4.15.1",
+            "debug": "^4.1.1",
+            "globby": "^11.0.1",
+            "is-glob": "^4.0.1",
+            "semver": "^7.3.2",
+            "tsutils": "^3.17.1"
+          }
+        },
+        "@typescript-eslint/visitor-keys": {
+          "version": "4.15.1",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.1.tgz",
+          "integrity": "sha512-tYzaTP9plooRJY8eNlpAewTOqtWW/4ff/5wBjNVaJ0S0wC4Gpq/zDVRTJa5bq2v1pCNQ08xxMCndcvR+h7lMww==",
+          "requires": {
+            "@typescript-eslint/types": "4.15.1",
+            "eslint-visitor-keys": "^2.0.0"
+          }
+        }
       }
     },
     "read-pkg": {
@@ -14897,6 +15231,43 @@
       "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
       "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ=="
     },
+    "vscode-json-languageservice": {
+      "version": "3.11.0",
+      "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.11.0.tgz",
+      "integrity": "sha512-QxI+qV97uD7HHOCjh3MrM1TfbdwmTXrMckri5Tus1/FQiG3baDZb2C9Y0y8QThs7PwHYBIQXcAc59ZveCRZKPA==",
+      "dev": true,
+      "requires": {
+        "jsonc-parser": "^3.0.0",
+        "vscode-languageserver-textdocument": "^1.0.1",
+        "vscode-languageserver-types": "3.16.0-next.2",
+        "vscode-nls": "^5.0.0",
+        "vscode-uri": "^2.1.2"
+      }
+    },
+    "vscode-languageserver-textdocument": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz",
+      "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==",
+      "dev": true
+    },
+    "vscode-languageserver-types": {
+      "version": "3.16.0-next.2",
+      "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz",
+      "integrity": "sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q==",
+      "dev": true
+    },
+    "vscode-nls": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.0.0.tgz",
+      "integrity": "sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA==",
+      "dev": true
+    },
+    "vscode-uri": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz",
+      "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==",
+      "dev": true
+    },
     "w3c-hr-time": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
diff --git a/client/package.json b/client/package.json
index 3b69eed1..70f2bf2e 100644
--- a/client/package.json
+++ b/client/package.json
@@ -17,17 +17,27 @@
     "axios": "^0.21.1",
     "web-vitals": "^1.1.0"
   },
+  "devDependencies": {
+    "@typescript-eslint/eslint-plugin": "4.2.0",
+    "@typescript-eslint/parser": "4.2.0",
+    "eslint": "7.19.0",
+    "eslint-config-airbnb": "^18.2.1",
+    "eslint-config-airbnb-typescript": "^12.3.1",
+    "eslint-config-prettier": "^7.2.0",
+    "eslint-import-resolver-typescript": "^2.4.0",
+    "eslint-plugin-import": "^2.22.1",
+    "eslint-plugin-json": "^2.1.2",
+    "eslint-plugin-jsx-a11y": "^6.4.1",
+    "eslint-plugin-prettier": "^3.3.1",
+    "eslint-plugin-react": "^7.22.0",
+    "prettier": "^2.2.1"
+  },
   "scripts": {
     "start": "react-scripts start",
     "build": "react-scripts build",
     "test": "react-scripts test",
-    "eject": "react-scripts eject"
-  },
-  "eslintConfig": {
-    "extends": [
-      "react-app",
-      "react-app/jest"
-    ]
+    "eject": "react-scripts eject",
+    "lint": "eslint \"./src/**/*.{js,ts,tsx}\""
   },
   "browserslist": {
     "production": [
diff --git a/client/src/App.test.tsx b/client/src/App.test.tsx
index 2a68616d..3a7a8cc5 100644
--- a/client/src/App.test.tsx
+++ b/client/src/App.test.tsx
@@ -1,9 +1,9 @@
-import React from 'react';
-import { render, screen } from '@testing-library/react';
-import App from './App';
+import React from 'react'
+import { render, screen } from '@testing-library/react'
+import App from './App'
 
 test('renders learn react link', () => {
-  render(<App />);
-  const linkElement = screen.getByText(/learn react/i);
-  expect(linkElement).toBeInTheDocument();
-});
+  render(<App />)
+  const linkElement = screen.getByText(/learn react/i)
+  expect(linkElement).toBeInTheDocument()
+})
diff --git a/client/src/App.tsx b/client/src/App.tsx
index 6d9c9bdb..931b58fa 100644
--- a/client/src/App.tsx
+++ b/client/src/App.tsx
@@ -1,20 +1,19 @@
-import React from 'react';
-import logo from './logo.svg';
-import './App.css';
-import { useState, useEffect } from "react";
-import axios from "axios";
+import axios from 'axios'
+import React, { useEffect, useState } from 'react'
+import './App.css'
+import logo from './logo.svg'
 
 interface Message {
-  message: string;
+  message: string
 }
 
-function App() {
-  const [currentMessage, setCurrentMessage] = useState<Message>();
+const App: React.FC = () => {
+  const [currentMessage, setCurrentMessage] = useState<Message>()
   useEffect(() => {
-    axios.get<Message>("users/test").then(response=> {
-      setCurrentMessage(response.data);
-    });
-  }, []);
+    axios.get<Message>('users/test').then((response) => {
+      setCurrentMessage(response.data)
+    })
+  }, [])
 
   return (
     <div className="App">
@@ -34,7 +33,7 @@ function App() {
         <p>Current message is {currentMessage?.message}</p>
       </header>
     </div>
-  );
+  )
 }
 
-export default App;
+export default App
diff --git a/client/src/index.tsx b/client/src/index.tsx
index ef2edf8e..e7b11a23 100644
--- a/client/src/index.tsx
+++ b/client/src/index.tsx
@@ -1,17 +1,17 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import './index.css';
-import App from './App';
-import reportWebVitals from './reportWebVitals';
+import React from 'react'
+import ReactDOM from 'react-dom'
+import App from './App'
+import './index.css'
+import reportWebVitals from './reportWebVitals'
 
 ReactDOM.render(
   <React.StrictMode>
     <App />
   </React.StrictMode>,
   document.getElementById('root')
-);
+)
 
 // If you want to start measuring performance in your app, pass a function
 // to log results (for example: reportWebVitals(console.log))
 // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
-reportWebVitals();
+reportWebVitals()
diff --git a/client/src/reportWebVitals.ts b/client/src/reportWebVitals.ts
index 49a2a16e..57a24a21 100644
--- a/client/src/reportWebVitals.ts
+++ b/client/src/reportWebVitals.ts
@@ -1,15 +1,15 @@
-import { ReportHandler } from 'web-vitals';
+import { ReportHandler } from 'web-vitals'
 
 const reportWebVitals = (onPerfEntry?: ReportHandler) => {
   if (onPerfEntry && onPerfEntry instanceof Function) {
     import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
-      getCLS(onPerfEntry);
-      getFID(onPerfEntry);
-      getFCP(onPerfEntry);
-      getLCP(onPerfEntry);
-      getTTFB(onPerfEntry);
-    });
+      getCLS(onPerfEntry)
+      getFID(onPerfEntry)
+      getFCP(onPerfEntry)
+      getLCP(onPerfEntry)
+      getTTFB(onPerfEntry)
+    })
   }
-};
+}
 
-export default reportWebVitals;
+export default reportWebVitals
diff --git a/client/src/setupTests.ts b/client/src/setupTests.ts
index 8f2609b7..52aaef1d 100644
--- a/client/src/setupTests.ts
+++ b/client/src/setupTests.ts
@@ -2,4 +2,4 @@
 // allows you to do things like:
 // expect(element).toHaveTextContent(/react/i)
 // learn more: https://github.com/testing-library/jest-dom
-import '@testing-library/jest-dom';
+import '@testing-library/jest-dom'
-- 
GitLab