From ec2ddd8a7f5449e3c7ba60b643541536595a732a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=BAt?= Date: Mon, 5 Aug 2024 01:24:29 +0700 Subject: [PATCH 1/6] feat: ratting --- src/app/globals.css | 9 ++-- .../[slug]/reviews/@component/ratting.tsx | 43 +++++++++++++++++++ src/app/title/[slug]/reviews/page.tsx | 9 +++- src/components/icon/icon.star.border.tsx | 23 ++++++++++ src/components/icon/icon.star.tsx | 27 ++++++++++++ 5 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 src/app/title/[slug]/reviews/@component/ratting.tsx create mode 100644 src/components/icon/icon.star.border.tsx create mode 100644 src/components/icon/icon.star.tsx diff --git a/src/app/globals.css b/src/app/globals.css index 685d29c..dbc0299 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -33,6 +33,9 @@ --ring: 222.2 84% 4.9%; --radius: 0.5rem; + + /* customs */ + --primary-color: rgb(5 170 240); } .dark { @@ -133,15 +136,15 @@ } .primary-color { - color: rgb(5 170 240); + color: var(--primary-color); } .bg-primary-color { - background-color: rgb(5 170 240); + background-color: var(--primary-color); } .border-primary-color { - border-color: rgb(5 170 240); + border-color: var(--primary-color); } ::-webkit-scrollbar { diff --git a/src/app/title/[slug]/reviews/@component/ratting.tsx b/src/app/title/[slug]/reviews/@component/ratting.tsx new file mode 100644 index 0000000..5698204 --- /dev/null +++ b/src/app/title/[slug]/reviews/@component/ratting.tsx @@ -0,0 +1,43 @@ +"use client"; +import IconStar from "@/components/icon/icon.star"; +import IconStarBorder from "@/components/icon/icon.star.border"; +import { useState } from "react"; + +const Rating = () => { + const [rating, setRating] = useState(null); + const [hover, setHover] = useState(null); + + return ( +
+ {[...Array(5)].map((star, index) => { + const currentRating = index + 1; + return ( + + ); + })} +
+ ); +}; + +export default Rating; diff --git a/src/app/title/[slug]/reviews/page.tsx b/src/app/title/[slug]/reviews/page.tsx index 4409e80..175d090 100644 --- a/src/app/title/[slug]/reviews/page.tsx +++ b/src/app/title/[slug]/reviews/page.tsx @@ -1,5 +1,12 @@ +import TabContent from "@/app/title/@component/tab.content.wrapper"; +import Ratting from "@/app/title/[slug]/reviews/@component/ratting"; + const ReviewsTab = () => { - return
this is reviews tab
; + return ( + + + + ); }; export default ReviewsTab; diff --git a/src/components/icon/icon.star.border.tsx b/src/components/icon/icon.star.border.tsx new file mode 100644 index 0000000..ef89a2f --- /dev/null +++ b/src/components/icon/icon.star.border.tsx @@ -0,0 +1,23 @@ +import { ComponentProps } from "react"; + +const IconStarBorder = (props: ComponentProps<"svg">) => { + return ( + + + + ); +}; + +export default IconStarBorder; diff --git a/src/components/icon/icon.star.tsx b/src/components/icon/icon.star.tsx new file mode 100644 index 0000000..571690f --- /dev/null +++ b/src/components/icon/icon.star.tsx @@ -0,0 +1,27 @@ +import { ComponentProps } from "react"; + +const IconStar = (props: ComponentProps<"svg">) => { + return ( + + + + ); +}; + +export default IconStar; From 7ab70ea436242b817f46d7ff9c44fd6ff542fdda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=BAt?= Date: Mon, 5 Aug 2024 10:17:05 +0700 Subject: [PATCH 2/6] feat(ui): add ui review form --- src/app/title/[slug]/page.tsx | 3 +-- src/app/title/[slug]/reviews/page.tsx | 16 ++++++++++++++++ src/components/icon/icon.send.tsx | 24 ++++++++++++++++++++++++ src/components/ui/button.tsx | 2 +- src/components/ui/textarea.tsx | 24 ++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 src/components/icon/icon.send.tsx create mode 100644 src/components/ui/textarea.tsx diff --git a/src/app/title/[slug]/page.tsx b/src/app/title/[slug]/page.tsx index 33cc74e..555a773 100644 --- a/src/app/title/[slug]/page.tsx +++ b/src/app/title/[slug]/page.tsx @@ -17,7 +17,6 @@ import { AlertDialogAction, AlertDialogCancel, AlertDialogContent, - AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, @@ -34,7 +33,7 @@ const ChaptersTab = async (props: any) => { const id = temp1[temp1.length - 1]; const data = await sendRequest({ - url: `${process.env.WEB_COMIC_API}/api//chapters?comicId=${id}&_sort=createdAt&_order=desc`, + url: `${process.env.WEB_COMIC_API}/api/chapters?comicId=${id}&_sort=createdAt&_order=desc`, method: "GET", nextOption: { cache: "no-store", diff --git a/src/app/title/[slug]/reviews/page.tsx b/src/app/title/[slug]/reviews/page.tsx index 175d090..3b85c64 100644 --- a/src/app/title/[slug]/reviews/page.tsx +++ b/src/app/title/[slug]/reviews/page.tsx @@ -1,10 +1,26 @@ import TabContent from "@/app/title/@component/tab.content.wrapper"; import Ratting from "@/app/title/[slug]/reviews/@component/ratting"; +import IconSend from "@/components/icon/icon.send"; +import { Button } from "@/components/ui/button"; +import { Textarea } from "@/components/ui/textarea"; const ReviewsTab = () => { return ( +
+ + +
+
+ +
); }; diff --git a/src/components/icon/icon.send.tsx b/src/components/icon/icon.send.tsx new file mode 100644 index 0000000..f1a6c7e --- /dev/null +++ b/src/components/icon/icon.send.tsx @@ -0,0 +1,24 @@ +import { ComponentProps } from "react"; + +const IconSend = (props: ComponentProps<"svg">) => { + return ( + + + + + ); +}; + +export default IconSend; diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 1bc2325..3f30f8c 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -20,7 +20,7 @@ const buttonVariants = cva( link: "text-primary underline-offset-4 hover:underline", }, size: { - default: "h-10 px-4 py-2", + default: "px-4 py-2", sm: "h-9 rounded-md px-3", lg: "h-11 rounded-md px-8", icon: "h-10 w-10", diff --git a/src/components/ui/textarea.tsx b/src/components/ui/textarea.tsx new file mode 100644 index 0000000..7601cc7 --- /dev/null +++ b/src/components/ui/textarea.tsx @@ -0,0 +1,24 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +export interface TextareaProps + extends React.TextareaHTMLAttributes {} + +const Textarea = React.forwardRef( + ({ className, ...props }, ref) => { + return ( + @@ -21,6 +46,62 @@ const ReviewsTab = () => { Submit + +
+ {data.length >= 1 ? ( +
    + {data?.map((reviews) => { + return ( +
  • + + + + + {reviews?.author?.name} + + + +
    + +

    + {reviews?.author?.name} + + @{reviews?.author?.name} + +

    + +
    +
    + + + + + +
    +
    + {dayjs( + reviews?.createdAt + ).fromNow()} +
    +
    +

    + {reviews?.content} +

    +
    +
  • + ); + })} +
+ ) : ( +
No Reviews
+ )} +
); }; diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx new file mode 100644 index 0000000..51e507b --- /dev/null +++ b/src/components/ui/avatar.tsx @@ -0,0 +1,50 @@ +"use client" + +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/src/types/backend.d.ts b/src/types/backend.d.ts index ed0fdce..28a028a 100644 --- a/src/types/backend.d.ts +++ b/src/types/backend.d.ts @@ -42,4 +42,20 @@ declare global { vip: boolean; createdAt: number } + + interface IReviews { + id: number; + comicId: number; + authorId: number, + content: string, + rated: number, + createdAt: number, + author: { + id: number, + name: string, + country: string, + avatar: string, + banner: string + } + } } \ No newline at end of file From c66b6b6b3c2f261a33bc1293be5832e38475bbd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=BAt?= Date: Wed, 7 Aug 2024 00:06:12 +0700 Subject: [PATCH 4/6] feat: add rating read only component --- .../reviews/@component/rating.read.only.tsx | 26 +++++++++++++++++++ .../@component/{ratting.tsx => rating.tsx} | 0 src/app/title/[slug]/reviews/page.tsx | 15 +++++------ src/components/icon/icon.star.half.tsx | 20 ++++++++++++++ 4 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 src/app/title/[slug]/reviews/@component/rating.read.only.tsx rename src/app/title/[slug]/reviews/@component/{ratting.tsx => rating.tsx} (100%) create mode 100644 src/components/icon/icon.star.half.tsx diff --git a/src/app/title/[slug]/reviews/@component/rating.read.only.tsx b/src/app/title/[slug]/reviews/@component/rating.read.only.tsx new file mode 100644 index 0000000..1314dbf --- /dev/null +++ b/src/app/title/[slug]/reviews/@component/rating.read.only.tsx @@ -0,0 +1,26 @@ +import IconStar from "@/components/icon/icon.star"; +import IconStarBorder from "@/components/icon/icon.star.border"; +import IconStarHalf from "@/components/icon/icon.star.half"; + +const RatingReadOnly = (props: { stars: number; half?: boolean }) => { + const { stars, half = false } = props; + const rattingStar = Array.from({ length: 5 }, (elm, index) => { + let number = index + 0.5; + return ( + + {stars >= index + 1 ? ( + + ) : stars >= number ? ( + + ) : ( + + )} + + ); + }); + return
{rattingStar}
; +}; + +export default RatingReadOnly; diff --git a/src/app/title/[slug]/reviews/@component/ratting.tsx b/src/app/title/[slug]/reviews/@component/rating.tsx similarity index 100% rename from src/app/title/[slug]/reviews/@component/ratting.tsx rename to src/app/title/[slug]/reviews/@component/rating.tsx diff --git a/src/app/title/[slug]/reviews/page.tsx b/src/app/title/[slug]/reviews/page.tsx index f018d3e..f8030d4 100644 --- a/src/app/title/[slug]/reviews/page.tsx +++ b/src/app/title/[slug]/reviews/page.tsx @@ -1,5 +1,5 @@ import TabContent from "@/app/title/@component/tab.content.wrapper"; -import Ratting from "@/app/title/[slug]/reviews/@component/ratting"; +import Rating from "@/app/title/[slug]/reviews/@component/rating"; import IconSend from "@/components/icon/icon.send"; import IconStarBorder from "@/components/icon/icon.star.border"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; @@ -11,6 +11,7 @@ import Link from "next/link"; import dayjs from "dayjs"; import relativeTime from "dayjs/plugin/relativeTime"; +import RatingReadOnly from "@/app/title/[slug]/reviews/@component/rating.read.only"; dayjs.extend(relativeTime); @@ -30,7 +31,7 @@ const ReviewsTab = async (props: any) => { return ( - +