mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 10:42:08 +00:00
Update: beer post form now connected to a specific brewery.
This commit eliminates the brewery selector in the create beer post form, and reroutes the form page to /breweries/[id]/beers/create. This commit also introduces the use of turbopack for `next dev`.
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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,16 +28,19 @@ 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>
|
||||
<h1 className="text-2xl font-bold lg:text-4xl">{breweryPost.name}</h1>
|
||||
<h2 className="text-lg font-semibold lg:text-2xl">
|
||||
Located in
|
||||
{` ${breweryPost.location.city}, ${
|
||||
breweryPost.location.stateOrProvince || breweryPost.location.country
|
||||
}`}
|
||||
</h2>
|
||||
<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">
|
||||
Located in
|
||||
{` ${breweryPost.location.city}, ${
|
||||
breweryPost.location.stateOrProvince || breweryPost.location.country
|
||||
}`}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="italic">
|
||||
{' posted by '}
|
||||
|
||||
@@ -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,48 +80,24 @@ 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>
|
||||
</FormInfo>
|
||||
<FormSegment>
|
||||
<FormSelect
|
||||
disabled={isSubmitting}
|
||||
formRegister={register('typeId')}
|
||||
error={!!errors.typeId}
|
||||
id="typeId"
|
||||
options={types.map((beerType) => ({
|
||||
value: beerType.id,
|
||||
text: beerType.name,
|
||||
}))}
|
||||
placeholder="Beer type"
|
||||
message="Pick a beer type"
|
||||
/>
|
||||
</FormSegment>
|
||||
</div>
|
||||
</div>
|
||||
<FormInfo>
|
||||
<FormLabel htmlFor="typeId">Type</FormLabel>
|
||||
<FormError>{errors.typeId?.message}</FormError>
|
||||
</FormInfo>
|
||||
<FormSegment>
|
||||
<FormSelect
|
||||
disabled={isSubmitting}
|
||||
formRegister={register('typeId')}
|
||||
error={!!errors.typeId}
|
||||
id="typeId"
|
||||
options={types.map((beerType) => ({
|
||||
value: beerType.id,
|
||||
text: beerType.name,
|
||||
}))}
|
||||
placeholder="Beer type"
|
||||
message="Pick a beer type"
|
||||
/>
|
||||
</FormSegment>
|
||||
|
||||
<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>
|
||||
|
||||
|
||||
@@ -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' },
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -47,16 +47,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 && (
|
||||
|
||||
@@ -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();
|
||||
const beerTypes = await DBClient.instance.beerType.findMany();
|
||||
export const getServerSideProps = withPageAuthRequired<CreateBeerPageProps>(
|
||||
async (context) => {
|
||||
const id = context.params?.id as string;
|
||||
|
||||
return {
|
||||
props: {
|
||||
breweries: JSON.parse(JSON.stringify(breweryPosts)),
|
||||
types: JSON.parse(JSON.stringify(beerTypes)),
|
||||
},
|
||||
};
|
||||
});
|
||||
const breweryPost = await getBreweryPostById(id);
|
||||
|
||||
const beerTypes = await DBClient.instance.beerType.findMany();
|
||||
|
||||
return {
|
||||
props: {
|
||||
brewery: JSON.parse(JSON.stringify(breweryPost)),
|
||||
types: JSON.parse(JSON.stringify(beerTypes)),
|
||||
},
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
export default CreateBeerPost;
|
||||
Reference in New Issue
Block a user