source: chapterx-frontend/src/components/story/LikeButton.tsx@ 73b69b2

main
Last change on this file since 73b69b2 was 73b69b2, checked in by kikisrbinoska <srbinoskakristina07@…>, 3 months ago

Fixed reading lists,comments and likes

  • Property mode set to 100644
File size: 3.2 KB
Line 
1import React, { useEffect, useState } from 'react'
2import { Heart } from 'lucide-react'
3import { useNavigate } from 'react-router-dom'
4import axios from 'axios'
5import { useAuthStore } from '../../store/authStore'
6import { useNotificationStore } from '../../store/notificationStore'
7import { useUIStore } from '../../store/uiStore'
8
9const API = 'https://localhost:7125/api'
10
11function getAuthHeaders() {
12 try {
13 const token = JSON.parse(localStorage.getItem('chapterx-auth') || '{}')?.state?.token
14 return token ? { Authorization: `Bearer ${token}` } : {}
15 } catch { return {} }
16}
17
18interface LikeButtonProps {
19 storyId: number
20 authorUserId: number
21 totalLikes: number
22 onCountChange?: (count: number) => void
23}
24
25export const LikeButton: React.FC<LikeButtonProps> = ({ storyId, authorUserId, totalLikes, onCountChange }) => {
26 const navigate = useNavigate()
27 const { currentUser } = useAuthStore()
28 const { addNotification } = useNotificationStore()
29 const { addToast } = useUIStore()
30 const [liked, setLiked] = useState(false)
31 const [count, setCount] = useState(totalLikes)
32 const [loading, setLoading] = useState(false)
33
34 useEffect(() => {
35 axios.get(`${API}/likes/story/${storyId}`)
36 .then(res => {
37 const c = res.data?.count ?? totalLikes
38 setCount(c)
39 onCountChange?.(c)
40 if (currentUser) {
41 setLiked((res.data?.userIds ?? []).includes(currentUser.user_id))
42 }
43 })
44 .catch(() => {})
45 }, [storyId, currentUser?.user_id])
46
47 const handleClick = async () => {
48 if (!currentUser) {
49 addToast('Please sign in to like stories.', 'info')
50 navigate('/login')
51 return
52 }
53 if (loading) return
54 setLoading(true)
55 try {
56 if (liked) {
57 await axios.delete(`${API}/likes/user/${currentUser.user_id}/story/${storyId}`, { headers: getAuthHeaders() })
58 setLiked(false)
59 setCount(c => { const n = c - 1; onCountChange?.(n); return n })
60 addToast('Removed from likes', 'info')
61 } else {
62 await axios.post(`${API}/likes`, { userId: currentUser.user_id, storyId }, { headers: getAuthHeaders() })
63 setLiked(true)
64 setCount(c => { const n = c + 1; onCountChange?.(n); return n })
65 if (currentUser.user_id !== authorUserId) {
66 await addNotification({
67 recipientUserId: authorUserId,
68 type: 'like',
69 content: `${currentUser.username} liked your story.`,
70 link: `/story/${storyId}`,
71 })
72 }
73 addToast('Added to likes!', 'success')
74 }
75 } catch {
76 addToast('Something went wrong.', 'error')
77 }
78 setLoading(false)
79 }
80
81 return (
82 <button
83 onClick={handleClick}
84 disabled={loading}
85 className={`flex items-center gap-2 px-4 py-2 rounded-xl border transition-all duration-200 ${
86 liked
87 ? 'bg-rose-500/20 border-rose-500/40 text-rose-400 hover:bg-rose-500/30'
88 : 'bg-slate-800 border-slate-700 text-slate-400 hover:border-rose-500/40 hover:text-rose-400 hover:bg-rose-500/10'
89 }`}
90 >
91 <Heart size={16} className={liked ? 'fill-rose-400' : ''} />
92 <span className="text-sm font-medium">{count.toLocaleString()}</span>
93 </button>
94 )
95}
Note: See TracBrowser for help on using the repository browser.