Files
ember-market-frontend/components/modals/image-viewer-modal.tsx
g fe01f31538
Some checks failed
Build Frontend / build (push) Failing after 7s
Refactor UI imports and update component paths
Replaces imports from 'components/ui' with 'components/common' across the app and dashboard pages, and updates model and API imports to use new paths under 'lib'. Removes redundant authentication checks from several dashboard pages. Adds new dashboard components and utility files, and reorganizes hooks and services into the 'lib' directory for improved structure.
2026-01-13 05:02:13 +00:00

100 lines
3.2 KiB
TypeScript

import { Dialog, DialogContent } from "@/components/common/dialog";
import { ChevronLeft, ChevronRight, X } from "lucide-react";
import { Button } from "@/components/common/button";
import { useEffect } from "react";
interface ImageViewerModalProps {
isOpen: boolean;
onClose: () => void;
imageUrl: string;
onNavigate?: (direction: 'prev' | 'next') => void;
}
export function ImageViewerModal({ isOpen, onClose, imageUrl, onNavigate }: ImageViewerModalProps) {
const handleNavigation = (direction: 'prev' | 'next') => (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
onNavigate?.(direction);
};
// Add keyboard navigation
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (!onNavigate) return;
if (e.key === 'ArrowLeft') {
e.preventDefault();
onNavigate('prev');
} else if (e.key === 'ArrowRight') {
e.preventDefault();
onNavigate('next');
} else if (e.key === 'Escape') {
e.preventDefault();
onClose();
}
};
if (isOpen) {
window.addEventListener('keydown', handleKeyDown);
}
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}, [isOpen, onNavigate, onClose]);
return (
<Dialog open={isOpen} onOpenChange={onClose}>
<DialogContent className="p-0 border-none bg-black/90 max-w-[90vw] max-h-[90vh] overflow-hidden [&>button:not([id='custom-close-btn'])]:hidden">
{/* Custom close button */}
<Button
id="custom-close-btn"
variant="ghost"
size="icon"
onClick={onClose}
className="absolute top-4 right-4 z-50 bg-black/40 hover:bg-black/60 text-white rounded-full border border-white/20"
>
<X size={18} />
</Button>
<div className="relative w-[90vw] h-[90vh] mx-auto">
{/* Navigation buttons */}
{onNavigate && (
<>
<Button
variant="ghost"
size="icon"
className="absolute left-4 top-1/2 -translate-y-1/2 z-50 bg-black/40 hover:bg-black/60 text-white rounded-full w-10 h-10 border border-white/20"
onClick={handleNavigation('prev')}
>
<ChevronLeft size={24} />
</Button>
<Button
variant="ghost"
size="icon"
className="absolute right-4 top-1/2 -translate-y-1/2 z-50 bg-black/40 hover:bg-black/60 text-white rounded-full w-10 h-10 border border-white/20"
onClick={handleNavigation('next')}
>
<ChevronRight size={24} />
</Button>
</>
)}
{/* Image container - add onClick handler to close modal */}
<div
className="w-full h-full flex items-center justify-center p-4 cursor-pointer"
onClick={onClose}
>
<img
src={imageUrl}
alt="Full size image"
className="max-w-full max-h-full object-contain cursor-pointer"
loading="eager"
/>
</div>
</div>
</DialogContent>
</Dialog>
);
}