Refactor codebase, format

This commit is contained in:
Aaron William Po
2023-02-09 04:03:11 -05:00
parent e654216c1a
commit dbd342fd3e
26 changed files with 517 additions and 809 deletions

View File

@@ -2,6 +2,6 @@
"semi": true, "semi": true,
"trailingComma": "all", "trailingComma": "all",
"singleQuote": true, "singleQuote": true,
"printWidth": 80, "printWidth": 90,
"plugins": ["prettier-plugin-jsdoc"] "plugins": ["prettier-plugin-jsdoc"]
} }

View File

@@ -9,9 +9,7 @@ import UserContext from '@/contexts/userContext';
import sendCheckIfUserLikesBeerPostRequest from '@/requests/sendCheckIfUserLikesBeerPostRequest'; import sendCheckIfUserLikesBeerPostRequest from '@/requests/sendCheckIfUserLikesBeerPostRequest';
import sendLikeRequest from '../../requests/sendLikeRequest'; import sendLikeRequest from '../../requests/sendLikeRequest';
const BeerInfoHeader: FC<{ beerPost: BeerPostQueryResult }> = ({ const BeerInfoHeader: FC<{ beerPost: BeerPostQueryResult }> = ({ beerPost }) => {
beerPost,
}) => {
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);
@@ -36,9 +34,7 @@ const BeerInfoHeader: FC<{ beerPost: BeerPostQueryResult }> = ({
}, [user, beerPost.id]); }, [user, beerPost.id]);
useEffect(() => { useEffect(() => {
setTimeDistance( setTimeDistance(formatDistanceStrict(new Date(beerPost.createdAt), new Date()));
formatDistanceStrict(new Date(beerPost.createdAt), new Date()),
);
}, [beerPost.createdAt]); }, [beerPost.createdAt]);
const handleLike = async () => { const handleLike = async () => {
@@ -66,10 +62,7 @@ const BeerInfoHeader: FC<{ beerPost: BeerPostQueryResult }> = ({
<h3 className="italic"> <h3 className="italic">
posted by{' '} posted by{' '}
<Link <Link href={`/users/${beerPost.postedBy.id}`} className="link-hover link">
href={`/users/${beerPost.postedBy.id}`}
className="link-hover link"
>
{beerPost.postedBy.username}{' '} {beerPost.postedBy.username}{' '}
</Link> </Link>
<span <span
@@ -92,9 +85,7 @@ const BeerInfoHeader: FC<{ beerPost: BeerPostQueryResult }> = ({
</Link> </Link>
</div> </div>
<div> <div>
<span className="mr-4 text-lg font-medium"> <span className="mr-4 text-lg font-medium">{beerPost.abv}% ABV</span>
{beerPost.abv}% ABV
</span>
<span className="text-lg font-medium">{beerPost.ibu} IBU</span> <span className="text-lg font-medium">{beerPost.ibu} IBU</span>
</div> </div>
</div> </div>

View File

@@ -14,17 +14,10 @@ const BeerRecommendations: FunctionComponent<BeerRecommendationsProps> = ({
{beerRecommendations.map((beerPost) => ( {beerRecommendations.map((beerPost) => (
<div key={beerPost.id} className="w-full"> <div key={beerPost.id} className="w-full">
<div> <div>
<Link <Link className="link-hover" href={`/beers/${beerPost.id}`} scroll={false}>
className="link-hover"
href={`/beers/${beerPost.id}`}
scroll={false}
>
<h2 className="text-2xl font-bold">{beerPost.name}</h2> <h2 className="text-2xl font-bold">{beerPost.name}</h2>
</Link> </Link>
<Link <Link href={`/breweries/${beerPost.brewery.id}`} className="link-hover">
href={`/breweries/${beerPost.brewery.id}`}
className="link-hover"
>
<p className="text-lg font-semibold">{beerPost.brewery.name}</p> <p className="text-lg font-semibold">{beerPost.brewery.name}</p>
</Link> </Link>
</div> </div>

View File

@@ -1,5 +1,5 @@
import sendLoginUserRequest from '@/requests/sendLoginUserRequest'; import sendLoginUserRequest from '@/requests/sendLoginUserRequest';
import LoginValidationSchema from '@/services/user/schema/LoginValidationSchema'; import LoginValidationSchema from '@/services/User/schema/LoginValidationSchema';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useForm, SubmitHandler } from 'react-hook-form'; import { useForm, SubmitHandler } from 'react-hook-form';
@@ -66,7 +66,7 @@ const LoginForm = () => {
</div> </div>
<div className="w-full"> <div className="w-full">
<button type="submit" className="btn-primary btn w-full"> <button type="submit" className="btn btn-primary w-full">
Login Login
</button> </button>
</div> </div>

View File

@@ -26,7 +26,7 @@ const Navbar = () => {
return ( return (
<nav className="navbar bg-primary"> <nav className="navbar bg-primary">
<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>
@@ -51,7 +51,7 @@ const Navbar = () => {
</div> </div>
<div className="flex-none lg:hidden"> <div className="flex-none lg:hidden">
<div className="dropdown-end dropdown"> <div className="dropdown-end dropdown">
<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"

View File

@@ -7,7 +7,7 @@ interface FormButtonProps {
const Button: FunctionComponent<FormButtonProps> = ({ children, type }) => ( const Button: FunctionComponent<FormButtonProps> = ({ children, type }) => (
// eslint-disable-next-line react/button-has-type // eslint-disable-next-line react/button-has-type
<button type={type} className="btn-primary btn mt-4 w-full rounded-xl"> <button type={type} className="btn btn-primary mt-4 w-full rounded-xl">
{children} {children}
</button> </button>
); );

View File

@@ -1,4 +1,4 @@
import findUserByUsername from '@/services/user/findUserByUsername'; import findUserByUsername from '@/services/User/findUserByUsername';
import Local from 'passport-local'; import Local from 'passport-local';
import ServerError from '../util/ServerError'; import ServerError from '../util/ServerError';
import { validatePassword } from './passwordFns'; import { validatePassword } from './passwordFns';

View File

@@ -1,6 +1,6 @@
import { NextApiResponse } from 'next'; import { NextApiResponse } from 'next';
import { NextHandler } from 'next-connect'; import { NextHandler } from 'next-connect';
import findUserById from '@/services/user/findUserById'; import findUserById from '@/services/User/findUserById';
import ServerError from '@/config/util/ServerError'; import ServerError from '@/config/util/ServerError';
import { getLoginSession } from '../session'; import { getLoginSession } from '../session';
import { UserExtendedNextApiRequest } from '../types'; import { UserExtendedNextApiRequest } from '../types';

View File

@@ -1,4 +1,4 @@
import GetUserSchema from '@/services/user/schema/GetUserSchema'; import GetUserSchema from '@/services/User/schema/GetUserSchema';
import { IncomingMessage } from 'http'; import { IncomingMessage } from 'http';
import { NextApiRequest } from 'next'; import { NextApiRequest } from 'next';
import { z } from 'zod'; import { z } from 'zod';

View File

@@ -37,7 +37,7 @@ const validateRequest =
if (querySchema) { if (querySchema) {
const parsed = querySchema.safeParse(req.query); const parsed = querySchema.safeParse(req.query);
if (!parsed.success) { if (!parsed.success) {
throw new ServerError(parsed.error.message, 400); throw new ServerError('Invalid request query.', 400);
} }
req.query = parsed.data; req.query = parsed.data;
} }

View File

@@ -1,4 +1,4 @@
import GetUserSchema from '@/services/user/schema/GetUserSchema'; import GetUserSchema from '@/services/User/schema/GetUserSchema';
import { createContext } from 'react'; import { createContext } from 'react';
import { z } from 'zod'; import { z } from 'zod';

View File

@@ -1,4 +1,4 @@
import GetUserSchema from '@/services/user/schema/GetUserSchema'; import GetUserSchema from '@/services/User/schema/GetUserSchema';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import useSWR from 'swr'; import useSWR from 'swr';

1104
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -37,7 +37,7 @@
"devDependencies": { "devDependencies": {
"@faker-js/faker": "^7.6.0", "@faker-js/faker": "^7.6.0",
"@types/cookie": "^0.5.1", "@types/cookie": "^0.5.1",
"@types/node": "18.11.19", "@types/node": "^18.13.0",
"@types/passport-local": "^1.0.35", "@types/passport-local": "^1.0.35",
"@types/react": "18.0.27", "@types/react": "18.0.27",
"@types/react-dom": "18.0.10", "@types/react-dom": "18.0.10",

View File

@@ -1,4 +1,3 @@
import DBClient from '@/prisma/DBClient';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import getBeerPostById from '@/services/BeerPost/getBeerPostById'; import getBeerPostById from '@/services/BeerPost/getBeerPostById';
import { UserExtendedNextApiRequest } from '@/config/auth/types'; import { UserExtendedNextApiRequest } from '@/config/auth/types';
@@ -9,8 +8,11 @@ import nextConnect from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
import { NextApiResponse } from 'next'; import { NextApiResponse } from 'next';
import ServerError from '@/config/util/ServerError'; import ServerError from '@/config/util/ServerError';
import createBeerPostLike from '@/services/BeerPostLike/createBeerPostLike';
import removeBeerPostLikeById from '@/services/BeerPostLike/removeBeerPostLikeById';
import findBeerPostLikeById from '@/services/BeerPostLike/findBeerPostLikeById';
const likeBeerPost = async ( const sendLikeRequest = async (
req: UserExtendedNextApiRequest, req: UserExtendedNextApiRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>, res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => { ) => {
@@ -22,41 +24,23 @@ const likeBeerPost = async (
throw new ServerError('Could not find a beer post with that id', 404); throw new ServerError('Could not find a beer post with that id', 404);
} }
const alreadyLiked = await DBClient.instance.beerPostLikes.findFirst({ const alreadyLiked = await findBeerPostLikeById(id);
where: {
beerPostId: id, const jsonResponse = {
userId: user.id, success: true as const,
}, message: '',
}); statusCode: 200 as const,
};
if (alreadyLiked) { if (alreadyLiked) {
await DBClient.instance.beerPostLikes.delete({ await removeBeerPostLikeById(alreadyLiked.id);
where: { jsonResponse.message = 'Successfully unliked beer post';
id: alreadyLiked.id, } else {
}, await createBeerPostLike({ id, user });
}); jsonResponse.message = 'Successfully liked beer post';
res.status(200).json({
success: true,
message: 'Successfully unliked beer post',
statusCode: 200,
});
return;
} }
await DBClient.instance.beerPostLikes.create({ res.status(200).json(jsonResponse);
data: {
beerPost: { connect: { id } },
user: { connect: { id: user.id } },
},
});
res.status(200).json({
success: true,
message: 'Successfully liked beer post',
statusCode: 200,
});
}; };
const handler = nextConnect(NextConnectConfig).post( const handler = nextConnect(NextConnectConfig).post(
@@ -66,7 +50,7 @@ const handler = nextConnect(NextConnectConfig).post(
id: z.string().uuid(), id: z.string().uuid(),
}), }),
}), }),
likeBeerPost, sendLikeRequest,
); );
export default handler; export default handler;

View File

@@ -15,7 +15,7 @@ const checkIfLiked = async (
const user = req.user!; const user = req.user!;
const id = req.query.id as string; const id = req.query.id as string;
const alreadyLiked = await DBClient.instance.beerPostLikes.findFirst({ const alreadyLiked = await DBClient.instance.beerPostLike.findFirst({
where: { where: {
beerPostId: id, beerPostId: id,
userId: user.id, userId: user.id,
@@ -26,19 +26,13 @@ const checkIfLiked = async (
success: true, success: true,
message: alreadyLiked ? 'Beer post is liked.' : 'Beer post is not liked.', message: alreadyLiked ? 'Beer post is liked.' : 'Beer post is not liked.',
statusCode: 200, statusCode: 200,
payload: { payload: { isLiked: !!alreadyLiked },
isLiked: !!alreadyLiked,
},
}); });
}; };
const handler = nextConnect(NextConnectConfig).get( const handler = nextConnect(NextConnectConfig).get(
getCurrentUser, getCurrentUser,
validateRequest({ validateRequest({ querySchema: z.object({ id: z.string().uuid() }) }),
querySchema: z.object({
id: z.string().uuid(),
}),
}),
checkIfLiked, checkIfLiked,
); );

View File

@@ -7,7 +7,7 @@ import { setLoginSession } from '@/config/auth/session';
import { NextApiResponse } from 'next'; import { NextApiResponse } from 'next';
import { z } from 'zod'; import { z } from 'zod';
import ServerError from '@/config/util/ServerError'; import ServerError from '@/config/util/ServerError';
import LoginValidationSchema from '@/services/user/schema/LoginValidationSchema'; import LoginValidationSchema from '@/services/User/schema/LoginValidationSchema';
import { UserExtendedNextApiRequest } from '../../../config/auth/types'; import { UserExtendedNextApiRequest } from '../../../config/auth/types';
export default nextConnect< export default nextConnect<

View File

@@ -2,11 +2,11 @@ import { NextApiRequest, NextApiResponse } from 'next';
import { z } from 'zod'; import { z } from 'zod';
import ServerError from '@/config/util/ServerError'; import ServerError from '@/config/util/ServerError';
import nc from 'next-connect'; import nc from 'next-connect';
import createNewUser from '@/services/user/createNewUser'; import createNewUser from '@/services/User/createNewUser';
import CreateUserValidationSchema from '@/services/user/schema/CreateUserValidationSchema'; import CreateUserValidationSchema from '@/services/User/schema/CreateUserValidationSchema';
import NextConnectConfig from '@/config/nextConnect/NextConnectConfig'; import NextConnectConfig from '@/config/nextConnect/NextConnectConfig';
import findUserByUsername from '@/services/user/findUserByUsername'; import findUserByUsername from '@/services/User/findUserByUsername';
import findUserByEmail from '@/services/user/findUserByEmail'; import findUserByEmail from '@/services/User/findUserByEmail';
import validateRequest from '@/config/zod/middleware/validateRequest'; import validateRequest from '@/config/zod/middleware/validateRequest';
interface RegisterUserRequest extends NextApiRequest { interface RegisterUserRequest extends NextApiRequest {

View File

@@ -1,16 +0,0 @@
-- CreateTable
CREATE TABLE "BeerPostLikes" (
"id" TEXT NOT NULL,
"beerPostId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
CONSTRAINT "BeerPostLikes_pkey" PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "BeerPostLikes" ADD CONSTRAINT "BeerPostLikes_beerPostId_fkey" FOREIGN KEY ("beerPostId") REFERENCES "BeerPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BeerPostLikes" ADD CONSTRAINT "BeerPostLikes_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -0,0 +1,16 @@
-- CreateTable
CREATE TABLE "BeerPostLike" (
"id" TEXT NOT NULL,
"beerPostId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
CONSTRAINT "BeerPostLike_pkey" PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "BeerPostLike" ADD CONSTRAINT "BeerPostLike_beerPostId_fkey" FOREIGN KEY ("beerPostId") REFERENCES "BeerPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BeerPostLike" ADD CONSTRAINT "BeerPostLike_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -25,7 +25,7 @@ model User {
breweryPosts BreweryPost[] breweryPosts BreweryPost[]
beerComments BeerComment[] beerComments BeerComment[]
breweryComments BreweryComment[] breweryComments BreweryComment[]
BeerPostLikes BeerPostLikes[] BeerPostLikes BeerPostLike[]
} }
model BeerPost { model BeerPost {
@@ -44,10 +44,10 @@ model BeerPost {
updatedAt DateTime? @updatedAt @db.Timestamptz(3) updatedAt DateTime? @updatedAt @db.Timestamptz(3)
beerComments BeerComment[] beerComments BeerComment[]
beerImages BeerImage[] beerImages BeerImage[]
BeerPostLikes BeerPostLikes[] BeerPostLikes BeerPostLike[]
} }
model BeerPostLikes { model BeerPostLike {
id String @id @default(uuid()) id String @id @default(uuid())
beerPost BeerPost @relation(fields: [beerPostId], references: [id], onDelete: Cascade) beerPost BeerPost @relation(fields: [beerPostId], references: [id], onDelete: Cascade)
beerPostId String beerPostId String

View File

@@ -1,4 +1,4 @@
import type { BeerPost, BeerPostLikes, User } from '@prisma/client'; import type { BeerPost, BeerPostLike, User } from '@prisma/client';
import DBClient from '../../DBClient'; import DBClient from '../../DBClient';
const createNewBeerPostLikes = async ({ const createNewBeerPostLikes = async ({
@@ -11,7 +11,7 @@ const createNewBeerPostLikes = async ({
}; };
numberOfLikes: number; numberOfLikes: number;
}) => { }) => {
const beerPostLikePromises: Promise<BeerPostLikes>[] = []; const beerPostLikePromises: Promise<BeerPostLike>[] = [];
// eslint-disable-next-line no-plusplus // eslint-disable-next-line no-plusplus
for (let i = 0; i < numberOfLikes; i++) { for (let i = 0; i < numberOfLikes; i++) {
@@ -19,7 +19,7 @@ const createNewBeerPostLikes = async ({
const user = users[Math.floor(Math.random() * users.length)]; const user = users[Math.floor(Math.random() * users.length)];
beerPostLikePromises.push( beerPostLikePromises.push(
DBClient.instance.beerPostLikes.create({ DBClient.instance.beerPostLike.create({
data: { data: {
beerPost: { connect: { id: beerPost.id } }, beerPost: { connect: { id: beerPost.id } },
user: { connect: { id: user.id } }, user: { connect: { id: user.id } },

View File

@@ -5,6 +5,7 @@ import BeerCommentValidationSchema from './schema/CreateBeerCommentValidationSch
const CreateBeerCommentWithUserSchema = BeerCommentValidationSchema.extend({ const CreateBeerCommentWithUserSchema = BeerCommentValidationSchema.extend({
userId: z.string().uuid(), userId: z.string().uuid(),
}); });
const createNewBeerComment = async ({ const createNewBeerComment = async ({
content, content,
rating, rating,

View File

@@ -0,0 +1,20 @@
import DBClient from '@/prisma/DBClient';
import { z } from 'zod';
import GetUserSchema from '../User/schema/GetUserSchema';
const createBeerPostLike = async ({
id,
user,
}: {
id: string;
user: z.infer<typeof GetUserSchema>;
}) => {
return DBClient.instance.beerPostLike.create({
data: {
beerPost: { connect: { id } },
user: { connect: { id: user.id } },
},
});
};
export default createBeerPostLike;

View File

@@ -0,0 +1,6 @@
import DBClient from '@/prisma/DBClient';
const findBeerPostLikeById = async (id: string) =>
DBClient.instance.beerPostLike.findUnique({ where: { id } });
export default findBeerPostLikeById;

View File

@@ -0,0 +1,11 @@
import DBClient from '@/prisma/DBClient';
const removeBeerPostLikeById = async (id: string) => {
return DBClient.instance.beerPostLike.delete({
where: {
id,
},
});
};
export default removeBeerPostLikeById;