- Updated import paths for various components to align with new directory structure. - Changed imports from 'row-actions', 'confirm-dialog', 'image-preview-button', and 'file-upload' to their respective new locations in 'data-display', 'dialogs', and 'inputs'. - Adjusted imports in multiple pages including purchase, restock, transaction, category, customer, product, raw-material, supplier, roles, and settings. - Ensured all relevant components are imported from their new locations to maintain functionality.
99 lines
3.2 KiB
TypeScript
99 lines
3.2 KiB
TypeScript
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|
import { useState } from 'react';
|
|
import { Button } from '@/components/ui/button';
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from '@/components/ui/dialog';
|
|
|
|
type ImagePreviewModalProps = {
|
|
open: boolean;
|
|
onOpenChange: (open: boolean) => void;
|
|
src: string | null;
|
|
title?: string;
|
|
alt?: string;
|
|
sources?: string[];
|
|
};
|
|
|
|
export function ImagePreviewModal({
|
|
open,
|
|
onOpenChange,
|
|
src,
|
|
title,
|
|
alt = 'Preview',
|
|
sources,
|
|
}: ImagePreviewModalProps) {
|
|
const allImages = sources && sources.length > 0 ? sources : src ? [src] : [];
|
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
|
|
const currentSrc = allImages[currentIndex] ?? src;
|
|
const hasMultiple = allImages.length > 1;
|
|
|
|
function handlePrev() {
|
|
setCurrentIndex((prev) =>
|
|
prev === 0 ? allImages.length - 1 : prev - 1,
|
|
);
|
|
}
|
|
|
|
function handleNext() {
|
|
setCurrentIndex((prev) =>
|
|
prev === allImages.length - 1 ? 0 : prev + 1,
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Dialog
|
|
open={open}
|
|
onOpenChange={(v) => {
|
|
if (!v) {
|
|
setCurrentIndex(0);
|
|
}
|
|
|
|
onOpenChange(v);
|
|
}}
|
|
>
|
|
<DialogContent showCloseButton>
|
|
{title && (
|
|
<DialogHeader>
|
|
<DialogTitle>{title}</DialogTitle>
|
|
</DialogHeader>
|
|
)}
|
|
{currentSrc && (
|
|
<div className="relative">
|
|
<img
|
|
src={currentSrc}
|
|
alt={alt}
|
|
className="max-h-[80vh] w-full rounded-lg object-contain"
|
|
/>
|
|
{hasMultiple && (
|
|
<>
|
|
<Button
|
|
variant="secondary"
|
|
size="icon"
|
|
className="absolute left-2 top-1/2 h-8 w-8 -translate-y-1/2 rounded-full bg-black/50 text-white hover:bg-black/70"
|
|
onClick={handlePrev}
|
|
>
|
|
<ChevronLeft className="h-4 w-4" />
|
|
</Button>
|
|
<Button
|
|
variant="secondary"
|
|
size="icon"
|
|
className="absolute right-2 top-1/2 h-8 w-8 -translate-y-1/2 rounded-full bg-black/50 text-white hover:bg-black/70"
|
|
onClick={handleNext}
|
|
>
|
|
<ChevronRight className="h-4 w-4" />
|
|
</Button>
|
|
<div className="absolute bottom-2 left-1/2 -translate-x-1/2 rounded-full bg-black/50 px-2 py-1 text-xs text-white">
|
|
{currentIndex + 1} / {allImages.length}
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
)}
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|