22
33import { useEffect , useState } from 'react' ;
44import Link from 'next/link' ;
5+ import { usePathname } from 'next/navigation' ;
56import { formatDistanceToNow } from 'date-fns' ;
67import { PrimaryButton } from '@servicestack/react' ;
78import { useAuthorization } from '@/lib/hooks/useAuthorization' ;
@@ -11,7 +12,7 @@ import * as gateway from '@/lib/api/gateway';
1112import { TechnologyTags } from '@/components/TechnologyTags' ;
1213import { Avatar } from '@/components/ui/Avatar' ;
1314
14- export default function PostDetailClient ( { id , slug } : { id : string ; slug : string } ) {
15+ export default function PostDetailClient ( ) {
1516 const { canEditPost, canDeleteComment } = useAuthorization ( ) ;
1617 const { sessionInfo, isAuthenticated } = useAppStore ( ) ;
1718 const [ post , setPost ] = useState < any > ( null ) ;
@@ -26,10 +27,22 @@ export default function PostDetailClient({ id, slug }: { id: string; slug: strin
2627 const [ downVotedCommentIds , setDownVotedCommentIds ] = useState < number [ ] > ( [ ] ) ;
2728 const [ localCommentPoints , setLocalCommentPoints ] = useState < Record < number , number > > ( { } ) ;
2829
30+ const pathname = usePathname ( ) ;
31+ const segments = pathname . split ( '/' ) . filter ( Boolean ) ;
32+ const idSegment = segments [ 1 ] ; // /posts/{id}/{slug}
33+ const slug = segments [ 2 ] ?? '' ;
34+
35+ const postId = idSegment ? parseInt ( idSegment , 10 ) : NaN ;
36+
2937 useEffect ( ( ) => {
3038 const loadPost = async ( ) => {
39+ if ( ! postId || Number . isNaN ( postId ) ) {
40+ setNotFound ( true ) ;
41+ setLoading ( false ) ;
42+ return ;
43+ }
44+
3145 try {
32- const postId = parseInt ( id ) ;
3346 const response = await gateway . getPost ( postId ) ;
3447 setPost ( response . post ) ;
3548 setComments ( response . comments || [ ] ) ;
@@ -53,7 +66,7 @@ export default function PostDetailClient({ id, slug }: { id: string; slug: strin
5366 } ;
5467
5568 loadPost ( ) ;
56- } , [ id , isAuthenticated ] ) ;
69+ } , [ postId , isAuthenticated ] ) ;
5770
5871 const handleCommentVote = async ( commentId : number , weight : number , e : React . MouseEvent ) => {
5972 e . stopPropagation ( ) ;
@@ -98,7 +111,7 @@ export default function PostDetailClient({ id, slug }: { id: string; slug: strin
98111 [ commentId ] : currentPoints + pointsDelta
99112 } ) ) ;
100113
101- await gateway . votePostComment ( parseInt ( id ) , commentId , newWeight ) ;
114+ await gateway . votePostComment ( postId , commentId , newWeight ) ;
102115 } catch ( err ) {
103116 console . error ( 'Failed to vote on comment:' , err ) ;
104117 }
@@ -112,12 +125,12 @@ export default function PostDetailClient({ id, slug }: { id: string; slug: strin
112125 }
113126
114127 try {
115- await gateway . createPostComment ( parseInt ( id ) , newComment , replyToId || undefined ) ;
128+ await gateway . createPostComment ( postId , newComment , replyToId || undefined ) ;
116129 setNewComment ( '' ) ;
117130 setReplyToId ( null ) ;
118131
119132 // Reload post to get updated comments
120- const response = await gateway . getPost ( parseInt ( id ) ) ;
133+ const response = await gateway . getPost ( postId ) ;
121134 setComments ( response . comments || [ ] ) ;
122135 } catch ( err ) {
123136 console . error ( 'Failed to create comment:' , err ) ;
@@ -128,12 +141,12 @@ export default function PostDetailClient({ id, slug }: { id: string; slug: strin
128141 if ( ! editContent . trim ( ) ) return ;
129142
130143 try {
131- await gateway . updatePostComment ( commentId , parseInt ( id ) , editContent ) ;
144+ await gateway . updatePostComment ( commentId , postId , editContent ) ;
132145 setEditingCommentId ( null ) ;
133146 setEditContent ( '' ) ;
134147
135148 // Reload comments
136- const response = await gateway . getPost ( parseInt ( id ) ) ;
149+ const response = await gateway . getPost ( postId ) ;
137150 setComments ( response . comments || [ ] ) ;
138151 } catch ( err ) {
139152 console . error ( 'Failed to update comment:' , err ) ;
@@ -146,10 +159,10 @@ export default function PostDetailClient({ id, slug }: { id: string; slug: strin
146159 }
147160
148161 try {
149- await gateway . deletePostComment ( commentId , parseInt ( id ) ) ;
162+ await gateway . deletePostComment ( commentId , postId ) ;
150163
151164 // Reload comments
152- const response = await gateway . getPost ( parseInt ( id ) ) ;
165+ const response = await gateway . getPost ( postId ) ;
153166 setComments ( response . comments || [ ] ) ;
154167 } catch ( err ) {
155168 console . error ( 'Failed to delete comment:' , err ) ;
@@ -388,7 +401,7 @@ export default function PostDetailClient({ id, slug }: { id: string; slug: strin
388401 ) }
389402 </ h1 >
390403 { canEditPost ( post ) && (
391- < Link href = { routes . postEdit ( parseInt ( id ) , slug ) } >
404+ < Link href = { routes . postEdit ( postId , slug ) } >
392405 < PrimaryButton className = "ml-4" >
393406 Edit
394407 </ PrimaryButton >
0 commit comments