Merge branch 'beer-style-fix' into dev-beer-styles

This commit is contained in:
Aaron William Po
2023-10-30 12:39:21 -04:00
6 changed files with 154 additions and 25 deletions

View File

@@ -20,8 +20,8 @@ const BeerStyleBeerSection: FC<BeerStyleBeerSectionProps> = ({ beerStyle }) => {
}); });
const { ref: penultimateBeerPostRef } = useInView({ const { ref: penultimateBeerPostRef } = useInView({
/** /**
* When the last beer post comes into view, call setSize from useBeerPostsByBrewery to * When the last beer post comes into view, call setSize from useBeerPostsByBeerStyle
* load more beer posts. * to load more beer posts.
*/ */
onChange: (visible) => { onChange: (visible) => {
if (!visible || isAtEnd) return; if (!visible || isAtEnd) return;

View File

@@ -0,0 +1,66 @@
import BeerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import useSWRInfinite from 'swr/infinite';
import { z } from 'zod';
interface UseBeerPostsByBeerStyleParams {
pageSize: number;
beerStyleId: string;
}
const useBeerPostsByBeerStyle = ({
pageSize,
beerStyleId,
}: UseBeerPostsByBeerStyleParams) => {
const fetcher = async (url: string) => {
const response = await fetch(url);
if (!response.ok) {
throw new Error(response.statusText);
}
const json = await response.json();
const count = response.headers.get('X-Total-Count');
const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
throw new Error('API response validation failed');
}
const parsedPayload = z.array(BeerPostQueryResult).safeParse(parsed.data.payload);
if (!parsedPayload.success) {
throw new Error('API response validation failed');
}
const pageCount = Math.ceil(parseInt(count as string, 10) / pageSize);
return {
beerPosts: parsedPayload.data,
pageCount,
};
};
const { data, error, isLoading, setSize, size } = useSWRInfinite(
(index) =>
`/api/beers/styles/${beerStyleId}/beers?page_num=${
index + 1
}&page_size=${pageSize}`,
fetcher,
);
const beerPosts = data?.flatMap((d) => d.beerPosts) ?? [];
const pageCount = data?.[0].pageCount ?? 0;
const isLoadingMore = size > 0 && data && typeof data[size - 1] === 'undefined';
const isAtEnd = !(size < data?.[0].pageCount!);
return {
beerPosts,
pageCount,
size,
setSize,
isLoading,
isLoadingMore,
isAtEnd,
error: error as unknown,
};
};
export default useBeerPostsByBeerStyle;

View File

@@ -46,6 +46,8 @@ const useBeerPostsByBeerStyle = ({
fetcher, fetcher,
); );
console.log(error);
const beerPosts = data?.flatMap((d) => d.beerPosts) ?? []; const beerPosts = data?.flatMap((d) => d.beerPosts) ?? [];
const pageCount = data?.[0].pageCount ?? 0; const pageCount = data?.[0].pageCount ?? 0;
const isLoadingMore = size > 0 && data && typeof data[size - 1] === 'undefined'; const isLoadingMore = size > 0 && data && typeof data[size - 1] === 'undefined';

View File

@@ -1,7 +1,8 @@
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions'; import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
import validateRequest from '@/config/nextConnect/middleware/validateRequest'; import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import DBClient from '@/prisma/DBClient'; import DBClient from '@/prisma/DBClient';
import BeerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult'; import getBeerPostsByBeerStyleId from '@/services/BeerPost/getBeerPostsByBeerStyleId';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiRequest, NextApiResponse } from 'next'; import { NextApiRequest, NextApiResponse } from 'next';
import { createRouter } from 'next-connect'; import { createRouter } from 'next-connect';
@@ -18,29 +19,13 @@ const getAllBeersByBeerStyle = async (
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
const { page_size, page_num, id } = req.query; const { page_size, page_num, id } = req.query;
const beers: z.infer<typeof BeerPostQueryResult>[] = const beers = await getBeerPostsByBeerStyleId({
await DBClient.instance.beerPost.findMany({ pageNum: parseInt(page_num, 10),
where: { styleId: id }, pageSize: parseInt(page_size, 10),
take: parseInt(page_size, 10), styleId: id,
skip: parseInt(page_num, 10) * parseInt(page_size, 10),
select: {
id: true,
name: true,
ibu: true,
abv: true,
createdAt: true,
updatedAt: true,
description: true,
postedBy: { select: { username: true, id: true } },
brewery: { select: { name: true, id: true } },
style: { select: { name: true, id: true, description: true } },
beerImages: { select: { alt: true, path: true, caption: true, id: true } },
},
}); });
const pageCount = await DBClient.instance.beerPost.count({ const pageCount = await DBClient.instance.beerPost.count({ where: { styleId: id } });
where: { breweryId: id },
});
res.setHeader('X-Total-Count', pageCount); res.setHeader('X-Total-Count', pageCount);

View File

@@ -0,0 +1,38 @@
import DBClient from '@/prisma/DBClient';
import { z } from 'zod';
import BeerPostQueryResult from './schema/BeerPostQueryResult';
interface GetBeerPostsByBeerStyleIdArgs {
styleId: string;
pageSize: number;
pageNum: number;
}
const getBeerPostsByBeerStyleId = async ({
pageNum,
pageSize,
styleId,
}: GetBeerPostsByBeerStyleIdArgs): Promise<z.infer<typeof BeerPostQueryResult>[]> => {
const beers = await DBClient.instance.beerPost.findMany({
where: { styleId },
take: pageSize,
skip: pageNum * pageSize,
select: {
id: true,
name: true,
ibu: true,
abv: true,
createdAt: true,
updatedAt: true,
description: true,
postedBy: { select: { username: true, id: true } },
brewery: { select: { name: true, id: true } },
style: { select: { name: true, id: true, description: true } },
beerImages: { select: { alt: true, path: true, caption: true, id: true } },
},
});
return beers;
};
export default getBeerPostsByBeerStyleId;

View File

@@ -0,0 +1,38 @@
import DBClient from '@/prisma/DBClient';
import { z } from 'zod';
import BeerPostQueryResult from './schema/BeerPostQueryResult';
interface GetBeerPostsByBeerStyleIdArgs {
breweryId: string;
pageSize: number;
pageNum: number;
}
const getBeerPostsByBeerStyleId = async ({
pageNum,
pageSize,
breweryId,
}: GetBeerPostsByBeerStyleIdArgs): Promise<z.infer<typeof BeerPostQueryResult>[]> => {
const beers = await DBClient.instance.beerPost.findMany({
where: { breweryId },
take: pageSize,
skip: pageNum * pageSize,
select: {
id: true,
name: true,
ibu: true,
abv: true,
createdAt: true,
updatedAt: true,
description: true,
postedBy: { select: { username: true, id: true } },
brewery: { select: { name: true, id: true } },
style: { select: { name: true, id: true, description: true } },
beerImages: { select: { alt: true, path: true, caption: true, id: true } },
},
});
return beers;
};
export default getBeerPostsByBeerStyleId;