diff --git a/client/src/app/(post)/post/[slug]/page.tsx b/client/src/app/(post)/post/[slug]/page.tsx index 92843ec..480efb7 100644 --- a/client/src/app/(post)/post/[slug]/page.tsx +++ b/client/src/app/(post)/post/[slug]/page.tsx @@ -9,7 +9,7 @@ import { Button } from "~/components/ui/button"; import { FaPlus } from "react-icons/fa6"; import FullPost from "~/components/posts/fullpost"; import Comment from "~/components/comment/comment"; - +import CommentInput from "~/components/comment/commentInput"; function Page({ params }: { params: { slug: string } }) { const { getPost, getComments } = useFetcher(); const { data: postData, error: postError } = useSWR(`getPost/${params.slug}`, getPost); @@ -21,6 +21,7 @@ function Page({ params }: { params: { slug: string } }) { {postData && (
+
)} diff --git a/client/src/app/[username]/page.tsx b/client/src/app/[username]/page.tsx new file mode 100644 index 0000000..0788890 --- /dev/null +++ b/client/src/app/[username]/page.tsx @@ -0,0 +1,208 @@ +"use client"; + +import { useFetcher } from "~/hooks/fetcher"; +import React from "react"; +import { useState } from 'react'; +import useSWR from 'swr'; +import Link from 'next/link'; + +function UserProfile({ params }: { params: { username: string } }) { + const { getUser, getUserPosts, getUserComments, getUserFollowers, getUserFollowing, getUserSubscriptions, getUserPostVotes, getUserCommentVotes } = useFetcher(); + const { data: userProfile, error } = useSWR(`getUser/${params.username}`, getUser); + + const [selectedTab, setSelectedTab] = useState('posts'); + const endpoint = selectedTab === 'posts' ? `getUserPosts/${params.username}` : + selectedTab === 'comments' ? `getUserComments/${params.username}` : + selectedTab === 'followers' ? `getUserFollowers/${params.username}` : + selectedTab === 'following' ? `getUserFollowing/${params.username}` : + selectedTab === 'subscriptions' ? `getUserSubscriptions/${params.username}` : + selectedTab === 'postVotes' ? `getUserPostVotes/${params.username}` : + `getUserCommentVotes/${params.username}`; + + const fetcher = selectedTab === 'posts' ? getUserPosts : + selectedTab === 'comments' ? getUserComments : + selectedTab === 'followers' ? getUserFollowers : + selectedTab === 'following' ? getUserFollowing : + selectedTab === 'subscriptions' ? getUserSubscriptions : + selectedTab === 'postVotes' ? getUserPostVotes : + getUserCommentVotes; + + const { data: tabData } = useSWR(endpoint, fetcher); + const dataToDisplay = selectedTab === 'followers' ? tabData?.followers : + selectedTab === 'following' ? tabData?.followings : + tabData; + console.log(endpoint, dataToDisplay); + if (error) return
Error: {error.message}
+ if (!userProfile) return
Loading...
+ + return ( +
+
+
+
+ {userProfile.username} +

{userProfile.username}

+

{userProfile.email}

+

{userProfile.aboutMe}

+

Social Media

+
+ GitHub + Twitter + LinkedIn +
+
+
+
+
+

Stats

+
+
Reputation: {userProfile.reputation}
+
Posts: {userProfile.PostCount}
+
Comments: {userProfile.CommentCount}
+
Followers: {userProfile.followersCount}
+
Following: {userProfile.followingCount}
+
+
+
+
+
+

Basic Information

+
+
Last Login: {new Date(userProfile.lastLogin).toLocaleString() || 'Not available'}
+
Country: {userProfile.country || 'Not available'}
+
City: {userProfile.city || 'Not available'}
+
Phone: {userProfile.phone || 'Not available'}
+
Website: {userProfile.website || 'Not available'}
+
Join Time: {new Date(userProfile.createdAt).toLocaleString() || 'Not available'}
+
+
+
+
+
+
+
+ + + + + + + +
+
+ {dataToDisplay ? ( + dataToDisplay.length > 0 ? ( + dataToDisplay.map(item => { + switch (selectedTab) { + case 'posts': + return ( + +
+

{item.title}

+

{item.content}

+
+ + ); + case 'comments': + return ( + +
+

{item.content}

+

Upvotes: {item.upvotesCount}, Downvotes: {item.downvotesCount}

+
+ + ); + case 'followers': + case 'following': + return ( + +
+ {item.username} +

{item.username}

+

Reputation: {item.reputation}

+
+ + ); + case 'subscriptions': + return ( + +
+ {item.name} +

{item.name}

+

{item.description}

+
+ + ); + case 'postVotes': + return ( + +
+

{item.content}

+

Vote status: {item.voteStatus}, Upvotes: {item.upvotesCount}, Downvotes: {item.downvotesCount}

+
+ + ); + case 'commentVotes': + return ( + +
+

{item.content}

+

Vote status: {item.voteStatus}, Upvotes: {item.upvotesCount}, Downvotes: {item.downvotesCount}

+
+ + ); + default: + return null; + } + }) + ) : ( +

No data available.

+ ) + ) : ( +
+

Loading...

+
+ )} +
+
+
+
+ ); +}; + +export default UserProfile; diff --git a/client/src/app/layout.tsx b/client/src/app/layout.tsx index db45625..e30305b 100644 --- a/client/src/app/layout.tsx +++ b/client/src/app/layout.tsx @@ -14,8 +14,8 @@ import { dark } from "@clerk/themes"; const inter = Inter({ subsets: ["latin"] }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "WeGotThis Community", + description: "You are not alone. WeGotThis Community is here to help you.", }; export default function RootLayout({ diff --git a/client/src/app/search/[query]/page.tsx b/client/src/app/search/[query]/page.tsx new file mode 100644 index 0000000..4c53b0b --- /dev/null +++ b/client/src/app/search/[query]/page.tsx @@ -0,0 +1,29 @@ +"use client"; + +import React from "react"; +import { useFetcher } from "~/hooks/fetcher"; +import useSWR from "swr"; +import Post from "~/components/posts/post"; +import { Separator } from "@radix-ui/react-separator"; + + +function SearchPage({ params }: { params: { query: string } }) { + const { searchPosts } = useFetcher(); + const { data: results, error } = useSWR(`searchPosts/${params.query}`, searchPosts); + + if (error) return
Failed to load
+ if (!results) return
Loading...
+ + return ( +
+ {results.map((post: any) => ( +
+ + +
+ ))} +
+ ); +}; + +export default SearchPage; diff --git a/client/src/components/comment/commentInput.tsx b/client/src/components/comment/commentInput.tsx new file mode 100644 index 0000000..24f5537 --- /dev/null +++ b/client/src/components/comment/commentInput.tsx @@ -0,0 +1,56 @@ +import { useFetcher } from '~/hooks/fetcher'; +import Image from 'next/image'; +import Link from 'next/link'; +import { useState, useEffect } from 'react'; + +interface CommentInputProps { + postId: string; +} +interface User { + username: string; + avatarUrl: string; + } +const CommentInput: React.FC = ({ postId }) => { + const [content, setContent] = useState(''); + const [user, setUser] = useState(null); + const { postComment, getMe } = useFetcher(); + + useEffect(() => { + const fetchUser = async () => { + const userData = await getMe(); + setUser(userData); + }; + + fetchUser(); + }, []); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + await postComment(`postComment/${postId}`, content, null); + setContent(''); + }; + + return ( +
+ {user && ( + <> + + logo + +
+