mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 20:13:49 +00:00
Formatting changes
This commit is contained in:
@@ -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 });
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -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,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 (
|
||||||
!(
|
!(
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user