Formatting changes

This commit is contained in:
Aaron William Po
2023-02-20 09:09:45 -05:00
parent d50ce7497b
commit 4cd2ab476f
14 changed files with 61 additions and 109 deletions

View File

@@ -26,7 +26,6 @@ const BeerCommentForm: FunctionComponent<BeerCommentFormProps> = ({ beerPost })
z.infer<typeof BeerCommentValidationSchema> z.infer<typeof BeerCommentValidationSchema>
>({ >({
defaultValues: { defaultValues: {
beerPostId: beerPost.id,
rating: 0, rating: 0,
}, },
resolver: zodResolver(BeerCommentValidationSchema), resolver: zodResolver(BeerCommentValidationSchema),
@@ -35,8 +34,8 @@ const BeerCommentForm: FunctionComponent<BeerCommentFormProps> = ({ beerPost })
const [rating, setRating] = useState(0); const [rating, setRating] = useState(0);
useEffect(() => { useEffect(() => {
setRating(0); setRating(0);
reset({ beerPostId: beerPost.id, rating: 0, content: '' }); reset({ rating: 0, content: '' });
}, [beerPost.id, reset]); }, [reset]);
const router = useRouter(); const router = useRouter();
const onSubmit: SubmitHandler<z.infer<typeof BeerCommentValidationSchema>> = async ( const onSubmit: SubmitHandler<z.infer<typeof BeerCommentValidationSchema>> = async (
@@ -44,7 +43,11 @@ const BeerCommentForm: FunctionComponent<BeerCommentFormProps> = ({ beerPost })
) => { ) => {
setValue('rating', 0); setValue('rating', 0);
setRating(0); setRating(0);
await sendCreateBeerCommentRequest(data); await sendCreateBeerCommentRequest({
content: data.content,
rating: data.rating,
beerPostId: beerPost.id,
});
reset(); reset();
router.replace(router.asPath, undefined, { scroll: false }); router.replace(router.asPath, undefined, { scroll: false });
}; };

View File

@@ -68,7 +68,9 @@ const BeerInfoHeader: FC<{ beerPost: BeerPostQueryResult; initialLikeCount: numb
<span className="text-lg font-medium">{beerPost.ibu} IBU</span> <span className="text-lg font-medium">{beerPost.ibu} IBU</span>
</div> </div>
<div> <div>
<span>Liked by {likeCount} users</span> <span>
Liked by {likeCount} user{likeCount !== 1 && 's'}
</span>
</div> </div>
</div> </div>
<div className="card-actions items-end"> <div className="card-actions items-end">

View File

@@ -1,8 +1,8 @@
import UserContext from '@/contexts/userContext'; import UserContext from '@/contexts/userContext';
import sendCheckIfUserLikesBeerPostRequest from '@/requests/sendCheckIfUserLikesBeerPostRequest';
import sendLikeRequest from '@/requests/sendLikeRequest'; import sendLikeRequest from '@/requests/sendLikeRequest';
import { Dispatch, FC, SetStateAction, useContext, useEffect, useState } from 'react'; import { Dispatch, FC, SetStateAction, useContext, useEffect, useState } from 'react';
import { FaThumbsUp, FaRegThumbsUp } from 'react-icons/fa'; import { FaThumbsUp, FaRegThumbsUp } from 'react-icons/fa';
import sendCheckIfUserLikesBeerPostRequest from '@/requests/sendCheckIfUserLikesBeerPostRequest';
const BeerPostLikeButton: FC<{ const BeerPostLikeButton: FC<{
beerPostId: string; beerPostId: string;

View File

@@ -4,9 +4,10 @@ import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQuer
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 } 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 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';
import FormInfo from './ui/forms/FormInfo'; import FormInfo from './ui/forms/FormInfo';
@@ -46,6 +47,8 @@ const BeerForm: FunctionComponent<BeerFormProps> = ({
}, },
}); });
const [error, setError] = useState('');
const onSubmit: SubmitHandler<BeerPostT> = async (data) => { const onSubmit: SubmitHandler<BeerPostT> = async (data) => {
switch (formType) { switch (formType) {
case 'create': { case 'create': {
@@ -54,8 +57,9 @@ const BeerForm: FunctionComponent<BeerFormProps> = ({
router.push(`/beers/${response.id}`); router.push(`/beers/${response.id}`);
break; break;
} catch (e) { } catch (e) {
// eslint-disable-next-line no-console if (e instanceof Error) {
console.error(e); setError(e.message);
}
break; break;
} }
} }
@@ -68,6 +72,9 @@ const BeerForm: FunctionComponent<BeerFormProps> = ({
return ( return (
<form className="form-control" onSubmit={handleSubmit(onSubmit)}> <form className="form-control" onSubmit={handleSubmit(onSubmit)}>
<div className="my-5">
{error && <ErrorAlert error={error} setError={setError} />}
</div>
<FormInfo> <FormInfo>
<FormLabel htmlFor="name">Name</FormLabel> <FormLabel htmlFor="name">Name</FormLabel>
<FormError>{errors.name?.message}</FormError> <FormError>{errors.name?.message}</FormError>

View File

@@ -12,6 +12,7 @@ const withPageAuthRequired =
} }
return await fn(context); return await fn(context);
} catch (error) { } catch (error) {
console.log(error);
return { return {
redirect: { redirect: {
destination: '/login', destination: '/login',

View File

@@ -13,13 +13,16 @@ import { NextApiResponse } from 'next';
interface CreateCommentRequest extends UserExtendedNextApiRequest { interface CreateCommentRequest extends UserExtendedNextApiRequest {
body: z.infer<typeof BeerCommentValidationSchema>; body: z.infer<typeof BeerCommentValidationSchema>;
query: { id: string };
} }
const createComment = async ( const createComment = async (
req: CreateCommentRequest, req: CreateCommentRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>, res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => { ) => {
const { content, rating, beerPostId } = req.body; const { content, rating } = req.body;
const beerPostId = req.query.id;
const newBeerComment: BeerCommentQueryResultT = await createNewBeerComment({ const newBeerComment: BeerCommentQueryResultT = await createNewBeerComment({
content, content,
@@ -42,7 +45,10 @@ const router = createRouter<
>(); >();
router.post( router.post(
validateRequest({ bodySchema: BeerCommentValidationSchema }), validateRequest({
bodySchema: BeerCommentValidationSchema,
querySchema: z.object({ id: z.string().uuid() }),
}),
getCurrentUser, getCurrentUser,
createComment, createComment,
); );

View File

@@ -1,5 +1,6 @@
import BeerForm from '@/components/BeerForm'; import BeerForm from '@/components/BeerForm';
import Layout from '@/components/ui/Layout'; import Layout from '@/components/ui/Layout';
import withPageAuthRequired from '@/config/auth/withPageAuthRequired';
import DBClient from '@/prisma/DBClient'; import DBClient from '@/prisma/DBClient';
import getAllBreweryPosts from '@/services/BreweryPost/getAllBreweryPosts'; import getAllBreweryPosts from '@/services/BreweryPost/getAllBreweryPosts';
@@ -30,7 +31,7 @@ const Create: NextPage<CreateBeerPageProps> = ({ breweries, types }) => {
); );
}; };
export const getServerSideProps = async () => { export const getServerSideProps = withPageAuthRequired(async () => {
const breweryPosts = await getAllBreweryPosts(); const breweryPosts = await getAllBreweryPosts();
const beerTypes = await DBClient.instance.beerType.findMany(); const beerTypes = await DBClient.instance.beerType.findMany();
@@ -40,6 +41,6 @@ export const getServerSideProps = async () => {
types: JSON.parse(JSON.stringify(beerTypes)), types: JSON.parse(JSON.stringify(beerTypes)),
}, },
}; };
}; });
export default Create; export default Create;

View File

@@ -3,11 +3,15 @@ import BeerCommentValidationSchema from '@/services/BeerComment/schema/CreateBee
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { z } from 'zod'; import { z } from 'zod';
const BeerCommentValidationSchemaWithId = BeerCommentValidationSchema.extend({
beerPostId: z.string().uuid(),
});
const sendCreateBeerCommentRequest = async ({ const sendCreateBeerCommentRequest = async ({
beerPostId, beerPostId,
content, content,
rating, rating,
}: z.infer<typeof BeerCommentValidationSchema>) => { }: 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: {
@@ -29,7 +33,6 @@ const sendCreateBeerCommentRequest = async ({
const parsedResponse = APIResponseValidationSchema.safeParse(data); const parsedResponse = APIResponseValidationSchema.safeParse(data);
if (!parsedResponse.success) { if (!parsedResponse.success) {
console.log(parsedResponse.error);
throw new Error('Invalid API response'); throw new Error('Invalid API response');
} }
@@ -37,7 +40,6 @@ const sendCreateBeerCommentRequest = async ({
const parsedPayload = BeerCommentQueryResult.safeParse(parsedResponse.data.payload); const parsedPayload = BeerCommentQueryResult.safeParse(parsedResponse.data.payload);
if (!parsedPayload.success) { if (!parsedPayload.success) {
console.log(parsedPayload.error);
throw new Error('Invalid API response payload'); throw new Error('Invalid API response payload');
} }

View File

@@ -7,21 +7,21 @@ const sendCreateBeerPostRequest = async (
) => { ) => {
const response = await fetch('/api/beers/create', { const response = await fetch('/api/beers/create', {
method: 'POST', method: 'POST',
headers: { headers: { 'Content-Type': 'application/json' },
'Content-Type': 'application/json',
},
body: JSON.stringify(data), body: JSON.stringify(data),
}); });
const json = await response.json(); const json = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json); const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) { if (!parsed.success) {
throw new Error('Invalid API response'); throw new Error('Invalid API response');
} }
const { payload } = parsed.data; const { payload, success, message } = parsed.data;
if (!success) {
throw new Error(message);
}
if ( if (
!( !(

View File

@@ -2,8 +2,9 @@ import DBClient from '@/prisma/DBClient';
import { z } from 'zod'; import { z } from 'zod';
import BeerCommentValidationSchema from './schema/CreateBeerCommentValidationSchema'; import BeerCommentValidationSchema from './schema/CreateBeerCommentValidationSchema';
const CreateBeerCommentWithUserSchema = BeerCommentValidationSchema.extend({ const CreateNewBeerCommentServiceSchema = BeerCommentValidationSchema.extend({
userId: z.string().uuid(), userId: z.string().uuid(),
beerPostId: z.string().uuid(),
}); });
const createNewBeerComment = async ({ const createNewBeerComment = async ({
@@ -11,7 +12,7 @@ const createNewBeerComment = async ({
rating, rating,
beerPostId, beerPostId,
userId, userId,
}: z.infer<typeof CreateBeerCommentWithUserSchema>) => { }: z.infer<typeof CreateNewBeerCommentServiceSchema>) => {
return DBClient.instance.beerComment.create({ return DBClient.instance.beerComment.create({
data: { data: {
content, content,

View File

@@ -9,27 +9,17 @@ const getAllBeerComments = async (
const skip = (pageNum - 1) * pageSize; const skip = (pageNum - 1) * pageSize;
const beerComments: BeerCommentQueryResultArrayT = const beerComments: BeerCommentQueryResultArrayT =
await DBClient.instance.beerComment.findMany({ await DBClient.instance.beerComment.findMany({
where: { skip,
beerPostId: id, take: pageSize,
}, where: { beerPostId: id },
select: { select: {
id: true, id: true,
content: true, content: true,
rating: true, rating: true,
createdAt: true, createdAt: true,
postedBy: { postedBy: { select: { id: true, username: true, createdAt: true } },
select: {
id: true,
username: true,
createdAt: true,
}, },
}, orderBy: { createdAt: 'desc' },
},
orderBy: {
createdAt: 'desc',
},
skip,
take: pageSize,
}); });
return beerComments; return beerComments;
}; };

View File

@@ -10,7 +10,6 @@ const BeerCommentValidationSchema = z.object({
.int() .int()
.min(1, { message: 'Rating must be greater than 1.' }) .min(1, { message: 'Rating must be greater than 1.' })
.max(5, { message: 'Rating must be less than 5.' }), .max(5, { message: 'Rating must be less than 5.' }),
beerPostId: z.string().uuid({ message: 'Beer post ID must be a valid UUID.' }),
}); });
export default BeerCommentValidationSchema; export default BeerCommentValidationSchema;

View File

@@ -10,36 +10,14 @@ const getAllBeerPosts = async (pageNum: number, pageSize: number) => {
select: { select: {
id: true, id: true,
name: true, name: true,
type: {
select: {
name: true,
id: true,
},
},
ibu: true, ibu: true,
abv: true, abv: true,
brewery: {
select: {
name: true,
id: true,
},
},
description: true, description: true,
createdAt: true, createdAt: true,
postedBy: { type: { select: { name: true, id: true } },
select: { brewery: { select: { name: true, id: true } },
id: true, postedBy: { select: { id: true, username: true } },
username: true, beerImages: { select: { path: true, caption: true, id: true, alt: true } },
},
},
beerImages: {
select: {
path: true,
caption: true,
id: true,
alt: true,
},
},
}, },
take: pageSize, take: pageSize,
skip, skip,

View File

@@ -6,56 +6,18 @@ const prisma = DBClient.instance;
const getBeerPostById = async (id: string) => { const getBeerPostById = async (id: string) => {
const beerPost: BeerPostQueryResult | null = await prisma.beerPost.findFirst({ const beerPost: BeerPostQueryResult | null = await prisma.beerPost.findFirst({
select: { select: {
beerComments: {
select: {
id: true,
content: true,
createdAt: true,
postedBy: {
select: {
username: true,
id: true,
},
},
rating: true,
},
},
id: true, id: true,
name: true, name: true,
brewery: {
select: {
name: true,
id: true,
},
},
ibu: true, ibu: true,
abv: true, abv: true,
type: {
select: {
name: true,
id: true,
},
},
beerImages: {
select: {
alt: true,
path: true,
caption: true,
id: true,
},
},
createdAt: true, createdAt: true,
description: true, description: true,
postedBy: { postedBy: { select: { username: true, id: true } },
select: { brewery: { select: { name: true, id: true } },
username: true, type: { select: { name: true, id: true } },
id: true, beerImages: { select: { alt: true, path: true, caption: true, id: true } },
},
},
},
where: {
id,
}, },
where: { id },
}); });
return beerPost; return beerPost;