Skip to content

Commit

Permalink
Merge pull request #77 from Code-Hammers/CHE-64/subtask/Create-Thread…
Browse files Browse the repository at this point in the history
…Details-Component

[CHE-64] Create ThreadDetails Component
  • Loading branch information
brok3turtl3 authored Apr 21, 2024
2 parents 3c2cd9c + 1d49f9f commit 175d75b
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 5 deletions.
62 changes: 62 additions & 0 deletions client/src/components/Forums/ThreadDetails/ThreadDetails.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React, { useEffect, useState } from "react";
import axios from "axios";
import { Thread, IPost } from "../../../../types/forums";

interface ThreadDetailProps {
forumId: string | null;
threadId: string;
}

const ThreadDetail: React.FC<ThreadDetailProps> = ({ forumId, threadId }) => {
const [thread, setThread] = useState<Thread | null>(null);
const [posts, setPosts] = useState<IPost[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

useEffect(() => {
const fetchThreadDetails = async () => {
setLoading(true);
try {
const endpoint = forumId
? `/api/forums/${forumId}/threads/${threadId}`
: `/api/forums/threads/${threadId}`;
const response = await axios.get(endpoint, { withCredentials: true });
setThread(response.data.thread);
setPosts(response.data.posts || []);

setLoading(false);
} catch (err) {
const error = err as Error;
setError(error.message);
setLoading(false);
}
};

fetchThreadDetails();
}, [forumId, threadId]);

if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
if (!thread) return <div>Thread not found.</div>;

return (
<div>
<h2 className="text-3xl font-bold">{thread.title}</h2>
<p className="my-4">{thread.content}</p>
<div>
<h3 className="text-2xl font-bold">Replies</h3>
{posts.map((post) => (
<div key={post._id} className="mb-4">
<p>{post.content}</p>
<small>
By {post.user.firstName} {post.user.lastName} on{" "}
{new Date(post.createdAt).toLocaleDateString()}
</small>
</div>
))}
</div>
</div>
);
};

export default ThreadDetail;
12 changes: 10 additions & 2 deletions client/src/components/Forums/ThreadsDisplay/ThreadsDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import { Thread, IForum } from "../../../../types/forums";

interface ThreadsDisplayProps {
forumId?: string | null;
onThreadSelect: (threadId: string) => void;
}

const ThreadsDisplay: React.FC<ThreadsDisplayProps> = ({ forumId }) => {
const ThreadsDisplay: React.FC<ThreadsDisplayProps> = ({
forumId,
onThreadSelect,
}) => {
const [threads, setThreads] = useState<Thread[]>([]);
const [forum, setForum] = useState<IForum | null>(null);
const [loading, setLoading] = useState(false);
Expand Down Expand Up @@ -50,7 +54,11 @@ const ThreadsDisplay: React.FC<ThreadsDisplayProps> = ({ forumId }) => {
</h3>
<ul>
{threads.map((thread) => (
<li key={thread._id} className="mb-2 p-2 bg-gray-800 rounded-lg">
<li
key={thread._id}
className="mb-2 p-2 bg-gray-800 rounded-lg cursor-pointer"
onClick={() => onThreadSelect(thread._id)}
>
<h4 className="font-bold">{thread.title}</h4>
<p>{thread.content}</p>
<small>
Expand Down
20 changes: 19 additions & 1 deletion client/src/pages/Forums/Forums.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import React, { useState } from "react";
import ForumsList from "../../components/Forums/ForumsList/ForumsList";
import ThreadsDisplay from "../../components/Forums/ThreadsDisplay/ThreadsDisplay";
import ThreadDetails from "../../components/Forums/ThreadDetails/ThreadDetails";

const Forums = (): JSX.Element => {
const [selectedForumId, setSelectedForumId] = useState<string | null>(null);
const [selectedThreadId, setSelectedThreadId] = useState<string | null>(null);

const handleForumSelect = (forumId: string | null) => {
setSelectedForumId(forumId);
setSelectedThreadId(null);
};

const handleThreadSelect = (threadId: string) => {
setSelectedThreadId(threadId);
};

return (
<div className="min-h-screen bg-gray-900 text-white flex pt-40 px-4">
<div className="w-64 md:w-1/4 lg:w-1/5 p-4 bg-gradient-to-r from-gray-700 via-gray-800 to-gray-900 overflow-y-auto">
Expand All @@ -18,7 +26,17 @@ const Forums = (): JSX.Element => {
</div>

<div className="flex-1 p-4 overflow-y-auto">
<ThreadsDisplay forumId={selectedForumId} />
{selectedThreadId ? (
<ThreadDetails
forumId={selectedForumId}
threadId={selectedThreadId}
/>
) : (
<ThreadsDisplay
forumId={selectedForumId}
onThreadSelect={handleThreadSelect}
/>
)}
</div>
</div>
);
Expand Down
7 changes: 7 additions & 0 deletions client/types/forums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,10 @@ export interface IForum {
_id: string;
title: string;
}

export interface IPost {
_id: string;
user: IUser;
content: string;
createdAt: string;
}
4 changes: 2 additions & 2 deletions server/controllers/threadController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ const getThreadById = async (
res: Response,
next: NextFunction
) => {
const { forumId, threadId } = req.params;
const { threadId } = req.params;

try {
const thread = await Thread.findOne({ _id: threadId, forum: forumId })
const thread = await Thread.findOne({ _id: threadId })
.populate("user", "firstName lastName")
.exec();

Expand Down
1 change: 1 addition & 0 deletions server/routes/forumRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { protect } from "../middleware/authMiddleware"; //TODO Add admin auth mi
const router = express.Router();

router.get("/threads", getAllThreads);
router.get("/threads/:threadId", protect, getThreadById);

//Forum Routes
router.post("/", protect, addForum); //TODO Protect with admin auth
Expand Down

0 comments on commit 175d75b

Please sign in to comment.