Skip to content

Commit

Permalink
added comment
Browse files Browse the repository at this point in the history
  • Loading branch information
jummapr committed Aug 25, 2023
1 parent 8c21b6b commit 47a9dec
Show file tree
Hide file tree
Showing 5 changed files with 410 additions and 2 deletions.
30 changes: 29 additions & 1 deletion app/(root)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
import { fetchPost } from "@/lib/actions/thread.action";
import { UserButton } from "@clerk/nextjs";
import Image from "next/image";
import { currentUser } from "@clerk/nextjs";
import ThreadCard from "@/components/cards/ThreadCard";

export default function Home() {
export default async function Home() {
const result = await fetchPost(1, 30);
const user = await currentUser();

console.log(result);
return (
<div>
<h1 className="head-text text-left">Home</h1>
<section className="mt-9 flex flex-col gap-10">
{result.posts.length === 0 ? (
<p className="no-result ">No threads found</p>
) : (
<>
{result.posts.map((post) => (
<ThreadCard
key={post._id}
id={post._id}
currentUserId={user?.id || ""}
parentId={post.parentId}
content={post.text}
author={post.author}
community={post.community}
createdAt={post.createdAt}
comments={post.children}
/>
))}
</>
)}
</section>
</div>
);
}
63 changes: 63 additions & 0 deletions app/(root)/thread/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import ThreadCard from "@/components/cards/ThreadCard";
import React from "react";
import { currentUser } from "@clerk/nextjs";
import { fetchUser } from "@/lib/actions/user.actions";
import { redirect } from "next/navigation";
import { fetchThreadById } from "@/lib/actions/thread.action";
import Comment from "@/components/forms/Comment";

const page = async ({ params }: { params: { id: string } }) => {
if (!params.id) return null;

const user = await currentUser();
if (!user) return null;

const userInfo = await fetchUser(user.id);

if (!userInfo?.onboarded) redirect("/onboarding");

const thread = await fetchThreadById(params.id);

return (
<section className="relative ">
<div>
<ThreadCard
key={thread._id}
id={thread._id}
currentUserId={user?.id || ""}
parentId={thread.parentId}
content={thread.text}
author={thread.author}
community={thread.community}
createdAt={thread.createdAt}
comments={thread.children}
/>
</div>
<div className="mt-7 ">
<Comment
threadId={thread.id}
currentUserImg={userInfo.image}
currentUserId={JSON.stringify(userInfo._id)}
/>
</div>
<div className="mt-10">
{thread.children.map((childItem: any) => (
<ThreadCard
key={childItem._id}
id={childItem._id}
currentUserId={childItem?.id || ""}
parentId={childItem.parentId}
content={childItem.text}
author={childItem.author}
community={childItem.community}
createdAt={childItem.createdAt}
comments={childItem.children}
isComment
/>
))}
</div>
</section>
);
};

export default page;
117 changes: 117 additions & 0 deletions components/cards/ThreadCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import Image from "next/image";
import Link from "next/link";
import React from "react";

interface ThreadCardProps {
id: string;
currentUserId: string;
parentId: string | null;
content: string;
author: {
name: string;
image: string;
id: string;
};
community: {
id: string;
name: string;
image: string;
} | null;
createdAt: string;
comments: {
author: {
image: string;
};
}[];
isComment?: boolean;
}

const ThreadCard = ({
id,
currentUserId,
parentId,
content,
author,
community,
createdAt,
comments,
isComment
}: ThreadCardProps) => {
return (
<article className={`flex w-full flex-col rounded-xl ${isComment? "px-0 xs:px-7" : "bg-dark-2 p-7"}`}>
<div className="flex items-start justify-between">
<div className="flex w-full flex-1 flex-row gap-4">
<div className="flex flex-col items-center">
<Link
href={`/profile/${author.id}`}
className="relative h-11 w-11"
>
<Image
src={author.image}
alt="Profile Image"
fill
className="cursor-pointer rounded-full"
/>
</Link>

<div className="thread-card_bar" />
</div>

<div className="flex w-full flex-col">
<Link href={`/profile/${author.id}`} className="w-fit">
<h4 className="cursor-pointer text-base-semibold text-light-1">
{author.name}
</h4>
</Link>

<p className="mt-2 text-small-regular text-light-2">{content}</p>
<div className="mt-5 flex flex-col gap-3">
<div className="flex gap-3.5">
<Image
src={"/assets/heart-gray.svg"}
alt="heart"
width={24}
height={24}
className="cursor-pointer object-contain"
/>
<Link href={`/thread/${id}`}>
<Image
src={"/assets/reply.svg"}
alt="reply"
width={24}
height={24}
className="cursor-pointer object-contain"
/>
</Link>
<Image
src={"/assets/repost.svg"}
alt="repost"
width={24}
height={24}
className="cursor-pointer object-contain"
/>
<Image
src='/assets/share.svg'
alt='heart'
width={24}
height={24}
className='cursor-pointer object-contain'
/>
</div>

{
isComment && comments.length > 0 && (
<Link href={`/thread/${id}`}>
<p className="mt-1 text-subtle-medium text-gray-1">{comments.length} replies</p>
</Link>
)
}
</div>
</div>
</div>
</div>
</article>
);
};

export default ThreadCard;
87 changes: 87 additions & 0 deletions components/forms/Comment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"use client";

import { useForm } from "react-hook-form";
import * as z from "zod";
import { usePathname, useRouter } from "next/navigation";

import { Button } from "@/components/ui/button";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Input } from "@/components/ui/input";

import { CommentValidation } from "@/lib/validation/Thread";
import { addCommentToThread } from "@/lib/actions/thread.action";
import Image from "next/image";

interface CommentProps {
threadId: string;
currentUserImg: string;
currentUserId: string;
}

const Comment = ({ threadId, currentUserImg, currentUserId }: CommentProps) => {

const router = useRouter();
const pathname = usePathname();

const form = useForm({
resolver: zodResolver(CommentValidation),
defaultValues: {
thread: "",
},
});

const onSubmit = async (values: z.infer<typeof CommentValidation>) => {
await addCommentToThread(threadId,values.thread, JSON.parse(currentUserId),pathname);

form.reset();
};

return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="comment-form"
>
<FormField
control={form.control}
name="thread"
render={({ field }) => (
<FormItem className="flex w-full items-center gap-3">
<FormLabel>
<Image
src={currentUserImg}
alt="Profile Image"
width={48}
height={48}
className="rounded-full object-cover"
/>
</FormLabel>
<FormControl className="border-none bg-transparent">
<Input
type="text"
placeholder="Comment..."
className="no-focus text-light-1 outline-none"
{...field}
/>
</FormControl>
</FormItem>
)}
/>
<Button type="submit" className="comment-form_btn">
Reply
</Button>
</form>
</Form>
);
};

export default Comment;
Loading

0 comments on commit 47a9dec

Please sign in to comment.