Merge pull request #12 from aaronpo97/dev

Refactor BeerPostHeader, refactor login and register
This commit is contained in:
Aaron Po
2023-03-16 23:28:07 -04:00
committed by GitHub
8 changed files with 106 additions and 69 deletions

View File

@@ -39,10 +39,10 @@ const BeerInfoHeader: FC<{ beerPost: BeerPostQueryResult; initialLikeCount: numb
}, [beerPost.createdAt]);
return (
<div className="card flex flex-col justify-center bg-base-300">
<div className="card-body">
<main className="card flex flex-col justify-center bg-base-300">
<article className="card-body">
<div className="flex justify-between">
<div>
<header>
<h1 className="text-4xl font-bold">{beerPost.name}</h1>
<h2 className="text-2xl font-semibold">
by{' '}
@@ -53,31 +53,29 @@ const BeerInfoHeader: FC<{ beerPost: BeerPostQueryResult; initialLikeCount: numb
{beerPost.brewery.name}
</Link>
</h2>
</div>
<div>
{isPostOwner && (
<div className="tooltip tooltip-left" data-tip={`Edit '${beerPost.name}'`}>
<Link
href={`/beers/${beerPost.id}/edit`}
className="btn-outline btn-sm btn"
>
<FaRegEdit className="text-xl" />
</Link>
</div>
)}
</div>
</header>
{isPostOwner && (
<div className="tooltip tooltip-left" data-tip={`Edit '${beerPost.name}'`}>
<Link
href={`/beers/${beerPost.id}/edit`}
className="btn-outline btn-sm btn"
>
<FaRegEdit className="text-xl" />
</Link>
</div>
)}
</div>
<h3 className="italic">
posted by{' '}
<Link href={`/users/${beerPost.postedBy.id}`} className="link-hover link">
{beerPost.postedBy.username}{' '}
{beerPost.postedBy.username}
</Link>
<span
className="tooltip tooltip-bottom"
data-tip={format(createdAtDate, 'MM/dd/yyyy')}
>
{timeDistance} ago
{` ${timeDistance}`} ago
</span>
</h3>
@@ -108,8 +106,8 @@ const BeerInfoHeader: FC<{ beerPost: BeerPostQueryResult; initialLikeCount: numb
)}
</div>
</div>
</div>
</div>
</article>
</main>
);
};

View File

