diff --git a/components/BeerById/BeerPostCommentsSection.tsx b/components/BeerById/BeerPostCommentsSection.tsx deleted file mode 100644 index bfeb7c9..0000000 --- a/components/BeerById/BeerPostCommentsSection.tsx +++ /dev/null @@ -1,117 +0,0 @@ -/* eslint-disable no-nested-ternary */ -import UserContext from '@/contexts/userContext'; - -import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult'; - -import { FC, MutableRefObject, useContext, useRef } from 'react'; -import { z } from 'zod'; -import useBeerPostComments from '@/hooks/useBeerPostComments'; -import { useRouter } from 'next/router'; -import { useInView } from 'react-intersection-observer'; -import BeerCommentForm from './BeerCommentForm'; - -import CommentCardBody from './CommentCardBody'; -import NoCommentsCard from './NoCommentsCard'; -import CommentLoadingCardBody from './CommentLoadingCardBody'; -import Spinner from '../ui/Spinner'; - -interface BeerPostCommentsSectionProps { - beerPost: z.infer; -} - -const LoadingComponent: FC<{ length: number }> = ({ length }) => { - return ( - <> - {Array.from({ length }).map((_, i) => ( - - ))} -
- -
- - ); -}; - -const BeerPostCommentsSection: FC = ({ beerPost }) => { - const { user } = useContext(UserContext); - const router = useRouter(); - const { id } = beerPost; - const pageNum = parseInt(router.query.comments_page as string, 10) || 1; - const PAGE_SIZE = 6; - - const { comments, isLoading, mutate, setSize, size, isLoadingMore, isAtEnd } = - useBeerPostComments({ - id, - pageNum, - pageSize: PAGE_SIZE, - }); - - const { ref } = useInView({ - delay: 3000, - onChange: (visible) => { - if (!visible || isAtEnd) return; - setSize(size + 1); - }, - }); - - const sectionRef: MutableRefObject = useRef(null); - return ( -
-
-
- {user ? ( - - ) : ( -
- Log in to leave a comment. -
- )} -
-
- - {comments && !!comments.length && !isLoading && ( -
- {comments.map((comment, index) => { - const isLastComment = index === comments.length - 1; - - return ( -
- -
- ); - })} - - {!!isLoadingMore && ( -
- -
- )} - - {isAtEnd && ( -
- -
- )} -
- )} - - {!comments?.length && !isLoading && } - - {isLoading && ( -
- -
- )} -
- ); -}; - -export default BeerPostCommentsSection; diff --git a/package-lock.json b/package-lock.json index c29ccf7..79eb09d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "version": "0.1.0", "dependencies": { "@hapi/iron": "^7.0.1", + "@headlessui/react": "^1.7.13", + "@headlessui/tailwindcss": "^0.1.2", "@hookform/resolvers": "^3.0.0", "@prisma/client": "^4.12.0", "@react-email/components": "^0.0.4", @@ -36,6 +38,7 @@ "react-hook-form": "^7.43.9", "react-icons": "^4.8.0", "react-intersection-observer": "^9.4.3", + "react-responsive-carousel": "^3.2.23", "sparkpost": "^2.1.4", "swr": "^2.1.2", "zod": "^3.21.4" @@ -52,6 +55,7 @@ "@types/react": "^18.0.33", "@types/react-dom": "^18.0.11", "@types/sparkpost": "^2.1.5", + "@vercel/fetch": "^6.2.0", "autoprefixer": "^10.4.14", "daisyui": "^2.51.5", "dotenv-cli": "^7.1.0", @@ -647,6 +651,32 @@ "@hapi/hoek": "^11.0.2" } }, + "node_modules/@headlessui/react": { + "version": "1.7.13", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.13.tgz", + "integrity": "sha512-9n+EQKRtD9266xIHXdY5MfiXPDfYwl7zBM7KOx2Ae3Gdgxy8QML1FkCMjq6AsOf0l6N9uvI4HcFtuFlenaldKg==", + "dependencies": { + "client-only": "^0.0.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16 || ^17 || ^18", + "react-dom": "^16 || ^17 || ^18" + } + }, + "node_modules/@headlessui/tailwindcss": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@headlessui/tailwindcss/-/tailwindcss-0.1.2.tgz", + "integrity": "sha512-AQNESz+f1grCxifrocOE6hDMDFqhqY0g3xrSGOS0ocGkmVkssaBzXaAPAPNSs/nHmr4ZUhfl5THQpYrvaouWlQ==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "tailwindcss": "^3.0" + } + }, "node_modules/@hookform/resolvers": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.0.0.tgz", @@ -1558,6 +1588,15 @@ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", "devOptional": true }, + "node_modules/@types/async-retry": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@types/async-retry/-/async-retry-1.4.5.tgz", + "integrity": "sha512-YrdjSD+yQv7h6d5Ip+PMxh3H6ZxKyQk0Ts+PvaNRInxneG9PFVZjFg77ILAN+N6qYf7g4giSJ1l+ZjQ1zeegvA==", + "dev": true, + "dependencies": { + "@types/retry": "*" + } + }, "node_modules/@types/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", @@ -1655,6 +1694,12 @@ "integrity": "sha512-km+Vyn3BYm5ytMO13k9KTp27O75rbQ0NFw+U//g+PX7VZyjCioXaRFisqSIJRECljcTv73G3i6BpglNGHgUQ5A==", "dev": true }, + "node_modules/@types/lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-8mNEUG6diOrI6pMqOHrHPDBB1JsrpedeMK9AWGzVCQ7StRRribiT9BRvUmF8aUws9iBbVlgVekOT5Sgzc1MTKw==", + "dev": true + }, "node_modules/@types/mdast": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", @@ -1691,6 +1736,30 @@ "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", "devOptional": true }, + "node_modules/@types/node-fetch": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz", + "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==", + "dev": true, + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", @@ -1776,6 +1845,12 @@ "form-data": "^2.5.0" } }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true + }, "node_modules/@types/scheduler": { "version": "0.16.3", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", @@ -2012,6 +2087,107 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@vercel/fetch": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@vercel/fetch/-/fetch-6.2.0.tgz", + "integrity": "sha512-MU+Mzh06NIAXxwdnyHmBFg+/lTKBbzDkCSNhAwWTFJ4rHuBc4pHc8E6XP+qnwqaWugjOBQgFfQCGDLnV820c9A==", + "dev": true, + "dependencies": { + "@types/async-retry": "^1.4.3", + "@vercel/fetch-cached-dns": "^2.0.2", + "@vercel/fetch-retry": "^5.0.3", + "agentkeepalive": "^4.2.1", + "debug": "^4.3.3" + }, + "peerDependencies": { + "@types/node-fetch": "^2.6.1", + "node-fetch": "^2.6.7" + } + }, + "node_modules/@vercel/fetch-cached-dns": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vercel/fetch-cached-dns/-/fetch-cached-dns-2.1.2.tgz", + "integrity": "sha512-8JHBmYuXYGlyRupRgnyRML84NL1SBi3lVedYhPaWb+6HwMsYF5/PXfQ9M9GPrXsZ8bqKpLQH9tQcVpZmAUJzeQ==", + "dev": true, + "dependencies": { + "@types/node-fetch": "^2.6.1", + "@zeit/dns-cached-resolve": "^2.1.2" + }, + "peerDependencies": { + "node-fetch": "^2.6.1" + } + }, + "node_modules/@vercel/fetch-retry": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@vercel/fetch-retry/-/fetch-retry-5.1.3.tgz", + "integrity": "sha512-UIbFc4VsEZHOr6dWuE+kxY4NxnOLXFMCWm0fSKRRHUEtrIzaJLzHpWk2QskCXTSzFgFvhkLAvSrBK2XZg7NSzg==", + "dev": true, + "dependencies": { + "async-retry": "^1.3.3", + "debug": "^4.3.3" + }, + "peerDependencies": { + "node-fetch": "^2.6.7" + } + }, + "node_modules/@zeit/dns-cached-resolve": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@zeit/dns-cached-resolve/-/dns-cached-resolve-2.1.2.tgz", + "integrity": "sha512-A/5gbBskKPETTBqHwvlaW1Ri2orO62yqoFoXdxna1SQ7A/lXjpWgpJ1wdY3IQEcz5LydpS4sJ8SzI2gFyyLEhg==", + "dev": true, + "dependencies": { + "@types/async-retry": "1.2.1", + "@types/lru-cache": "4.1.1", + "@types/node": "10.12.18", + "async-retry": "1.2.3", + "lru-cache": "5.1.1" + } + }, + "node_modules/@zeit/dns-cached-resolve/node_modules/@types/async-retry": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/async-retry/-/async-retry-1.2.1.tgz", + "integrity": "sha512-yMQ6CVgICWtyFNBqJT3zqOc+TnqqEPLo4nKJNPFwcialiylil38Ie6q1ENeFTjvaLOkVim9K5LisHgAKJWidGQ==", + "dev": true + }, + "node_modules/@zeit/dns-cached-resolve/node_modules/@types/node": { + "version": "10.12.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==", + "dev": true + }, + "node_modules/@zeit/dns-cached-resolve/node_modules/async-retry": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.2.3.tgz", + "integrity": "sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q==", + "dev": true, + "dependencies": { + "retry": "0.12.0" + } + }, + "node_modules/@zeit/dns-cached-resolve/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@zeit/dns-cached-resolve/node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@zeit/dns-cached-resolve/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -2098,6 +2274,20 @@ "node": ">= 6.0.0" } }, + "node_modules/agentkeepalive": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", + "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "depd": "^2.0.0", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -2334,6 +2524,15 @@ "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", "dev": true }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "dev": true, + "dependencies": { + "retry": "0.13.1" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2753,6 +2952,11 @@ "node": ">=10" } }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -3206,7 +3410,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "optional": true, + "devOptional": true, "engines": { "node": ">= 0.8" } @@ -5258,6 +5462,15 @@ "node": ">=10.17.0" } }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -8013,7 +8226,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -8205,6 +8417,17 @@ "react": "^18.2.0" } }, + "node_modules/react-easy-swipe": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/react-easy-swipe/-/react-easy-swipe-0.0.21.tgz", + "integrity": "sha512-OeR2jAxdoqUMHIn/nS9fgreI5hSpgGoL5ezdal4+oO7YSSgJR8ga+PkYGJrSrJ9MKlPcQjMQXnketrD7WNmNsg==", + "dependencies": { + "prop-types": "^15.5.8" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/react-email": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/react-email/-/react-email-1.9.0.tgz", @@ -8353,14 +8576,23 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-property": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.0.tgz", "integrity": "sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw==" }, + "node_modules/react-responsive-carousel": { + "version": "3.2.23", + "resolved": "https://registry.npmjs.org/react-responsive-carousel/-/react-responsive-carousel-3.2.23.tgz", + "integrity": "sha512-pqJLsBaKHWJhw/ItODgbVoziR2z4lpcJg+YwmRlSk4rKH32VE633mAtZZ9kDXjy4wFO+pgUZmDKPsPe1fPmHCg==", + "dependencies": { + "classnames": "^2.2.5", + "prop-types": "^15.5.8", + "react-easy-swipe": "^0.0.21" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -8602,6 +8834,15 @@ "node": ">=8" } }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -10478,6 +10719,20 @@ "@hapi/hoek": "^11.0.2" } }, + "@headlessui/react": { + "version": "1.7.13", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.13.tgz", + "integrity": "sha512-9n+EQKRtD9266xIHXdY5MfiXPDfYwl7zBM7KOx2Ae3Gdgxy8QML1FkCMjq6AsOf0l6N9uvI4HcFtuFlenaldKg==", + "requires": { + "client-only": "^0.0.1" + } + }, + "@headlessui/tailwindcss": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@headlessui/tailwindcss/-/tailwindcss-0.1.2.tgz", + "integrity": "sha512-AQNESz+f1grCxifrocOE6hDMDFqhqY0g3xrSGOS0ocGkmVkssaBzXaAPAPNSs/nHmr4ZUhfl5THQpYrvaouWlQ==", + "requires": {} + }, "@hookform/resolvers": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.0.0.tgz", @@ -11109,6 +11364,15 @@ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", "devOptional": true }, + "@types/async-retry": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@types/async-retry/-/async-retry-1.4.5.tgz", + "integrity": "sha512-YrdjSD+yQv7h6d5Ip+PMxh3H6ZxKyQk0Ts+PvaNRInxneG9PFVZjFg77ILAN+N6qYf7g4giSJ1l+ZjQ1zeegvA==", + "dev": true, + "requires": { + "@types/retry": "*" + } + }, "@types/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", @@ -11206,6 +11470,12 @@ "integrity": "sha512-km+Vyn3BYm5ytMO13k9KTp27O75rbQ0NFw+U//g+PX7VZyjCioXaRFisqSIJRECljcTv73G3i6BpglNGHgUQ5A==", "dev": true }, + "@types/lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-8mNEUG6diOrI6pMqOHrHPDBB1JsrpedeMK9AWGzVCQ7StRRribiT9BRvUmF8aUws9iBbVlgVekOT5Sgzc1MTKw==", + "dev": true + }, "@types/mdast": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", @@ -11242,6 +11512,29 @@ "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", "devOptional": true }, + "@types/node-fetch": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz", + "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", @@ -11327,6 +11620,12 @@ "form-data": "^2.5.0" } }, + "@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true + }, "@types/scheduler": { "version": "0.16.3", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", @@ -11474,6 +11773,96 @@ "eslint-visitor-keys": "^3.3.0" } }, + "@vercel/fetch": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@vercel/fetch/-/fetch-6.2.0.tgz", + "integrity": "sha512-MU+Mzh06NIAXxwdnyHmBFg+/lTKBbzDkCSNhAwWTFJ4rHuBc4pHc8E6XP+qnwqaWugjOBQgFfQCGDLnV820c9A==", + "dev": true, + "requires": { + "@types/async-retry": "^1.4.3", + "@vercel/fetch-cached-dns": "^2.0.2", + "@vercel/fetch-retry": "^5.0.3", + "agentkeepalive": "^4.2.1", + "debug": "^4.3.3" + } + }, + "@vercel/fetch-cached-dns": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vercel/fetch-cached-dns/-/fetch-cached-dns-2.1.2.tgz", + "integrity": "sha512-8JHBmYuXYGlyRupRgnyRML84NL1SBi3lVedYhPaWb+6HwMsYF5/PXfQ9M9GPrXsZ8bqKpLQH9tQcVpZmAUJzeQ==", + "dev": true, + "requires": { + "@types/node-fetch": "^2.6.1", + "@zeit/dns-cached-resolve": "^2.1.2" + } + }, + "@vercel/fetch-retry": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@vercel/fetch-retry/-/fetch-retry-5.1.3.tgz", + "integrity": "sha512-UIbFc4VsEZHOr6dWuE+kxY4NxnOLXFMCWm0fSKRRHUEtrIzaJLzHpWk2QskCXTSzFgFvhkLAvSrBK2XZg7NSzg==", + "dev": true, + "requires": { + "async-retry": "^1.3.3", + "debug": "^4.3.3" + } + }, + "@zeit/dns-cached-resolve": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@zeit/dns-cached-resolve/-/dns-cached-resolve-2.1.2.tgz", + "integrity": "sha512-A/5gbBskKPETTBqHwvlaW1Ri2orO62yqoFoXdxna1SQ7A/lXjpWgpJ1wdY3IQEcz5LydpS4sJ8SzI2gFyyLEhg==", + "dev": true, + "requires": { + "@types/async-retry": "1.2.1", + "@types/lru-cache": "4.1.1", + "@types/node": "10.12.18", + "async-retry": "1.2.3", + "lru-cache": "5.1.1" + }, + "dependencies": { + "@types/async-retry": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/async-retry/-/async-retry-1.2.1.tgz", + "integrity": "sha512-yMQ6CVgICWtyFNBqJT3zqOc+TnqqEPLo4nKJNPFwcialiylil38Ie6q1ENeFTjvaLOkVim9K5LisHgAKJWidGQ==", + "dev": true + }, + "@types/node": { + "version": "10.12.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==", + "dev": true + }, + "async-retry": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.2.3.tgz", + "integrity": "sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q==", + "dev": true, + "requires": { + "retry": "0.12.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -11536,6 +11925,17 @@ "debug": "4" } }, + "agentkeepalive": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", + "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "depd": "^2.0.0", + "humanize-ms": "^1.2.1" + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -11716,6 +12116,15 @@ "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", "dev": true }, + "async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "dev": true, + "requires": { + "retry": "0.13.1" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -11982,6 +12391,11 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" }, + "classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -12318,7 +12732,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "optional": true + "devOptional": true }, "deprecation": { "version": "2.3.1", @@ -13878,6 +14292,15 @@ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -15666,7 +16089,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -15810,6 +16232,14 @@ "scheduler": "^0.23.0" } }, + "react-easy-swipe": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/react-easy-swipe/-/react-easy-swipe-0.0.21.tgz", + "integrity": "sha512-OeR2jAxdoqUMHIn/nS9fgreI5hSpgGoL5ezdal4+oO7YSSgJR8ga+PkYGJrSrJ9MKlPcQjMQXnketrD7WNmNsg==", + "requires": { + "prop-types": "^15.5.8" + } + }, "react-email": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/react-email/-/react-email-1.9.0.tgz", @@ -15919,14 +16349,23 @@ "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "react-property": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.0.tgz", "integrity": "sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw==" }, + "react-responsive-carousel": { + "version": "3.2.23", + "resolved": "https://registry.npmjs.org/react-responsive-carousel/-/react-responsive-carousel-3.2.23.tgz", + "integrity": "sha512-pqJLsBaKHWJhw/ItODgbVoziR2z4lpcJg+YwmRlSk4rKH32VE633mAtZZ9kDXjy4wFO+pgUZmDKPsPe1fPmHCg==", + "requires": { + "classnames": "^2.2.5", + "prop-types": "^15.5.8", + "react-easy-swipe": "^0.0.21" + } + }, "read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -16114,6 +16553,12 @@ "signal-exit": "^3.0.2" } }, + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", diff --git a/package.json b/package.json index 61d2955..3cfd4fe 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,8 @@ }, "dependencies": { "@hapi/iron": "^7.0.1", + "@headlessui/react": "^1.7.13", + "@headlessui/tailwindcss": "^0.1.2", "@hookform/resolvers": "^3.0.0", "@prisma/client": "^4.12.0", "@react-email/components": "^0.0.4", @@ -39,6 +41,7 @@ "react-hook-form": "^7.43.9", "react-icons": "^4.8.0", "react-intersection-observer": "^9.4.3", + "react-responsive-carousel": "^3.2.23", "sparkpost": "^2.1.4", "swr": "^2.1.2", "zod": "^3.21.4" @@ -55,6 +58,7 @@ "@types/react": "^18.0.33", "@types/react-dom": "^18.0.11", "@types/sparkpost": "^2.1.5", + "@vercel/fetch": "^6.2.0", "autoprefixer": "^10.4.14", "daisyui": "^2.51.5", "dotenv-cli": "^7.1.0", @@ -73,5 +77,8 @@ "tailwindcss-animate": "^1.0.5", "ts-node": "^10.9.1", "typescript": "^5.0.3" + }, + "prisma": { + "schema": "./src/prisma/schema.prisma" } } diff --git a/pages/beers/[id]/index.tsx b/pages/beers/[id]/index.tsx deleted file mode 100644 index 53bdcb7..0000000 --- a/pages/beers/[id]/index.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { NextPage, GetServerSideProps } from 'next'; -import Head from 'next/head'; -import Image from 'next/image'; - -import BeerInfoHeader from '@/components/BeerById/BeerInfoHeader'; -import BeerPostCommentsSection from '@/components/BeerById/BeerPostCommentsSection'; -import BeerRecommendations from '@/components/BeerById/BeerRecommendations'; -import Layout from '@/components/ui/Layout'; - -import getBeerPostById from '@/services/BeerPost/getBeerPostById'; -import getBeerRecommendations from '@/services/BeerPost/getBeerRecommendations'; - -import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult'; -import { BeerPost } from '@prisma/client'; - -import { z } from 'zod'; - -interface BeerPageProps { - beerPost: z.infer; - beerRecommendations: (BeerPost & { - brewery: { id: string; name: string }; - beerImages: { id: string; alt: string; url: string }[]; - })[]; -} - -const BeerByIdPage: NextPage = ({ beerPost, beerRecommendations }) => { - return ( - <> - - {beerPost.name} - - - -
- {beerPost.beerImages[0] && ( - {beerPost.beerImages[0].alt} - )} - -
-
- -
- -
- -
-
-
-
-
-
- - ); -}; - -export const getServerSideProps: GetServerSideProps = async (context) => { - const beerPost = await getBeerPostById(context.params!.id! as string); - - if (!beerPost) { - return { notFound: true }; - } - - const { type, brewery, id } = beerPost; - const beerRecommendations = await getBeerRecommendations({ type, brewery, id }); - - const props = { - beerPost: JSON.parse(JSON.stringify(beerPost)), - beerRecommendations: JSON.parse(JSON.stringify(beerRecommendations)), - }; - - return { props }; -}; - -export default BeerByIdPage; diff --git a/components/BeerById/BeerCommentForm.tsx b/src/components/BeerById/BeerCommentForm.tsx similarity index 100% rename from components/BeerById/BeerCommentForm.tsx rename to src/components/BeerById/BeerCommentForm.tsx diff --git a/components/BeerById/BeerInfoHeader.tsx b/src/components/BeerById/BeerInfoHeader.tsx similarity index 100% rename from components/BeerById/BeerInfoHeader.tsx rename to src/components/BeerById/BeerInfoHeader.tsx diff --git a/src/components/BeerById/BeerPostCommentsSection.tsx b/src/components/BeerById/BeerPostCommentsSection.tsx new file mode 100644 index 0000000..fa0bd32 --- /dev/null +++ b/src/components/BeerById/BeerPostCommentsSection.tsx @@ -0,0 +1,140 @@ +/* eslint-disable no-nested-ternary */ +import UserContext from '@/contexts/userContext'; + +import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult'; + +import { FC, MutableRefObject, useContext, useRef } from 'react'; +import { z } from 'zod'; +import useBeerPostComments from '@/hooks/useBeerPostComments'; +import { useRouter } from 'next/router'; +import { useInView } from 'react-intersection-observer'; +import { FaArrowUp } from 'react-icons/fa'; +import BeerCommentForm from './BeerCommentForm'; + +import CommentCardBody from './CommentCardBody'; +import NoCommentsCard from './NoCommentsCard'; +import LoadingComponent from './LoadingComponent'; + +interface BeerPostCommentsSectionProps { + beerPost: z.infer; +} + +const BeerPostCommentsSection: FC = ({ beerPost }) => { + const { user } = useContext(UserContext); + const router = useRouter(); + const { id } = beerPost; + const pageNum = parseInt(router.query.comments_page as string, 10) || 1; + const PAGE_SIZE = 4; + + const { comments, isLoading, mutate, setSize, size, isLoadingMore, isAtEnd } = + useBeerPostComments({ + id, + pageNum, + pageSize: PAGE_SIZE, + }); + + const { ref: lastCommentRef } = useInView({ + /** + * When the last comment comes into view, call setSize from useBeerPostComments to + * load more comments. + */ + onChange: (visible) => { + if (!visible || isAtEnd) return; + setSize(size + 1); + }, + }); + + const sectionRef: MutableRefObject = useRef(null); + return ( +
+
+
+ {user ? ( + + ) : ( +
+ Log in to leave a comment. +
+ )} +
+
+ + { + /** + * If the comments are loading, show a loading component. Otherwise, show the + * comments. + */ + isLoading ? ( +
+ +
+ ) : ( + <> + {!!comments.length && ( +
+ {comments.map((comment, index) => { + const isLastComment = index === comments.length - 1; + + /** + * Attach a ref to the last comment in the list. When it comes into + * view, the component will call setSize to load more comments. + */ + return ( +
+ +
+ ); + })} + + { + /** + * If there are more comments to load, show a loading component with a + * skeleton loader and a loading spinner. + */ + !!isLoadingMore && ( + + ) + } + + { + /** + * If the user has scrolled to the end of the comments, show a button + * that will scroll them back to the top of the comments section. + */ + !!isAtEnd && ( +
+
+ +
+
+ ) + } +
+ )} + + {!comments.length && } + + ) + } +
+ ); +}; + +export default BeerPostCommentsSection; diff --git a/components/BeerById/BeerPostLikeButton.tsx b/src/components/BeerById/BeerPostLikeButton.tsx similarity index 100% rename from components/BeerById/BeerPostLikeButton.tsx rename to src/components/BeerById/BeerPostLikeButton.tsx diff --git a/components/BeerById/BeerRecommendations.tsx b/src/components/BeerById/BeerRecommendations.tsx similarity index 100% rename from components/BeerById/BeerRecommendations.tsx rename to src/components/BeerById/BeerRecommendations.tsx diff --git a/components/BeerById/CommentCardBody.tsx b/src/components/BeerById/CommentCardBody.tsx similarity index 100% rename from components/BeerById/CommentCardBody.tsx rename to src/components/BeerById/CommentCardBody.tsx diff --git a/components/BeerById/CommentLoadingCardBody.tsx b/src/components/BeerById/CommentLoadingCardBody.tsx similarity index 100% rename from components/BeerById/CommentLoadingCardBody.tsx rename to src/components/BeerById/CommentLoadingCardBody.tsx diff --git a/src/components/BeerById/LoadingComponent.tsx b/src/components/BeerById/LoadingComponent.tsx new file mode 100644 index 0000000..5e09a28 --- /dev/null +++ b/src/components/BeerById/LoadingComponent.tsx @@ -0,0 +1,22 @@ +import { FC } from 'react'; +import Spinner from '../ui/Spinner'; +import CommentLoadingCardBody from './CommentLoadingCardBody'; + +interface LoadingComponentProps { + length: number; +} + +const LoadingComponent: FC = ({ length }) => { + return ( + <> + {Array.from({ length }).map((_, i) => ( + + ))} +
+ +
+ + ); +}; + +export default LoadingComponent; diff --git a/components/BeerById/NoCommentsCard.tsx b/src/components/BeerById/NoCommentsCard.tsx similarity index 100% rename from components/BeerById/NoCommentsCard.tsx rename to src/components/BeerById/NoCommentsCard.tsx diff --git a/components/BeerIndex/BeerCard.tsx b/src/components/BeerIndex/BeerCard.tsx similarity index 100% rename from components/BeerIndex/BeerCard.tsx rename to src/components/BeerIndex/BeerCard.tsx diff --git a/components/BeerIndex/BeerIndexPaginationBar.tsx b/src/components/BeerIndex/BeerIndexPaginationBar.tsx similarity index 100% rename from components/BeerIndex/BeerIndexPaginationBar.tsx rename to src/components/BeerIndex/BeerIndexPaginationBar.tsx diff --git a/components/CreateBeerPostForm.tsx b/src/components/CreateBeerPostForm.tsx similarity index 100% rename from components/CreateBeerPostForm.tsx rename to src/components/CreateBeerPostForm.tsx diff --git a/components/EditBeerPostForm.tsx b/src/components/EditBeerPostForm.tsx similarity index 100% rename from components/EditBeerPostForm.tsx rename to src/components/EditBeerPostForm.tsx diff --git a/components/Login/LoginForm.tsx b/src/components/Login/LoginForm.tsx similarity index 100% rename from components/Login/LoginForm.tsx rename to src/components/Login/LoginForm.tsx diff --git a/components/RegisterUserForm.tsx b/src/components/RegisterUserForm.tsx similarity index 92% rename from components/RegisterUserForm.tsx rename to src/components/RegisterUserForm.tsx index 140ad78..ab092ae 100644 --- a/components/RegisterUserForm.tsx +++ b/src/components/RegisterUserForm.tsx @@ -56,6 +56,7 @@ const RegisterUserForm: FC = () => { { { { { { { { />
- +
diff --git a/components/ui/Layout.tsx b/src/components/ui/Layout.tsx similarity index 100% rename from components/ui/Layout.tsx rename to src/components/ui/Layout.tsx diff --git a/components/ui/Navbar.tsx b/src/components/ui/Navbar.tsx similarity index 100% rename from components/ui/Navbar.tsx rename to src/components/ui/Navbar.tsx diff --git a/components/ui/Spinner.tsx b/src/components/ui/Spinner.tsx similarity index 83% rename from components/ui/Spinner.tsx rename to src/components/ui/Spinner.tsx index df69177..d42f745 100644 --- a/components/ui/Spinner.tsx +++ b/src/components/ui/Spinner.tsx @@ -7,17 +7,22 @@ interface SpinnerProps { const Spinner: FC = ({ size = 'md' }) => { const spinnerWidths: Record, `w-[${number}px]`> = { xs: 'w-[45px]', - sm: 'w-[60px]', - md: 'w-[100px]', - lg: 'w-[150px]', - xl: 'w-[200px]', + sm: 'w-[90px]', + md: 'w-[135px]', + lg: 'w-[180px]', + xl: 'w-[225px]', }; return ( -
+
+ {beerPost.name} + + + +
+ + {beerPost.beerImages.map((image, index) => ( +
+ {image.alt} +
+ ))} +
+ +
+
+ + + {isMd ? ( +
+
+ +
+
+ +
+
+ ) : ( + + + + Comments + + + Recommendations + + + + + + + + + + + + )} +
+
+
+
+ + ); +}; + +export const getServerSideProps: GetServerSideProps = async (context) => { + const beerPost = await getBeerPostById(context.params!.id! as string); + + if (!beerPost) { + return { notFound: true }; + } + + const { type, brewery, id } = beerPost; + const beerRecommendations = await getBeerRecommendations({ type, brewery, id }); + + const props = { + beerPost: JSON.parse(JSON.stringify(beerPost)), + beerRecommendations: JSON.parse(JSON.stringify(beerRecommendations)), + }; + + return { props }; +}; + +export default BeerByIdPage; diff --git a/pages/beers/create.tsx b/src/pages/beers/create.tsx similarity index 100% rename from pages/beers/create.tsx rename to src/pages/beers/create.tsx diff --git a/pages/beers/index.tsx b/src/pages/beers/index.tsx similarity index 84% rename from pages/beers/index.tsx rename to src/pages/beers/index.tsx index 6be6a80..2471037 100644 --- a/pages/beers/index.tsx +++ b/src/pages/beers/index.tsx @@ -9,6 +9,9 @@ import BeerCard from '@/components/BeerIndex/BeerCard'; import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult'; import Head from 'next/head'; import { z } from 'zod'; +import Link from 'next/link'; +import UserContext from '@/contexts/userContext'; +import { useContext } from 'react'; interface BeerPageProps { initialBeerPosts: z.infer[]; @@ -19,6 +22,8 @@ const BeerPage: NextPage = ({ initialBeerPosts, pageCount }) => { const router = useRouter(); const { query } = router; + const { user } = useContext(UserContext); + const pageNum = parseInt(query.page_num as string, 10) || 1; return ( @@ -28,13 +33,20 @@ const BeerPage: NextPage = ({ initialBeerPosts, pageCount }) => {
-
+

The Biergarten Index

Page {pageNum} of {pageCount}

+ {!!user && ( +
+ + Create a new beer post + +
+ )}
{initialBeerPosts.map((post) => { diff --git a/pages/beers/search.tsx b/src/pages/beers/search.tsx similarity index 100% rename from pages/beers/search.tsx rename to src/pages/beers/search.tsx diff --git a/pages/breweries/[id].tsx b/src/pages/breweries/[id].tsx similarity index 100% rename from pages/breweries/[id].tsx rename to src/pages/breweries/[id].tsx diff --git a/pages/breweries/index.tsx b/src/pages/breweries/index.tsx similarity index 100% rename from pages/breweries/index.tsx rename to src/pages/breweries/index.tsx diff --git a/pages/index.tsx b/src/pages/index.tsx similarity index 100% rename from pages/index.tsx rename to src/pages/index.tsx diff --git a/pages/login/index.tsx b/src/pages/login/index.tsx similarity index 100% rename from pages/login/index.tsx rename to src/pages/login/index.tsx diff --git a/pages/register/index.tsx b/src/pages/register/index.tsx similarity index 100% rename from pages/register/index.tsx rename to src/pages/register/index.tsx diff --git a/pages/user/current.tsx b/src/pages/user/current.tsx similarity index 100% rename from pages/user/current.tsx rename to src/pages/user/current.tsx diff --git a/prisma/DBClient.ts b/src/prisma/DBClient.ts similarity index 89% rename from prisma/DBClient.ts rename to src/prisma/DBClient.ts index bcdb365..219576e 100644 --- a/prisma/DBClient.ts +++ b/src/prisma/DBClient.ts @@ -1,5 +1,5 @@ import { PrismaClient } from '@prisma/client'; -import { NODE_ENV } from '../config/env'; +import { NODE_ENV } from '@/config/env'; const globalForPrisma = global as unknown as { prisma: PrismaClient }; diff --git a/prisma/ERD.svg b/src/prisma/ERD.svg similarity index 100% rename from prisma/ERD.svg rename to src/prisma/ERD.svg diff --git a/prisma/migrations/20230406013055_/migration.sql b/src/prisma/migrations/20230406013055_/migration.sql similarity index 100% rename from prisma/migrations/20230406013055_/migration.sql rename to src/prisma/migrations/20230406013055_/migration.sql diff --git a/prisma/migrations/migration_lock.toml b/src/prisma/migrations/migration_lock.toml similarity index 100% rename from prisma/migrations/migration_lock.toml rename to src/prisma/migrations/migration_lock.toml diff --git a/prisma/schema.prisma b/src/prisma/schema.prisma similarity index 100% rename from prisma/schema.prisma rename to src/prisma/schema.prisma diff --git a/prisma/seed/clean/cleanDatabase.ts b/src/prisma/seed/clean/cleanDatabase.ts similarity index 100% rename from prisma/seed/clean/cleanDatabase.ts rename to src/prisma/seed/clean/cleanDatabase.ts diff --git a/prisma/seed/create/createNewBeerImages.ts b/src/prisma/seed/create/createNewBeerImages.ts similarity index 90% rename from prisma/seed/create/createNewBeerImages.ts rename to src/prisma/seed/create/createNewBeerImages.ts index 0642f4c..f28e3ee 100644 --- a/prisma/seed/create/createNewBeerImages.ts +++ b/src/prisma/seed/create/createNewBeerImages.ts @@ -20,12 +20,15 @@ const createNewBeerImages = async ({ for (let i = 0; i < numberOfImages; i++) { const beerPost = beerPosts[Math.floor(Math.random() * beerPosts.length)]; const user = users[Math.floor(Math.random() * users.length)]; + const caption = faker.lorem.sentence(); + const alt = faker.lorem.sentence(); + beerImagesPromises.push( prisma.beerImage.create({ data: { path: 'https://picsum.photos/5000/5000', - alt: 'Placeholder beer image.', - caption: 'Placeholder beer image caption.', + alt, + caption, beerPost: { connect: { id: beerPost.id } }, postedBy: { connect: { id: user.id } }, createdAt, diff --git a/prisma/seed/create/createNewBeerPostComments.ts b/src/prisma/seed/create/createNewBeerPostComments.ts similarity index 100% rename from prisma/seed/create/createNewBeerPostComments.ts rename to src/prisma/seed/create/createNewBeerPostComments.ts diff --git a/prisma/seed/create/createNewBeerPostLikes.ts b/src/prisma/seed/create/createNewBeerPostLikes.ts similarity index 100% rename from prisma/seed/create/createNewBeerPostLikes.ts rename to src/prisma/seed/create/createNewBeerPostLikes.ts diff --git a/prisma/seed/create/createNewBeerPosts.ts b/src/prisma/seed/create/createNewBeerPosts.ts similarity index 100% rename from prisma/seed/create/createNewBeerPosts.ts rename to src/prisma/seed/create/createNewBeerPosts.ts diff --git a/prisma/seed/create/createNewBeerTypes.ts b/src/prisma/seed/create/createNewBeerTypes.ts similarity index 100% rename from prisma/seed/create/createNewBeerTypes.ts rename to src/prisma/seed/create/createNewBeerTypes.ts diff --git a/prisma/seed/create/createNewBreweryImages.ts b/src/prisma/seed/create/createNewBreweryImages.ts similarity index 100% rename from prisma/seed/create/createNewBreweryImages.ts rename to src/prisma/seed/create/createNewBreweryImages.ts diff --git a/prisma/seed/create/createNewBreweryPostComments.ts b/src/prisma/seed/create/createNewBreweryPostComments.ts similarity index 100% rename from prisma/seed/create/createNewBreweryPostComments.ts rename to src/prisma/seed/create/createNewBreweryPostComments.ts diff --git a/prisma/seed/create/createNewBreweryPosts.ts b/src/prisma/seed/create/createNewBreweryPosts.ts similarity index 100% rename from prisma/seed/create/createNewBreweryPosts.ts rename to src/prisma/seed/create/createNewBreweryPosts.ts diff --git a/prisma/seed/create/createNewUsers.ts b/src/prisma/seed/create/createNewUsers.ts similarity index 95% rename from prisma/seed/create/createNewUsers.ts rename to src/prisma/seed/create/createNewUsers.ts index c34bf4e..62da73b 100644 --- a/prisma/seed/create/createNewUsers.ts +++ b/src/prisma/seed/create/createNewUsers.ts @@ -18,7 +18,7 @@ const createNewUsers = async ({ numberOfUsers }: CreateNewUsersArgs) => { // eslint-disable-next-line no-plusplus for (let i = 0; i < numberOfUsers; i++) { - const randomValue = crypto.randomBytes(8).toString('hex'); + const randomValue = crypto.randomBytes(10).toString('hex'); const firstName = faker.name.firstName(); const lastName = faker.name.lastName(); const username = `${firstName[0]}.${lastName}.${randomValue}`; diff --git a/prisma/seed/index.ts b/src/prisma/seed/index.ts similarity index 100% rename from prisma/seed/index.ts rename to src/prisma/seed/index.ts diff --git a/requests/sendCreateBeerCommentRequest.ts b/src/requests/sendCreateBeerCommentRequest.ts similarity index 100% rename from requests/sendCreateBeerCommentRequest.ts rename to src/requests/sendCreateBeerCommentRequest.ts diff --git a/requests/sendCreateBeerPostRequest.ts b/src/requests/sendCreateBeerPostRequest.ts similarity index 100% rename from requests/sendCreateBeerPostRequest.ts rename to src/requests/sendCreateBeerPostRequest.ts diff --git a/requests/sendEditBeerPostRequest.ts b/src/requests/sendEditBeerPostRequest.ts similarity index 100% rename from requests/sendEditBeerPostRequest.ts rename to src/requests/sendEditBeerPostRequest.ts diff --git a/requests/sendLikeRequest.ts b/src/requests/sendLikeRequest.ts similarity index 100% rename from requests/sendLikeRequest.ts rename to src/requests/sendLikeRequest.ts diff --git a/requests/sendLoginUserRequest.ts b/src/requests/sendLoginUserRequest.ts similarity index 100% rename from requests/sendLoginUserRequest.ts rename to src/requests/sendLoginUserRequest.ts diff --git a/requests/sendRegisterUserRequest.ts b/src/requests/sendRegisterUserRequest.ts similarity index 100% rename from requests/sendRegisterUserRequest.ts rename to src/requests/sendRegisterUserRequest.ts diff --git a/services/BeerComment/createNewBeerComment.ts b/src/services/BeerComment/createNewBeerComment.ts similarity index 100% rename from services/BeerComment/createNewBeerComment.ts rename to src/services/BeerComment/createNewBeerComment.ts diff --git a/services/BeerComment/getAllBeerComments.ts b/src/services/BeerComment/getAllBeerComments.ts similarity index 100% rename from services/BeerComment/getAllBeerComments.ts rename to src/services/BeerComment/getAllBeerComments.ts diff --git a/services/BeerComment/getBeerCommentCount.ts b/src/services/BeerComment/getBeerCommentCount.ts similarity index 100% rename from services/BeerComment/getBeerCommentCount.ts rename to src/services/BeerComment/getBeerCommentCount.ts diff --git a/services/BeerComment/schema/BeerCommentQueryResult.ts b/src/services/BeerComment/schema/BeerCommentQueryResult.ts similarity index 100% rename from services/BeerComment/schema/BeerCommentQueryResult.ts rename to src/services/BeerComment/schema/BeerCommentQueryResult.ts diff --git a/services/BeerComment/schema/CreateBeerCommentValidationSchema.ts b/src/services/BeerComment/schema/CreateBeerCommentValidationSchema.ts similarity index 100% rename from services/BeerComment/schema/CreateBeerCommentValidationSchema.ts rename to src/services/BeerComment/schema/CreateBeerCommentValidationSchema.ts diff --git a/services/BeerPost/createNewBeerPost.ts b/src/services/BeerPost/createNewBeerPost.ts similarity index 100% rename from services/BeerPost/createNewBeerPost.ts rename to src/services/BeerPost/createNewBeerPost.ts diff --git a/services/BeerPost/editBeerPostById.ts b/src/services/BeerPost/editBeerPostById.ts similarity index 100% rename from services/BeerPost/editBeerPostById.ts rename to src/services/BeerPost/editBeerPostById.ts diff --git a/services/BeerPost/getAllBeerPosts.ts b/src/services/BeerPost/getAllBeerPosts.ts similarity index 100% rename from services/BeerPost/getAllBeerPosts.ts rename to src/services/BeerPost/getAllBeerPosts.ts diff --git a/services/BeerPost/getBeerPostById.ts b/src/services/BeerPost/getBeerPostById.ts similarity index 100% rename from services/BeerPost/getBeerPostById.ts rename to src/services/BeerPost/getBeerPostById.ts diff --git a/services/BeerPost/getBeerRecommendations.ts b/src/services/BeerPost/getBeerRecommendations.ts similarity index 100% rename from services/BeerPost/getBeerRecommendations.ts rename to src/services/BeerPost/getBeerRecommendations.ts diff --git a/services/BeerPost/schema/BeerPostQueryResult.ts b/src/services/BeerPost/schema/BeerPostQueryResult.ts similarity index 100% rename from services/BeerPost/schema/BeerPostQueryResult.ts rename to src/services/BeerPost/schema/BeerPostQueryResult.ts diff --git a/services/BeerPost/schema/BeerRecommendationQueryResult.ts b/src/services/BeerPost/schema/BeerRecommendationQueryResult.ts similarity index 100% rename from services/BeerPost/schema/BeerRecommendationQueryResult.ts rename to src/services/BeerPost/schema/BeerRecommendationQueryResult.ts diff --git a/services/BeerPost/schema/CreateBeerPostValidationSchema.ts b/src/services/BeerPost/schema/CreateBeerPostValidationSchema.ts similarity index 100% rename from services/BeerPost/schema/CreateBeerPostValidationSchema.ts rename to src/services/BeerPost/schema/CreateBeerPostValidationSchema.ts diff --git a/services/BeerPost/schema/EditBeerPostValidationSchema.ts b/src/services/BeerPost/schema/EditBeerPostValidationSchema.ts similarity index 100% rename from services/BeerPost/schema/EditBeerPostValidationSchema.ts rename to src/services/BeerPost/schema/EditBeerPostValidationSchema.ts diff --git a/services/BeerPostLike/createBeerPostLike.ts b/src/services/BeerPostLike/createBeerPostLike.ts similarity index 100% rename from services/BeerPostLike/createBeerPostLike.ts rename to src/services/BeerPostLike/createBeerPostLike.ts diff --git a/services/BeerPostLike/findBeerPostLikeById.ts b/src/services/BeerPostLike/findBeerPostLikeById.ts similarity index 100% rename from services/BeerPostLike/findBeerPostLikeById.ts rename to src/services/BeerPostLike/findBeerPostLikeById.ts diff --git a/services/BeerPostLike/getBeerPostLikeCount.ts b/src/services/BeerPostLike/getBeerPostLikeCount.ts similarity index 100% rename from services/BeerPostLike/getBeerPostLikeCount.ts rename to src/services/BeerPostLike/getBeerPostLikeCount.ts diff --git a/services/BeerPostLike/removeBeerPostLikeById.ts b/src/services/BeerPostLike/removeBeerPostLikeById.ts similarity index 100% rename from services/BeerPostLike/removeBeerPostLikeById.ts rename to src/services/BeerPostLike/removeBeerPostLikeById.ts diff --git a/services/BreweryPost/getAllBreweryPosts.ts b/src/services/BreweryPost/getAllBreweryPosts.ts similarity index 100% rename from services/BreweryPost/getAllBreweryPosts.ts rename to src/services/BreweryPost/getAllBreweryPosts.ts diff --git a/services/BreweryPost/getBreweryPostById.ts b/src/services/BreweryPost/getBreweryPostById.ts similarity index 100% rename from services/BreweryPost/getBreweryPostById.ts rename to src/services/BreweryPost/getBreweryPostById.ts diff --git a/services/BreweryPost/types/BreweryPostQueryResult.ts b/src/services/BreweryPost/types/BreweryPostQueryResult.ts similarity index 100% rename from services/BreweryPost/types/BreweryPostQueryResult.ts rename to src/services/BreweryPost/types/BreweryPostQueryResult.ts diff --git a/services/User/createNewUser.ts b/src/services/User/createNewUser.ts similarity index 100% rename from services/User/createNewUser.ts rename to src/services/User/createNewUser.ts diff --git a/services/User/findUserByEmail.ts b/src/services/User/findUserByEmail.ts similarity index 100% rename from services/User/findUserByEmail.ts rename to src/services/User/findUserByEmail.ts diff --git a/services/User/findUserById.ts b/src/services/User/findUserById.ts similarity index 100% rename from services/User/findUserById.ts rename to src/services/User/findUserById.ts diff --git a/services/User/findUserByUsername.ts b/src/services/User/findUserByUsername.ts similarity index 100% rename from services/User/findUserByUsername.ts rename to src/services/User/findUserByUsername.ts diff --git a/services/User/schema/CreateUserValidationSchema.ts b/src/services/User/schema/CreateUserValidationSchema.ts similarity index 100% rename from services/User/schema/CreateUserValidationSchema.ts rename to src/services/User/schema/CreateUserValidationSchema.ts diff --git a/services/User/schema/GetUserSchema.ts b/src/services/User/schema/GetUserSchema.ts similarity index 100% rename from services/User/schema/GetUserSchema.ts rename to src/services/User/schema/GetUserSchema.ts diff --git a/services/User/schema/LoginValidationSchema.ts b/src/services/User/schema/LoginValidationSchema.ts similarity index 100% rename from services/User/schema/LoginValidationSchema.ts rename to src/services/User/schema/LoginValidationSchema.ts diff --git a/services/User/sendConfirmationEmail.ts b/src/services/User/sendConfirmationEmail.ts similarity index 100% rename from services/User/sendConfirmationEmail.ts rename to src/services/User/sendConfirmationEmail.ts diff --git a/services/User/updateUserToBeConfirmedById.ts b/src/services/User/updateUserToBeConfirmedById.ts similarity index 100% rename from services/User/updateUserToBeConfirmedById.ts rename to src/services/User/updateUserToBeConfirmedById.ts diff --git a/styles/globals.css b/src/styles/globals.css similarity index 100% rename from styles/globals.css rename to src/styles/globals.css diff --git a/validation/APIResponseValidationSchema.ts b/src/validation/APIResponseValidationSchema.ts similarity index 100% rename from validation/APIResponseValidationSchema.ts rename to src/validation/APIResponseValidationSchema.ts diff --git a/tailwind.config.js b/tailwind.config.js index fe63a71..d797873 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,36 +1,60 @@ +//themes + +const myTheme = { + default: { + primary: 'hsl(227, 23%, 20%)', + secondary: 'hsl(255, 9%, 69%)', + error: 'hsl(9, 52%, 57%)', + accent: 'hsl(316, 96%, 60%)', + neutral: 'hsl(240, 11%, 8%)', + info: 'hsl(207, 100%, 50%)', + success: 'hsl(100, 57%, 53%)', + warning: 'hsl(50, 98%, 50%)', + 'primary-content': 'hsl(0, 0%, 98%)', + 'error-content': 'hsl(0, 0%, 98%)', + 'base-100': 'hsl(190, 4%, 9%)', + 'base-200': 'hsl(190, 4%, 8%)', + 'base-300': 'hsl(190, 4%, 5%)', + }, +}; + +const pastelTheme = { + default: { + primary: 'hsl(180, 28%, 65%)', + secondary: 'hsl(21, 54%, 83%)', + error: 'hsl(4, 87%, 74%)', + accent: 'hsl(93, 27%, 73%)', + neutral: 'hsl(38, 31%, 91%)', + info: 'hsl(163, 40%, 79%)', + success: 'hsl(93, 27%, 73%)', + warning: 'hsl(40, 76%, 73%)', + 'primary-content': 'hsl(0, 0%, 12%)', + 'error-content': 'hsl(0, 0%, 12%)', + 'base-100': 'hsl(0, 0%, 85%)', + 'base-200': 'hsl(0, 0%, 82%)', + 'base-300': 'hsl(0, 0%, 78%)', + 'base-400': 'hsl(0, 0%, 75%)', + }, +}; + /** @type {import('tailwindcss').Config} */ module.exports = { content: [ - './pages/**/*.{js,ts,jsx,tsx}', - './components/**/*.{js,ts,jsx,tsx}', + './src/**/*.{js,ts,jsx,tsx}', 'node_modules/daisyui/dist/**/*.js', 'node_modules/react-daisyui/dist/**/*.js', ], theme: { extend: {}, }, - plugins: [require('daisyui'), require('tailwindcss-animate')], + plugins: [ + require('@headlessui/tailwindcss'), + require('daisyui'), + require('tailwindcss-animate'), + ], daisyui: { logs: false, - themes: [ - { - default: { - primary: 'hsl(227, 23%, 20%)', - secondary: '#ABA9C3', - error: '#c17c74', - accent: '#fe3bd9', - neutral: '#131520', - info: '#0A7CFF', - success: '#8ACE2B', - warning: '#F9D002', - 'primary-content': '#FAF9F6', - 'error-content': '#FAF9F6', - 'base-100': 'hsl(190, 4%, 9%)', - 'base-200': 'hsl(190, 4%, 8%)', - 'base-300': 'hsl(190, 4%, 5%)', - }, - }, - ], + themes: [myTheme], }, }; diff --git a/tsconfig.json b/tsconfig.json index ff7df8d..5596200 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,7 +16,7 @@ "incremental": true, "baseUrl": ".", "paths": { - "@/*": ["./*"] + "@/*": ["./src/*"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],