返回 JoyAI-Echo
LikeButton.tsx
1 import { cn } from "@/lib/utils";
2 import { ThumbsDown, ThumbsUp } from "lucide-react";
3 import { useEffect, useState } from "react";
4
5 export type LikeType = 1;
6 export type UnLikeType = 2;
7 export type DefaultType = 0;
8 export type LikeButtonType = LikeType | UnLikeType | DefaultType;
9
10 export function LikeButton(props: {
11 echoRequestId?: string | null;
12 likeStatus?: LikeButtonType;
13 onLike?: (action: 1 | 2) => Promise<void>;
14 className: string;
15 spanClassName?: string;
16 }) {
17 const {
18 echoRequestId,
19 likeStatus = 0,
20 onLike,
21 className,
22 spanClassName = "bg-foreground/40 hover:bg-foreground/80",
23 } = props;
24
25 const [liked, setLiked] = useState<LikeButtonType>(likeStatus);
26
27 useEffect(() => {
28 setLiked(likeStatus);
29 }, [likeStatus]);
30 console.log("likeStatus", likeStatus, echoRequestId);
31 // if (!echoRequestId) return null;
32
33 const handleLike = async (type: 1 | 2) => {
34 if (!onLike) return;
35 const prev = liked;
36 const optimistic: LikeButtonType = prev === type ? 0 : type;
37 setLiked(optimistic);
38 try {
39 await onLike(type);
40 } catch (err) {
41 setLiked(prev);
42 console.warn("failed to update like status", err);
43 }
44 };
45
46 return (
47 <div className="flex items-center gap-2">
48 <button
49 type="button"
50 onClick={() => void handleLike(1)}
51 className={cn(
52 className,
53 liked === 1 ? "text-red-500 hover:text-red-500" : className,
54 )}
55 >
56 <ThumbsUp className="h-3 w-3" />
57 </button>
58 <span
59 className={cn("h-[10px] w-[1px] rounded-full", spanClassName)}
60 ></span>
61 <button
62 type="button"
63 onClick={() => void handleLike(2)}
64 className={cn(
65 className,
66 liked === 2 ? "text-gray-500 hover:text-gray-500" : className,
67 )}
68 >
69 <ThumbsDown
70 className="h-3 w-3"
71 fill={liked === 2 ? "currentColor" : "none"}
72 />
73 </button>
74 </div>
75 );
76 }
77
77 lines Plain Text