import { useEffect, useState } from 'react'; import { useMutation } from '@tanstack/react-query'; import { Box, Button, FormControl, FormLabel, FormErrorMessage, Heading, Input, Text, Textarea, VStack, useToast, useColorModeValue, Container, Tabs, TabList, TabPanels, Tab, TabPanel, SimpleGrid, HStack, Avatar, Badge, Icon, Link, Divider } from '@chakra-ui/react'; import { useForm } from 'react-hook-form'; import { sendContact } from '../services/public'; import { useSettings } from '../hooks/useSettings'; import MainLayout from '../components/layout/MainLayout'; import { FiMail, FiPhone, FiMapPin } from 'react-icons/fi'; import { trackContactSubmit, trackFormSubmit } from '../utils/umami'; import SponsorsSection from '../components/common/SponsorsSection'; import ContactMap from '../components/home/ContactMap'; import { getPublicContacts, GroupedContacts } from '../services/contactInfo'; type ContactFormData = { name: string; email: string; subject: string; message: string; source?: string; }; const ContactPage: React.FC = () => { const toast = useToast(); const { settings } = useSettings(); const cardBg = useColorModeValue('white', 'gray.800'); const cardBorder = useColorModeValue('gray.200', 'gray.700'); const bgColor = useColorModeValue('white', 'gray.800'); const borderColor = useColorModeValue('gray.200', 'gray.700'); // Public contacts (grouped by category) const [contactsData, setContactsData] = useState(null); const [contactsLoading, setContactsLoading] = useState(true); const { register, handleSubmit, reset, formState: { errors, isSubmitting }, } = useForm(); const { mutate, isLoading } = useMutation({ mutationFn: (data: ContactFormData) => sendContact({ ...data, source: 'contact' }), onSuccess: () => { reset(); // Track successful contact form submission trackContactSubmit(true); trackFormSubmit('Contact Form', true); toast({ title: 'Zpráva odeslána', description: 'Děkujeme za vaši zprávu. Brzy se vám ozveme zpět.', status: 'success', duration: 5000, isClosable: true, }); }, onError: (error: any) => { // Heuristics for Axios errors const code = error?.code || ''; const msgFromServer = error?.response?.data?.error || error?.response?.data?.message; const isTimeout = code === 'ECONNABORTED' || /timeout/i.test(String(error?.message || '')); const isNetwork = !!error?.isAxiosError && !error?.response; const description = msgFromServer || (isTimeout ? 'Vypršel časový limit požadavku. Zkuste to prosím znovu za chvíli.' : isNetwork ? 'Požadavek se nezdařil (síť/CORS). Zkuste to znovu nebo obnovte stránku.' : 'Něco se pokazilo. Zkuste to prosím znovu později.'); // Track failed contact form submission trackContactSubmit(false); trackFormSubmit('Contact Form', false); toast({ title: 'Chyba', description, status: 'error', duration: 6000, isClosable: true, }); }, }); // Load public contacts once useEffect(() => { let mounted = true; (async () => { try { const data = await getPublicContacts(); if (mounted) setContactsData(data); } catch (e) { console.error('Failed to load contacts', e); } finally { if (mounted) setContactsLoading(false); } })(); return () => { mounted = false; }; }, []); const onSubmit = (data: ContactFormData) => { mutate(data); }; return ( {/* Top: Map + Contact categories (tabs) */} Kontakt {/* contacts are loaded in useEffect */} {(() => { const lat = (settings as any)?.location_latitude; const lng = (settings as any)?.location_longitude; const hasLocation = !!lat && !!lng; const categories = Object.entries(contactsData?.categories || {}); const uncategorized = contactsData?.uncategorized || []; const hasContacts = categories.length > 0 || uncategorized.length > 0; const hasContactInfo = !!( (settings as any)?.contact_address || (settings as any)?.contact_phone || (settings as any)?.contact_email ); if (!hasLocation && !hasContacts && !hasContactInfo) return null; return ( {/* Map on the left */} {hasLocation && ( )} {/* Right column: contact info card (if any) + contacts tabs */} {(hasContactInfo || hasContacts) && ( {hasContactInfo && ( Kontaktní údaje {(settings as any)?.contact_address && ( Adresa {(settings as any)?.contact_address} {(settings as any)?.contact_city && ( {(settings as any)?.contact_zip && `${(settings as any)?.contact_zip} `} {(settings as any)?.contact_city} )} {(settings as any)?.contact_country && {(settings as any)?.contact_country}} )} {(settings as any)?.contact_phone && ( Telefon {(settings as any)?.contact_phone} )} {(settings as any)?.contact_email && ( Email {(settings as any)?.contact_email} )} )} {hasContacts && ( Kontaktní osoby {categories.map(([name]) => ( {name} ))} {uncategorized.length > 0 && Ostatní} {categories.map(([name, persons]) => ( {persons.map((contact) => ( {contact.image_url && ( )} {contact.name} {contact.position && ( {contact.position} )} {contact.description && ( {contact.description} )} {contact.email && ( {contact.email} )} {contact.phone && ( {contact.phone} )} ))} ))} {uncategorized.length > 0 && ( {uncategorized.map((contact) => ( {contact.image_url && ( )} {contact.name} {contact.position && ( {contact.position} )} {contact.description && ( {contact.description} )} {contact.email && ( {contact.email} )} {contact.phone && ( {contact.phone} )} ))} )} )} )} ); })()} {/* Contact form at the end */} Kontaktujte nás Máte dotaz nebo připomínku? Napište nám zprávu a my se vám ozveme co nejdříve zpět.
Jméno a příjmení * {errors.name && errors.name.message} E-mailová adresa * {errors.email && errors.email.message} Předmět {errors.subject && errors.subject.message} Zpráva *