← Kapat

main.js

(function () {
    'use strict';

    const routeToPhp = {
        '/': 'index.php',
        '/index.php': 'index.php',
        '/dezenfeksiyon-hizmeti': 'dezenfeksiyon-hizmeti.php',
        '/dezenfeksiyon-hizmeti.php': 'dezenfeksiyon-hizmeti.php',
        '/kurumsal-hasere-kontrolu': 'kurumsal-hasere-kontrolu.php',
        '/kurumsal-hasere-kontrolu.php': 'kurumsal-hasere-kontrolu.php',
        '/deltrap': 'deltrap.php',
        '/deltrap.php': 'deltrap.php',
        '/iletisim': 'iletisim.php',
        '/iletisim.php': 'iletisim.php',
        '/teklif-al': 'teklif-al.php',
        '/teklif-al.php': 'teklif-al.php',
        '/kvkk': 'kvkk.php',
        '/kvkk.php': 'kvkk.php'
    };

    const phpToClean = {
        'index.php': '/',
        'dezenfeksiyon-hizmeti.php': '/dezenfeksiyon-hizmeti',
        'kurumsal-hasere-kontrolu.php': '/kurumsal-hasere-kontrolu',
        'deltrap.php': '/deltrap',
        'iletisim.php': '/iletisim',
        'teklif-al.php': '/teklif-al',
        'kvkk.php': '/kvkk'
    };

    const pageCache = new Map();
    const preloader = document.getElementById('preloader');
    const siteHeader = document.querySelector('.site-header');
    const scrollTopButton = document.getElementById('scroll-top');
    const appBasePath = detectAppBasePath();
    let isNavigating = false;

    if (window.gsap && window.ScrollTrigger) {
        gsap.registerPlugin(ScrollTrigger);
    }

    function ensureTopBeforeTransition() {
        if (window.scrollY <= 4) {
            return Promise.resolve();
        }

        return new Promise((resolve) => {
            const startedAt = performance.now();
            const maxWait = 900;

            window.scrollTo({ top: 0, behavior: 'smooth' });

            const check = () => {
                const elapsed = performance.now() - startedAt;
                if (window.scrollY <= 4 || elapsed >= maxWait) {
                    window.scrollTo({ top: 0, behavior: 'auto' });
                    resolve();
                    return;
                }
                requestAnimationFrame(check);
            };

            requestAnimationFrame(check);
        });
    }

    function detectAppBasePath() {
        const knownSegments = new Set([
            '',
            'index.php',
            'dezenfeksiyon-hizmeti',
            'dezenfeksiyon-hizmeti.php',
            'kurumsal-hasere-kontrolu',
            'kurumsal-hasere-kontrolu.php',
            'deltrap',
            'deltrap.php',
            'iletisim',
            'iletisim.php',
            'teklif-al',
            'teklif-al.php',
            'kvkk',
            'kvkk.php'
        ]);

        const segments = window.location.pathname.split('/').filter(Boolean);
        const lastSegment = segments[segments.length - 1] ?? '';
        if (knownSegments.has(lastSegment)) {
            segments.pop();
        }
        return '/' + segments.join('/');
    }

    function waitForLoad() {
        if (document.readyState === 'complete') {
            return Promise.resolve();
        }
        return new Promise((resolve) => window.addEventListener('load', resolve, { once: true }));
    }

    function showPreloader() {
        if (!preloader) return;
        preloader.classList.add('active');
    }

    function hidePreloader() {
        if (!preloader) return;
        preloader.classList.remove('active');
    }

    function toRelativePath(pathname) {
        let relative = pathname;
        if (appBasePath !== '/' && pathname.startsWith(appBasePath + '/')) {
            relative = pathname.slice(appBasePath.length);
        } else if (appBasePath !== '/' && pathname === appBasePath) {
            relative = '/';
        }
        if (!relative.startsWith('/')) {
            relative = '/' + relative;
        }
        if (relative.length > 1 && relative.endsWith('/')) {
            relative = relative.slice(0, -1);
        }
        return relative;
    }

    function toPublicPath(cleanPath) {
        if (cleanPath === '/') {
            return appBasePath === '/' ? '/' : appBasePath + '/';
        }
        return (appBasePath === '/' ? '' : appBasePath) + cleanPath;
    }

    function getPhpFromPath(pathname) {
        const relativePath = toRelativePath(pathname);
        return routeToPhp[relativePath] || null;
    }

    function cleanPathFromPhp(phpFile) {
        return phpToClean[phpFile] || '/';
    }

    async function fetchPage(phpFile) {
        if (pageCache.has(phpFile)) {
            return pageCache.get(phpFile);
        }

        const response = await fetch(phpFile, { credentials: 'same-origin' });
        if (!response.ok) {
            throw new Error('Sayfa yüklenemedi: ' + phpFile);
        }

        const html = await response.text();
        const parser = new DOMParser();
        const doc = parser.parseFromString(html, 'text/html');
        const main = doc.querySelector('main');

        if (!main) {
            throw new Error('Main içeriği bulunamadı: ' + phpFile);
        }

        const pageData = {
            mainHtml: main.outerHTML,
            title: doc.title,
            description: doc.querySelector('meta[name="description"]')?.getAttribute('content') || ''
        };

        pageCache.set(phpFile, pageData);
        return pageData;
    }

    async function preloadAllPages() {
        const uniquePages = Array.from(new Set(Object.values(routeToPhp)));
        await Promise.all(uniquePages.map((phpFile) => fetchPage(phpFile)));
    }

    async function animateMainIn(mainElement) {
        if (!mainElement || !window.gsap) {
            return;
        }

        gsap.set(mainElement, { y: -42, opacity: 0 });
        await new Promise((resolve) => {
            gsap.to(mainElement, {
                y: 0,
                opacity: 1,
                duration: 0.32,
                ease: 'power2.out',
                clearProps: 'transform,opacity',
                onComplete: resolve
            });
        });
    }

    async function replaceMainContent(mainHtml, options = {}) {
        const { animateIn = true } = options;

        const parser = new DOMParser();
        const doc = parser.parseFromString(mainHtml, 'text/html');
        const newMain = doc.querySelector('main');
        const currentMain = document.querySelector('main');

        if (!newMain || !currentMain) {
            return null;
        }

        if (!window.gsap) {
            currentMain.replaceWith(newMain);
            return newMain;
        }

        await new Promise((resolve) => {
            gsap.killTweensOf(currentMain);
            gsap.to(currentMain, {
                y: -42,
                opacity: 0,
                duration: 0.24,
                ease: 'power2.in',
                onComplete: resolve
            });
        });

        currentMain.replaceWith(newMain);

        if (animateIn) {
            await animateMainIn(newMain);
        } else {
            gsap.set(newMain, { y: -42, opacity: 0 });
        }

        return newMain;
    }

    function updateMeta(title, description) {
        document.title = title;
        const descriptionMeta = document.querySelector('meta[name="description"]');
        if (descriptionMeta) {
            descriptionMeta.setAttribute('content', description || '');
        }
    }

    function updateActiveNav(cleanPath) {
        const navLinks = document.querySelectorAll('.site-header nav a');
        navLinks.forEach((link) => {
            const href = link.getAttribute('href') || '';
            const url = new URL(href, window.location.origin + toPublicPath('/'));
            const phpFile = getPhpFromPath(url.pathname);
            const linkCleanPath = cleanPathFromPhp(phpFile || 'index.php');
            link.classList.toggle('active-nav', linkCleanPath === cleanPath);
        });
    }

    function toggleHeaderScrolledState() {
        if (!siteHeader) return;
        siteHeader.classList.toggle('scrolled', window.scrollY > 12);
    }

    function runPageAnimations(options = {}) {
        const { skipEntrance = false } = options;

        if (!(window.gsap && window.ScrollTrigger)) {
            return;
        }

        ScrollTrigger.getAll().forEach((trigger) => trigger.kill());

        const revealItems = document.querySelectorAll('.reveal');
        revealItems.forEach((item) => gsap.set(item, { clearProps: 'opacity,transform' }));

        requestAnimationFrame(() => {
            revealItems.forEach((item, index) => {
                const itemTop = item.getBoundingClientRect().top;
                const isInInitialViewport = itemTop < window.innerHeight * 0.9;

                if (skipEntrance) {
                    gsap.set(item, { clearProps: 'opacity,transform' });
                    return;
                }

                if (isInInitialViewport) {
                    gsap.fromTo(item, { opacity: 0, y: 14 }, {
                        opacity: 1,
                        y: 0,
                        duration: 0.55,
                        ease: 'power2.out',
                        delay: (index % 5) * 0.02,
                        clearProps: 'opacity,transform'
                    });
                    return;
                }

                gsap.set(item, { opacity: 0, y: 20 });
                gsap.to(item, {
                    opacity: 1,
                    y: 0,
                    duration: 0.72,
                    ease: 'power2.out',
                    delay: (index % 5) * 0.02,
                    clearProps: 'opacity,transform',
                    scrollTrigger: {
                        trigger: item,
                        start: 'top 86%',
                        toggleActions: 'play none none none'
                    }
                });
            });

            ScrollTrigger.refresh();

            setTimeout(() => {
                document.querySelectorAll('.reveal').forEach((item) => {
                    const computed = window.getComputedStyle(item);
                    if (Number.parseFloat(computed.opacity) === 0) {
                        gsap.set(item, { clearProps: 'opacity,transform' });
                        item.style.opacity = '1';
                        item.style.transform = 'none';
                    }
                });
            }, 900);
        });

        if (skipEntrance) {
            return;
        }

        const heroTitle = document.querySelector('.hero-title');
        const heroSub = document.querySelector('.hero-sub');
        const heroMedia = document.querySelector('.hero-media');

        if (heroTitle && heroSub) {
            const heroTimeline = gsap.timeline({ defaults: { ease: 'power3.out' } });
            heroTimeline
                .from(heroTitle, { y: 30, opacity: 0, duration: 0.8 })
                .from(heroSub, { y: 16, opacity: 0, duration: 0.5 }, '-=0.45');

            if (heroMedia) {
                heroTimeline.from(heroMedia, { y: 20, opacity: 0, duration: 0.6 }, '-=0.4');
            }
        }
    }

    function initScrollTop() {
        if (!scrollTopButton || scrollTopButton.dataset.bound === 'true') {
            return;
        }

        const toggleScrollTop = () => {
            scrollTopButton.classList.toggle('active', window.scrollY > 100);
        };

        toggleScrollTop();
        window.addEventListener('scroll', toggleScrollTop, { passive: true });
        scrollTopButton.addEventListener('click', (event) => {
            event.preventDefault();
            window.scrollTo({ top: 0, behavior: 'smooth' });
        });

        scrollTopButton.dataset.bound = 'true';
    }

    function initContactWidget() {
        const widget = document.getElementById('contactWidget');
        if (!widget || widget.dataset.bound === 'true') return;

        const widgetButton = widget.querySelector('.contact-widget-button');
        const widgetMenu = widget.querySelector('.contact-widget-menu');
        const widgetPrompt = widget.querySelector('.contact-widget-prompt');
        const promptClose = widget.querySelector('.prompt-close');

        if (!widgetButton || !widgetMenu || !widgetPrompt) return;

        let promptDismissed = false;
        let promptHideTimer;

        const hidePrompt = (options = {}) => {
            const { removeNotification = true, dismiss = false } = options;
            widgetPrompt.classList.remove('show');
            if (promptHideTimer) {
                clearTimeout(promptHideTimer);
                promptHideTimer = null;
            }
            if (dismiss) promptDismissed = true;
            if (removeNotification) widget.classList.remove('has-notification');
        };

        const showPrompt = () => {
            if (promptDismissed) return;
            widget.classList.remove('has-notification');
            widgetPrompt.classList.add('show');
            promptHideTimer = setTimeout(() => {
                widget.classList.add('has-notification');
                hidePrompt({ removeNotification: false, dismiss: true });
            }, 2000);
        };

        const toggleWidget = () => {
            widget.classList.toggle('active');
            if (widget.classList.contains('active')) {
                hidePrompt({ removeNotification: true, dismiss: true });
                widgetMenu.classList.remove('show-campaign');
            }
        };

        widgetButton.addEventListener('click', toggleWidget);
        widgetButton.addEventListener('keydown', (event) => {
            if (event.key === 'Enter' || event.key === ' ') {
                event.preventDefault();
                toggleWidget();
            }
        });

        document.addEventListener('click', (event) => {
            if (!widget.contains(event.target) && widget.classList.contains('active')) {
                widget.classList.remove('active');
                widgetMenu.classList.remove('show-campaign');
            }
        });

        setTimeout(showPrompt, 1000);

        if (promptClose) {
            promptClose.addEventListener('click', (event) => {
                event.stopPropagation();
                hidePrompt({ removeNotification: true, dismiss: true });
            });
        }

        widgetPrompt.addEventListener('click', (event) => {
            if (event.target !== promptClose) {
                widget.classList.add('active');
                hidePrompt({ removeNotification: true, dismiss: true });
            }
        });

        widget.querySelectorAll('.campaign-btn, .contact-item a').forEach((element) => {
            element.addEventListener('click', () => {
                widget.classList.remove('active');
                widgetMenu.classList.remove('show-campaign');
            });
        });

        widget.dataset.bound = 'true';
    }

    function initCallRequestPopup() {
        const popup = document.getElementById('callRequestPopup');
        const form = document.getElementById('callRequestForm');
        if (!popup || !form || popup.dataset.bound === 'true') return;

        const loadingMessage = popup.querySelector('.call-popup-loading');
        const successMessage = popup.querySelector('.call-popup-success');
        const errorMessage = popup.querySelector('.call-popup-error');
        const closeElements = popup.querySelectorAll('[data-call-popup-close]');

        const resetFeedback = () => {
            [loadingMessage, successMessage, errorMessage].forEach((el) => {
                if (el) el.style.display = 'none';
            });
        };

        const setFeedback = (state) => {
            resetFeedback();
            if (state === 'loading' && loadingMessage) loadingMessage.style.display = 'inline-flex';
            if (state === 'success' && successMessage) successMessage.style.display = 'inline-flex';
            if (state === 'error' && errorMessage) errorMessage.style.display = 'inline-flex';
        };

        const closePopup = () => {
            popup.classList.remove('is-visible');
            document.body.classList.remove('call-popup-open');
            document.removeEventListener('keydown', handleEscape);
            resetFeedback();
        };

        const handleEscape = (event) => {
            if (event.key === 'Escape') closePopup();
        };

        const openPopup = () => {
            form.reset();
            form.classList.remove('is-submitting');
            resetFeedback();
            const timeField = form.querySelector('[name="form_time"]');
            if (timeField) timeField.value = Date.now();
            popup.classList.add('is-visible');
            document.body.classList.add('call-popup-open');
            document.addEventListener('keydown', handleEscape);
        };

        closeElements.forEach((element) => {
            element.addEventListener('click', () => {
                if (!form.classList.contains('is-submitting')) closePopup();
            });
        });

        document.addEventListener('click', (event) => {
            const trigger = event.target.closest('[data-call-popup="true"]');
            if (!trigger) return;
            event.preventDefault();
            openPopup();
        });

        form.addEventListener('submit', (event) => {
            event.preventDefault();

            if (!form.checkValidity()) {
                form.reportValidity();
                return;
            }

            form.classList.add('is-submitting');
            setFeedback('loading');

            fetch('forms/call-request.php', {
                method: 'POST',
                body: new FormData(form)
            })
                .then((response) => {
                    if (!response.ok) throw new Error('Request failed');
                    return response.text();
                })
                .then(() => {
                    setFeedback('success');
                    form.reset();
                    setTimeout(closePopup, 1800);
                })
                .catch(() => setFeedback('error'))
                .finally(() => form.classList.remove('is-submitting'));
        });

        popup.dataset.bound = 'true';
    }

    function initTeklifForm() {
        const form = document.getElementById('teklifForm');
        if (!form || form.dataset.bound === 'true') return;
        form.dataset.bound = 'true';

        const timeField = form.querySelector('[name="form_time"]');
        if (timeField) timeField.value = Date.now();

        const submit = document.getElementById('teklifSubmit');
        const feedback = document.getElementById('teklifFeedback');

        form.addEventListener('submit', function (e) {
            e.preventDefault();

            if (!form.checkValidity()) {
                form.reportValidity();
                return;
            }

            const label = submit.querySelector('.btn-label');
            const loading = submit.querySelector('.btn-loading');
            label.hidden = true;
            loading.hidden = false;
            submit.disabled = true;
            if (feedback) feedback.innerHTML = '';

            fetch('forms/teklif.php', {
                method: 'POST',
                body: new FormData(form)
            })
            .then(function (r) {
                if (!r.ok) return r.text().then(function (t) { throw new Error(t); });
                return r.text();
            })
            .then(function () {
                if (feedback) feedback.innerHTML = '<div class="teklif-success">&#10003; Talebiniz alındı! En geç 24 saat içinde sizi arayacağız.</div>';
                form.reset();
                if (timeField) timeField.value = Date.now();
            })
            .catch(function (err) {
                if (feedback) feedback.innerHTML = '<div class="teklif-error">&#10005; ' + (err.message || 'Bir hata oluştu. Lütfen tekrar deneyin.') + '</div>';
            })
            .finally(function () {
                label.hidden = false;
                loading.hidden = true;
                submit.disabled = false;
            });
        });
    }

    function initHamburgerMenu() {
        const toggle = document.getElementById('navToggle');
        const nav = document.getElementById('siteNav');
        if (!toggle || !nav) return;

        function closeMenu() {
            document.body.classList.remove('nav-open');
            toggle.setAttribute('aria-expanded', 'false');
        }

        toggle.addEventListener('click', (e) => {
            e.stopPropagation();
            const isOpen = document.body.classList.toggle('nav-open');
            toggle.setAttribute('aria-expanded', String(isOpen));
        });

        nav.addEventListener('click', (e) => {
            if (e.target.closest('a')) closeMenu();
        });

        document.addEventListener('click', (e) => {
            if (!e.target.closest('.nav-wrap') && document.body.classList.contains('nav-open')) {
                closeMenu();
            }
        });

        window.addEventListener('scroll', () => {
            if (document.body.classList.contains('nav-open')) closeMenu();
        }, { passive: true });
    }

    function initPersistentUi() {
        toggleHeaderScrolledState();
        window.addEventListener('scroll', toggleHeaderScrolledState, { passive: true });
        initScrollTop();
        initContactWidget();
        initCallRequestPopup();
        initHamburgerMenu();
    }

    function reinitPageUi(options = {}) {
        runPageAnimations(options);
        toggleHeaderScrolledState();
        initTeklifForm();
    }

    async function navigateTo(phpFile, options = {}) {
        const { push = true, immediate = false } = options;

        if (isNavigating) return;

        const currentPhp = history.state?.phpFile || getPhpFromPath(window.location.pathname) || 'index.php';
        if (phpFile === currentPhp && push) {
            return;
        }

        const shouldScrollBeforeEnter = window.scrollY > 4;
        isNavigating = true;

        try {
            if (!pageCache.has(phpFile) && !immediate) {
                showPreloader();
            }

            const pageData = await fetchPage(phpFile);
            const nextMain = await replaceMainContent(pageData.mainHtml, {
                animateIn: !shouldScrollBeforeEnter
            });

            if (shouldScrollBeforeEnter) {
                await ensureTopBeforeTransition();
                await animateMainIn(nextMain);
            }

            updateMeta(pageData.title, pageData.description);

            const cleanPath = cleanPathFromPhp(phpFile);
            const publicPath = toPublicPath(cleanPath);

            if (push) {
                history.pushState({ phpFile }, '', publicPath);
            } else {
                history.replaceState({ phpFile }, '', publicPath);
            }

            updateActiveNav(cleanPath);
            reinitPageUi({ skipEntrance: true });
        } finally {
            hidePreloader();
            isNavigating = false;
        }
    }

    function shouldHandleLink(event, link) {
        if (!link) return false;
        if (link.target === '_blank' || link.hasAttribute('download')) return false;
        if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return false;

        const href = link.getAttribute('href') || '';
        if (href.startsWith('#') || href.startsWith('mailto:') || href.startsWith('tel:')) return false;

        const url = new URL(href, window.location.origin + toPublicPath('/'));
        if (url.origin !== window.location.origin) return false;
        return Boolean(getPhpFromPath(url.pathname));
    }

    function initRouter() {
        document.addEventListener('click', (event) => {
            const link = event.target.closest('a[href]');
            if (!shouldHandleLink(event, link)) return;

            const url = new URL(link.getAttribute('href'), window.location.origin + toPublicPath('/'));
            const phpFile = getPhpFromPath(url.pathname);
            if (!phpFile) return;

            event.preventDefault();
            navigateTo(phpFile, { push: true }).catch(() => {
                window.location.href = url.pathname;
            });
        });

        window.addEventListener('popstate', () => {
            const phpFile = getPhpFromPath(window.location.pathname) || 'index.php';
            navigateTo(phpFile, { push: false, immediate: true }).catch(() => {
                window.location.reload();
            });
        });
    }

    async function boot() {
        showPreloader();
        initPersistentUi();
        initRouter();

        const currentPhp = getPhpFromPath(window.location.pathname) || 'index.php';
        const currentMain = document.querySelector('main');
        const currentDescription = document.querySelector('meta[name="description"]')?.getAttribute('content') || '';
        if (currentMain) {
            pageCache.set(currentPhp, {
                mainHtml: currentMain.outerHTML,
                title: document.title,
                description: currentDescription
            });
        }

        await Promise.all([waitForLoad(), preloadAllPages()]);
        updateActiveNav(cleanPathFromPhp(currentPhp));
        reinitPageUi({ skipEntrance: false });
        history.replaceState({ phpFile: currentPhp }, '', toPublicPath(cleanPathFromPhp(currentPhp)));
        hidePreloader();
    }

    boot().catch(() => {
        hidePreloader();
    });
})();