import RootLayout from "~/layout/RootLayout"; import type { Route } from "../+types/root"; import { useNavigate, useParams } from "react-router"; import { useEffect, useState, type FormEventHandler } from "react"; import { API } from "~/api/api"; import Icon, { ICONS } from "~/components/Icon"; import { getTagColor } from "../utils/tags"; import type { Post } from "~/types/post"; import Modal from "~/components/Modal"; import type { Comment } from "~/types/comment"; import Loading from "~/components/Loading"; import { useAuth } from "~/context/AuthContext"; import { NotFound } from "~/components/NotFound"; import type { PaginatedResponse } from "~/types/PaginatedResponse"; type ActionButtonProps = { onClick?: React.MouseEventHandler; icon: string; children: React.ReactNode; className?: string; }; export function meta({}: Route.MetaArgs) { return [ { title: "ImgBoard - Viewing Post" }, ]; } function formatDate(dateString: string): string { const date = new Date(dateString); return date.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); } export default function Post() { const { id } = useParams(); const navigate = useNavigate(); if (!id) { return } const idNum = parseInt(id, 10); if (isNaN(idNum)) { return } const [post, setPost] = useState(null); const [isEditPostModalOpen, setIsEditPostModalOpen] = useState(false); const [paginatedComments, setPaginatedComments] = useState | null>(null); const [currentCommentPage, setCurrentCommentPage] = useState(1); const [commentToEdit, setCommentToEdit] = useState(null); const [isEditCommentModalOpen, setIsEditCommentModalOpen] = useState(false); console.log("Post ID from params:", id); useEffect(() => { // Fetch post details using the id console.log(`Fetching post with id: ${id}`); async function fetchData() { const post = await API.fetchPostById(idNum); setPost(post); } fetchData(); }, [id]); useEffect(() => { async function fetchComments() { const comments = await API.fetchCommentsByPostId(idNum, currentCommentPage); setPaginatedComments(comments); } fetchComments(); }, [id, currentCommentPage]); const { user } = useAuth(); if (!post) { return ; } /** * Button component for actions like Edit, Delete, View Raw, etc. */ const ActionButton: React.FC = ({ onClick, icon, children, className }) => ( ); const Pagination = ({ itemsPerPage, totalItems, paginate, currentPage, }: { itemsPerPage: number; totalItems: number; paginate: (pageNumber: number) => void; currentPage: number; }) => { const pageNumbers = []; for (let i = 1; i <= Math.ceil(totalItems / itemsPerPage); i++) { pageNumbers.push(i); } if(pageNumbers.length <= 1) return null; return ( ); }; const EditPostModal = () => { const [title, setTitle] = useState(''); const [description, setDescription] = useState(''); const [tags, setTags] = useState(''); const [error, setError] = useState(''); useEffect(() => { if (post) { setTitle(post.title); setDescription(post.description); setTags(post.tags.map(t => t.name).join(' ')); } }, [post]); const handleSubmit: FormEventHandler = async (e) => { e.preventDefault(); setError(''); if (!user) return; const enteredTags = tags.split(' ').filter(t => t); if (title && description && tags) { const res = await API.updatePost(post.id, title, description, enteredTags, user); const data = await res.json(); if (!res.ok) { setError(data.detail || "Failed to update post."); return; } setPost(data); setIsEditPostModalOpen(false); } }; if (!post) return null; return ( setIsEditPostModalOpen(false)}>

Edit Post

setTitle(e.target.value)} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700"/>
{error &&

{error}

} ); }; const EditCommentModal = () => { const [newText, setNewText] = useState(commentToEdit?.text || ''); useEffect(() => { if (commentToEdit) { setNewText(commentToEdit.text); } }, [commentToEdit]); const handleSubmit: FormEventHandler = async (e) => { e.preventDefault(); if (newText && commentToEdit && newText !== commentToEdit.text && user) { // TODO const res = await API.updateComment(post.id, commentToEdit.id, newText, user); if (!res.ok) { alert("Failed to update comment."); return; } setPaginatedComments(prev => prev ? { ...prev, items: prev.items.map(c => c.id === commentToEdit.id ? {...c, text: newText} : c) } : null); } setIsEditCommentModalOpen(false) }; return ( setIsEditCommentModalOpen(false)}>

Edit Comment