Fix engagement for news posts (guid-based)

News posts have id=0, causing early returns in engagement handlers.
Fixed by checking both postId and post?.guid:
- handleTruthVote
- handleLike
- refreshComments (fetch comments)
- Initial data fetch (recordView, fetchTruth)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Your Name 2026-01-31 20:17:49 +00:00
parent fca617681a
commit 53b6426a34
2 changed files with 20 additions and 11 deletions

View File

@ -1,7 +1,7 @@
{
"name": "sociowire-frontend",
"private": true,
"version": "0.0.136",
"version": "0.0.180",
"type": "module",
"scripts": {
"dev": "vite --host 0.0.0.0",

View File

@ -559,7 +559,7 @@ export default function PostDetailModal({ post, onClose, onPostUpdated, onPostDe
shares: post?.share_count || 0, comments: post?.comment_count || 0,
});
const [liked, setLiked] = useState(false);
const [truth, setTruth] = useState({ score: 50, count: 0 });
const [truth, setTruth] = useState({ score: 50, count: 0, userVote: null });
const [authorAvatar, setAuthorAvatar] = useState("");
const [commenterAvatars, setCommenterAvatars] = useState({});
const [comments, setComments] = useState([]);
@ -623,12 +623,12 @@ export default function PostDetailModal({ post, onClose, onPostUpdated, onPostDe
// Initial data fetch
useEffect(() => {
if (!postId) return;
if (!postId && !post?.guid) return;
recordPostView(postId, post?.guid, post?.app_id).then(res => {
if (res?.counts) setCounts(c => ({ ...c, views: res.counts.view_count || c.views, likes: res.counts.like_count || c.likes }));
});
fetchPostLikeState(postId).then(res => { if (res?.liked !== undefined) setLiked(res.liked); });
fetchPostTruth(postId).then(res => { if (res) setTruth({ score: res.truth_score ?? res.user_score ?? 50, count: res.vote_count ?? 0 }); });
fetchPostTruth(postId, post?.guid, post?.app_id).then(res => { if (res) setTruth({ score: res.truth_score ?? res.user_score ?? 50, count: res.vote_count ?? 0, userVote: res.user_vote || null }); });
}, [postId]);
// Fetch full post data from API to get image_urls (map markers don't have it)
@ -666,8 +666,8 @@ export default function PostDetailModal({ post, onClose, onPostUpdated, onPostDe
// Fetch comments
const refreshComments = useCallback(async (autoOpen = false) => {
if (!postId) return;
const items = await fetchPostComments(postId, 50);
if (!postId && !post?.guid) return;
const items = await fetchPostComments(postId, 50, post?.guid, post?.app_id);
if (Array.isArray(items)) {
setComments(items);
setCounts(c => ({ ...c, comments: items.length }));
@ -686,7 +686,7 @@ export default function PostDetailModal({ post, onClose, onPostUpdated, onPostDe
// Handlers
const handleLike = useCallback(async () => {
if (!postId) return;
if (!postId && !post?.guid) return;
const newLiked = !liked;
setLiked(newLiked);
setCounts(c => ({ ...c, likes: c.likes + (newLiked ? 1 : -1) }));
@ -716,13 +716,14 @@ export default function PostDetailModal({ post, onClose, onPostUpdated, onPostDe
}, [postId, post?.title, post?.guid, post?.app_id]);
const handleTruthVote = useCallback(async (vote) => {
if (!postId) return;
if (!postId && !post?.guid) return;
if (!token) {
window.dispatchEvent(new CustomEvent("sociowire:auth-required"));
return;
}
// User can switch their vote by clicking the opposite button
const res = await votePostTruth(postId, vote, post?.guid, post?.app_id);
if (res) setTruth({ score: res.truth_score ?? res.user_score ?? truth.score, count: res.vote_count ?? truth.count });
if (res) setTruth({ score: res.truth_score ?? res.user_score ?? truth.score, count: res.vote_count ?? truth.count, userVote: res.user_vote || vote });
}, [postId, truth, token, post?.guid, post?.app_id]);
const handleComment = useCallback(async () => {
@ -1057,7 +1058,11 @@ export default function PostDetailModal({ post, onClose, onPostUpdated, onPostDe
{/* Mini Truth Score */}
<div className="flex items-center gap-1.5 px-2 py-1 rounded-lg bg-themed-elevated">
<motion.button whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.9 }} onClick={() => handleTruthVote("false")}
className="w-6 h-6 rounded-full bg-red-500/20 text-red-400 flex items-center justify-center hover:bg-red-500/30 text-xs">
className={`w-6 h-6 rounded-full flex items-center justify-center text-xs transition-all ${
truth.userVote === "false"
? "bg-red-500 text-white ring-2 ring-red-300"
: "bg-red-500/20 text-red-400 hover:bg-red-500/30"
}`}>
<i className="fa-solid fa-thumbs-down" />
</motion.button>
<div className="flex items-center gap-1 min-w-[50px]">
@ -1070,7 +1075,11 @@ export default function PostDetailModal({ post, onClose, onPostUpdated, onPostDe
</span>
</div>
<motion.button whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.9 }} onClick={() => handleTruthVote("true")}
className="w-6 h-6 rounded-full bg-emerald-500/20 text-emerald-400 flex items-center justify-center hover:bg-emerald-500/30 text-xs">
className={`w-6 h-6 rounded-full flex items-center justify-center text-xs transition-all ${
truth.userVote === "true"
? "bg-emerald-500 text-white ring-2 ring-emerald-300"
: "bg-emerald-500/20 text-emerald-400 hover:bg-emerald-500/30"
}`}>
<i className="fa-solid fa-thumbs-up" />
</motion.button>
</div>