astro_advokat/frontend/src/components/base/Map.astro
2026-03-30 20:21:41 +05:00

160 lines
8.5 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
import { CONTACT_CONSTANTS } from '@constants/constants.ts';
interface Props {
variant?: 'full' | 'card' | 'simple';
title?: string;
subtitle?: string;
address?: string;
mapUrl?: string;
showRouteButton?: boolean;
lazyLoad?: boolean;
}
const {
variant = 'full',
title = "Наш офис",
subtitle = "г. Сургут, пр. Комсомольский, 19",
address = CONTACT_CONSTANTS.address,
mapUrl = "https://yandex.ru/maps/-/CDu~yK-j",
showRouteButton = true,
lazyLoad = true
} = Astro.props;
const defaultMapUrl = "https://yandex.ru/map-widget/v1/?um=constructor%3Acdxezk6x&source=constructor";
const currentMapUrl = variant === 'card' ? defaultMapUrl : mapUrl;
---
{variant === 'full' ? (
<div class="w-full px-4 md:container md:mx-auto md:px-4 md:max-w-7xl mb-12">
<section id="map-section" class="relative w-full h-[500px] overflow-hidden rounded-3xl shadow-2xl">
<div class="absolute inset-0 bg-gray-200">
<iframe
data-src={currentMapUrl}
class="map-iframe w-full h-full border-0 grayscale contrast-125 opacity-0 transition-opacity duration-700"
allowfullscreen
loading={lazyLoad ? "lazy" : "eager"}
title="Карта проезда"
></iframe>
</div>
<div class="absolute inset-0 flex items-center justify-center pointer-events-none">
<div class="bg-white/95 backdrop-blur-xl p-8 md:p-10 rounded-2xl shadow-2xl max-w-sm text-center pointer-events-auto border border-white/50 mx-4">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-gold)] to-[var(--color-gold-hover)] rounded-2xl flex items-center justify-center mx-auto mb-6 shadow-lg">
<svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
</div>
<h3 class="text-gray-900 font-bold text-lg uppercase tracking-wider mb-3">
{title}
</h3>
<p class="text-gray-600 mb-6 leading-relaxed">
{address}
</p>
{showRouteButton && (
<a
href={currentMapUrl}
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center gap-2 px-6 py-3 bg-gray-900 text-white text-sm font-bold uppercase tracking-wider rounded-xl hover:bg-[var(--color-gold)] transition-colors shadow-lg hover:shadow-xl"
>
Открыть в картах
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/>
</svg>
</a>
)}
</div>
</div>
</section>
</div>
) : variant === 'card' ? (
<div class="relative bg-white/80 backdrop-blur-xl border border-white/50 rounded-3xl overflow-hidden shadow-2xl shadow-gray-900/5 hover:shadow-2xl hover:shadow-[var(--color-blue-primary)]/10 transition-all duration-500 group">
<div class="absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-gray-100/80 pointer-events-none z-10"></div>
<div class="relative z-20 p-8 pb-0 flex flex-col items-center text-center md:flex-row md:items-center md:justify-between gap-4">
<div>
<h2 class="text-xl sm:text-2xl md:text-3xl font-bold text-gray-900 mb-2 flex items-center gap-3 justify-center md:justify-start">
<span class="w-2 h-6 sm:h-8 bg-gradient-to-b from-[var(--color-gold)] to-[var(--color-gold-hover)] rounded-full hidden md:block"></span>
{title}
</h2>
<p class="text-gray-600 text-base sm:text-lg flex items-center gap-2 justify-center md:justify-start">
<svg class="w-4 sm:w-5 h-4 sm:h-5 text-[var(--color-gold)] hidden md:block" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"/>
</svg>
{subtitle}
</p>
</div>
{showRouteButton && (
<a href={currentMapUrl} target="_blank" class="inline-flex items-center justify-center gap-2 px-4 sm:px-6 py-2 sm:py-3 bg-[var(--color-gold)]/10 hover:bg-[var(--color-gold)]/20 text-[var(--color-gold)] font-semibold rounded-xl transition-all duration-300 border border-[var(--color-gold)]/20 hover:border-[var(--color-gold)]/40 self-center md:self-auto">
<span class="text-sm sm:text-base">Маршрут</span>
<svg class="w-4 sm:w-5 h-4 sm:h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
<path stroke-linecap="round" stroke-linejoin="round" d="M4 20L20 4" opacity="0.2" stroke-width="1" />
</svg>
</a>
)}
</div>
<div class="relative h-[450px] mt-8 bg-gray-100 overflow-hidden">
<iframe
src={currentMapUrl}
width="100%"
height="100%"
frameborder="0"
class="filter grayscale-[30%] contrast-125 group-hover:grayscale-0 transition-all duration-700"
loading={lazyLoad ? "lazy" : "eager"}
title="Офис на карте Сургута"
></iframe>
<div class="absolute inset-0 flex items-center justify-center bg-gray-900/0 group-hover:bg-gray-900/0 transition-all duration-500 pointer-events-none">
<span class="px-4 sm:px-6 py-2 sm:py-3 bg-white/95 backdrop-blur-sm text-gray-900 rounded-full text-xs sm:text-sm font-bold border border-gray-200 shadow-xl transform translate-y-4 opacity-0 group-hover:translate-y-0 group-hover:opacity-100 transition-all duration-500 pointer-events-auto cursor-pointer hover:bg-[var(--color-gold)] hover:text-white hover:border-[var(--color-gold)]">
Наведите для взаимодействия
</span>
</div>
</div>
</div>
) : (
<div class="relative h-[400px] bg-gray-100 overflow-hidden rounded-xl">
<iframe
src={currentMapUrl}
width="100%"
height="100%"
frameborder="0"
loading={lazyLoad ? "lazy" : "eager"}
title="Карта"
></iframe>
</div>
)}
{lazyLoad && variant === 'full' && (
<script>
const mapSection = document.getElementById('map-section');
const iframe = mapSection?.querySelector('.map-iframe');
if (mapSection && iframe) {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const frame = entry.target.querySelector('iframe');
if (frame && frame.dataset.src) {
frame.src = frame.dataset.src;
frame.onload = () => {
frame.classList.remove('opacity-0');
frame.classList.add('opacity-100');
};
observer.unobserve(entry.target);
}
}
});
}, { rootMargin: '200px', threshold: 0.1 });
observer.observe(mapSection);
}
</script>
)}