mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 10:42:08 +00:00
Merge branch 'beer-style-fix' into dev-beer-styles
This commit is contained in:
@@ -20,8 +20,8 @@ const BeerStyleBeerSection: FC<BeerStyleBeerSectionProps> = ({ beerStyle }) => {
|
||||
});
|
||||
const { ref: penultimateBeerPostRef } = useInView({
|
||||
/**
|
||||
* When the last beer post comes into view, call setSize from useBeerPostsByBrewery to
|
||||
* load more beer posts.
|
||||
* When the last beer post comes into view, call setSize from useBeerPostsByBeerStyle
|
||||
* to load more beer posts.
|
||||
*/
|
||||
onChange: (visible) => {
|
||||
if (!visible || isAtEnd) return;
|
||||
|
||||
@@ -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;
|
||||
@@ -46,6 +46,8 @@ const useBeerPostsByBeerStyle = ({
|
||||
fetcher,
|
||||
);
|
||||
|
||||
console.log(error);
|
||||
|
||||
const beerPosts = data?.flatMap((d) => d.beerPosts) ?? [];
|
||||
const pageCount = data?.[0].pageCount ?? 0;
|
||||
const isLoadingMore = size > 0 && data && typeof data[size - 1] === 'undefined';
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
|
||||
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
|
||||
import DBClient from '@/prisma/DBClient';
|
||||
import BeerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||
import getBeerPostsByBeerStyleId from '@/services/BeerPost/getBeerPostsByBeerStyleId';
|
||||
|
||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { createRouter } from 'next-connect';
|
||||
@@ -18,30 +19,14 @@ const getAllBeersByBeerStyle = async (
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const { page_size, page_num, id } = req.query;
|
||||
|
||||
const beers: z.infer<typeof BeerPostQueryResult>[] =
|
||||
await DBClient.instance.beerPost.findMany({
|
||||
where: { styleId: id },
|
||||
take: parseInt(page_size, 10),
|
||||
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({
|
||||
where: { breweryId: id },
|
||||
const beers = await getBeerPostsByBeerStyleId({
|
||||
pageNum: parseInt(page_num, 10),
|
||||
pageSize: parseInt(page_size, 10),
|
||||
styleId: id,
|
||||
});
|
||||
|
||||
const pageCount = await DBClient.instance.beerPost.count({ where: { styleId: id } });
|
||||
|
||||
res.setHeader('X-Total-Count', pageCount);
|
||||
|
||||
res.status(200).json({
|
||||
|
||||
38
src/services/BeerPost/getBeerPostsByBeerStyleId.ts
Normal file
38
src/services/BeerPost/getBeerPostsByBeerStyleId.ts
Normal 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;
|
||||
38
src/services/BeerPost/getBeerPostsByBreweryId.ts
Normal file
38
src/services/BeerPost/getBeerPostsByBreweryId.ts
Normal 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;
|
||||
Reference in New Issue
Block a user