Merge pull request #40 from aaronpo97/create-beer-updates

Update: beer post form now connected to a specific brewery
This commit is contained in:
Aaron Po
2023-05-12 20:27:42 -04:00
committed by GitHub
8 changed files with 78 additions and 106 deletions

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next dev --turbo",
"build": "next build",
"start": "next start",
"lint": "next lint",

View File

@@ -4,6 +4,7 @@ import Link from 'next/link';
import { FC } from 'react';
import { useInView } from 'react-intersection-observer';
import { z } from 'zod';
import { FaPlus } from 'react-icons/fa';
import BeerRecommendationLoadingComponent from '../BeerById/BeerRecommendationLoadingComponent';
interface BreweryCommentsSectionProps {
@@ -31,7 +32,21 @@ const BreweryBeersSection: FC<BreweryCommentsSectionProps> = ({ breweryPost }) =
<div className="card">
<div className="card-body">
<>
<h3 className="text-2xl font-bold">Brews</h3>
<div className="my-2 flex flex-row items-center justify-between">
<div>
<h3 className="text-3xl font-bold">Brews</h3>
</div>
<div>
<Link
className={`btn-ghost btn-sm btn gap-2 rounded-2xl outline`}
href={`/breweries/${breweryPost.id}/beers/create`}
>
<FaPlus className="text-xl" />
Add Beer
</Link>
</div>
</div>
{!!beerPosts.length && (
<div className="space-y-5">
{beerPosts.map((beerPost, index) => {

View File

@@ -4,9 +4,11 @@ import useTimeDistance from '@/hooks/utilities/useTimeDistance';
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
import { format } from 'date-fns';
import { FC, useContext } from 'react';
import { Link } from 'react-daisyui';
import { FaRegEdit } from 'react-icons/fa';
import { z } from 'zod';
import Link from 'next/link';
import BreweryPostLikeButton from '../BreweryIndex/BreweryPostLikeButton';
interface BreweryInfoHeaderProps {
@@ -26,7 +28,8 @@ const BreweryInfoHeader: FC<BreweryInfoHeaderProps> = ({ breweryPost }) => {
<article className="card flex flex-col justify-center bg-base-300">
<div className="card-body">
<header className="flex justify-between">
<div className="space-y-2">
<div className="w-full space-y-2">
<div className="flex w-full flex-row justify-between">
<div>
<h1 className="text-2xl font-bold lg:text-4xl">{breweryPost.name}</h1>
<h2 className="text-lg font-semibold lg:text-2xl">
@@ -36,6 +39,8 @@ const BreweryInfoHeader: FC<BreweryInfoHeaderProps> = ({ breweryPost }) => {
}`}
</h2>
</div>
</div>
<div>
<h3 className="italic">
{' posted by '}

View File

@@ -20,7 +20,7 @@ import FormTextArea from './ui/forms/FormTextArea';
import FormTextInput from './ui/forms/FormTextInput';
interface BeerFormProps {
breweries: z.infer<typeof BreweryPostQueryResult>[];
brewery: z.infer<typeof BreweryPostQueryResult>;
types: BeerType[];
}
@@ -29,13 +29,14 @@ const CreateBeerPostWithImagesValidationSchema = CreateBeerPostValidationSchema.
);
const CreateBeerPostForm: FunctionComponent<BeerFormProps> = ({
breweries = [],
types = [],
brewery,
}) => {
const { register, handleSubmit, formState } = useForm<
z.infer<typeof CreateBeerPostWithImagesValidationSchema>
>({
resolver: zodResolver(CreateBeerPostWithImagesValidationSchema),
defaultValues: { breweryId: brewery.id },
});
const { errors, isSubmitting } = formState;
@@ -48,23 +49,9 @@ const CreateBeerPostForm: FunctionComponent<BeerFormProps> = ({
return;
}
const { breweryId, typeId, name, abv, ibu, description } = data;
try {
const response = await sendCreateBeerPostRequest({
breweryId,
typeId,
name,
abv,
ibu,
description,
});
await sendUploadBeerImagesRequest({
beerPost: response,
images: data.images,
});
const response = await sendCreateBeerPostRequest(data);
await sendUploadBeerImagesRequest({ beerPost: response, images: data.images });
router.push(`/beers/${response.id}`);
} catch (e) {
if (!(e instanceof Error)) {
@@ -93,28 +80,6 @@ const CreateBeerPostForm: FunctionComponent<BeerFormProps> = ({
/>
</FormSegment>
<div className="flex flex-wrap">
<div className="mb-2 w-full md:mb-0 md:w-1/2 md:pr-3">
<FormInfo>
<FormLabel htmlFor="breweryId">Brewery</FormLabel>
<FormError>{errors.breweryId?.message}</FormError>
</FormInfo>
<FormSegment>
<FormSelect
disabled={isSubmitting}
formRegister={register('breweryId')}
error={!!errors.breweryId}
id="breweryId"
options={breweries.map((brewery) => ({
value: brewery.id,
text: brewery.name,
}))}
placeholder="Brewery"
message="Pick a brewery"
/>
</FormSegment>
</div>
<div className="mb-2 w-full md:mb-0 md:w-1/2 md:pl-3">
<FormInfo>
<FormLabel htmlFor="typeId">Type</FormLabel>
<FormError>{errors.typeId?.message}</FormError>
@@ -133,8 +98,6 @@ const CreateBeerPostForm: FunctionComponent<BeerFormProps> = ({
message="Pick a beer type"
/>
</FormSegment>
</div>
</div>
<div className="flex flex-wrap md:mb-3">
<div className="mb-2 w-full md:mb-0 md:w-1/2 md:pr-3">
@@ -192,6 +155,7 @@ const CreateBeerPostForm: FunctionComponent<BeerFormProps> = ({
{...register('images')}
multiple
className="file-input-bordered file-input w-full"
disabled={isSubmitting}
/>
</FormSegment>

View File

@@ -34,8 +34,8 @@ const useNavbar = () => {
/** These pages are accessible to both authenticated and unauthenticated users. */
const otherPages: readonly Page[] = [
{ slug: '/beers', name: 'Beers' },
{ slug: '/breweries', name: 'Breweries' },
{ slug: '/beers', name: 'Beers' },
];
/**

View File

@@ -1,21 +1,14 @@
import { NextPage } from 'next';
import BeerCard from '@/components/BeerIndex/BeerCard';
import Head from 'next/head';
import Link from 'next/link';
import UserContext from '@/contexts/userContext';
import { MutableRefObject, useContext, useRef } from 'react';
import { MutableRefObject, useRef } from 'react';
import { useInView } from 'react-intersection-observer';
import Spinner from '@/components/ui/Spinner';
import useBeerPosts from '@/hooks/data-fetching/beer-posts/useBeerPosts';
import { FaArrowUp, FaPlus } from 'react-icons/fa';
import { FaArrowUp } from 'react-icons/fa';
import LoadingCard from '@/components/ui/LoadingCard';
const BeerPage: NextPage = () => {
const { user } = useContext(UserContext);
const PAGE_SIZE = 6;
const { beerPosts, setSize, size, isLoading, isLoadingMore, isAtEnd } = useBeerPosts({
@@ -47,16 +40,6 @@ const BeerPage: NextPage = () => {
<h1 className="text-4xl font-bold lg:text-6xl">The Biergarten App</h1>
<h2 className="text-2xl font-bold lg:text-4xl">Beers</h2>
</div>
{!!user && (
<div
className="tooltip tooltip-left h-full"
data-tip="Create a new beer post"
>
<Link href="/beers/create" className="btn-ghost btn-sm btn">
<FaPlus />
</Link>
</div>
)}
</header>
<div className="grid gap-6 xl:grid-cols-2">
{!!beerPosts.length && !isLoading && (

View File

@@ -3,19 +3,19 @@ import FormPageLayout from '@/components/ui/forms/FormPageLayout';
import withPageAuthRequired from '@/util/withPageAuthRequired';
import DBClient from '@/prisma/DBClient';
import getAllBreweryPosts from '@/services/BreweryPost/getAllBreweryPosts';
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
import { BeerType } from '@prisma/client';
import { NextPage } from 'next';
import { BiBeer } from 'react-icons/bi';
import { z } from 'zod';
import getBreweryPostById from '@/services/BreweryPost/getBreweryPostById';
interface CreateBeerPageProps {
breweries: z.infer<typeof BreweryPostQueryResult>[];
brewery: z.infer<typeof BreweryPostQueryResult>;
types: BeerType[];
}
const CreateBeerPost: NextPage<CreateBeerPageProps> = ({ breweries, types }) => {
const CreateBeerPost: NextPage<CreateBeerPageProps> = ({ brewery, types }) => {
return (
<FormPageLayout
headingText="Create a new beer"
@@ -23,21 +23,26 @@ const CreateBeerPost: NextPage<CreateBeerPageProps> = ({ breweries, types }) =>
backLink="/beers"
backLinkText="Back to beers"
>
<CreateBeerPostForm breweries={breweries} types={types} />
<CreateBeerPostForm brewery={brewery} types={types} />
</FormPageLayout>
);
};
export const getServerSideProps = withPageAuthRequired<CreateBeerPageProps>(async () => {
const breweryPosts = await getAllBreweryPosts();
export const getServerSideProps = withPageAuthRequired<CreateBeerPageProps>(
async (context) => {
const id = context.params?.id as string;
const breweryPost = await getBreweryPostById(id);
const beerTypes = await DBClient.instance.beerType.findMany();
return {
props: {
breweries: JSON.parse(JSON.stringify(breweryPosts)),
brewery: JSON.parse(JSON.stringify(breweryPost)),
types: JSON.parse(JSON.stringify(beerTypes)),
},
};
});
},
);
export default CreateBeerPost;