mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 10:42:08 +00:00
Add date established to brewery page
This commit is contained in:
@@ -46,7 +46,7 @@ const BeerCard: FC<{ post: z.infer<typeof beerPostQueryResult> }> = ({ post }) =
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
liked by {likeCount} users
|
<span>liked by {likeCount} users</span>
|
||||||
{user && <BeerPostLikeButton beerPostId={post.id} mutateCount={mutate} />}
|
{user && <BeerPostLikeButton beerPostId={post.id} mutateCount={mutate} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import UserContext from '@/contexts/userContext';
|
|||||||
import useGetBreweryPostLikeCount from '@/hooks/useGetBreweryPostLikeCount';
|
import useGetBreweryPostLikeCount from '@/hooks/useGetBreweryPostLikeCount';
|
||||||
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
||||||
import { FC, useContext } from 'react';
|
import { FC, useContext } from 'react';
|
||||||
import { Link } from 'react-daisyui';
|
import Link from 'next/link';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import BreweryPostLikeButton from './BreweryPostLikeButton';
|
import BreweryPostLikeButton from './BreweryPostLikeButton';
|
||||||
@@ -24,17 +24,26 @@ const BreweryCard: FC<{ brewery: z.infer<typeof BreweryPostQueryResult> }> = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</figure>
|
</figure>
|
||||||
<div className="card-body space-y-3">
|
<div className="card-body">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-3xl font-bold">
|
<h2 className="mb-2 text-2xl font-bold lg:text-3xl">
|
||||||
<Link href={`/breweries/${brewery.id}`}>{brewery.name}</Link>
|
<Link href={`/breweries/${brewery.id}`} className="link-hover link">
|
||||||
|
{brewery.name}
|
||||||
|
</Link>
|
||||||
</h2>
|
</h2>
|
||||||
<h3 className="text-xl font-semibold">{brewery.location}</h3>
|
<h3 className="text-xl font-normal lg:text-2xl">
|
||||||
|
located in {brewery.location}
|
||||||
|
</h3>
|
||||||
|
<h4 className="text-lg lg:text-xl">
|
||||||
|
est. {brewery.dateEstablished.getFullYear()}
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span>liked by {likeCount} users</span>
|
||||||
|
{user && (
|
||||||
|
<BreweryPostLikeButton breweryPostId={brewery.id} mutateCount={mutate} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
liked by {likeCount} users
|
|
||||||
{user && (
|
|
||||||
<BreweryPostLikeButton breweryPostId={brewery.id} mutateCount={mutate} />
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -34,14 +34,17 @@ const BeerPage: NextPage = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
<title>Beer</title>
|
<title>Beers | The Biergarten App</title>
|
||||||
<meta name="description" content="Beer posts" />
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Find beers made by breweries near you and around the world."
|
||||||
|
/>
|
||||||
</Head>
|
</Head>
|
||||||
<div className="flex items-center justify-center bg-base-100" ref={pageRef}>
|
<div className="flex items-center justify-center bg-base-100" ref={pageRef}>
|
||||||
<div className="my-10 flex w-10/12 flex-col space-y-4 lg:w-8/12 2xl:w-7/12">
|
<div className="my-10 flex w-10/12 flex-col space-y-4 lg:w-8/12 2xl:w-7/12">
|
||||||
<header className="my-10 flex justify-between lg:flex-row">
|
<header className="my-10 flex justify-between lg:flex-row">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-4xl font-bold lg:text-6xl">The Biergarten Index</h1>
|
<h1 className="text-4xl font-bold lg:text-6xl">The Biergarten App</h1>
|
||||||
<h2 className="text-2xl font-bold lg:text-4xl">Beers</h2>
|
<h2 className="text-2xl font-bold lg:text-4xl">Beers</h2>
|
||||||
</div>
|
</div>
|
||||||
{!!user && (
|
{!!user && (
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import UserContext from '@/contexts/userContext';
|
|||||||
import useBreweryPosts from '@/hooks/useBreweryPosts';
|
import useBreweryPosts from '@/hooks/useBreweryPosts';
|
||||||
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
||||||
import { NextPage } from 'next';
|
import { NextPage } from 'next';
|
||||||
|
import Head from 'next/head';
|
||||||
import { useContext, MutableRefObject, useRef } from 'react';
|
import { useContext, MutableRefObject, useRef } from 'react';
|
||||||
import { Link } from 'react-daisyui';
|
import { Link } from 'react-daisyui';
|
||||||
import { FaPlus, FaArrowUp } from 'react-icons/fa';
|
import { FaPlus, FaArrowUp } from 'react-icons/fa';
|
||||||
@@ -34,81 +35,90 @@ const BreweryPage: NextPage<BreweryPageProps> = () => {
|
|||||||
|
|
||||||
const pageRef: MutableRefObject<HTMLDivElement | null> = useRef(null);
|
const pageRef: MutableRefObject<HTMLDivElement | null> = useRef(null);
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center bg-base-100" ref={pageRef}>
|
<>
|
||||||
<div className="my-10 flex w-10/12 flex-col space-y-4 lg:w-8/12 2xl:w-7/12">
|
<Head>
|
||||||
<header className="my-10 flex justify-between lg:flex-row">
|
<title>Breweries</title>
|
||||||
<div>
|
<meta
|
||||||
<h1 className="text-4xl font-bold lg:text-6xl">The Biergarten Index</h1>
|
name="description"
|
||||||
<h2 className="text-2xl font-bold lg:text-4xl">Breweries</h2>
|
content="Find breweries near you and around the world."
|
||||||
|
/>
|
||||||
|
</Head>
|
||||||
|
<div className="flex items-center justify-center bg-base-100" ref={pageRef}>
|
||||||
|
<div className="my-10 flex w-10/12 flex-col space-y-4 lg:w-8/12 2xl:w-7/12">
|
||||||
|
<header className="my-10 flex justify-between lg:flex-row">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-4xl font-bold lg:text-6xl">The Biergarten App</h1>
|
||||||
|
<h2 className="text-2xl font-bold lg:text-4xl">Breweries</h2>
|
||||||
|
</div>
|
||||||
|
{!!user && (
|
||||||
|
<div
|
||||||
|
className="tooltip tooltip-left h-full"
|
||||||
|
data-tip="Create a new brewery post"
|
||||||
|
>
|
||||||
|
<Link href="/breweries/create" className="btn-ghost btn-sm btn">
|
||||||
|
<FaPlus />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</header>
|
||||||
|
<div className="grid gap-6 xl:grid-cols-2">
|
||||||
|
{!!breweryPosts.length && !isLoading && (
|
||||||
|
<>
|
||||||
|
{breweryPosts.map((breweryPost) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={breweryPost.id}
|
||||||
|
ref={
|
||||||
|
breweryPosts[breweryPosts.length - 1] === breweryPost
|
||||||
|
? lastBreweryPostRef
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<BreweryCard brewery={breweryPost} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{(isLoading || isLoadingMore) && (
|
||||||
|
<>
|
||||||
|
{Array.from({ length: PAGE_SIZE }, (_, i) => (
|
||||||
|
<LoadingCard key={i} />
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!!user && (
|
|
||||||
<div
|
{(isLoading || isLoadingMore) && (
|
||||||
className="tooltip tooltip-left h-full"
|
<div className="flex h-32 w-full items-center justify-center">
|
||||||
data-tip="Create a new brewery post"
|
<Spinner size="sm" />
|
||||||
>
|
|
||||||
<Link href="/breweries/create" className="btn-ghost btn-sm btn">
|
|
||||||
<FaPlus />
|
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</header>
|
{isAtEnd && !isLoading && (
|
||||||
<div className="grid gap-6 xl:grid-cols-2">
|
<div className="flex h-20 items-center justify-center text-center">
|
||||||
{!!breweryPosts.length && !isLoading && (
|
<div
|
||||||
<>
|
className="tooltip tooltip-bottom"
|
||||||
{breweryPosts.map((breweryPost) => {
|
data-tip="Scroll back to top of page."
|
||||||
return (
|
>
|
||||||
<div
|
<button
|
||||||
key={breweryPost.id}
|
type="button"
|
||||||
ref={
|
className="btn-ghost btn-sm btn"
|
||||||
breweryPosts[breweryPosts.length - 1] === breweryPost
|
aria-label="Scroll back to top of page."
|
||||||
? lastBreweryPostRef
|
onClick={() => {
|
||||||
: undefined
|
pageRef.current?.scrollIntoView({
|
||||||
}
|
behavior: 'smooth',
|
||||||
>
|
block: 'start',
|
||||||
<BreweryCard brewery={breweryPost} />
|
});
|
||||||
</div>
|
}}
|
||||||
);
|
>
|
||||||
})}
|
<FaArrowUp />
|
||||||
</>
|
</button>
|
||||||
)}
|
</div>
|
||||||
{(isLoading || isLoadingMore) && (
|
</div>
|
||||||
<>
|
|
||||||
{Array.from({ length: PAGE_SIZE }, (_, i) => (
|
|
||||||
<LoadingCard key={i} />
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{(isLoading || isLoadingMore) && (
|
|
||||||
<div className="flex h-32 w-full items-center justify-center">
|
|
||||||
<Spinner size="sm" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{isAtEnd && !isLoading && (
|
|
||||||
<div className="flex h-20 items-center justify-center text-center">
|
|
||||||
<div
|
|
||||||
className="tooltip tooltip-bottom"
|
|
||||||
data-tip="Scroll back to top of page."
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn-ghost btn-sm btn"
|
|
||||||
aria-label="Scroll back to top of page."
|
|
||||||
onClick={() => {
|
|
||||||
pageRef.current?.scrollIntoView({
|
|
||||||
behavior: 'smooth',
|
|
||||||
block: 'start',
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FaArrowUp />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
2
src/prisma/migrations/20230423235322_/migration.sql
Normal file
2
src/prisma/migrations/20230423235322_/migration.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "BreweryPost" ADD COLUMN "dateEstablished" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||||
@@ -105,7 +105,8 @@ model BreweryPost {
|
|||||||
postedById String
|
postedById String
|
||||||
breweryComments BreweryComment[]
|
breweryComments BreweryComment[]
|
||||||
breweryImages BreweryImage[]
|
breweryImages BreweryImage[]
|
||||||
BreweryPostLike BreweryPostLike[]
|
breweryPostLike BreweryPostLike[]
|
||||||
|
dateEstablished DateTime @default(now()) @db.Timestamptz(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
model BreweryComment {
|
model BreweryComment {
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ const createNewBreweryPosts = async ({
|
|||||||
const description = faker.lorem.lines(5);
|
const description = faker.lorem.lines(5);
|
||||||
const user = users[Math.floor(Math.random() * users.length)];
|
const user = users[Math.floor(Math.random() * users.length)];
|
||||||
const createdAt = faker.date.past(1);
|
const createdAt = faker.date.past(1);
|
||||||
|
const dateEstablished = faker.date.past(40);
|
||||||
|
|
||||||
breweryPromises.push(
|
breweryPromises.push(
|
||||||
prisma.breweryPost.create({
|
prisma.breweryPost.create({
|
||||||
data: {
|
data: {
|
||||||
@@ -32,6 +34,7 @@ const createNewBreweryPosts = async ({
|
|||||||
description,
|
description,
|
||||||
postedBy: { connect: { id: user.id } },
|
postedBy: { connect: { id: user.id } },
|
||||||
createdAt,
|
createdAt,
|
||||||
|
dateEstablished,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ const getAllBeerPosts = async (pageNum: number, pageSize: number) => {
|
|||||||
},
|
},
|
||||||
take: pageSize,
|
take: pageSize,
|
||||||
skip,
|
skip,
|
||||||
|
orderBy: { createdAt: 'desc' },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,10 @@ const getAllBreweryPosts = async (pageNum?: number, pageSize?: number) => {
|
|||||||
name: true,
|
name: true,
|
||||||
postedBy: { select: { username: true, id: true } },
|
postedBy: { select: { username: true, id: true } },
|
||||||
breweryImages: { select: { path: true, caption: true, id: true, alt: true } },
|
breweryImages: { select: { path: true, caption: true, id: true, alt: true } },
|
||||||
|
createdAt: true,
|
||||||
|
dateEstablished: true,
|
||||||
},
|
},
|
||||||
|
orderBy: { createdAt: 'desc' },
|
||||||
});
|
});
|
||||||
|
|
||||||
return breweryPosts;
|
return breweryPosts;
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ const getBreweryPostById = async (id: string) => {
|
|||||||
name: true,
|
name: true,
|
||||||
breweryImages: { select: { path: true, caption: true, id: true, alt: true } },
|
breweryImages: { select: { path: true, caption: true, id: true, alt: true } },
|
||||||
postedBy: { select: { username: true, id: true } },
|
postedBy: { select: { username: true, id: true } },
|
||||||
|
createdAt: true,
|
||||||
|
dateEstablished: true,
|
||||||
},
|
},
|
||||||
where: { id },
|
where: { id },
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ const BreweryPostQueryResult = z.object({
|
|||||||
breweryImages: z.array(
|
breweryImages: z.array(
|
||||||
z.object({ path: z.string(), caption: z.string(), id: z.string(), alt: z.string() }),
|
z.object({ path: z.string(), caption: z.string(), id: z.string(), alt: z.string() }),
|
||||||
),
|
),
|
||||||
|
createdAt: z.coerce.date(),
|
||||||
|
dateEstablished: z.coerce.date(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default BreweryPostQueryResult;
|
export default BreweryPostQueryResult;
|
||||||
|
|||||||
Reference in New Issue
Block a user