@@ -14,6 +14,7 @@ import {
1414 Send ,
1515 Trash ,
1616 X ,
17+ Download ,
1718} from "lucide-react" ;
1819import Swal from "sweetalert2" ;
1920import type { Task , Attachment , TeamMember } from "../types" ;
@@ -22,6 +23,7 @@ import { PrioritySelect } from "./PrioritySelect";
2223import { AssigneeSelect } from "./AssigneeSelect" ;
2324import { handleWhatsapp , handleWhatsappTask } from "../utils/sendWhatsapp" ;
2425import WhatsappIcon from "./WhatsappIcon" ;
26+ import MediaModal from "./MediaModal" ;
2527import { useAuthStore } from "../utils/store" ;
2628import { FaComment } from "react-icons/fa" ;
2729
@@ -57,6 +59,11 @@ export default function TaskModal({
5759 const [ files , setFiles ] = useState < File [ ] > ( [ ] ) ;
5860 const [ isLoading , setIsLoading ] = useState ( false ) ;
5961 const [ uploading , setUploading ] = useState ( false ) ;
62+ const [ mediaViewerOpen , setMediaViewerOpen ] = useState ( false ) ;
63+ const [ mediaViewerUrl , setMediaViewerUrl ] = useState < string > ( "" ) ;
64+ const [ mediaViewerType , setMediaViewerType ] = useState < "image" | "video" > (
65+ "image"
66+ ) ;
6067 const fileInputRef = useRef < HTMLInputElement | null > ( null ) ;
6168 const currentAssignee = team . find ( ( t ) => t . id === task . assigneeId ) ;
6269 const assigneePhone = currentAssignee ?. phone || "" ;
@@ -383,6 +390,17 @@ export default function TaskModal({
383390 return s . length === 0 ;
384391 }
385392
393+ const openMediaViewer = ( url : string , type : "image" | "video" ) => {
394+ setMediaViewerUrl ( url ) ;
395+ setMediaViewerType ( type ) ;
396+ setMediaViewerOpen ( true ) ;
397+ } ;
398+
399+ const closeMediaViewer = ( ) => {
400+ setMediaViewerOpen ( false ) ;
401+ setMediaViewerUrl ( "" ) ;
402+ } ;
403+
386404 return (
387405 < div className = "fixed inset-0 z-50 flex items-center justify-center p-6" >
388406 { /* Backdrop */ }
@@ -603,16 +621,33 @@ export default function TaskModal({
603621 < img
604622 src = { a . url }
605623 alt = { a . name }
606- className = "max-h-60 rounded-lg object-cover"
624+ onClick = { ( ) =>
625+ openMediaViewer ( a . url , "image" )
626+ }
627+ className = "max-h-60 rounded-lg object-cover cursor-pointer hover:opacity-80 transition-opacity"
628+ title = "Click to view full size"
607629 />
608630 ) }
609631
610632 { isVideo && (
611- < video
612- src = { a . url }
613- controls
614- className = "max-h-60 rounded-lg"
615- />
633+ < div className = "relative" >
634+ < video
635+ src = { a . url }
636+ className = "max-h-60 rounded-lg cursor-pointer"
637+ onClick = { ( ) =>
638+ openMediaViewer ( a . url , "video" )
639+ }
640+ title = "Click to view in modal"
641+ />
642+ < div
643+ className = "absolute inset-0 flex items-center justify-center pointer-events-none"
644+ aria-hidden = "true"
645+ >
646+ < div className = "w-16 h-16 rounded-full bg-black/50 flex items-center justify-center" >
647+ < div className = "w-0 h-0 border-t-8 border-t-transparent border-l-12 border-l-white border-b-8 border-b-transparent ml-1" > </ div >
648+ </ div >
649+ </ div >
650+ </ div >
616651 ) }
617652 </ >
618653 ) }
@@ -625,23 +660,6 @@ export default function TaskModal({
625660 ({ Math . round ( ( a . size || 0 ) / 1024 ) } KB)
626661 </ span >
627662 </ div >
628-
629- < div >
630- { a . url ? (
631- < a
632- href = { a . url }
633- target = "_blank"
634- rel = "noreferrer"
635- className = "text-sm underline"
636- >
637- Open
638- </ a >
639- ) : (
640- < span className = "text-xs text-gray-400" >
641- (no url)
642- </ span >
643- ) }
644- </ div >
645663 </ div >
646664 </ div >
647665 ) ;
@@ -748,6 +766,14 @@ export default function TaskModal({
748766 </ div >
749767 </ div >
750768 </ div >
769+
770+ { /* Media Viewer Modal */ }
771+ < MediaModal
772+ isOpen = { mediaViewerOpen }
773+ url = { mediaViewerUrl }
774+ type = { mediaViewerType }
775+ onClose = { closeMediaViewer }
776+ />
751777 </ div >
752778 ) ;
753779}
0 commit comments