22
33import { useState } from 'react' ;
44import Link from 'next/link' ;
5+ import { useRouter } from 'next/navigation' ;
56import { formatDistanceToNow , format } from 'date-fns' ;
67import { useMutation , useQuery , usePaginatedQuery } from 'convex/react' ;
78import { api } from '@repo/backend' ;
@@ -21,6 +22,7 @@ import {
2122 Shield ,
2223 ThumbsUp ,
2324 Trophy ,
25+ Trash2 ,
2426} from 'lucide-react' ;
2527
2628import { ConvexError } from 'convex/values' ;
@@ -88,9 +90,14 @@ export function ActivityDetailContent({
8890 const [ flagSubmitting , setFlagSubmitting ] = useState ( false ) ;
8991 const [ flagError , setFlagError ] = useState < string | null > ( null ) ;
9092 const [ flagSuccess , setFlagSuccess ] = useState ( false ) ;
93+ const [ showDeleteDialog , setShowDeleteDialog ] = useState ( false ) ;
94+ const [ deleteSubmitting , setDeleteSubmitting ] = useState ( false ) ;
95+ const [ deleteError , setDeleteError ] = useState < string | null > ( null ) ;
9196
97+ const router = useRouter ( ) ;
9298 const toggleLike = useMutation ( api . mutations . likes . toggle ) ;
9399 const flagActivity = useMutation ( api . mutations . activities . flagActivity ) ;
100+ const deleteActivity = useMutation ( api . mutations . activities . remove ) ;
94101
95102 const handleToggleLike = async ( ) => {
96103 setPendingLike ( true ) ;
@@ -153,6 +160,20 @@ export function ActivityDetailContent({
153160 }
154161 } ;
155162
163+ const handleDelete = async ( ) => {
164+ setDeleteSubmitting ( true ) ;
165+ setDeleteError ( null ) ;
166+ try {
167+ await deleteActivity ( { activityId : activityId as Id < 'activities' > } ) ;
168+ router . push ( `/challenges/${ challengeId } /dashboard` ) ;
169+ } catch ( err ) {
170+ setDeleteError (
171+ err instanceof Error ? err . message : 'Failed to delete activity'
172+ ) ;
173+ setDeleteSubmitting ( false ) ;
174+ }
175+ } ;
176+
156177 if ( activityData === undefined ) {
157178 return (
158179 < div className = "flex items-center justify-center py-20" >
@@ -183,7 +204,19 @@ export function ActivityDetailContent({
183204 ) ;
184205 }
185206
186- const { activity, user, activityType, challenge, likes, comments, likedByUser, mediaUrls, adminComment, isAdmin } =
207+ const {
208+ activity,
209+ user,
210+ activityType,
211+ challenge,
212+ likes,
213+ comments,
214+ likedByUser,
215+ mediaUrls,
216+ adminComment,
217+ isAdmin,
218+ isOwner,
219+ } =
187220 activityData ;
188221
189222 const metrics = activity . metrics as Record < string , unknown > | undefined ;
@@ -396,6 +429,18 @@ export function ActivityDetailContent({
396429 </ Button >
397430 </ DropdownMenuTrigger >
398431 < DropdownMenuContent align = "end" >
432+ { isOwner && (
433+ < DropdownMenuItem
434+ onClick = { ( ) => {
435+ setDeleteError ( null ) ;
436+ setShowDeleteDialog ( true ) ;
437+ } }
438+ className = "text-destructive focus:text-destructive"
439+ >
440+ < Trash2 className = "mr-2 h-4 w-4" />
441+ Delete activity
442+ </ DropdownMenuItem >
443+ ) }
399444 < DropdownMenuItem
400445 onClick = { ( ) => {
401446 setFlagSuccess ( false ) ;
@@ -490,6 +535,48 @@ export function ActivityDetailContent({
490535 </ DialogFooter >
491536 </ DialogContent >
492537 </ Dialog >
538+
539+ < Dialog open = { showDeleteDialog } onOpenChange = { setShowDeleteDialog } >
540+ < DialogContent className = "sm:max-w-md" >
541+ < DialogHeader >
542+ < DialogTitle > Delete activity?</ DialogTitle >
543+ < DialogDescription >
544+ This removes the activity from your logs and leaderboards. This action
545+ cannot be undone.
546+ </ DialogDescription >
547+ </ DialogHeader >
548+ { deleteError && (
549+ < Alert variant = "destructive" >
550+ < AlertDescription > { deleteError } </ AlertDescription >
551+ </ Alert >
552+ ) }
553+ < DialogFooter className = "flex-col gap-2 sm:flex-row sm:justify-end" >
554+ < Button
555+ variant = "outline"
556+ className = "w-full sm:w-auto"
557+ onClick = { ( ) => setShowDeleteDialog ( false ) }
558+ disabled = { deleteSubmitting }
559+ >
560+ Cancel
561+ </ Button >
562+ < Button
563+ variant = "destructive"
564+ className = "w-full sm:w-auto"
565+ onClick = { handleDelete }
566+ disabled = { deleteSubmitting }
567+ >
568+ { deleteSubmitting ? (
569+ < >
570+ < Loader2 className = "mr-2 h-4 w-4 animate-spin" />
571+ Deleting
572+ </ >
573+ ) : (
574+ 'Delete activity'
575+ ) }
576+ </ Button >
577+ </ DialogFooter >
578+ </ DialogContent >
579+ </ Dialog >
493580 </ CardFooter >
494581 </ Card >
495582
0 commit comments