@@ -50,6 +50,18 @@ const EditBeerPostForm: FC<EditBeerPostFormProps> = ({ previousValues }) => {
}
};
const onDelete = async () => {
try {
const response = await fetch(`/api/beers/${previousValues.id}`, {
method: 'DELETE',
});
if (response.status === 200) {
router.push('/beers');
}
} catch (e) {
console.error(e);
}
};
return (
<form className="form-control" onSubmit={handleSubmit(onSubmit)}>
<div className="mb-5">
@@ -116,10 +128,17 @@ const EditBeerPostForm: FC<EditBeerPostFormProps> = ({ previousValues }) => {
/>
</FormSegment>
<div className="mt-2">
<div className="mt-2 space-y-4">
<Button type="submit" isSubmitting={isSubmitting}>
{isSubmitting ? 'Submitting...' : 'Submit'}
</Button>
<button
className={`btn-primary btn w-full rounded-xl ${isSubmitting ? 'loading' : ''}`}
type="button"
onClick={onDelete}
>
Delete
</button>
</div>
</form>
);

View File

@@ -1,28 +0,0 @@
import { GetServerSideProps, GetServerSidePropsContext, Redirect } from 'next';
import { getLoginSession } from '@/config/auth/session';
import findUserById from '@/services/User/findUserById';
const redirectIfLoggedIn = (redirect: Redirect) => {
const fn: GetServerSideProps = async (context: GetServerSidePropsContext) => {
try {
const { req } = context;
const session = await getLoginSession(req);
const { id } = session;
const user = await findUserById(id);
if (!user) {
throw new Error('Could not get user.');
}
return { redirect };
} catch {
return { props: {} };
}
};
return fn;
};
export default redirectIfLoggedIn;

View File

@@ -0,0 +1,17 @@
import UserContext from '@/contexts/userContext';
import { useRouter } from 'next/router';
import { useContext, useEffect } from 'react';
const useRedirectWhenLoggedIn = () => {
const { user } = useContext(UserContext);
const router = useRouter();
useEffect(() => {
if (!user) {
return;
}
router.push('/');
}, [user, router]);
};
export default useRedirectWhenLoggedIn;

View File

@@ -6,20 +6,25 @@ import editBeerPostById from '@/services/BeerPost/editBeerPostById';
import EditBeerPostValidationSchema from '@/services/BeerPost/schema/EditBeerPostValidationSchema';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect';
import { createRouter, NextHandler } from 'next-connect';
import { z } from 'zod';
import ServerError from '@/config/util/ServerError';
import DBClient from '@/prisma/DBClient';
interface EditBeerPostRequest extends UserExtendedNextApiRequest {
interface BeerPostRequest extends UserExtendedNextApiRequest {
query: { id: string };
}
interface EditBeerPostRequest extends BeerPostRequest {
body: z.infer<typeof EditBeerPostValidationSchema>;
}
const editBeerPost = async (
req: EditBeerPostRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
const checkIfBeerPostOwner = async (
req: BeerPostRequest,
res: NextApiResponse,
next: NextHandler,
) => {
const { body, user, query } = req;
const { user, query } = req;
const { id } = query;
const beerPost = await getBeerPostById(id);
@@ -32,6 +37,18 @@ const editBeerPost = async (
throw new ServerError('You cannot edit that beer post.', 403);
}
next();
};
const editBeerPost = async (
req: EditBeerPostRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const {
body,
query: { id },
} = req;
await editBeerPostById(id, body);
res.status(200).json({
@@ -41,12 +58,32 @@ const editBeerPost = async (
});
};
const deleteBeerPost = async (req: BeerPostRequest, res: NextApiResponse) => {
const {
query: { id },
} = req;
const deleted = await DBClient.instance.beerPost.delete({
where: { id },
});
if (!deleted) {
throw new ServerError('Beer post not found', 404);
}
res.status(200).json({
message: 'Beer post deleted successfully',
success: true,
statusCode: 200,
});
};
const router = createRouter<
EditBeerPostRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
>();
router.put(getCurrentUser, editBeerPost);
router.put(getCurrentUser, checkIfBeerPostOwner, editBeerPost);
router.delete(getCurrentUser, checkIfBeerPostOwner, deleteBeerPost);
const handler = router.handler(NextConnectOptions);

View File

@@ -6,9 +6,11 @@ import Image from 'next/image';
import { FaUserCircle } from 'react-icons/fa';
import Head from 'next/head';
import Link from 'next/link';
import redirectIfLoggedIn from '@/getServerSideProps/redirectIfLoggedIn';
import useRedirectWhenLoggedIn from '@/hooks/useRedirectIfLoggedIn';
const LoginPage: NextPage = () => {
useRedirectWhenLoggedIn();
return (
<Layout>
<Head>
@@ -52,8 +54,3 @@ const LoginPage: NextPage = () => {
};
export default LoginPage;
export const getServerSideProps = redirectIfLoggedIn({
destination: '/',
permanent: false,
});

View File

@@ -1,12 +1,15 @@
import RegisterUserForm from '@/components/RegisterUserForm';
import FormPageLayout from '@/components/ui/forms/FormPageLayout';
import Layout from '@/components/ui/Layout';
import redirectIfLoggedIn from '@/getServerSideProps/redirectIfLoggedIn';
import useRedirectWhenLoggedIn from '@/hooks/useRedirectIfLoggedIn';
import { NextPage } from 'next';
import Head from 'next/head';
import { BiUser } from 'react-icons/bi';
const RegisterUserPage: NextPage = () => {
useRedirectWhenLoggedIn();
return (
<Layout>
<Head>
@@ -26,8 +29,3 @@ const RegisterUserPage: NextPage = () => {
};
export default RegisterUserPage;
export const getServerSideProps = redirectIfLoggedIn({
destination: '/',
permanent: false,
});

View File

@@ -36,7 +36,6 @@ const sendCreateBeerCommentRequest = async ({
throw new Error('Invalid API response');
}
console.log(parsedResponse);
const parsedPayload = BeerCommentQueryResult.safeParse(parsedResponse.data.payload);
if (!parsedPayload.success) {