194 lines
6.1 KiB
TypeScript
194 lines
6.1 KiB
TypeScript
import { Star, X, Reply } from "lucide-react";
|
||
import { useState } from "react";
|
||
import { Button } from "~/components/ui/button";
|
||
import {
|
||
Drawer,
|
||
DrawerContent,
|
||
DrawerHeader,
|
||
DrawerTitle,
|
||
} from "~/components/ui/drawer";
|
||
import AppTextArea from "~/components/AppTextArea";
|
||
import { useServiceCreateComment } from "~/requestHandler/use-comments-hooks";
|
||
import { useRootData } from "~/hooks/use-root-data";
|
||
import { useToast } from "~/hooks/use-toast";
|
||
import { useIsOwnerProduct } from "~/requestHandler/use-product-hooks";
|
||
|
||
export interface ReviewProps {
|
||
id?: string;
|
||
productId: string;
|
||
name: string;
|
||
rating: number;
|
||
date: string;
|
||
comment: string;
|
||
sellerReply?: {
|
||
date: string;
|
||
comment: string;
|
||
};
|
||
isLast: boolean;
|
||
}
|
||
|
||
export const Review = ({
|
||
id,
|
||
productId,
|
||
name,
|
||
rating,
|
||
isLast,
|
||
date,
|
||
comment,
|
||
sellerReply,
|
||
}: ReviewProps) => {
|
||
const [isReplyDrawerOpen, setIsReplyDrawerOpen] = useState(false);
|
||
const [replyComment, setReplyComment] = useState("");
|
||
const [error, setError] = useState<string | null>(null);
|
||
const { toast } = useToast();
|
||
const { user } = useRootData();
|
||
const createCommentMutation = useServiceCreateComment();
|
||
|
||
const { data: isOwnerProduct } = useIsOwnerProduct(productId);
|
||
const isOwner = isOwnerProduct?.isOwner;
|
||
|
||
const authToken = user?.access_token
|
||
? user.access_token.replace(/^"|"$/g, "")
|
||
: "";
|
||
|
||
const handleReplySubmit = async () => {
|
||
// Check if user is authenticated
|
||
if (!authToken) {
|
||
setError("لطفا ابتدا وارد حساب کاربری خود شوید.");
|
||
return;
|
||
}
|
||
|
||
// Form validation
|
||
if (!replyComment || replyComment.trim().length < 1) {
|
||
setError("لطفا پاسخ خود را وارد کنید.");
|
||
return;
|
||
}
|
||
|
||
if (!id) {
|
||
setError("خطا در شناسایی نظر.");
|
||
return;
|
||
}
|
||
|
||
setError(null);
|
||
|
||
try {
|
||
await createCommentMutation.mutateAsync({
|
||
product: productId,
|
||
comment: replyComment,
|
||
parent: id,
|
||
});
|
||
|
||
// Reset form and close drawer on success
|
||
setReplyComment("");
|
||
setIsReplyDrawerOpen(false);
|
||
|
||
// Show success toast
|
||
toast({
|
||
title: "پاسخ شما با موفقیت ثبت شد",
|
||
description: "پاسخ شما بعد از بررسی به زودی اضافه خواهد شد.",
|
||
variant: "default",
|
||
duration: 3000,
|
||
});
|
||
} catch {
|
||
setError("خطا در ثبت پاسخ. لطفا مجددا تلاش کنید.");
|
||
}
|
||
};
|
||
|
||
return (
|
||
<>
|
||
<div
|
||
className={`flex gap-3 py-2 border-b flex-col w-full ${isLast ? "border-b-0" : ""}`}
|
||
>
|
||
<div>
|
||
<div className="flex gap-4 items-center">
|
||
<p className="text-B14 font-bold">{name}</p>
|
||
<div className="flex items-center gap-[2px]">
|
||
<p className="text-B12 font-bold">{rating}</p>
|
||
<Star className="text-BLACK fill-current" size={24} />
|
||
</div>
|
||
<p className="text-B12 font-bold text-GRAY">{date}</p>
|
||
{/* Reply button */}
|
||
{isOwner && (
|
||
<div className="mr-2">
|
||
<button
|
||
onClick={() => setIsReplyDrawerOpen(true)}
|
||
className="text-BLUE text-R12 flex items-center gap-1 hover:underline"
|
||
>
|
||
<Reply style={{ transform: "rotateY(180deg)" }} size={16} />
|
||
پاسخ
|
||
</button>
|
||
</div>
|
||
)}
|
||
</div>
|
||
<p className="text-R12">{comment}</p>
|
||
</div>
|
||
{sellerReply && (
|
||
<div className="rounded-[10px] bg-WHITE2 p-2">
|
||
<div className="flex gap-4 items-center">
|
||
<p className="text-B14 font-bold">پاسخ فروشنده</p>
|
||
<p className="text-B12 font-bold text-GRAY">{sellerReply.date}</p>
|
||
</div>
|
||
<p className="text-R12">{sellerReply.comment}</p>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{/* Reply Drawer */}
|
||
<Drawer open={isReplyDrawerOpen} onOpenChange={setIsReplyDrawerOpen}>
|
||
<DrawerContent>
|
||
<DrawerHeader className="flex flex-col py-3">
|
||
<div className="flex relative pt-2 text-B12 font-bold items-center justify-center w-full">
|
||
<X
|
||
className="absolute right-2 cursor-pointer"
|
||
size={24}
|
||
onClick={() => setIsReplyDrawerOpen(false)}
|
||
/>
|
||
<DrawerTitle className="text-B12 font-bold">پاسخ شما</DrawerTitle>
|
||
</div>
|
||
</DrawerHeader>
|
||
|
||
<div className="p-4 flex flex-col gap-4">
|
||
{/* Original comment display */}
|
||
<div className="bg-WHITE2 rounded-[10px] p-3">
|
||
<div className="flex gap-4 items-center mb-2">
|
||
<p className="text-B14 font-bold">{name}</p>
|
||
<div className="flex items-center gap-[2px]">
|
||
<p className="text-B12 font-bold">{rating}</p>
|
||
<Star className="text-BLACK fill-current" size={16} />
|
||
</div>
|
||
<p className="text-B12 font-bold text-GRAY">{date}</p>
|
||
</div>
|
||
<p className="text-R12">{comment}</p>
|
||
</div>
|
||
|
||
{/* Reply input */}
|
||
<AppTextArea
|
||
inputTitle="پاسخ شما:"
|
||
inputValue={replyComment}
|
||
inputOnChange={(e) => setReplyComment(e.target.value)}
|
||
inputPlaceholder="پاسخ خود را در این قسمت وارد کنید..."
|
||
inputDir="rtl"
|
||
/>
|
||
|
||
{/* Error message */}
|
||
{error && (
|
||
<div className="text-red-500 text-R12 text-right">{error}</div>
|
||
)}
|
||
|
||
{/* Submit button */}
|
||
<Button
|
||
variant="dark"
|
||
size="lg"
|
||
className="w-full font-bold"
|
||
onClick={handleReplySubmit}
|
||
disabled={createCommentMutation.isPending}
|
||
>
|
||
{createCommentMutation.isPending ? "در حال ثبت..." : "ثبت پاسخ"}
|
||
</Button>
|
||
</div>
|
||
</DrawerContent>
|
||
</Drawer>
|
||
</>
|
||
);
|
||
};
|