HotTRDealsFrontend/src/components/DealDetails/DealComments.tsx
cureb a48d32fdec created image array
ui overhaul
2026-01-23 17:28:05 +00:00

170 lines
6.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useState } from "react"
import { Link } from "react-router-dom"
import { Heart, MessageCircle, MoreHorizontal } from "lucide-react"
import { getComments, postComment } from "../../api/deal/commentDeal"
import { useAuth } from "../../context/AuthContext"
import { timeAgo } from "../../utils/timeAgo"
import type { Comment } from "../../models/comment/Comment"
type DealCommentsProps = {
dealId: number
onRequireLogin: () => void
}
export default function DealComments({ dealId, onRequireLogin }: DealCommentsProps) {
const [comments, setComments] = useState<Comment[]>([])
const [newComment, setNewComment] = useState("")
const [loading, setLoading] = useState(false)
const { isAuthenticated } = useAuth()
useEffect(() => {
async function loadComments() {
try {
const data = await getComments(dealId)
setComments(data)
} catch (err) {
console.error("Yorumlar alınamadı:", err)
}
}
loadComments()
}, [dealId])
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (!newComment.trim()) return
if (!isAuthenticated) return onRequireLogin()
setLoading(true)
try {
const added = await postComment(dealId, newComment)
setComments((prev) => [added, ...prev])
setNewComment("")
} catch (err: any) {
console.error(err)
alert(err.message || "Sunucu hatası")
} finally {
setLoading(false)
}
}
return (
<div className="rounded-3xl bg-surface border border-white/10 p-5 flex flex-col">
{/* Header */}
<div className="flex items-center justify-between gap-3">
<h2 className="text-lg font-semibold text-text">Yorumlar</h2>
<span className="text-xs text-text-muted bg-background border border-white/10 rounded-full px-3 py-1">
{comments.length}
</span>
</div>
{/* List: only desktop scroll */}
<div className="mt-4 flex-1 lg:max-h-[calc(100vh-280px)] lg:overflow-y-auto pr-2">
{comments.length > 0 ? (
<div className="divide-y divide-white/10">
{comments.map((c) => (
<div key={c.id} className="py-5 first:pt-0 last:pb-0">
<div className="flex gap-3">
<Link to={`/user/${c.user.username}`} className="shrink-0">
<img
src={
c.user.avatarUrl ||
`${import.meta.env.BASE_URL}placeholders/placeholder-profile.png`
}
alt={c.user.username}
className="w-16 h-16 rounded-full object-cover border border-white/10"
/>
</Link>
<div className="min-w-0 flex-1">
<div className="flex items-center justify-between gap-3">
<div className="min-w-0 flex items-center gap-2">
<Link
to={`/user/${c.user.username}`}
className="text-lg font-semibold text-text hover:underline truncate"
>
{c.user.username}
</Link>
<span className="text-xs text-text-muted">
{timeAgo(c.createdAt)}
</span>
</div>
<button
type="button"
className="inline-flex items-center justify-center rounded-lg p-2 bg-background border border-white/10 text-text-muted hover:text-text hover:border-white/20 transition"
aria-label="Yorum seçenekleri"
>
<MoreHorizontal className="w-4 h-4" />
</button>
</div>
<p className="mt-2 text-base text-text leading-relaxed whitespace-pre-line">
{c.text}
</p>
<div className="mt-3 flex items-center gap-2">
<button
type="button"
className="inline-flex items-center gap-2 rounded-lg px-3 py-2 text-xs font-semibold bg-background border border-white/10 text-text-muted hover:text-primary hover:border-white/20 transition"
>
<Heart className="w-4 h-4" />
<span>25</span>
</button>
<button
type="button"
className="inline-flex items-center gap-2 rounded-lg px-3 py-2 text-xs font-semibold bg-background border border-white/10 text-text-muted hover:text-primary hover:border-white/20 transition"
>
<MessageCircle className="w-4 h-4" />
<span>Yanıtla</span>
</button>
</div>
</div>
</div>
</div>
))}
</div>
) : (
<div className="rounded-2xl bg-background border border-white/10 p-4 text-center">
<div className="text-sm font-semibold text-text">Henüz yorum yok</div>
<div className="text-xs text-text-muted mt-1">
İlk yorumu sen yazabilirsin.
</div>
</div>
)}
</div>
{/* Footer (always visible) */}
<div className="mt-5 pt-5 border-t border-white/10">
{isAuthenticated ? (
<form onSubmit={handleSubmit} className="flex items-center gap-3">
<input
type="text"
value={newComment}
onChange={(e) => setNewComment(e.target.value)}
placeholder="Yorum ekle..."
className="flex-1 rounded-xl border border-white/10 bg-background px-4 py-3 text-sm text-text placeholder:text-text-muted/70 outline-none focus:ring-2 focus:ring-primary/40"
disabled={loading}
/>
<button
type="submit"
disabled={loading}
className="shrink-0 rounded-xl px-5 py-3 text-sm font-semibold bg-primary text-black hover:bg-primary-hover transition disabled:opacity-60 disabled:cursor-not-allowed"
>
{loading ? "..." : "Gönder"}
</button>
</form>
) : (
<button
type="button"
onClick={onRequireLogin}
className="w-full rounded-xl border border-white/10 bg-background px-4 py-3 text-sm font-semibold text-primary hover:border-white/20 transition"
>
Yorum yazmak için giriş yap veya kayıt ol
</button>
)}
</div>
</div>
)
}