Files
nobat724_front/app/component/comment/ItemUser.js
T
hamedandClaude Opus 4.8 12917cd900 fix(doctor): correct rating/comment API paths to real backend routes
Doctor page logged a 404 on GET /api/v1/clinicpro/rate/{uuid}. The
frontend used a stale Drupal-era `clinicpro/` prefix; the Symfony API
exposes these under /api/v1 directly.

- response.js: rate/comments/like wrappers point to real routes
  (rate/{uuid}, comments/{uuid}, POST rate, POST comment,
  POST like/{commentUuid}); patch maps to POST upsert; writes use
  requireAuth. Add getDoctorComments wrapper.
- doctor page: fetch comments from comments/{doctor.uuid} (was
  clinicpro/comments/{doctor.id}) and unwrap double-nested data.
- ItemUser: postCommentsLike sends commentUuid for the toggle endpoint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 23:07:20 +03:30

168 lines
5.2 KiB
JavaScript

import Image from "next/image";
import { imageUrl } from "@/helper";
import { Button, CircularProgress } from "@mui/material";
// Icons
import BoldDisLikeComment from "@/components/icons/BoldDisLikeComment";
import BoldLikeComment from "@/components/icons/BoldLikeComment";
import DisLikeComment from "@/components/icons/DisLikeComment";
import LikeComment from "@/components/icons/LikeComment";
import Replies from "./Replies";
import AnswerField from "./AnswerField";
import SendAnswer from "./SendAnswer";
import { alert, isUserLoggedIn, timeAgo } from "@/helper";
import { request } from "@/services/response";
import { useState } from "react";
function ItemUser({ update, setUpdate, data }) {
const [loadingLike, setLoadingLike] = useState(false);
const [loadingDislike, setLoadingDislike] = useState(false);
const SendReq = async (type) => {
if (type === "like") setLoadingLike(true);
else setLoadingDislike(true);
try {
const res = await request.postCommentsLike(data.uuid ?? data.id);
} catch (err) {
// err
} finally {
if (type === "like") setLoadingLike(false);
else setLoadingDislike(false);
}
};
const handleLike = (data, type) => {
SendReq(type);
const { current_user_like } = data.like_status;
if (type === "like") {
if (current_user_like.like) {
data.like_status.like_count -= 1;
current_user_like.like = false;
} else {
data.like_status.like_count += 1;
current_user_like.like = true;
if (current_user_like.dislike) {
data.like_status.dislike_count -= 1;
current_user_like.dislike = false;
}
}
} else {
if (current_user_like.dislike) {
data.like_status.dislike_count -= 1;
current_user_like.dislike = false;
} else {
data.like_status.dislike_count += 1;
current_user_like.dislike = true;
if (current_user_like.like) {
data.like_status.like_count -= 1;
current_user_like.like = false;
}
}
}
setUpdate(!update);
};
return (
<li className="w-full">
<div className="flex items-center justify-start gap-2">
<Image
className="!w-[32px] !h-[32px]"
src={imageUrl(data.author?.picture?.[0]?.url)}
width={40}
height={40}
alt="profile"
/>
<div className="flex flex-col items-start justify-center gap-[8px]">
<p className="text-[#343A40] text-[14px] md:text-[16px] font-medium">
{data.author.real_name}
</p>
<p className="text-[#7E7E7E] text-[12px] md:text-[14px] font-medium">
{timeAgo(data.created)}
</p>
</div>
</div>
<div className="mt-2">
<p className="text-[#495057] text-[12px] md:text-[14px]">
{data.comment}
</p>
<div className="flex items-center justify-start mt-2 gap-[28px]">
{/* لایک */}
<div className="flex items-center justify-start gap-1">
<div
className="cursor-pointer"
onClick={() => handleLike(data, "like")}
>
{loadingLike ? (
<CircularProgress
className="!w-[24px] !h-[24px]"
sx={{ color: "#7E7E7E" }}
/>
) : data.like_status.current_user_like.like ? (
<BoldLikeComment />
) : (
<LikeComment />
)}
</div>
<p className="text-[#6C757D] text-[12px] select-none">
{data.like_status.like_count || ""}
</p>
</div>
{/* دیس‌لایک */}
<div className="flex items-center justify-start gap-1">
<div
className="cursor-pointer"
onClick={() => handleLike(data, "dislike")}
>
{loadingDislike ? (
<CircularProgress
className="!w-[24px] !h-[24px]"
sx={{ color: "#7E7E7E" }}
/>
) : data.like_status.current_user_like.dislike ? (
<BoldDisLikeComment />
) : (
<DisLikeComment />
)}
</div>
<p className="text-[#6C757D] text-[12px] select-none">
{data.like_status.dislike_count || ""}
</p>
</div>
<Button
className="!text-[#495057] !text-[12px] !font-medium"
onClick={() => {
if (isUserLoggedIn()) {
data.is_open_answer = !data.is_open_answer;
setUpdate(!update);
} else {
alert(
"warning",
"برای ارسال کامنت باید ابتدا وارد حساب کاربری شوید."
);
}
}}
variant="text"
>
پاسخ
</Button>
</div>
<SendAnswer data={data} />
{!!data.replies.length && (
<AnswerField data={data} update={update} setUpdate={setUpdate} />
)}
<Replies data={data} update={update} setUpdate={setUpdate} />
</div>
</li>
);
}
export default ItemUser;