@@ -135,6 +161,8 @@ const BreweryCommentsSection: FC
= ({ breweryPost }) =>
size={size}
commentSectionRef={commentSectionRef}
mutate={mutate}
+ handleDeleteRequest={handleDeleteRequest}
+ handleEditRequest={handleEditRequest}
/>
)
}
diff --git a/src/components/BreweryById/BreweryInfoHeader.tsx b/src/components/BreweryById/BreweryInfoHeader.tsx
index 35f18a4..018f0e7 100644
--- a/src/components/BreweryById/BreweryInfoHeader.tsx
+++ b/src/components/BreweryById/BreweryInfoHeader.tsx
@@ -1,6 +1,6 @@
import UserContext from '@/contexts/userContext';
-import useGetBreweryPostLikeCount from '@/hooks/useGetBreweryPostLikeCount';
-import useTimeDistance from '@/hooks/useTimeDistance';
+import useGetBreweryPostLikeCount from '@/hooks/data-fetching/brewery-likes/useGetBreweryPostLikeCount';
+import useTimeDistance from '@/hooks/utilities/useTimeDistance';
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
import { format } from 'date-fns';
import { FC, useContext } from 'react';
@@ -72,7 +72,7 @@ const BreweryInfoHeader: FC = ({ breweryPost }) => {
{(!!likeCount || likeCount === 0) && (
- Liked by {likeCount} user{likeCount !== 1 && 's'}
+ Liked by {likeCount} {likeCount === 1 ? 'user' : 'users'}
)}
diff --git a/src/components/BreweryById/BreweryPostMap.tsx b/src/components/BreweryById/BreweryPostMap.tsx
index c880f15..2543122 100644
--- a/src/components/BreweryById/BreweryPostMap.tsx
+++ b/src/components/BreweryById/BreweryPostMap.tsx
@@ -1,4 +1,4 @@
-import useMediaQuery from '@/hooks/useMediaQuery';
+import useMediaQuery from '@/hooks/utilities/useMediaQuery';
import 'mapbox-gl/dist/mapbox-gl.css';
import { FC, useMemo } from 'react';
import Map, { Marker } from 'react-map-gl';
diff --git a/src/components/BreweryIndex/BreweryCard.tsx b/src/components/BreweryIndex/BreweryCard.tsx
index fb85024..e4f8594 100644
--- a/src/components/BreweryIndex/BreweryCard.tsx
+++ b/src/components/BreweryIndex/BreweryCard.tsx
@@ -1,5 +1,5 @@
import UserContext from '@/contexts/userContext';
-import useGetBreweryPostLikeCount from '@/hooks/useGetBreweryPostLikeCount';
+import useGetBreweryPostLikeCount from '@/hooks/data-fetching/brewery-likes/useGetBreweryPostLikeCount';
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
import { FC, useContext } from 'react';
import Link from 'next/link';
diff --git a/src/components/BreweryIndex/BreweryPostLikeButton.tsx b/src/components/BreweryIndex/BreweryPostLikeButton.tsx
index b990420..0a58b04 100644
--- a/src/components/BreweryIndex/BreweryPostLikeButton.tsx
+++ b/src/components/BreweryIndex/BreweryPostLikeButton.tsx
@@ -1,5 +1,5 @@
-import useCheckIfUserLikesBreweryPost from '@/hooks/useCheckIfUserLikesBreweryPost';
-import useGetBreweryPostLikeCount from '@/hooks/useGetBreweryPostLikeCount';
+import useCheckIfUserLikesBreweryPost from '@/hooks/data-fetching/brewery-likes/useCheckIfUserLikesBreweryPost';
+import useGetBreweryPostLikeCount from '@/hooks/data-fetching/brewery-likes/useGetBreweryPostLikeCount';
import sendBreweryPostLikeRequest from '@/requests/sendBreweryPostLikeRequest';
import { FC, useState } from 'react';
import LikeButton from '../ui/LikeButton';
diff --git a/src/components/ui/CommentsComponent.tsx b/src/components/ui/CommentsComponent.tsx
index f91484c..ece5752 100644
--- a/src/components/ui/CommentsComponent.tsx
+++ b/src/components/ui/CommentsComponent.tsx
@@ -3,11 +3,12 @@ import { FaArrowUp } from 'react-icons/fa';
import { useInView } from 'react-intersection-observer';
-import useBeerPostComments from '@/hooks/useBeerPostComments';
-import useBreweryPostComments from '@/hooks/useBreweryPostComments';
+import useBeerPostComments from '@/hooks/data-fetching/beer-comments/useBeerPostComments';
+
+import useBreweryPostComments from '@/hooks/data-fetching/brewery-comments/useBreweryPostComments';
import NoCommentsCard from '../BeerById/NoCommentsCard';
import LoadingComponent from '../BeerById/LoadingComponent';
-import CommentCardBody from '../BeerById/CommentCardBody';
+import CommentCardBody from '../BeerBreweryComments/CommentCardBody';
interface CommentsComponentProps {
commentSectionRef: MutableRefObject;
@@ -28,6 +29,11 @@ interface CommentsComponentProps {
mutate: ReturnType<
typeof useBeerPostComments | typeof useBreweryPostComments
>['mutate'];
+ handleDeleteRequest: (id: string) => Promise;
+ handleEditRequest: (
+ id: string,
+ data: { content: string; rating: number },
+ ) => Promise;
}
const CommentsComponent: FC = ({
@@ -39,6 +45,8 @@ const CommentsComponent: FC = ({
setSize,
size,
mutate,
+ handleDeleteRequest,
+ handleEditRequest,
}) => {
const { ref: penultimateCommentRef } = useInView({
/**
@@ -67,7 +75,12 @@ const CommentsComponent: FC = ({
ref={isPenultimateComment ? penultimateCommentRef : undefined}
key={comment.id}
>
-
+
);
})}
diff --git a/src/components/ui/Navbar.tsx b/src/components/ui/Navbar.tsx
index 324d972..6162052 100644
--- a/src/components/ui/Navbar.tsx
+++ b/src/components/ui/Navbar.tsx
@@ -1,10 +1,11 @@
-import useMediaQuery from '@/hooks/useMediaQuery';
-import useNavbar from '@/hooks/useNavbar';
+import useMediaQuery from '@/hooks/utilities/useMediaQuery';
+import useNavbar from '@/hooks/utilities/useNavbar';
+import useTheme from '@/hooks/utilities/useTheme';
+
import Link from 'next/link';
import { FC } from 'react';
import { MdDarkMode, MdLightMode } from 'react-icons/md';
import { GiHamburgerMenu } from 'react-icons/gi';
-import useTheme from '@/hooks/useTheme';
const DesktopLinks: FC = () => {
const { pages, currentURL } = useNavbar();
diff --git a/src/contexts/userContext.ts b/src/contexts/userContext.ts
index 7345769..ac84c98 100644
--- a/src/contexts/userContext.ts
+++ b/src/contexts/userContext.ts
@@ -1,4 +1,4 @@
-import useUser from '@/hooks/useUser';
+import useUser from '@/hooks/auth/useUser';
import GetUserSchema from '@/services/User/schema/GetUserSchema';
import { createContext } from 'react';
import { z } from 'zod';
diff --git a/src/hooks/useRedirectIfLoggedIn.ts b/src/hooks/auth/useRedirectIfLoggedIn.ts
similarity index 64%
rename from src/hooks/useRedirectIfLoggedIn.ts
rename to src/hooks/auth/useRedirectIfLoggedIn.ts
index d8d444e..ee6d16a 100644
--- a/src/hooks/useRedirectIfLoggedIn.ts
+++ b/src/hooks/auth/useRedirectIfLoggedIn.ts
@@ -3,9 +3,12 @@ import { useRouter } from 'next/router';
import { useContext } from 'react';
/**
- * Custom React hook that redirects the user to the home page if they are logged in. This
- * hook is used to prevent logged in users from accessing the login and signup pages. Must
- * be used under the UserContext provider.
+ * Custom React hook that redirects the user to the home page if they are logged in.
+ *
+ * This hook is used to prevent logged in users from accessing the login and signup pages
+ * by redirecting them to the home page.
+ *
+ * This hook should only be used in a component that is under the UserContext provider.
*
* @returns {void}
*/
diff --git a/src/hooks/useUser.ts b/src/hooks/auth/useUser.ts
similarity index 73%
rename from src/hooks/useUser.ts
rename to src/hooks/auth/useUser.ts
index 10a5359..86c4a9f 100644
--- a/src/hooks/useUser.ts
+++ b/src/hooks/auth/useUser.ts
@@ -5,11 +5,13 @@ import useSWR from 'swr';
/**
* A custom React hook that fetches the current user's data from the server.
*
- * @returns An object containing the current user's data, a boolean indicating if the
- * request is currently loading, and an error object if an error occurred during the
- * request.
- * @throws When the user is not logged in, the server returns an error status code, or if
- * the response data fails to validate against the expected schema.
+ * @returns An object with the following properties:
+ *
+ * - `user`: The current user's data.
+ * - `isLoading`: A boolean indicating whether the request is still in progress.
+ * - `error`: An error object if the user is not logged in, if the response data fails to
+ * validate against the expected schema, or if the server returns an error.
+ * - `mutate`: A function that can be used to mutate the current user's data.
*/
const useUser = () => {
const {
diff --git a/src/hooks/useBeerPostComments.ts b/src/hooks/data-fetching/beer-comments/useBeerPostComments.ts
similarity index 74%
rename from src/hooks/useBeerPostComments.ts
rename to src/hooks/data-fetching/beer-comments/useBeerPostComments.ts
index 126ac8c..32e39ba 100644
--- a/src/hooks/useBeerPostComments.ts
+++ b/src/hooks/data-fetching/beer-comments/useBeerPostComments.ts
@@ -16,22 +16,31 @@ interface UseBeerPostCommentsProps {
* @param props.pageNum - The page number of the comments to fetch.
* @param props.id - The ID of the beer post to fetch comments for.
* @param props.pageSize - The number of comments to fetch per page.
- * @returns An object containing the fetched comments, the total number of comment pages,
- * a boolean indicating if the request is currently loading, and a function to mutate
- * the data.
+ * @returns An object with the following properties:
+ *
+ * - `comments`: The comments for the beer post.
+ * - `isLoading`: A boolean indicating whether the comments are being fetched.
+ * - `error`: The error that occurred while fetching the comments.
+ * - `mutate`: A function to mutate the comments.
+ * - `size`: The number of pages of comments that have been fetched.
+ * - `setSize`: A function to set the number of pages of comments that have been fetched.
+ * - `isLoadingMore`: A boolean indicating whether more comments are being fetched.
+ * - `isAtEnd`: A boolean indicating whether all comments have been fetched.
+ * - `pageCount`: The total number of pages of comments.
*/
const useBeerPostComments = ({ id, pageSize }: UseBeerPostCommentsProps) => {
const fetcher = async (url: string) => {
const response = await fetch(url);
+
const json = await response.json();
const count = response.headers.get('X-Total-Count');
- const parsed = APIResponseValidationSchema.safeParse(json);
+ const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
throw new Error(parsed.error.message);
}
- const parsedPayload = z.array(CommentQueryResult).safeParse(parsed.data.payload);
+ const parsedPayload = z.array(CommentQueryResult).safeParse(parsed.data.payload);
if (!parsedPayload.success) {
throw new Error(parsedPayload.error.message);
}
diff --git a/src/hooks/useBeerPostLikeCount.ts b/src/hooks/data-fetching/beer-likes/useBeerPostLikeCount.ts
similarity index 78%
rename from src/hooks/useBeerPostLikeCount.ts
rename to src/hooks/data-fetching/beer-likes/useBeerPostLikeCount.ts
index 513c06d..2300ef2 100644
--- a/src/hooks/useBeerPostLikeCount.ts
+++ b/src/hooks/data-fetching/beer-likes/useBeerPostLikeCount.ts
@@ -6,8 +6,12 @@ import useSWR from 'swr';
* Custom hook to fetch the like count for a beer post from the server.
*
* @param beerPostId - The ID of the beer post to fetch the like count for.
- * @returns An object with the current like count, as well as metadata about the current
- * state of the request.
+ * @returns An object with the following properties:
+ *
+ * - `error`: The error that occurred while fetching the like count.
+ * - `isLoading`: A boolean indicating whether the like count is being fetched.
+ * - `mutate`: A function to mutate the like count.
+ * - `likeCount`: The like count for the beer post.
*/
const useGetBeerPostLikeCount = (beerPostId: string) => {
diff --git a/src/hooks/useCheckIfUserLikesBeerPost.ts b/src/hooks/data-fetching/beer-likes/useCheckIfUserLikesBeerPost.ts
similarity index 73%
rename from src/hooks/useCheckIfUserLikesBeerPost.ts
rename to src/hooks/data-fetching/beer-likes/useCheckIfUserLikesBeerPost.ts
index ce44b6c..3425ed3 100644
--- a/src/hooks/useCheckIfUserLikesBeerPost.ts
+++ b/src/hooks/data-fetching/beer-likes/useCheckIfUserLikesBeerPost.ts
@@ -9,22 +9,23 @@ import { z } from 'zod';
* data from the server.
*
* @param beerPostId The ID of the beer post to check for likes.
- * @returns An object containing a boolean indicating if the user has liked the beer post,
- * an error object if an error occurred during the request, and a boolean indicating if
- * the request is currently loading.
- * @throws When the user is not logged in, the server returns an error status code, or if
- * the response data fails to validate against the expected schema.
+ * @returns An object with the following properties:
+ *
+ * - `error`: The error that occurred while fetching the data.
+ * - `isLoading`: A boolean indicating whether the data is being fetched.
+ * - `mutate`: A function to mutate the data.
+ * - `isLiked`: A boolean indicating whether the current user has liked the beer post.
*/
const useCheckIfUserLikesBeerPost = (beerPostId: string) => {
const { user } = useContext(UserContext);
const { data, error, isLoading, mutate } = useSWR(
`/api/beers/${beerPostId}/like/is-liked`,
- async () => {
+ async (url) => {
if (!user) {
throw new Error('User is not logged in.');
}
- const response = await fetch(`/api/beers/${beerPostId}/like/is-liked`);
+ const response = await fetch(url);
const json = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json);
diff --git a/src/hooks/useBeerPostSearch.ts b/src/hooks/data-fetching/beer-posts/useBeerPostSearch.ts
similarity index 76%
rename from src/hooks/useBeerPostSearch.ts
rename to src/hooks/data-fetching/beer-posts/useBeerPostSearch.ts
index 3f20ea2..d07e606 100644
--- a/src/hooks/useBeerPostSearch.ts
+++ b/src/hooks/data-fetching/beer-posts/useBeerPostSearch.ts
@@ -5,9 +5,11 @@ import { z } from 'zod';
* A custom React hook that searches for beer posts that match a given query string.
*
* @param query The search query string to match beer posts against.
- * @returns An object containing an array of search results matching the query, an error
- * object if an error occurred during the search, and a boolean indicating if the
- * request is currently loading.
+ * @returns An object with the following properties:
+ *
+ * - `searchResults`: The beer posts that match the search query.
+ * - `searchError`: The error that occurred while fetching the data.
+ * - `isLoading`: A boolean indicating whether the data is being fetched.
*/
const useBeerPostSearch = (query: string | undefined) => {
const { data, isLoading, error } = useSWR(
diff --git a/src/hooks/useBeerPosts.ts b/src/hooks/data-fetching/beer-posts/useBeerPosts.ts
similarity index 73%
rename from src/hooks/useBeerPosts.ts
rename to src/hooks/data-fetching/beer-posts/useBeerPosts.ts
index 4cc28a2..043a35e 100644
--- a/src/hooks/useBeerPosts.ts
+++ b/src/hooks/data-fetching/beer-posts/useBeerPosts.ts
@@ -8,7 +8,16 @@ import { z } from 'zod';
*
* @param options The options to use when fetching beer posts.
* @param options.pageSize The number of beer posts to fetch per page.
- * @returns An object containing the beer posts, page count, and loading state.
+ * @returns An object with the following properties:
+ *
+ * - `beerPosts`: The beer posts fetched from the API.
+ * - `error`: The error that occurred while fetching the data.
+ * - `isAtEnd`: A boolean indicating whether all data has been fetched.
+ * - `isLoading`: A boolean indicating whether the data is being fetched.
+ * - `isLoadingMore`: A boolean indicating whether more data is being fetched.
+ * - `pageCount`: The total number of pages of data.
+ * - `setSize`: A function to set the size of the data.
+ * - `size`: The size of the data.
*/
const useBeerPosts = ({ pageSize }: { pageSize: number }) => {
const fetcher = async (url: string) => {
@@ -38,7 +47,7 @@ const useBeerPosts = ({ pageSize }: { pageSize: number }) => {
};
const { data, error, isLoading, setSize, size } = useSWRInfinite(
- (index) => `/api/beers?pageNum=${index + 1}&pageSize=${pageSize}`,
+ (index) => `/api/beers?page_num=${index + 1}&page_size=${pageSize}`,
fetcher,
);
@@ -49,13 +58,13 @@ const useBeerPosts = ({ pageSize }: { pageSize: number }) => {
return {
beerPosts,
- pageCount,
- size,
- setSize,
+ error: error as unknown,
+ isAtEnd,
isLoading,
isLoadingMore,
- isAtEnd,
- error: error as unknown,
+ pageCount,
+ setSize,
+ size,
};
};
diff --git a/src/hooks/useBeerPostsByBrewery.ts b/src/hooks/data-fetching/beer-posts/useBeerPostsByBrewery.ts
similarity index 78%
rename from src/hooks/useBeerPostsByBrewery.ts
rename to src/hooks/data-fetching/beer-posts/useBeerPostsByBrewery.ts
index c0762cb..c1627fb 100644
--- a/src/hooks/useBeerPostsByBrewery.ts
+++ b/src/hooks/data-fetching/beer-posts/useBeerPostsByBrewery.ts
@@ -14,7 +14,16 @@ interface UseBeerPostsByBreweryParams {
* @param options The options to use when fetching beer posts.
* @param options.pageSize The number of beer posts to fetch per page.
* @param options.breweryId The ID of the brewery to fetch beer posts for.
- * @returns An object containing the beer posts, page count, and loading state.
+ * @returns An object with the following properties:
+ *
+ * - `beerPosts`: The beer posts fetched from the API.
+ * - `error`: The error that occurred while fetching the data.
+ * - `isAtEnd`: A boolean indicating whether all data has been fetched.
+ * - `isLoading`: A boolean indicating whether the data is being fetched.
+ * - `isLoadingMore`: A boolean indicating whether more data is being fetched.
+ * - `pageCount`: The total number of pages of data.
+ * - `setSize`: A function to set the size of the data.
+ * - `size`: The size of the data.
*/
const UseBeerPostsByBrewery = ({ pageSize, breweryId }: UseBeerPostsByBreweryParams) => {
const fetcher = async (url: string) => {
diff --git a/src/hooks/useBreweryPostComments.ts b/src/hooks/data-fetching/brewery-comments/useBreweryPostComments.ts
similarity index 77%
rename from src/hooks/useBreweryPostComments.ts
rename to src/hooks/data-fetching/brewery-comments/useBreweryPostComments.ts
index bb87859..d90dc1a 100644
--- a/src/hooks/useBreweryPostComments.ts
+++ b/src/hooks/data-fetching/brewery-comments/useBreweryPostComments.ts
@@ -15,28 +15,35 @@ interface UseBreweryPostCommentsProps {
* @param props.pageNum - The page number of the comments to fetch.
* @param props.id - The ID of the brewery post to fetch comments for.
* @param props.pageSize - The number of comments to fetch per page.
- * @returns An object containing the fetched comments, the total number of comment pages,
- * a boolean indicating if the request is currently loading, and a function to mutate
- * the data.
+ * @returns An object with the following properties:
+ *
+ * - `comments`: The comments fetched from the API.
+ * - `error`: The error that occurred while fetching the data.
+ * - `isLoading`: A boolean indicating whether the data is being fetched.
+ * - `isLoadingMore`: A boolean indicating whether more data is being fetched.
+ * - `isAtEnd`: A boolean indicating whether all data has been fetched.
+ * - `mutate`: A function to mutate the data.
+ * - `pageCount`: The total number of pages of data.
+ * - `setSize`: A function to set the size of the data.
+ * - `size`: The size of the data.
*/
const useBreweryPostComments = ({ id, pageSize }: UseBreweryPostCommentsProps) => {
const fetcher = async (url: string) => {
const response = await fetch(url);
const json = await response.json();
const count = response.headers.get('X-Total-Count');
- const parsed = APIResponseValidationSchema.safeParse(json);
+ const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
throw new Error(parsed.error.message);
}
- const parsedPayload = z.array(CommentQueryResult).safeParse(parsed.data.payload);
+ const parsedPayload = z.array(CommentQueryResult).safeParse(parsed.data.payload);
if (!parsedPayload.success) {
throw new Error(parsedPayload.error.message);
}
const pageCount = Math.ceil(parseInt(count as string, 10) / pageSize);
-
return { comments: parsedPayload.data, pageCount };
};
diff --git a/src/hooks/useCheckIfUserLikesBreweryPost.ts b/src/hooks/data-fetching/brewery-likes/useCheckIfUserLikesBreweryPost.ts
similarity index 71%
rename from src/hooks/useCheckIfUserLikesBreweryPost.ts
rename to src/hooks/data-fetching/brewery-likes/useCheckIfUserLikesBreweryPost.ts
index 7574d55..910ca43 100644
--- a/src/hooks/useCheckIfUserLikesBreweryPost.ts
+++ b/src/hooks/data-fetching/brewery-likes/useCheckIfUserLikesBreweryPost.ts
@@ -4,6 +4,18 @@ import { useContext } from 'react';
import useSWR from 'swr';
import { z } from 'zod';
+/**
+ * A custom React hook that checks if the current user likes a given brewery post.
+ *
+ * @param breweryPostId - The ID of the brewery post to check.
+ * @returns An object with the following properties:
+ *
+ * - `isLiked`: A boolean indicating whether the current user likes the brewery post.
+ * - `error`: The error that occurred while fetching the data.
+ * - `isLoading`: A boolean indicating whether the data is being fetched.
+ * - `mutate`: A function to mutate the data.
+ */
+
const useCheckIfUserLikesBreweryPost = (breweryPostId: string) => {
const { user } = useContext(UserContext);
const { data, error, isLoading, mutate } = useSWR(
@@ -15,8 +27,8 @@ const useCheckIfUserLikesBreweryPost = (breweryPostId: string) => {
const response = await fetch(`/api/breweries/${breweryPostId}/like/is-liked`);
const json = await response.json();
+
const parsed = APIResponseValidationSchema.safeParse(json);
-
if (!parsed.success) {
throw new Error('Invalid API response.');
}
diff --git a/src/hooks/useGetBreweryPostLikeCount.ts b/src/hooks/data-fetching/brewery-likes/useGetBreweryPostLikeCount.ts
similarity index 67%
rename from src/hooks/useGetBreweryPostLikeCount.ts
rename to src/hooks/data-fetching/brewery-likes/useGetBreweryPostLikeCount.ts
index 0a1a20e..c2ba167 100644
--- a/src/hooks/useGetBreweryPostLikeCount.ts
+++ b/src/hooks/data-fetching/brewery-likes/useGetBreweryPostLikeCount.ts
@@ -2,6 +2,17 @@ import APIResponseValidationSchema from '@/validation/APIResponseValidationSchem
import useSWR from 'swr';
import { z } from 'zod';
+/**
+ * A custom React hook that fetches the number of likes a brewery post has.
+ *
+ * @param breweryPostId
+ * @returns An object with the following properties:
+ *
+ * - `likeCount`: The number of likes the brewery post has.
+ * - `error`: The error that occurred while fetching the data.
+ * - `isLoading`: A boolean indicating whether the data is being fetched.
+ * - `mutate`: A function to mutate the data.
+ */
const useGetBreweryPostLikeCount = (breweryPostId: string) => {
const { error, mutate, data, isLoading } = useSWR(
`/api/breweries/${breweryPostId}/like`,
@@ -10,15 +21,12 @@ const useGetBreweryPostLikeCount = (breweryPostId: string) => {
const json = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json);
-
if (!parsed.success) {
throw new Error('Failed to parse API response');
}
const parsedPayload = z
- .object({
- likeCount: z.number(),
- })
+ .object({ likeCount: z.number() })
.safeParse(parsed.data.payload);
if (!parsedPayload.success) {
diff --git a/src/hooks/useBreweryPosts.ts b/src/hooks/data-fetching/brewery-posts/useBreweryPosts.ts
similarity index 71%
rename from src/hooks/useBreweryPosts.ts
rename to src/hooks/data-fetching/brewery-posts/useBreweryPosts.ts
index ed73414..18127ee 100644
--- a/src/hooks/useBreweryPosts.ts
+++ b/src/hooks/data-fetching/brewery-posts/useBreweryPosts.ts
@@ -8,7 +8,16 @@ import { z } from 'zod';
*
* @param options The options to use when fetching brewery posts.
* @param options.pageSize The number of brewery posts to fetch per page.
- * @returns An object containing the brewery posts, page count, and loading state.
+ * @returns An object with the following properties:
+ *
+ * - `breweryPosts`: The brewery posts fetched from the API.
+ * - `error`: The error that occurred while fetching the data.
+ * - `isAtEnd`: A boolean indicating whether all data has been fetched.
+ * - `isLoading`: A boolean indicating whether the data is being fetched.
+ * - `isLoadingMore`: A boolean indicating whether more data is being fetched.
+ * - `pageCount`: The total number of pages of data.
+ * - `setSize`: A function to set the size of the data.
+ * - `size`: The size of the data.
*/
const useBreweryPosts = ({ pageSize }: { pageSize: number }) => {
const fetcher = async (url: string) => {
@@ -31,14 +40,11 @@ const useBreweryPosts = ({ pageSize }: { pageSize: number }) => {
}
const pageCount = Math.ceil(parseInt(count as string, 10) / pageSize);
- return {
- breweryPosts: parsedPayload.data,
- pageCount,
- };
+ return { breweryPosts: parsedPayload.data, pageCount };
};
const { data, error, isLoading, setSize, size } = useSWRInfinite(
- (index) => `/api/breweries?pageNum=${index + 1}&pageSize=${pageSize}`,
+ (index) => `/api/breweries?page_num=${index + 1}&page_size=${pageSize}`,
fetcher,
);
diff --git a/src/hooks/useGeolocation.ts b/src/hooks/utilities/useGeolocation.ts
similarity index 93%
rename from src/hooks/useGeolocation.ts
rename to src/hooks/utilities/useGeolocation.ts
index 277d248..8e0cea0 100644
--- a/src/hooks/useGeolocation.ts
+++ b/src/hooks/utilities/useGeolocation.ts
@@ -4,8 +4,7 @@ import { useEffect, useState } from 'react';
* A custom React Hook that retrieves and monitors the user's geolocation using the
* browser's built-in `navigator.geolocation` API.
*
- * @returns An object containing the user's geolocation information and any errors that
- * might occur. The object has the following properties:
+ * @returns An object with the following properties:
*
* - `coords` - The user's current geolocation coordinates, or null if the geolocation could
* not be retrieved.
diff --git a/src/hooks/useMediaQuery.ts b/src/hooks/utilities/useMediaQuery.ts
similarity index 100%
rename from src/hooks/useMediaQuery.ts
rename to src/hooks/utilities/useMediaQuery.ts
diff --git a/src/hooks/useNavbar.ts b/src/hooks/utilities/useNavbar.ts
similarity index 92%
rename from src/hooks/useNavbar.ts
rename to src/hooks/utilities/useNavbar.ts
index 73f90e8..c718a14 100644
--- a/src/hooks/useNavbar.ts
+++ b/src/hooks/utilities/useNavbar.ts
@@ -11,7 +11,10 @@ interface Page {
* A custom hook that returns the current URL and the pages to display in the navbar. It
* uses the user context to determine whether the user is authenticated or not.
*
- * @returns An object containing the current URL and the pages to display in the navbar.
+ * @returns An object with the following properties:
+ *
+ * - `currentURL`: The current URL.
+ * - `pages`: The pages to display in the navbar.
*/
const useNavbar = () => {
const router = useRouter();
diff --git a/src/hooks/useTheme.ts b/src/hooks/utilities/useTheme.ts
similarity index 55%
rename from src/hooks/useTheme.ts
rename to src/hooks/utilities/useTheme.ts
index 6aa0595..23c3b83 100644
--- a/src/hooks/useTheme.ts
+++ b/src/hooks/utilities/useTheme.ts
@@ -2,13 +2,18 @@ import { useState, useEffect } from 'react';
import useMediaQuery from './useMediaQuery';
/**
- * A custom hook to manage the theme of the app. If a preferred theme is not set in
- * localStorage, it will use what the user's browser prefers as determined by the
- * prefers-color-scheme media query. If the user changes their preferred theme, it will be
- * saved in localStorage and used in subsequent visits.
+ * A custom hook to manage the theme of the app.
*
- * @returns ThemeState.theme - The current theme of the app.
- * @returns ThemeState.setTheme - A setter function to change the theme of the app.
+ * If a preferred theme is not set in localStorage, it will use what the user's browser
+ * prefers as determined by the prefers-color-scheme media query.
+ *
+ * If the user changes their preferred theme, it will be saved in localStorage and used in
+ * subsequent visits.
+ *
+ * @returns An object with the following properties:
+ *
+ * - `theme`: The current theme of the app.
+ * - `setTheme`: A function to set the theme of the app.
*/
const useTheme = () => {
const [theme, setTheme] = useState<'light' | 'dark'>('light');
diff --git a/src/hooks/useTimeDistance.ts b/src/hooks/utilities/useTimeDistance.ts
similarity index 59%
rename from src/hooks/useTimeDistance.ts
rename to src/hooks/utilities/useTimeDistance.ts
index 9d4f01b..f93a18b 100644
--- a/src/hooks/useTimeDistance.ts
+++ b/src/hooks/utilities/useTimeDistance.ts
@@ -2,12 +2,17 @@ import formatDistanceStrict from 'date-fns/formatDistanceStrict';
import { useState, useEffect } from 'react';
/**
- * Returns the time distance between the provided date and the current time, using the
- * `date-fns` `formatDistanceStrict` function. This hook ensures that the same result is
- * calculated on both the server and client, preventing hydration errors.
+ * A custom hook to calculate the time distance between the provided date and the current
+ * time.
+ *
+ * This hook uses the date-fns library to calculate the time distance.
+ *
+ * This hook ensures that the same result is calculated on both the server and client,
+ * preventing hydration errors.
*
* @param createdAt The date to calculate the time distance from.
* @returns The time distance between the provided date and the current time.
+ * @see https://date-fns.org/v2.30.0/docs/formatDistanceStrict
*/
const useTimeDistance = (createdAt: Date) => {
const [timeDistance, setTimeDistance] = useState('');
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index a8ca703..aa265a4 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -1,5 +1,5 @@
import UserContext from '@/contexts/userContext';
-import useUser from '@/hooks/useUser';
+
import '@/styles/globals.css';
import type { AppProps } from 'next/app';
import { useEffect } from 'react';
@@ -10,6 +10,7 @@ import { Analytics } from '@vercel/analytics/react';
import { Space_Grotesk } from 'next/font/google';
import Head from 'next/head';
import Layout from '@/components/ui/Layout';
+import useUser from '@/hooks/auth/useUser';
const spaceGrotesk = Space_Grotesk({
subsets: ['latin'],
diff --git a/src/pages/api/beers/index.ts b/src/pages/api/beers/index.ts
index 6d9c3c8..48c1995 100644
--- a/src/pages/api/beers/index.ts
+++ b/src/pages/api/beers/index.ts
@@ -9,8 +9,8 @@ import { z } from 'zod';
interface GetBeerPostsRequest extends NextApiRequest {
query: {
- pageNum: string;
- pageSize: string;
+ page_num: string;
+ page_size: string;
};
}
@@ -18,8 +18,8 @@ const getBeerPosts = async (
req: GetBeerPostsRequest,
res: NextApiResponse
>,
) => {
- const pageNum = parseInt(req.query.pageNum, 10);
- const pageSize = parseInt(req.query.pageSize, 10);
+ const pageNum = parseInt(req.query.page_num, 10);
+ const pageSize = parseInt(req.query.page_size, 10);
const beerPosts = await getAllBeerPosts(pageNum, pageSize);
const beerPostCount = await DBClient.instance.beerPost.count();
@@ -42,8 +42,8 @@ const router = createRouter<
router.get(
validateRequest({
querySchema: z.object({
- pageNum: z.string().regex(/^\d+$/),
- pageSize: z.string().regex(/^\d+$/),
+ page_num: z.string().regex(/^\d+$/),
+ page_size: z.string().regex(/^\d+$/),
}),
}),
getBeerPosts,
diff --git a/src/pages/api/breweries/index.ts b/src/pages/api/breweries/index.ts
index bd1d183..5f2f2aa 100644
--- a/src/pages/api/breweries/index.ts
+++ b/src/pages/api/breweries/index.ts
@@ -9,8 +9,8 @@ import { z } from 'zod';
interface GetBreweryPostsRequest extends NextApiRequest {
query: {
- pageNum: string;
- pageSize: string;
+ page_num: string;
+ page_size: string;
};
}
@@ -18,8 +18,8 @@ const getBreweryPosts = async (
req: GetBreweryPostsRequest,
res: NextApiResponse>,
) => {
- const pageNum = parseInt(req.query.pageNum, 10);
- const pageSize = parseInt(req.query.pageSize, 10);
+ const pageNum = parseInt(req.query.page_num, 10);
+ const pageSize = parseInt(req.query.page_size, 10);
const breweryPosts = await getAllBreweryPosts(pageNum, pageSize);
const breweryPostCount = await DBClient.instance.breweryPost.count();
@@ -42,8 +42,8 @@ const router = createRouter<
router.get(
validateRequest({
querySchema: z.object({
- pageNum: z.string().regex(/^\d+$/),
- pageSize: z.string().regex(/^\d+$/),
+ page_num: z.string().regex(/^\d+$/),
+ page_size: z.string().regex(/^\d+$/),
}),
}),
getBreweryPosts,
diff --git a/src/pages/api/brewery-comments/[id].ts b/src/pages/api/brewery-comments/[id].ts
new file mode 100644
index 0000000..8b81abf
--- /dev/null
+++ b/src/pages/api/brewery-comments/[id].ts
@@ -0,0 +1,106 @@
+import { UserExtendedNextApiRequest } from '@/config/auth/types';
+import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
+import validateRequest from '@/config/nextConnect/middleware/validateRequest';
+import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
+import ServerError from '@/config/util/ServerError';
+import DBClient from '@/prisma/DBClient';
+import CreateCommentValidationSchema from '@/services/types/CommentSchema/CreateCommentValidationSchema';
+
+import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
+import { NextApiResponse } from 'next';
+import { createRouter, NextHandler } from 'next-connect';
+import { z } from 'zod';
+
+interface DeleteCommentRequest extends UserExtendedNextApiRequest {
+ query: { id: string };
+}
+
+interface EditCommentRequest extends UserExtendedNextApiRequest {
+ query: { id: string };
+ body: z.infer;
+}
+
+const checkIfCommentOwner = async (
+ req: DeleteCommentRequest | EditCommentRequest,
+ res: NextApiResponse>,
+ next: NextHandler,
+) => {
+ const { id } = req.query;
+ const user = req.user!;
+ const comment = await DBClient.instance.breweryComment.findUnique({
+ where: { id },
+ });
+
+ if (!comment) {
+ throw new ServerError('Comment not found', 404);
+ }
+
+ if (comment.postedById !== user.id) {
+ throw new ServerError('You are not authorized to modify this comment', 403);
+ }
+
+ await next();
+};
+
+const editComment = async (
+ req: EditCommentRequest,
+ res: NextApiResponse>,
+) => {
+ const { id } = req.query;
+
+ const updated = await DBClient.instance.breweryComment.update({
+ where: { id },
+ data: {
+ content: req.body.content,
+ rating: req.body.rating,
+ updatedAt: new Date(),
+ },
+ });
+
+ return res.status(200).json({
+ success: true,
+ message: 'Comment updated successfully',
+ statusCode: 200,
+ payload: updated,
+ });
+};
+
+const deleteComment = async (
+ req: DeleteCommentRequest,
+ res: NextApiResponse>,
+) => {
+ const { id } = req.query;
+
+ await DBClient.instance.breweryComment.delete({ where: { id } });
+
+ res.status(200).json({
+ success: true,
+ message: 'Comment deleted successfully',
+ statusCode: 200,
+ });
+};
+
+const router = createRouter<
+ DeleteCommentRequest,
+ NextApiResponse>
+>();
+
+router
+ .delete(
+ validateRequest({ querySchema: z.object({ id: z.string().uuid() }) }),
+ getCurrentUser,
+ checkIfCommentOwner,
+ deleteComment,
+ )
+ .put(
+ validateRequest({
+ querySchema: z.object({ id: z.string().uuid() }),
+ bodySchema: CreateCommentValidationSchema,
+ }),
+ getCurrentUser,
+ checkIfCommentOwner,
+ editComment,
+ );
+
+const handler = router.handler(NextConnectOptions);
+export default handler;
diff --git a/src/pages/beers/[id]/edit.tsx b/src/pages/beers/[id]/edit.tsx
index a0e65f3..a55e933 100644
--- a/src/pages/beers/[id]/edit.tsx
+++ b/src/pages/beers/[id]/edit.tsx
@@ -2,7 +2,7 @@ import { NextPage } from 'next';
import Head from 'next/head';
import React from 'react';
-import withPageAuthRequired from '@/getServerSideProps/withPageAuthRequired';
+import withPageAuthRequired from '@/util/withPageAuthRequired';
import getBeerPostById from '@/services/BeerPost/getBeerPostById';
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
import EditBeerPostForm from '@/components/EditBeerPostForm';
diff --git a/src/pages/beers/[id]/index.tsx b/src/pages/beers/[id]/index.tsx
index 6cf7fa3..dcf4e02 100644
--- a/src/pages/beers/[id]/index.tsx
+++ b/src/pages/beers/[id]/index.tsx
@@ -16,7 +16,7 @@ import { z } from 'zod';
import 'react-responsive-carousel/lib/styles/carousel.min.css';
import { Carousel } from 'react-responsive-carousel';
-import useMediaQuery from '@/hooks/useMediaQuery';
+import useMediaQuery from '@/hooks/utilities/useMediaQuery';
import { Tab } from '@headlessui/react';
interface BeerPageProps {
diff --git a/src/pages/beers/create.tsx b/src/pages/beers/create.tsx
index 24bf470..eff60f2 100644
--- a/src/pages/beers/create.tsx
+++ b/src/pages/beers/create.tsx
@@ -1,7 +1,7 @@
import CreateBeerPostForm from '@/components/CreateBeerPostForm';
import FormPageLayout from '@/components/ui/forms/FormPageLayout';
-import withPageAuthRequired from '@/getServerSideProps/withPageAuthRequired';
+import withPageAuthRequired from '@/util/withPageAuthRequired';
import DBClient from '@/prisma/DBClient';
import getAllBreweryPosts from '@/services/BreweryPost/getAllBreweryPosts';
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
diff --git a/src/pages/beers/index.tsx b/src/pages/beers/index.tsx
index df6b2dd..3e21a0c 100644
--- a/src/pages/beers/index.tsx
+++ b/src/pages/beers/index.tsx
@@ -9,7 +9,7 @@ import { MutableRefObject, useContext, useRef } from 'react';
import { useInView } from 'react-intersection-observer';
import Spinner from '@/components/ui/Spinner';
-import useBeerPosts from '@/hooks/useBeerPosts';
+import useBeerPosts from '@/hooks/data-fetching/beer-posts/useBeerPosts';
import { FaArrowUp, FaPlus } from 'react-icons/fa';
import LoadingCard from '@/components/ui/LoadingCard';
diff --git a/src/pages/beers/search.tsx b/src/pages/beers/search.tsx
index 29b65a6..b595cf4 100644
--- a/src/pages/beers/search.tsx
+++ b/src/pages/beers/search.tsx
@@ -6,7 +6,7 @@ import { ChangeEvent, useEffect, useState } from 'react';
import Spinner from '@/components/ui/Spinner';
import debounce from 'lodash/debounce';
-import useBeerPostSearch from '@/hooks/useBeerPostSearch';
+import useBeerPostSearch from '@/hooks/data-fetching/beer-posts/useBeerPostSearch';
import FormLabel from '@/components/ui/forms/FormLabel';
const DEBOUNCE_DELAY = 300;
diff --git a/src/pages/breweries/[id].tsx b/src/pages/breweries/[id].tsx
index 351ae30..291c612 100644
--- a/src/pages/breweries/[id].tsx
+++ b/src/pages/breweries/[id].tsx
@@ -7,7 +7,7 @@ import Head from 'next/head';
import Image from 'next/image';
import 'react-responsive-carousel/lib/styles/carousel.min.css'; // requires a loader
import { Carousel } from 'react-responsive-carousel';
-import useMediaQuery from '@/hooks/useMediaQuery';
+import useMediaQuery from '@/hooks/utilities/useMediaQuery';
import { Tab } from '@headlessui/react';
import BreweryInfoHeader from '@/components/BreweryById/BreweryInfoHeader';
import BreweryPostMap from '@/components/BreweryById/BreweryPostMap';
diff --git a/src/pages/breweries/index.tsx b/src/pages/breweries/index.tsx
index 29cba00..96e9add 100644
--- a/src/pages/breweries/index.tsx
+++ b/src/pages/breweries/index.tsx
@@ -2,7 +2,7 @@ import BreweryCard from '@/components/BreweryIndex/BreweryCard';
import LoadingCard from '@/components/ui/LoadingCard';
import Spinner from '@/components/ui/Spinner';
import UserContext from '@/contexts/userContext';
-import useBreweryPosts from '@/hooks/useBreweryPosts';
+import useBreweryPosts from '@/hooks/data-fetching/brewery-posts/useBreweryPosts';
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
import { NextPage } from 'next';
import Head from 'next/head';
diff --git a/src/pages/breweries/map.tsx b/src/pages/breweries/map.tsx
index 90d85c1..cfa5854 100644
--- a/src/pages/breweries/map.tsx
+++ b/src/pages/breweries/map.tsx
@@ -13,7 +13,7 @@ import DBClient from '@/prisma/DBClient';
import LocationMarker from '@/components/ui/LocationMarker';
import Link from 'next/link';
import Head from 'next/head';
-import useGeolocation from '@/hooks/useGeolocation';
+import useGeolocation from '@/hooks/utilities/useGeolocation';
type MapStyles = Record<'light' | 'dark', `mapbox://styles/mapbox/${string}`>;
diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx
index b7d75bf..3c6241e 100644
--- a/src/pages/login/index.tsx
+++ b/src/pages/login/index.tsx
@@ -7,7 +7,7 @@ import { FaUserCircle } from 'react-icons/fa';
import Head from 'next/head';
import Link from 'next/link';
-import useRedirectWhenLoggedIn from '@/hooks/useRedirectIfLoggedIn';
+import useRedirectWhenLoggedIn from '@/hooks/auth/useRedirectIfLoggedIn';
const LoginPage: NextPage = () => {
useRedirectWhenLoggedIn();
diff --git a/src/pages/register/index.tsx b/src/pages/register/index.tsx
index 9559b45..d67e25b 100644
--- a/src/pages/register/index.tsx
+++ b/src/pages/register/index.tsx
@@ -1,7 +1,7 @@
import RegisterUserForm from '@/components/RegisterUserForm';
import FormPageLayout from '@/components/ui/forms/FormPageLayout';
-import useRedirectWhenLoggedIn from '@/hooks/useRedirectIfLoggedIn';
+import useRedirectWhenLoggedIn from '@/hooks/auth/useRedirectIfLoggedIn';
import { NextPage } from 'next';
import Head from 'next/head';
import { BiUser } from 'react-icons/bi';
diff --git a/src/pages/user/current.tsx b/src/pages/user/current.tsx
index c152068..e39acf2 100644
--- a/src/pages/user/current.tsx
+++ b/src/pages/user/current.tsx
@@ -1,10 +1,10 @@
import Spinner from '@/components/ui/Spinner';
-import withPageAuthRequired from '@/getServerSideProps/withPageAuthRequired';
+import withPageAuthRequired from '@/util/withPageAuthRequired';
import UserContext from '@/contexts/userContext';
import { GetServerSideProps, NextPage } from 'next';
import { useContext } from 'react';
-import useMediaQuery from '@/hooks/useMediaQuery';
+import useMediaQuery from '@/hooks/utilities/useMediaQuery';
const ProtectedPage: NextPage = () => {
const { user, isLoading } = useContext(UserContext);
diff --git a/src/prisma/migrations/20230502225418_/migration.sql b/src/prisma/migrations/20230502225418_/migration.sql
index 990f476..bf26619 100644
--- a/src/prisma/migrations/20230502225418_/migration.sql
+++ b/src/prisma/migrations/20230502225418_/migration.sql
@@ -10,10 +10,8 @@ CREATE TABLE "User" (
"updatedAt" TIMESTAMPTZ(3),
"isAccountVerified" BOOLEAN NOT NULL DEFAULT false,
"dateOfBirth" TIMESTAMP(3) NOT NULL,
-
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-
-- CreateTable
CREATE TABLE "BeerPost" (
"id" TEXT NOT NULL,
@@ -26,10 +24,8 @@ CREATE TABLE "BeerPost" (
"typeId" TEXT NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
-
CONSTRAINT "BeerPost_pkey" PRIMARY KEY ("id")
);
-
-- CreateTable
CREATE TABLE "BeerPostLike" (
"id" TEXT NOT NULL,
@@ -37,10 +33,8 @@ CREATE TABLE "BeerPostLike" (
"likedById" TEXT NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
-
CONSTRAINT "BeerPostLike_pkey" PRIMARY KEY ("id")
);
-
-- CreateTable
CREATE TABLE "BreweryPostLike" (
"id" TEXT NOT NULL,
@@ -48,10 +42,8 @@ CREATE TABLE "BreweryPostLike" (
"likedById" TEXT NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
-
CONSTRAINT "BreweryPostLike_pkey" PRIMARY KEY ("id")
);
-
-- CreateTable
CREATE TABLE "BeerComment" (
"id" TEXT NOT NULL,
@@ -61,10 +53,8 @@ CREATE TABLE "BeerComment" (
"content" TEXT NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
-
CONSTRAINT "BeerComment_pkey" PRIMARY KEY ("id")
);
-
-- CreateTable
CREATE TABLE "BeerType" (
"id" TEXT NOT NULL,
@@ -72,23 +62,19 @@ CREATE TABLE "BeerType" (
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
"postedById" TEXT NOT NULL,
-
CONSTRAINT "BeerType_pkey" PRIMARY KEY ("id")
);
-
-- CreateTable
CREATE TABLE "Location" (
"id" TEXT NOT NULL,
"city" TEXT NOT NULL,
"stateOrProvince" TEXT,
"country" TEXT,
- "coordinates" DOUBLE PRECISION[],
+ "coordinates" DOUBLE PRECISION [],
"address" TEXT NOT NULL,
"postedById" TEXT NOT NULL,
-
CONSTRAINT "Location_pkey" PRIMARY KEY ("id")
);
-
-- CreateTable
CREATE TABLE "BreweryPost" (
"id" TEXT NOT NULL,
@@ -99,10 +85,8 @@ CREATE TABLE "BreweryPost" (
"updatedAt" TIMESTAMPTZ(3),
"postedById" TEXT NOT NULL,
"dateEstablished" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
-
CONSTRAINT "BreweryPost_pkey" PRIMARY KEY ("id")
);
-
-- CreateTable
CREATE TABLE "BreweryComment" (
"id" TEXT NOT NULL,
@@ -112,10 +96,8 @@ CREATE TABLE "BreweryComment" (
"content" TEXT NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
-
CONSTRAINT "BreweryComment_pkey" PRIMARY KEY ("id")
);
-
-- CreateTable
CREATE TABLE "BeerImage" (
"id" TEXT NOT NULL,
@@ -126,10 +108,8 @@ CREATE TABLE "BeerImage" (
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
"postedById" TEXT NOT NULL,
-
CONSTRAINT "BeerImage_pkey" PRIMARY KEY ("id")
);
-
-- CreateTable
CREATE TABLE "BreweryImage" (
"id" TEXT NOT NULL,
@@ -140,72 +120,68 @@ CREATE TABLE "BreweryImage" (
"caption" TEXT NOT NULL,
"alt" TEXT NOT NULL,
"postedById" TEXT NOT NULL,
-
CONSTRAINT "BreweryImage_pkey" PRIMARY KEY ("id")
);
-
-- CreateIndex
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
-
-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
-
-- CreateIndex
CREATE UNIQUE INDEX "BreweryPost_locationId_key" ON "BreweryPost"("locationId");
-
-- AddForeignKey
-ALTER TABLE "BeerPost" ADD CONSTRAINT "BeerPost_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BeerPost"
+ADD CONSTRAINT "BeerPost_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BeerPost" ADD CONSTRAINT "BeerPost_breweryId_fkey" FOREIGN KEY ("breweryId") REFERENCES "BreweryPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BeerPost"
+ADD CONSTRAINT "BeerPost_breweryId_fkey" FOREIGN KEY ("breweryId") REFERENCES "BreweryPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BeerPost" ADD CONSTRAINT "BeerPost_typeId_fkey" FOREIGN KEY ("typeId") REFERENCES "BeerType"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BeerPost"
+ADD CONSTRAINT "BeerPost_typeId_fkey" FOREIGN KEY ("typeId") REFERENCES "BeerType"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BeerPostLike" ADD CONSTRAINT "BeerPostLike_beerPostId_fkey" FOREIGN KEY ("beerPostId") REFERENCES "BeerPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+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_likedById_fkey" FOREIGN KEY ("likedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BeerPostLike"
+ADD CONSTRAINT "BeerPostLike_likedById_fkey" FOREIGN KEY ("likedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BreweryPostLike" ADD CONSTRAINT "BreweryPostLike_breweryPostId_fkey" FOREIGN KEY ("breweryPostId") REFERENCES "BreweryPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BreweryPostLike"
+ADD CONSTRAINT "BreweryPostLike_breweryPostId_fkey" FOREIGN KEY ("breweryPostId") REFERENCES "BreweryPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BreweryPostLike" ADD CONSTRAINT "BreweryPostLike_likedById_fkey" FOREIGN KEY ("likedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BreweryPostLike"
+ADD CONSTRAINT "BreweryPostLike_likedById_fkey" FOREIGN KEY ("likedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BeerComment" ADD CONSTRAINT "BeerComment_beerPostId_fkey" FOREIGN KEY ("beerPostId") REFERENCES "BeerPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BeerComment"
+ADD CONSTRAINT "BeerComment_beerPostId_fkey" FOREIGN KEY ("beerPostId") REFERENCES "BeerPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BeerComment" ADD CONSTRAINT "BeerComment_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BeerComment"
+ADD CONSTRAINT "BeerComment_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BeerType" ADD CONSTRAINT "BeerType_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BeerType"
+ADD CONSTRAINT "BeerType_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "Location" ADD CONSTRAINT "Location_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "Location"
+ADD CONSTRAINT "Location_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BreweryPost" ADD CONSTRAINT "BreweryPost_locationId_fkey" FOREIGN KEY ("locationId") REFERENCES "Location"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-
+ALTER TABLE "BreweryPost"
+ADD CONSTRAINT "BreweryPost_locationId_fkey" FOREIGN KEY ("locationId") REFERENCES "Location"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BreweryPost" ADD CONSTRAINT "BreweryPost_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BreweryPost"
+ADD CONSTRAINT "BreweryPost_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BreweryComment" ADD CONSTRAINT "BreweryComment_breweryPostId_fkey" FOREIGN KEY ("breweryPostId") REFERENCES "BreweryPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BreweryComment"
+ADD CONSTRAINT "BreweryComment_breweryPostId_fkey" FOREIGN KEY ("breweryPostId") REFERENCES "BreweryPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BreweryComment" ADD CONSTRAINT "BreweryComment_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BreweryComment"
+ADD CONSTRAINT "BreweryComment_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BeerImage" ADD CONSTRAINT "BeerImage_beerPostId_fkey" FOREIGN KEY ("beerPostId") REFERENCES "BeerPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BeerImage"
+ADD CONSTRAINT "BeerImage_beerPostId_fkey" FOREIGN KEY ("beerPostId") REFERENCES "BeerPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BeerImage" ADD CONSTRAINT "BeerImage_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BeerImage"
+ADD CONSTRAINT "BeerImage_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BreweryImage" ADD CONSTRAINT "BreweryImage_breweryPostId_fkey" FOREIGN KEY ("breweryPostId") REFERENCES "BreweryPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-
+ALTER TABLE "BreweryImage"
+ADD CONSTRAINT "BreweryImage_breweryPostId_fkey" FOREIGN KEY ("breweryPostId") REFERENCES "BreweryPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
-ALTER TABLE "BreweryImage" ADD CONSTRAINT "BreweryImage_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+ALTER TABLE "BreweryImage"
+ADD CONSTRAINT "BreweryImage_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
\ No newline at end of file
diff --git a/src/prisma/schema.prisma b/src/prisma/schema.prisma
index 25d46ef..e5ce2b4 100644
--- a/src/prisma/schema.prisma
+++ b/src/prisma/schema.prisma
@@ -6,10 +6,9 @@ generator client {
}
datasource db {
- provider = "postgresql"
- url = env("POSTGRES_PRISMA_URL") // uses connection pooling
- directUrl = env("POSTGRES_URL_NON_POOLING") // uses a direct connection
- shadowDatabaseUrl = env("POSTGRES_URL_NON_POOLING") // used for migrations
+ provider = "postgresql"
+ url = env("POSTGRES_PRISMA_URL") // uses connection pooling
+ directUrl = env("POSTGRES_URL_NON_POOLING") // uses a direct connection
}
model User {
diff --git a/src/prisma/seed/clean/cleanDatabase.ts b/src/prisma/seed/clean/cleanDatabase.ts
index af0135a..f62e49d 100644
--- a/src/prisma/seed/clean/cleanDatabase.ts
+++ b/src/prisma/seed/clean/cleanDatabase.ts
@@ -2,15 +2,26 @@ import DBClient from '../../DBClient';
const cleanDatabase = async () => {
const prisma = DBClient.instance;
- await prisma.$executeRaw`TRUNCATE TABLE "User" CASCADE`;
- await prisma.$executeRaw`TRUNCATE TABLE "BeerPost" CASCADE`;
- await prisma.$executeRaw`TRUNCATE TABLE "BeerType" CASCADE`;
- await prisma.$executeRaw`TRUNCATE TABLE "BreweryPost" CASCADE`;
- await prisma.$executeRaw`TRUNCATE TABLE "BeerComment" CASCADE`;
- await prisma.$executeRaw`TRUNCATE TABLE "BreweryComment" CASCADE`;
- await prisma.$executeRaw`TRUNCATE TABLE "BeerPostLike" CASCADE`;
- await prisma.$executeRaw`TRUNCATE TABLE "BeerImage" CASCADE`;
- await prisma.$executeRaw`TRUNCATE TABLE "BreweryImage" CASCADE`;
+
+ /**
+ * Truncate all tables in the database.
+ *
+ * Declares a cursor called statements that contains all table names in the public
+ * schema then loops through each table and truncates it.
+ */
+ await prisma.$executeRaw`
+ DO $$
+ DECLARE
+ statements CURSOR FOR
+ SELECT tablename FROM pg_tables
+ WHERE schemaname = 'public';
+ BEGIN
+ FOR statement IN statements LOOP
+ EXECUTE 'TRUNCATE TABLE ' || quote_ident(statement.tablename) || ' CASCADE;';
+ END LOOP;
+ END;
+ $$ LANGUAGE plpgsql;
+ `;
await prisma.$disconnect();
};
diff --git a/src/getServerSideProps/withPageAuthRequired.ts b/src/util/withPageAuthRequired.ts
similarity index 100%
rename from src/getServerSideProps/withPageAuthRequired.ts
rename to src/util/withPageAuthRequired.ts