Add user location marker to brewery map, Add beer sec. for brewery posts

This commit is contained in:
Aaron William Po
2023-05-01 23:09:50 -04:00
parent f3d471be4c
commit d20ab0fd1f
10 changed files with 363 additions and 21 deletions

View File

@@ -0,0 +1,33 @@
import { FC } from 'react';
import Spinner from '../ui/Spinner';
interface BeerRecommendationLoadingComponentProps {
length: number;
}
const BeerRecommendationLoadingComponent: FC<BeerRecommendationLoadingComponentProps> = ({
length,
}) => {
return (
<>
{Array.from({ length }).map((_, i) => (
<div className="animate my-3 fade-in-10" key={i}>
<div className="flex animate-pulse space-x-4">
<div className="flex-1 space-y-4 py-1">
<div className="h-4 w-3/4 rounded bg-base-100" />
<div className="space-y-2">
<div className="h-4 rounded bg-base-100" />
<div className="h-4 w-11/12 rounded bg-base-100" />
</div>
</div>
</div>
</div>
))}
<div className="p-1">
<Spinner size="sm" />
</div>
</>
);
};
export default BeerRecommendationLoadingComponent;

View File

@@ -0,0 +1,84 @@
import UseBeerPostsByBrewery from '@/hooks/useBeerPostsByBrewery';
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
import Link from 'next/link';
import { FC } from 'react';
import { useInView } from 'react-intersection-observer';
import { z } from 'zod';
import BeerRecommendationLoadingComponent from '../BeerById/BeerRecommendationLoadingComponent';
interface BreweryCommentsSectionProps {
breweryPost: z.infer<typeof BreweryPostQueryResult>;
}
const BreweryBeersSection: FC<BreweryCommentsSectionProps> = ({ breweryPost }) => {
const PAGE_SIZE = 2;
const { beerPosts, isAtEnd, isLoadingMore, setSize, size } = UseBeerPostsByBrewery({
breweryId: breweryPost.id,
pageSize: PAGE_SIZE,
});
const { ref: penultimateBeerPostRef } = useInView({
/**
* When the last beer post comes into view, call setSize from useBeerPostsByBrewery to
* load more beer posts.
*/
onChange: (visible) => {
if (!visible || isAtEnd) return;
setSize(size + 1);
},
});
return (
<div className="card">
<div className="card-body">
<>
<h3 className="text-2xl font-bold">Brews</h3>
{!!beerPosts.length && (
<div className="space-y-5">
{beerPosts.map((beerPost, index) => {
const isPenultimateBeerPost = index === beerPosts.length - 2;
/**
* Attach a ref to the second last beer post in the list. When it comes
* into view, the component will call setSize to load more beer posts.
*/
return (
<div
ref={isPenultimateBeerPost ? penultimateBeerPostRef : undefined}
key={beerPost.id}
>
<div>
<Link className="link-hover link" href={`/beers/${beerPost.id}`}>
<span className="text-xl font-semibold">{beerPost.name}</span>
</Link>
</div>
<div>
<span className="text-lg font-medium">{beerPost.type.name}</span>
</div>
<div className="space-x-2">
<span>{beerPost.abv}% ABV</span>
<span>{beerPost.ibu} IBU</span>
</div>
</div>
);
})}
</div>
)}
{
/**
* If there are more beer posts to load, show a loading component with a
* skeleton loader and a loading spinner.
*/
!!isLoadingMore && !isAtEnd && (
<BeerRecommendationLoadingComponent length={PAGE_SIZE} />
)
}
</>
</div>
</div>
);
};
export default BreweryBeersSection;

View File

@@ -1,9 +0,0 @@
import { FC } from 'react';
interface BreweryCommentsSectionProps {}
const BreweryBeersSection: FC<BreweryCommentsSectionProps> = () => {
return <div className="card h-full"></div>;
};
export default BreweryBeersSection;

View File

@@ -36,10 +36,10 @@ const CommentsComponent: FC<CommentsComponentProps> = ({
setSize,
size,
}) => {
const { ref: lastCommentRef } = useInView({
const { ref: penultimateCommentRef } = useInView({
/**
* When the last comment comes into view, call setSize from useBeerPostComments to
* load more comments.
* When the second last comment comes into view, call setSize from useBeerPostComments
* to load more comments.
*/
onChange: (visible) => {
if (!visible || isAtEnd) return;
@@ -52,7 +52,7 @@ const CommentsComponent: FC<CommentsComponentProps> = ({
{!!comments.length && (
<div className="card bg-base-300 pb-6">
{comments.map((comment, index) => {
const isPenulitmateComment = index === comments.length - 2;
const isPenultimateComment = index === comments.length - 2;
/**
* Attach a ref to the last comment in the list. When it comes into view, the
@@ -60,7 +60,7 @@ const CommentsComponent: FC<CommentsComponentProps> = ({
*/
return (
<div
ref={isPenulitmateComment ? lastCommentRef : undefined}
ref={isPenultimateComment ? penultimateCommentRef : undefined}
key={comment.id}
>
<CommentCardBody comment={comment} mutate={mutate} />

View File

@@ -1,8 +1,20 @@
import React from 'react';
import React, { FC } from 'react';
import { HiLocationMarker } from 'react-icons/hi';
const LocationMarker = () => {
return <HiLocationMarker className="text-3xl" />;
interface LocationMarkerProps {
size?: 'sm' | 'md' | 'lg' | 'xl';
color?: 'blue' | 'red' | 'green' | 'yellow';
}
const sizeClasses: Record<NonNullable<LocationMarkerProps['size']>, `text-${string}`> = {
sm: 'text-2xl',
md: 'text-3xl',
lg: 'text-4xl',
xl: 'text-5xl',
};
const LocationMarker: FC<LocationMarkerProps> = ({ size = 'md', color = 'blue' }) => {
return <HiLocationMarker className={`${sizeClasses[size]} text-${color}-400`} />;
};
export default React.memo(LocationMarker);