From 7604aa3b28984ab0dbc9823c39c3d3e93af47201 Mon Sep 17 00:00:00 2001 From: lcflight Date: Thu, 11 Jan 2024 09:31:37 -0600 Subject: [PATCH 1/7] type corrections to the naviegator --- src/components/types.tsx | 4 ++-- src/screens/HomeScreen.tsx | 2 +- src/screens/LoginScreen.tsx | 2 +- src/screens/ProfileScreen.tsx | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/types.tsx b/src/components/types.tsx index 8736354..37a010b 100644 --- a/src/components/types.tsx +++ b/src/components/types.tsx @@ -36,8 +36,8 @@ type ProfileScreenNavigationProp = StackNavigationProp< type ProfileScreenRouteProp = RouteProp; export type Props = { - navigation: ProfileScreenNavigationProp; - route: ProfileScreenRouteProp; + navigation?: ProfileScreenNavigationProp; + route?: ProfileScreenRouteProp; }; export type TaskPopupProps = { diff --git a/src/screens/HomeScreen.tsx b/src/screens/HomeScreen.tsx index 67d4e49..29077f0 100644 --- a/src/screens/HomeScreen.tsx +++ b/src/screens/HomeScreen.tsx @@ -59,7 +59,7 @@ export default function HomeScreen({navigation}: Props): JSX.Element { }; function handleUserProfilePress() { - navigation.navigate('ProfileScreen'); + navigation?.navigate('ProfileScreen'); } function handleInfoButtonPress() { diff --git a/src/screens/LoginScreen.tsx b/src/screens/LoginScreen.tsx index 54898ec..40e83af 100644 --- a/src/screens/LoginScreen.tsx +++ b/src/screens/LoginScreen.tsx @@ -47,7 +47,7 @@ export default function LoginScreen({navigation}: Props): JSX.Element { const tasks = await getTasks(); await AsyncStorage.setItem('tasks', JSON.stringify(tasks)); await AsyncStorage.setItem('me', JSON.stringify(me)); - navigation.navigate('HomeScreen'); + navigation?.navigate('HomeScreen'); } else { setOutputStatus('Login Failed, try again!'); } diff --git a/src/screens/ProfileScreen.tsx b/src/screens/ProfileScreen.tsx index 52719bd..52c40b5 100644 --- a/src/screens/ProfileScreen.tsx +++ b/src/screens/ProfileScreen.tsx @@ -43,7 +43,7 @@ export default function ProfileScreen({navigation}: Props) { }, []); function goToLoginScreen() { - navigation.navigate('LoginScreen'); + navigation?.navigate('LoginScreen'); } return ( From db0b05ee841752d7fd6209ac35c7a48433250cec Mon Sep 17 00:00:00 2001 From: lcflight Date: Thu, 11 Jan 2024 11:44:19 -0600 Subject: [PATCH 2/7] Use react-query --- .eslintrc.js | 11 +- package-lock.json | 339 ++++++++++++--------------- package.json | 5 +- src/App.tsx | 27 ++- src/components/taskListItem.tsx | 15 +- src/components/taskPopup.tsx | 154 +++++------- src/components/types.tsx | 17 +- src/screens/HomeScreen.tsx | 48 ++-- src/screens/LoginScreen.tsx | 33 ++- src/screens/ProfileScreen.tsx | 91 ++++--- src/services/taskratchet/getTasks.ts | 5 +- 11 files changed, 322 insertions(+), 423 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 3ae4aac..d665dc9 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,7 +6,13 @@ module.exports = { tsconfigRootDir: __dirname, ecmaVersion: 2018, }, - plugins: ['simple-import-sort', 'react-native', 'unused-imports', 'jest'], + plugins: [ + 'simple-import-sort', + 'react-native', + 'unused-imports', + 'jest', + 'no-autofix', + ], env: { jest: true, }, @@ -15,7 +21,8 @@ module.exports = { 'simple-import-sort/exports': 'error', 'no-unused-vars': 'error', 'react-native/no-unused-styles': 'error', - 'unused-imports/no-unused-imports': 'error', + 'unused-imports/no-unused-imports': 'off', + 'no-autofix/unused-imports/no-unused-imports': 'error', }, overrides: [ { diff --git a/package-lock.json b/package-lock.json index a648814..991b4c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@react-navigation/native": "^6.1.9", "@react-navigation/native-stack": "^6.9.17", "@react-navigation/stack": "^6.3.20", + "@tanstack/react-query": "^5.17.9", "@testing-library/react-native": "^12.4.2", "babel-preset-react-native": "2.1.0", "eslint-plugin-react-native": "^4.1.0", @@ -24,8 +25,7 @@ "react-native-gesture-handler": "^2.14.0", "react-native-safe-area-context": "^4.7.4", "react-native-screens": "^3.27.0", - "react-native-secure-key-store": "^2.0.10", - "react-query": "^3.39.3" + "react-native-secure-key-store": "^2.0.10" }, "devDependencies": { "@babel/core": "^7.20.0", @@ -44,6 +44,7 @@ "babel-jest": "^29.7.0", "eslint": "^8.19.0", "eslint-plugin-jest": "^27.6.0", + "eslint-plugin-no-autofix": "^1.2.3", "eslint-plugin-react": "^7.33.2", "eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-unused-imports": "^3.0.0", @@ -7584,6 +7585,30 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@tanstack/query-core": { + "version": "5.17.9", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.17.9.tgz", + "integrity": "sha512-8xcvpWIPaRMDNLMvG9ugcUJMgFK316ZsqkPPbsI+TMZsb10N9jk0B6XgPk4/kgWC2ziHyWR7n7wUhxmD0pChQw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.17.9", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.17.9.tgz", + "integrity": "sha512-M5E9gwUq1Stby/pdlYjBlL24euIVuGbWKIFCbtnQxSdXI4PgzjTSdXdV3QE6fc+itF+TUvX/JPTKIwq8yuBXcg==", + "dependencies": { + "@tanstack/query-core": "5.17.9" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, "node_modules/@testing-library/react-native": { "version": "12.4.2", "resolved": "https://registry.npmjs.org/@testing-library/react-native/-/react-native-12.4.2.tgz", @@ -9846,6 +9871,7 @@ "version": "1.6.52", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "peer": true, "engines": { "node": ">=0.6" } @@ -9959,35 +9985,6 @@ "node": ">=8" } }, - "node_modules/broadcast-channel": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", - "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", - "dependencies": { - "@babel/runtime": "^7.7.2", - "detect-node": "^2.1.0", - "js-sha3": "0.8.0", - "microseconds": "0.2.0", - "nano-time": "1.0.0", - "oblivious-set": "1.0.0", - "rimraf": "3.0.2", - "unload": "2.2.0" - } - }, - "node_modules/broadcast-channel/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/browserslist": { "version": "4.22.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", @@ -11159,11 +11156,6 @@ "node": ">=8" } }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" - }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -11629,6 +11621,68 @@ } } }, + "node_modules/eslint-plugin-no-autofix": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-autofix/-/eslint-plugin-no-autofix-1.2.3.tgz", + "integrity": "sha512-JFSYe82Da2A8Krh+Gfq7+3X2pchTScKgmrlMKIA4HmV6t5xGBF/kgjiFL3YTWRQXQ0NB9eOqpcxh6SuLtQUFjQ==", + "dev": true, + "dependencies": { + "eslint-rule-composer": "^0.3.0", + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "eslint": ">= 5.12.1" + } + }, + "node_modules/eslint-plugin-no-autofix/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-no-autofix/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-no-autofix/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint-plugin-prettier": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", @@ -16263,11 +16317,6 @@ "integrity": "sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==", "peer": true }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -17051,15 +17100,6 @@ "tmpl": "1.0.5" } }, - "node_modules/match-sorter": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.1.tgz", - "integrity": "sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "remove-accents": "0.4.2" - } - }, "node_modules/md5": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", @@ -17949,11 +17989,6 @@ "node": ">=8.6" } }, - "node_modules/microseconds": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", - "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" - }, "node_modules/mime": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", @@ -18194,14 +18229,6 @@ "thenify-all": "^1.0.0" } }, - "node_modules/nano-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", - "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", - "dependencies": { - "big-integer": "^1.6.16" - } - }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -18522,11 +18549,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/oblivious-set": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", - "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -19665,31 +19687,6 @@ "react-deep-force-update": "^1.0.0" } }, - "node_modules/react-query": { - "version": "3.39.3", - "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", - "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==", - "dependencies": { - "@babel/runtime": "^7.5.5", - "broadcast-channel": "^3.4.1", - "match-sorter": "^6.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } - } - }, "node_modules/react-refresh": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz", @@ -19896,11 +19893,6 @@ "jsesc": "bin/jsesc" } }, - "node_modules/remove-accents": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", - "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" - }, "node_modules/remove-trailing-slash": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/remove-trailing-slash/-/remove-trailing-slash-0.1.1.tgz", @@ -21575,15 +21567,6 @@ "node": ">= 4.0.0" } }, - "node_modules/unload": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", - "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", - "dependencies": { - "@babel/runtime": "^7.6.2", - "detect-node": "^2.0.4" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -28126,6 +28109,19 @@ "@sinonjs/commons": "^3.0.0" } }, + "@tanstack/query-core": { + "version": "5.17.9", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.17.9.tgz", + "integrity": "sha512-8xcvpWIPaRMDNLMvG9ugcUJMgFK316ZsqkPPbsI+TMZsb10N9jk0B6XgPk4/kgWC2ziHyWR7n7wUhxmD0pChQw==" + }, + "@tanstack/react-query": { + "version": "5.17.9", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.17.9.tgz", + "integrity": "sha512-M5E9gwUq1Stby/pdlYjBlL24euIVuGbWKIFCbtnQxSdXI4PgzjTSdXdV3QE6fc+itF+TUvX/JPTKIwq8yuBXcg==", + "requires": { + "@tanstack/query-core": "5.17.9" + } + }, "@testing-library/react-native": { "version": "12.4.2", "resolved": "https://registry.npmjs.org/@testing-library/react-native/-/react-native-12.4.2.tgz", @@ -29916,7 +29912,8 @@ "big-integer": { "version": "1.6.52", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==" + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "peer": true }, "bl": { "version": "4.1.0", @@ -30018,31 +30015,6 @@ "fill-range": "^7.0.1" } }, - "broadcast-channel": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", - "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", - "requires": { - "@babel/runtime": "^7.7.2", - "detect-node": "^2.1.0", - "js-sha3": "0.8.0", - "microseconds": "0.2.0", - "nano-time": "1.0.0", - "oblivious-set": "1.0.0", - "rimraf": "3.0.2", - "unload": "2.2.0" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, "browserslist": { "version": "4.22.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", @@ -30908,11 +30880,6 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "devOptional": true }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" - }, "diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -31374,6 +31341,46 @@ "@typescript-eslint/utils": "^5.10.0" } }, + "eslint-plugin-no-autofix": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-autofix/-/eslint-plugin-no-autofix-1.2.3.tgz", + "integrity": "sha512-JFSYe82Da2A8Krh+Gfq7+3X2pchTScKgmrlMKIA4HmV6t5xGBF/kgjiFL3YTWRQXQ0NB9eOqpcxh6SuLtQUFjQ==", + "dev": true, + "requires": { + "eslint-rule-composer": "^0.3.0", + "find-up": "^5.0.0" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + } + } + }, "eslint-plugin-prettier": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", @@ -34648,11 +34655,6 @@ "integrity": "sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==", "peer": true }, - "js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -35204,15 +35206,6 @@ "tmpl": "1.0.5" } }, - "match-sorter": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.1.tgz", - "integrity": "sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==", - "requires": { - "@babel/runtime": "^7.12.5", - "remove-accents": "0.4.2" - } - }, "md5": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", @@ -35886,11 +35879,6 @@ "picomatch": "^2.3.1" } }, - "microseconds": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", - "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" - }, "mime": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", @@ -36083,14 +36071,6 @@ "thenify-all": "^1.0.0" } }, - "nano-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", - "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", - "requires": { - "big-integer": "^1.6.16" - } - }, "nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -36313,11 +36293,6 @@ "es-abstract": "^1.22.1" } }, - "oblivious-set": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", - "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" - }, "on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -37148,16 +37123,6 @@ "react-deep-force-update": "^1.0.0" } }, - "react-query": { - "version": "3.39.3", - "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", - "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==", - "requires": { - "@babel/runtime": "^7.5.5", - "broadcast-channel": "^3.4.1", - "match-sorter": "^6.0.2" - } - }, "react-refresh": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz", @@ -37331,11 +37296,6 @@ } } }, - "remove-accents": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", - "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" - }, "remove-trailing-slash": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/remove-trailing-slash/-/remove-trailing-slash-0.1.1.tgz", @@ -38595,15 +38555,6 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, - "unload": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", - "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", - "requires": { - "@babel/runtime": "^7.6.2", - "detect-node": "^2.0.4" - } - }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index c65362a..d3d0e43 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@react-navigation/native": "^6.1.9", "@react-navigation/native-stack": "^6.9.17", "@react-navigation/stack": "^6.3.20", + "@tanstack/react-query": "^5.17.9", "@testing-library/react-native": "^12.4.2", "babel-preset-react-native": "2.1.0", "eslint-plugin-react-native": "^4.1.0", @@ -31,8 +32,7 @@ "react-native-gesture-handler": "^2.14.0", "react-native-safe-area-context": "^4.7.4", "react-native-screens": "^3.27.0", - "react-native-secure-key-store": "^2.0.10", - "react-query": "^3.39.3" + "react-native-secure-key-store": "^2.0.10" }, "devDependencies": { "@babel/core": "^7.20.0", @@ -51,6 +51,7 @@ "babel-jest": "^29.7.0", "eslint": "^8.19.0", "eslint-plugin-jest": "^27.6.0", + "eslint-plugin-no-autofix": "^1.2.3", "eslint-plugin-react": "^7.33.2", "eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-unused-imports": "^3.0.0", diff --git a/src/App.tsx b/src/App.tsx index 63ff372..4f164c5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,7 @@ // react imports: import {NavigationContainer} from '@react-navigation/native'; import {createStackNavigator} from '@react-navigation/stack'; +import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; import * as React from 'react'; import {useState} from 'react'; import {enableScreens} from 'react-native-screens'; @@ -13,6 +14,8 @@ import ProfileScreen from './screens/ProfileScreen'; enableScreens(); +const queryClient = new QueryClient(); + const Stack = createStackNavigator(); export const UserContext = React.createContext({ @@ -29,17 +32,19 @@ function App(): JSX.Element { const isAppReady = true; return ( - - - - - - - - - - - + + + + + + + + + + + + + ); } diff --git a/src/components/taskListItem.tsx b/src/components/taskListItem.tsx index 1f490f3..50f18fe 100644 --- a/src/components/taskListItem.tsx +++ b/src/components/taskListItem.tsx @@ -10,7 +10,7 @@ import getStoredTasks from '../utils/getStoredTasks'; import {TaskType} from './types'; interface taskProps { - item: number; + item: TaskType; } export default function Task({item}: taskProps): JSX.Element { @@ -82,10 +82,11 @@ export default function Task({item}: taskProps): JSX.Element { return {text, style}; } - const deadlineDetails = tasks[item] - ? getDeadlineDetails(tasks[item].complete, checkDate(tasks[item].due)) + const deadlineDetails = item + ? getDeadlineDetails(item.complete, checkDate(item.due)) : {text: '', style: {}}; + // TODO: Call this something other than "footer" function getFooterStyle(isComplete: boolean, daysToDue: number) { switch (true) { case isComplete: @@ -101,8 +102,8 @@ export default function Task({item}: taskProps): JSX.Element { } } - const footerStyle = tasks[item] - ? getFooterStyle(tasks[item].complete, checkDate(tasks[item].due)) + const footerStyle = item + ? getFooterStyle(item.complete, checkDate(item.due)) : {style: {}}; return ( @@ -110,7 +111,7 @@ export default function Task({item}: taskProps): JSX.Element { - {tasks && tasks.length > 0 ? tasks[item].task : 'Loading...'} + {tasks && tasks.length > 0 ? item.task : 'Loading...'} {deadlineDetails.text} @@ -118,7 +119,7 @@ export default function Task({item}: taskProps): JSX.Element { {tasks && tasks.length > 0 - ? convertCents(tasks[item].cents) + ? convertCents(item.cents) : 'Loading...'} diff --git a/src/components/taskPopup.tsx b/src/components/taskPopup.tsx index 1e85ace..7749769 100644 --- a/src/components/taskPopup.tsx +++ b/src/components/taskPopup.tsx @@ -1,22 +1,19 @@ -import React, {useEffect, useState} from 'react'; +import {useMutation} from '@tanstack/react-query'; +import React from 'react'; import {Modal, Pressable, Text, View} from 'react-native'; import themeProvider from '../providers/themeProvider'; -import {updateTask} from '../services/taskratchet/updateTask'; +import {TaskInput, updateTask} from '../services/taskratchet/updateTask'; import {styles} from '../styles/taskPopupStyle'; import useIsDarkMode from '../utils/checkDarkMode'; import checkDate from '../utils/checkDate'; -import convertCents from '../utils/convertCents'; -import getStoredTasks from '../utils/getStoredTasks'; -import {TaskPopupProps, TaskType} from './types'; +import {TaskPopupProps} from './types'; export default function TaskPopup({ item, modalVisible, setModalVisible, }: TaskPopupProps): JSX.Element { - const [tasks, setTasks] = useState([]); - const isDarkMode = useIsDarkMode(); const backgroundStyle = { @@ -29,20 +26,14 @@ export default function TaskPopup({ color: isDarkMode ? 'white' : 'black', }; - useEffect(() => { - async function fetchTasks() { - try { - const fetchedTasks = await getStoredTasks(); - setTasks(fetchedTasks); - } catch (error) { - console.error(error); - } - } - - fetchTasks().catch(error => { - console.error('Error fetching tasks:', error); - }); - }, []); + const mutation = useMutation({ + mutationFn: (vars: {taskId: string; data: TaskInput}) => { + return updateTask(vars.taskId, vars.data); + }, + onError: error => { + console.error('Error updating task:', error); + }, + }); function getDeadlineDetails(days: number) { if (days === null) { @@ -60,22 +51,7 @@ export default function TaskPopup({ } } - function CompletionText() { - if (item !== undefined && tasks[item] !== undefined) { - if (tasks[item].complete !== undefined && tasks[item].complete) { - return 'Mark Incomplete'; - } else { - return 'Mark Complete'; - } - } else { - return 'Task not found'; - } - } - - const deadlineDetails = - tasks && tasks[item] && tasks[item].due - ? getDeadlineDetails(checkDate(tasks[item].due)) - : {text: '', style: {}}; + const deadlineDetails = item && getDeadlineDetails(checkDate(item.due)); return ( @@ -86,76 +62,62 @@ export default function TaskPopup({ onRequestClose={() => { setModalVisible(!modalVisible); }}> - - - - - - {tasks && tasks !== null && tasks.length > 0 - ? tasks[item].task - : 'Loading...'} - - - {deadlineDetails.text} + {item ? ( + + + + + + {item.task} + + + {deadlineDetails?.text} + + + + {item.cents} - - {tasks && tasks[item] - ? convertCents(tasks[item].cents) - : 'Loading...'} - - - {tasks && tasks[item] && checkDate(tasks[item].due) >= 0 ? ( + {checkDate(item.due) >= 0 ? ( + [ + { + backgroundColor: pressed + ? 'rgba(0, 103, 69, 0.5)' + : '#006745', + }, + styles.button, + styles.buttonComplete, + ]} + onPress={() => { + mutation.mutate({ + taskId: item.id, + data: {complete: !item.complete}, + }); + }}> + + {item.complete ? 'Mark Incomplete' : 'Mark Complete'} + + + ) : null} [ { backgroundColor: pressed - ? 'rgba(0, 103, 69, 0.5)' - : '#006745', + ? 'rgba(33, 150, 243, 0.5)' + : '#2196F3', + marginTop: checkDate(item.due) >= 0 ? 5 : 35, }, styles.button, - styles.buttonComplete, ]} - onPress={() => { - if (tasks[item].complete) { - updateTask(tasks[item].id, {complete: false}).catch( - error => { - console.error( - 'Error updating complete task to incomplete:', - error, - ); - }, - ); - } else { - updateTask(tasks[item].id, {complete: true}).catch( - error => { - console.error( - 'Error updating incomplete task to complete:', - error, - ); - }, - ); - } - }}> - {CompletionText()} + onPress={() => setModalVisible(!modalVisible)}> + Hide - ) : null} - [ - { - backgroundColor: pressed - ? 'rgba(33, 150, 243, 0.5)' - : '#2196F3', - marginTop: - tasks[item] && checkDate(tasks[item].due) >= 0 ? 5 : 35, - }, - styles.button, - ]} - onPress={() => setModalVisible(!modalVisible)}> - Hide - + - + ) : ( + Failed to find selected item + )} ); diff --git a/src/components/types.tsx b/src/components/types.tsx index 37a010b..3bb41c4 100644 --- a/src/components/types.tsx +++ b/src/components/types.tsx @@ -2,15 +2,6 @@ import {RouteProp} from '@react-navigation/native'; import {StackNavigationProp, StackScreenProps} from '@react-navigation/stack'; import {Dispatch, SetStateAction} from 'react'; -export type taskType = { - id: number; - title: string; - description: string; - completed: boolean; - deadline: string; - stakes: string; -}; - export type tasksType = { [key: string]: taskType; }; @@ -42,7 +33,7 @@ export type Props = { export type TaskPopupProps = { testID?: string; - item: number; + item?: taskType; modalVisible: boolean; setModalVisible: Dispatch>; }; @@ -60,11 +51,17 @@ export type LoginScreenProps = StackScreenProps< export type TaskType = { id: string; + title: string; + description: string; task: string; due: string; + deadline: string; due_timestamp: number; cents: number; + stakes: string; complete: boolean; status: string; timezone: string; }; + +export type taskType = TaskType; diff --git a/src/screens/HomeScreen.tsx b/src/screens/HomeScreen.tsx index 29077f0..426dedc 100644 --- a/src/screens/HomeScreen.tsx +++ b/src/screens/HomeScreen.tsx @@ -1,4 +1,5 @@ -import React, {useEffect, useState} from 'react'; +import {useQuery} from '@tanstack/react-query'; +import React, {useState} from 'react'; import { Image, ImageSourcePropType, @@ -16,35 +17,22 @@ import logo from '../../assets/images/logo_taskratchet_square_64@2.png'; import InfoPopup from '../components/infoPopup'; import Task from '../components/taskListItem'; import TaskPopup from '../components/taskPopup'; -import {Props, TaskType} from '../components/types'; +import {Props, taskType} from '../components/types'; import themeProvider from '../providers/themeProvider'; +import {getTasks} from '../services/taskratchet/getTasks'; import {styles} from '../styles/homeScreenStyle'; import useIsDarkMode from '../utils/checkDarkMode'; import checkDate from '../utils/checkDate'; -import getStoredTasks from '../utils/getStoredTasks'; export default function HomeScreen({navigation}: Props): JSX.Element { const [taskModalVisible, setTaskModalVisible] = useState(false); const [infoModalVisible, setInfoModalVisible] = useState(false); - const [clickedItem, setClickedItem] = useState('0'); - const [tasks, setCurrentTasks] = useState([]); + const [clickedItem, setClickedItem] = useState(); - useEffect(() => { - async function getTasksAsync() { - try { - const result: TaskType[] = await getStoredTasks(); - setCurrentTasks(result); - } catch (error) { - console.error( - `Error retrieving tasks from storage. Error Log: ${String(error)}`, - ); - } - } - - getTasksAsync().catch(error => { - console.error('error fetching tasks', error); - }); - }, []); + const {data: tasks} = useQuery({ + queryKey: ['tasks'], + queryFn: getTasks, + }); const isDarkMode = useIsDarkMode(); @@ -66,9 +54,9 @@ export default function HomeScreen({navigation}: Props): JSX.Element { setInfoModalVisible(!infoModalVisible); } - function taskItemPress(key: string) { + function taskItemPress(item: taskType) { setTaskModalVisible(!taskModalVisible); - setClickedItem(key); + setClickedItem(item); } return ( @@ -85,7 +73,7 @@ export default function HomeScreen({navigation}: Props): JSX.Element { /> @@ -122,10 +110,10 @@ export default function HomeScreen({navigation}: Props): JSX.Element { {tasks && - Object.keys(tasks) + tasks .sort((a, b) => { - const taskA = tasks[Number(a)]; - const taskB = tasks[Number(b)]; + const taskA = a; + const taskB = b; if ('due' in taskA && 'due' in taskB) { const diffDaysA = checkDate(String(taskA.due)); @@ -142,10 +130,10 @@ export default function HomeScreen({navigation}: Props): JSX.Element { return 0; } }) - .map(key => { + .map(task => { return ( - taskItemPress(key)}> - + taskItemPress(task)}> + ); })} diff --git a/src/screens/LoginScreen.tsx b/src/screens/LoginScreen.tsx index 40e83af..4339e2f 100644 --- a/src/screens/LoginScreen.tsx +++ b/src/screens/LoginScreen.tsx @@ -1,4 +1,5 @@ import AsyncStorage from '@react-native-async-storage/async-storage'; +import {useMutation} from '@tanstack/react-query'; import React from 'react'; import { Image, @@ -39,23 +40,21 @@ export default function LoginScreen({navigation}: Props): JSX.Element { const [passInput, setPassInput] = React.useState(''); const [outputStatus, setOutputStatus] = React.useState(''); - async function handleLogin() { - try { - const result = await login(userInput, passInput); - if (result === true) { - const me = await getMe(); - const tasks = await getTasks(); - await AsyncStorage.setItem('tasks', JSON.stringify(tasks)); - await AsyncStorage.setItem('me', JSON.stringify(me)); - navigation?.navigate('HomeScreen'); - } else { + const mutation = useMutation({ + mutationFn: () => login(userInput, passInput), + onSettled: async (data, error) => { + if (!data || error) { + console.error('login error ' + String(error)); setOutputStatus('Login Failed, try again!'); + return; } - } catch (error) { - console.error('login error ' + String(error)); - setOutputStatus('Login Failed, try again!'); - } - } + const me = await getMe(); + const tasks = await getTasks(); + await AsyncStorage.setItem('tasks', JSON.stringify(tasks)); + await AsyncStorage.setItem('me', JSON.stringify(me)); + navigation?.navigate('HomeScreen'); + }, + }); return ( @@ -104,9 +103,7 @@ export default function LoginScreen({navigation}: Props): JSX.Element { testID="loginButton" style={styles.login} onPress={() => { - handleLogin().catch(error => { - console.error('login error ' + String(error)); - }); + mutation.mutate(); }}> Login diff --git a/src/screens/ProfileScreen.tsx b/src/screens/ProfileScreen.tsx index 52c40b5..a2a31fb 100644 --- a/src/screens/ProfileScreen.tsx +++ b/src/screens/ProfileScreen.tsx @@ -1,13 +1,13 @@ -import React, {useEffect, useState} from 'react'; +import {useQuery} from '@tanstack/react-query'; +import React from 'react'; import {Button, Image, ImageSourcePropType, Text, View} from 'react-native'; import logo from '../../assets/images/logo_taskratchet_square_64@2.png'; import {Props} from '../components/types'; import themeProvider from '../providers/themeProvider'; -import {User} from '../services/taskratchet/getMe'; +import {getMe} from '../services/taskratchet/getMe'; import {styles} from '../styles/profileScreenStyle'; import useIsDarkMode from '../utils/checkDarkMode'; -import getStoredUser from '../utils/getStoredUser'; export default function ProfileScreen({navigation}: Props) { const isDarkMode = useIsDarkMode(); @@ -21,27 +21,10 @@ export default function ProfileScreen({navigation}: Props) { color: isDarkMode ? 'white' : 'black', }; - const [user, setCurrentUser] = useState(null); + const {data: user} = useQuery({queryKey: ['user'], queryFn: getMe}); const dataBorderColor = {borderColor: isDarkMode ? 'white' : 'black'}; - useEffect(() => { - async function getUser() { - try { - const result: User | null = await getStoredUser(); - if (result === null) { - throw new Error('Unable to get user info'); - } - setCurrentUser(result); - } catch (error) { - console.error('getUser error ' + String(error)); - } - } - - // eslint-disable-next-line no-void - void getUser(); - }, []); - function goToLoginScreen() { navigation?.navigate('LoginScreen'); } @@ -57,36 +40,42 @@ export default function ProfileScreen({navigation}: Props) { Profile - - - Name: - - {user !== null ? user.name : '...'} - - - - - - Email: - - {user !== null ? user.email : '...'} - - - - - - Timezone: - - {user !== null ? user.timezone : '...'} - - - + {user ? ( + <> + + + Name: + + {user.name} + + + + + + Email: + + {user.email} + + + + + + Timezone: + + {user.timezone} + + + + + ) : ( + Loading... + )}