11import { useEffect , useState } from "react" ;
22import Image from "next/image" ;
3- import Link from "next/link" ;
43import FeedPostModal from "@/components/modals/FeedPostModal" ;
54import { Box } from "@/components/shared/dashboard" ;
65import { defaultAvatar } from "@/public/assets/images" ;
76import { useUserStore } from "@/store/codev-store" ;
87import { format } from "date-fns" ;
9- import { ArrowBigUp , MessageSquare } from "lucide-react" ;
108import toast from "react-hot-toast" ;
119
1210import { deletePost } from "../_services/action" ;
1311import { PostType } from "../_services/query" ;
1412import { DeleteDialog } from "./DeleteDialog" ;
1513import PostCommentCount from "./PostCommentCount" ;
1614import PostTags from "./PostTags" ;
17- import PostUpvote from "./PostUpvote" ;
15+ import PostUpvote from "./PostUpvote" ;
1816
1917interface PostProps {
2018 post : PostType ;
@@ -30,21 +28,11 @@ export default function Post({ post, isAdmin, onDelete }: PostProps) {
3028 const { user } = useUserStore ( ) ;
3129
3230 useEffect ( ( ) => {
33- const checkIfAuthor = async ( ) => {
34- if ( ! user ) return ;
35- if ( user . id === post . author_id ?. id ) {
36- setIsAuthor ( true ) ;
37- } else {
38- setIsAuthor ( false ) ;
39- }
40- } ;
41-
42- if ( user ) {
43- checkIfAuthor ( ) ;
44- }
31+ if ( ! user ) return ;
32+ setIsAuthor ( user . id === post . author_id ?. id ) ;
4533 } , [ user , post . author_id ?. id ] ) ;
4634
47- const openDeleteDialog = async ( e : React . MouseEvent ) => {
35+ const openDeleteDialog = ( e : React . MouseEvent ) => {
4836 e . stopPropagation ( ) ;
4937 e . preventDefault ( ) ;
5038 setShowDeleteDialog ( true ) ;
@@ -54,9 +42,7 @@ export default function Post({ post, isAdmin, onDelete }: PostProps) {
5442 try {
5543 setIsDeleting ( true ) ;
5644 await deletePost ( post . id ) ;
57- if ( onDelete ) {
58- onDelete ( post . id ) ;
59- }
45+ if ( onDelete ) onDelete ( post . id ) ;
6046 toast . success ( "Post deleted successfully!" ) ;
6147 } catch ( error ) {
6248 toast . error ( "Failed to delete post." ) ;
@@ -70,79 +56,75 @@ export default function Post({ post, isAdmin, onDelete }: PostProps) {
7056 const openModal = ( ) => setIsModalOpen ( true ) ;
7157 const closeModal = ( ) => setIsModalOpen ( false ) ;
7258
59+ const isSystemPost = post . id === "00000000-0000-0000-0000-000000000001" ;
60+
7361 return (
7462 < div >
75- < Box
76- className = "group relative flex h-[440px] cursor-pointer flex-col justify-between rounded-xl p-3"
63+ { /* Card */ }
64+ < div
7765 onClick = { openModal }
66+ className = "group relative flex h-[440px] cursor-pointer flex-col justify-between overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-sm transition-all duration-200 hover:border-cyan-400 hover:shadow-md dark:border-gray-700 dark:bg-gray-800 dark:hover:border-cyan-500/40 dark:hover:shadow-lg dark:hover:shadow-cyan-500/5"
7867 >
79- { /* Delete Button in top-right */ }
80- { ( isAdmin || isAuthor ) && post . id !== "00000000-0000-0000-0000-000000000001" && (
68+ { /* Delete button */ }
69+ { ( isAdmin || isAuthor ) && ! isSystemPost && (
8170 < button
82- className = "invisible absolute right-2 top-2 rounded bg-red-500 px-2 py-1 text-white hover:bg-red-600 group-hover:visible"
71+ className = "invisible absolute right-2 top-2 z-10 rounded-lg bg-red-500 px-2 py-1 text-xs font-medium text- white transition hover:bg-red-600 group-hover:visible"
8372 onClick = { openDeleteDialog }
8473 aria-label = "Delete post"
8574 >
8675 ✕
8776 </ button >
8877 ) }
8978
90- < div className = "mx-4 mt-2 h-[200px]" >
91- < div className = "flex items-center justify-between" >
92- < div className = "mb-2 flex items-center" >
93- < Image
94- src = {
95- post . author_id ?. image_url ||
96- ( post . id === "00000000-0000-0000-0000-000000000001" ? "/favicon.ico" : defaultAvatar )
97- }
98- alt = { `${ post . author_id ?. first_name || "Codebility" } 's profile` }
99- className = "mr-4 h-12 w-12 rounded-full object-cover"
100- width = { 30 }
101- height = { 30 }
102- />
103- < div className = "flex-1" >
104- < h2 className = "font-semibold text-gray-800 dark:text-gray-100" >
105- { post . author_id ?. first_name
106- ? `${ post . author_id ?. first_name } ${ post . author_id ?. last_name } `
107- : "Codebility" }
108- </ h2 >
109- </ div >
110- </ div >
111- </ div >
112-
113- < div className = "h-[60px] flex-grow" >
114- < p className = "mt-2 line-clamp-2 text-xl font-semibold leading-snug text-gray-700 dark:text-gray-300" >
115- { post . title }
116- </ p >
117- </ div >
118- < div className = "mb-2" >
119- < PostTags post = { post } minimal = { true } />
120- </ div >
121-
122- < p className = "text-sm text-gray-500 dark:text-gray-400" >
123- { format ( new Date ( post . created_at ) , "MMM d, yyyy" ) }
79+ { /* Title */ }
80+ < div className = "px-4 pt-4" >
81+ < p className = "line-clamp-2 text-base font-semibold leading-snug text-gray-800 dark:text-gray-100" >
82+ { post . title }
12483 </ p >
12584 </ div >
12685
127- < div className = "my-2 h-60 w-full overflow-hidden rounded-sm" >
86+ { /* Thumbnail image — takes up most of the card */ }
87+ < div className = "mx-4 mt-2 flex-1 overflow-hidden rounded-xl" >
12888 < img
12989 src = { post . image_url || "/assets/images/bg-certificate.png" }
13090 alt = "Post image"
131- className = "h-full w-full object-cover"
91+ className = "h-full w-full object-cover transition-transform duration-300 group-hover:scale-[1.02] "
13292 />
13393 </ div >
13494
135- < div className = "mx-4 flex items-center space-x-4 text-gray-600 dark:text-gray-400" >
136- < PostUpvote post = { post } />
95+ { /* Footer: author + date on left, upvotes + comments on right */ }
96+ < div className = "flex items-center justify-between border-t border-gray-100 px-4 py-3 dark:border-gray-700" >
97+ < div className = "flex items-center gap-2" >
98+ < Image
99+ src = {
100+ post . author_id ?. image_url ||
101+ ( isSystemPost ? "/favicon.ico" : defaultAvatar )
102+ }
103+ alt = { `${ post . author_id ?. first_name || "Codebility" } 's profile` }
104+ className = "h-7 w-7 rounded-full object-cover ring-1 ring-gray-200 dark:ring-white/10"
105+ width = { 28 }
106+ height = { 28 }
107+ />
108+ < div className = "flex flex-col" >
109+ < span className = "text-xs font-semibold text-gray-700 dark:text-gray-200" >
110+ { post . author_id ?. first_name
111+ ? `${ post . author_id . first_name } ${ post . author_id . last_name } `
112+ : "Codebility" }
113+ </ span >
114+ < span className = "text-[10px] text-gray-400 dark:text-gray-500" >
115+ { format ( new Date ( post . created_at ) , "MMM d, yyyy" ) }
116+ </ span >
117+ </ div >
118+ </ div >
137119
138- < PostCommentCount post = { post } />
120+ < div className = "flex items-center gap-3 text-gray-500 dark:text-gray-400" >
121+ < PostUpvote post = { post } />
122+ < PostCommentCount post = { post } />
123+ </ div >
139124 </ div >
140- </ Box >
141- < FeedPostModal
142- isOpen = { isModalOpen }
143- onClose = { closeModal }
144- postId = { post . id }
145- />
125+ </ div >
126+
127+ < FeedPostModal isOpen = { isModalOpen } onClose = { closeModal } postId = { post . id } />
146128 < DeleteDialog
147129 isOpen = { showDeleteDialog }
148130 onClose = { ( ) => setShowDeleteDialog ( false ) }
0 commit comments