Rework pagination and cookies

This commit is contained in:
Aaron William Po
2023-03-19 18:04:13 -04:00
parent 6b12cb72c5
commit cf6a8309f1
7 changed files with 53 additions and 50 deletions

View File

@@ -0,0 +1,34 @@
import Link from 'next/link';
import { FC } from 'react';
interface PaginationProps {
pageNum: number;
pageCount: number;
}
const BeerIndexPaginationBar: FC<PaginationProps> = ({ pageCount, pageNum }) => {
return (
<div className="btn-group">
<Link
className={`btn ${pageNum === 1 ? 'btn-disabled' : ''}`}
href={{ pathname: '/beers', query: { page_num: pageNum - 1 } }}
scroll={false}
prefetch={true}
>
«
</Link>
<button className="btn">Page {pageNum}</button>
<Link
className={`btn ${pageNum === pageCount ? 'btn-disabled' : ''}`}
href={{ pathname: '/beers', query: { page_num: pageNum + 1 } }}
scroll={false}
prefetch={true}
>
»
</Link>
</div>
);
};
export default BeerIndexPaginationBar;

View File

@@ -1,37 +0,0 @@
import { useRouter } from 'next/router';
import { FC } from 'react';
interface PaginationProps {
pageNum: number;
pageCount: number;
}
const Pagination: FC<PaginationProps> = ({ pageCount, pageNum }) => {
const router = useRouter();
return (
<div className="btn-group">
<button
className="btn"
disabled={pageNum <= 1}
onClick={async () =>
router.push({ pathname: '/beers', query: { page_num: pageNum - 1 } })
}
>
«
</button>
<button className="btn">Page {pageNum}</button>
<button
className="btn"
disabled={pageNum >= pageCount}
onClick={async () =>
router.push({ pathname: '/beers', query: { page_num: pageNum + 1 } })
}
>
»
</button>
</div>
);
};
export default Pagination;

View File

@@ -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 btn-ghost btn-sm"> <Link href={backLink} className="btn-ghost btn-sm btn p-0">
<BiArrowBack className="text-xl" /> <BiArrowBack className="text-xl" />
</Link> </Link>
</div> </div>

View File

@@ -8,7 +8,7 @@ export const MAX_AGE = 60 * 60 * 8; // 8 hours
export function setTokenCookie(res: NextApiResponse, token: string) { export function setTokenCookie(res: NextApiResponse, token: string) {
const cookie = serialize(TOKEN_NAME, token, { const cookie = serialize(TOKEN_NAME, token, {
maxAge: MAX_AGE, maxAge: MAX_AGE,
httpOnly: true, httpOnly: false,
secure: process.env.NODE_ENV === 'production', secure: process.env.NODE_ENV === 'production',
path: '/', path: '/',
sameSite: 'lax', sameSite: 'lax',

View File

@@ -3,15 +3,18 @@ import APIResponseValidationSchema from '@/validation/APIResponseValidationSchem
import useSWR from 'swr'; import useSWR from 'swr';
const useUser = () => { const useUser = () => {
// check cookies for user
const { const {
data: user, data: user,
error, error,
isLoading, isLoading,
} = useSWR('/api/users/current', async (url) => { } = useSWR('/api/users/current', async (url) => {
if (!document.cookie.includes('token')) {
throw new Error('No token cookie found');
}
const response = await fetch(url); const response = await fetch(url);
if (!response.ok) { if (!response.ok) {
document.cookie = 'token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
throw new Error(response.statusText); throw new Error(response.statusText);
} }
@@ -23,6 +26,7 @@ const useUser = () => {
} }
const parsedPayload = GetUserSchema.safeParse(parsed.data.payload); const parsedPayload = GetUserSchema.safeParse(parsed.data.payload);
console.log(parsedPayload);
if (!parsedPayload.success) { if (!parsedPayload.success) {
throw new Error(parsedPayload.error.message); throw new Error(parsedPayload.error.message);
} }

View File

@@ -17,12 +17,6 @@ interface RegisterUserRequest extends NextApiRequest {
body: z.infer<typeof CreateUserValidationSchema>; body: z.infer<typeof CreateUserValidationSchema>;
} }
const { BASE_URL } = process.env;
if (!BASE_URL) {
throw new ServerError('BASE_URL env variable is not set.', 500);
}
const registerUser = async (req: RegisterUserRequest, res: NextApiResponse) => { const registerUser = async (req: RegisterUserRequest, res: NextApiResponse) => {
const [usernameTaken, emailTaken] = await Promise.all([ const [usernameTaken, emailTaken] = await Promise.all([
findUserByUsername(req.body.username), findUserByUsername(req.body.username),

View File

@@ -4,7 +4,7 @@ import getAllBeerPosts from '@/services/BeerPost/getAllBeerPosts';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import DBClient from '@/prisma/DBClient'; import DBClient from '@/prisma/DBClient';
import Layout from '@/components/ui/Layout'; import Layout from '@/components/ui/Layout';
import Pagination from '@/components/BeerIndex/Pagination'; 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';
@@ -26,16 +26,24 @@ const BeerPage: NextPage<BeerPageProps> = ({ initialBeerPosts, pageCount }) => {
<meta name="description" content="Beer posts" /> <meta name="description" content="Beer posts" />
</Head> </Head>
<div className="flex items-center justify-center bg-base-100"> <div className="flex items-center justify-center bg-base-100">
<main className="my-10 flex w-10/12 flex-col space-y-4"> <div className="my-10 flex w-10/12 flex-col space-y-4">
<header className="my-10">
<div className="space-y-2">
<h1 className="text-6xl font-bold">The Biergarten Index</h1>
<h2 className="text-2xl font-bold">
Page {pageNum} of {pageCount}
</h2>
</div>
</header>
<div className="grid gap-5 md:grid-cols-2 xl:grid-cols-3"> <div className="grid gap-5 md:grid-cols-2 xl:grid-cols-3">
{initialBeerPosts.map((post) => { {initialBeerPosts.map((post) => {
return <BeerCard post={post} key={post.id} />; return <BeerCard post={post} key={post.id} />;
})} })}
</div> </div>
<div className="flex justify-center"> <div className="flex justify-center">
<Pagination pageNum={pageNum} pageCount={pageCount} /> <BeerIndexPaginationBar pageNum={pageNum} pageCount={pageCount} />
</div>
</div> </div>
</main>
</div> </div>
</Layout> </Layout>
); );