2023-09-11 13:51:35 -05:00
|
|
|
import { PostWithUserDto } from '@/app/types';
|
2023-09-11 00:40:14 -05:00
|
|
|
import { Text } from '@codemirror/state';
|
|
|
|
|
import Image from 'next/image';
|
2023-09-11 17:39:02 -05:00
|
|
|
import Link from 'next/link';
|
|
|
|
|
import { useEffect, useRef, useState } from 'react';
|
|
|
|
|
import { BiDotsHorizontalRounded } from 'react-icons/bi';
|
|
|
|
|
import { GoDotFill } from 'react-icons/go';
|
2023-09-11 00:40:14 -05:00
|
|
|
import PostContent from './PostContent';
|
|
|
|
|
|
2023-09-11 13:49:13 -05:00
|
|
|
export default function Post({ post }: { post: PostWithUserDto }) {
|
2023-09-11 17:39:02 -05:00
|
|
|
const modalRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
const [modalOpen, setModalOpen] = useState(false);
|
2023-09-11 13:44:51 -05:00
|
|
|
const username = post.user.clerkUsername ?? post.user._id;
|
2023-09-11 00:40:14 -05:00
|
|
|
const createdPostDate = new Date(post._creationTime);
|
|
|
|
|
const postYear = createdPostDate.getFullYear();
|
|
|
|
|
const postMonth = createdPostDate.toLocaleString(undefined, {
|
|
|
|
|
month: 'short',
|
|
|
|
|
});
|
|
|
|
|
const dayOfMonth = createdPostDate.getDate();
|
|
|
|
|
|
2023-09-11 13:51:35 -05:00
|
|
|
// TODO: Posts content should only be allowed to grow to a set height
|
|
|
|
|
// after which the post's content should be truncated
|
|
|
|
|
// and we should display a 'more' link to load the post
|
|
|
|
|
// in an individual page
|
|
|
|
|
|
2023-09-11 14:03:55 -05:00
|
|
|
// TODO: Add menu button
|
|
|
|
|
|
|
|
|
|
// TODO: Add reply and like buttons
|
|
|
|
|
|
2023-09-11 17:39:02 -05:00
|
|
|
useEffect(() => {
|
|
|
|
|
function handleClickOutside(e: MouseEvent) {
|
|
|
|
|
if (
|
|
|
|
|
modalOpen &&
|
|
|
|
|
modalRef.current &&
|
|
|
|
|
modalRef.current.contains(e.target as Node) === false
|
|
|
|
|
) {
|
|
|
|
|
setModalOpen(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
document.addEventListener('click', handleClickOutside);
|
|
|
|
|
return () => document.removeEventListener('click', handleClickOutside);
|
|
|
|
|
}, [modalOpen]);
|
|
|
|
|
|
|
|
|
|
function handleDeleteClick() {
|
|
|
|
|
throw new Error('Function not implemented.');
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-11 00:40:14 -05:00
|
|
|
return (
|
2023-09-11 17:39:02 -05:00
|
|
|
<div className='flex w-full gap-4 p-8 bg-white dark:bg-secondary-gray'>
|
2023-09-11 00:40:14 -05:00
|
|
|
<div>
|
|
|
|
|
<Image
|
|
|
|
|
alt='user profile image'
|
2023-09-11 13:44:51 -05:00
|
|
|
src={post.user.clerkImageUrl}
|
2023-09-11 00:40:14 -05:00
|
|
|
width={40}
|
|
|
|
|
height={40}
|
|
|
|
|
className='rounded-full object-cover border-4 border-primary-accent'
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2023-09-11 17:39:02 -05:00
|
|
|
<div className='flex flex-1 flex-col gap-2'>
|
|
|
|
|
<div className='flex items-center justify-between gap-2'>
|
|
|
|
|
<div className='flex items-center gap-2'>
|
|
|
|
|
<div>{username}</div>
|
|
|
|
|
<GoDotFill className='w-3 h-3' />
|
|
|
|
|
<div className='text-xs'>
|
|
|
|
|
{`${postMonth} ${dayOfMonth}, ${postYear}`}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className='relative'>
|
|
|
|
|
<button onClick={() => setModalOpen(!modalOpen)}>
|
|
|
|
|
<BiDotsHorizontalRounded />
|
|
|
|
|
</button>
|
|
|
|
|
<div
|
|
|
|
|
ref={modalRef}
|
|
|
|
|
className={`${
|
|
|
|
|
modalOpen ? '' : 'hidden'
|
|
|
|
|
} max-w-min whitespace-nowrap absolute top-5 right-0 rounded-md py-2 pl-4 pr-10 shadow-md bg-white dark:bg-primary-gray`}
|
|
|
|
|
>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>
|
|
|
|
|
<Link href={`/posts/${post._id}/edit`}>Edit post</Link>
|
|
|
|
|
</li>
|
|
|
|
|
<li className='text-red-600'>
|
|
|
|
|
<button
|
|
|
|
|
onClick={handleDeleteClick}
|
|
|
|
|
type='button'
|
|
|
|
|
>
|
|
|
|
|
Delete post
|
|
|
|
|
</button>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-09-11 00:40:14 -05:00
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<PostContent content={Text.of(post.content).toString()} />
|
|
|
|
|
</div>
|
|
|
|
|
<div></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|