mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 10:42:08 +00:00
Work on brewery page, refactors
Refactor query types to explicitly use z.infer
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import sendCreateBeerCommentRequest from '@/requests/sendCreateBeerCommentRequest';
|
import sendCreateBeerCommentRequest from '@/requests/sendCreateBeerCommentRequest';
|
||||||
import BeerCommentValidationSchema from '@/services/BeerComment/schema/CreateBeerCommentValidationSchema';
|
import BeerCommentValidationSchema from '@/services/BeerComment/schema/CreateBeerCommentValidationSchema';
|
||||||
import { BeerPostQueryResult } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { FunctionComponent, useState, useEffect } from 'react';
|
import { FunctionComponent, useState, useEffect } from 'react';
|
||||||
@@ -16,7 +16,7 @@ import FormSegment from '../ui/forms/FormSegment';
|
|||||||
import FormTextArea from '../ui/forms/FormTextArea';
|
import FormTextArea from '../ui/forms/FormTextArea';
|
||||||
|
|
||||||
interface BeerCommentFormProps {
|
interface BeerCommentFormProps {
|
||||||
beerPost: BeerPostQueryResult;
|
beerPost: z.infer<typeof beerPostQueryResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BeerCommentForm: FunctionComponent<BeerCommentFormProps> = ({ beerPost }) => {
|
const BeerCommentForm: FunctionComponent<BeerCommentFormProps> = ({ beerPost }) => {
|
||||||
|
|||||||
@@ -2,33 +2,24 @@ import Link from 'next/link';
|
|||||||
import formatDistanceStrict from 'date-fns/formatDistanceStrict';
|
import formatDistanceStrict from 'date-fns/formatDistanceStrict';
|
||||||
import format from 'date-fns/format';
|
import format from 'date-fns/format';
|
||||||
import { FC, useContext, useEffect, useState } from 'react';
|
import { FC, useContext, useEffect, useState } from 'react';
|
||||||
import { BeerPostQueryResult } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
|
||||||
|
|
||||||
import UserContext from '@/contexts/userContext';
|
import UserContext from '@/contexts/userContext';
|
||||||
import { FaRegEdit } from 'react-icons/fa';
|
import { FaRegEdit } from 'react-icons/fa';
|
||||||
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
|
import { z } from 'zod';
|
||||||
import BeerPostLikeButton from './BeerPostLikeButton';
|
import BeerPostLikeButton from './BeerPostLikeButton';
|
||||||
|
|
||||||
const BeerInfoHeader: FC<{ beerPost: BeerPostQueryResult; initialLikeCount: number }> = ({
|
const BeerInfoHeader: FC<{
|
||||||
beerPost,
|
beerPost: z.infer<typeof beerPostQueryResult>;
|
||||||
initialLikeCount,
|
initialLikeCount: number;
|
||||||
}) => {
|
}> = ({ beerPost, initialLikeCount }) => {
|
||||||
const createdAtDate = new Date(beerPost.createdAt);
|
const createdAtDate = new Date(beerPost.createdAt);
|
||||||
const [timeDistance, setTimeDistance] = useState('');
|
const [timeDistance, setTimeDistance] = useState('');
|
||||||
const { user } = useContext(UserContext);
|
const { user } = useContext(UserContext);
|
||||||
|
|
||||||
const [likeCount, setLikeCount] = useState(initialLikeCount);
|
const [likeCount, setLikeCount] = useState(initialLikeCount);
|
||||||
const [isPostOwner, setIsPostOwner] = useState(false);
|
const idMatches = user && beerPost.postedBy.id === user.id;
|
||||||
|
const isPostOwner = !!(user && idMatches);
|
||||||
useEffect(() => {
|
|
||||||
const idMatches = user && beerPost.postedBy.id === user.id;
|
|
||||||
|
|
||||||
if (!(user && idMatches)) {
|
|
||||||
setIsPostOwner(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsPostOwner(true);
|
|
||||||
}, [user, beerPost]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLikeCount(initialLikeCount);
|
setLikeCount(initialLikeCount);
|
||||||
@@ -67,15 +58,15 @@ const BeerInfoHeader: FC<{ beerPost: BeerPostQueryResult; initialLikeCount: numb
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3 className="italic">
|
<h3 className="italic">
|
||||||
posted by{' '}
|
{' posted by '}
|
||||||
<Link href={`/users/${beerPost.postedBy.id}`} className="link-hover link">
|
<Link href={`/users/${beerPost.postedBy.id}`} className="link-hover link">
|
||||||
{beerPost.postedBy.username}
|
{`${beerPost.postedBy.username} `}
|
||||||
</Link>
|
</Link>
|
||||||
<span
|
<span
|
||||||
className="tooltip tooltip-bottom"
|
className="tooltip tooltip-right"
|
||||||
data-tip={format(createdAtDate, 'MM/dd/yyyy')}
|
data-tip={format(createdAtDate, 'MM/dd/yyyy')}
|
||||||
>
|
>
|
||||||
{` ${timeDistance}`} ago
|
{`${timeDistance} ago`}
|
||||||
</span>
|
</span>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { BeerPostQueryResult } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
|
||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
interface BeerCommentsPaginationBarProps {
|
interface BeerCommentsPaginationBarProps {
|
||||||
commentsPageNum: number;
|
commentsPageNum: number;
|
||||||
commentsPageCount: number;
|
commentsPageCount: number;
|
||||||
beerPost: BeerPostQueryResult;
|
beerPost: z.infer<typeof beerPostQueryResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BeerCommentsPaginationBar: FC<BeerCommentsPaginationBarProps> = ({
|
const BeerCommentsPaginationBar: FC<BeerCommentsPaginationBarProps> = ({
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import UserContext from '@/contexts/userContext';
|
import UserContext from '@/contexts/userContext';
|
||||||
import { BeerCommentQueryResultArrayT } from '@/services/BeerComment/schema/BeerCommentQueryResult';
|
import BeerCommentQueryResult from '@/services/BeerComment/schema/BeerCommentQueryResult';
|
||||||
import { BeerPostQueryResult } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
|
||||||
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { FC, useContext } from 'react';
|
import { FC, useContext } from 'react';
|
||||||
|
import { z } from 'zod';
|
||||||
import BeerCommentForm from './BeerCommentForm';
|
import BeerCommentForm from './BeerCommentForm';
|
||||||
import BeerCommentsPaginationBar from './BeerPostCommentsPaginationBar';
|
import BeerCommentsPaginationBar from './BeerPostCommentsPaginationBar';
|
||||||
import CommentCard from './CommentCard';
|
import CommentCard from './CommentCard';
|
||||||
|
|
||||||
interface BeerPostCommentsSectionProps {
|
interface BeerPostCommentsSectionProps {
|
||||||
beerPost: BeerPostQueryResult;
|
beerPost: z.infer<typeof beerPostQueryResult>;
|
||||||
comments: BeerCommentQueryResultArrayT;
|
comments: z.infer<typeof BeerCommentQueryResult>[];
|
||||||
commentsPageCount: number;
|
commentsPageCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import UserContext from '@/contexts/userContext';
|
import UserContext from '@/contexts/userContext';
|
||||||
import { BeerCommentQueryResultT } from '@/services/BeerComment/schema/BeerCommentQueryResult';
|
import BeerCommentQueryResult from '@/services/BeerComment/schema/BeerCommentQueryResult';
|
||||||
import { format, formatDistanceStrict } from 'date-fns';
|
import { format, formatDistanceStrict } from 'date-fns';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
@@ -7,9 +7,10 @@ import { useContext, useEffect, useState } from 'react';
|
|||||||
import { Rating } from 'react-daisyui';
|
import { Rating } from 'react-daisyui';
|
||||||
|
|
||||||
import { FaEllipsisH } from 'react-icons/fa';
|
import { FaEllipsisH } from 'react-icons/fa';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
const CommentCardDropdown: React.FC<{
|
const CommentCardDropdown: React.FC<{
|
||||||
comment: BeerCommentQueryResultT;
|
comment: z.infer<typeof BeerCommentQueryResult>;
|
||||||
beerPostId: string;
|
beerPostId: string;
|
||||||
}> = ({ comment, beerPostId }) => {
|
}> = ({ comment, beerPostId }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -52,7 +53,7 @@ const CommentCardDropdown: React.FC<{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CommentCard: React.FC<{
|
const CommentCard: React.FC<{
|
||||||
comment: BeerCommentQueryResultT;
|
comment: z.infer<typeof BeerCommentQueryResult>;
|
||||||
beerPostId: string;
|
beerPostId: string;
|
||||||
}> = ({ comment, beerPostId }) => {
|
}> = ({ comment, beerPostId }) => {
|
||||||
const [timeDistance, setTimeDistance] = useState('');
|
const [timeDistance, setTimeDistance] = useState('');
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { BeerPostQueryResult } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
const BeerCard: FC<{ post: BeerPostQueryResult }> = ({ post }) => {
|
const BeerCard: FC<{ post: z.infer<typeof beerPostQueryResult> }> = ({ post }) => {
|
||||||
return (
|
return (
|
||||||
<div className="card bg-base-300" key={post.id}>
|
<div className="card bg-base-300" key={post.id}>
|
||||||
<figure className="card-image h-96">
|
<figure className="card-image h-96">
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import sendCreateBeerPostRequest from '@/requests/sendCreateBeerPostRequest';
|
import sendCreateBeerPostRequest from '@/requests/sendCreateBeerPostRequest';
|
||||||
import CreateBeerPostValidationSchema from '@/services/BeerPost/schema/CreateBeerPostValidationSchema';
|
import CreateBeerPostValidationSchema from '@/services/BeerPost/schema/CreateBeerPostValidationSchema';
|
||||||
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { BeerType } from '@prisma/client';
|
import { BeerType } from '@prisma/client';
|
||||||
import router from 'next/router';
|
import router from 'next/router';
|
||||||
import { FunctionComponent, useState } from 'react';
|
import { FunctionComponent, useState } from 'react';
|
||||||
import { useForm, SubmitHandler } from 'react-hook-form';
|
import { useForm, SubmitHandler } from 'react-hook-form';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
||||||
import ErrorAlert from './ui/alerts/ErrorAlert';
|
import ErrorAlert from './ui/alerts/ErrorAlert';
|
||||||
import Button from './ui/forms/Button';
|
import Button from './ui/forms/Button';
|
||||||
import FormError from './ui/forms/FormError';
|
import FormError from './ui/forms/FormError';
|
||||||
@@ -20,7 +20,7 @@ import FormTextInput from './ui/forms/FormTextInput';
|
|||||||
type CreateBeerPostSchema = z.infer<typeof CreateBeerPostValidationSchema>;
|
type CreateBeerPostSchema = z.infer<typeof CreateBeerPostValidationSchema>;
|
||||||
|
|
||||||
interface BeerFormProps {
|
interface BeerFormProps {
|
||||||
breweries: BreweryPostQueryResult[];
|
breweries: z.infer<typeof BreweryPostQueryResult>[];
|
||||||
types: BeerType[];
|
types: BeerType[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ const EditBeerPostForm: FC<EditBeerPostFormProps> = ({ previousValues }) => {
|
|||||||
{isSubmitting ? 'Submitting...' : 'Submit'}
|
{isSubmitting ? 'Submitting...' : 'Submit'}
|
||||||
</Button>
|
</Button>
|
||||||
<button
|
<button
|
||||||
className={`btn-primary btn w-full rounded-xl ${isSubmitting ? 'loading' : ''}`}
|
className={`btn btn-primary w-full rounded-xl ${isSubmitting ? 'loading' : ''}`}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={onDelete}
|
onClick={onDelete}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const Navbar = () => {
|
|||||||
return (
|
return (
|
||||||
<nav className="navbar bg-primary text-primary-content">
|
<nav className="navbar bg-primary text-primary-content">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<Link className="btn-ghost btn text-3xl normal-case" href="/">
|
<Link className="btn btn-ghost text-3xl normal-case" href="/">
|
||||||
<span className="cursor-pointer text-xl font-bold">The Biergarten App</span>
|
<span className="cursor-pointer text-xl font-bold">The Biergarten App</span>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
@@ -68,8 +68,8 @@ const Navbar = () => {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-none lg:hidden">
|
<div className="flex-none lg:hidden">
|
||||||
<div className="dropdown-end dropdown">
|
<div className="dropdown dropdown-end">
|
||||||
<label tabIndex={0} className="btn-ghost btn-circle btn">
|
<label tabIndex={0} className="btn btn-ghost btn-circle">
|
||||||
<span className="w-10 rounded-full">
|
<span className="w-10 rounded-full">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const FormPageLayout: FC<FormPageLayoutProps> = ({
|
|||||||
<div className="align-center my-20 flex h-fit flex-col items-center justify-center">
|
<div className="align-center my-20 flex h-fit flex-col items-center justify-center">
|
||||||
<div className="w-8/12">
|
<div className="w-8/12">
|
||||||
<div className="tooltip tooltip-bottom absolute" data-tip={backLinkText}>
|
<div className="tooltip tooltip-bottom absolute" data-tip={backLinkText}>
|
||||||
<Link href={backLink} className="btn-ghost btn-sm btn p-0">
|
<Link href={backLink} className="btn btn-ghost btn-sm p-0">
|
||||||
<BiArrowBack className="text-xl" />
|
<BiArrowBack className="text-xl" />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import { beerPostQueryResultArraySchema } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
import { z } from 'zod';
|
||||||
|
|
||||||
const useBeerPostSearch = (query: string | undefined) => {
|
const useBeerPostSearch = (query: string | undefined) => {
|
||||||
const { data, isLoading, error } = useSWR(
|
const { data, isLoading, error } = useSWR(
|
||||||
@@ -13,7 +14,7 @@ const useBeerPostSearch = (query: string | undefined) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
const result = beerPostQueryResultArraySchema.parse(json);
|
const result = z.array(beerPostQueryResult).parse(json);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
import UserContext from '@/contexts/userContext';
|
import UserContext from '@/contexts/userContext';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useContext, useEffect } from 'react';
|
import { useContext } from 'react';
|
||||||
|
|
||||||
const useRedirectWhenLoggedIn = () => {
|
const useRedirectWhenLoggedIn = () => {
|
||||||
const { user } = useContext(UserContext);
|
const { user } = useContext(UserContext);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
useEffect(() => {
|
if (!user) {
|
||||||
if (!user) {
|
return;
|
||||||
return;
|
}
|
||||||
}
|
router.push('/');
|
||||||
router.push('/');
|
|
||||||
}, [user, router]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useRedirectWhenLoggedIn;
|
export default useRedirectWhenLoggedIn;
|
||||||
|
|||||||
@@ -1,21 +1,28 @@
|
|||||||
|
import DBClient from '@/prisma/DBClient';
|
||||||
|
import getAllBeerComments from '@/services/BeerComment/getAllBeerComments';
|
||||||
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
|
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
|
||||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||||
import { UserExtendedNextApiRequest } from '@/config/auth/types';
|
import { UserExtendedNextApiRequest } from '@/config/auth/types';
|
||||||
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
|
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
|
||||||
import createNewBeerComment from '@/services/BeerComment/createNewBeerComment';
|
import createNewBeerComment from '@/services/BeerComment/createNewBeerComment';
|
||||||
import { BeerCommentQueryResultT } from '@/services/BeerComment/schema/BeerCommentQueryResult';
|
|
||||||
import BeerCommentValidationSchema from '@/services/BeerComment/schema/CreateBeerCommentValidationSchema';
|
import BeerCommentValidationSchema from '@/services/BeerComment/schema/CreateBeerCommentValidationSchema';
|
||||||
|
|
||||||
import { createRouter } from 'next-connect';
|
import { createRouter } from 'next-connect';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
|
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
|
||||||
import { NextApiResponse } from 'next';
|
import { NextApiResponse } from 'next';
|
||||||
|
import BeerCommentQueryResult from '@/services/BeerComment/schema/BeerCommentQueryResult';
|
||||||
|
|
||||||
interface CreateCommentRequest extends UserExtendedNextApiRequest {
|
interface CreateCommentRequest extends UserExtendedNextApiRequest {
|
||||||
body: z.infer<typeof BeerCommentValidationSchema>;
|
body: z.infer<typeof BeerCommentValidationSchema>;
|
||||||
query: { id: string };
|
query: { id: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface GetAllCommentsRequest extends UserExtendedNextApiRequest {
|
||||||
|
query: { id: string; page_size: string; page_num: string };
|
||||||
|
}
|
||||||
|
|
||||||
const createComment = async (
|
const createComment = async (
|
||||||
req: CreateCommentRequest,
|
req: CreateCommentRequest,
|
||||||
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
||||||
@@ -24,12 +31,13 @@ const createComment = async (
|
|||||||
|
|
||||||
const beerPostId = req.query.id;
|
const beerPostId = req.query.id;
|
||||||
|
|
||||||
const newBeerComment: BeerCommentQueryResultT = await createNewBeerComment({
|
const newBeerComment: z.infer<typeof BeerCommentQueryResult> =
|
||||||
content,
|
await createNewBeerComment({
|
||||||
rating,
|
content,
|
||||||
beerPostId,
|
rating,
|
||||||
userId: req.user!.id,
|
beerPostId,
|
||||||
});
|
userId: req.user!.id,
|
||||||
|
});
|
||||||
|
|
||||||
res.status(201).json({
|
res.status(201).json({
|
||||||
message: 'Beer comment created successfully',
|
message: 'Beer comment created successfully',
|
||||||
@@ -39,8 +47,34 @@ const createComment = async (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getAll = async (
|
||||||
|
req: GetAllCommentsRequest,
|
||||||
|
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
||||||
|
) => {
|
||||||
|
const beerPostId = req.query.id;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
|
const { page_size, page_num } = req.query;
|
||||||
|
|
||||||
|
const comments = await getAllBeerComments(
|
||||||
|
{ id: beerPostId },
|
||||||
|
{ pageSize: parseInt(page_size, 10), pageNum: parseInt(page_num, 10) },
|
||||||
|
);
|
||||||
|
|
||||||
|
const pageCount = await DBClient.instance.beerComment.count({ where: { beerPostId } });
|
||||||
|
|
||||||
|
res.setHeader('X-Total-Count', pageCount);
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
message: 'Beer comments fetched successfully',
|
||||||
|
statusCode: 200,
|
||||||
|
payload: comments,
|
||||||
|
success: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const router = createRouter<
|
const router = createRouter<
|
||||||
CreateCommentRequest,
|
// I don't want to use any, but I can't figure out how to get the types to work
|
||||||
|
any,
|
||||||
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
|
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
|
||||||
>();
|
>();
|
||||||
|
|
||||||
@@ -53,5 +87,16 @@ router.post(
|
|||||||
createComment,
|
createComment,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
router.get(
|
||||||
|
validateRequest({
|
||||||
|
querySchema: z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
page_size: z.coerce.number().int().positive(),
|
||||||
|
page_num: z.coerce.number().int().positive(),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
getAll,
|
||||||
|
);
|
||||||
|
|
||||||
const handler = router.handler(NextConnectOptions);
|
const handler = router.handler(NextConnectOptions);
|
||||||
export default handler;
|
export default handler;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { NextApiRequest, NextApiResponse } from 'next';
|
|||||||
import { createRouter } from 'next-connect';
|
import { createRouter } from 'next-connect';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import DBClient from '@/prisma/DBClient';
|
import DBClient from '@/prisma/DBClient';
|
||||||
import { BeerPostQueryResult } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
|
|
||||||
const SearchSchema = z.object({
|
const SearchSchema = z.object({
|
||||||
search: z.string().min(1),
|
search: z.string().min(1),
|
||||||
@@ -18,29 +18,30 @@ interface SearchAPIRequest extends NextApiRequest {
|
|||||||
const search = async (req: SearchAPIRequest, res: NextApiResponse) => {
|
const search = async (req: SearchAPIRequest, res: NextApiResponse) => {
|
||||||
const { search: query } = req.query;
|
const { search: query } = req.query;
|
||||||
|
|
||||||
const beers: BeerPostQueryResult[] = await DBClient.instance.beerPost.findMany({
|
const beers: z.infer<typeof beerPostQueryResult>[] =
|
||||||
select: {
|
await DBClient.instance.beerPost.findMany({
|
||||||
id: true,
|
select: {
|
||||||
name: true,
|
id: true,
|
||||||
ibu: true,
|
name: true,
|
||||||
abv: true,
|
ibu: true,
|
||||||
createdAt: true,
|
abv: true,
|
||||||
description: true,
|
createdAt: true,
|
||||||
postedBy: { select: { username: true, id: true } },
|
description: true,
|
||||||
brewery: { select: { name: true, id: true } },
|
postedBy: { select: { username: true, id: true } },
|
||||||
type: { select: { name: true, id: true } },
|
brewery: { select: { name: true, id: true } },
|
||||||
beerImages: { select: { alt: true, path: true, caption: true, id: true } },
|
type: { select: { name: true, id: true } },
|
||||||
},
|
beerImages: { select: { alt: true, path: true, caption: true, id: true } },
|
||||||
where: {
|
},
|
||||||
OR: [
|
where: {
|
||||||
{ name: { contains: query, mode: 'insensitive' } },
|
OR: [
|
||||||
{ description: { contains: query, mode: 'insensitive' } },
|
{ name: { contains: query, mode: 'insensitive' } },
|
||||||
|
{ description: { contains: query, mode: 'insensitive' } },
|
||||||
|
|
||||||
{ brewery: { name: { contains: query, mode: 'insensitive' } } },
|
{ brewery: { name: { contains: query, mode: 'insensitive' } } },
|
||||||
{ type: { name: { contains: query, mode: 'insensitive' } } },
|
{ type: { name: { contains: query, mode: 'insensitive' } } },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
res.status(200).json(beers);
|
res.status(200).json(beers);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,13 +5,14 @@ import React from 'react';
|
|||||||
import Layout from '@/components/ui/Layout';
|
import Layout from '@/components/ui/Layout';
|
||||||
import withPageAuthRequired from '@/getServerSideProps/withPageAuthRequired';
|
import withPageAuthRequired from '@/getServerSideProps/withPageAuthRequired';
|
||||||
import getBeerPostById from '@/services/BeerPost/getBeerPostById';
|
import getBeerPostById from '@/services/BeerPost/getBeerPostById';
|
||||||
import { BeerPostQueryResult } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
import EditBeerPostForm from '@/components/EditBeerPostForm';
|
import EditBeerPostForm from '@/components/EditBeerPostForm';
|
||||||
import FormPageLayout from '@/components/ui/forms/FormPageLayout';
|
import FormPageLayout from '@/components/ui/forms/FormPageLayout';
|
||||||
import { BiBeer } from 'react-icons/bi';
|
import { BiBeer } from 'react-icons/bi';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
interface EditPageProps {
|
interface EditPageProps {
|
||||||
beerPost: BeerPostQueryResult;
|
beerPost: z.infer<typeof beerPostQueryResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EditPage: NextPage<EditPageProps> = ({ beerPost }) => {
|
const EditPage: NextPage<EditPageProps> = ({ beerPost }) => {
|
||||||
|
|||||||
@@ -11,19 +11,20 @@ import getAllBeerComments from '@/services/BeerComment/getAllBeerComments';
|
|||||||
import getBeerPostById from '@/services/BeerPost/getBeerPostById';
|
import getBeerPostById from '@/services/BeerPost/getBeerPostById';
|
||||||
import getBeerRecommendations from '@/services/BeerPost/getBeerRecommendations';
|
import getBeerRecommendations from '@/services/BeerPost/getBeerRecommendations';
|
||||||
|
|
||||||
import { BeerCommentQueryResultArrayT } from '@/services/BeerComment/schema/BeerCommentQueryResult';
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
import { BeerPostQueryResult } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
|
||||||
import { BeerPost } from '@prisma/client';
|
import { BeerPost } from '@prisma/client';
|
||||||
import getBeerPostLikeCount from '@/services/BeerPostLike/getBeerPostLikeCount';
|
import getBeerPostLikeCount from '@/services/BeerPostLike/getBeerPostLikeCount';
|
||||||
import getBeerCommentCount from '@/services/BeerComment/getBeerCommentCount';
|
import getBeerCommentCount from '@/services/BeerComment/getBeerCommentCount';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import BeerCommentQueryResult from '@/services/BeerComment/schema/BeerCommentQueryResult';
|
||||||
|
|
||||||
interface BeerPageProps {
|
interface BeerPageProps {
|
||||||
beerPost: BeerPostQueryResult;
|
beerPost: z.infer<typeof beerPostQueryResult>;
|
||||||
beerRecommendations: (BeerPost & {
|
beerRecommendations: (BeerPost & {
|
||||||
brewery: { id: string; name: string };
|
brewery: { id: string; name: string };
|
||||||
beerImages: { id: string; alt: string; url: string }[];
|
beerImages: { id: string; alt: string; url: string }[];
|
||||||
})[];
|
})[];
|
||||||
beerComments: BeerCommentQueryResultArrayT;
|
beerComments: z.infer<typeof BeerCommentQueryResult>[];
|
||||||
commentsPageCount: number;
|
commentsPageCount: number;
|
||||||
likeCount: number;
|
likeCount: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQuer
|
|||||||
import { BeerType } from '@prisma/client';
|
import { BeerType } from '@prisma/client';
|
||||||
import { NextPage } from 'next';
|
import { NextPage } from 'next';
|
||||||
import { BiBeer } from 'react-icons/bi';
|
import { BiBeer } from 'react-icons/bi';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
interface CreateBeerPageProps {
|
interface CreateBeerPageProps {
|
||||||
breweries: BreweryPostQueryResult[];
|
breweries: z.infer<typeof BreweryPostQueryResult>[];
|
||||||
types: BeerType[];
|
types: BeerType[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,12 @@ import DBClient from '@/prisma/DBClient';
|
|||||||
import Layout from '@/components/ui/Layout';
|
import Layout from '@/components/ui/Layout';
|
||||||
import BeerIndexPaginationBar from '@/components/BeerIndex/BeerIndexPaginationBar';
|
import BeerIndexPaginationBar from '@/components/BeerIndex/BeerIndexPaginationBar';
|
||||||
import BeerCard from '@/components/BeerIndex/BeerCard';
|
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';
|
||||||
|
|
||||||
interface BeerPageProps {
|
interface BeerPageProps {
|
||||||
initialBeerPosts: BeerPostQueryResult[];
|
initialBeerPosts: z.infer<typeof beerPostQueryResult>[];
|
||||||
pageCount: number;
|
pageCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ const DEBOUNCE_DELAY = 300;
|
|||||||
|
|
||||||
const SearchPage: NextPage = () => {
|
const SearchPage: NextPage = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const querySearch = router.query.search as string | undefined;
|
const querySearch = (router.query.search as string) || '';
|
||||||
const [searchValue, setSearchValue] = useState(querySearch || '');
|
const [searchValue, setSearchValue] = useState(querySearch);
|
||||||
const { searchResults, isLoading, searchError } = useBeerPostSearch(searchValue);
|
const { searchResults, isLoading, searchError } = useBeerPostSearch(searchValue);
|
||||||
|
|
||||||
const debounceSearch = debounce((value: string) => {
|
const debounceSearch = debounce((value: string) => {
|
||||||
@@ -36,7 +36,7 @@ const SearchPage: NextPage = () => {
|
|||||||
if (!querySearch || searchValue) {
|
if (!querySearch || searchValue) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setSearchValue(searchValue);
|
setSearchValue(querySearch);
|
||||||
}, DEBOUNCE_DELAY)();
|
}, DEBOUNCE_DELAY)();
|
||||||
}, [querySearch, searchValue]);
|
}, [querySearch, searchValue]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import Layout from '@/components/ui/Layout';
|
import Layout from '@/components/ui/Layout';
|
||||||
import { BeerPostQueryResult } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
|
||||||
import getBreweryPostById from '@/services/BreweryPost/getBreweryPostById';
|
import getBreweryPostById from '@/services/BreweryPost/getBreweryPostById';
|
||||||
|
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
||||||
import { GetServerSideProps, NextPage } from 'next';
|
import { GetServerSideProps, NextPage } from 'next';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
interface BreweryPageProps {
|
interface BreweryPageProps {
|
||||||
breweryPost: BeerPostQueryResult;
|
breweryPost: z.infer<typeof BreweryPostQueryResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BreweryByIdPage: NextPage<BreweryPageProps> = ({ breweryPost }) => {
|
const BreweryByIdPage: NextPage<BreweryPageProps> = ({ breweryPost }) => {
|
||||||
|
|||||||
@@ -4,24 +4,58 @@ import Link from 'next/link';
|
|||||||
import getAllBreweryPosts from '@/services/BreweryPost/getAllBreweryPosts';
|
import getAllBreweryPosts from '@/services/BreweryPost/getAllBreweryPosts';
|
||||||
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
||||||
import Layout from '@/components/ui/Layout';
|
import Layout from '@/components/ui/Layout';
|
||||||
|
import { FC } from 'react';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
interface BreweryPageProps {
|
interface BreweryPageProps {
|
||||||
breweryPosts: BreweryPostQueryResult[];
|
breweryPosts: z.infer<typeof BreweryPostQueryResult>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BreweryCard: FC<{ brewery: z.infer<typeof BreweryPostQueryResult> }> = ({
|
||||||
|
brewery,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className="card bg-base-300" key={brewery.id}>
|
||||||
|
<figure className="card-image h-96">
|
||||||
|
{brewery.breweryImages.length > 0 && (
|
||||||
|
<Image
|
||||||
|
src={brewery.breweryImages[0].path}
|
||||||
|
alt={brewery.name}
|
||||||
|
width="1029"
|
||||||
|
height="110"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</figure>
|
||||||
|
<div className="card-body space-y-3">
|
||||||
|
<div>
|
||||||
|
<h2 className="text-3xl font-bold">
|
||||||
|
<Link href={`/breweries/${brewery.id}`}>{brewery.name}</Link>
|
||||||
|
</h2>
|
||||||
|
<h3 className="text-xl font-semibold">{brewery.location}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const BreweryPage: NextPage<BreweryPageProps> = ({ breweryPosts }) => {
|
const BreweryPage: NextPage<BreweryPageProps> = ({ breweryPosts }) => {
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<h1 className="text-3xl font-bold underline">Brewery Posts</h1>
|
<div className="flex items-center justify-center bg-base-100">
|
||||||
{breweryPosts.map((post) => {
|
<div className="my-10 flex w-10/12 flex-col space-y-4">
|
||||||
return (
|
<header className="my-10">
|
||||||
<div key={post.id}>
|
<div className="space-y-2">
|
||||||
<h2>
|
<h1 className="text-6xl font-bold">Breweries</h1>
|
||||||
<Link href={`/breweries/${post.id}`}>{post.name}</Link>
|
</div>
|
||||||
</h2>
|
</header>
|
||||||
|
<div className="grid gap-5 md:grid-cols-1 xl:grid-cols-2">
|
||||||
|
{breweryPosts.map((brewery) => {
|
||||||
|
return <BreweryCard brewery={brewery} key={brewery.id} />;
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
);
|
</div>
|
||||||
})}
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BeerCommentQueryResult } from '@/services/BeerComment/schema/BeerCommentQueryResult';
|
import BeerCommentQueryResult from '@/services/BeerComment/schema/BeerCommentQueryResult';
|
||||||
import BeerCommentValidationSchema from '@/services/BeerComment/schema/CreateBeerCommentValidationSchema';
|
import BeerCommentValidationSchema from '@/services/BeerComment/schema/CreateBeerCommentValidationSchema';
|
||||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
@@ -14,14 +14,8 @@ const sendCreateBeerCommentRequest = async ({
|
|||||||
}: z.infer<typeof BeerCommentValidationSchemaWithId>) => {
|
}: z.infer<typeof BeerCommentValidationSchemaWithId>) => {
|
||||||
const response = await fetch(`/api/beers/${beerPostId}/comments`, {
|
const response = await fetch(`/api/beers/${beerPostId}/comments`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: { 'Content-Type': 'application/json' },
|
||||||
'Content-Type': 'application/json',
|
body: JSON.stringify({ beerPostId, content, rating }),
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
beerPostId,
|
|
||||||
content,
|
|
||||||
rating,
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { beerPostQueryResultSchema } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
import CreateBeerPostValidationSchema from '@/services/BeerPost/schema/CreateBeerPostValidationSchema';
|
import CreateBeerPostValidationSchema from '@/services/BeerPost/schema/CreateBeerPostValidationSchema';
|
||||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
@@ -24,7 +24,7 @@ const sendCreateBeerPostRequest = async (
|
|||||||
throw new Error(message);
|
throw new Error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsedPayload = beerPostQueryResultSchema.safeParse(payload);
|
const parsedPayload = beerPostQueryResult.safeParse(payload);
|
||||||
|
|
||||||
if (!parsedPayload.success) {
|
if (!parsedPayload.success) {
|
||||||
throw new Error('Invalid API response payload');
|
throw new Error('Invalid API response payload');
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import DBClient from '@/prisma/DBClient';
|
import DBClient from '@/prisma/DBClient';
|
||||||
import { BeerPostQueryResult } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
import { BeerCommentQueryResultArrayT } from './schema/BeerCommentQueryResult';
|
import { z } from 'zod';
|
||||||
|
import BeerCommentQueryResult from './schema/BeerCommentQueryResult';
|
||||||
|
|
||||||
const getAllBeerComments = async (
|
const getAllBeerComments = async (
|
||||||
{ id }: Pick<BeerPostQueryResult, 'id'>,
|
{ id }: Pick<z.infer<typeof beerPostQueryResult>, 'id'>,
|
||||||
{ pageSize, pageNum = 0 }: { pageSize: number; pageNum?: number },
|
{ pageSize, pageNum = 0 }: { pageSize: number; pageNum?: number },
|
||||||
) => {
|
) => {
|
||||||
const skip = (pageNum - 1) * pageSize;
|
const skip = (pageNum - 1) * pageSize;
|
||||||
const beerComments: BeerCommentQueryResultArrayT =
|
const beerComments: z.infer<typeof BeerCommentQueryResult>[] =
|
||||||
await DBClient.instance.beerComment.findMany({
|
await DBClient.instance.beerComment.findMany({
|
||||||
skip,
|
skip,
|
||||||
take: pageSize,
|
take: pageSize,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export const BeerCommentQueryResult = z.object({
|
const BeerCommentQueryResult = z.object({
|
||||||
id: z.string().uuid(),
|
id: z.string().uuid(),
|
||||||
content: z.string().min(1).max(300),
|
content: z.string().min(1).max(500),
|
||||||
rating: z.number().int().min(1).max(5),
|
rating: z.number().int().min(1).max(5),
|
||||||
createdAt: z.coerce.date(),
|
createdAt: z.coerce.date(),
|
||||||
postedBy: z.object({
|
postedBy: z.object({
|
||||||
@@ -10,6 +10,5 @@ export const BeerCommentQueryResult = z.object({
|
|||||||
username: z.string().min(1).max(50),
|
username: z.string().min(1).max(50),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
export const BeerCommentQueryResultArray = z.array(BeerCommentQueryResult);
|
|
||||||
export type BeerCommentQueryResultT = z.infer<typeof BeerCommentQueryResult>;
|
export default BeerCommentQueryResult;
|
||||||
export type BeerCommentQueryResultArrayT = z.infer<typeof BeerCommentQueryResultArray>;
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import DBClient from '@/prisma/DBClient';
|
import DBClient from '@/prisma/DBClient';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { BeerPostQueryResult } from './schema/BeerPostQueryResult';
|
import beerPostQueryResult from './schema/BeerPostQueryResult';
|
||||||
import CreateBeerPostValidationSchema from './schema/CreateBeerPostValidationSchema';
|
import CreateBeerPostValidationSchema from './schema/CreateBeerPostValidationSchema';
|
||||||
|
|
||||||
const CreateBeerPostWithUserSchema = CreateBeerPostValidationSchema.extend({
|
const CreateBeerPostWithUserSchema = CreateBeerPostValidationSchema.extend({
|
||||||
@@ -16,29 +16,30 @@ const createNewBeerPost = async ({
|
|||||||
breweryId,
|
breweryId,
|
||||||
userId,
|
userId,
|
||||||
}: z.infer<typeof CreateBeerPostWithUserSchema>) => {
|
}: z.infer<typeof CreateBeerPostWithUserSchema>) => {
|
||||||
const newBeerPost: BeerPostQueryResult = await DBClient.instance.beerPost.create({
|
const newBeerPost: z.infer<typeof beerPostQueryResult> =
|
||||||
data: {
|
await DBClient.instance.beerPost.create({
|
||||||
name,
|
data: {
|
||||||
description,
|
name,
|
||||||
abv,
|
description,
|
||||||
ibu,
|
abv,
|
||||||
type: { connect: { id: typeId } },
|
ibu,
|
||||||
postedBy: { connect: { id: userId } },
|
type: { connect: { id: typeId } },
|
||||||
brewery: { connect: { id: breweryId } },
|
postedBy: { connect: { id: userId } },
|
||||||
},
|
brewery: { connect: { id: breweryId } },
|
||||||
select: {
|
},
|
||||||
id: true,
|
select: {
|
||||||
name: true,
|
id: true,
|
||||||
description: true,
|
name: true,
|
||||||
abv: true,
|
description: true,
|
||||||
ibu: true,
|
abv: true,
|
||||||
createdAt: true,
|
ibu: true,
|
||||||
beerImages: { select: { id: true, path: true, caption: true, alt: true } },
|
createdAt: true,
|
||||||
brewery: { select: { id: true, name: true } },
|
beerImages: { select: { id: true, path: true, caption: true, alt: true } },
|
||||||
type: { select: { id: true, name: true } },
|
brewery: { select: { id: true, name: true } },
|
||||||
postedBy: { select: { id: true, username: true } },
|
type: { select: { id: true, name: true } },
|
||||||
},
|
postedBy: { select: { id: true, username: true } },
|
||||||
});
|
},
|
||||||
|
});
|
||||||
return newBeerPost;
|
return newBeerPost;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,30 @@
|
|||||||
import DBClient from '@/prisma/DBClient';
|
import DBClient from '@/prisma/DBClient';
|
||||||
import { BeerPostQueryResult } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
const prisma = DBClient.instance;
|
const prisma = DBClient.instance;
|
||||||
|
|
||||||
const getAllBeerPosts = async (pageNum: number, pageSize: number) => {
|
const getAllBeerPosts = async (pageNum: number, pageSize: number) => {
|
||||||
const skip = (pageNum - 1) * pageSize;
|
const skip = (pageNum - 1) * pageSize;
|
||||||
|
|
||||||
const beerPosts: BeerPostQueryResult[] = await prisma.beerPost.findMany({
|
const beerPosts: z.infer<typeof beerPostQueryResult>[] = await prisma.beerPost.findMany(
|
||||||
select: {
|
{
|
||||||
id: true,
|
select: {
|
||||||
name: true,
|
id: true,
|
||||||
ibu: true,
|
name: true,
|
||||||
abv: true,
|
ibu: true,
|
||||||
description: true,
|
abv: true,
|
||||||
createdAt: true,
|
description: true,
|
||||||
type: { select: { name: true, id: true } },
|
createdAt: true,
|
||||||
brewery: { select: { name: true, id: true } },
|
type: { select: { name: true, id: true } },
|
||||||
postedBy: { select: { id: true, username: true } },
|
brewery: { select: { name: true, id: true } },
|
||||||
beerImages: { select: { path: true, caption: true, id: true, alt: true } },
|
postedBy: { select: { id: true, username: true } },
|
||||||
|
beerImages: { select: { path: true, caption: true, id: true, alt: true } },
|
||||||
|
},
|
||||||
|
take: pageSize,
|
||||||
|
skip,
|
||||||
},
|
},
|
||||||
take: pageSize,
|
);
|
||||||
skip,
|
|
||||||
});
|
|
||||||
|
|
||||||
return beerPosts;
|
return beerPosts;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,24 +1,26 @@
|
|||||||
import DBClient from '@/prisma/DBClient';
|
import DBClient from '@/prisma/DBClient';
|
||||||
import { BeerPostQueryResult } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
const prisma = DBClient.instance;
|
const prisma = DBClient.instance;
|
||||||
|
|
||||||
const getBeerPostById = async (id: string) => {
|
const getBeerPostById = async (id: string) => {
|
||||||
const beerPost: BeerPostQueryResult | null = await prisma.beerPost.findFirst({
|
const beerPost: z.infer<typeof beerPostQueryResult> | null =
|
||||||
select: {
|
await prisma.beerPost.findFirst({
|
||||||
id: true,
|
select: {
|
||||||
name: true,
|
id: true,
|
||||||
ibu: true,
|
name: true,
|
||||||
abv: true,
|
ibu: true,
|
||||||
createdAt: true,
|
abv: true,
|
||||||
description: true,
|
createdAt: true,
|
||||||
postedBy: { select: { username: true, id: true } },
|
description: true,
|
||||||
brewery: { select: { name: true, id: true } },
|
postedBy: { select: { username: true, id: true } },
|
||||||
type: { select: { name: true, id: true } },
|
brewery: { select: { name: true, id: true } },
|
||||||
beerImages: { select: { alt: true, path: true, caption: true, id: true } },
|
type: { select: { name: true, id: true } },
|
||||||
},
|
beerImages: { select: { alt: true, path: true, caption: true, id: true } },
|
||||||
where: { id },
|
},
|
||||||
});
|
where: { id },
|
||||||
|
});
|
||||||
|
|
||||||
return beerPost;
|
return beerPost;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import DBClient from '@/prisma/DBClient';
|
import DBClient from '@/prisma/DBClient';
|
||||||
import { BeerPostQueryResult } from '@/services/BeerPost/schema/BeerPostQueryResult';
|
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
const getBeerRecommendations = async (
|
const getBeerRecommendations = async (
|
||||||
beerPost: Pick<BeerPostQueryResult, 'type' | 'brewery' | 'id'>,
|
beerPost: Pick<z.infer<typeof beerPostQueryResult>, 'type' | 'brewery' | 'id'>,
|
||||||
) => {
|
) => {
|
||||||
const beerRecommendations = await DBClient.instance.beerPost.findMany({
|
const beerRecommendations = await DBClient.instance.beerPost.findMany({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@@ -1,36 +1,18 @@
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
export const beerPostQueryResultSchema = z.object({
|
const beerPostQueryResult = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
brewery: z.object({
|
brewery: z.object({ id: z.string(), name: z.string() }),
|
||||||
id: z.string(),
|
|
||||||
name: z.string(),
|
|
||||||
}),
|
|
||||||
description: z.string(),
|
description: z.string(),
|
||||||
beerImages: z.array(
|
beerImages: z.array(
|
||||||
z.object({
|
z.object({ path: z.string(), caption: z.string(), id: z.string(), alt: z.string() }),
|
||||||
path: z.string(),
|
|
||||||
caption: z.string(),
|
|
||||||
id: z.string(),
|
|
||||||
alt: z.string(),
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
ibu: z.number(),
|
ibu: z.number(),
|
||||||
abv: z.number(),
|
abv: z.number(),
|
||||||
type: z.object({
|
type: z.object({ id: z.string(), name: z.string() }),
|
||||||
id: z.string(),
|
postedBy: z.object({ id: z.string(), username: z.string() }),
|
||||||
name: z.string(),
|
|
||||||
}),
|
|
||||||
postedBy: z.object({
|
|
||||||
id: z.string(),
|
|
||||||
username: z.string(),
|
|
||||||
}),
|
|
||||||
createdAt: z.coerce.date(),
|
createdAt: z.coerce.date(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const beerPostQueryResultArraySchema = z.array(beerPostQueryResultSchema);
|
export default beerPostQueryResult;
|
||||||
|
|
||||||
export type BeerPostQueryResult = z.infer<typeof beerPostQueryResultSchema>;
|
|
||||||
|
|
||||||
export type BeerPostQueryResultArray = z.infer<typeof beerPostQueryResultArraySchema>;
|
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
import DBClient from '@/prisma/DBClient';
|
import DBClient from '@/prisma/DBClient';
|
||||||
import BreweryPostQueryResult from './types/BreweryPostQueryResult';
|
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
const prisma = DBClient.instance;
|
const prisma = DBClient.instance;
|
||||||
|
|
||||||
const getAllBreweryPosts = async () => {
|
const getAllBreweryPosts = async () => {
|
||||||
const breweryPosts: BreweryPostQueryResult[] = await prisma.breweryPost.findMany({
|
const breweryPosts: z.infer<typeof BreweryPostQueryResult>[] =
|
||||||
select: {
|
await prisma.breweryPost.findMany({
|
||||||
id: true,
|
select: {
|
||||||
location: true,
|
id: true,
|
||||||
name: true,
|
location: true,
|
||||||
postedBy: { select: { firstName: true, lastName: true, id: true } },
|
name: true,
|
||||||
},
|
postedBy: { select: { username: true, id: true } },
|
||||||
});
|
breweryImages: { select: { path: true, caption: true, id: true, alt: true } },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return breweryPosts;
|
return breweryPosts;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,26 +1,21 @@
|
|||||||
import DBClient from '@/prisma/DBClient';
|
import DBClient from '@/prisma/DBClient';
|
||||||
import BreweryPostQueryResult from './types/BreweryPostQueryResult';
|
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
const prisma = DBClient.instance;
|
const prisma = DBClient.instance;
|
||||||
|
|
||||||
const getBreweryPostById = async (id: string) => {
|
const getBreweryPostById = async (id: string) => {
|
||||||
const breweryPost: BreweryPostQueryResult | null = await prisma.breweryPost.findFirst({
|
const breweryPost: z.infer<typeof BreweryPostQueryResult> | null =
|
||||||
select: {
|
await prisma.breweryPost.findFirst({
|
||||||
id: true,
|
select: {
|
||||||
location: true,
|
id: true,
|
||||||
name: true,
|
location: true,
|
||||||
postedBy: {
|
name: true,
|
||||||
select: {
|
breweryImages: { select: { path: true, caption: true, id: true, alt: true } },
|
||||||
firstName: true,
|
postedBy: { select: { username: true, id: true } },
|
||||||
lastName: true,
|
|
||||||
id: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
where: { id },
|
||||||
where: {
|
});
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return breweryPost;
|
return breweryPost;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
export default interface BreweryPostQueryResult {
|
import { z } from 'zod';
|
||||||
id: string;
|
|
||||||
location: string;
|
const BreweryPostQueryResult = z.object({
|
||||||
name: string;
|
id: z.string(),
|
||||||
postedBy: {
|
location: z.string(),
|
||||||
id: string;
|
name: z.string(),
|
||||||
firstName: string;
|
postedBy: z.object({ id: z.string(), username: z.string() }),
|
||||||
lastName: string;
|
breweryImages: z.array(
|
||||||
};
|
z.object({ path: z.string(), caption: z.string(), id: z.string(), alt: z.string() }),
|
||||||
}
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default BreweryPostQueryResult;
|
||||||
|
|||||||
Reference in New Issue
Block a user