mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 18:52:06 +00:00
Styling changes and refactor
Switch google fonts to use Next.js font optimization, animate comment fade in, and refactor beer like handler and comment submit handler.
This commit is contained in:
@@ -10,6 +10,7 @@ import { z } from 'zod';
|
||||
|
||||
import { KeyedMutator } from 'swr';
|
||||
import BeerCommentQueryResult from '@/services/BeerComment/schema/BeerCommentQueryResult';
|
||||
import { useRouter } from 'next/router';
|
||||
import Button from '../ui/forms/Button';
|
||||
import FormError from '../ui/forms/FormError';
|
||||
import FormInfo from '../ui/forms/FormInfo';
|
||||
@@ -44,6 +45,7 @@ const BeerCommentForm: FunctionComponent<BeerCommentFormProps> = ({
|
||||
reset({ rating: 0, content: '' });
|
||||
}, [reset]);
|
||||
|
||||
const router = useRouter();
|
||||
const onSubmit: SubmitHandler<z.infer<typeof BeerCommentValidationSchema>> = async (
|
||||
data,
|
||||
) => {
|
||||
@@ -55,44 +57,58 @@ const BeerCommentForm: FunctionComponent<BeerCommentFormProps> = ({
|
||||
beerPostId: beerPost.id,
|
||||
});
|
||||
reset();
|
||||
await mutate();
|
||||
|
||||
const submitTasks: Promise<unknown>[] = [
|
||||
router.push(`/beers/${beerPost.id}`, undefined, { scroll: false }),
|
||||
mutate(),
|
||||
];
|
||||
|
||||
await Promise.all(submitTasks);
|
||||
};
|
||||
|
||||
const { errors } = formState;
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<FormInfo>
|
||||
<FormLabel htmlFor="content">Leave a comment</FormLabel>
|
||||
<FormError>{errors.content?.message}</FormError>
|
||||
</FormInfo>
|
||||
<FormSegment>
|
||||
<FormTextArea
|
||||
id="content"
|
||||
formValidationSchema={register('content')}
|
||||
placeholder="Comment"
|
||||
rows={5}
|
||||
error={!!errors.content?.message}
|
||||
/>
|
||||
</FormSegment>
|
||||
<FormInfo>
|
||||
<FormLabel htmlFor="rating">Rating</FormLabel>
|
||||
<FormError>{errors.rating?.message}</FormError>
|
||||
</FormInfo>
|
||||
<Rating
|
||||
value={rating}
|
||||
onChange={(value) => {
|
||||
setRating(value);
|
||||
setValue('rating', value);
|
||||
}}
|
||||
>
|
||||
<Rating.Item name="rating-1" className="mask mask-star" />
|
||||
<Rating.Item name="rating-1" className="mask mask-star" />
|
||||
<Rating.Item name="rating-1" className="mask mask-star" />
|
||||
<Rating.Item name="rating-1" className="mask mask-star" />
|
||||
<Rating.Item name="rating-1" className="mask mask-star" />
|
||||
</Rating>
|
||||
<Button type="submit">Submit</Button>
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-5">
|
||||
<div>
|
||||
<FormInfo>
|
||||
<FormLabel htmlFor="content">Leave a comment</FormLabel>
|
||||
<FormError>{errors.content?.message}</FormError>
|
||||
</FormInfo>
|
||||
<FormSegment>
|
||||
<FormTextArea
|
||||
id="content"
|
||||
formValidationSchema={register('content')}
|
||||
placeholder="Comment"
|
||||
rows={5}
|
||||
error={!!errors.content?.message}
|
||||
disabled={formState.isSubmitting}
|
||||
/>
|
||||
</FormSegment>
|
||||
<FormInfo>
|
||||
<FormLabel htmlFor="rating">Rating</FormLabel>
|
||||
<FormError>{errors.rating?.message}</FormError>
|
||||
</FormInfo>
|
||||
<Rating
|
||||
value={rating}
|
||||
onChange={(value) => {
|
||||
setRating(value);
|
||||
setValue('rating', value);
|
||||
}}
|
||||
>
|
||||
<Rating.Item name="rating-1" className="mask mask-star" />
|
||||
<Rating.Item name="rating-1" className="mask mask-star" />
|
||||
<Rating.Item name="rating-1" className="mask mask-star" />
|
||||
<Rating.Item name="rating-1" className="mask mask-star" />
|
||||
<Rating.Item name="rating-1" className="mask mask-star" />
|
||||
</Rating>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Button type="submit" isSubmitting={formState.isSubmitting}>
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,6 +3,8 @@ import Link from 'next/link';
|
||||
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { FaArrowLeft, FaArrowRight } from 'react-icons/fa';
|
||||
|
||||
interface BeerCommentsPaginationBarProps {
|
||||
commentsPageNum: number;
|
||||
commentsPageCount: number;
|
||||
@@ -15,9 +17,9 @@ const BeerCommentsPaginationBar: FC<BeerCommentsPaginationBarProps> = ({
|
||||
beerPost,
|
||||
}) => (
|
||||
<div className="flex items-center justify-center" id="comments-pagination">
|
||||
<div className="btn-group grid w-6/12 grid-cols-2">
|
||||
<div className="btn-group">
|
||||
<Link
|
||||
className={`btn-outline btn ${
|
||||
className={`btn btn-ghost ${
|
||||
commentsPageNum === 1
|
||||
? 'btn-disabled pointer-events-none'
|
||||
: 'pointer-events-auto'
|
||||
@@ -28,10 +30,11 @@ const BeerCommentsPaginationBar: FC<BeerCommentsPaginationBarProps> = ({
|
||||
}}
|
||||
scroll={false}
|
||||
>
|
||||
Next Comments
|
||||
<FaArrowLeft />
|
||||
</Link>
|
||||
<button className="btn btn-ghost pointer-events-none">{commentsPageNum}</button>
|
||||
<Link
|
||||
className={`btn-outline btn ${
|
||||
className={`btn btn-ghost ${
|
||||
commentsPageNum === commentsPageCount
|
||||
? 'btn-disabled pointer-events-none'
|
||||
: 'pointer-events-auto'
|
||||
@@ -42,7 +45,7 @@ const BeerCommentsPaginationBar: FC<BeerCommentsPaginationBarProps> = ({
|
||||
}}
|
||||
scroll={false}
|
||||
>
|
||||
Previous Comments
|
||||
<FaArrowRight />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,6 +29,7 @@ const BeerPostCommentsSection: FC<BeerPostCommentsSectionProps> = ({ beerPost })
|
||||
pageNum,
|
||||
pageSize,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="w-full space-y-3 md:w-[60%]">
|
||||
<div className="card h-96 bg-base-300">
|
||||
@@ -43,7 +44,7 @@ const BeerPostCommentsSection: FC<BeerPostCommentsSectionProps> = ({ beerPost })
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{comments && !!commentsPageCount && !isLoading && (
|
||||
{comments && !!comments.length && !!commentsPageCount && !isLoading && (
|
||||
<div className="card bg-base-300 pb-6">
|
||||
{comments.map((comment) => (
|
||||
<CommentCardBody key={comment.id} comment={comment} mutate={mutate} />
|
||||
@@ -60,10 +61,16 @@ const BeerPostCommentsSection: FC<BeerPostCommentsSectionProps> = ({ beerPost })
|
||||
{!comments?.length && !isLoading && <NoCommentsCard />}
|
||||
|
||||
{isLoading && (
|
||||
<div className="card bg-base-300">
|
||||
{Array.from({ length: 5 }).map((_, i) => (
|
||||
<div className="card bg-base-300 pb-6">
|
||||
{Array.from({ length: pageSize }).map((_, i) => (
|
||||
<CommentLoadingCardBody key={i} />
|
||||
))}
|
||||
|
||||
<BeerCommentsPaginationBar
|
||||
commentsPageNum={pageNum}
|
||||
commentsPageCount={20}
|
||||
beerPost={beerPost}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import useCheckIfUserLikesBeerPost from '@/hooks/useCheckIfUserLikesBeerPost';
|
||||
import sendLikeRequest from '@/requests/sendLikeRequest';
|
||||
import { FC, useState } from 'react';
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { FaThumbsUp, FaRegThumbsUp } from 'react-icons/fa';
|
||||
import { KeyedMutator } from 'swr';
|
||||
|
||||
@@ -9,14 +9,18 @@ const BeerPostLikeButton: FC<{
|
||||
mutateCount: KeyedMutator<number>;
|
||||
}> = ({ beerPostId, mutateCount }) => {
|
||||
const { isLiked, mutate: mutateLikeStatus } = useCheckIfUserLikesBeerPost(beerPostId);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(false);
|
||||
}, [isLiked]);
|
||||
|
||||
const handleLike = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
await sendLikeRequest(beerPostId);
|
||||
mutateCount();
|
||||
mutateLikeStatus();
|
||||
await mutateCount();
|
||||
await mutateLikeStatus();
|
||||
setLoading(false);
|
||||
} catch (e) {
|
||||
setLoading(false);
|
||||
|
||||
@@ -10,7 +10,7 @@ const BeerRecommendations: FunctionComponent<BeerRecommendationsProps> = ({
|
||||
}) => {
|
||||
return (
|
||||
<div className="card sticky top-2 h-full overflow-y-scroll bg-base-300">
|
||||
<div className="card-body">
|
||||
<div className="card-body space-y-3">
|
||||
{beerRecommendations.map((beerPost) => (
|
||||
<div key={beerPost.id} className="w-full">
|
||||
<div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import useTimeDistance from '@/hooks/useTimeDistance';
|
||||
import BeerCommentQueryResult from '@/services/BeerComment/schema/BeerCommentQueryResult';
|
||||
import { format } from 'date-fns';
|
||||
import format from 'date-fns/format';
|
||||
import Link from 'next/link';
|
||||
import { useContext } from 'react';
|
||||
import { Rating } from 'react-daisyui';
|
||||
@@ -69,7 +69,7 @@ const CommentCardBody: React.FC<{
|
||||
const timeDistance = useTimeDistance(new Date(comment.createdAt));
|
||||
|
||||
return (
|
||||
<div className="card-body h-64">
|
||||
<div className="card-body h-64 animate-in fade-in-10">
|
||||
<div className="flex flex-col justify-between sm:flex-row">
|
||||
<div>
|
||||
<h3 className="font-semibold sm:text-2xl">
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
const CommentLoadingCardBody = () => {
|
||||
return (
|
||||
<div className="card-body h-64">
|
||||
<div className="flex animate-pulse space-x-4">
|
||||
<div className="animate card-body h-64 fade-in-10">
|
||||
<div className="flex animate-pulse space-x-4 slide-in-from-top">
|
||||
<div className="flex-1 space-y-4 py-1">
|
||||
<div className="h-4 w-3/4 rounded bg-base-200" />
|
||||
<div className="h-4 w-3/4 rounded bg-base-100" />
|
||||
<div className="space-y-2">
|
||||
<div className="h-4 rounded bg-base-200" />
|
||||
<div className="h-4 w-5/6 rounded bg-base-200" />
|
||||
<div className="h-4 rounded bg-base-100" />
|
||||
<div className="h-4 w-5/6 rounded bg-base-100" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user