scaffold create/edit beer form, scaffold beer page

This commit is contained in:
Aaron William Po
2023-01-23 20:13:25 -05:00
parent f08731de17
commit 972846f5a8
29 changed files with 776 additions and 70 deletions

View File

@@ -2,16 +2,120 @@ import { GetServerSideProps, NextPage } from 'next';
import BeerPostQueryResult from '@/services/BeerPost/types/BeerPostQueryResult';
import getBeerPostById from '@/services/BeerPost/getBeerPostById';
import Layout from '@/components/Layout';
import Head from 'next/head';
import Link from 'next/link';
import formatDistanceStrict from 'date-fns/formatDistanceStrict';
import { useState } from 'react';
import { FaRegThumbsUp, FaThumbsUp } from 'react-icons/fa';
interface BeerPageProps {
beerPost: BeerPostQueryResult;
}
const BeerInfoHeader: React.FC<{ beerPost: BeerPostQueryResult }> = ({ beerPost }) => {
const createdAtDate = new Date(beerPost.createdAt);
const timeDistance = formatDistanceStrict(createdAtDate, Date.now());
const [isLiked, setIsLiked] = useState(false);
return (
<div className="card bg-base-300">
<div className="card-body">
<h1 className="text-4xl font-bold">{beerPost.name}</h1>
<h2 className="text-2xl font-semibold">
by{' '}
<Link
href={`/breweries/${beerPost.brewery.id}`}
className="link-hover link text-2xl font-semibold"
>
{beerPost.brewery.name}
</Link>
</h2>
<h3 className="italic">
posted by{' '}
<Link href={`/users/${beerPost.postedBy.id}`} className="link-hover link">
{beerPost.postedBy.username}
</Link>
{` ${timeDistance}`} ago
</h3>
<p>{beerPost.description}</p>
<div className="flex justify-between">
<div>
<div className="mb-1">
<Link
className="text-lg font-medium"
href={`/beers/types/${beerPost.type.id}`}
>
{beerPost.type.name}
</Link>
</div>
<div>
<span className="mr-4 text-lg font-medium">{beerPost.abv}% ABV</span>
<span className="text-lg font-medium">{beerPost.ibu} IBU</span>
</div>
</div>
<div className="card-actions">
<button
type="button"
className={`btn gap-2 rounded-2xl ${
!isLiked ? 'btn-ghost outline' : 'btn-primary'
}`}
onClick={() => {
setIsLiked(!isLiked);
}}
>
{isLiked ? (
<>
<FaThumbsUp className="text-2xl" />
<span>Liked</span>
</>
) : (
<>
<FaRegThumbsUp className="text-2xl" />
<span>Like</span>
</>
)}
</button>
</div>
</div>
</div>
</div>
);
};
const BeerByIdPage: NextPage<BeerPageProps> = ({ beerPost }) => {
return (
<Layout>
<Head>
<title>{beerPost.name}</title>
<meta name="description" content={beerPost.description} />
</Head>
<main>
<h1 className="text-3xl font-bold underline">{beerPost.name}</h1>
{beerPost.beerImages[0] && (
<img
src={beerPost.beerImages[0].url}
className="h-[42rem] w-full object-cover"
/>
)}
<div className="my-12 flex w-full items-center justify-center ">
<div className="w-10/12 space-y-3">
<BeerInfoHeader beerPost={beerPost} />
<div className="mt-4 flex space-x-3">
<div className="w-[60%] space-y-3">
<div className="card h-[22rem] bg-base-300"></div>
<div className="card h-[44rem] bg-base-300"></div>
</div>
<div className="w-[40%]">
<div className="card h-full bg-base-300"></div>
</div>
</div>
</div>
</div>
</main>
</Layout>
);

32
pages/beers/create.tsx Normal file
View File

@@ -0,0 +1,32 @@
import BeerForm from '@/components/BeerForm';
import Layout from '@/components/Layout';
import getAllBreweryPosts from '@/services/BreweryPost/getAllBreweryPosts';
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
import { NextPage } from 'next';
interface CreateBeerPageProps {
breweries: BreweryPostQueryResult[];
}
const Create: NextPage<CreateBeerPageProps> = ({ breweries }) => {
return (
<Layout>
<div className="align-center flex h-full flex-col items-center justify-center">
<div className="w-8/12">
<BeerForm type="create" breweries={breweries} />
</div>
</div>
</Layout>
);
};
export const getServerSideProps = async () => {
const breweryPosts = await getAllBreweryPosts();
return {
props: {
breweries: breweryPosts,
},
};
};
export default Create;

View File

@@ -7,6 +7,7 @@ import { useRouter } from 'next/router';
import DBClient from '@/prisma/DBClient';
import Layout from '@/components/Layout';
import { FC } from 'react';
import Image from 'next/image';
interface BeerPageProps {
initialBeerPosts: BeerPostQueryResult[];
@@ -48,8 +49,14 @@ const Pagination: FC<PaginationProps> = ({ pageCount, pageNum }) => {
const BeerCard: FC<{ post: BeerPostQueryResult }> = ({ post }) => {
return (
<div className="card h-52 bg-base-200 p-6" key={post.id}>
<div className="card-content space-y-3">
<div className="card bg-base-300" key={post.id}>
<figure className="card-image h-96">
{post.beerImages.length > 0 && (
<Image src={post.beerImages[0].url} alt={post.name} width="1029" height="110" />
)}
</figure>
<div className="card-body space-y-3">
<div>
<h2 className="text-3xl font-bold">
<Link href={`/beers/${post.id}`}>{post.name}</Link>
@@ -70,10 +77,9 @@ const BeerPage: NextPage<BeerPageProps> = ({ initialBeerPosts, pageCount }) => {
const pageNum = parseInt(query.page_num as string, 10) || 1;
return (
<Layout>
<div className="flex items-center justify-center">
<main className="mt-10 flex w-8/12 flex-col space-y-4">
<h1 className="card-title text-5xl font-bold">Beer Posts</h1>
<div className="space-y-4">
<div className="flex items-center justify-center bg-base-100">
<main className="mt-10 flex w-10/12 flex-col space-y-4">
<div className="grid gap-5 md:grid-cols-2 xl:grid-cols-3">
{initialBeerPosts.map((post) => {
return <BeerCard post={post} key={post.id} />;
})}
@@ -90,7 +96,7 @@ export const getServerSideProps: GetServerSideProps<BeerPageProps> = async (cont
const pageNumber = parseInt(query.page_num as string, 10) || 1;
const pageSize = 9;
const pageSize = 24;
const numberOfPosts = await DBClient.instance.beerPost.count();
const pageCount = numberOfPosts ? Math.ceil(numberOfPosts / pageSize) : 0;