File "SharedMediaModal.tsx"
Full Path: /home/trinadezambia/public_html/student_panel/src/components/chat/SharedMediaModal.tsx
File size: 4.11 KB
MIME-type: text/x-java
Charset: utf-8
'use client';
import React, { useState } from 'react';
import Image from 'next/image';
import { Download } from 'lucide-react';
import {
Dialog,
DialogClose,
DialogContent,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { BiX } from 'react-icons/bi';
// Props interface for the SharedMediaModal component
interface SharedMediaModalProps {
isOpen: boolean;
onClose: () => void;
images: string[];
}
// SharedMediaModal component for displaying shared media in a modal
export const SharedMediaModal: React.FC<SharedMediaModalProps> = ({
isOpen,
onClose,
images,
}) => {
// State for managing image pagination
const [visibleImagesCount, setVisibleImagesCount] = useState(6);
// Calculate how many images to show (minimum 6, or all if less than 6)
const imagesToShow = Math.min(visibleImagesCount, images.length);
const hasMoreImages = images.length > visibleImagesCount;
// Handle download for individual image
const handleDownload = (imageSrc: string, index: number) => {
// Create a temporary link element to trigger download
const link = document.createElement('a');
link.href = imageSrc;
link.download = `shared-media-${index + 1}.jpg`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
// Handle loading more images
const handleLoadMore = () => {
setVisibleImagesCount((prev) => Math.min(prev + 6, images.length));
};
// Reset visible images count when modal opens
React.useEffect(() => {
if (isOpen) {
setVisibleImagesCount(6);
}
}, [isOpen]);
return (
<Dialog open={isOpen} onOpenChange={onClose}>
<DialogContent
className="!max-h-[700px] overflow-y-auto p-0 w-[95vw] md:w-[650px] max-w-[95vw] md:max-w-[650px] min-w-[95vw] md:min-w-[650px]"
showCloseButton={false}
>
{/* Modal Header */}
<DialogHeader className="flex flex-row items-center justify-between border-b border-gray-200 p-3 md:p-6">
<DialogTitle className="text-lg md:text-xl font-bold text-gray-800">
Shared Media
</DialogTitle>
<DialogClose>
<BiX className="w-6 h-6 md:w-8 md:h-8 cursor-pointer text-gray-400 bg-[var(--light-primary-color)] border border-gray-200 rounded-[4px] p-1 flex-shrink-0" />
</DialogClose>
</DialogHeader>
{/* Images Grid */}
<div className="grid grid-cols-2 md:grid-cols-3 gap-2 md:gap-4 mt-4 p-3 md:px-6">
{images.slice(0, imagesToShow).map((imageSrc, index) => (
<div key={index} className="relative group">
{/* Image Container */}
<div className="relative w-full h-32 md:h-48 rounded-lg overflow-hidden bg-white border border-gray-200">
<Image
src={imageSrc}
alt={`Shared media ${index + 1}`}
fill
className="object-cover"
priority={index < 6} // Prioritize first 6 images for better performance
/>
{/* Download Button - appears on hover */}
<button
onClick={() => handleDownload(imageSrc, index)}
className="absolute top-1 end-1 md:top-2 md:end-2 bg-[var(--secondary-color)] text-white p-1.5 md:p-2 rounded-[4px] transition-opacity duration-200"
aria-label={`Download image ${index + 1}`}
>
<Download size={14} className="md:w-4 md:h-4" />
</button>
</div>
</div>
))}
</div>
{/* Action Buttons */}
<div className="flex flex-col items-center gap-3 mb-4 md:mb-6">
{/* Load More Button - only show if there are more images */}
{hasMoreImages && (
<button
onClick={handleLoadMore}
className="bg-(--primary-color) text-white px-4 md:px-6 py-2 md:py-3 rounded-[4px] font-medium transition-colors duration-200 shadow-md hover:shadow-lg text-sm md:text-base"
>
Load More Images
</button>
)}
</div>
</DialogContent>
</Dialog>
);
};