CMU Coding Bootcamp
1import { useParams, Outlet } from "react-router";
2import { posts } from "../lib/post";
3import { Link } from "react-router";
4import { ContentState, convertFromRaw, Editor, EditorState } from "draft-js";
5import { useState } from "react";
6import { useNavigate } from "react-router";
7
8export function BlogPostDetail({
9 deletePost,
10}: {
11 deletePost: (id: number) => void;
12}) {
13 const { postId } = useParams();
14 const post = posts.find((post) => post.id === parseInt(postId!));
15 const [editorState, setEditorState] = useState(() => {
16 try {
17 const data = JSON.parse(`"${post?.content ?? ""}"`);
18 return EditorState.createWithContent(convertFromRaw(data));
19 } catch {
20 console.log("fallback");
21 return EditorState.createWithContent(
22 ContentState.createFromText(post?.content ?? ""),
23 );
24 }
25 });
26 const navigate = useNavigate();
27
28 if (!post) {
29 return <div>Post not found</div>;
30 }
31
32 const formattedDate = new Date(post.datePosted).toLocaleDateString("en-US", {
33 month: "long",
34 day: "numeric",
35 year: "numeric",
36 });
37
38 return (
39 <>
40 <title>{post.title}</title>
41 <div className="md:grid md:grid-cols-3 flex flex-col w-full">
42 <Link
43 to="/"
44 className="text-gray-700 dark:text-gray-200 hover:text-gray-400 flex justify-center items-center w-16 mb-4 md:mb-0"
45 >
46 Home
47 </Link>
48 <h1 className="text-3xl md:text-4xl font-bold text-center mb-4 md:mb-0">
49 {post.title}
50 </h1>
51 <div className="flex md:justify-end items-center">
52 <Link to={`/post?postId=${post.id}`} className="w-1/3">
53 <div className="bg-blue-500 hover:bg-blue-700 text-white w-full font-bold py-2 px-4 rounded cursor-pointer text-center">
54 Edit Post
55 </div>
56 </Link>
57 </div>
58 </div>
59 <div className="flex flex-col gap-1 md:gap-2.5 justify-center items-center mb-1.5 md:mb-2.5">
60 <p className="text-gray-700 dark:text-gray-400 text-sm md:text-lg">
61 By: {post.author}
62 </p>
63 <p className="text-gray-600 dark:text-gray-500 text-xs md:text-base">
64 Published on {formattedDate}
65 </p>
66 </div>
67 <div className="text-sm md:text-lg md:w-3xl w-full md:mb-10">
68 <Editor
69 editorState={editorState}
70 onChange={setEditorState}
71 readOnly={true}
72 />
73 </div>
74 <button
75 className="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded cursor-pointer w-full md:w-3xl"
76 onClick={() => {
77 if (window.confirm("Are you sure you want to delete this post?")) {
78 deletePost(post.id);
79 navigate("/");
80 }
81 }}
82 >
83 Delete
84 </button>
85 </>
86 );
87}
88
89export function PostLayout() {
90 return (
91 <div className="flex flex-col justify-center gap-3.5 md:gap-5 items-center p-5 w-screen">
92 <Outlet />
93 </div>
94 );
95}