mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 18:52:06 +00:00
Merge pull request #21 from aaronpo97/dev
Improving code structure and implement features to enhance user experience.
This commit is contained in:
@@ -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<typeof beerPostQueryResult>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const LoadingComponent: FC<{ length: number }> = ({ length }) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{Array.from({ length }).map((_, i) => (
|
|
||||||
<CommentLoadingCardBody key={i} />
|
|
||||||
))}
|
|
||||||
<div className="p-1">
|
|
||||||
<Spinner size="sm" />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const BeerPostCommentsSection: FC<BeerPostCommentsSectionProps> = ({ 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<HTMLDivElement | null> = useRef(null);
|
|
||||||
return (
|
|
||||||
<div className="w-full space-y-3 md:w-[60%]">
|
|
||||||
<div className="card h-96 bg-base-300">
|
|
||||||
<div className="card-body h-full">
|
|
||||||
{user ? (
|
|
||||||
<BeerCommentForm beerPost={beerPost} mutate={mutate} />
|
|
||||||
) : (
|
|
||||||
<div className="flex h-full flex-col items-center justify-center">
|
|
||||||
<span className="text-lg font-bold">Log in to leave a comment.</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{comments && !!comments.length && !isLoading && (
|
|
||||||
<div className="card bg-base-300 pb-6" ref={sectionRef}>
|
|
||||||
{comments.map((comment, index) => {
|
|
||||||
const isLastComment = index === comments.length - 1;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div ref={isLastComment ? ref : undefined} key={comment.id}>
|
|
||||||
<CommentCardBody comment={comment} mutate={mutate} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
|
|
||||||
{!!isLoadingMore && (
|
|
||||||
<div>
|
|
||||||
<LoadingComponent length={Math.floor(PAGE_SIZE / 2)} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{isAtEnd && (
|
|
||||||
<div className="flex h-10 items-center justify-center text-center">
|
|
||||||
<button
|
|
||||||
className="btn-ghost btn-sm btn"
|
|
||||||
type="button"
|
|
||||||
onClick={() => {
|
|
||||||
sectionRef.current!.scrollIntoView({ behavior: 'smooth' });
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Scroll to top of comments
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!comments?.length && !isLoading && <NoCommentsCard />}
|
|
||||||
|
|
||||||
{isLoading && (
|
|
||||||
<div className="card bg-base-300 pb-6">
|
|
||||||
<LoadingComponent length={PAGE_SIZE} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default BeerPostCommentsSection;
|
|
||||||
461
package-lock.json
generated
461
package-lock.json
generated
@@ -9,6 +9,8 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hapi/iron": "^7.0.1",
|
"@hapi/iron": "^7.0.1",
|
||||||
|
"@headlessui/react": "^1.7.13",
|
||||||
|
"@headlessui/tailwindcss": "^0.1.2",
|
||||||
"@hookform/resolvers": "^3.0.0",
|
"@hookform/resolvers": "^3.0.0",
|
||||||
"@prisma/client": "^4.12.0",
|
"@prisma/client": "^4.12.0",
|
||||||
"@react-email/components": "^0.0.4",
|
"@react-email/components": "^0.0.4",
|
||||||
@@ -36,6 +38,7 @@
|
|||||||
"react-hook-form": "^7.43.9",
|
"react-hook-form": "^7.43.9",
|
||||||
"react-icons": "^4.8.0",
|
"react-icons": "^4.8.0",
|
||||||
"react-intersection-observer": "^9.4.3",
|
"react-intersection-observer": "^9.4.3",
|
||||||
|
"react-responsive-carousel": "^3.2.23",
|
||||||
"sparkpost": "^2.1.4",
|
"sparkpost": "^2.1.4",
|
||||||
"swr": "^2.1.2",
|
"swr": "^2.1.2",
|
||||||
"zod": "^3.21.4"
|
"zod": "^3.21.4"
|
||||||
@@ -52,6 +55,7 @@
|
|||||||
"@types/react": "^18.0.33",
|
"@types/react": "^18.0.33",
|
||||||
"@types/react-dom": "^18.0.11",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@types/sparkpost": "^2.1.5",
|
"@types/sparkpost": "^2.1.5",
|
||||||
|
"@vercel/fetch": "^6.2.0",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
"daisyui": "^2.51.5",
|
"daisyui": "^2.51.5",
|
||||||
"dotenv-cli": "^7.1.0",
|
"dotenv-cli": "^7.1.0",
|
||||||
@@ -647,6 +651,32 @@
|
|||||||
"@hapi/hoek": "^11.0.2"
|
"@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": {
|
"node_modules/@hookform/resolvers": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.0.0.tgz",
|
||||||
@@ -1558,6 +1588,15 @@
|
|||||||
"integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
|
"integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
|
||||||
"devOptional": true
|
"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": {
|
"node_modules/@types/body-parser": {
|
||||||
"version": "1.19.2",
|
"version": "1.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
|
"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==",
|
"integrity": "sha512-km+Vyn3BYm5ytMO13k9KTp27O75rbQ0NFw+U//g+PX7VZyjCioXaRFisqSIJRECljcTv73G3i6BpglNGHgUQ5A==",
|
||||||
"dev": true
|
"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": {
|
"node_modules/@types/mdast": {
|
||||||
"version": "3.0.11",
|
"version": "3.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz",
|
||||||
@@ -1691,6 +1736,30 @@
|
|||||||
"integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==",
|
"integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==",
|
||||||
"devOptional": true
|
"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": {
|
"node_modules/@types/normalize-package-data": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz",
|
"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"
|
"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": {
|
"node_modules/@types/scheduler": {
|
||||||
"version": "0.16.3",
|
"version": "0.16.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
|
||||||
@@ -2012,6 +2087,107 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"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": {
|
"node_modules/abbrev": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||||
@@ -2098,6 +2274,20 @@
|
|||||||
"node": ">= 6.0.0"
|
"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": {
|
"node_modules/ajv": {
|
||||||
"version": "6.12.6",
|
"version": "6.12.6",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||||
@@ -2334,6 +2524,15 @@
|
|||||||
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
|
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
|
||||||
"dev": true
|
"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": {
|
"node_modules/asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
@@ -2753,6 +2952,11 @@
|
|||||||
"node": ">=10"
|
"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": {
|
"node_modules/cli-cursor": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
|
||||||
@@ -3206,7 +3410,7 @@
|
|||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
|
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
|
||||||
"optional": true,
|
"devOptional": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
@@ -5258,6 +5462,15 @@
|
|||||||
"node": ">=10.17.0"
|
"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": {
|
"node_modules/iconv-lite": {
|
||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
@@ -8013,7 +8226,6 @@
|
|||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
@@ -8205,6 +8417,17 @@
|
|||||||
"react": "^18.2.0"
|
"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": {
|
"node_modules/react-email": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-email/-/react-email-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-email/-/react-email-1.9.0.tgz",
|
||||||
@@ -8353,14 +8576,23 @@
|
|||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/react-property": {
|
"node_modules/react-property": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.0.tgz",
|
||||||
"integrity": "sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw=="
|
"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": {
|
"node_modules/read-cache": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||||
@@ -8602,6 +8834,15 @@
|
|||||||
"node": ">=8"
|
"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": {
|
"node_modules/reusify": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||||
@@ -10478,6 +10719,20 @@
|
|||||||
"@hapi/hoek": "^11.0.2"
|
"@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": {
|
"@hookform/resolvers": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.0.0.tgz",
|
||||||
@@ -11109,6 +11364,15 @@
|
|||||||
"integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
|
"integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
|
||||||
"devOptional": true
|
"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": {
|
"@types/body-parser": {
|
||||||
"version": "1.19.2",
|
"version": "1.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
|
"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==",
|
"integrity": "sha512-km+Vyn3BYm5ytMO13k9KTp27O75rbQ0NFw+U//g+PX7VZyjCioXaRFisqSIJRECljcTv73G3i6BpglNGHgUQ5A==",
|
||||||
"dev": true
|
"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": {
|
"@types/mdast": {
|
||||||
"version": "3.0.11",
|
"version": "3.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz",
|
||||||
@@ -11242,6 +11512,29 @@
|
|||||||
"integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==",
|
"integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==",
|
||||||
"devOptional": true
|
"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": {
|
"@types/normalize-package-data": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz",
|
"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"
|
"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": {
|
"@types/scheduler": {
|
||||||
"version": "0.16.3",
|
"version": "0.16.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
|
||||||
@@ -11474,6 +11773,96 @@
|
|||||||
"eslint-visitor-keys": "^3.3.0"
|
"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": {
|
"abbrev": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||||
@@ -11536,6 +11925,17 @@
|
|||||||
"debug": "4"
|
"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": {
|
"ajv": {
|
||||||
"version": "6.12.6",
|
"version": "6.12.6",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||||
@@ -11716,6 +12116,15 @@
|
|||||||
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
|
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
|
||||||
"dev": true
|
"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": {
|
"asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||||
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
|
"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": {
|
"cli-cursor": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
|
||||||
@@ -12318,7 +12732,7 @@
|
|||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
|
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
|
||||||
"optional": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
"deprecation": {
|
"deprecation": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
@@ -13878,6 +14292,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||||
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="
|
"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": {
|
"iconv-lite": {
|
||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
@@ -15666,7 +16089,6 @@
|
|||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
@@ -15810,6 +16232,14 @@
|
|||||||
"scheduler": "^0.23.0"
|
"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": {
|
"react-email": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-email/-/react-email-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-email/-/react-email-1.9.0.tgz",
|
||||||
@@ -15919,14 +16349,23 @@
|
|||||||
"react-is": {
|
"react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"react-property": {
|
"react-property": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.0.tgz",
|
||||||
"integrity": "sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw=="
|
"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": {
|
"read-cache": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||||
@@ -16114,6 +16553,12 @@
|
|||||||
"signal-exit": "^3.0.2"
|
"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": {
|
"reusify": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hapi/iron": "^7.0.1",
|
"@hapi/iron": "^7.0.1",
|
||||||
|
"@headlessui/react": "^1.7.13",
|
||||||
|
"@headlessui/tailwindcss": "^0.1.2",
|
||||||
"@hookform/resolvers": "^3.0.0",
|
"@hookform/resolvers": "^3.0.0",
|
||||||
"@prisma/client": "^4.12.0",
|
"@prisma/client": "^4.12.0",
|
||||||
"@react-email/components": "^0.0.4",
|
"@react-email/components": "^0.0.4",
|
||||||
@@ -39,6 +41,7 @@
|
|||||||
"react-hook-form": "^7.43.9",
|
"react-hook-form": "^7.43.9",
|
||||||
"react-icons": "^4.8.0",
|
"react-icons": "^4.8.0",
|
||||||
"react-intersection-observer": "^9.4.3",
|
"react-intersection-observer": "^9.4.3",
|
||||||
|
"react-responsive-carousel": "^3.2.23",
|
||||||
"sparkpost": "^2.1.4",
|
"sparkpost": "^2.1.4",
|
||||||
"swr": "^2.1.2",
|
"swr": "^2.1.2",
|
||||||
"zod": "^3.21.4"
|
"zod": "^3.21.4"
|
||||||
@@ -55,6 +58,7 @@
|
|||||||
"@types/react": "^18.0.33",
|
"@types/react": "^18.0.33",
|
||||||
"@types/react-dom": "^18.0.11",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@types/sparkpost": "^2.1.5",
|
"@types/sparkpost": "^2.1.5",
|
||||||
|
"@vercel/fetch": "^6.2.0",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
"daisyui": "^2.51.5",
|
"daisyui": "^2.51.5",
|
||||||
"dotenv-cli": "^7.1.0",
|
"dotenv-cli": "^7.1.0",
|
||||||
@@ -73,5 +77,8 @@
|
|||||||
"tailwindcss-animate": "^1.0.5",
|
"tailwindcss-animate": "^1.0.5",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "^5.0.3"
|
"typescript": "^5.0.3"
|
||||||
|
},
|
||||||
|
"prisma": {
|
||||||
|
"schema": "./src/prisma/schema.prisma"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<typeof beerPostQueryResult>;
|
|
||||||
beerRecommendations: (BeerPost & {
|
|
||||||
brewery: { id: string; name: string };
|
|
||||||
beerImages: { id: string; alt: string; url: string }[];
|
|
||||||
})[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const BeerByIdPage: NextPage<BeerPageProps> = ({ beerPost, beerRecommendations }) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Head>
|
|
||||||
<title>{beerPost.name}</title>
|
|
||||||
<meta name="description" content={beerPost.description} />
|
|
||||||
</Head>
|
|
||||||
<Layout>
|
|
||||||
<div>
|
|
||||||
{beerPost.beerImages[0] && (
|
|
||||||
<Image
|
|
||||||
alt={beerPost.beerImages[0].alt}
|
|
||||||
src={beerPost.beerImages[0].path}
|
|
||||||
height={1080}
|
|
||||||
width={1920}
|
|
||||||
className="h-[42rem] w-full object-cover"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="my-12 flex w-full items-center justify-center ">
|
|
||||||
<div className="w-11/12 space-y-3 xl:w-9/12">
|
|
||||||
<BeerInfoHeader beerPost={beerPost} />
|
|
||||||
<div className="mt-4 flex flex-col space-y-3 md:flex-row md:space-x-3 md:space-y-0">
|
|
||||||
<BeerPostCommentsSection beerPost={beerPost} />
|
|
||||||
<div className="md:w-[40%]">
|
|
||||||
<BeerRecommendations beerRecommendations={beerRecommendations} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Layout>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getServerSideProps: GetServerSideProps<BeerPageProps> = 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;
|
|
||||||
140
src/components/BeerById/BeerPostCommentsSection.tsx
Normal file
140
src/components/BeerById/BeerPostCommentsSection.tsx
Normal file
@@ -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<typeof beerPostQueryResult>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BeerPostCommentsSection: FC<BeerPostCommentsSectionProps> = ({ 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<HTMLDivElement | null> = useRef(null);
|
||||||
|
return (
|
||||||
|
<div className="w-full space-y-3">
|
||||||
|
<div className="card h-96 bg-base-300">
|
||||||
|
<div className="card-body h-full" ref={sectionRef}>
|
||||||
|
{user ? (
|
||||||
|
<BeerCommentForm beerPost={beerPost} mutate={mutate} />
|
||||||
|
) : (
|
||||||
|
<div className="flex h-full flex-col items-center justify-center">
|
||||||
|
<span className="text-lg font-bold">Log in to leave a comment.</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* If the comments are loading, show a loading component. Otherwise, show the
|
||||||
|
* comments.
|
||||||
|
*/
|
||||||
|
isLoading ? (
|
||||||
|
<div className="card bg-base-300 pb-6">
|
||||||
|
<LoadingComponent length={PAGE_SIZE} />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{!!comments.length && (
|
||||||
|
<div className="card bg-base-300 pb-6">
|
||||||
|
{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 (
|
||||||
|
<div
|
||||||
|
ref={isLastComment ? lastCommentRef : undefined}
|
||||||
|
key={comment.id}
|
||||||
|
>
|
||||||
|
<CommentCardBody comment={comment} mutate={mutate} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* If there are more comments to load, show a loading component with a
|
||||||
|
* skeleton loader and a loading spinner.
|
||||||
|
*/
|
||||||
|
!!isLoadingMore && (
|
||||||
|
<LoadingComponent length={Math.floor(PAGE_SIZE / 2)} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 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 && (
|
||||||
|
<div className="flex h-20 items-center justify-center text-center">
|
||||||
|
<div
|
||||||
|
className="tooltip tooltip-bottom"
|
||||||
|
data-tip="Scroll back to top of comments."
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn-ghost btn-sm btn"
|
||||||
|
aria-label="Scroll back to top of comments"
|
||||||
|
onClick={() => {
|
||||||
|
sectionRef.current?.scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FaArrowUp />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!comments.length && <NoCommentsCard />}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BeerPostCommentsSection;
|
||||||
22
src/components/BeerById/LoadingComponent.tsx
Normal file
22
src/components/BeerById/LoadingComponent.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import Spinner from '../ui/Spinner';
|
||||||
|
import CommentLoadingCardBody from './CommentLoadingCardBody';
|
||||||
|
|
||||||
|
interface LoadingComponentProps {
|
||||||
|
length: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LoadingComponent: FC<LoadingComponentProps> = ({ length }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{Array.from({ length }).map((_, i) => (
|
||||||
|
<CommentLoadingCardBody key={i} />
|
||||||
|
))}
|
||||||
|
<div className="p-1">
|
||||||
|
<Spinner size="sm" />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LoadingComponent;
|
||||||
@@ -56,6 +56,7 @@ const RegisterUserForm: FC = () => {
|
|||||||
</FormInfo>
|
</FormInfo>
|
||||||
<FormSegment>
|
<FormSegment>
|
||||||
<FormTextInput
|
<FormTextInput
|
||||||
|
disabled={formState.isSubmitting}
|
||||||
id="firstName"
|
id="firstName"
|
||||||
type="text"
|
type="text"
|
||||||
formValidationSchema={register('firstName')}
|
formValidationSchema={register('firstName')}
|
||||||
@@ -72,6 +73,7 @@ const RegisterUserForm: FC = () => {
|
|||||||
</FormInfo>
|
</FormInfo>
|
||||||
<FormSegment>
|
<FormSegment>
|
||||||
<FormTextInput
|
<FormTextInput
|
||||||
|
disabled={formState.isSubmitting}
|
||||||
id="lastName"
|
id="lastName"
|
||||||
type="text"
|
type="text"
|
||||||
formValidationSchema={register('lastName')}
|
formValidationSchema={register('lastName')}
|
||||||
@@ -90,6 +92,7 @@ const RegisterUserForm: FC = () => {
|
|||||||
</FormInfo>
|
</FormInfo>
|
||||||
<FormSegment>
|
<FormSegment>
|
||||||
<FormTextInput
|
<FormTextInput
|
||||||
|
disabled={formState.isSubmitting}
|
||||||
id="email"
|
id="email"
|
||||||
type="email"
|
type="email"
|
||||||
formValidationSchema={register('email')}
|
formValidationSchema={register('email')}
|
||||||
@@ -105,6 +108,7 @@ const RegisterUserForm: FC = () => {
|
|||||||
</FormInfo>
|
</FormInfo>
|
||||||
<FormSegment>
|
<FormSegment>
|
||||||
<FormTextInput
|
<FormTextInput
|
||||||
|
disabled={formState.isSubmitting}
|
||||||
id="username"
|
id="username"
|
||||||
type="text"
|
type="text"
|
||||||
formValidationSchema={register('username')}
|
formValidationSchema={register('username')}
|
||||||
@@ -123,6 +127,7 @@ const RegisterUserForm: FC = () => {
|
|||||||
</FormInfo>
|
</FormInfo>
|
||||||
<FormSegment>
|
<FormSegment>
|
||||||
<FormTextInput
|
<FormTextInput
|
||||||
|
disabled={formState.isSubmitting}
|
||||||
id="password"
|
id="password"
|
||||||
type="password"
|
type="password"
|
||||||
formValidationSchema={register('password')}
|
formValidationSchema={register('password')}
|
||||||
@@ -138,6 +143,7 @@ const RegisterUserForm: FC = () => {
|
|||||||
</FormInfo>
|
</FormInfo>
|
||||||
<FormSegment>
|
<FormSegment>
|
||||||
<FormTextInput
|
<FormTextInput
|
||||||
|
disabled={formState.isSubmitting}
|
||||||
id="confirmPassword"
|
id="confirmPassword"
|
||||||
type="password"
|
type="password"
|
||||||
formValidationSchema={register('confirmPassword')}
|
formValidationSchema={register('confirmPassword')}
|
||||||
@@ -154,6 +160,7 @@ const RegisterUserForm: FC = () => {
|
|||||||
<FormSegment>
|
<FormSegment>
|
||||||
<FormTextInput
|
<FormTextInput
|
||||||
id="dateOfBirth"
|
id="dateOfBirth"
|
||||||
|
disabled={formState.isSubmitting}
|
||||||
type="date"
|
type="date"
|
||||||
formValidationSchema={register('dateOfBirth')}
|
formValidationSchema={register('dateOfBirth')}
|
||||||
error={!!errors.dateOfBirth}
|
error={!!errors.dateOfBirth}
|
||||||
@@ -161,7 +168,9 @@ const RegisterUserForm: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</FormSegment>
|
</FormSegment>
|
||||||
<div className="mt-6 w-full">
|
<div className="mt-6 w-full">
|
||||||
<Button type="submit">Register User</Button>
|
<Button type="submit" isSubmitting={formState.isSubmitting}>
|
||||||
|
Register User
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -7,17 +7,22 @@ interface SpinnerProps {
|
|||||||
const Spinner: FC<SpinnerProps> = ({ size = 'md' }) => {
|
const Spinner: FC<SpinnerProps> = ({ size = 'md' }) => {
|
||||||
const spinnerWidths: Record<NonNullable<SpinnerProps['size']>, `w-[${number}px]`> = {
|
const spinnerWidths: Record<NonNullable<SpinnerProps['size']>, `w-[${number}px]`> = {
|
||||||
xs: 'w-[45px]',
|
xs: 'w-[45px]',
|
||||||
sm: 'w-[60px]',
|
sm: 'w-[90px]',
|
||||||
md: 'w-[100px]',
|
md: 'w-[135px]',
|
||||||
lg: 'w-[150px]',
|
lg: 'w-[180px]',
|
||||||
xl: 'w-[200px]',
|
xl: 'w-[225px]',
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div role="status" className="flex flex-col items-center justify-center rounded-3xl">
|
<div
|
||||||
|
role="alert"
|
||||||
|
aria-busy="true"
|
||||||
|
aria-live="polite"
|
||||||
|
className="flex flex-col items-center justify-center rounded-3xl text-primary"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className={`${spinnerWidths[size]} animate-spin fill-secondary text-primary`}
|
className={`${spinnerWidths[size]} animate-spin fill-base-content`}
|
||||||
viewBox="0 0 100 101"
|
viewBox="0 0 100 101"
|
||||||
fill="none"
|
fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
19
src/hooks/useMediaQuery.ts
Normal file
19
src/hooks/useMediaQuery.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
const useMediaQuery = (query: string) => {
|
||||||
|
const [matches, setMatches] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const media = window.matchMedia(query);
|
||||||
|
if (media.matches !== matches) {
|
||||||
|
setMatches(media.matches);
|
||||||
|
}
|
||||||
|
const listener = () => setMatches(media.matches);
|
||||||
|
window.addEventListener('resize', listener);
|
||||||
|
return () => window.removeEventListener('resize', listener);
|
||||||
|
}, [matches, query]);
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useMediaQuery;
|
||||||
122
src/pages/beers/[id]/index.tsx
Normal file
122
src/pages/beers/[id]/index.tsx
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
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';
|
||||||
|
|
||||||
|
import 'react-responsive-carousel/lib/styles/carousel.min.css'; // requires a loader
|
||||||
|
import { Carousel } from 'react-responsive-carousel';
|
||||||
|
import useMediaQuery from '@/hooks/useMediaQuery';
|
||||||
|
import { Tab } from '@headlessui/react';
|
||||||
|
|
||||||
|
interface BeerPageProps {
|
||||||
|
beerPost: z.infer<typeof beerPostQueryResult>;
|
||||||
|
beerRecommendations: (BeerPost & {
|
||||||
|
brewery: { id: string; name: string };
|
||||||
|
beerImages: { id: string; alt: string; url: string }[];
|
||||||
|
})[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const BeerByIdPage: NextPage<BeerPageProps> = ({ beerPost, beerRecommendations }) => {
|
||||||
|
const isMd = useMediaQuery('(min-width: 768px)');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>{beerPost.name}</title>
|
||||||
|
<meta name="description" content={beerPost.description} />
|
||||||
|
</Head>
|
||||||
|
<Layout>
|
||||||
|
<div>
|
||||||
|
<Carousel
|
||||||
|
className="w-full"
|
||||||
|
useKeyboardArrows
|
||||||
|
autoPlay
|
||||||
|
interval={10000}
|
||||||
|
infiniteLoop
|
||||||
|
showThumbs={false}
|
||||||
|
>
|
||||||
|
{beerPost.beerImages.map((image, index) => (
|
||||||
|
<div key={image.id} id={`image-${index}}`} className="w-full">
|
||||||
|
<Image
|
||||||
|
alt={image.alt}
|
||||||
|
src={image.path}
|
||||||
|
height={1080}
|
||||||
|
width={1920}
|
||||||
|
className="h-[42rem] w-full object-cover"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</Carousel>
|
||||||
|
|
||||||
|
<div className="mb-12 mt-10 flex w-full items-center justify-center ">
|
||||||
|
<div className="w-11/12 space-y-3 xl:w-9/12">
|
||||||
|
<BeerInfoHeader beerPost={beerPost} />
|
||||||
|
|
||||||
|
{isMd ? (
|
||||||
|
<div className="mt-4 flex flex-row space-x-3 space-y-0">
|
||||||
|
<div className="w-[60%]">
|
||||||
|
<BeerPostCommentsSection beerPost={beerPost} />
|
||||||
|
</div>
|
||||||
|
<div className="w-[40%]">
|
||||||
|
<BeerRecommendations beerRecommendations={beerRecommendations} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Tab.Group>
|
||||||
|
<Tab.List className="card flex flex-row bg-base-300">
|
||||||
|
<Tab className="ui-selected:bg-gray w-1/2 p-3 uppercase">
|
||||||
|
Comments
|
||||||
|
</Tab>
|
||||||
|
<Tab className="ui-selected:bg-gray w-1/2 p-3 uppercase">
|
||||||
|
Recommendations
|
||||||
|
</Tab>
|
||||||
|
</Tab.List>
|
||||||
|
<Tab.Panels className="mt-2">
|
||||||
|
<Tab.Panel>
|
||||||
|
<BeerPostCommentsSection beerPost={beerPost} />
|
||||||
|
</Tab.Panel>
|
||||||
|
<Tab.Panel>
|
||||||
|
<BeerRecommendations beerRecommendations={beerRecommendations} />
|
||||||
|
</Tab.Panel>
|
||||||
|
</Tab.Panels>
|
||||||
|
</Tab.Group>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getServerSideProps: GetServerSideProps<BeerPageProps> = 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;
|
||||||
@@ -9,6 +9,9 @@ import BeerCard from '@/components/BeerIndex/BeerCard';
|
|||||||
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import UserContext from '@/contexts/userContext';
|
||||||
|
import { useContext } from 'react';
|
||||||
|
|
||||||
interface BeerPageProps {
|
interface BeerPageProps {
|
||||||
initialBeerPosts: z.infer<typeof beerPostQueryResult>[];
|
initialBeerPosts: z.infer<typeof beerPostQueryResult>[];
|
||||||
@@ -19,6 +22,8 @@ const BeerPage: NextPage<BeerPageProps> = ({ initialBeerPosts, pageCount }) => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { query } = router;
|
const { query } = router;
|
||||||
|
|
||||||
|
const { user } = useContext(UserContext);
|
||||||
|
|
||||||
const pageNum = parseInt(query.page_num as string, 10) || 1;
|
const pageNum = parseInt(query.page_num as string, 10) || 1;
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
@@ -28,13 +33,20 @@ const BeerPage: NextPage<BeerPageProps> = ({ initialBeerPosts, pageCount }) => {
|
|||||||
</Head>
|
</Head>
|
||||||
<div className="flex items-center justify-center bg-base-100">
|
<div className="flex items-center justify-center bg-base-100">
|
||||||
<div className="my-10 flex w-10/12 flex-col space-y-4">
|
<div className="my-10 flex w-10/12 flex-col space-y-4">
|
||||||
<header className="my-10">
|
<header className="my-10 flex justify-between">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<h1 className="text-6xl font-bold">The Biergarten Index</h1>
|
<h1 className="text-6xl font-bold">The Biergarten Index</h1>
|
||||||
<h2 className="text-2xl font-bold">
|
<h2 className="text-2xl font-bold">
|
||||||
Page {pageNum} of {pageCount}
|
Page {pageNum} of {pageCount}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
{!!user && (
|
||||||
|
<div>
|
||||||
|
<Link href="/beers/create" className="btn-primary btn">
|
||||||
|
Create a new beer post
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</header>
|
</header>
|
||||||
<div className="grid gap-5 md:grid-cols-2 xl:grid-cols-3">
|
<div className="grid gap-5 md:grid-cols-2 xl:grid-cols-3">
|
||||||
{initialBeerPosts.map((post) => {
|
{initialBeerPosts.map((post) => {
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { PrismaClient } from '@prisma/client';
|
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 };
|
const globalForPrisma = global as unknown as { prisma: PrismaClient };
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
@@ -20,12 +20,15 @@ const createNewBeerImages = async ({
|
|||||||
for (let i = 0; i < numberOfImages; i++) {
|
for (let i = 0; i < numberOfImages; i++) {
|
||||||
const beerPost = beerPosts[Math.floor(Math.random() * beerPosts.length)];
|
const beerPost = beerPosts[Math.floor(Math.random() * beerPosts.length)];
|
||||||
const user = users[Math.floor(Math.random() * users.length)];
|
const user = users[Math.floor(Math.random() * users.length)];
|
||||||
|
const caption = faker.lorem.sentence();
|
||||||
|
const alt = faker.lorem.sentence();
|
||||||
|
|
||||||
beerImagesPromises.push(
|
beerImagesPromises.push(
|
||||||
prisma.beerImage.create({
|
prisma.beerImage.create({
|
||||||
data: {
|
data: {
|
||||||
path: 'https://picsum.photos/5000/5000',
|
path: 'https://picsum.photos/5000/5000',
|
||||||
alt: 'Placeholder beer image.',
|
alt,
|
||||||
caption: 'Placeholder beer image caption.',
|
caption,
|
||||||
beerPost: { connect: { id: beerPost.id } },
|
beerPost: { connect: { id: beerPost.id } },
|
||||||
postedBy: { connect: { id: user.id } },
|
postedBy: { connect: { id: user.id } },
|
||||||
createdAt,
|
createdAt,
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user