@@ -35,6 +35,7 @@ export default function PostPage() {
3535 const [ showCommentProductSearch , setShowCommentProductSearch ] = useState ( false ) ;
3636 const [ isRealTimeActive , setIsRealTimeActive ] = useState ( false ) ;
3737 const [ isOnline , setIsOnline ] = useState ( true ) ;
38+ const [ newlyAddedComments , setNewlyAddedComments ] = useState < Set < string > > ( new Set ( ) ) ;
3839
3940 useEffect ( ( ) => {
4041 const unsubscribe = onAuthStateChanged ( auth , ( user ) => {
@@ -161,17 +162,36 @@ export default function PostPage() {
161162 } )
162163 ) ;
163164
164- // Sort comments by createdAt in JavaScript
165+ // Sort comments by createdAt in JavaScript (newest first)
165166 commentsData . sort ( ( a , b ) => {
166167 const aTime = new Date ( a . createdAt ) . getTime ( ) ;
167168 const bTime = new Date ( b . createdAt ) . getTime ( ) ;
168- return aTime - bTime ;
169+ return bTime - aTime ; // Changed from aTime - bTime to bTime - aTime for newest first
169170 } ) ;
170171
171172 // Filter out optimistic updates and merge with real data
172173 setComments ( prevComments => {
173174 const tempComments = prevComments . filter ( c => c . id . startsWith ( 'temp-' ) ) ;
174175 const realComments = commentsData ;
176+
177+ // Detect new comments for animation
178+ const prevCommentIds = new Set ( prevComments . map ( c => c . id ) ) ;
179+ const newCommentIds = realComments
180+ . filter ( c => ! prevCommentIds . has ( c . id ) && ! c . id . startsWith ( 'temp-' ) )
181+ . map ( c => c . id ) ;
182+
183+ if ( newCommentIds . length > 0 ) {
184+ setNewlyAddedComments ( prev => new Set ( [ ...prev , ...newCommentIds ] ) ) ;
185+ // Remove animation class after animation duration
186+ setTimeout ( ( ) => {
187+ setNewlyAddedComments ( prev => {
188+ const updated = new Set ( prev ) ;
189+ newCommentIds . forEach ( id => updated . delete ( id ) ) ;
190+ return updated ;
191+ } ) ;
192+ } , 1000 ) ; // Remove animation after 1 second
193+ }
194+
175195 return [ ...realComments , ...tempComments ] ;
176196 } ) ;
177197 setLoadingComments ( false ) ;
@@ -411,27 +431,31 @@ export default function PostPage() {
411431 { user ? (
412432 < form onSubmit = { handleSubmitComment } className = "mb-4 sm:mb-6" >
413433 < div className = "flex gap-3" >
414- < div className = "flex-shrink-0" >
415- < div className = "w-10 h-10 rounded-full flex items-center justify-center" style = { { backgroundColor : colours . tag . default . background } } >
416- < span className = "font-medium text-sm" style = { { color : colours . tag . default . text } } >
417- { ( user . displayName || user . email || '' ) . charAt ( 0 ) . toUpperCase ( ) }
434+ < div className = "flex-1" >
435+ < div className = "relative" >
436+ < textarea
437+ value = { newComment }
438+ onChange = { ( e ) => setNewComment ( e . target . value ) }
439+ className = "w-full px-3 py-2 pr-20 shadow-lg rounded-lg resize-none border-2 border-black"
440+ style = { {
441+ backgroundColor : colours . input . background ,
442+ color : colours . input . text
443+ } }
444+ rows = { 3 }
445+ placeholder = "Share your thoughts..."
446+ maxLength = { 500 }
447+ />
448+ { /* Character count inside textarea */ }
449+ < span
450+ className = "absolute bottom-3 right-2 text-xs pointer-events-none px-2 py-1 rounded"
451+ style = { {
452+ color : colours . text . muted ,
453+ backgroundColor : colours . input . background ,
454+ } }
455+ >
456+ { newComment . length } /500
418457 </ span >
419458 </ div >
420- </ div >
421- < div className = "flex-1" >
422- < textarea
423- value = { newComment }
424- onChange = { ( e ) => setNewComment ( e . target . value ) }
425- className = "w-full px-3 py-2 rounded-lg resize-none"
426- style = { {
427- border : `1px solid ${ colours . card . border } ` ,
428- backgroundColor : colours . input . background ,
429- color : colours . input . text
430- } }
431- rows = { 3 }
432- placeholder = "Share your thoughts..."
433- maxLength = { 500 }
434- />
435459
436460 { /* Product Linking for Comments */ }
437461 < div className = "mt-2" >
@@ -475,7 +499,7 @@ export default function PostPage() {
475499 ) }
476500
477501 { showCommentProductSearch && ! selectedCommentProduct && (
478- < div className = "relative mb-3 " >
502+ < div className = "relative mb-2 " >
479503 < div className = "relative" >
480504 < Search className = "absolute left-3 top-1/2 transform -translate-y-1/2" size = { 16 } style = { { color : colours . text . muted } } />
481505 < input
@@ -537,31 +561,16 @@ export default function PostPage() {
537561 ) }
538562 </ div >
539563
540- < div className = "flex justify-between items-center mt-3" >
541- < div className = "flex items-center gap-3" >
542- < span className = "text-xs px-2 py-1 rounded-full" style = { {
543- color : colours . text . muted ,
544- backgroundColor : colours . background . secondary
545- } } >
546- { newComment . length } /500
547- </ span >
564+ < div className = "flex justify-between items-center mt-2" >
565+ < div className = "flex items-center" >
548566 { ! selectedCommentProduct && (
549567 < button
550568 type = "button"
551569 onClick = { ( ) => setShowCommentProductSearch ( ! showCommentProductSearch ) }
552- className = { `flex items-center gap-2 px-3 py-2 rounded-lg text-xs font-medium transition-all ${
553- showCommentProductSearch ? 'shadow-sm' : ''
554- } `}
570+ className = "flex items-center gap-2 px-3 py-2 shadow-xl rounded-xl border-2 border-black text-xs font-medium transition-all"
555571 style = { {
556- backgroundColor : showCommentProductSearch
557- ? colours . button . primary . background
558- : colours . tag . default . background ,
559- color : showCommentProductSearch
560- ? colours . button . primary . text
561- : colours . text . secondary ,
562- border : `1px solid ${ showCommentProductSearch
563- ? colours . button . primary . background
564- : colours . tag . default . border } `
572+ backgroundColor : '#f1f5fb' ,
573+ color : colours . text . primary
565574 } }
566575 >
567576 < Package size = { 14 } />
@@ -572,21 +581,21 @@ export default function PostPage() {
572581 < button
573582 type = "submit"
574583 disabled = { ! newComment . trim ( ) || submittingComment }
575- className = "flex items-center justify-center w-10 h-10 rounded-full disabled:opacity-50 disabled:cursor-not-allowed transition-all"
584+ className = "flex items-center gap-2 px-4 py-2 rounded-xl border-2 shadow-xl border-black text-xs font-medium disabled:opacity-50 disabled:cursor-not-allowed disabled:border-dotted transition-all"
576585 style = { {
577- backgroundColor : colours . button . primary . background ,
578- color : colours . button . primary . text
586+ backgroundColor : '#f1f5fb' ,
587+ color : colours . text . primary
579588 } }
580- title = { submittingComment ? 'Posting...' : 'Post Comment' }
581589 >
582- < Send size = { 16 } />
590+ < Send size = { 14 } />
591+ < span > { submittingComment ? 'Posting...' : 'Post Comment' } </ span >
583592 </ button >
584593 </ div >
585594 </ div >
586595 </ div >
587596 </ form >
588597 ) : (
589- < div className = "mb-6 p-4 rounded-lg text-center" style = { { backgroundColor : colours . background . secondary } } >
598+ < div className = "mb- p-4 rounded-lg text-center" style = { { backgroundColor : colours . background . secondary } } >
590599 < p className = "mb-2" style = { { color : colours . text . secondary } } > Sign in to join the conversation</ p >
591600 < Link
592601 href = "/auth"
@@ -606,20 +615,34 @@ export default function PostPage() {
606615 </ div >
607616 ) : comments . length === 0 ? (
608617 < div className = "text-center py-8" >
609- < MessageCircle size = { 48 } className = "mx-auto mb-3 " style = { { color : colours . text . muted } } />
618+ < MessageCircle size = { 48 } className = "mx-auto mb-2 " style = { { color : colours . text . muted } } />
610619 < p style = { { color : colours . text . secondary } } > No comments yet. Be the first to share your thoughts!</ p >
611620 </ div >
612621 ) : (
613- < div className = "space-y-4 " >
622+ < div className = "space-y-1 " >
614623 { comments . map ( ( comment ) => (
615- < CommentItem
624+ < div
616625 key = { comment . id }
617- comment = { comment }
618- currentUserId = { user ?. uid }
619- onLike = { handleCommentLike }
620- onDislike = { handleCommentDislike }
621- depth = { 0 }
622- />
626+ className = { `transition-all duration-1000 ease-out ${
627+ newlyAddedComments . has ( comment . id )
628+ ? 'animate-slide-in-top opacity-100 transform translate-y-0'
629+ : 'opacity-100 transform translate-y-0'
630+ } `}
631+ style = { {
632+ animation : newlyAddedComments . has ( comment . id )
633+ ? 'slideInTop 0.8s ease-out, highlightNew 2s ease-out'
634+ : undefined ,
635+ borderRadius : '0.75rem'
636+ } }
637+ >
638+ < CommentItem
639+ comment = { comment }
640+ currentUserId = { user ?. uid }
641+ onLike = { handleCommentLike }
642+ onDislike = { handleCommentDislike }
643+ depth = { 0 }
644+ />
645+ </ div >
623646 ) ) }
624647 </ div >
625648 ) }
0 commit comments