@ieltsrealtest/ui
Version:
Reusable UI components for IELTS Real Test platform, built with React and TypeScript.
111 lines (110 loc) • 6.42 kB
JavaScript
'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faThumbsUp as solidThumbsUp } from '@fortawesome/free-solid-svg-icons';
import { faThumbsUp as regularThumbsUp } from '@fortawesome/free-regular-svg-icons';
import { useState } from 'react';
import CommentInput from './commentInput';
import { faThumbtack } from '@fortawesome/free-solid-svg-icons';
function formatTimeAgo(date) {
const seconds = Math.floor((Date.now() - new Date(date).getTime()) / 1000);
if (seconds < 60)
return `${seconds}s ago`;
const minutes = Math.floor(seconds / 60);
if (minutes < 60)
return `${minutes}m ago`;
const hours = Math.floor(seconds / 3600);
if (hours < 24)
return `${hours}h ago`;
const days = Math.floor(seconds / 86400);
return `${days}d ago`;
}
export default function CommentCard({ id, avatar, name, comment, threadId, userId, isReplying = false, onReplyClick, onRefresh, role, replied_user, time, likes, pin }) {
const [liked, setLiked] = useState(() => (likes || []).includes(userId));
const [likeCount, setLikeCount] = useState(likes?.length || 0);
const handleToggleLike = async () => {
try {
if (!liked) {
// Gửi POST để thêm like
const res = await fetch(`https://api.youready.net/ielts/comment/api/discussion/likes/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
discussion_id: id,
user_id: userId,
}),
});
if (!res.ok)
throw new Error('Failed to like');
setLiked(true);
setLikeCount((prev) => prev + 1);
}
else {
// Gửi DELETE để bỏ like
const res = await fetch(`https://api.youready.net/ielts/comment/api/discussion/likes/`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
discussion_id: id,
user_id: userId,
}),
});
if (!res.ok)
throw new Error('Failed to unlike');
setLiked(false);
setLikeCount((prev) => Math.max(0, prev - 1));
}
}
catch (err) {
console.error('Error toggling like:', err);
}
};
const [pinned, setPinned] = useState(pin);
const handleTogglePin = async () => {
try {
if (!pinned) {
// Gửi POST để ghim
const res = await fetch(`https://api.youready.net/ielts/comment/api/discussion/pins/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
discussion_id: id,
}),
});
if (!res.ok)
throw new Error('Failed to pin');
setPinned(true);
}
else {
// Gửi DELETE để bỏ ghim
const res = await fetch(`https://api.youready.net/ielts/api/discussion/pins/`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
discussion_id: id,
}),
});
if (!res.ok)
throw new Error('Failed to unpin');
setPinned(false);
}
// Refresh UI nếu cần
onRefresh?.();
}
catch (err) {
console.error('Error toggling pin:', err);
}
};
return (_jsxs("div", { className: "w-full flex gap-4 sm:flex-col md:flex-row sm:gap-2 md:gap-4", children: [_jsx("div", { className: "flex-shrink-0 mb-4 sm:mb-2 md:mb-0" }), _jsxs("div", { className: "flex-1 text-sm", children: [_jsxs("div", { className: "bg-[#FFF9F1] border border-black/70 rounded-md p-3", children: [_jsxs("div", { className: "flex items-center mb-1 gap-2", children: [_jsx("span", { className: "text-[#A11D33] font-bold text-sm", children: name }), role && (_jsx("span", { className: "text-[#333] bg-[#FEEBCB] border border-[#F8D29B] px-2 py-0.5 rounded text-xs font-medium", children: role })), pin && (_jsxs("div", { className: "bg-gray-100 text-sm text-gray-800 rounded-full px-2 py-1 flex items-center gap-1 w-fit", children: [_jsx(FontAwesomeIcon, { icon: faThumbtack, className: "text-orange-500 rotate-45" }), _jsx("span", { children: "pinned" })] })), _jsx("span", { className: "text-xs text-gray-500", children: formatTimeAgo(time) })] }), _jsxs("p", { className: "text-sm", children: [replied_user && (_jsxs("span", { className: "text-blue-500", children: ["@", replied_user, " "] })), comment] })] }), userId !== "" && userId !== undefined && userId !== null && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "ml-5 mt-2 flex gap-4 items-center text-sm", children: [_jsxs("button", { onClick: handleToggleLike, className: "flex items-center cursor-pointer gap-1 hover:scale-105 transition-all duration-200", children: [_jsx(FontAwesomeIcon, { icon: liked ? solidThumbsUp : regularThumbsUp, className: `text-[22px] ${liked ? "text-[#DA1E37]" : "text-gray-500"}` }), _jsx("span", { className: "text-gray-700", children: likeCount })] }), _jsx("button", { onClick: onReplyClick, className: "text-black hover:underline cursor-pointer", children: "Reply" }), _jsx("button", { onClick: handleTogglePin, className: "text-black hover:underline cursor-pointer", children: pinned ? "Unpin" : "Pin" })] }), isReplying && (_jsx(CommentInput, { userId: userId, threadId: threadId, parentId: id, onSuccess: () => {
onReplyClick?.();
onRefresh();
}, name: name }))] }))] })] }));
}