From ce6f13a7e7c9d447cb0454185d63b1d3fcceb39f Mon Sep 17 00:00:00 2001 From: Justin Lee <91563628+jjstnlee@users.noreply.github.com> Date: Mon, 4 Mar 2024 18:37:32 -0800 Subject: [PATCH 01/34] [auth] Update onboarding page to have demographic collection warning (#56) * Added demographic warning * Random * Updated onboarding page to have demographic collection warning * Updated onboarding page to have demographic collection warning * Fixed requested changes * Fixed requested styling changes * Changed margin spacing to match Figma --------- Co-authored-by: Justin Lee --- .gitignore | 3 + .vscode/extensions.json | 8 - .vscode/settings.json | 7 - package-lock.json | 251 +++++++++++++++++++++++------ src/app/auth/login/index.tsx | 4 +- src/app/auth/onboarding/index.tsx | 26 ++- src/app/auth/onboarding/styles.tsx | 19 +++ src/styles/globalStyles.ts | 1 + 8 files changed, 244 insertions(+), 75 deletions(-) delete mode 100644 .vscode/extensions.json delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index dbe5e160..3d623bed 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,6 @@ yarn-error.* # typescript *.tsbuildinfo + +# vscode +.vscode/* diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index c162df42..00000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "recommendations": [ - "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode", - "eamodio.gitlens" - ], - "unwantedRecommendations": [] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index a93e2d6f..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.codeActionsOnSave": { - "source.formatDocument": true, - "source.fixAll.eslint": true - } -} diff --git a/package-lock.json b/package-lock.json index 32a32ae2..6a31d071 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2382,9 +2382,9 @@ } }, "node_modules/@expo/cli": { - "version": "0.10.12", - "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.10.12.tgz", - "integrity": "sha512-sc4IkRBbm6HO1Z/0JeJMY/sJiyCAfHyt2EOHhAY8jYfbXr/aqCIGsPrwEGQAfGpsE2OPvyzRa+byZG03HRPTkQ==", + "version": "0.10.17", + "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.10.17.tgz", + "integrity": "sha512-HkHDvHPzq4M244hIerwnsw2IdjOo7RSsMYWGhc7ZY7DQWIMUC88b7f5+0RtD4JQfXQrgKS5Tvqm/5E6kAH0rIA==", "dependencies": { "@babel/runtime": "^7.20.0", "@expo/code-signing-certificates": "0.0.5", @@ -2518,9 +2518,9 @@ } }, "node_modules/@expo/cli/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -2755,6 +2755,18 @@ "temp-dir": "^2.0.0" } }, + "node_modules/@expo/dev-server/node_modules/@expo/osascript": { + "version": "2.0.33", + "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.0.33.tgz", + "integrity": "sha512-FQinlwHrTlJbntp8a7NAlCKedVXe06Va/0DSLXRO8lZVtgbEMrYYSUZWQNcOlNtc58c2elNph6z9dMOYwSo3JQ==", + "dependencies": { + "@expo/spawn-async": "^1.5.0", + "exec-async": "^2.2.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@expo/dev-server/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2834,9 +2846,9 @@ } }, "node_modules/@expo/dev-server/node_modules/jsonfile/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "engines": { "node": ">= 10.0.0" } @@ -2945,14 +2957,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/@expo/env/node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", - "engines": { - "node": ">=12" - } - }, "node_modules/@expo/env/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3268,9 +3272,9 @@ } }, "node_modules/@expo/osascript": { - "version": "2.0.33", - "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.0.33.tgz", - "integrity": "sha512-FQinlwHrTlJbntp8a7NAlCKedVXe06Va/0DSLXRO8lZVtgbEMrYYSUZWQNcOlNtc58c2elNph6z9dMOYwSo3JQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.1.0.tgz", + "integrity": "sha512-bOhuFnlRaS7CU33+rFFIWdcET/Vkyn1vsN8BYFwCDEF5P1fVVvYN7bFOsQLTMD3nvi35C1AGmtqUr/Wfv8Xaow==", "dependencies": { "@expo/spawn-async": "^1.5.0", "exec-async": "^2.2.0" @@ -3280,9 +3284,9 @@ } }, "node_modules/@expo/package-manager": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-1.1.1.tgz", - "integrity": "sha512-NxtfIA25iEiNwMT+s8PEmdKzjyfWd2qkCLJkf6jKZGaH9c06YXyOAi2jvCyM8XuSzJz4pcEH8kz1HkJAInjB7Q==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-1.1.2.tgz", + "integrity": "sha512-JI9XzrxB0QVXysyuJ996FPCJGDCYRkbUvgG4QmMTTMFA1T+mv8YzazC3T9C1pHQUAAveVCre1+Pqv0nZXN24Xg==", "dependencies": { "@expo/json-file": "^8.2.37", "@expo/spawn-async": "^1.5.0", @@ -3506,9 +3510,9 @@ "integrity": "sha512-TI+l71+5aSKnShYclFa14Kum+hQMZ86b95SH6tQUG3qZEmLTarvWpKwqtTwQKqvlJSJrpFiSFu3eCuZokY6zWA==" }, "node_modules/@expo/xcpretty": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@expo/xcpretty/-/xcpretty-4.2.2.tgz", - "integrity": "sha512-Lke/geldJqUV0Dfxg5/QIOugOzdqZ/rQ9yHKSgGbjZtG1uiSqWyFwWvXmrdd3/sIdX33eykGvIcf+OrvvcXVUw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@expo/xcpretty/-/xcpretty-4.3.1.tgz", + "integrity": "sha512-sqXgo1SCv+j4VtYEwl/bukuOIBrVgx6euIoCat3Iyx5oeoXwEA2USCoeL0IPubflMxncA2INkqJ/Wr3NGrSgzw==", "dependencies": { "@babel/code-frame": "7.10.4", "chalk": "^4.1.0", @@ -4581,9 +4585,9 @@ } }, "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -9046,9 +9050,12 @@ "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==" }, "node_modules/component-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-type/-/component-type-1.2.1.tgz", - "integrity": "sha512-Kgy+2+Uwr75vAi6ChWXgHuLvd+QLD7ssgpaRq2zCvt80ptvAfMc/hijcJxXkBa2wMlEZcJvC2H8Ubo+A9ATHIg==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/component-type/-/component-type-1.2.2.tgz", + "integrity": "sha512-99VUHREHiN5cLeHm3YLq312p6v+HUEcwtLCAtelvUDI6+SH5g5Cr85oNR2S1o6ywzL0ykMbuwLzM2ANocjEOIA==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/compressible": { "version": "2.0.18", @@ -9905,6 +9912,14 @@ "domelementtype": "1" } }, + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + }, "node_modules/dotenv-expand": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", @@ -10874,12 +10889,12 @@ } }, "node_modules/expo": { - "version": "49.0.11", - "resolved": "https://registry.npmjs.org/expo/-/expo-49.0.11.tgz", - "integrity": "sha512-4UtSnaVn4bAEsdp2Z2I8okCJEmAm2cj1Rl3ifm79fI4zMz3EqBaXMKs6OdMSTa6DWq3dZp8C/5dEKy/ynah0CA==", + "version": "49.0.23", + "resolved": "https://registry.npmjs.org/expo/-/expo-49.0.23.tgz", + "integrity": "sha512-mFdBpWisPXBuocRGywC14nDai5vSUmvEyQpwvKH/xUo+m5/TUvfqV6YIewFpW22zn5WFGFiuJPhzNrqhBBinIw==", "dependencies": { "@babel/runtime": "^7.20.0", - "@expo/cli": "0.10.12", + "@expo/cli": "0.10.17", "@expo/config": "8.1.2", "@expo/config-plugins": "7.2.5", "@expo/vector-icons": "^13.0.0", @@ -10887,11 +10902,11 @@ "expo-application": "~5.3.0", "expo-asset": "~8.10.1", "expo-constants": "~14.4.2", - "expo-file-system": "~15.4.4", + "expo-file-system": "~15.4.5", "expo-font": "~11.4.0", "expo-keep-awake": "~12.3.0", "expo-modules-autolinking": "1.5.1", - "expo-modules-core": "1.5.11", + "expo-modules-core": "1.5.13", "fbemitter": "^3.0.0", "invariant": "^2.2.4", "md5-file": "^3.2.3", @@ -10938,9 +10953,9 @@ } }, "node_modules/expo-file-system": { - "version": "15.4.4", - "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-15.4.4.tgz", - "integrity": "sha512-F0xS88D85F7qVQ61r0qBnzh6VW/s6iIl+VaQEEi2nAIOQHw1JIEj4yCXPLTtbyn5VmArbe2dSL3KYz1V+BLkKA==", + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-15.4.5.tgz", + "integrity": "sha512-xy61KaTaDgXhT/dllwYDHm3ch026EyO8j4eC6wSVr/yE12MMMxAC09yGwy4f7kkOs6ztGVQF5j7ldRzNLN4l0Q==", "dependencies": { "uuid": "^3.4.0" }, @@ -11106,9 +11121,9 @@ } }, "node_modules/expo-modules-core": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-1.5.11.tgz", - "integrity": "sha512-1Dj2t74nVjxq6xEQf2b9WFfAMhPzVnR0thY0PfRFgob4STyj3sq1U4PIHVWvKQBtDKIa227DrNRb+Hu+LqKWQg==", + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-1.5.13.tgz", + "integrity": "sha512-cKRsiHKwpDPRkBgMW3XdUWmEUDzihEPWXAyeo629BXpJ6uX6a66Zbz63SEXhlgsbLq8FB77gvYku3ceBqb+hHg==", "dependencies": { "compare-versions": "^3.4.0", "invariant": "^2.2.4" @@ -13779,6 +13794,25 @@ "lightningcss-win32-x64-msvc": "1.19.0" } }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.19.0.tgz", + "integrity": "sha512-wIJmFtYX0rXHsXHSr4+sC5clwblEMji7HHQ4Ub1/CznVRxtCFha6JIt5JZaNf8vQrfdZnBxLLC6R8pC818jXqg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/lightningcss-darwin-x64": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.19.0.tgz", @@ -13798,6 +13832,120 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.19.0.tgz", + "integrity": "sha512-P15VXY5682mTXaiDtbnLYQflc8BYb774j2R84FgDLJTN6Qp0ZjWEFyN1SPqyfTj2B2TFjRHRUvQSSZ7qN4Weig==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.19.0.tgz", + "integrity": "sha512-zwXRjWqpev8wqO0sv0M1aM1PpjHz6RVIsBcxKszIG83Befuh4yNysjgHVplF9RTU7eozGe3Ts7r6we1+Qkqsww==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.19.0.tgz", + "integrity": "sha512-vSCKO7SDnZaFN9zEloKSZM5/kC5gbzUjoJQ43BvUpyTFUX7ACs/mDfl2Eq6fdz2+uWhUh7vf92c4EaaP4udEtA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.19.0.tgz", + "integrity": "sha512-0AFQKvVzXf9byrXUq9z0anMGLdZJS+XSDqidyijI5njIwj6MdbvX2UZK/c4FfNmeRa2N/8ngTffoIuOUit5eIQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.19.0.tgz", + "integrity": "sha512-SJoM8CLPt6ECCgSuWe+g0qo8dqQYVcPiW2s19dxkmSI5+Uu1GIRzyKA0b7QqmEXolA+oSJhQqCmJpzjY4CuZAg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.19.0.tgz", + "integrity": "sha512-C+VuUTeSUOAaBZZOPT7Etn/agx/MatzJzGRkeV+zEABmPuntv1zihncsi+AyGmjkkzq3wVedEy7h0/4S84mUtg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -18319,9 +18467,12 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/traverse": { - "version": "0.6.7", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.7.tgz", - "integrity": "sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.8.tgz", + "integrity": "sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -19108,9 +19259,9 @@ } }, "node_modules/ws": { - "version": "8.14.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", - "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "engines": { "node": ">=10.0.0" }, diff --git a/src/app/auth/login/index.tsx b/src/app/auth/login/index.tsx index 9485d483..f8319596 100644 --- a/src/app/auth/login/index.tsx +++ b/src/app/auth/login/index.tsx @@ -9,8 +9,8 @@ import styles from './styles'; import StyledButton from '../../../components/StyledButton/StyledButton'; import UserStringInput from '../../../components/UserStringInput/UserStringInput'; import { isEmailUsed, queryEmailByUsername } from '../../../queries/auth'; -import globalStyles from '../../../styles/globalStyles'; import colors from '../../../styles/colors'; +import globalStyles from '../../../styles/globalStyles'; import { useSession } from '../../../utils/AuthContext'; function LoginScreen() { @@ -72,7 +72,6 @@ function LoginScreen() { {'Read stories from \nyoung creators'} - setPasswordTextHidden(!passwordTextHidden)} /> - - Welcome, {username} - + + Welcome, {user?.user_metadata.username} + + + Input your profile information below. + + + + + This information is only used for outreach efforts, and will not be + visible to other users on the app. + + Date: Tue, 5 Mar 2024 15:12:40 -0800 Subject: [PATCH 02/34] [chore] Prune styles (#58) * Added demographic warning * Random * Updated onboarding page to have demographic collection warning * Updated onboarding page to have demographic collection warning * Fixed requested changes * Pruned unused styles in auth/login auth/onboarding auth/signup auth/forgotPassword * Fix loading bug * Remove console errors --------- Co-authored-by: Justin Lee Co-authored-by: Aditya Pawar Co-authored-by: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> --- src/app/auth/login/styles.tsx | 1 - src/app/auth/onboarding/styles.tsx | 12 ------------ src/app/auth/signup/index.tsx | 2 +- src/app/auth/signup/styles.tsx | 3 --- src/app/index.tsx | 10 +--------- 5 files changed, 2 insertions(+), 26 deletions(-) diff --git a/src/app/auth/login/styles.tsx b/src/app/auth/login/styles.tsx index 3f0cb0cd..54177601 100644 --- a/src/app/auth/login/styles.tsx +++ b/src/app/auth/login/styles.tsx @@ -1,5 +1,4 @@ import { StyleSheet } from 'react-native'; -import colors from '../../../styles/colors'; export default StyleSheet.create({ flex: { diff --git a/src/app/auth/onboarding/styles.tsx b/src/app/auth/onboarding/styles.tsx index 7e350ae2..a868ff3b 100644 --- a/src/app/auth/onboarding/styles.tsx +++ b/src/app/auth/onboarding/styles.tsx @@ -3,18 +3,6 @@ import { StyleSheet } from 'react-native'; import colors from '../../../styles/colors'; export default StyleSheet.create({ - input: { - height: 40, - borderColor: 'gray', - borderWidth: 1, - marginTop: 10, - padding: 5, - }, - verticallySpaced: { - paddingTop: 4, - paddingBottom: 4, - alignSelf: 'stretch', - }, container: { paddingVertical: 63, paddingLeft: 43, diff --git a/src/app/auth/signup/index.tsx b/src/app/auth/signup/index.tsx index 748cd3d9..f386e42f 100644 --- a/src/app/auth/signup/index.tsx +++ b/src/app/auth/signup/index.tsx @@ -304,7 +304,7 @@ function SignUpScreen() { )} - + { @@ -43,7 +35,7 @@ function StartPage() { return () => { clearTimeout(timer); }; - }, [delay]); + }, [delay, isLoading]); return ; } From 56833da5dc19540936b4b6484cec772182fd7682 Mon Sep 17 00:00:00 2001 From: Kyle Ramachandran <156966341+kylezryr@users.noreply.github.com> Date: Tue, 5 Mar 2024 15:52:57 -0800 Subject: [PATCH 03/34] [home] Updating preview card (#62) * styling preview card * finished styling preview card * Add cheerio to get text of header * Run prettier --------- Co-authored-by: Kyle Ramachandran Co-authored-by: Aditya Pawar --- package-lock.json | 238 +++++++++++++++++++++ package.json | 1 + src/components/PreviewCard/PreviewCard.tsx | 39 ++-- src/components/PreviewCard/styles.ts | 71 +++--- 4 files changed, 304 insertions(+), 45 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6a31d071..e9602b7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "@supabase/supabase-js": "^2.36.0", "@types/validator": "^13.11.5", "axios": "^1.5.0", + "cheerio": "^1.0.0-rc.12", "deprecated-react-native-prop-types": "^4.2.1", "dom-parser": "^0.1.6", "expo": "~49.0.11", @@ -8865,6 +8866,184 @@ "node": "*" } }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cheerio-select/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/cheerio-select/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/cheerio-select/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/cheerio-select/node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/cheerio-select/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/cheerio/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/cheerio/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/cheerio/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/cheerio/node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/cheerio/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/cheerio/node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -15742,6 +15921,65 @@ "node": ">=10" } }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", diff --git a/package.json b/package.json index 3e8c0f7b..714681ff 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@supabase/supabase-js": "^2.36.0", "@types/validator": "^13.11.5", "axios": "^1.5.0", + "cheerio": "^1.0.0-rc.12", "deprecated-react-native-prop-types": "^4.2.1", "dom-parser": "^0.1.6", "expo": "~49.0.11", diff --git a/src/components/PreviewCard/PreviewCard.tsx b/src/components/PreviewCard/PreviewCard.tsx index 61e42f2e..ac894d63 100644 --- a/src/components/PreviewCard/PreviewCard.tsx +++ b/src/components/PreviewCard/PreviewCard.tsx @@ -5,6 +5,7 @@ import { Text, View, } from 'react-native'; +import * as cheerio from 'cheerio'; import styles from './styles'; import globalStyles from '../../styles/globalStyles'; @@ -31,40 +32,48 @@ function PreviewCard({ return ( - + + + {title} + + + - - {title} - {author} - - {excerpt.html.slice(3, -3)} + + "{cheerio.load(excerpt.html).text()}" - {/* - - {tags.map(tag => ( - - {tag} + + + + + {tags[0]} - ))} + - more tags + + {' '} + + {tags.length - 1} more tags + - */} + ); diff --git a/src/components/PreviewCard/styles.ts b/src/components/PreviewCard/styles.ts index 9f361b45..d69aae26 100644 --- a/src/components/PreviewCard/styles.ts +++ b/src/components/PreviewCard/styles.ts @@ -6,7 +6,7 @@ const styles = StyleSheet.create({ card: { flexDirection: 'column', justifyContent: 'flex-end', - backgroundColor: colors.white, + backgroundColor: '#FFF', borderRadius: 6, marginTop: 8, marginBottom: 8, @@ -14,31 +14,6 @@ const styles = StyleSheet.create({ shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.5, elevation: 4, - paddingRight: 8, - }, - top: { - flex: 1, - flexDirection: 'row', - justifyContent: 'flex-start', - alignItems: 'flex-start', - paddingLeft: 12, - paddingRight: 12, - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.3, - shadowRadius: 3, - }, - bottom: { - flex: 1, - flexDirection: 'column', - justifyContent: 'flex-start', - alignItems: 'flex-start', - height: 48, - backgroundColor: colors.lightGrey, - overflow: 'hidden', - borderRadius: 6, - paddingHorizontal: 12, - paddingTop: 8, }, image: { height: 96, @@ -46,7 +21,6 @@ const styles = StyleSheet.create({ backgroundColor: colors.lilac, borderRadius: 4, marginBottom: 12, - marginTop: 12, }, author: { marginLeft: 8, @@ -56,11 +30,11 @@ const styles = StyleSheet.create({ width: 22, backgroundColor: colors.gwnOrange, borderRadius: 22 / 2, + marginLeft: 8, }, cardTextContainer: { flex: 1, - marginLeft: 16, - marginTop: 12, + marginTop: 10, marginBottom: 8, }, authorContainer: { @@ -72,10 +46,16 @@ const styles = StyleSheet.create({ title: { marginBottom: 8, }, + titleContainer: { + paddingTop: 16, + paddingLeft: 12, + borderBottomColor: '#EBEBEB', + borderBottomWidth: StyleSheet.hairlineWidth, + }, tag: { paddingHorizontal: 8, paddingVertical: 4, - backgroundColor: colors.darkGrey, + backgroundColor: '#EBEBEB', borderRadius: 10, width: 'auto', marginRight: 8, @@ -83,10 +63,41 @@ const styles = StyleSheet.create({ }, tagsContainer: { // backgroundColor: colors.darkGrey, + flex: 1, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + flexWrap: 'wrap', + borderRadius: 6, + paddingLeft: 12, + paddingBottom: 4, + backgroundColor: colors.white, + }, + tagsRow: { flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center', flexWrap: 'wrap', + paddingTop: 4, + }, + moreTags: { + paddingRight: 12, + alignItems: 'center', + justifyContent: 'center', + }, + moreTagsText: { + color: colors.darkGrey, + }, + storyDescription: { + color: colors.darkGrey, + paddingRight: 12, + paddingLeft: 10, + }, + body: { + flexDirection: 'row', + marginTop: 16, + paddingLeft: 12, + paddingBottom: 12, }, }); From cbbb30bf58f1f3e1a7152978bd166b0801bef604 Mon Sep 17 00:00:00 2001 From: Inaya Yusuf <71958031+InayaY3@users.noreply.github.com> Date: Sat, 9 Mar 2024 21:29:43 -0800 Subject: [PATCH 04/34] [auth] Style OTP verification screen (#47) * package error for otptextinput * otp screen basic elements unstyled * stuff from last sem * Finish otp input screen * Make toast into its own component * Fix signup link on login * Remove old comments --------- Co-authored-by: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> Co-authored-by: Aditya Pawar --- package-lock.json | 34 +++---- package.json | 2 +- src/app/(tabs)/home/index.tsx | 1 - src/app/_layout.tsx | 2 + src/app/auth/login/index.tsx | 6 +- src/app/auth/login/styles.tsx | 4 +- src/app/auth/signup/index.tsx | 3 +- src/app/auth/verify/index.tsx | 154 +++++++++++++++++++++----------- src/app/auth/verify/styles.tsx | 55 ++++++++++-- src/components/Toast/Toast.tsx | 31 +++++++ src/components/Toast/styles.tsx | 14 +++ src/components/ToastScreen.tsx | 30 ------- src/styles/globalStyles.ts | 7 +- 13 files changed, 225 insertions(+), 118 deletions(-) create mode 100644 src/components/Toast/Toast.tsx create mode 100644 src/components/Toast/styles.tsx delete mode 100644 src/components/ToastScreen.tsx diff --git a/package-lock.json b/package-lock.json index e9602b7d..29d5a254 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,10 +49,10 @@ "react-native-paper": "^5.10.6", "react-native-render-html": "^6.3.4", "react-native-root-siblings": "^4.1.1", - "react-native-root-toast": "^3.5.1", "react-native-safe-area-context": "4.6.3", "react-native-screens": "~3.22.0", "react-native-svg": "13.9.0", + "react-native-toast-message": "^2.2.0", "react-native-url-polyfill": "^2.0.0", "react-native-vector-icons": "^10.0.2", "react-scroll-to-top": "^3.0.0", @@ -16896,29 +16896,6 @@ "resolved": "https://registry.npmjs.org/react-native-root-siblings/-/react-native-root-siblings-4.1.1.tgz", "integrity": "sha512-sdmLElNs5PDWqmZmj4/aNH4anyxreaPm61c4ZkRiR8SO/GzLg6KjAbb0e17RmMdnBdD0AIQbS38h/l55YKN4ZA==" }, - "node_modules/react-native-root-toast": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/react-native-root-toast/-/react-native-root-toast-3.5.1.tgz", - "integrity": "sha512-zqsuec7Ugx2/9hR9BHqcmb3WWC/WBouqn2RYIpeTG+OpVvVfvr2UhWK4kLPJLk5/icZWl3xJrqiktPpbRpEA2A==", - "dependencies": { - "deprecated-react-native-prop-types": "^2.3.0", - "prop-types": "^15.5.10", - "react-native-root-siblings": "^4.0.0" - }, - "peerDependencies": { - "react-native": ">=0.47.0" - } - }, - "node_modules/react-native-root-toast/node_modules/deprecated-react-native-prop-types": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-2.3.0.tgz", - "integrity": "sha512-pWD0voFtNYxrVqvBMYf5gq3NA2GCpfodS1yNynTPc93AYA/KEMGeWDqqeUB6R2Z9ZofVhks2aeJXiuQqKNpesA==", - "dependencies": { - "@react-native/normalize-color": "*", - "invariant": "*", - "prop-types": "*" - } - }, "node_modules/react-native-safe-area-context": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.6.3.tgz", @@ -16962,6 +16939,15 @@ "react-native": "*" } }, + "node_modules/react-native-toast-message": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/react-native-toast-message/-/react-native-toast-message-2.2.0.tgz", + "integrity": "sha512-AFti8VzUk6JvyGAlLm9/BknTNDXrrhqnUk7ak/pM7uCTxDPveAu2ekszU0on6vnUPFnG04H/QfYE2IlETqeaWw==", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-url-polyfill": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/react-native-url-polyfill/-/react-native-url-polyfill-2.0.0.tgz", diff --git a/package.json b/package.json index 714681ff..d25b4adf 100644 --- a/package.json +++ b/package.json @@ -53,10 +53,10 @@ "react-native-paper": "^5.10.6", "react-native-render-html": "^6.3.4", "react-native-root-siblings": "^4.1.1", - "react-native-root-toast": "^3.5.1", "react-native-safe-area-context": "4.6.3", "react-native-screens": "~3.22.0", "react-native-svg": "13.9.0", + "react-native-toast-message": "^2.2.0", "react-native-url-polyfill": "^2.0.0", "react-native-vector-icons": "^10.0.2", "react-scroll-to-top": "^3.0.0", diff --git a/src/app/(tabs)/home/index.tsx b/src/app/(tabs)/home/index.tsx index f9067788..4c26eed3 100644 --- a/src/app/(tabs)/home/index.tsx +++ b/src/app/(tabs)/home/index.tsx @@ -7,7 +7,6 @@ import styles from './styles'; import Icon from '../../../../assets/icons'; import ContentCard from '../../../components/ContentCard/ContentCard'; import PreviewCard from '../../../components/PreviewCard/PreviewCard'; -import RecentSearchCard from '../../../components/RecentSearchCard/RecentSearchCard'; import { fetchUsername } from '../../../queries/profiles'; import { fetchFeaturedStoriesDescription, diff --git a/src/app/_layout.tsx b/src/app/_layout.tsx index 92819933..2223fa0e 100644 --- a/src/app/_layout.tsx +++ b/src/app/_layout.tsx @@ -2,6 +2,7 @@ import { Stack } from 'expo-router'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { AuthContextProvider } from '../utils/AuthContext'; +import ToastComponent from '../components/Toast/Toast'; function StackLayout() { return ( @@ -14,6 +15,7 @@ function StackLayout() { + ); } diff --git a/src/app/auth/login/index.tsx b/src/app/auth/login/index.tsx index f8319596..9dd4e71a 100644 --- a/src/app/auth/login/index.tsx +++ b/src/app/auth/login/index.tsx @@ -118,12 +118,12 @@ function LoginScreen() { /> - - Don't have an account?{' '} + + Don't have an account? Sign Up - + ); diff --git a/src/app/auth/login/styles.tsx b/src/app/auth/login/styles.tsx index 54177601..25271c92 100644 --- a/src/app/auth/login/styles.tsx +++ b/src/app/auth/login/styles.tsx @@ -13,7 +13,9 @@ export default StyleSheet.create({ textDecorationLine: 'underline', }, redirectText: { - textAlign: 'center', + gap: 8, + flexDirection: 'row', + justifyContent: 'center', marginTop: 16, marginBottom: 64, }, diff --git a/src/app/auth/signup/index.tsx b/src/app/auth/signup/index.tsx index f386e42f..12f09715 100644 --- a/src/app/auth/signup/index.tsx +++ b/src/app/auth/signup/index.tsx @@ -1,5 +1,5 @@ import { Link, router } from 'expo-router'; -import React, { useEffect, useRef, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { Alert, Text, View } from 'react-native'; import { Icon as RNEIcon } from 'react-native-elements'; import { ScrollView } from 'react-native-gesture-handler'; @@ -238,7 +238,6 @@ function SignUpScreen() { /> - {password !== '' && ( diff --git a/src/app/auth/verify/index.tsx b/src/app/auth/verify/index.tsx index e2d9679a..c469ba84 100644 --- a/src/app/auth/verify/index.tsx +++ b/src/app/auth/verify/index.tsx @@ -1,81 +1,135 @@ -import { router } from 'expo-router'; -import React, { useState } from 'react'; -import { Alert, TextInput, View } from 'react-native'; -import { Button } from 'react-native-elements'; +import { Link, router } from 'expo-router'; +import { useState, useRef, useEffect } from 'react'; +import { View, Text } from 'react-native'; +import OTPTextInput from 'react-native-otp-textinput'; import { SafeAreaView } from 'react-native-safe-area-context'; import styles from './styles'; +import colors from '../../../styles/colors'; import globalStyles from '../../../styles/globalStyles'; import { useSession } from '../../../utils/AuthContext'; +import Toast, { BaseToast, BaseToastProps } from 'react-native-toast-message'; +import { Icon } from 'react-native-elements'; function VerificationScreen() { const { user, verifyOtp, resendVerification } = useSession(); - const [loading, setLoading] = useState(false); - const [verificationCode, setCode] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [showX, setShowX] = useState(false); + const [userInput, setUserInput] = useState(''); - // let otpInput = useRef(null); + const inputRef = useRef(null); - // const clearText = () => { - // otpInput.current.clear(); - // } + useEffect(() => { + if (userInput.length === 6) { + console.log('we are checking'); + console.log(userInput); - // const setText = () => { - // otpInput.current.setValue("1234"); - // } - - const verifyAccount = async () => { - setLoading(true); + verifyCode(); + } + }, [userInput]); - if (user?.email && verificationCode) { - const { error } = await verifyOtp(user.email, verificationCode); + const clearText = () => { + inputRef.current?.clear(); + }; - if (error) Alert.alert(error.message); - else router.replace('/auth/onboarding'); - } else if (!verificationCode) { - Alert.alert(`Please enter a verification code`); - } else { - Alert.alert(`Please sign up again.`); + const verifyCode = async () => { + if (user?.email) { + const { error } = await verifyOtp(user.email, userInput); + + console.log(error); + if (error) { + setShowX(true); + setErrorMessage('Incorrect code. Please try again.'); + } else { + router.replace('/auth/onboarding'); + } } - - setLoading(false); }; const resendCode = async () => { - setLoading(true); + clearText(); if (user?.email) { const { error } = await resendVerification(user.email); - if (error) Alert.alert(error.message); - else Alert.alert(`Verification email sent to ${user.email}.`); - } else { - Alert.alert(`Please sign up again.`); + if (error) { + setShowX(false); + setErrorMessage( + 'Please wait 1 minute for us to resend the verification code.', + ); + } else { + Toast.show({ + type: 'success', + text1: `A new verification code has been sent to`, + text2: `${blurrEmail()}.`, + text2Style: globalStyles.subtextBold, + text1Style: globalStyles.subtext, + position: 'bottom', + }); + } + } + }; + + const blurrEmail = () => { + if (user?.email) { + const length = user?.email?.split('@')[0].length; + return `${user?.email?.substring(0, 2)}*****${user?.email + ?.split('@')[0] + .substring(length - 1, length)}@${user?.email?.split('@')[1]}`; } + return 'your email'; + }; - setLoading(false); + const renderBlurredEmail = () => { + return {blurrEmail()}.; }; return ( - - - - - + + + + ); +} + +export default TestCard; diff --git a/src/components/TestCard/styles.tsx b/src/components/TestCard/styles.tsx new file mode 100644 index 00000000..1ea6f118 --- /dev/null +++ b/src/components/TestCard/styles.tsx @@ -0,0 +1,26 @@ +import { StyleSheet } from 'react-native'; + +import colors from '../../styles/colors'; + +const styles = StyleSheet.create({ + contentCard: { + marginRight: 20, + flexDirection: 'column', + justifyContent: 'space-between', + }, + image: { + height: 140, + width: 148, + backgroundColor: colors.lime, + borderRadius: 4, + marginBottom: 8, + }, + textContainer: { + width: 148, + }, + title: { + marginBottom: 4, + }, +}); + +export default styles; diff --git a/src/queries/savedStories.tsx b/src/queries/savedStories.tsx new file mode 100644 index 00000000..78ce29ec --- /dev/null +++ b/src/queries/savedStories.tsx @@ -0,0 +1,87 @@ +import supabase from '../utils/supabase'; + +const favorites = 'favorites'; +const readingList = 'reading list'; + +async function fetchUserStories( + user_id: string | undefined, + name: string | undefined, +) { + const { data, error } = await supabase + .from('saved_stories') + .select('story_id') + .eq('user_id', user_id) + .eq('name', name); + + if (error) { + if (process.env.NODE_ENV !== 'production') { + throw new Error( + `An error occured when trying to fetch user saved stories: ${error.details}`, + ); + } + } else { + return data; + } +} + +export async function fetchUserStoriesFavorites(user_id: string | undefined) { + fetchUserStories(user_id, favorites); +} + +export async function fetchUserStoriesReadingList(user_id: string | undefined) { + fetchUserStories(user_id, readingList); +} + +async function addUserStory( + user_id: string | undefined, + story_id: number, + name: string, +) { + const { error } = await supabase + .from('saved_stories') + .insert([{ user_id: user_id, story_id: story_id, name: name }]) + .select(); + + if (error) { + if (process.env.NODE_ENV !== 'production') { + throw new Error( + `An error occured when trying to set user saved stories: ${error.details}`, + ); + } + } +} + +export async function addUserStoryToFavorites( + user_id: string | undefined, + story_id: number, +) { + addUserStory(user_id, story_id, favorites); +} + +export async function addUserStoryToReadingList( + user_id: string | undefined, + story_id: number, +) { + addUserStory(user_id, story_id, readingList); +} + +export async function deleteUserStories( + user_id: string | undefined, + story_id: number, + name: string, +) { + const { error } = await supabase + .from('saved_stories') + .delete() + .eq('user_id', user_id) + .eq('story_id', story_id) + .eq('name', name); + + if (error) { + if (process.env.NODE_ENV !== 'production') { + throw new Error( + `An error occured when trying to delete user saved stories: ${error.details}`, + ); + } + } +} From 6f73709cf6a32237ebd7177bf2e314320b8547c5 Mon Sep 17 00:00:00 2001 From: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> Date: Sat, 16 Mar 2024 15:39:03 -0700 Subject: [PATCH 10/34] Fix keyboard dismiss bug on story scroll (#70) * Fix keyboard dismiss bug on story scroll * Remove comments --- src/app/(tabs)/home/index.tsx | 1 - src/app/_layout.tsx | 26 ++++++++++++-------------- src/app/auth/_layout.tsx | 25 +++++++++++++++++-------- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/app/(tabs)/home/index.tsx b/src/app/(tabs)/home/index.tsx index 4c26eed3..7c224297 100644 --- a/src/app/(tabs)/home/index.tsx +++ b/src/app/(tabs)/home/index.tsx @@ -65,7 +65,6 @@ function HomeScreen() { diff --git a/src/app/_layout.tsx b/src/app/_layout.tsx index 88109572..7e805eaa 100644 --- a/src/app/_layout.tsx +++ b/src/app/_layout.tsx @@ -1,25 +1,23 @@ import { Stack } from 'expo-router'; -import { Keyboard, TouchableWithoutFeedback } from 'react-native'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { AuthContextProvider } from '../utils/AuthContext'; import ToastComponent from '../components/Toast/Toast'; +import { Keyboard, TouchableWithoutFeedback } from 'react-native'; function StackLayout() { return ( - - - - - - - - - - - - - + + + + + + + + + + + ); } diff --git a/src/app/auth/_layout.tsx b/src/app/auth/_layout.tsx index 93291c32..6bc4e7b0 100644 --- a/src/app/auth/_layout.tsx +++ b/src/app/auth/_layout.tsx @@ -1,15 +1,24 @@ import { Stack } from 'expo-router'; +import { Keyboard, TouchableWithoutFeedback } from 'react-native'; +import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'; function StackLayout() { return ( - - - - - - - - + + + + + + + + + + + + ); } From 2e531e6e41390686ea12f45c99ba4e1e2157ab38 Mon Sep 17 00:00:00 2001 From: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> Date: Sat, 16 Mar 2024 16:56:31 -0700 Subject: [PATCH 11/34] Fix return statement in fetch (#72) * Fix return statement in fetch * Batch rpc call * Run prettier --- src/app/(tabs)/home/index.tsx | 2 + src/components/TestCard/TestCard.tsx | 22 +++++-- .../UserSelectorInput/UserSelectorInput.tsx | 62 +++++++++---------- src/queries/savedStories.tsx | 35 +++++++++-- src/queries/types.tsx | 1 + 5 files changed, 77 insertions(+), 45 deletions(-) diff --git a/src/app/(tabs)/home/index.tsx b/src/app/(tabs)/home/index.tsx index 7c224297..4056f3d1 100644 --- a/src/app/(tabs)/home/index.tsx +++ b/src/app/(tabs)/home/index.tsx @@ -17,6 +17,7 @@ import { import { StoryCard, StoryPreview } from '../../../queries/types'; import globalStyles from '../../../styles/globalStyles'; import { useSession } from '../../../utils/AuthContext'; +import TestCard from '../../../components/TestCard/TestCard'; function HomeScreen() { const { user } = useSession(); @@ -62,6 +63,7 @@ function HomeScreen() { Loading )} + setStoryId(t)} value={storyId} /> await addUserStoryToReadingList(user?.id, parseInt(storyId)) } > - Add story to favorites + Add story to reading - Add story to reading list + Add story to favs list - + diff --git a/src/components/UserSelectorInput/UserSelectorInput.tsx b/src/components/UserSelectorInput/UserSelectorInput.tsx index 4fd7fb81..dd5be4fc 100644 --- a/src/components/UserSelectorInput/UserSelectorInput.tsx +++ b/src/components/UserSelectorInput/UserSelectorInput.tsx @@ -26,39 +26,35 @@ function UserSelectorInput({ return ( {label} - - { - return { label: option, value: option }; - })} - maxHeight={400} - labelField="label" - valueField="value" - placeholder={'Select Option'} - value={value} - renderItem={(item: Option, selected: boolean | undefined) => ( - - {item.value} - - )} - renderRightIcon={() => ( - - )} - onChange={(item: Option) => { - setValue(item.value); - }} - /> - + { + return { label: option, value: option }; + })} + maxHeight={400} + labelField="label" + valueField="value" + placeholder={'Select Option'} + value={value} + renderItem={(item: Option, selected: boolean | undefined) => ( + + {item.value} + + )} + renderRightIcon={() => } + onChange={(item: Option) => { + setValue(item.value); + }} + /> ); } diff --git a/src/queries/savedStories.tsx b/src/queries/savedStories.tsx index 78ce29ec..59f6ecaa 100644 --- a/src/queries/savedStories.tsx +++ b/src/queries/savedStories.tsx @@ -7,7 +7,7 @@ async function fetchUserStories( user_id: string | undefined, name: string | undefined, ) { - const { data, error } = await supabase + const { data: storyObjects, error } = await supabase .from('saved_stories') .select('story_id') .eq('user_id', user_id) @@ -16,20 +16,43 @@ async function fetchUserStories( if (error) { if (process.env.NODE_ENV !== 'production') { throw new Error( - `An error occured when trying to fetch user saved stories: ${error.details}`, + `An error occured when trying to fetch user saved stories: ${JSON.stringify( + error, + )}`, ); } - } else { - return data; + return []; } + + let storyData = []; + for (const storyObject of storyObjects) { + const storyId = storyObject['story_id']; + const { data, error } = await supabase.rpc('fetch_story', { + input_id: storyId, + }); + + if (error || data.length == 0) { + if (process.env.NODE_ENV !== 'production') { + throw new Error( + `An error occured when trying to use rpc to get story data: ${JSON.stringify( + error, + )}`, + ); + } + } else { + storyData.push(data[0]); + } + } + + return storyData; } export async function fetchUserStoriesFavorites(user_id: string | undefined) { - fetchUserStories(user_id, favorites); + return await fetchUserStories(user_id, favorites); } export async function fetchUserStoriesReadingList(user_id: string | undefined) { - fetchUserStories(user_id, readingList); + return await fetchUserStories(user_id, readingList); } async function addUserStory( diff --git a/src/queries/types.tsx b/src/queries/types.tsx index 01d7f547..04ec7d19 100644 --- a/src/queries/types.tsx +++ b/src/queries/types.tsx @@ -24,6 +24,7 @@ export interface RecentSearch { value: string; numResults: number; } + export interface Story { id: number; date: string; From d15439694a80a685614551f384a0ab7da67dfac1 Mon Sep 17 00:00:00 2001 From: surajr10 <73401552+surajr10@users.noreply.github.com> Date: Sat, 16 Mar 2024 19:05:31 -0700 Subject: [PATCH 12/34] Added content width prop to RenderHTML (#71) --- src/app/(tabs)/story/index.tsx | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/app/(tabs)/story/index.tsx b/src/app/(tabs)/story/index.tsx index 381a937f..646a1e4a 100644 --- a/src/app/(tabs)/story/index.tsx +++ b/src/app/(tabs)/story/index.tsx @@ -9,6 +9,7 @@ import { Text, TouchableOpacity, View, + useWindowDimensions, } from 'react-native'; import { Button } from 'react-native-paper'; import { RenderHTML } from 'react-native-render-html'; @@ -26,6 +27,8 @@ function StoryScreen() { const params = useLocalSearchParams<{ storyId: string }>(); const { storyId } = params; + const { width } = useWindowDimensions(); + const scrollUp = () => { scrollRef.current?.scrollTo({ x: 0, y: 0 }); }; @@ -112,9 +115,17 @@ function StoryScreen() { - + - + - )} - {showDatePicker && ( - { - setShowDatePicker(Platform.OS === 'ios'); - if (date.nativeEvent.timestamp) { - setDate(new Date(date.nativeEvent.timestamp)); - } - }} - /> - )} - - ); -} - -export default DatePicker; diff --git a/src/components/DatePicker/styles.tsx b/src/components/DatePicker/styles.tsx deleted file mode 100644 index a11509d5..00000000 --- a/src/components/DatePicker/styles.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { StyleSheet } from 'react-native'; - -export default StyleSheet.create({ - mt16: { - marginTop: 16, - width: '100%', - }, - container: { - paddingRight: 10, - marginTop: 8, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - borderWidth: 1, - borderRadius: 5, - borderColor: 'black', - fontFamily: 'Manrope-Regular', - }, - inputField: { - flex: 1, - fontSize: 14, - padding: 10, - color: '#000000', - }, - button: { - backgroundColor: 'gray', - }, - verticallySpaced: { - alignSelf: 'stretch', - }, -}); diff --git a/src/queries/stories.tsx b/src/queries/stories.tsx index 68bfafc4..e9fd3683 100644 --- a/src/queries/stories.tsx +++ b/src/queries/stories.tsx @@ -25,7 +25,6 @@ export async function fetchStory(storyId: number): Promise { `An error occured when trying to fetch story ${storyId}: ${error.code}`, ); } else { - console.log(data); return data; } } From 23bebf3da022d81d7692861719d2ef696e3071d7 Mon Sep 17 00:00:00 2001 From: Justin Lee <91563628+jjstnlee@users.noreply.github.com> Date: Tue, 26 Mar 2024 21:20:42 -0700 Subject: [PATCH 14/34] [auth] OTP input for forgot password (#67) * Added ability to go to verification screen from signup and forgot password * Fixed error with verification screen after forgetting password * Changed new password screen so that password requirements show even when the user hasn't inputted a new password yet * Fix small bugs in sign up and create password * Added ability to dismiss keyboard when tapping screen (#68) * [save] Database schema changes for saving stories (#61) * accidently forgot to branch * fethUserSavedStories function created * categories created * added method to delete row * favorites and reading list global variables set * PR changes * Add testcard * Finish testing schema changes * Run prettier * Remove testcard from home * Clean up code * Run prettier --------- Co-authored-by: Marcos Hernandez Co-authored-by: Aditya Pawar * Fix keyboard dismiss bug on story scroll (#70) * Fix keyboard dismiss bug on story scroll * Remove comments * Fix return statement in fetch (#72) * Fix return statement in fetch * Batch rpc call * Run prettier * Added content width prop to RenderHTML (#71) * [auth] Date picker crossplatform (#69) * added date picker button, no styling yet * working on style datepicker * working on datePicker * new datePicker library * testing on android * finished datePicker * changed small bugs * Fix date picker bugs * Revert set state --------- Co-authored-by: Kyle Ramachandran Co-authored-by: Aditya Pawar * Fixed requested changes * Add eas.json to gitignore --------- Co-authored-by: Aditya Pawar Co-authored-by: Marcoss28 <69034384+Marcoss28@users.noreply.github.com> Co-authored-by: Marcos Hernandez Co-authored-by: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> Co-authored-by: surajr10 <73401552+surajr10@users.noreply.github.com> Co-authored-by: Kyle Ramachandran <156966341+kylezryr@users.noreply.github.com> Co-authored-by: Kyle Ramachandran --- .gitignore | 1 + src/app/auth/forgotPassword/index.tsx | 6 ++- src/app/auth/resetPassword/index.tsx | 64 +++++++++++------------ src/app/auth/signup/index.tsx | 9 +++- src/app/auth/verify/index.tsx | 75 ++++++++++++++------------- 5 files changed, 82 insertions(+), 73 deletions(-) diff --git a/.gitignore b/.gitignore index 4c58e1b7..afc76a51 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ yarn-error.* *.tsbuildinfo .vscode/ +eas.json diff --git a/src/app/auth/forgotPassword/index.tsx b/src/app/auth/forgotPassword/index.tsx index 99692e48..45570132 100644 --- a/src/app/auth/forgotPassword/index.tsx +++ b/src/app/auth/forgotPassword/index.tsx @@ -25,7 +25,11 @@ function ForgotPasswordScreen() { const { error } = await resetPassword(emailToReset); if (error) Alert.alert('Could not send a reset password email. Please try again.'); - else router.replace('auth/signup'); + else + router.push({ + pathname: '/auth/verify', + params: { finalRedirect: 'resetPassword', userEmail: emailToReset }, + }); }; useEffect(() => { diff --git a/src/app/auth/resetPassword/index.tsx b/src/app/auth/resetPassword/index.tsx index 2356d256..024fcf06 100644 --- a/src/app/auth/resetPassword/index.tsx +++ b/src/app/auth/resetPassword/index.tsx @@ -1,17 +1,15 @@ -import { Link, router } from 'expo-router'; -import React, { useEffect, useRef, useState } from 'react'; +import { router } from 'expo-router'; +import { useEffect, useState } from 'react'; import { Alert, Text, View } from 'react-native'; import { Icon as RNEIcon } from 'react-native-elements'; import styles from './styles'; -import Icon from '../../../../assets/icons'; import StyledButton from '../../../components/StyledButton/StyledButton'; import UserStringInput from '../../../components/UserStringInput/UserStringInput'; import colors from '../../../styles/colors'; import globalStyles from '../../../styles/globalStyles'; import { useSession } from '../../../utils/AuthContext'; import PasswordComplexityText from '../../../components/PasswordComplexityText/PasswordComplexityText'; -import supabase from '../../../utils/supabase'; function ResetPasswordScreen() { const { updateUser, signOut } = useSession(); @@ -43,6 +41,11 @@ function ResetPasswordScreen() { setHasNumber(/[0-9]/.test(text)); setHasLength(text.length >= 8); //need to check that it is different from old password + } else { + setHasUppercase(false); + setHasLowercase(false); + setHasNumber(false); + setHasLength(false); } }; @@ -105,38 +108,31 @@ function ResetPasswordScreen() { - {password !== '' && ( - - )} - {password !== '' && ( - - )} - {password !== '' && ( - - )} - {password !== '' && ( - - )} + + + + + + + {/* functionality for this has not been implemented */} - {password !== '' && ( - - )} + {passwordIsValid && ( diff --git a/src/app/auth/signup/index.tsx b/src/app/auth/signup/index.tsx index 41246d2c..f7c9506f 100644 --- a/src/app/auth/signup/index.tsx +++ b/src/app/auth/signup/index.tsx @@ -7,7 +7,6 @@ import { SafeAreaView } from 'react-native-safe-area-context'; import validator from 'validator'; import styles from './styles'; -import Icon from '../../../../assets/icons'; import StyledButton from '../../../components/StyledButton/StyledButton'; import UserStringInput from '../../../components/UserStringInput/UserStringInput'; import PasswordComplexityText from '../../../components/PasswordComplexityText/PasswordComplexityText'; @@ -130,7 +129,11 @@ function SignUpScreen() { }); if (error) Alert.alert(error.message); - else router.replace('/auth/verify'); + else + router.push({ + pathname: '/auth/verify', + params: { finalRedirect: 'onboarding' }, + }); setLoading(false); }; @@ -251,6 +254,8 @@ function SignUpScreen() { loading || emailError !== '' || usernameError !== '' || + firstName.length === 0 || + lastName.length === 0 || email.length === 0 || username.length === 0 } diff --git a/src/app/auth/verify/index.tsx b/src/app/auth/verify/index.tsx index 75a00648..a3b9406c 100644 --- a/src/app/auth/verify/index.tsx +++ b/src/app/auth/verify/index.tsx @@ -1,4 +1,4 @@ -import { Link, router } from 'expo-router'; +import { Link, Redirect, router, useLocalSearchParams } from 'expo-router'; import { useState, useRef, useEffect } from 'react'; import { View, Text } from 'react-native'; import OTPTextInput from 'react-native-otp-textinput'; @@ -16,6 +16,12 @@ function VerificationScreen() { const [errorMessage, setErrorMessage] = useState(''); const [showX, setShowX] = useState(false); const [userInput, setUserInput] = useState(''); + const params = useLocalSearchParams<{ + finalRedirect: string; + userEmail: string; + }>(); + const { finalRedirect, userEmail } = params; + const email = user?.email ?? userEmail ?? ''; const inputRef = useRef(null); @@ -30,57 +36,54 @@ function VerificationScreen() { }; const verifyCode = async () => { - if (user?.email) { - const { error } = await verifyOtp(user.email, userInput); - - console.log(error); - if (error) { - setShowX(true); - setErrorMessage('Incorrect code. Please try again.'); - } else { - router.replace('/auth/onboarding'); - } + const { error } = await verifyOtp(email, userInput); + + console.log(error); + if (error) { + setShowX(true); + setErrorMessage('Incorrect code. Please try again.'); + } else { + router.replace('/auth/' + finalRedirect); } }; const resendCode = async () => { clearText(); - if (user?.email) { - const { error } = await resendVerification(user.email); - - if (error) { - setShowX(false); - setErrorMessage( - 'Please wait 1 minute for us to resend the verification code.', - ); - } else { - Toast.show({ - type: 'success', - text1: `A new verification code has been sent to`, - text2: `${blurrEmail()}.`, - text2Style: globalStyles.subtextBold, - text1Style: globalStyles.subtext, - position: 'bottom', - }); - } + const { error } = await resendVerification(email); + + if (error) { + setShowX(false); + setErrorMessage( + 'Please wait 1 minute for us to resend the verification code.', + ); + } else { + Toast.show({ + type: 'success', + text1: `A new verification code has been sent to`, + text2: `${blurrEmail()}.`, + text2Style: globalStyles.subtextBold, + text1Style: globalStyles.subtext, + position: 'bottom', + }); } }; const blurrEmail = () => { - if (user?.email) { - const length = user?.email?.split('@')[0].length; - return `${user?.email?.substring(0, 2)}*****${user?.email - ?.split('@')[0] - .substring(length - 1, length)}@${user?.email?.split('@')[1]}`; - } - return 'your email'; + const length = email?.split('@')[0].length; + return `${email?.substring(0, 2)}*****${email + ?.split('@')[0] + .substring(length - 1, length)}@${email?.split('@')[1]}`; }; const renderBlurredEmail = () => { return {blurrEmail()}.; }; + if (email === '') { + return ; + } + return ( From 3f724dc68baad51566cb213a573e06cae4f224e7 Mon Sep 17 00:00:00 2001 From: Justin Lee <91563628+jjstnlee@users.noreply.github.com> Date: Wed, 27 Mar 2024 00:07:31 -0700 Subject: [PATCH 15/34] [auth] Style onboarding screen (#66) * Added birthday boxand link for skip button on onboarding * Revert "Added birthday boxand link for skip button on onboarding" This reverts commit 8fdf6d804782cc39f9deb904f296cf6296e68e31. Mistake yes * Revert "Revert "Added birthday boxand link for skip button on onboarding"" This reverts commit 7c2d1b5595e1be593c50752d0518bb9c37fb8ade. * Created Birthday input box placeholder, implemented Skip For Now Button, and styled according to Figma * Added pseduo birthday input button, implemented Skip For Now, and styled onboarding screen * Added back commented/changed out code and also fixed the screen to be white * Fix login button * Fix merge errors * Fixed requested changes Yur * Fix spacing * Fix UserSelectorInput height * Fix pronouns * Remove logs * Various style changes * Various style changes * Run prettier --------- Co-authored-by: Aditya Pawar Co-authored-by: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> --- package-lock.json | 2 +- package.json | 2 +- src/app/(tabs)/home/index.tsx | 4 +- src/app/auth/onboarding/index.tsx | 189 ++++++++++-------- src/app/auth/onboarding/styles.tsx | 28 ++- src/app/auth/signup/index.tsx | 6 +- src/app/auth/signup/styles.tsx | 6 +- src/app/settings/index.tsx | 59 +++--- src/app/settings/styles.tsx | 4 + .../UserSelectorInput/UserSelectorInput.tsx | 4 +- src/components/UserSelectorInput/styles.tsx | 8 +- .../UserStringInput/UserStringInput.tsx | 4 +- 12 files changed, 169 insertions(+), 147 deletions(-) diff --git a/package-lock.json b/package-lock.json index 93232be4..b1f5b69e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "@mui/styled-engine-sc": "^6.0.0-alpha.1", "@mui/system": "^5.14.13", "@react-native-async-storage/async-storage": "^1.18.2", - "@react-native-community/datetimepicker": "7.2.0", + "@react-native-community/datetimepicker": "^7.2.0", "@react-navigation/bottom-tabs": "^6.5.9", "@react-navigation/material-bottom-tabs": "^6.2.17", "@react-navigation/native": "^6.1.8", diff --git a/package.json b/package.json index 5518a736..7ba5f154 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@mui/styled-engine-sc": "^6.0.0-alpha.1", "@mui/system": "^5.14.13", "@react-native-async-storage/async-storage": "^1.18.2", - "@react-native-community/datetimepicker": "7.2.0", + "@react-native-community/datetimepicker": "^7.2.0", "@react-navigation/bottom-tabs": "^6.5.9", "@react-navigation/material-bottom-tabs": "^6.2.17", "@react-navigation/native": "^6.1.8", diff --git a/src/app/(tabs)/home/index.tsx b/src/app/(tabs)/home/index.tsx index 7c224297..81ffc8db 100644 --- a/src/app/(tabs)/home/index.tsx +++ b/src/app/(tabs)/home/index.tsx @@ -68,7 +68,7 @@ function HomeScreen() { contentContainerStyle={{ paddingHorizontal: 8 }} > - + {username ? `Welcome, ${username}` : 'Welcome!'} router.push('/settings')}> @@ -86,7 +86,7 @@ function HomeScreen() { {featuredStories.map(story => ( - - setShowDatePicker(false)} - date={displayDate} - display="inline" - isDarkModeEnabled={isDark} - themeVariant={isDark ? 'dark' : 'light'} - /> - - Welcome, {user?.user_metadata.username} - - - Input your profile information below. - - - - - This information is only used for outreach efforts, and will not be - visible to other users on the app. + + + + setShowDatePicker(false)} + date={displayDate} + display="inline" + isDarkModeEnabled={isDark} + themeVariant={isDark ? 'dark' : 'light'} + /> + + Welcome, {user?.user_metadata.username} - - - - { - setShowDatePicker(!showDatePicker); - }} - > - - + Input your profile information below. + + + + + This information is only used for outreach efforts, and will not + be visible to other users on the app. + + + + + { + setShowDatePicker(!showDatePicker); + }} > - - + + + + + + - + + + + - - - - - - - router.replace('/home')} - disabled={false} - /> - - + + + + + + Skip For Now + + + + ); } diff --git a/src/app/auth/onboarding/styles.tsx b/src/app/auth/onboarding/styles.tsx index 688d843b..6555413a 100644 --- a/src/app/auth/onboarding/styles.tsx +++ b/src/app/auth/onboarding/styles.tsx @@ -4,35 +4,41 @@ import colors from '../../../styles/colors'; export default StyleSheet.create({ container: { - flex: 1, backgroundColor: 'white', + flex: 1, + }, + flex: { + flexGrow: 1, + justifyContent: 'space-between', paddingTop: 64, - paddingLeft: 44, + paddingBottom: 54, + paddingLeft: 43, paddingRight: 44, }, - verticallySpaced: { + inputContainer: { flex: 1, - justifyContent: 'space-between', - }, - datePickerButton: { - paddingBottom: 16, + gap: 16, }, subtext: { color: colors.darkGrey, marginLeft: 8, }, - h1: { - marginTop: 66, - }, body1: { marginTop: 26, }, info: { flexDirection: 'row', marginTop: 12, - marginBottom: 16, width: 250, }, + updateProfileButton: { + marginBottom: 24, + }, + skipButton: { + flex: 1, + alignSelf: 'center', + color: colors.darkGrey, + }, icon: { paddingLeft: 8, }, diff --git a/src/app/auth/signup/index.tsx b/src/app/auth/signup/index.tsx index f7c9506f..84a9e511 100644 --- a/src/app/auth/signup/index.tsx +++ b/src/app/auth/signup/index.tsx @@ -262,12 +262,12 @@ function SignUpScreen() { onPress={signUpWithEmail} /> - - Already have an account?{' '} + + Already have an account? Log In - + diff --git a/src/app/auth/signup/styles.tsx b/src/app/auth/signup/styles.tsx index 600bcb26..51de2d40 100644 --- a/src/app/auth/signup/styles.tsx +++ b/src/app/auth/signup/styles.tsx @@ -14,9 +14,11 @@ export default StyleSheet.create({ textDecorationLine: 'underline', }, redirectText: { - textAlign: 'center', - marginBottom: 64, + gap: 8, + flexDirection: 'row', + justifyContent: 'center', marginTop: 16, + marginBottom: 64, }, title: { paddingTop: 64, diff --git a/src/app/settings/index.tsx b/src/app/settings/index.tsx index bd846b2b..40f501ad 100644 --- a/src/app/settings/index.tsx +++ b/src/app/settings/index.tsx @@ -57,7 +57,7 @@ function SettingsScreen() { const { data, error, status } = await supabase .from('profiles') .select( - `first_name, last_name, username, birthday, gender, race_ethnicity`, + `first_name, last_name, username, birthday, gender, race_ethnicity, pronouns`, ) .eq('user_id', session?.user.id) .single(); @@ -81,7 +81,7 @@ function SettingsScreen() { } setGender(data.gender || gender); - // setPronouns(data.pronouns || pronouns); + setPronouns(data.pronouns || pronouns); setRaceEthnicity(data.race_ethnicity || raceEthnicity); } } catch (error) { @@ -115,8 +115,6 @@ function SettingsScreen() { // Only update values that are not blank const updates = { - ...(firstName && { first_name: firstName }), - ...(lastName && { last_name: lastName }), ...(gender && { gender }), ...(pronouns && { pronouns }), ...(raceEthnicity && { race_ethnicity: raceEthnicity }), @@ -189,7 +187,6 @@ function SettingsScreen() { {' - - - - + + + + + {birthdayChanged && ( diff --git a/src/app/settings/styles.tsx b/src/app/settings/styles.tsx index 580f7838..944c1819 100644 --- a/src/app/settings/styles.tsx +++ b/src/app/settings/styles.tsx @@ -2,6 +2,10 @@ import { StyleSheet } from 'react-native'; import colors from '../../styles/colors'; export default StyleSheet.create({ + selectors: { + flex: 1, + gap: 16, + }, container: { flex: 1, backgroundColor: 'white', diff --git a/src/components/UserSelectorInput/UserSelectorInput.tsx b/src/components/UserSelectorInput/UserSelectorInput.tsx index dd5be4fc..a032b1ab 100644 --- a/src/components/UserSelectorInput/UserSelectorInput.tsx +++ b/src/components/UserSelectorInput/UserSelectorInput.tsx @@ -24,7 +24,7 @@ function UserSelectorInput({ value, }: UserSelectorInputProps) { return ( - + {label} ( diff --git a/src/components/UserSelectorInput/styles.tsx b/src/components/UserSelectorInput/styles.tsx index ad54c0ab..734f782b 100644 --- a/src/components/UserSelectorInput/styles.tsx +++ b/src/components/UserSelectorInput/styles.tsx @@ -10,17 +10,15 @@ export default StyleSheet.create({ position: 'relative', zIndex: 1, }, - container: { - marginBottom: 16, - }, label: { - marginBottom: 10, + marginBottom: 8, }, dropdown: { - height: 50, + height: 44, borderWidth: 1, borderRadius: 5, paddingHorizontal: 10, + paddingVertical: 10, }, dropdownContainer: { borderRadius: 5, diff --git a/src/components/UserStringInput/UserStringInput.tsx b/src/components/UserStringInput/UserStringInput.tsx index f7cd12d6..6d2d586b 100644 --- a/src/components/UserStringInput/UserStringInput.tsx +++ b/src/components/UserStringInput/UserStringInput.tsx @@ -2,8 +2,8 @@ import { ReactNode } from 'react'; import { View, Text, TextInput } from 'react-native'; import styles from './styles'; -import globalStyles from '../../styles/globalStyles'; import colors from '../../styles/colors'; +import globalStyles from '../../styles/globalStyles'; type UserStringInputProps = { placeholder: string; @@ -23,7 +23,7 @@ export default function UserStringInput({ label, children, labelColor = '#000', - placeholderTextColor = '#000', + placeholderTextColor = colors.darkGrey, onChange = _ => {}, }: UserStringInputProps) { return ( From 9a84783aa056b5eb69d8cc5ad2274be5c3910eee Mon Sep 17 00:00:00 2001 From: emilysunaryo <99292788+emilysunaryo@users.noreply.github.com> Date: Thu, 28 Mar 2024 21:58:50 -0700 Subject: [PATCH 16/34] [reactions] Database schema changes for reacting to stories (#65) * committing changes from previous branch * finished queries for reactions * fixing merge conflicts * Fix compiler error --------- Co-authored-by: Aditya Pawar --- src/queries/reactions.tsx | 79 +++++++++++++++++++++++++++++++++++++++ src/queries/stories.tsx | 16 ++++++++ src/queries/types.tsx | 15 ++++++++ 3 files changed, 110 insertions(+) create mode 100644 src/queries/reactions.tsx diff --git a/src/queries/reactions.tsx b/src/queries/reactions.tsx new file mode 100644 index 00000000..8a9da888 --- /dev/null +++ b/src/queries/reactions.tsx @@ -0,0 +1,79 @@ +import { Reactions } from './types'; +import supabase from '../utils/supabase'; + +export async function addReactionToStory( + input_profile_id: number, + input_story_id: number, + input_reaction_id: number, +): Promise { + const { data, error } = await supabase.rpc('add_reaction_to_story', { + story_id: input_story_id, + profile_id: input_profile_id, + reaction_id: input_reaction_id, + }); + if (error) { + console.log(error); + throw new Error( + `An error occured when trying to insert author reaction to story: ${error}`, + ); + } else { + return data; + } +} + +export async function deleteReactionToStory( + input_profile_id: number, + input_story_id: number, + input_reaction_id: number, +): Promise { + const { data, error } = await supabase.rpc('remove_reaction_from_story', { + story_id: input_story_id, + profile_id: input_profile_id, + reaction_id: input_reaction_id, + }); + if (error) { + console.log(error); + throw new Error( + `An error occured when trying to delete reaction to story by a user: ${error}`, + ); + } else { + return data; + } +} + +export async function fetchAllReactionsToStory( + storyId: number, +): Promise { + const { data, error } = await supabase.rpc('curr_get_reactions_for_story', { + input_story_id: storyId, + }); + if (error) { + console.log(error); + throw new Error( + `An error occured when trying to fetch reactions to a story', ${error}`, + ); + } else { + return data; + } +} + +export async function fetchReactionsToStoryByUser( + story_id: number, + profile_id: number, +): Promise { + const { data, error } = await supabase.rpc( + 'get_reactions_for_user_and_story', + { + _story_id: story_id, + _profile_id: profile_id, + }, + ); + if (error) { + console.log(error); + throw new Error( + `An error occured when trying to fetch reactions for user and story ${error}`, + ); + } else { + return data; + } +} diff --git a/src/queries/stories.tsx b/src/queries/stories.tsx index e9fd3683..86747ad9 100644 --- a/src/queries/stories.tsx +++ b/src/queries/stories.tsx @@ -82,3 +82,19 @@ export async function fetchNewStories(): Promise { return data; } } + +export async function fetchStoryPreviewById( + storyId: number, +): Promise { + const { data, error } = await supabase.rpc('curr_story_preview_by_id', { + input_story_id: storyId, + }); + if (error) { + console.log(error); + throw new Error( + `An error occured when trying to fetch story preview by ID: ${error}`, + ); + } else { + return data; + } +} diff --git a/src/queries/types.tsx b/src/queries/types.tsx index 04ec7d19..55821c54 100644 --- a/src/queries/types.tsx +++ b/src/queries/types.tsx @@ -59,3 +59,18 @@ export interface Genre { parent_name: string; subgenres: Subgenre[]; } + +export interface GenreStories { + parent_id: number; + parent_name: string; + subgenre_id: number; + subgenre_name: string; + genre_story_previews: string[]; +} + +export interface Reactions { + profile_id: number; + story_id: number; + emoji_id: number; + emoji: string; +} From 9470964cf3bdeeb2d24d01aadec8312fa708c305 Mon Sep 17 00:00:00 2001 From: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> Date: Fri, 29 Mar 2024 00:51:07 -0700 Subject: [PATCH 17/34] [chore] Standardize fonts for other files (#75) * Finish standardizing story page * Finish authors page * Finish standardizing fonts * Run prettier --- src/app/(tabs)/author/index.tsx | 14 +++-- src/app/(tabs)/author/styles.tsx | 21 +------- src/app/(tabs)/story/index.tsx | 45 +++++++++++----- src/app/(tabs)/story/styles.ts | 54 ++----------------- .../AccountDataDisplay/AccountDataDisplay.tsx | 5 +- src/components/AccountDataDisplay/styles.tsx | 7 --- src/components/UserStringInput/styles.tsx | 1 - src/styles/globalStyles.ts | 8 +++ 8 files changed, 56 insertions(+), 99 deletions(-) diff --git a/src/app/(tabs)/author/index.tsx b/src/app/(tabs)/author/index.tsx index 9b8065c5..c460e112 100644 --- a/src/app/(tabs)/author/index.tsx +++ b/src/app/(tabs)/author/index.tsx @@ -76,12 +76,14 @@ function AuthorScreen() { {authorInfo.name} {authorInfo?.pronouns && ( - {authorInfo.pronouns} + + {authorInfo.pronouns} + )} )} @@ -91,17 +93,19 @@ function AuthorScreen() { {authorInfo?.bio && ( <> - {decode(authorInfo.bio)} + {decode(authorInfo.bio)} )} {authorInfo?.artist_statement && ( <> - + Artist's Statement - + {decode(authorInfo.artist_statement)} diff --git a/src/app/(tabs)/author/styles.tsx b/src/app/(tabs)/author/styles.tsx index d85a4dd7..213b9e7b 100644 --- a/src/app/(tabs)/author/styles.tsx +++ b/src/app/(tabs)/author/styles.tsx @@ -10,28 +10,12 @@ const styles = StyleSheet.create({ justifyContent: 'flex-start', alignItems: 'flex-end', }, - name: { - fontWeight: 'bold', - fontSize: 24, - fontFamily: 'Manrope-Regular', - }, image: { height: 68, width: 68, backgroundColor: colors.darkGrey, borderRadius: 4, }, - bioText: { - color: 'black', - fontFamily: 'Manrope-Regular', - fontSize: 14, - }, - authorStatement: { - fontSize: 14, - color: 'black', - fontWeight: '400', - fontFamily: 'Manrope-Regular', - }, authorTextContainer: { paddingLeft: 20, }, @@ -40,9 +24,6 @@ const styles = StyleSheet.create({ borderTopWidth: 20, }, authorStatementTitle: { - fontWeight: 'bold', - fontFamily: 'Manrope-Regular', - fontSize: 16, marginBottom: 8, }, storyCountText: { @@ -50,7 +31,7 @@ const styles = StyleSheet.create({ marginBottom: 8, }, pronouns: { - color: '#797979', + color: colors.textGrey, }, }); diff --git a/src/app/(tabs)/story/index.tsx b/src/app/(tabs)/story/index.tsx index 646a1e4a..a3505219 100644 --- a/src/app/(tabs)/story/index.tsx +++ b/src/app/(tabs)/story/index.tsx @@ -18,6 +18,8 @@ import { SafeAreaView } from 'react-native-safe-area-context'; import styles from './styles'; import { fetchStory } from '../../../queries/stories'; import { Story } from '../../../queries/types'; +import colors from '../../../styles/colors'; +import globalStyles, { fonts } from '../../../styles/globalStyles'; function StoryScreen() { const [isLoading, setLoading] = useState(true); @@ -74,7 +76,7 @@ function StoryScreen() { > {/* */} - {story?.title} + {story?.title} { router.push({ @@ -88,7 +90,9 @@ function StoryScreen() { style={styles.authorImage} source={{ uri: story.author_image ? story.author_image : '' }} /> - By {story.author_name} + + By {story.author_name} + @@ -99,50 +103,63 @@ function StoryScreen() { data={story.genre_medium} renderItem={({ item }) => ( - {item} + + {item} + )} /> - Author's Process + + Author's Process + @@ -150,7 +167,9 @@ function StoryScreen() { style={styles.authorImage} source={{ uri: story.author_image }} /> - By {story.author_name} + + By {story.author_name} + )} diff --git a/src/app/(tabs)/story/styles.ts b/src/app/(tabs)/story/styles.ts index cbe432a8..9a173b05 100644 --- a/src/app/(tabs)/story/styles.ts +++ b/src/app/(tabs)/story/styles.ts @@ -1,4 +1,5 @@ import { StyleSheet } from 'react-native'; +import colors from '../../../styles/colors'; const styles = StyleSheet.create({ container: { @@ -22,11 +23,6 @@ const styles = StyleSheet.create({ borderRadius: 100 / 2, }, title: { - fontFamily: 'Manrope-Regular', - fontSize: 24, - fontWeight: '400', - textAlign: 'left', - color: 'black', marginBottom: 16, }, author: { @@ -35,13 +31,6 @@ const styles = StyleSheet.create({ gap: 10, marginBottom: 16, }, - authorText: { - fontFamily: 'Manrope-Regular', - fontSize: 12, - fontWeight: '400', - textAlign: 'left', - color: 'black', - }, genres: { display: 'flex', flexDirection: 'row', @@ -59,61 +48,24 @@ const styles = StyleSheet.create({ marginRight: 8, }, genresText: { - fontFamily: 'Manrope-Regular', - fontSize: 12, - fontWeight: '400', - color: 'black', backgroundColor: '#D9D9D9', }, shareButtonText: { - fontFamily: 'Manrope-Regular', - fontSize: 12, - fontWeight: '400', - textAlign: 'left', - color: 'black', - textDecorationLine: 'underline', - backgroundColor: '#D9D9D9', + color: colors.white, }, excerpt: { - fontFamily: 'Manrope-Regular', - fontSize: 16, - fontWeight: '400', textAlign: 'left', - color: 'black', - paddingTop: 16, - paddingBottom: 16, + paddingVertical: 16, }, story: { - fontFamily: 'Manrope-Regular', - fontSize: 12, - fontWeight: '400', - textAlign: 'left', - color: 'black', marginBottom: 16, }, authorProcess: { - fontFamily: 'Manrope-Regular', - fontSize: 16, - fontWeight: '600', - textAlign: 'left', - color: 'black', marginBottom: 16, }, process: { - fontFamily: 'Manrope-Regular', - fontSize: 12, - fontWeight: '400', - textAlign: 'left', - color: 'black', marginBottom: 16, }, - backToTopButtonText: { - fontFamily: 'Manrope-Regular', - fontSize: 12, - fontWeight: '800', - textAlign: 'left', - color: 'black', - }, }); export default styles; diff --git a/src/components/AccountDataDisplay/AccountDataDisplay.tsx b/src/components/AccountDataDisplay/AccountDataDisplay.tsx index a2d464f3..4faccfff 100644 --- a/src/components/AccountDataDisplay/AccountDataDisplay.tsx +++ b/src/components/AccountDataDisplay/AccountDataDisplay.tsx @@ -1,6 +1,7 @@ import { View, Text } from 'react-native'; import styles from './styles'; +import globalStyles from '../../styles/globalStyles'; type AccountDataDisplayProps = { label: string; @@ -10,9 +11,9 @@ type AccountDataDisplayProps = { function AccountDataDisplay({ label, value }: AccountDataDisplayProps) { return ( - {label} + {label} {typeof value === 'string' ? ( - {value} + {value} ) : ( value )} diff --git a/src/components/AccountDataDisplay/styles.tsx b/src/components/AccountDataDisplay/styles.tsx index 5d769230..78da8ddb 100644 --- a/src/components/AccountDataDisplay/styles.tsx +++ b/src/components/AccountDataDisplay/styles.tsx @@ -8,18 +8,11 @@ export default StyleSheet.create({ marginBottom: 26, }, label: { - fontSize: 12, - fontFamily: 'Manrope-Regular', - fontStyle: 'normal', - fontWeight: '400', color: colors.textGrey, }, value: { paddingTop: 18, paddingRight: 20, fontSize: 14, - fontFamily: 'Manrope-Regular', - fontStyle: 'normal', - fontWeight: '400', }, }); diff --git a/src/components/UserStringInput/styles.tsx b/src/components/UserStringInput/styles.tsx index a11509d5..5642a55e 100644 --- a/src/components/UserStringInput/styles.tsx +++ b/src/components/UserStringInput/styles.tsx @@ -14,7 +14,6 @@ export default StyleSheet.create({ borderWidth: 1, borderRadius: 5, borderColor: 'black', - fontFamily: 'Manrope-Regular', }, inputField: { flex: 1, diff --git a/src/styles/globalStyles.ts b/src/styles/globalStyles.ts index ef9e2cb3..12e17283 100644 --- a/src/styles/globalStyles.ts +++ b/src/styles/globalStyles.ts @@ -79,6 +79,12 @@ export default StyleSheet.create({ textAlign: 'left', color: 'black', }, + body2Bold: { + fontFamily: 'Manrope-Bold', + fontSize: 16, + textAlign: 'left', + color: 'black', + }, body3: { fontFamily: 'Manrope-Regular', fontSize: 18, @@ -135,3 +141,5 @@ export default StyleSheet.create({ marginTop: 20, }, }); + +export const fonts = ['Manrope-Bold', 'Manrope-Regular', 'Manrope-Semibold']; From 02bcb3059ab4bcd2f102aae647d507da5edd0541 Mon Sep 17 00:00:00 2001 From: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> Date: Fri, 29 Mar 2024 00:54:14 -0700 Subject: [PATCH 18/34] Fix router call (#76) --- src/app/auth/signup/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/auth/signup/index.tsx b/src/app/auth/signup/index.tsx index 84a9e511..fbaeb5cd 100644 --- a/src/app/auth/signup/index.tsx +++ b/src/app/auth/signup/index.tsx @@ -130,7 +130,7 @@ function SignUpScreen() { if (error) Alert.alert(error.message); else - router.push({ + router.replace({ pathname: '/auth/verify', params: { finalRedirect: 'onboarding' }, }); From 06a6101b5c5cbffaf8d7512a3d79c47693be49a6 Mon Sep 17 00:00:00 2001 From: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> Date: Mon, 1 Apr 2024 17:33:57 -0700 Subject: [PATCH 19/34] Fix going back to login from home bug (#77) --- src/app/auth/onboarding/index.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/auth/onboarding/index.tsx b/src/app/auth/onboarding/index.tsx index a514b849..936624fb 100644 --- a/src/app/auth/onboarding/index.tsx +++ b/src/app/auth/onboarding/index.tsx @@ -128,6 +128,9 @@ function OnboardingScreen() { } } + while (router.canGoBack()) { + router.back(); + } router.replace('/home'); } catch (error) { if (error instanceof Error) { From 3c28469bec52c40b93a26c616b5bf6dbd8167c89 Mon Sep 17 00:00:00 2001 From: Marcoss28 <69034384+Marcoss28@users.noreply.github.com> Date: Wed, 3 Apr 2024 20:40:45 -0700 Subject: [PATCH 20/34] [home] Update content card (#63) * accidently forgot to branch * merging * fixing scaling * need to create add reactions and plus button * fixed Content Card to new look, however having trouble styling the authors * included temporary author image to style * Higher res + image * accidently forgot to branch * merging * fixing scaling * need to create add reactions and plus button * fixed Content Card to new look, however having trouble styling the authors * included temporary author image to style * resolved PR * Run prettier * Fix search screen key error * Live author images * Small style changes * Run prettier --------- Co-authored-by: Marcos Hernandez Co-authored-by: Aditya Pawar Co-authored-by: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> --- src/app/(tabs)/author/index.tsx | 1 - src/app/(tabs)/home/index.tsx | 7 +- src/app/(tabs)/home/styles.ts | 10 ++- src/app/(tabs)/search/index.tsx | 7 +- src/app/(tabs)/story/index.tsx | 3 +- src/app/(tabs)/story/styles.ts | 5 -- src/components/ContentCard/ContentCard.tsx | 66 ++++++++++++++++-- .../ContentCard/savedStoriesIcon.png | Bin 0 -> 1052 bytes src/components/ContentCard/styles.ts | 62 +++++++++++++++- src/components/PreviewCard/PreviewCard.tsx | 2 +- src/queries/types.tsx | 1 + 11 files changed, 141 insertions(+), 23 deletions(-) create mode 100644 src/components/ContentCard/savedStoriesIcon.png diff --git a/src/app/(tabs)/author/index.tsx b/src/app/(tabs)/author/index.tsx index c460e112..12c5bc73 100644 --- a/src/app/(tabs)/author/index.tsx +++ b/src/app/(tabs)/author/index.tsx @@ -6,7 +6,6 @@ import { SafeAreaView } from 'react-native-safe-area-context'; import styles from './styles'; import BackButton from '../../../components/BackButton/BackButton'; -import ContentCard from '../../../components/ContentCard/ContentCard'; import HorizontalLine from '../../../components/HorizontalLine/HorizontalLine'; import PreviewCard from '../../../components/PreviewCard/PreviewCard'; import { diff --git a/src/app/(tabs)/home/index.tsx b/src/app/(tabs)/home/index.tsx index 81ffc8db..c2517b49 100644 --- a/src/app/(tabs)/home/index.tsx +++ b/src/app/(tabs)/home/index.tsx @@ -43,6 +43,7 @@ function HomeScreen() { fetchRecommendedStories().catch(() => []), fetchNewStories().catch(() => []), ]); + setUsername(usernameResponse); setFeaturedStories(featuredStoryResponse); setFeaturedStoriesDescription(featuredStoryDescriptionResponse); @@ -115,13 +116,14 @@ function HomeScreen() { horizontal showsHorizontalScrollIndicator={false} bounces={false} - style={styles.scrollView} + style={styles.scrollView1} > {recommendedStories.map(story => ( router.push({ pathname: '/story', @@ -143,13 +145,14 @@ function HomeScreen() { horizontal showsHorizontalScrollIndicator={false} bounces={false} - style={styles.scrollView} + style={styles.scrollView2} > {newStories.map(story => ( router.push({ pathname: '/story', diff --git a/src/app/(tabs)/home/styles.ts b/src/app/(tabs)/home/styles.ts index 231f5d9d..e24896bc 100644 --- a/src/app/(tabs)/home/styles.ts +++ b/src/app/(tabs)/home/styles.ts @@ -19,9 +19,15 @@ const styles = StyleSheet.create({ marginTop: 12, marginBottom: 16, }, - scrollView: { - marginBottom: 20, + scrollView1: { + paddingBottom: 16, flexGrow: 0, + padding: 8, + }, + scrollView2: { + paddingBottom: 80, + flexGrow: 0, + padding: 8, }, headerContainer: { flexDirection: 'row', diff --git a/src/app/(tabs)/search/index.tsx b/src/app/(tabs)/search/index.tsx index 23450af4..337119a7 100644 --- a/src/app/(tabs)/search/index.tsx +++ b/src/app/(tabs)/search/index.tsx @@ -1,7 +1,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage'; import { SearchBar } from '@rneui/themed'; import { router } from 'expo-router'; -import { useEffect, useState } from 'react'; +import { Fragment, useEffect, useState } from 'react'; import { Button, FlatList, @@ -286,7 +286,7 @@ function SearchScreen() { contentContainerStyle={{ paddingHorizontal: 8 }} > {allGenres.map((genre, index) => ( - <> + {genre.parent_name} See All @@ -299,13 +299,14 @@ function SearchScreen() { > {genre.subgenres.map(subgenre => ( null} /> ))} - + ))} ) : ( diff --git a/src/app/(tabs)/story/index.tsx b/src/app/(tabs)/story/index.tsx index a3505219..73cbdfef 100644 --- a/src/app/(tabs)/story/index.tsx +++ b/src/app/(tabs)/story/index.tsx @@ -74,9 +74,8 @@ function StoryScreen() { ref={scrollRef} showsVerticalScrollIndicator={false} > - {/* */} - {story?.title} + { router.push({ diff --git a/src/app/(tabs)/story/styles.ts b/src/app/(tabs)/story/styles.ts index 9a173b05..7e6e2c8c 100644 --- a/src/app/(tabs)/story/styles.ts +++ b/src/app/(tabs)/story/styles.ts @@ -11,11 +11,6 @@ const styles = StyleSheet.create({ paddingRight: 24, paddingTop: 48, }, - image: { - width: '100%', - height: 153, - marginBottom: 16, - }, authorImage: { backgroundColor: '#D9D9D9', width: 21, diff --git a/src/components/ContentCard/ContentCard.tsx b/src/components/ContentCard/ContentCard.tsx index 99486907..4301cb9f 100644 --- a/src/components/ContentCard/ContentCard.tsx +++ b/src/components/ContentCard/ContentCard.tsx @@ -4,6 +4,7 @@ import { Pressable, Text, View, + TouchableOpacity, } from 'react-native'; import styles from './styles'; @@ -13,6 +14,7 @@ type ContentCardProps = { title: string; author: string; image: string; + authorImage: string; pressFunction: (event: GestureResponderEvent) => void; }; @@ -20,19 +22,73 @@ function ContentCard({ title, author, image, + authorImage, pressFunction, }: ContentCardProps) { + const saveStory = () => { + console.log("testing '+' icon does something for story " + title); + }; + return ( - + + + + + - + {title} - - {author} - + + + By + + + {author} + + + + + null} + style={{ flexDirection: 'row' }} + > + + + + + + 14{/*change number to work*/} + + + + + saveStory()}> + + + diff --git a/src/components/ContentCard/savedStoriesIcon.png b/src/components/ContentCard/savedStoriesIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..65b2ea6e4dd47e1c590ef1cbe5d7afc29d8fcca7 GIT binary patch literal 1052 zcmV+%1mpXOP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91JfH&r1ONa40RR91JOBUy0E^%0TmS$AhDk(0RA>e5n@@7uFciimr$e`7 zhCjm&P7v1VhMpkVWYbNP6Eryi^aM>$(8;zeN=^{ENH^V(6Qo@wfn;E^B&pr+b1h;E2p>P%^ zpbQq?-QDePZEbx)!+h{wlCB94d0Rp7Dd53i@ClWUJ+Q82S)K8Cd|s(k*x2~g@AvBv zl1CH3Rpd;qVzKz~->L8O;o+ePUuKrbW`fVi zqM-RzouJ&`-(P#ciMQ+o$~yrUE$teUld(|NMSdNuoR(_(yQfn;M+^dj^sVI7We(n$i%k7S&sd<5^duoYdS(=jKw9*6>g(U-yqNOC) z$t;{?>qU`$<1GA2r@nU*mXIMN=))V14f=4r*LT@(7=xLG;_HeuMsDMM!AIJIj+ z-`aK91W&7fuzLz$U`I&ND}KE^SwwMKU=uto54IuPy_rRDh0p@0&C}8Xm)bw*$iH1o zujaJQW@&S55sxI9h2znyIlX2UHpdq6NTS^USeB<1wpTUrpfqe!iaLA_ZvBkld~lhZ zpF%t`^;e5_9bT5F6}DG3@u235?{~1Uza|=*>cZb3SXT?YEKe(JugVe5m2@KfhX)Ho z@W>Wszd=xStsT;;;yUxe!J7-$vX1B$+n4|4^{FA9&C=_%S$Gv%UgtA13$IiA zt9W*1;ZQ8bmrI=+zT z9%pIy_a(shlL!-0X8zg|h$sEc;L`8BK;WetRm=0VB}580$ppr4fxLNn~&jVDeU zEM9H+KsFT*Zf$RGk1(8%JPkB`<2~{0FeYC?Y7t~69vrU$oKh3CHY3NAPD{&z$sM_P z-@%0@)71V7V0ptG@80a)V&HhGRB|UaHZVDHrOD-TdyttEaD%eK!k;1k#DG)4tbieX zh|K@q4~vtSMgTu5m&+Z$@H4>bCc$B4&fHZTbyaS1&QS@A_V9h}K0ZF4)oQg-P~N|w WSfpXwp?D_%0000 Date: Thu, 4 Apr 2024 18:07:13 -0700 Subject: [PATCH 21/34] [search] Update search styling (#74) * accidently forgot to branch * updated search styling and added screens for when there are no search results and no recent searches/stories * chnages made * changes made to color options * Small style changes * Run prettier --------- Co-authored-by: Marcos Hernandez Co-authored-by: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> Co-authored-by: Aditya Pawar --- src/app/(tabs)/home/index.tsx | 1 + src/app/(tabs)/search/index.tsx | 76 +++++++++++++++---- src/app/(tabs)/search/styles.ts | 26 ++++--- src/components/PreviewCard/styles.ts | 4 +- .../RecentSearchCard/RecentSearchCard.tsx | 8 +- src/components/RecentSearchCard/styles.ts | 11 ++- src/styles/colors.ts | 1 + 7 files changed, 92 insertions(+), 35 deletions(-) diff --git a/src/app/(tabs)/home/index.tsx b/src/app/(tabs)/home/index.tsx index c2517b49..871b0eed 100644 --- a/src/app/(tabs)/home/index.tsx +++ b/src/app/(tabs)/home/index.tsx @@ -78,6 +78,7 @@ function HomeScreen() { + {featuredStories.length > 0 && ( Featured Stories diff --git a/src/app/(tabs)/search/index.tsx b/src/app/(tabs)/search/index.tsx index 337119a7..fd64c5b7 100644 --- a/src/app/(tabs)/search/index.tsx +++ b/src/app/(tabs)/search/index.tsx @@ -190,18 +190,21 @@ function SearchScreen() { setShowRecents(true); setShowGenreCarousals(false); }} - searchIcon={false} - clearIcon + searchIcon + clearIcon={false} + cancelButtonProps={{ + buttonTextStyle: [globalStyles.body1Bold, styles.cancelButton], + }} containerStyle={[ styles.searchContainer, showGenreCarousals && { marginRight: 24 }, ]} inputContainerStyle={styles.inputContainer} - inputStyle={{ color: 'black' }} + inputStyle={globalStyles.body1Bold} leftIconContainerStyle={{}} rightIconContainerStyle={{}} - placeholder="Search" - placeholderTextColor="black" + placeholder="What do you want to read?" + placeholderTextColor="grey" onChangeText={text => searchFunction(text)} value={search} onSubmitEditing={searchString => { @@ -222,19 +225,44 @@ function SearchScreen() { )} {showRecents && - (search ? ( + (search && searchResults.length > 0 ? ( - - {searchResults.length}{' '} - {searchResults.length === 1 ? 'Story' : 'Stories'} + + Showing results 1-{searchResults.length} - ) : ( + ) : search && searchResults.length === 0 ? ( + + + + There are no stories + + + for "{search}". + + + + Try searching by title or author, or + + + check if your spelling is correct. + + + ) : recentSearches.length > 0 || recentlyViewed.length > 0 ? ( - Recent Searches + + Recent Searches + - Clear All + + Clear All + @@ -252,9 +280,18 @@ function SearchScreen() { - Recently Viewed + + Recently Viewed + - Clear All + + Clear All + @@ -278,6 +315,17 @@ function SearchScreen() { ))} + ) : ( + + + + Find stories from young creators. + + + + Search for stories, authors, or collections. + + ))} {showGenreCarousals ? ( diff --git a/src/app/(tabs)/search/styles.ts b/src/app/(tabs)/search/styles.ts index 648752e0..c1d184be 100644 --- a/src/app/(tabs)/search/styles.ts +++ b/src/app/(tabs)/search/styles.ts @@ -16,12 +16,15 @@ const styles = StyleSheet.create({ searchContainer: { backgroundColor: 'transparent', borderRadius: 10, - borderColor: 'transparent', marginBottom: 8, + borderColor: colors.grey, }, inputContainer: { - backgroundColor: '#D9D9D9', + backgroundColor: 'transparent', borderRadius: 10, + borderColor: colors.grey2, + borderWidth: 1, + borderBottomWidth: 1, }, greyOverlay: { flex: 1, @@ -51,19 +54,10 @@ const styles = StyleSheet.create({ marginBottom: 8, marginHorizontal: 8, }, - searchText: { - fontWeight: '500', - fontSize: 14, - }, numDisplay: { marginTop: 24, marginBottom: 8, }, - clearAll: { - color: colors.gwnOrange, - fontSize: 12, - fontWeight: '400', - }, contentContainerRecents: { paddingHorizontal: 8, marginBottom: 8, @@ -86,6 +80,16 @@ const styles = StyleSheet.create({ fontSize: 12, textDecorationLine: 'underline', }, + emptySearch: { + display: 'flex', + flexDirection: 'column', + textAlign: 'center', + alignItems: 'center', + marginTop: '60%', + }, + cancelButton: { + color: colors.grey, + }, }); export default styles; diff --git a/src/components/PreviewCard/styles.ts b/src/components/PreviewCard/styles.ts index d69aae26..e8af8f2c 100644 --- a/src/components/PreviewCard/styles.ts +++ b/src/components/PreviewCard/styles.ts @@ -11,8 +11,8 @@ const styles = StyleSheet.create({ marginTop: 8, marginBottom: 8, shadowColor: 'black', - shadowOffset: { width: 0, height: 4 }, - shadowOpacity: 0.5, + shadowOffset: { width: 0, height: 0 }, + shadowOpacity: 0.2, elevation: 4, }, image: { diff --git a/src/components/RecentSearchCard/RecentSearchCard.tsx b/src/components/RecentSearchCard/RecentSearchCard.tsx index eb77fcc6..e142baee 100644 --- a/src/components/RecentSearchCard/RecentSearchCard.tsx +++ b/src/components/RecentSearchCard/RecentSearchCard.tsx @@ -21,10 +21,14 @@ function RecentSearchCard({ - {value} + + {value} + - {numResults} Results + + {numResults} Results + diff --git a/src/components/RecentSearchCard/styles.ts b/src/components/RecentSearchCard/styles.ts index 676937de..b0cb9012 100644 --- a/src/components/RecentSearchCard/styles.ts +++ b/src/components/RecentSearchCard/styles.ts @@ -1,4 +1,5 @@ import { StyleSheet } from 'react-native'; +import colors from '../../styles/colors'; const styles = StyleSheet.create({ card: { @@ -13,10 +14,11 @@ const styles = StyleSheet.create({ paddingRight: 12, paddingBottom: 10, paddingTop: 10, + shadowColor: 'black', - shadowOffset: { width: 0, height: 4 }, - shadowOpacity: 0.5, - elevation: 4, + shadowOffset: { width: 0, height: 0 }, + shadowOpacity: 0.3, + elevation: 7, }, leftItems: { gap: 8, @@ -29,9 +31,6 @@ const styles = StyleSheet.create({ alignItems: 'center', }, searchValueText: { - color: 'black', - fontWeight: '400', - fontSize: 14, justifyContent: 'center', }, numResultsText: { diff --git a/src/styles/colors.ts b/src/styles/colors.ts index 73d10142..af1f15f4 100644 --- a/src/styles/colors.ts +++ b/src/styles/colors.ts @@ -14,6 +14,7 @@ const colors = { fadedBlack: '#2D2D2D', white: '#FBFBFB', grey: '#A7A5A5', + grey2: '#D9D9D9', darkGrey: '#797979', textPrimary: '#000000', // black From 9a3d7077df3e634b88c3ead0e78552ea1932b11b Mon Sep 17 00:00:00 2001 From: Kyle Ramachandran <156966341+kylezryr@users.noreply.github.com> Date: Thu, 4 Apr 2024 18:34:26 -0700 Subject: [PATCH 22/34] [setting] Update setting style (#78) * updated styling * Small style changes --------- Co-authored-by: Kyle Ramachandran Co-authored-by: Aditya Pawar --- src/app/(tabs)/_layout.tsx | 9 ++++++++- src/app/{ => (tabs)}/settings/_layout.tsx | 0 src/app/{ => (tabs)}/settings/index.tsx | 19 +++++++++++-------- src/app/{ => (tabs)}/settings/styles.tsx | 2 +- src/app/_layout.tsx | 1 - src/components/StyledButton/styles.tsx | 2 +- 6 files changed, 21 insertions(+), 12 deletions(-) rename src/app/{ => (tabs)}/settings/_layout.tsx (100%) rename src/app/{ => (tabs)}/settings/index.tsx (94%) rename src/app/{ => (tabs)}/settings/styles.tsx (96%) diff --git a/src/app/(tabs)/_layout.tsx b/src/app/(tabs)/_layout.tsx index 3040918a..c496d43f 100644 --- a/src/app/(tabs)/_layout.tsx +++ b/src/app/(tabs)/_layout.tsx @@ -1,5 +1,5 @@ import { Tabs } from 'expo-router'; -import { Platform } from 'react-native'; +import { Platform, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import Icon from '../../../assets/icons'; @@ -88,6 +88,13 @@ function TabNav() { tabBarIcon: ({ color }) => LibraryIcon({ color }), }} /> + ); } diff --git a/src/app/settings/_layout.tsx b/src/app/(tabs)/settings/_layout.tsx similarity index 100% rename from src/app/settings/_layout.tsx rename to src/app/(tabs)/settings/_layout.tsx diff --git a/src/app/settings/index.tsx b/src/app/(tabs)/settings/index.tsx similarity index 94% rename from src/app/settings/index.tsx rename to src/app/(tabs)/settings/index.tsx index 40f501ad..10bf4af9 100644 --- a/src/app/settings/index.tsx +++ b/src/app/(tabs)/settings/index.tsx @@ -13,13 +13,13 @@ import { SafeAreaView } from 'react-native-safe-area-context'; import { Icon } from 'react-native-elements'; import styles from './styles'; -import colors from '../../styles/colors'; -import AccountDataDisplay from '../../components/AccountDataDisplay/AccountDataDisplay'; -import StyledButton from '../../components/StyledButton/StyledButton'; -import UserSelectorInput from '../../components/UserSelectorInput/UserSelectorInput'; -import globalStyles from '../../styles/globalStyles'; -import { useSession } from '../../utils/AuthContext'; -import supabase from '../../utils/supabase'; +import colors from '../../../styles/colors'; +import AccountDataDisplay from '../../../components/AccountDataDisplay/AccountDataDisplay'; +import StyledButton from '../../../components/StyledButton/StyledButton'; +import UserSelectorInput from '../../../components/UserSelectorInput/UserSelectorInput'; +import globalStyles from '../../../styles/globalStyles'; +import { useSession } from '../../../utils/AuthContext'; +import supabase from '../../../utils/supabase'; import DateTimePickerModal from 'react-native-modal-datetime-picker'; function SettingsScreen() { @@ -175,7 +175,10 @@ function SettingsScreen() { } return ( - + - diff --git a/src/components/StyledButton/styles.tsx b/src/components/StyledButton/styles.tsx index 4e664ced..b2c4dc94 100644 --- a/src/components/StyledButton/styles.tsx +++ b/src/components/StyledButton/styles.tsx @@ -13,7 +13,7 @@ export default StyleSheet.create({ }, titleStyle: { paddingHorizontal: 24, - paddingVertical: 10, + paddingVertical: 5, color: 'white', }, }); From 507523a6b0f9c501036a8435d7af3ada85c3655b Mon Sep 17 00:00:00 2001 From: emilysunaryo <99292788+emilysunaryo@users.noreply.github.com> Date: Sat, 6 Apr 2024 23:06:07 -0700 Subject: [PATCH 23/34] [search] Implement genre screen (#59) * progress on database functions to pull genre information * pushing changes before rebase * ran prettier * finished styling genre preview card component * styling complete for genre screen, need to implement tone, topic dropdown selection logic * semi finished genre screen, need to debug drop down logic * Fix rpc calls * Seperate components in genre screen * Use PreviewCard instead of GenreStoryPreviewCard * Run initial useEffect async * Use rpc function to get all stories instead of loop * Run prettier * Implement tone and topic selectors * Refactor dropdowns * Fix type errors * Refactor some filter functions * More refactor of genre screen * Fix loading bug * Fix list key warning * Run prettier * Run prettier * Rename state variables * Small optimizations * Run prettier * Temp fix for spacing for tab bar * Small bug fixes * Run prettier --------- Co-authored-by: Aditya Pawar Co-authored-by: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> --- package-lock.json | 6 +- src/app/(tabs)/_layout.tsx | 8 +- src/app/(tabs)/author/index.tsx | 54 +-- src/app/(tabs)/genre/_layout.tsx | 11 + src/app/(tabs)/genre/index.tsx | 351 ++++++++++++++++++ src/app/(tabs)/genre/styles.tsx | 72 ++++ src/app/(tabs)/home/index.tsx | 21 +- src/app/(tabs)/home/styles.ts | 2 +- src/app/(tabs)/library/index.tsx | 2 +- src/app/(tabs)/search/index.tsx | 63 +++- src/app/(tabs)/settings/styles.tsx | 1 + src/app/(tabs)/story/index.tsx | 2 +- src/app/(tabs)/story/styles.ts | 4 - src/components/GenreCard/GenreCard.tsx | 1 + .../GenreStoryPreviewCard.tsx | 90 +++++ .../GenreStoryPreviewCard/styles.ts | 121 ++++++ src/components/PreviewCard/PreviewCard.tsx | 8 +- src/queries/genres.tsx | 21 +- src/queries/stories.tsx | 16 + src/styles/globalStyles.ts | 9 + src/utils/FilterContext.tsx | 186 ++++++++++ 21 files changed, 987 insertions(+), 62 deletions(-) create mode 100644 src/app/(tabs)/genre/_layout.tsx create mode 100644 src/app/(tabs)/genre/index.tsx create mode 100644 src/app/(tabs)/genre/styles.tsx create mode 100644 src/components/GenreStoryPreviewCard/GenreStoryPreviewCard.tsx create mode 100644 src/components/GenreStoryPreviewCard/styles.ts create mode 100644 src/utils/FilterContext.tsx diff --git a/package-lock.json b/package-lock.json index b1f5b69e..ca07deb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13667,9 +13667,9 @@ "integrity": "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==" }, "node_modules/joi": { - "version": "17.12.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.1.tgz", - "integrity": "sha512-vtxmq+Lsc5SlfqotnfVjlViWfOL9nt/avKNbKYizwf6gsCfq9NYY/ceYRMFD8XDdrjJ9abJyScWmhmIiy+XRtQ==", + "version": "17.12.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.2.tgz", + "integrity": "sha512-RonXAIzCiHLc8ss3Ibuz45u28GOsWE1UpfDXLbN/9NKbL4tCJf8TWYVKsoYuuh+sAUt7fsSNpA+r2+TBA6Wjmw==", "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", diff --git a/src/app/(tabs)/_layout.tsx b/src/app/(tabs)/_layout.tsx index c496d43f..de7b449d 100644 --- a/src/app/(tabs)/_layout.tsx +++ b/src/app/(tabs)/_layout.tsx @@ -55,7 +55,6 @@ function TabNav() { headerShown: false, tabBarLabel: 'Home', tabBarIcon: ({ color }) => HomeIcon({ color }), - // tabBarLabelStyle: { borderTopWidth: 12, paddingTop: 12 }, }} /> + ); } diff --git a/src/app/(tabs)/author/index.tsx b/src/app/(tabs)/author/index.tsx index 12c5bc73..38b8b88e 100644 --- a/src/app/(tabs)/author/index.tsx +++ b/src/app/(tabs)/author/index.tsx @@ -14,6 +14,7 @@ import { } from '../../../queries/authors'; import { Author, StoryPreview } from '../../../queries/types'; import globalStyles from '../../../styles/globalStyles'; +import * as cheerio from 'cheerio'; function AuthorScreen() { const [authorInfo, setAuthorInfo] = useState(); @@ -26,41 +27,39 @@ function AuthorScreen() { useEffect(() => { setLoading(true); (async () => { - const storyData: StoryPreview[] = await fetchAuthorStoryPreviews( - parseInt(author as string, 10), - ); - const authorData: Author = await fetchAuthor( - parseInt(author as string, 10), - ); try { - setAuthorInfo(authorData); - console.log('TESTING AUTHOR INFO QUERY OUTPUT:', authorInfo); - } catch (error) { - console.log( - `There was an error while trying to output authorinfo ${error}`, + const storyData: StoryPreview[] = await fetchAuthorStoryPreviews( + parseInt(author as string, 10), ); - } - try { + const authorData: Author = await fetchAuthor( + parseInt(author as string, 10), + ); + + // Assuming these setters do not throw, but if they do, they're caught by the catch block + setAuthorInfo(authorData); setAuthorStoryPreview(storyData); - console.log('TESTING STORY PREVIEW INFO QUERY OUTPUT:', storyData); } catch (error) { - console.log( - `There was an error while trying to output author story preview info ${error}`, - ); + console.error('There was an error while fetching data:', error); + } finally { + setLoading(false); } - })().then(() => { - setLoading(false); - }); + })(); }, [author]); + const getTextFromHtml = (text: string) => { + return cheerio.load(text).text().trim(); + }; + return ( - + {isLoading ? ( ) : ( router.back()} /> @@ -77,7 +76,7 @@ function AuthorScreen() { numberOfLines={2} style={globalStyles.h1} > - {authorInfo.name} + {getTextFromHtml(authorInfo.name)} {authorInfo?.pronouns && ( @@ -92,7 +91,9 @@ function AuthorScreen() { {authorInfo?.bio && ( <> - {decode(authorInfo.bio)} + + {getTextFromHtml(authorInfo.bio)} + )} @@ -105,7 +106,7 @@ function AuthorScreen() { Artist's Statement - {decode(authorInfo.artist_statement)} + {getTextFromHtml(authorInfo.artist_statement)} @@ -135,6 +136,9 @@ function AuthorScreen() { } /> ))} + + {/* View so there's space between the tab bar and the stories */} + )} diff --git a/src/app/(tabs)/genre/_layout.tsx b/src/app/(tabs)/genre/_layout.tsx new file mode 100644 index 00000000..d021a461 --- /dev/null +++ b/src/app/(tabs)/genre/_layout.tsx @@ -0,0 +1,11 @@ +import { Stack } from 'expo-router'; + +function StackLayout() { + return ( + + + + ); +} + +export default StackLayout; diff --git a/src/app/(tabs)/genre/index.tsx b/src/app/(tabs)/genre/index.tsx new file mode 100644 index 00000000..025680e5 --- /dev/null +++ b/src/app/(tabs)/genre/index.tsx @@ -0,0 +1,351 @@ +import { useLocalSearchParams, router } from 'expo-router'; +import { useEffect, useState, useMemo, ReactNode } from 'react'; +import { + ActivityIndicator, + ScrollView, + View, + Text, + FlatList, +} from 'react-native'; +import { MultiSelect } from 'react-native-element-dropdown'; +import { Icon } from 'react-native-elements'; +import { TouchableOpacity } from 'react-native-gesture-handler'; +import { SafeAreaView } from 'react-native-safe-area-context'; + +import styles from './styles'; +import BackButton from '../../../components/BackButton/BackButton'; +import { fetchGenreStoryById } from '../../../queries/genres'; +import { fetchStoryPreviewByIds } from '../../../queries/stories'; +import { StoryPreview, GenreStories } from '../../../queries/types'; +import globalStyles from '../../../styles/globalStyles'; +import PreviewCard from '../../../components/PreviewCard/PreviewCard'; + +function GenreScreen() { + const [genreStoryData, setGenreStoryData] = useState(); + const [genreStoryIds, setGenreStoryIds] = useState([]); + const [subgenres, setSubgenres] = useState([]); + const [allStoryPreviews, setAllStoryPreviews] = useState([]); + const [filteredStoryPreviews, setFilteredStoryPreviews] = useState< + StoryPreview[] + >([]); + const [selectedSubgenre, setSelectedSubgenre] = useState(''); + const [mainGenre, setMainGenre] = useState(''); + const [isLoading, setLoading] = useState(true); + const [toneFilterOptions, setToneFilterOptions] = useState([]); + const [topicFilterOptions, setTopicFilterOptions] = useState([]); + const [selectedTonesForFiltering, setSelectedTonesForFiltering] = useState< + string[] + >([]); + const [selectedTopicsForFiltering, setSelectedTopicsForFiltering] = useState< + string[] + >([]); + const { genreId, genreType, genreName } = useLocalSearchParams<{ + genreId: string; + genreType: GenreType; + genreName: string; + }>(); + + useEffect(() => { + const checkTopic = (preview: StoryPreview): boolean => { + if (preview == null || preview.topic == null) return false; + if (selectedTopicsForFiltering.length == 0) return true; + else + return selectedTopicsForFiltering.every(t => preview.topic.includes(t)); + }; + const checkTone = (preview: StoryPreview): boolean => { + if (preview == null || preview.tone == null) return false; + if (selectedTonesForFiltering.length == 0) return true; + else + return selectedTonesForFiltering.every(t => preview.tone.includes(t)); + }; + + const filteredPreviews = allStoryPreviews.filter( + preview => checkTopic(preview) && checkTone(preview), + ); + setFilteredStoryPreviews(filteredPreviews); + }, [selectedTopicsForFiltering, selectedTonesForFiltering]); + + function getAllStoryIds(genreStories: GenreStories[]): string[] { + return genreStories + .map(story => story.genre_story_previews) + .flat() + .filter(story => story !== null); + } + + function filterStoriesBySubgenreName( + subgenreName: string, + stories: GenreStories[], + ): string[] { + const matchingGenreStory = stories.find( + subgenre => subgenre.subgenre_name === subgenreName, + ); + + return matchingGenreStory?.genre_story_previews ?? []; + } + + function getSubgenres(stories: GenreStories[]): string[] { + const subgenres = stories.map(subgenre => subgenre.subgenre_name); + return ['All', ...subgenres]; + } + + function filterBySubgenre(subgenre: string) { + setLoading(true); + setSelectedSubgenre(subgenre); + if (!genreStoryData) { + setLoading(false); + return []; + } + + if (subgenre === 'All') { + setGenreStoryIds(getAllStoryIds(genreStoryData)); + } else { + const filteredStoryIds = filterStoriesBySubgenreName( + subgenre, + genreStoryData, + ); + + setGenreStoryIds(filteredStoryIds); + setToneFilterOptions([]); + setTopicFilterOptions([]); + setLoading(false); + } + } + + useEffect(() => { + const getGenre = async () => { + setLoading(true); + + const genreStoryData: GenreStories[] = await fetchGenreStoryById( + parseInt(genreId as string, 10), + ); + + setGenreStoryData(genreStoryData); + setMainGenre(genreStoryData[0].parent_name); + setSubgenres(getSubgenres(genreStoryData)); + + if (genreType == GenreType.PARENT) { + setSelectedSubgenre('All'); //if user clicks see all, selected should be 'ALL' + setGenreStoryIds(getAllStoryIds(genreStoryData)); + } else if (genreType == GenreType.SUBGENRE) { + setSelectedSubgenre(genreName || ''); //if user clicks a specific genre, selected should be genreName + + const filteredStoryIds = filterStoriesBySubgenreName( + genreName || '', + genreStoryData, + ); + setGenreStoryIds(filteredStoryIds); + + setLoading(false); + } + }; + getGenre(); + }, [genreName]); + + useEffect(() => { + const showAllStoryPreviews = async () => { + setLoading(true); + + const previews: StoryPreview[] = await fetchStoryPreviewByIds( + genreStoryIds as any, + ); + + const tones: string[] = previews + .reduce((acc: string[], current: StoryPreview) => { + return acc.concat(current.tone); + }, [] as string[]) + .filter(tone => tone !== null); + const topics: string[] = previews + .reduce((acc: string[], current: StoryPreview) => { + return acc.concat(current.topic); + }, [] as string[]) + .filter(topic => topic !== null); + + setAllStoryPreviews(previews.flat()); + setFilteredStoryPreviews(previews.flat()); + setTopicFilterOptions([...new Set(topics)]); + setToneFilterOptions([...new Set(tones)]); + + setLoading(false); + }; + + if (genreStoryIds.length > 0) { + showAllStoryPreviews(); + } + }, [genreStoryIds]); + + const renderGenreScrollSelector = () => { + return ( + + {subgenres.map((subgenre, index) => ( + filterBySubgenre(subgenre)} //onPress will trigger the filterBySubgenre function + style={{ paddingHorizontal: 20, paddingTop: 5 }} + key={index} + > + + {subgenre} + + + ))} + + ); + }; + + const renderGenreHeading = () => { + return ( + + + {selectedSubgenre === 'All' ? mainGenre : selectedSubgenre} + + {/* */} + {/* {' '} */} + {/* Subheading about{' '} */} + {/* {selectedSubgenre === 'All' ? mainGenre : selectedSubgenre} */} + {/* ...Include Later? */} + {/* */} + + ); + }; + + const renderFilterDropdown = ( + placeholder: string, + value: string[], + data: string[], + setter: React.Dispatch>, + ) => { + return ( + { + return { label: topic, value: topic }; + })} + renderSelectedItem={() => } + maxHeight={400} + labelField="label" + valueField="value" + placeholder={placeholder} + renderRightIcon={() => } + onChange={item => { + if (item) { + setter(item); + } + }} + /> + ); + }; + + const renderNoStoryText = () => { + return ( + + Sorry! + + There are no stories under this Genre or Subgenre. Please continue to + search for other stories + + + ); + }; + + const renderStories = () => { + return ( + ( + { + router.push({ + pathname: '/story', + params: { storyId: item.id.toString() }, + }); + }} + /> + )} + /> + ); + }; + + return ( + + + + + router.push({ + pathname: '/search', + }) + } + /> + + {useMemo(renderGenreHeading, [selectedSubgenre, mainGenre])} + {useMemo(renderGenreScrollSelector, [subgenres, selectedSubgenre])} + + + + {renderFilterDropdown( + 'Tone', + selectedTonesForFiltering, + toneFilterOptions, + setSelectedTonesForFiltering, + )} + {renderFilterDropdown( + 'Topic', + selectedTopicsForFiltering, + topicFilterOptions, + setSelectedTopicsForFiltering, + )} + + + {genreStoryIds.length === 0 && !isLoading ? ( + renderNoStoryText() + ) : ( + <> + + {isLoading ? ( + + + + ) : ( + renderStories() + )} + + + )} + + + ); +} + +export enum GenreType { + PARENT = 'parent', + SUBGENRE = 'subgenre', +} + +export default GenreScreen; diff --git a/src/app/(tabs)/genre/styles.tsx b/src/app/(tabs)/genre/styles.tsx new file mode 100644 index 00000000..1869ac12 --- /dev/null +++ b/src/app/(tabs)/genre/styles.tsx @@ -0,0 +1,72 @@ +import { StyleSheet } from 'react-native'; + +import colors from '../../../styles/colors'; + +const styles = StyleSheet.create({ + textSelected: { + color: '#EB563B', + textDecorationLine: 'underline', + }, + container: { + paddingHorizontal: 24, + width: '100%', + marginTop: 24, + flex: 1, + }, + + flatListStyle: { + paddingTop: 15, + }, + scrollViewContainer: { + marginVertical: 15, + width: '100%', + }, + noStoriesText: { + fontSize: 20, + color: '#EB563B', + }, + noStoriesText2: { + fontSize: 13, + }, + renderStories: { + paddingBottom: 10, + flex: 1, + }, + headerContainer: {}, + dropdown: { + borderColor: '#797979', + flexGrow: 0, + flexShrink: 0, + borderWidth: 1.5, + borderRadius: 7, + width: 140, + height: 30, + color: '#797979', + }, + dropdownContainer: { + marginTop: 20, + marginBottom: 20, + flexDirection: 'row', + justifyContent: 'flex-start', + }, + firstDropdown: { + marginRight: 10, + }, + secondDropdown: { + marginLeft: 10, + }, + icon: { + marginRight: 5, + }, + iconStyle: { + width: 20, + height: 20, + }, + itemContainer: {}, + placeholderStyle: { + color: colors.darkGrey, + marginLeft: 45, + }, +}); + +export default styles; diff --git a/src/app/(tabs)/home/index.tsx b/src/app/(tabs)/home/index.tsx index 871b0eed..81341d77 100644 --- a/src/app/(tabs)/home/index.tsx +++ b/src/app/(tabs)/home/index.tsx @@ -1,6 +1,12 @@ import { router } from 'expo-router'; import { useEffect, useState } from 'react'; -import { Pressable, ScrollView, Text, View } from 'react-native'; +import { + ActivityIndicator, + Pressable, + ScrollView, + Text, + View, +} from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import styles from './styles'; @@ -54,15 +60,16 @@ function HomeScreen() { }); }, [user]); + if (loading) { + return ; + } return ( - {loading && ( - - Loading - - )} + Library ); diff --git a/src/app/(tabs)/search/index.tsx b/src/app/(tabs)/search/index.tsx index fd64c5b7..a5114727 100644 --- a/src/app/(tabs)/search/index.tsx +++ b/src/app/(tabs)/search/index.tsx @@ -9,6 +9,7 @@ import { Text, ScrollView, Pressable, + TouchableOpacity, } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; @@ -22,13 +23,14 @@ import { fetchAllStoryPreviews } from '../../../queries/stories'; import { StoryPreview, RecentSearch, Genre } from '../../../queries/types'; import colors from '../../../styles/colors'; import globalStyles from '../../../styles/globalStyles'; +import { GenreType } from '../genre'; const getRecentSearch = async () => { try { const jsonValue = await AsyncStorage.getItem('GWN_RECENT_SEARCHES_ARRAY'); return jsonValue != null ? JSON.parse(jsonValue) : []; } catch (error) { - console.log(error); + console.error(error); } }; @@ -37,7 +39,7 @@ const setRecentSearch = async (searchResult: RecentSearch[]) => { const jsonValue = JSON.stringify(searchResult); await AsyncStorage.setItem('GWN_RECENT_SEARCHES_ARRAY', jsonValue); } catch (error) { - console.log(error); + console.error(error); } }; @@ -46,7 +48,7 @@ const getRecentStory = async () => { const jsonValue = await AsyncStorage.getItem('GWN_RECENT_STORIES_ARRAY'); return jsonValue != null ? JSON.parse(jsonValue) : []; } catch (error) { - console.log(error); + console.error(error); } }; @@ -55,7 +57,7 @@ const setRecentStory = async (recentStories: StoryPreview[]) => { const jsonValue = JSON.stringify(recentStories); await AsyncStorage.setItem('GWN_RECENT_STORIES_ARRAY', jsonValue); } catch (error) { - console.log(error); + console.error(error); } }; @@ -69,20 +71,24 @@ function SearchScreen() { const [showGenreCarousals, setShowGenreCarousals] = useState(true); const [showRecents, setShowRecents] = useState(false); const [recentlyViewed, setRecentlyViewed] = useState([]); + const genreColors = [colors.citrus, colors.lime, colors.lilac]; useEffect(() => { (async () => { - const data: StoryPreview[] = await fetchAllStoryPreviews(); - setAllStories(data); - const genreData: Genre[] = await fetchGenres(); - setAllGenres(genreData); - setRecentSearches(await getRecentSearch()); - setRecentlyViewed(await getRecentStory()); + fetchAllStoryPreviews().then((stories: StoryPreview[]) => + setAllStories(stories), + ); + fetchGenres().then((genres: Genre[]) => setAllGenres(genres)); + getRecentSearch().then((searches: RecentSearch[]) => + setRecentSearches(searches), + ); + getRecentStory().then((viewed: StoryPreview[]) => + setRecentlyViewed(viewed), + ); })(); }, []); const getColor = (index: number) => { - const genreColors = [colors.citrus, colors.lime, colors.lilac]; return genreColors[index % genreColors.length]; }; @@ -92,12 +98,14 @@ function SearchScreen() { setSearchResults([]); return; } + const updatedData = allStories.filter((item: StoryPreview) => { const title = `${item.title.toUpperCase()})`; const author = `${item.author_name.toUpperCase()})`; const text_data = text.toUpperCase(); return title.indexOf(text_data) > -1 || author.indexOf(text_data) > -1; }); + setSearch(text); setSearchResults(updatedData); setShowGenreCarousals(false); @@ -175,7 +183,7 @@ function SearchScreen() { return ( {allGenres.map((genre, index) => ( - + {genre.parent_name} - See All + { + router.push({ + pathname: '/genre', + params: { + genreId: genre.parent_id.toString(), + genreType: GenreType.PARENT, + genreName: genre.parent_name, + }, + }); + }} + > + See All + null} + pressFunction={() => { + router.push({ + pathname: '/genre', + params: { + genreId: genre.parent_id.toString(), + genreType: GenreType.SUBGENRE, + genreName: subgenre.name, + }, + }); + }} /> ))} - + ))} ) : ( diff --git a/src/app/(tabs)/settings/styles.tsx b/src/app/(tabs)/settings/styles.tsx index a5eceadc..cded918b 100644 --- a/src/app/(tabs)/settings/styles.tsx +++ b/src/app/(tabs)/settings/styles.tsx @@ -10,6 +10,7 @@ export default StyleSheet.create({ flex: 1, backgroundColor: 'white', paddingHorizontal: 24, + paddingBottom: 60, }, button: { marginBottom: 32, diff --git a/src/app/(tabs)/story/index.tsx b/src/app/(tabs)/story/index.tsx index 73cbdfef..2387f2f1 100644 --- a/src/app/(tabs)/story/index.tsx +++ b/src/app/(tabs)/story/index.tsx @@ -65,7 +65,7 @@ function StoryScreen() { }; return ( - + {isLoading ? ( ) : ( diff --git a/src/app/(tabs)/story/styles.ts b/src/app/(tabs)/story/styles.ts index 7e6e2c8c..66932cf5 100644 --- a/src/app/(tabs)/story/styles.ts +++ b/src/app/(tabs)/story/styles.ts @@ -3,10 +3,6 @@ import colors from '../../../styles/colors'; const styles = StyleSheet.create({ container: { - flex: 1, - backgroundColor: 'white', - alignItems: 'flex-start', - justifyContent: 'flex-start', paddingLeft: 24, paddingRight: 24, paddingTop: 48, diff --git a/src/components/GenreCard/GenreCard.tsx b/src/components/GenreCard/GenreCard.tsx index 86b9f552..37bb5360 100644 --- a/src/components/GenreCard/GenreCard.tsx +++ b/src/components/GenreCard/GenreCard.tsx @@ -9,6 +9,7 @@ import styles from './styles'; type GenreCardProps = { subgenres: string; + subgenre_id: number; cardColor: string; pressFunction: (event: GestureResponderEvent) => void; }; diff --git a/src/components/GenreStoryPreviewCard/GenreStoryPreviewCard.tsx b/src/components/GenreStoryPreviewCard/GenreStoryPreviewCard.tsx new file mode 100644 index 00000000..00b413da --- /dev/null +++ b/src/components/GenreStoryPreviewCard/GenreStoryPreviewCard.tsx @@ -0,0 +1,90 @@ +import { + GestureResponderEvent, + Text, + Image, + View, + TouchableOpacity, +} from 'react-native'; + +import styles from './styles'; +import globalStyles from '../../styles/globalStyles'; + +type GenreStoryPreviewCardProps = { + topic: string[]; + tone: string[]; + genreMedium: string[]; + allTags: string[]; + authorName: string; + storyImage: string; + authorImage: string; + storyTitle: string; + excerpt: { html: string }; + pressFunction: (event: GestureResponderEvent) => void; +}; + +function GenreStoryPreviewCard({ + topic, + tone, + genreMedium, + allTags, + authorName, + storyImage, + authorImage, + storyTitle, + excerpt, + pressFunction, +}: GenreStoryPreviewCardProps) { + return ( + + + + + + {storyTitle} + + + + + + + + + {authorName} + + + + {excerpt.html.slice(3, -3)} + + + + + + + + {genreMedium[0]} + + + {genreMedium[1]} + + + + + + {allTags.length} more{' '} + {allTags.length === 1 ? 'tag' : 'tags'} + + + + + + + + ); +} + +export default GenreStoryPreviewCard; diff --git a/src/components/GenreStoryPreviewCard/styles.ts b/src/components/GenreStoryPreviewCard/styles.ts new file mode 100644 index 00000000..a40bb58e --- /dev/null +++ b/src/components/GenreStoryPreviewCard/styles.ts @@ -0,0 +1,121 @@ +import { StyleSheet } from 'react-native'; + +import colors from '../../styles/colors'; + +const styles = StyleSheet.create({ + card: { + flexDirection: 'column', + justifyContent: 'flex-end', + backgroundColor: 'white', + borderRadius: 6, + marginTop: 8, + marginBottom: 8, + shadowColor: 'black', + shadowOffset: { width: 1, height: 3 }, + shadowOpacity: 0.5, + elevation: 10, + paddingRight: 30, + marginRight: 30, + width: '98%', + marginHorizontal: '0.75%', + }, + top: { + flex: 1, + flexDirection: 'row', + justifyContent: 'flex-start', + alignItems: 'flex-start', + }, + bottom: { + flex: 1, + flexDirection: 'column', + justifyContent: 'flex-start', + alignItems: 'flex-start', + height: 48, + backgroundColor: colors.lightGrey, + overflow: 'hidden', + borderRadius: 6, + paddingHorizontal: 12, + paddingTop: 8, + }, + image: { + height: 106, + width: 106, + backgroundColor: colors.lilac, + borderRadius: 4, + marginBottom: 12, + marginTop: 12, + }, + author: { + marginLeft: 8, + }, + authorImage: { + height: 22, + width: 22, + backgroundColor: colors.gwnOrange, + borderRadius: 22 / 2, + }, + cardTextContainer: { + flex: 1, + marginLeft: 16, + marginTop: 12, + marginBottom: 8, + }, + authorContainer: { + flexDirection: 'row', + alignItems: 'flex-start', + marginBottom: 10, + }, + title: { + marginBottom: 8, + fontSize: 22, + }, + tags: { + paddingHorizontal: 8, + paddingVertical: 4, + backgroundColor: '#EBEBEB', + borderRadius: 10, + width: 'auto', + marginRight: 8, + marginBottom: 10, + }, + tagsContainer: { + flexDirection: 'row', + justifyContent: 'flex-start', + + alignItems: 'center', + flexWrap: 'wrap', + }, + horizontalLine: { + borderBottomColor: '#EBEBEB', + borderBottomWidth: 1, + marginTop: 5, + marginBottom: 10, + }, + cardContainer2: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + }, + authorandText: { + flex: 1, + flexDirection: 'column', + marginLeft: 10, + marginTop: -10, + }, + subtext: { + color: '#797979', + fontSize: 15, + }, + tagSubtext: { + color: '#797979', + }, + tagParent: { + flex: 1, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + flexWrap: 'wrap', + }, +}); + +export default styles; diff --git a/src/components/PreviewCard/PreviewCard.tsx b/src/components/PreviewCard/PreviewCard.tsx index 98253bb7..84910f88 100644 --- a/src/components/PreviewCard/PreviewCard.tsx +++ b/src/components/PreviewCard/PreviewCard.tsx @@ -10,6 +10,9 @@ import { import styles from './styles'; import globalStyles from '../../styles/globalStyles'; +const placeholderImage = + 'https://gwn-uploads.s3.amazonaws.com/wp-content/uploads/2021/10/10120952/Girls-Write-Now-logo-avatar.png'; + type PreviewCardProps = { title: string; image: string; @@ -38,7 +41,10 @@ function PreviewCard({ - + diff --git a/src/queries/genres.tsx b/src/queries/genres.tsx index 4710cbcd..ca648b71 100644 --- a/src/queries/genres.tsx +++ b/src/queries/genres.tsx @@ -1,5 +1,4 @@ -// eslint-disable-next-line import/namespace -import { Genre } from './types'; +import { Genre, GenreStories } from './types'; import supabase from '../utils/supabase'; export async function fetchGenres(): Promise { @@ -12,3 +11,21 @@ export async function fetchGenres(): Promise { return data; } } + +export async function fetchGenreStoryById( + parent_id: number, +): Promise { + const { data, error } = await supabase.rpc( + 'fetch_genre_and_subgenre_stories', + { + genre_parent_id: parent_id, + }, + ); + if (error) { + throw new Error( + `An error occured when trying to fetch all genres story previews ${error}`, + ); + } else { + return data; + } +} diff --git a/src/queries/stories.tsx b/src/queries/stories.tsx index 86747ad9..9b8e833b 100644 --- a/src/queries/stories.tsx +++ b/src/queries/stories.tsx @@ -98,3 +98,19 @@ export async function fetchStoryPreviewById( return data; } } + +export async function fetchStoryPreviewByIds( + storyIds: number[], +): Promise { + const { data, error } = await supabase.rpc('curr_story_preview_by_ids', { + input_ids: storyIds, + }); + if (error) { + console.log(error); + throw new Error( + `An error occured when trying to fetch story preview by IDs: ${error}`, + ); + } else { + return data; + } +} diff --git a/src/styles/globalStyles.ts b/src/styles/globalStyles.ts index 12e17283..3a104cf0 100644 --- a/src/styles/globalStyles.ts +++ b/src/styles/globalStyles.ts @@ -10,6 +10,15 @@ export default StyleSheet.create({ justifyContent: 'flex-start', paddingHorizontal: 24, }, + + tabBarContainer: { + flex: 1, + backgroundColor: 'white', + alignItems: 'flex-start', + justifyContent: 'flex-start', + paddingHorizontal: 24, + paddingBottom: 60, + }, authContainer: { marginHorizontal: 38, flex: 1, diff --git a/src/utils/FilterContext.tsx b/src/utils/FilterContext.tsx new file mode 100644 index 00000000..b488e0dd --- /dev/null +++ b/src/utils/FilterContext.tsx @@ -0,0 +1,186 @@ +import React, { + createContext, + useContext, + useEffect, + useMemo, + useReducer, +} from 'react'; +import supabase from './supabase'; + +type FilterAction = + | { type: 'SET_TAGS'; tags: TagFilter[] } + | { type: 'TOGGLE_FILTER'; id: number } + | { type: 'SET_FILTER'; id: number; value: boolean } + | { type: 'CLEAR_ALL'; category: string } + | { type: 'TOGGLE_MAIN_GENRE'; mainGenreId: number }; + +export type FilterDispatch = React.Dispatch; + +export type TagFilter = { + id: number; + name: string; + category: string; + active: boolean; + parent: number | null; +}; + +type ParentFilter = { children: TagFilter[] } & TagFilter; + +export interface FilterState { + filters: Map; + isLoading: boolean; + dispatch: FilterDispatch; +} + +const FilterContext = createContext({} as FilterState); + +const mapParentsAndChildren = ( + filters: Map, + func: (filter: TagFilter) => TagFilter, +) => { + return new Map( + Array.from(filters).map(([id, parent]) => { + return [ + id, + { + ...func(parent), + children: parent.children.map(func), + } as ParentFilter, + ]; + }), + ); +}; + +export const useFilterReducer = () => + useReducer( + (prevState: FilterState, action: FilterAction) => { + switch (action.type) { + case 'SET_TAGS': + const nestedFilters = new Map(); + action.tags + .filter(filter => filter.parent === null) + .map(parentFilter => { + nestedFilters.set(parentFilter.id, { + ...parentFilter, + children: [], + } as ParentFilter); + }); + + action.tags.map(childFilter => { + if (childFilter.parent) { + nestedFilters.get(childFilter.parent)?.children.push(childFilter); + } + }); + + return { + ...prevState, + filters: nestedFilters, + isLoading: false, + }; + case 'SET_FILTER': + return { + ...prevState, + filters: mapParentsAndChildren(prevState.filters, fitler => + fitler.id == action.id + ? { ...fitler, active: action.value } + : fitler, + ), + }; + case 'TOGGLE_FILTER': + return { + ...prevState, + filters: mapParentsAndChildren(prevState.filters, fitler => + fitler.id == action.id + ? { ...fitler, active: !fitler.active } + : fitler, + ), + }; + case 'CLEAR_ALL': + return { + ...prevState, + filters: mapParentsAndChildren(prevState.filters, filter => + filter.category == action.category + ? { ...filter, active: false } + : filter, + ), + }; + case 'TOGGLE_MAIN_GENRE': + const parentGenre = prevState.filters.get(action.mainGenreId); + const newActiveState = !parentGenre?.active; + + const updatedFilters = mapParentsAndChildren( + prevState.filters, + tag => + tag.parent == action.mainGenreId || tag.id == action.mainGenreId + ? { ...tag, active: newActiveState } + : tag, + ); + + return { + ...prevState, + filters: updatedFilters, + }; + default: + return prevState; + } + }, + { + filters: new Map(), + isLoading: true, + dispatch: () => null, + }, + ); + +export function useFilter() { + const value = useContext(FilterContext); + if (process.env.NODE_ENV !== 'production') { + if (!value) { + throw new Error( + 'useFilter must be wrapped in a ', + ); + } + } + + return value; +} + +export function FilterContextProvider({ + children, +}: { + children: React.ReactNode; +}) { + const [filterState, dispatch] = useFilterReducer(); + + const getTags = async () => { + const { data } = await supabase.from('tags').select(`*`); + + return data?.map(entry => { + const { category, id, name, parent_id } = entry; + return { + id, + name, + category, + parent: parent_id, + active: false, + } as TagFilter; + }); + }; + + useEffect(() => { + getTags().then(tags => dispatch({ type: 'SET_TAGS', tags: tags ?? [] })); + }, []); + + const filterContextValue = useMemo( + () => ({ + ...filterState, + dispatch, + }), + [filterState], + ); + + return ( + + {children} + + ); +} From f9f6ed656ba447bd23158363ac03bd044ce3d5e2 Mon Sep 17 00:00:00 2001 From: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> Date: Mon, 8 Apr 2024 19:12:28 -0700 Subject: [PATCH 24/34] Use rpc to check if password is the same (#80) --- src/app/auth/resetPassword/index.tsx | 7 ++++++- src/queries/profiles.tsx | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/app/auth/resetPassword/index.tsx b/src/app/auth/resetPassword/index.tsx index 024fcf06..19a193bd 100644 --- a/src/app/auth/resetPassword/index.tsx +++ b/src/app/auth/resetPassword/index.tsx @@ -10,9 +10,10 @@ import colors from '../../../styles/colors'; import globalStyles from '../../../styles/globalStyles'; import { useSession } from '../../../utils/AuthContext'; import PasswordComplexityText from '../../../components/PasswordComplexityText/PasswordComplexityText'; +import { isPasswordSameAsBefore } from '../../../queries/profiles'; function ResetPasswordScreen() { - const { updateUser, signOut } = useSession(); + const { session, updateUser, signOut } = useSession(); const [password, setPassword] = useState(''); const [passwordTextHidden, setPasswordTextHidden] = useState(true); const [confirmPassword, setConfirmPassword] = useState(''); @@ -36,6 +37,9 @@ function ResetPasswordScreen() { const checkPassword = (text: string) => { if (text !== '') { + isPasswordSameAsBefore(text, session?.user?.id).then(isSame => + setIsDifferent(!isSame), + ); setHasUppercase(text !== text.toLowerCase()); setHasLowercase(text !== text.toUpperCase()); setHasNumber(/[0-9]/.test(text)); @@ -70,6 +74,7 @@ function ResetPasswordScreen() { const { error } = await updateUser({ password }); if (error) { + console.error(error); Alert.alert('Updating password failed'); } else { await signOut(); diff --git a/src/queries/profiles.tsx b/src/queries/profiles.tsx index 7bc979aa..dfdaea4c 100644 --- a/src/queries/profiles.tsx +++ b/src/queries/profiles.tsx @@ -25,3 +25,20 @@ export async function isEmailTaken(newEmail: string) { const emailIsTaken = (count ?? 0) >= 1; return emailIsTaken as boolean; } + +export async function isPasswordSameAsBefore( + new_plain_password: string, + user_id: string | undefined, +): Promise { + let { data, error } = await supabase.rpc('check_same_as_old_pass', { + new_plain_password, + user_id, + }); + + if (error) { + console.error(error); + return false; + } else { + return data; + } +} From 40f3394da93c539cbd980a61a0283396de9b71e8 Mon Sep 17 00:00:00 2001 From: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> Date: Mon, 8 Apr 2024 22:17:07 -0700 Subject: [PATCH 25/34] Fix worm bug (null tags) (#81) * Fix worm bug (null tags) * Run prettier * Update lint.yml * Run prettier on lint.yml --- .github/workflows/lint.yml | 3 --- src/components/PreviewCard/PreviewCard.tsx | 16 +++++++++------- src/components/PreviewCard/styles.ts | 1 + 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 579ef283..89691a02 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -6,9 +6,6 @@ name: Lint ############################# on: push: - branches-ignore: [main] - pull_request: - branches: [main] ############### # Set the Job # diff --git a/src/components/PreviewCard/PreviewCard.tsx b/src/components/PreviewCard/PreviewCard.tsx index 84910f88..8272b57b 100644 --- a/src/components/PreviewCard/PreviewCard.tsx +++ b/src/components/PreviewCard/PreviewCard.tsx @@ -59,23 +59,25 @@ function PreviewCard({ numberOfLines={3} style={[globalStyles.subtext, styles.storyDescription]} > - "{cheerio.load(excerpt.html).text()}" + "{cheerio.load(excerpt.html ?? '').text()}" - - - {tags[0]} - - + {(tags?.length ?? 0) > 0 && ( + + + {tags[0]} + + + )} {' '} - + {tags.length - 1} more tags + + {(tags?.length ?? 1) - 1} more tags diff --git a/src/components/PreviewCard/styles.ts b/src/components/PreviewCard/styles.ts index e8af8f2c..493e3061 100644 --- a/src/components/PreviewCard/styles.ts +++ b/src/components/PreviewCard/styles.ts @@ -81,6 +81,7 @@ const styles = StyleSheet.create({ paddingTop: 4, }, moreTags: { + paddingVertical: 10, paddingRight: 12, alignItems: 'center', justifyContent: 'center', From 62307fd76528736215551c59ab41cfa4c72c372d Mon Sep 17 00:00:00 2001 From: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> Date: Thu, 11 Apr 2024 22:15:21 -0700 Subject: [PATCH 26/34] [bug] Add other ethnicities (#83) * Add other ethnicities * Remove old settings --- src/app/(tabs)/settings/index.tsx | 3 +++ src/app/auth/onboarding/index.tsx | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/app/(tabs)/settings/index.tsx b/src/app/(tabs)/settings/index.tsx index 10bf4af9..0434bc6e 100644 --- a/src/app/(tabs)/settings/index.tsx +++ b/src/app/(tabs)/settings/index.tsx @@ -259,9 +259,12 @@ function SettingsScreen() { options={[ 'American Indian/Alaska Native', 'Asian', + 'Hispanic/Latinx', + 'Middle Eastern', 'Black or African American', 'Native Hawaiian or other Pacific Islander', 'White', + 'Not Listed Here', 'Prefer Not to Disclose', ]} label="Race/Ethnicity" diff --git a/src/app/auth/onboarding/index.tsx b/src/app/auth/onboarding/index.tsx index 936624fb..ea0af6ed 100644 --- a/src/app/auth/onboarding/index.tsx +++ b/src/app/auth/onboarding/index.tsx @@ -219,9 +219,12 @@ function OnboardingScreen() { options={[ 'American Indian/Alaska Native', 'Asian', + 'Hispanic/Latinx', + 'Middle Eastern', 'Black or African American', 'Native Hawaiian or other Pacific Islander', 'White', + 'Not Listed Here', 'Prefer Not to Disclose', ]} label="Race/Ethnicity" From 860d346d2a8fd29c88f365ea86fda2209ae0fd22 Mon Sep 17 00:00:00 2001 From: Marcoss28 <69034384+Marcoss28@users.noreply.github.com> Date: Thu, 11 Apr 2024 22:19:51 -0700 Subject: [PATCH 27/34] [update] Update preview card (#82) * accidently forgot to branch * [updated preview card]\n[updated preview and content card emojis/reactions] * chanegs made * Increase margin by 2 --------- Co-authored-by: Marcos Hernandez Co-authored-by: Aditya Pawar --- package-lock.json | 39 ++++++++++++++++ package.json | 3 ++ src/components/ContentCard/ContentCard.tsx | 42 ++++++++---------- src/components/ContentCard/styles.ts | 22 ++++++--- src/components/PreviewCard/PreviewCard.tsx | 37 ++++++++++++--- .../PreviewCard/savedStoriesIcon.png | Bin 0 -> 1052 bytes src/components/PreviewCard/styles.ts | 30 +++++++++++-- 7 files changed, 133 insertions(+), 40 deletions(-) create mode 100644 src/components/PreviewCard/savedStoriesIcon.png diff --git a/package-lock.json b/package-lock.json index ca07deb9..f83fb7da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,10 +38,13 @@ "expo-status-bar": "~1.6.0", "html-entities": "^2.4.0", "react": "18.2.0", + "react-apple-emojis": "^2.2.1", "react-native": "0.72.10", "react-native-dom-parser": "^1.5.3", "react-native-element-dropdown": "^2.10.0", "react-native-elements": "^3.4.3", + "react-native-emoji": "^1.8.0", + "react-native-emojicon": "^1.0.0", "react-native-gesture-handler": "~2.12.0", "react-native-htmlview": "^0.16.0", "react-native-ionicons": "^4.6.5", @@ -14217,6 +14220,11 @@ "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==" }, + "node_modules/lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==" + }, "node_modules/log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -15502,6 +15510,14 @@ "node": ">=10.5.0" } }, + "node_modules/node-emoji": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz", + "integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==", + "dependencies": { + "lodash.toarray": "^4.4.0" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -16664,6 +16680,16 @@ "node": ">=0.10.0" } }, + "node_modules/react-apple-emojis": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-apple-emojis/-/react-apple-emojis-2.2.1.tgz", + "integrity": "sha512-tgq/+GUR6WsBkkkl0EYgVbaU803IF8GoELcG83cfircrEiyiiIbHqpBXIHyD8YIOecAGgN2ucEG6U/REDR7jvQ==", + "peerDependencies": { + "prop-types": "*", + "react": ">=16.x", + "react-dom": ">=16.x" + } + }, "node_modules/react-devtools-core": { "version": "4.28.0", "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.0.tgz", @@ -16853,6 +16879,19 @@ "react-native-vector-icons": ">7.0.0" } }, + "node_modules/react-native-emoji": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/react-native-emoji/-/react-native-emoji-1.8.0.tgz", + "integrity": "sha512-VunKOtYes6eymyWwE7QS3mhmNXksTt2AN92PcGRtmDKLDPjuKrwd5tcJckFUekAK3H+6AMpwYy30CsiCJrDdFQ==", + "dependencies": { + "node-emoji": "1.10.0" + } + }, + "node_modules/react-native-emojicon": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/react-native-emojicon/-/react-native-emojicon-1.0.0.tgz", + "integrity": "sha512-rK6/7EIf/yNgkB24ujpV8zmmZylbQV+oq4F7YopZ9aSfNKmVKKFmqGOPahPo6OW8b1Dg5dm8caybgfpM2GP4Nw==" + }, "node_modules/react-native-gesture-handler": { "version": "2.12.1", "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.12.1.tgz", diff --git a/package.json b/package.json index 7ba5f154..ed0b39df 100644 --- a/package.json +++ b/package.json @@ -42,10 +42,13 @@ "expo-status-bar": "~1.6.0", "html-entities": "^2.4.0", "react": "18.2.0", + "react-apple-emojis": "^2.2.1", "react-native": "0.72.10", "react-native-dom-parser": "^1.5.3", "react-native-element-dropdown": "^2.10.0", "react-native-elements": "^3.4.3", + "react-native-emoji": "^1.8.0", + "react-native-emojicon": "^1.0.0", "react-native-gesture-handler": "~2.12.0", "react-native-htmlview": "^0.16.0", "react-native-ionicons": "^4.6.5", diff --git a/src/components/ContentCard/ContentCard.tsx b/src/components/ContentCard/ContentCard.tsx index 4301cb9f..dd62a58b 100644 --- a/src/components/ContentCard/ContentCard.tsx +++ b/src/components/ContentCard/ContentCard.tsx @@ -9,6 +9,7 @@ import { import styles from './styles'; import globalStyles from '../../styles/globalStyles'; +import Emoji from 'react-native-emoji'; type ContentCardProps = { title: string; @@ -58,33 +59,26 @@ function ContentCard({ - - null} - style={{ flexDirection: 'row' }} - > - - - - - - 14{/*change number to work*/} - - - + + + + + + + + + + + {/* heart, clap, muscle, cry, ??? */} + + + 14{/*change number to work*/} + + saveStory()}> diff --git a/src/components/ContentCard/styles.ts b/src/components/ContentCard/styles.ts index d4458704..f18d4837 100644 --- a/src/components/ContentCard/styles.ts +++ b/src/components/ContentCard/styles.ts @@ -50,18 +50,26 @@ const styles = StyleSheet.create({ color: colors.grey, }, reactionNumber: { - marginLeft: 15, - marginTop: 10, + marginLeft: 14, + marginTop: 16, }, reactions: { - width: 20, - height: 20, - borderRadius: 20 / 2, + width: 30, + height: 30, + borderRadius: 30 / 2, borderWidth: 1, - backgroundColor: '#89CFF0', //different per emoji reaction + backgroundColor: 'transparent', //different per emoji reaction borderColor: 'white', marginTop: 10, - marginRight: -10, + marginRight: -5, // -10 + overflow: 'hidden', + justifyContent: 'center', + paddingLeft: 3, + }, + saveStoryImage: { + width: 30, + height: 30, + marginTop: 10, }, buttons: { flexDirection: 'row', diff --git a/src/components/PreviewCard/PreviewCard.tsx b/src/components/PreviewCard/PreviewCard.tsx index 8272b57b..dfe73227 100644 --- a/src/components/PreviewCard/PreviewCard.tsx +++ b/src/components/PreviewCard/PreviewCard.tsx @@ -4,8 +4,10 @@ import { Image, Pressable, Text, + TouchableOpacity, View, } from 'react-native'; +import Emoji from 'react-native-emoji'; import styles from './styles'; import globalStyles from '../../styles/globalStyles'; @@ -32,6 +34,10 @@ function PreviewCard({ tags, pressFunction, }: PreviewCardProps) { + const saveStory = () => { + console.log("testing '+' icon does something for story " + title); + }; + return ( @@ -39,11 +45,17 @@ function PreviewCard({ {title} + saveStory()}> + + @@ -64,6 +76,23 @@ function PreviewCard({ + + + + + + + + + + + {/* heart, clap, muscle, cry, ??? */} + + + 14{/*change number to work*/} + + + {(tags?.length ?? 0) > 0 && ( @@ -72,12 +101,10 @@ function PreviewCard({ )} - - - + {' '} - + {(tags?.length ?? 1) - 1} more tags + + {(tags?.length ?? 1) - 1} diff --git a/src/components/PreviewCard/savedStoriesIcon.png b/src/components/PreviewCard/savedStoriesIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..65b2ea6e4dd47e1c590ef1cbe5d7afc29d8fcca7 GIT binary patch literal 1052 zcmV+%1mpXOP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91JfH&r1ONa40RR91JOBUy0E^%0TmS$AhDk(0RA>e5n@@7uFciimr$e`7 zhCjm&P7v1VhMpkVWYbNP6Eryi^aM>$(8;zeN=^{ENH^V(6Qo@wfn;E^B&pr+b1h;E2p>P%^ zpbQq?-QDePZEbx)!+h{wlCB94d0Rp7Dd53i@ClWUJ+Q82S)K8Cd|s(k*x2~g@AvBv zl1CH3Rpd;qVzKz~->L8O;o+ePUuKrbW`fVi zqM-RzouJ&`-(P#ciMQ+o$~yrUE$teUld(|NMSdNuoR(_(yQfn;M+^dj^sVI7We(n$i%k7S&sd<5^duoYdS(=jKw9*6>g(U-yqNOC) z$t;{?>qU`$<1GA2r@nU*mXIMN=))V14f=4r*LT@(7=xLG;_HeuMsDMM!AIJIj+ z-`aK91W&7fuzLz$U`I&ND}KE^SwwMKU=uto54IuPy_rRDh0p@0&C}8Xm)bw*$iH1o zujaJQW@&S55sxI9h2znyIlX2UHpdq6NTS^USeB<1wpTUrpfqe!iaLA_ZvBkld~lhZ zpF%t`^;e5_9bT5F6}DG3@u235?{~1Uza|=*>cZb3SXT?YEKe(JugVe5m2@KfhX)Ho z@W>Wszd=xStsT;;;yUxe!J7-$vX1B$+n4|4^{FA9&C=_%S$Gv%UgtA13$IiA zt9W*1;ZQ8bmrI=+zT z9%pIy_a(shlL!-0X8zg|h$sEc;L`8BK;WetRm=0VB}580$ppr4fxLNn~&jVDeU zEM9H+KsFT*Zf$RGk1(8%JPkB`<2~{0FeYC?Y7t~69vrU$oKh3CHY3NAPD{&z$sM_P z-@%0@)71V7V0ptG@80a)V&HhGRB|UaHZVDHrOD-TdyttEaD%eK!k;1k#DG)4tbieX zh|K@q4~vtSMgTu5m&+Z$@H4>bCc$B4&fHZTbyaS1&QS@A_V9h}K0ZF4)oQg-P~N|w WSfpXwp?D_%0000 Date: Wed, 17 Apr 2024 18:07:03 -0700 Subject: [PATCH 28/34] [saved] Implement saved story button (#79) * Implemented save story button * Move story image to assets * Add save story to preview card, one home screen viewing bug * Add pubsub to sync preview and content cards * Bug fixes * Refactor * Create SavedStoryButton componenet * Remove unused imports * Fix type errors --------- Co-authored-by: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> Co-authored-by: Aditya Pawar --- .../save_story.png | Bin assets/saved_story.png | Bin 0 -> 12911 bytes package-lock.json | 9 +++ package.json | 3 +- src/app/(tabs)/author/index.tsx | 1 + src/app/(tabs)/genre/index.tsx | 1 + src/app/(tabs)/home/index.tsx | 3 + src/app/(tabs)/search/index.tsx | 4 +- src/app/_layout.tsx | 13 ++-- src/components/AuthorCard/AuthorCard.tsx | 4 +- src/components/ContentCard/ContentCard.tsx | 16 ++--- src/components/PreviewCard/PreviewCard.tsx | 16 ++--- .../PreviewCard/savedStoriesIcon.png | Bin 1052 -> 0 bytes src/components/PreviewCard/styles.ts | 2 + .../SaveStoryButton/SaveStoryButton.tsx | 64 ++++++++++++++++++ src/queries/reactions.tsx | 2 +- src/queries/savedStories.tsx | 54 ++++++++++++--- src/utils/PubSubContext.tsx | 57 ++++++++++++++++ 18 files changed, 209 insertions(+), 40 deletions(-) rename src/components/ContentCard/savedStoriesIcon.png => assets/save_story.png (100%) create mode 100644 assets/saved_story.png delete mode 100644 src/components/PreviewCard/savedStoriesIcon.png create mode 100644 src/components/SaveStoryButton/SaveStoryButton.tsx create mode 100644 src/utils/PubSubContext.tsx diff --git a/src/components/ContentCard/savedStoriesIcon.png b/assets/save_story.png similarity index 100% rename from src/components/ContentCard/savedStoriesIcon.png rename to assets/save_story.png diff --git a/assets/saved_story.png b/assets/saved_story.png new file mode 100644 index 0000000000000000000000000000000000000000..46c3e7b053fe8b9c8b2a5a15994de304b40a3767 GIT binary patch literal 12911 zcmeHuc{tSV+c(opjZqPU$vQ<6$#f@MmWhl~mML3=k(P-pWsQm%)ZG}{-EL5M}G(m zG(mT@JH+>VIR4Znc`1SMqsgbeN)=4c|xLCJoX0j?MOq< z)JT2Gp1OqU;9TAF!w+H>lbWL_C-Lt2t~k};T91+Ud36exmo(-_)CIg|`VbnM@!|O0 zusHpt!R3;BSF#>c_o|ZfXAulKYqV{R{nx2dCxy$Luw}4*xB#UFF6s7V)K5cB=V2S^ zpK`@lj@2a1<2a8(WJ$wH@M@KSq&=|^-*!T0Q!YHwogSI@u3Y{;*X6*%2Ea<%r0A>H z6ADmSE9Sb~VT;J^skV9xFXkJz2P}X8Ha~ruj$jBQRDh-BH+?>PI<*dTNf+on~ zsf(TwO;3WV^YyApN*MJXnIvy|ZN+PSO@o((#eNWbOl#QuswP?-vfatOIgBGY;;ZIW z`_d!oXvyBG%fC{C;@8b~jqAgaqF7umUgjUW9uIN)v7MbiX~fWg(XU38A17Qm$6MA- z3_(Niq_vcjrJZm^R*oM|?C)1UXZUy65PWbY zjC1>F-6D;+8;4JYPj*8qfiq5ijFVmNI9Qjk z%PL?0WC@Er-)p7tW}89lSLaiglqXBL2h^t27!pIxIV&1TUAd&v-M2|Yx|wCmdQKWZ zJIJ+L9!*4SMldAG*>0VA`}W*+k@4`+5rIC5-pOZv(cWS7)9~piXQfc4X?r2&lHV8G zG`mXg(?3I@5!lAP>6Mj%i?i=zNSYaHgaWaE_JQ?V0MCLj8Ki8*x3&zC(}jCZwp=aE z3w`y*HZ#D9-6zhqA2)bsP@zG{z+{Z2GA5rSgL-9~88eq91szR*(hEyEW*|M*$FWE% zT->NQrPJl_6fDQ(3PZroMr@L5g)`BCJ}&m}}1S zIi}y|8SZijVh0>mBmTUn1x^}=5i+guIeuD+%ccqHp|Ba1jc1L%N*YN@@wC61oZ`o2 zLJ+2ilnsPtV8IN<3CC>S3`NvKlo^#6M{4QStC$^-u%{8apIKUPH+dySu3@v&DrXwk z7^4U>s}&o>V@fPiZgUwJl4xJ*P9PQU#fj0Ty&YO1#fLN7VbQ*5Eer$-b9*tKZia8m z8*HB6;?8&}p|kwz^YENVSW6!3@$_rEmn0?hY^NIkNH2sRhVJ2%BR(ht2FIULtG9BG z6o8x&GAlw7jEQnGJ*wPY@VU(U138Oec9!=ht|1Cg%Hdi@n^{0g0)^zGvnsDhJXmWM%99!6@@R;Ln z)_#@Tb4!lmJRQ6AKk~IP1*=@?)2!dm8!hP|5v!~~*SEL%@w7yXYks&?=97^aWjT6e z=69{=T|CRuMNWvAU0+YA=6tpq#_jUtX$?+5>#Wpgi_{xB;yNqmn@_LP_UYB1`P_Fb zq@<&A#WYRKggN`Hq;j-S`@IFdzj>cVReTp?-q%ektmJ&klQ+~~l3?s9)Njsn(@^H> z2#$Ox*1q(dt!#cYB4LE4wK3r%SI&a42e5I&jiEgko*)!U8{1-D@cab=zK2VOB{d!= zgbCgm>vnpKKxzTfItD zwh%gKsrt)G<9jKZbb+ z?x?)g{r4)~JVBT{(!VTA%MrKO@R9Q_C?jU4^9WzmdP4peL_=?oihq1=9e!2&BPB5q z$JHyq((RO%JOTsGknu_N2`q4y^Yp6!E%#BS_>fleH4Dxjr6Cbr9s+f8oPdI6Msnaj)lF-6uJDPBjcoZ@AI;msZuQ=LT_rC`#lf7ERs;k z7gvt?O-K2uxf+sj=S#@VJ1_9C1fX^QqdY`O|s7iSI=sDcRura8q8Dc>X*&nQwS+)O{ze71e$Ds39UnKc@c9z<8GHy#ka? zh&k8YV*#~qS~EA9efq5=Z_2WLOb9|z#Cb$MErcg3W+NS17r(uGqpoYfx2JSEv$sLBvx`EqIVGRVR}})G2b_nEvNS)#H<4)Olddys z3NRP69d8{~G3K2VE$MKv{ZmG1lfJ7>u=zXwen;WAdMx+&*1qYQDf(c%fiJ&D%*R{n zwX$8Se_2bdp(cz(qpS{G;4hxUTp6LuqX^!NlSvWAd`wJLVqJ^ zNXzkVMvggO(&Fu*dnUoPNhOwL_QdA#}EaqJ+$P?mZ1*RnZ z$vL%syao12iqbb*nfdTnw*#xIl^*B+Izd@tjaILGR|xdE6ujkpS_t1Mk@Ou9h|l-l z4E$ag6a*lt@(xe2;MRKsd!4G&b#}Rrv+}9ujm20D-{j*D;&Jb`#n&zm#rqsiD9j6`p2ch9E+<4LCgYYptro1RmEaDuyEu(B$BYrJa(Hp z7IQNdj{r|j)D^N2{4YS>7=LpVkY|Ly1RWi24DKCvYPkSm2! z@VF;ykfQrHh|&+=kUipv$Eg}nP-DUbiM4DoK8Ej%^?kOhxk>jh*VoM;7S`Jo36 zi0KZI9Ld8|6|UyP7x_?)0SEb@qRGFedD6pQ;@`IPa1#0yTAF`#@syix$U|3A0s!J& zs2D!<@&sg^#@hs`h{Z&0j3V%_6`uZb_%T}~Fn||yV?{m(Jo9Sdy{F(WfFZgOGJeMb zJQa=c;{`XMOdO*T$>YG9YeD}W^JeP5+BCQN*J!i0{vUlaCw+zeI@P{t` z3Xu|}d;{R{b3?7qx0emB-j=@xKmUvwix;3|!d$C=HfPRCY~_RHu(crT&FW46UJCzz zUkd*>_wB!UJp=#uS_*;jZePjI?aX1qkBFKispZW#W>Qt5e@z>OTR$#@SHvDhZUR!o+z zE{z*_M2e3}(;^wOifDS9j4qW=Yu7{znO%)Lj6;>S?&iH;*GrAcfPt-5)Pz1>-Uhdc zk^#0TzBo!{M_%4o%uO8pki_VLxohUHlQgILcIH7r3gsG-E&=9V)ea|VCb%NKpz|>= zB3`XGeZfwfyG7FM>)WNq9VvtyLYWHFx;RTcklZZsr;;TRjC03QZgM%Bk$fXZyEt&R z8AQjW`Qp6O4oSh!o3Lm5ko5a6PDV=75A z<>;3i&{33CuxJZUGL>CCoaMx2BRN`Btu zP+ph91nl<@JUnB8OZ+>qWv z(w^k}68(F-?-C-kw?8InzJ4%rw8;9#Yh8N@mdb7a+5k9%cGZd91pd3S zk-W{AnC`Z=g+|g89ZI%R#ME6_Y(8269p57BNCsK;`dC{wsip2c`yd>y*mWEQqq5QW zHB;oHGQWJt^~|Oc?RUOb08gW{v~3_VK60l?GXzb$zcbsS0!`Pt`J;RdjG9n~LkP0S zs3WvKhBZ2jaA^;kzK9CBq=@N&9|2SEej2bMe*u<$ zMdFcdhDyIR!Q%i14N1s&wX^ONoN=b!%iCF);FlE4nMIi{ugeZz%_7r|2)7lH&}XroN1^v8 z#u*5Ehhu=88m4u3!{)pVblM}ePGb5~lK;%(?4&t`DWhMD_H{jlmp>9~2CfPrO@H(% zP}$E%jNXhP7<(}(Cr(fjsqD>Y^*51>0j)S|&E(HE4N4e`fb*0^NjhwuiJBV1Lx`|s zlHjY^eP4=pr6_s&E}XH=N@M>Nl^DO5{K=XkO=ag=E6L9G{W2zo)i~B;F|B{SrH+fz zQG;qJ+i|m`;vK-{-#QI2DaP#Kz};1cak=Mm?|xLmoLp`1tw`CnhS37%2lPoB6N8F6 zT{mG`4F}eai}PNuq+C{xCj?8SH0vAQyR#J$3|))RdnG7>B1>;F9d=|bA?eEI0rGO& z23ng;-7JztF1W7X+e2lC-?7}C$ZVk!`@rh?z2?Sja`h?OWCvXCar#NAO_-ar_68Ot za~3%Ve3$E%F(!6Sy-$u4qYvvZQ`&Z5*1^AMGEj%MVAjb2bTaZ%%OJP7KK8KOfwA3X zF1!g(8iTnxTqfIUrR?^~1Y1%r=? ziN;<@$+p&fIFekijH&Yug5?Pah^a!o0B1Ve%){|y!2$A}??}@co%-4BRQ9p0K0R<` zBw93fF~(G7Y-FU>0$48scra2KE9<2tnnB*BT^Qm3G6;$QcSNo6;2uF|K=+6}$Snk} z0qjswNV78$8)!|*vNx5%1D|&%n8G6&H62lzo4cNjWm1W)pGtIKa1T+@*jrXam0Y)= z*G>^6w2!hLz&EC#;J~PxSjHQTw+_G!9iBkd5()(o$(Y(3l}XXQ)oh>yj93(c%6MjX zO#*f^luVWfvUz!JbqwuwNx{Dz%~PJWD0}sUsMP*-!EYL}~ITojOM#Y4wCv z&;gE+b^t1^jN>tBj>`>r(q1pr>PGwbbv%X5`j{g66 zpsx}>1g*Ks2cF%vACK$&yDl2y$%*6v@l=^M+>%1l%s%6!CI~AMyJHUYeyT*hM#JuR z;+5n_83iLdFFtkAjRlurY+exndn_H_0(Oe(*eu-vp8p-|Avsa-#eh~vYPRsd_S-s; z{t|zS0qzT~`(3mI=?9*mRJL2|0j8p~!>2t#R;6U$dg%UehGo5AgS1w6af#n@_wrZ} zXroxpJNCKd!9F}L_eA`yy+B1fU|U`gZ?7!MtD$EllBdQIjD`B%cS53f%JBJs&%}jS zU&}7Ca<-=52F6T!2P=tE%pkw3*hv7GK-V3G!h~A5hme^u@v*v%ts5&R_nhNeAZ0D_ zJ0alkT1gf5a%hlcLP6KlGYwoTBv7Ua@B;jcCKl| z+v~86M@bWa79f93YArB&2wNbgl9&#VK)WnyB`z$LHhq6kU8WomS}O;3IuKL+?i7Nd z`r3mChQ8T~vjI#^*B#1g1y@uL(32pn60vv%)WGMF$s{cB1?>K8=qcKb&{_wW>JGAe zIQu6WIpmn`3Fa#sd{s@7qUXxynL;83As-;VtK0wizZZ=V23-Zl?EWE3op@l3qW7Ai zK#Exd%LCFsk^LWqiaXDkD_k|D?;^Y65?S%;34p0B2uW}zRb52M5ny*V+qflr<|~+& zjz>g-0*noaqvA~pK>EN*;w?b(laMdU`z7j($I%Qo{jR(G&$`V2&WTT}s(yZ~*z>XA zlv)m74tQ)Pw`S+WnT_K-3LURe+pyHkYcBxil>{|N2@yJqC7>V@NX{5QcE)RlE?1&> zY&OW|9&u9V{{k65bclW;zhZPA)h$BkJGM0WH70t*ugx|Znh$}MW&e!K?WFvkP$Q`K z;KlCjO}zQxcuR`Hui;%Rm95Vp{DnZ|7yy~CXZ?ZuL6c8N28+_YFZpJD-xPOu_9lO$ z7sz4}m$Zumy)_>vcY!M5ow7d(Q|vb^w`HVv`Df*DmsPJuOLYCUZ7sy)5P1YMf!p_zAg!xjBWA=_j zuRpd^j6S_~uLPfXg_*(1@nS;*v-kr^7b%scY%tJ+)1P#(P^;o&HKtlzg2%Za41s`3 z%le?z=&D}ux3?dojRN-M_eb8~H)1>yny8L>Izvln*!50JTK%+FM2QjVAb=^?q|VO4$Z&ondZoeW$)sch=e@C7DBf2pP{{l0$(KP7w@wh8NXW(u-W*f4%0Z7;HAB9 zU082S+I7vcCI3tq%owk|5Q<>TDHTYsGuZrl{qx9)YR8tg2|4<)-S0rd0^bTVKpTWQ z=)ox2`u#w=N!+^yKK(Ib&d|Ryr(~MOo|~KV_AvQfCO;w)B+J_ipPmD`{O+x;Izj1I zleB$yOnT-W#CbIMj@&#=+hKj~x2xvz)M2s)^nXZa#lASlx6cC zD}Ho&$TY`pIldc`<#l%<*Qz#tmh8;@HpY~`LxGM$JHMe1M;=@?^6wtp_+?q6 zS6UBKg1ESOj<9QbGan*|r11~e>ljkKmimkRZbu`CPAm0l4QIO_N^!G3z#i6%L%m>? z;ZN2mmbQe{y^rSaF9DmZX!PcMGpoG#WDVnKSA|0L$BRpEmnx;_kMr$=X-xXQH#V== zJ5ALV7-HRpUX_4-v3$2!FW$b?_Ur9xMj$0s`w5%BY85QBFVW}=Y3Kr@%8513r81u* z=EBNn??n*zm=BP9Wje=r8rICB4~ z2bY&e*O+d75q1_hu~@ARX&0WA8rnd##d%06 z%Leppj)hV|g0LT=4pKD7s4*&dn#R?6-Q-zsG~Qe#R|``jyyv?Drx!w-=)1qW#ZZXD zCcsk2p`oFrag(`I(gzGqhi?1eRbr#gZ!6S8#5xD(K@G=4wd)d$Zb@{}MCqNcA{j%K z{dg`r);IAVty^|ffp$b$+mhGnyo8dH&{+`Ei_;?+_Y8)xyn#{7`x#_AaO&LSg-&p; zBkS0tTd5>EgG2w);zQ{FU5ReOi)xL5hny%vYWU?`%l3OrJ{cp~vAN)x2!Z`}`@S_;3+4Fq3{$@rwIi=%Q zORk-}BSzO?%za=|3dmZ*b!TT9=2FSu z98Cx^nceX6)tgyl0*n0EM(~U`=jbCBu)zl_QZrr&Q-{N--|D{1aa{Ub3}VjuDeYG@ zNO9?UlsPs1*p-Q_;Wu})?F`+omy;VX`SH0Dr>4#$?zOmz^LoJdQ7S29wrk6j>cLqV zwJ@6n=Q9s-CeJx*U+FsQ>@UadhungYzc5!j3_9%9y)wqD!&8KHsV~bMNt{<6J|!ha1xm9WwmiTc2OZisON_R<{#@Y%E^i#S zv++}x?Fztkp1<={h{i>M2ELF8fvtxY!3}De_w6%ekjxB@qv_ShjA(TU#l6* zHQt3P%LApH^PITq<)P)4%6_hwP%X83cjzwj=$s7+Od&C)B{uTUb zBbcDbouE%~w@UVkH3*!;QddK0cQhU#QMT0-0fj=Y>IAChI JufUi@{VzM@4g>%I literal 0 HcmV?d00001 diff --git a/package-lock.json b/package-lock.json index f83fb7da..68298471 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "expo": "~49.0.11", "expo-constants": "~14.4.2", "expo-font": "~11.4.0", + "expo-image": "~1.3.5", "expo-linking": "~5.0.2", "expo-router": "^2.0.0", "expo-status-bar": "~1.6.0", @@ -11174,6 +11175,14 @@ "react-native": "*" } }, + "node_modules/expo-image": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/expo-image/-/expo-image-1.3.5.tgz", + "integrity": "sha512-yrIR2mnfIKbKcguoqWK3U5m3zvLPnonvSCabB2ErVGhws8zQs7ILYf+7T08j8U6eFcohjw0CoAFJ6RWNsX2EhA==", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-keep-awake": { "version": "12.3.0", "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-12.3.0.tgz", diff --git a/package.json b/package.json index ed0b39df..d15d3b50 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,8 @@ "react-native-vector-icons": "^10.0.2", "react-scroll-to-top": "^3.0.0", "use-debounce": "^10.0.0", - "validator": "^13.11.0" + "validator": "^13.11.0", + "expo-image": "~1.3.5" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/src/app/(tabs)/author/index.tsx b/src/app/(tabs)/author/index.tsx index 38b8b88e..7767637c 100644 --- a/src/app/(tabs)/author/index.tsx +++ b/src/app/(tabs)/author/index.tsx @@ -122,6 +122,7 @@ function AuthorScreen() { {authorStoryPreview?.map(story => ( ( ( router.push({ pathname: '/story', @@ -161,6 +163,7 @@ function HomeScreen() { title={story.title} author={story.author_name} authorImage={story.author_image} + storyId={story.id} pressFunction={() => router.push({ pathname: '/story', diff --git a/src/app/(tabs)/search/index.tsx b/src/app/(tabs)/search/index.tsx index a5114727..fdc5612d 100644 --- a/src/app/(tabs)/search/index.tsx +++ b/src/app/(tabs)/search/index.tsx @@ -306,6 +306,7 @@ function SearchScreen() { {recentlyViewed.map(item => ( ( - - - - - + + + + + + + diff --git a/src/components/AuthorCard/AuthorCard.tsx b/src/components/AuthorCard/AuthorCard.tsx index afdd2b57..99694abd 100644 --- a/src/components/AuthorCard/AuthorCard.tsx +++ b/src/components/AuthorCard/AuthorCard.tsx @@ -1,7 +1,5 @@ -import { Image, Pressable, Text, View } from 'react-native'; - +import { Image, Text, View } from 'react-native'; import styles from './styles'; -import globalStyles from '../../styles/globalStyles'; type AuthorCardProps = { name: string; diff --git a/src/components/ContentCard/ContentCard.tsx b/src/components/ContentCard/ContentCard.tsx index dd62a58b..c766751a 100644 --- a/src/components/ContentCard/ContentCard.tsx +++ b/src/components/ContentCard/ContentCard.tsx @@ -1,21 +1,23 @@ import { GestureResponderEvent, - Image, Pressable, Text, View, TouchableOpacity, } from 'react-native'; +import { Image } from 'expo-image'; import styles from './styles'; import globalStyles from '../../styles/globalStyles'; import Emoji from 'react-native-emoji'; +import SaveStoryButton from '../SaveStoryButton/SaveStoryButton'; type ContentCardProps = { title: string; author: string; image: string; authorImage: string; + storyId: number; pressFunction: (event: GestureResponderEvent) => void; }; @@ -24,12 +26,9 @@ function ContentCard({ author, image, authorImage, + storyId, pressFunction, }: ContentCardProps) { - const saveStory = () => { - console.log("testing '+' icon does something for story " + title); - }; - return ( @@ -76,11 +75,8 @@ function ContentCard({ - saveStory()}> - + + diff --git a/src/components/PreviewCard/PreviewCard.tsx b/src/components/PreviewCard/PreviewCard.tsx index dfe73227..71d6d057 100644 --- a/src/components/PreviewCard/PreviewCard.tsx +++ b/src/components/PreviewCard/PreviewCard.tsx @@ -1,16 +1,17 @@ import * as cheerio from 'cheerio'; import { GestureResponderEvent, - Image, Pressable, Text, TouchableOpacity, View, } from 'react-native'; import Emoji from 'react-native-emoji'; +import { Image } from 'expo-image'; import styles from './styles'; import globalStyles from '../../styles/globalStyles'; +import SaveStoryButton from '../SaveStoryButton/SaveStoryButton'; const placeholderImage = 'https://gwn-uploads.s3.amazonaws.com/wp-content/uploads/2021/10/10120952/Girls-Write-Now-logo-avatar.png'; @@ -18,6 +19,7 @@ const placeholderImage = type PreviewCardProps = { title: string; image: string; + storyId: number; author: string; authorImage: string; excerpt: { html: string }; @@ -28,16 +30,13 @@ type PreviewCardProps = { function PreviewCard({ title, image, + storyId, author, authorImage, excerpt, tags, pressFunction, }: PreviewCardProps) { - const saveStory = () => { - console.log("testing '+' icon does something for story " + title); - }; - return ( @@ -45,11 +44,8 @@ function PreviewCard({ {title} - saveStory()}> - + + diff --git a/src/components/PreviewCard/savedStoriesIcon.png b/src/components/PreviewCard/savedStoriesIcon.png deleted file mode 100644 index 65b2ea6e4dd47e1c590ef1cbe5d7afc29d8fcca7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1052 zcmV+%1mpXOP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91JfH&r1ONa40RR91JOBUy0E^%0TmS$AhDk(0RA>e5n@@7uFciimr$e`7 zhCjm&P7v1VhMpkVWYbNP6Eryi^aM>$(8;zeN=^{ENH^V(6Qo@wfn;E^B&pr+b1h;E2p>P%^ zpbQq?-QDePZEbx)!+h{wlCB94d0Rp7Dd53i@ClWUJ+Q82S)K8Cd|s(k*x2~g@AvBv zl1CH3Rpd;qVzKz~->L8O;o+ePUuKrbW`fVi zqM-RzouJ&`-(P#ciMQ+o$~yrUE$teUld(|NMSdNuoR(_(yQfn;M+^dj^sVI7We(n$i%k7S&sd<5^duoYdS(=jKw9*6>g(U-yqNOC) z$t;{?>qU`$<1GA2r@nU*mXIMN=))V14f=4r*LT@(7=xLG;_HeuMsDMM!AIJIj+ z-`aK91W&7fuzLz$U`I&ND}KE^SwwMKU=uto54IuPy_rRDh0p@0&C}8Xm)bw*$iH1o zujaJQW@&S55sxI9h2znyIlX2UHpdq6NTS^USeB<1wpTUrpfqe!iaLA_ZvBkld~lhZ zpF%t`^;e5_9bT5F6}DG3@u235?{~1Uza|=*>cZb3SXT?YEKe(JugVe5m2@KfhX)Ho z@W>Wszd=xStsT;;;yUxe!J7-$vX1B$+n4|4^{FA9&C=_%S$Gv%UgtA13$IiA zt9W*1;ZQ8bmrI=+zT z9%pIy_a(shlL!-0X8zg|h$sEc;L`8BK;WetRm=0VB}580$ppr4fxLNn~&jVDeU zEM9H+KsFT*Zf$RGk1(8%JPkB`<2~{0FeYC?Y7t~69vrU$oKh3CHY3NAPD{&z$sM_P z-@%0@)71V7V0ptG@80a)V&HhGRB|UaHZVDHrOD-TdyttEaD%eK!k;1k#DG)4tbieX zh|K@q4~vtSMgTu5m&+Z$@H4>bCc$B4&fHZTbyaS1&QS@A_V9h}K0ZF4)oQg-P~N|w WSfpXwp?D_%0000 { + isStoryInReadingList(storyId, user?.id).then(storyInReadingList => { + setStoryIsSaved(storyInReadingList); + initializeChannel(storyId); + }); + }, [storyId]); + + useEffect(() => { + // if another card updates this story, update it here also + if (typeof channels[storyId] !== 'undefined') { + setStoryIsSaved(channels[storyId] ?? false); + } + }, [channels[storyId]]); + + useEffect(() => { + isStoryInReadingList(storyId, user?.id).then(storyInReadingList => + setStoryIsSaved(storyInReadingList), + ); + }, [storyId]); + + const saveStory = async (saved: boolean) => { + setStoryIsSaved(saved); + publish(storyId, saved); // update other cards with this story + + if (saved) { + await addUserStoryToReadingList(user?.id, storyId); + } else { + await deleteUserStoryToReadingList(user?.id, storyId); + } + }; + + return ( + saveStory(!storyIsSaved)}> + {storyIsSaved ? ( + + ) : ( + + )} + + ); +} diff --git a/src/queries/reactions.tsx b/src/queries/reactions.tsx index 8a9da888..ffe68c40 100644 --- a/src/queries/reactions.tsx +++ b/src/queries/reactions.tsx @@ -53,7 +53,7 @@ export async function fetchAllReactionsToStory( `An error occured when trying to fetch reactions to a story', ${error}`, ); } else { - return data; + return data as Reactions[]; } } diff --git a/src/queries/savedStories.tsx b/src/queries/savedStories.tsx index 59f6ecaa..0416ecb8 100644 --- a/src/queries/savedStories.tsx +++ b/src/queries/savedStories.tsx @@ -1,7 +1,9 @@ import supabase from '../utils/supabase'; -const favorites = 'favorites'; -const readingList = 'reading list'; +enum SavedList { + FAVORITES = 'favorites', + READING_LIST = 'reading list', +} async function fetchUserStories( user_id: string | undefined, @@ -48,11 +50,11 @@ async function fetchUserStories( } export async function fetchUserStoriesFavorites(user_id: string | undefined) { - return await fetchUserStories(user_id, favorites); + return await fetchUserStories(user_id, SavedList.FAVORITES); } export async function fetchUserStoriesReadingList(user_id: string | undefined) { - return await fetchUserStories(user_id, readingList); + return await fetchUserStories(user_id, SavedList.READING_LIST); } async function addUserStory( @@ -62,13 +64,15 @@ async function addUserStory( ) { const { error } = await supabase .from('saved_stories') - .insert([{ user_id: user_id, story_id: story_id, name: name }]) + .upsert([{ user_id: user_id, story_id: story_id, name: name }]) .select(); if (error) { if (process.env.NODE_ENV !== 'production') { throw new Error( - `An error occured when trying to set user saved stories: ${error.details}`, + `An error occured when trying to set user saved stories: ${JSON.stringify( + error, + )}`, ); } } @@ -78,17 +82,31 @@ export async function addUserStoryToFavorites( user_id: string | undefined, story_id: number, ) { - addUserStory(user_id, story_id, favorites); + addUserStory(user_id, story_id, SavedList.FAVORITES); } export async function addUserStoryToReadingList( user_id: string | undefined, story_id: number, ) { - addUserStory(user_id, story_id, readingList); + addUserStory(user_id, story_id, SavedList.READING_LIST); +} + +export async function deleteUserStoryToFavorites( + user_id: string | undefined, + story_id: number, +) { + deleteUserStory(user_id, story_id, SavedList.FAVORITES); } -export async function deleteUserStories( +export async function deleteUserStoryToReadingList( + user_id: string | undefined, + story_id: number, +) { + deleteUserStory(user_id, story_id, SavedList.READING_LIST); +} + +export async function deleteUserStory( user_id: string | undefined, story_id: number, name: string, @@ -108,3 +126,21 @@ export async function deleteUserStories( } } } + +export async function isStoryInReadingList( + storyId: number, + userId: string | undefined, +): Promise { + let { data, error } = await supabase.rpc('is_story_saved_for_user', { + list_name: 'reading list', + story_db_id: storyId, + user_uuid: userId, + }); + + if (error) { + console.error(error); + return false; + } + + return data; +} diff --git a/src/utils/PubSubContext.tsx b/src/utils/PubSubContext.tsx new file mode 100644 index 00000000..fbb9ada6 --- /dev/null +++ b/src/utils/PubSubContext.tsx @@ -0,0 +1,57 @@ +import React, { createContext, useContext, useMemo, useState } from 'react'; + +export interface PubSubState { + channels: Record; + initializeChannel: (id: number) => void; + publish: (id: number, message: boolean) => void; +} + +const BooleanPubSubContext = createContext({} as PubSubState); + +export function usePubSub() { + const value = useContext(BooleanPubSubContext); + if (process.env.NODE_ENV !== 'production') { + if (!value) { + throw new Error( + 'usePubSub must be wrapped in a ', + ); + } + } + + return value; +} + +export function BooleanPubSubProvider({ + children, +}: { + children: React.ReactNode; +}) { + const [channels, setChannels] = useState>( + {}, + ); + + const initializeChannel = (id: number) => { + if (!(id in channels)) { + setChannels({ ...channels, [id]: undefined }); + } + }; + + const publish = (id: number, message: boolean) => { + setChannels({ ...channels, [id]: message }); + }; + + const authContextValue = useMemo( + () => ({ + channels, + initializeChannel, + publish, + }), + [channels], + ); + + return ( + + {children} + + ); +} From 9cc1b1a05e002f992873c7949ffd2519f651baa0 Mon Sep 17 00:00:00 2001 From: Aditya Pawar <34043950+adityapawar1@users.noreply.github.com> Date: Thu, 18 Apr 2024 21:34:15 -0700 Subject: [PATCH 29/34] [bug] Bug bash changes (#86) * Bug bash changes * Change link back to login --- src/app/(tabs)/story/index.tsx | 39 ++++++++++++++++++++++-------- src/app/auth/onboarding/index.tsx | 13 ++++++++++ src/app/auth/onboarding/styles.tsx | 4 +++ src/app/auth/signup/index.tsx | 4 +-- 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/app/(tabs)/story/index.tsx b/src/app/(tabs)/story/index.tsx index 2387f2f1..2995426d 100644 --- a/src/app/(tabs)/story/index.tsx +++ b/src/app/(tabs)/story/index.tsx @@ -89,7 +89,12 @@ function StoryScreen() { style={styles.authorImage} source={{ uri: story.author_image ? story.author_image : '' }} /> - + By {story.author_name} @@ -161,15 +166,29 @@ function StoryScreen() { systemFonts={fonts} /> - - - - By {story.author_name} - - + { + router.push({ + pathname: '/author', + params: { author: story.author_id.toString() }, + }); + }} + > + + + + By {story.author_name} + + +