Skip to content

Commit

Permalink
feat(public-layout): scaffold - CommentsPage
Browse files Browse the repository at this point in the history
  • Loading branch information
yoopark committed Apr 21, 2024
1 parent dfd7964 commit 2750a90
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 5 deletions.
66 changes: 61 additions & 5 deletions app/(public)/users/[userHandle]/posts/[slug]/comments/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,71 @@
import { Fragment } from 'react';

import { randomInt } from 'crypto';
import { CornerDownRight } from 'lucide-react';

import {
AppBar,
AppBarBack,
AppBarTitle,
} from '@/components/ui-unstable/app-bar';
import { ChatInput } from '@/components/ui-unstable/chat-input';
import { CommentableListItem } from '@/features/comments-page/commentable-list-item';
import { generateCommentsWithReplies } from '@/lib/utils';

type CommentsPageProps = {
params: {
username: string;
userHandle: string;
slug: string;
};
};

const CommentsPage = ({ params: { username, slug } }: CommentsPageProps) => {
const commentWithRepliesCount = randomInt(1, 10);

const commentsWithReplies = generateCommentsWithReplies(
commentWithRepliesCount,
);

const CommentsPage = ({
params: { userHandle: _, slug: __ },
}: CommentsPageProps) => {
return (
<div>
CommentsPage (username: {username}, slug: {slug})
</div>
<>
<AppBar>
<AppBarBack />
<AppBarTitle>댓글</AppBarTitle>
</AppBar>
<div className="flex flex-col gap-2 px-4 pb-20 pt-14">
<div className="h-2" />
{commentsWithReplies.map((commentWithReplies, index) => (
<div key={index}>
<CommentableListItem
username={commentWithReplies.comment.user.username}
handle={commentWithReplies.comment.user.handle}
profileImage={commentWithReplies.comment.user.profileImage}
content={commentWithReplies.comment.content}
/>
<div className="relative ml-10 mt-2 flex flex-col gap-2">
{commentWithReplies.replies.map((reply, index) => (
<Fragment key={index}>
{index === 0 && (
<CornerDownRight className="absolute -left-7 top-2 h-4 w-4 text-blccu-neutral-400" />
)}
<CommentableListItem
username={reply.user.username}
handle={reply.user.handle}
profileImage={reply.user.profileImage}
content={reply.content}
/>
</Fragment>
))}
</div>
</div>
))}
</div>
<div className="fixed bottom-0 mx-auto h-20 w-full max-w-md bg-blccu-white/80 backdrop-blur">
<ChatInput />
</div>
</>
);
};

Expand Down
43 changes: 43 additions & 0 deletions components/ui-unstable/chat-input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use client';

import { useState } from 'react';

import { Send } from 'lucide-react';

import { IconButton } from '@/components/ui/icon-button';
import { cn } from '@/lib/utils';

const ChatInput = () => {
const [value, setValue] = useState<string>('');

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { value } = event.target;

setValue(value);
};

return (
<div
className={cn(
'mx-4 mt-4 flex items-center rounded-full bg-blccu-neutral-200/50 py-2 pl-7 pr-5',
'transition-shadow focus-within:outline-none focus-within:ring-1 focus-within:ring-blccu-ring',
)}
>
<input
className={cn(
'w-full bg-transparent',
'focus:outline-none',
'placeholder:text-blccu-neutral-400',
)}
placeholder="댓글을 작성하세요."
value={value}
onChange={handleChange}
/>
<IconButton className="ml-2">
<Send className="h-5 w-5 text-blccu-neutral-600" />
</IconButton>
</div>
);
};

export { ChatInput };
48 changes: 48 additions & 0 deletions features/comments-page/commentable-list-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Link from 'next/link';

import { EllipsisVertical } from 'lucide-react';

import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { IconButton } from '@/components/ui/icon-button';
import { ROUTES } from '@/constants/routes';
import { ReportCommentBottomActionSheet } from '@/features/comments-page/report-comment-bottom-action-sheet';

type CommentableListItemProps = {
username: string;
handle: string;
profileImage: string;
content: string;
};

const CommentableListItem = ({
username,
handle,
profileImage,
content,
}: CommentableListItemProps) => {
return (
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Link href={ROUTES.USER_HANDLE_OF(handle)}>
<Avatar size="xs">
<AvatarImage src={profileImage} />
<AvatarFallback className="bg-blccu-neutral-400" />
</Avatar>
</Link>
<p className="text-sm font-medium">{username}</p>
</div>
<ReportCommentBottomActionSheet
trigger={
<IconButton>
<EllipsisVertical className="h-4 w-4 text-blccu-neutral-400" />
</IconButton>
}
/>
</div>
<p className="text-sm text-blccu-neutral-600">{content}</p>
</div>
);
};

export { CommentableListItem };

0 comments on commit 2750a90

Please sign in to comment.