diff --git a/app.json b/app.json index d8e36a6e..6a1cdecc 100644 --- a/app.json +++ b/app.json @@ -17,10 +17,12 @@ "supportsTablet": true }, "android": { + "softwareKeyboardLayoutMode": "pan", "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#ffffff" - } + }, + "softwareKeyboardLayoutMode": "pan" }, "web": { "favicon": "./assets/favicon.png" diff --git a/assets/Frame 88.svg b/assets/Frame 88.svg new file mode 100644 index 00000000..3b243e9f --- /dev/null +++ b/assets/Frame 88.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/bx_x.svg b/assets/bx_x.svg new file mode 100644 index 00000000..2f3f79e8 --- /dev/null +++ b/assets/bx_x.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/formkit_hidden.svg b/assets/formkit_hidden.svg new file mode 100644 index 00000000..2df2a82c --- /dev/null +++ b/assets/formkit_hidden.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/icons.tsx b/assets/icons.tsx index 03a92b5f..05654a56 100644 --- a/assets/icons.tsx +++ b/assets/icons.tsx @@ -6,12 +6,18 @@ export type IconType = | 'home_outline' | 'document_outline' | 'search_outline' - | 'close_modal_button'; + | 'close_modal_button' + | 'red_x' + | 'green_check' + | 'hide_password' + | 'grey_dot' + | 'settings_gear'; const IconSvgs: Record = { home_outline: , search_outline: , document_outline: , + settings_gear: , close_modal_button: ( = { `} /> ), + red_x: ( + + + + + `} + /> + ), + green_check: ( + + + + + `} + /> + ), + hide_password: ( + + + + + + + `} + /> + ), + grey_dot: ( + + + + + `} + /> + ), }; type Props = { className?: string; diff --git a/assets/material-symbols_check.svg b/assets/material-symbols_check.svg new file mode 100644 index 00000000..ac8060ab --- /dev/null +++ b/assets/material-symbols_check.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/package-lock.json b/package-lock.json index d85cab47..c3b4e9ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@mui/material": "^5.14.13", "@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-async-storage/async-storage": "^1.19.5", "@react-native-community/datetimepicker": "7.2.0", "@react-navigation/bottom-tabs": "^6.5.9", "@react-navigation/material-bottom-tabs": "^6.2.17", @@ -24,6 +24,7 @@ "@react-navigation/stack": "^6.3.18", "@rneui/themed": "^4.0.0-rc.8", "@supabase/supabase-js": "^2.36.0", + "@types/validator": "^13.11.5", "axios": "^1.5.0", "deprecated-react-native-prop-types": "^4.2.1", "dom-parser": "^0.1.6", @@ -40,6 +41,7 @@ "react-native-gesture-handler": "~2.12.0", "react-native-htmlview": "^0.16.0", "react-native-ionicons": "^4.6.5", + "react-native-otp-textinput": "^1.1.3", "react-native-paper": "^5.10.6", "react-native-render-html": "^6.3.4", "react-native-root-siblings": "^4.1.1", @@ -48,7 +50,8 @@ "react-native-screens": "~3.22.0", "react-native-svg": "13.9.0", "react-native-url-polyfill": "^2.0.0", - "react-native-vector-icons": "^10.0.0", + "validator": "^13.11.0", + "react-native-vector-icons": "^10.0.2", "react-scroll-to-top": "^3.0.0" }, "devDependencies": { @@ -61,6 +64,7 @@ "eslint-config-universe": "^12.0.0", "husky": "^8.0.3", "prettier": "^3.0.3", + "supabase": "^1.110.1", "typescript": "^5.1.3" } }, @@ -4767,9 +4771,9 @@ } }, "node_modules/@react-native-async-storage/async-storage": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.18.2.tgz", - "integrity": "sha512-dM8AfdoeIxlh+zqgr0o5+vCTPQ0Ru1mrPzONZMsr7ufp5h+6WgNxQNza7t0r5qQ6b04AJqTlBNixTWZxqP649Q==", + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.19.5.tgz", + "integrity": "sha512-zLT7oNPXpW8BxJyHyq8AJbXtlHE/eonFWuJt44y0WeCGnp4KOJ8mfqD8mtAIKLyrYHHE1uadFe/s4C+diYAi8g==", "dependencies": { "merge-options": "^3.0.4" }, @@ -7326,6 +7330,11 @@ "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.20.tgz", "integrity": "sha512-77Mq/2BeHU894J364dUv9tSwxxyCLtcX228Pc8TwZpP5bvOoMns+gZoftp3LYl3FBH8vChpWbuagKGiMki2c1A==" }, + "node_modules/@types/validator": { + "version": "13.11.5", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.5.tgz", + "integrity": "sha512-xW4qsT4UIYILu+7ZrBnfQdBYniZrMLYYK3wN9M/NdeIHgBN5pZI2/8Q7UfdWIcr5RLJv/OGENsx91JIpUUoC7Q==" + }, "node_modules/@types/websocket": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.7.tgz", @@ -8379,6 +8388,46 @@ "node": ">=0.6" } }, + "node_modules/bin-links": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-4.0.3.tgz", + "integrity": "sha512-obsRaULtJurnfox/MDwgq6Yo9kzbv1CPTk/1/s7Z/61Lezc8IKkFCOXNeVLXz0456WRzBQmSsDWlai2tIhBsfA==", + "dev": true, + "dependencies": { + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/bin-links/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/bin-links/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -8906,6 +8955,15 @@ "node": ">=6" } }, + "node_modules/cmd-shim": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-6.0.2.tgz", + "integrity": "sha512-+FFYbB0YLaAkhkcrjkyNLYDiOsFSfRjwjY19LXk/psmMx1z00xlCv7hhQoTGXXIKi+YXHL/iiFo8NqMVQX9nOw==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/color": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", @@ -9298,6 +9356,15 @@ "resolved": "https://registry.npmjs.org/dag-map/-/dag-map-1.0.2.tgz", "integrity": "sha512-+LSAiGFwQ9dRnRdOeaj7g47ZFJcOUPukAP8J3A3fuZ1g9Y44BG+P1sgApjLXTQPOzC4+7S9Wr8kXsfpINM4jpw==" }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/dayjs": { "version": "1.11.10", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", @@ -11209,6 +11276,29 @@ "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/fetch-retry": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-4.1.1.tgz", @@ -11433,6 +11523,18 @@ "node": ">= 6" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/freeport-async": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/freeport-async/-/freeport-async-2.0.0.tgz", @@ -14996,6 +15098,25 @@ "node": ">= 0.10.5" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -15063,6 +15184,15 @@ "node": ">=0.10.0" } }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/npm-package-arg": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-7.0.0.tgz", @@ -16289,6 +16419,17 @@ "react-native": "*" } }, + "node_modules/react-native-otp-textinput": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/react-native-otp-textinput/-/react-native-otp-textinput-1.1.3.tgz", + "integrity": "sha512-C32Tz9spngydOpiyjI20SCDDJ5vGGkR0EBYM0ynVhyPZ8gUHZEfz7zxdtvGhAp+PKiU7d6rvI3i5ZpTQJpPg+g==", + "dependencies": { + "react": "^18.2.0" + }, + "peerDependencies": { + "react-native": "^0.72.4" + } + }, "node_modules/react-native-paper": { "version": "5.10.6", "resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.10.6.tgz", @@ -16420,9 +16561,9 @@ } }, "node_modules/react-native-vector-icons": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-10.0.0.tgz", - "integrity": "sha512-efMOVbZIebY8RszZPzPBoXi9pvD/NFYmjIDYxRoc9LYSzV8rMJtT8FfcO2hPu85Rn2x9xktha0+qn0B7EqMAcQ==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-10.0.2.tgz", + "integrity": "sha512-ZwhUkJhIMkGL3cW7IT4sEEHu2AOzerqsRQ73UzXsB+ecBpVK5bRmp0XswiQleZKZalZfs/WIfWLXLfTQHcQo6A==", "dependencies": { "prop-types": "^15.7.2", "yargs": "^16.1.1" @@ -16554,6 +16695,15 @@ "react-dom": ">=16.6.0" } }, + "node_modules/read-cmd-shim": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz", + "integrity": "sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -17770,6 +17920,68 @@ "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-8.2.5.tgz", "integrity": "sha512-rlBo3HU/1zAJUrkY6jNxDOC9eVYliG6nS4JA8u8KAshITd07tafMc/Br7xQwCSseXwJ2iCcHCE8SNWX3q8Z+kw==" }, + "node_modules/supabase": { + "version": "1.110.1", + "resolved": "https://registry.npmjs.org/supabase/-/supabase-1.110.1.tgz", + "integrity": "sha512-pQVfbs/n8ZBDuSDv6YJKIH1Uh/QBRxjp6pLW52YkKgjgfwndlKwKuJoPiuWDxBkRG1QXxmCHi3Hk+JeNx9/FRg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bin-links": "^4.0.1", + "https-proxy-agent": "^7.0.2", + "node-fetch": "^3.2.10", + "tar": "6.2.0" + }, + "bin": { + "supabase": "bin/supabase" + }, + "engines": { + "npm": ">=8" + } + }, + "node_modules/supabase/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/supabase/node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/supabase/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -18583,6 +18795,14 @@ "builtins": "^1.0.3" } }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -18617,6 +18837,15 @@ "defaults": "^1.0.3" } }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", diff --git a/package.json b/package.json index d978c864..4f7a1498 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "@react-navigation/stack": "^6.3.18", "@rneui/themed": "^4.0.0-rc.8", "@supabase/supabase-js": "^2.36.0", + "@types/validator": "^13.11.5", "axios": "^1.5.0", "deprecated-react-native-prop-types": "^4.2.1", "dom-parser": "^0.1.6", @@ -44,6 +45,7 @@ "react-native-gesture-handler": "~2.12.0", "react-native-htmlview": "^0.16.0", "react-native-ionicons": "^4.6.5", + "react-native-otp-textinput": "^1.1.3", "react-native-paper": "^5.10.6", "react-native-render-html": "^6.3.4", "react-native-root-siblings": "^4.1.1", @@ -52,7 +54,8 @@ "react-native-screens": "~3.22.0", "react-native-svg": "13.9.0", "react-native-url-polyfill": "^2.0.0", - "react-native-vector-icons": "^10.0.0", + "validator": "^13.11.0", + "react-native-vector-icons": "^10.0.2", "react-scroll-to-top": "^3.0.0" }, "devDependencies": { @@ -65,6 +68,7 @@ "eslint-config-universe": "^12.0.0", "husky": "^8.0.3", "prettier": "^3.0.3", + "supabase": "^1.110.1", "typescript": "^5.1.3" }, "private": true diff --git a/src/app/(tabs)/home/index.tsx b/src/app/(tabs)/home/index.tsx index 63953427..a8a37052 100644 --- a/src/app/(tabs)/home/index.tsx +++ b/src/app/(tabs)/home/index.tsx @@ -1,102 +1,166 @@ -import { Link } from 'expo-router'; -import { Button, ScrollView, Text, View } from 'react-native'; +import { router } from 'expo-router'; +import { useEffect, useState } from 'react'; +import { Pressable, ScrollView, Text, View } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import styles from './styles'; +import Icon from '../../../../assets/icons'; import ContentCard from '../../../components/ContentCard/ContentCard'; -import SearchCard from '../../../components/SearchCard/SearchCard'; +import PreviewCard from '../../../components/PreviewCard/PreviewCard'; +import RecentSearchCard from '../../../components/RecentSearchCard/RecentSearchCard'; +import { fetchUsername } from '../../../queries/profiles'; +import { + fetchFeaturedStoriesDescription, + fetchFeaturedStoryPreviews, + fetchNewStories, + fetchRecommendedStories, +} from '../../../queries/stories'; +import { StoryCard, StoryPreview } from '../../../queries/types'; import globalStyles from '../../../styles/globalStyles'; - -const dummyStories = [ - { - title: 'The Witch and Her Wings', - author: 'Victoria V.', - image: '', - author_image: '', - tags: ['Non-fiction', 'Mysterious', 'Goofy', 'Silly', 'Adventurous'], - }, - { - title: "It's Carnival", - author: 'Victoria V.', - image: '', - author_image: '', - tags: ['Non-fiction', 'Mysterious'], - }, - { - title: "Akshay's Adventures", - author: 'Victoria V.', - image: '', - author_image: '', - tags: ['Non-fiction', 'Mysterious'], - }, -]; +import { useSession } from '../../../utils/AuthContext'; function HomeScreen() { + const { user } = useSession(); + const [username, setUsername] = useState(''); + const [loading, setLoading] = useState(true); + const [featuredStories, setFeaturedStories] = useState([]); + const [featuredStoriesDescription, setFeaturedStoriesDescription] = + useState(''); + const [recommendedStories, setRecommendedStories] = useState([]); + const [newStories, setNewStories] = useState([]); + + useEffect(() => { + (async () => { + const [ + usernameResponse, + featuredStoryResponse, + featuredStoryDescriptionResponse, + recommendedStoriesResponse, + newStoriesResponse, + ] = await Promise.all([ + fetchUsername(user?.id).catch(() => ''), + fetchFeaturedStoryPreviews().catch(() => []), + fetchFeaturedStoriesDescription().catch(() => ''), + fetchRecommendedStories().catch(() => []), + fetchNewStories().catch(() => []), + ]); + setUsername(usernameResponse); + setFeaturedStories(featuredStoryResponse); + setFeaturedStoriesDescription(featuredStoryDescriptionResponse); + setRecommendedStories(recommendedStoriesResponse); + setNewStories(newStoriesResponse); + })().finally(() => { + setLoading(false); + }); + }, [user]); return ( - + + {loading && ( + + Loading + + )} - Welcome, Brenda - -