import { useEffect, useState } from "react"; import { Link } from "react-router-dom"; function getImageFilename(post) { return post.image || post.image_filename || post.filename || null; } function getAuthorName(post, authorId) { return post.author?.name || post.author_name || (post.author_username ? `@${post.author_username}` : `User ${authorId || ""}`); } function getAuthorUsername(post) { return post.author_username || post.author?.username || null; } function getInitials(name) { if (!name) return "?"; const cleaned = name.replace(/^@/, ""); return cleaned .split(" ") .filter(Boolean) .slice(0, 2) .map((part) => part[0]) .join("") .toUpperCase() || "?"; } function formatDate(timestamp) { if (!timestamp) return null; try { const date = new Date(timestamp); if (Number.isNaN(date.getTime())) return String(timestamp); return new Intl.DateTimeFormat("en-US", { month: "short", day: "numeric", year: "numeric", hour: "numeric", minute: "2-digit", }).format(date); } catch { return String(timestamp); } } function AuthenticatedImage({ filename, alt, loadImage }) { const [source, setSource] = useState(""); const [error, setError] = useState(""); useEffect(() => { let active = true; let objectUrl = ""; if (!filename) { setSource(""); return () => {}; } loadImage(filename) .then((blob) => { if (active) { objectUrl = URL.createObjectURL(blob); setSource(objectUrl); } }) .catch(() => { if (active) { setError("Image unavailable."); } }); return () => { active = false; if (objectUrl) { URL.revokeObjectURL(objectUrl); } }; }, [filename, loadImage]); if (error) { return

{error}

; } return source ? {alt} : null; } export function PostCard({ post, currentUserId, loadImage, onEdit, onDelete }) { const [editing, setEditing] = useState(false); const [form, setForm] = useState({ title: post.title || "", text: post.text || "", image: null, removeImage: false }); const [error, setError] = useState(""); const authorId = post.author_id ?? post.authorId ?? post.author?.id; const isOwner = authorId !== undefined && String(authorId) === String(currentUserId); const imageFilename = getImageFilename(post); const authorName = getAuthorName(post, authorId); const authorUsername = getAuthorUsername(post); const formattedDate = formatDate(post.created_at || post.createdAt); async function handleEdit(event) { event.preventDefault(); setError(""); if (form.image && form.removeImage) { setError("An image cannot be uploaded and removed at the same time."); return; } try { await onEdit(post.id, form); setEditing(false); } catch (editError) { setError(editError.message || "Unable to edit post."); } } async function handleDelete() { if (!window.confirm("Delete this post?")) { return; } try { await onDelete(post.id); } catch (deleteError) { setError(deleteError.message || "Unable to delete post."); } } const profilePath = authorId ? `/profile/${authorId}` : "/profile"; return (
{getInitials(authorName)}
{authorName} {authorUsername && !authorName.startsWith("@") ? ( @{authorUsername} ) : null}
{formattedDate ? {formattedDate} : null} {isOwner && !editing ? (
) : null}
{editing ? (