This commit is contained in:
Tomáš Dvořák
2025-10-16 13:32:05 +02:00
commit 12cba639b9
663 changed files with 168914 additions and 0 deletions
@@ -0,0 +1,184 @@
import React from 'react';
import {
Modal,
ModalOverlay,
ModalContent,
ModalBody,
ModalCloseButton,
Image,
Box,
HStack,
Button,
Text,
useToast,
IconButton,
VStack,
} from '@chakra-ui/react';
import { Download, ExternalLink } from 'lucide-react';
interface PhotoModalProps {
isOpen: boolean;
onClose: () => void;
photoUrl: string;
pageUrl: string;
albumTitle?: string;
}
const PhotoModal: React.FC<PhotoModalProps> = ({
isOpen,
onClose,
photoUrl,
pageUrl,
albumTitle,
}) => {
const toast = useToast();
const getProxyUrl = (url: string) => {
const apiUrl = process.env.REACT_APP_API_URL || 'http://localhost:8080';
return `${apiUrl}/api/v1/gallery/proxy-image?url=${encodeURIComponent(url)}`;
};
const handleDownload = async () => {
try {
const response = await fetch(getProxyUrl(photoUrl));
if (!response.ok) {
throw new Error('Failed to fetch image');
}
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = `fotka-${Date.now()}.jpg`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
toast({
title: 'Stahování zahájeno',
description: 'Fotka se stahuje',
status: 'success',
duration: 2000,
isClosable: true,
});
} catch (error) {
console.error('Failed to download image:', error);
toast({
title: 'Chyba',
description: 'Nepodařilo se stáhnout obrázek',
status: 'error',
duration: 2000,
isClosable: true,
});
}
};
return (
<Modal isOpen={isOpen} onClose={onClose} size="6xl" isCentered>
<ModalOverlay bg="blackAlpha.800" backdropFilter="blur(10px)" />
<ModalContent bg="transparent" boxShadow="none" maxW="90vw">
<ModalCloseButton
color="white"
bg="blackAlpha.600"
_hover={{ bg: 'blackAlpha.800' }}
size="lg"
top={2}
right={2}
zIndex={2}
/>
<ModalBody p={0}>
<VStack spacing={4} align="stretch">
{/* Image */}
<Box
position="relative"
borderRadius="lg"
overflow="hidden"
maxH="80vh"
display="flex"
alignItems="center"
justifyContent="center"
>
<Image
src={photoUrl}
alt={albumTitle || 'Fotka'}
maxH="80vh"
maxW="100%"
objectFit="contain"
loading="lazy"
/>
</Box>
{/* Controls */}
<Box
bg="bg.elevated"
borderWidth="1px"
borderColor="border.subtle"
borderRadius="lg"
p={4}
boxShadow="xl"
>
<VStack spacing={3} align="stretch">
{albumTitle && (
<Text fontSize="md" fontWeight="600" color="gray.700">
{albumTitle}
</Text>
)}
<HStack spacing={2} justify="space-between" flexWrap="wrap">
<HStack spacing={2}>
<Button
leftIcon={<Download size={18} />}
onClick={handleDownload}
colorScheme="green"
size="sm"
>
Stáhnout
</Button>
<Button
as="a"
href={pageUrl}
target="_blank"
rel="noopener noreferrer"
leftIcon={<ExternalLink size={18} />}
colorScheme="purple"
size="sm"
>
Zobrazit originál
</Button>
</HStack>
</HStack>
{/* Zonerama Copyright */}
<Box
pt={2}
borderTopWidth="1px"
borderColor="gray.200"
>
<HStack spacing={2} fontSize="xs" color="gray.500">
<Text>
© Fotografie z{' '}
<Text
as="a"
href="https://zonerama.com"
target="_blank"
rel="noopener noreferrer"
color="blue.500"
fontWeight="600"
_hover={{ textDecoration: 'underline' }}
>
Zonerama
</Text>
</Text>
</HStack>
</Box>
</VStack>
</Box>
</VStack>
</ModalBody>
</ModalContent>
</Modal>
);
};
export default PhotoModal;