diff --git a/public/app.js b/public/app.js new file mode 100644 index 0000000..e9e48fc --- /dev/null +++ b/public/app.js @@ -0,0 +1,207 @@ +/* ============================================================ + ÖMER KALPAT CEP TELEFONU TAMİRİ — Yerinde Servis Vitrin + app.js: nav/scroll, mobil menü, data.json'dan kart doldurma, + hızlı + tam randevu formu (/api/randevu), aktif bölüm izleme + ============================================================ */ +'use strict'; + +(function () { + const API_DATA = '/api/data'; + const API_RANDEVU = '/api/randevu'; + + /* ---------- Navbar scroll durumu ---------- */ + const header = document.getElementById('header'); + function onScroll() { + if (header) header.classList.toggle('scrolled', window.scrollY > 30); + } + window.addEventListener('scroll', onScroll, { passive: true }); + onScroll(); + + /* ---------- Mobil menü ---------- */ + const menuBtn = document.getElementById('menuBtn'); + const nav = document.getElementById('navbar'); + if (menuBtn && nav) { + menuBtn.addEventListener('click', function () { + const open = nav.classList.toggle('open'); + menuBtn.classList.toggle('active', open); + menuBtn.setAttribute('aria-expanded', open ? 'true' : 'false'); + menuBtn.setAttribute('aria-label', open ? 'Menüyü kapat' : 'Menüyü aç'); + }); + nav.querySelectorAll('a').forEach(function (a) { + a.addEventListener('click', function () { + nav.classList.remove('open'); + menuBtn.classList.remove('active'); + menuBtn.setAttribute('aria-expanded', 'false'); + }); + }); + } + + /* ---------- Yardımcılar ---------- */ + function setMsg(id, text, ok) { + const el = document.getElementById(id); + if (!el) return; + el.textContent = text || ''; + el.className = 'form-msg ' + (ok ? 'ok' : 'err'); + } + + /* Türkçe telefon normalizasyon + basit doğrulama */ + function normalizeTel(v) { + return (v || '').replace(/[\s().\-]/g, ''); + } + function telGecerli(v) { + const t = normalizeTel(v); + return /^(\+?90|0)?5\d{9}$/.test(t); + } + + /* ---------- data.json'dan hizmet + fiyat kartlarını doldur ---------- */ + async function yukle() { + let data = null; + try { + const res = await fetch(API_DATA); + if (!res.ok) throw new Error('HTTP ' + res.status); + data = await res.json(); + } catch (err) { + console.error('data yüklenemedi, yedek içerik kullanılıyor:', err); + data = null; + } + + // Hizmet kartları + const hizmetGrid = document.getElementById('hizmetGrid'); + const hizmetler = (data && data.hizmetler.length) + ? data.hizmetler + : [ + { ad: 'Ekran Değişimi', ikon: '📱', aciklama: 'Kırık ve çatlak ekranları kaliteli parçayla değiştiriyoruz.', etiketler: [] }, + { ad: 'Batarya Değişimi', ikon: '🔋', aciklama: 'Hızlı biten bataryaları güvenli şekilde yeniliyoruz.', etiketler: [] }, + { ad: 'Yazılım & Format', ikon: '💾', aciklama: 'Donma ve kilitlenmelerde veri yedekli yazılım çözümü.', etiketler: [] }, + { ad: 'Diğer Arızalar', ikon: '🛠️', aciklama: 'Kamera, ses ve bağlantı sorunlarında yerinde onarım.', etiketler: [] } + ]; + + if (hizmetGrid) { + hizmetGrid.innerHTML = hizmetler.map(function (h) { + return ( + '
' + + '
' + (h.ikon || '🔧') + '
' + + '

' + h.ad + '

' + + '

' + h.aciklama + '

' + + (h.etiketler && h.etiketler.length + ? '' + h.etiketler.join(' · ') + '' + : 'Randevu al →') + + '
' + ); + }).join(''); + } + + // Fiyat kartları + const priceGrid = document.getElementById('priceGrid'); + const fiyatlar = (data && data.fiyatlar.length) ? data.fiyatlar : []; + if (priceGrid && fiyatlar.length) { + priceGrid.innerHTML = fiyatlar.map(function (f) { + const feat = f.oncelik + ? ' featured' + : ''; + const badge = f.oncelik ? 'En çok tercih edilen' : ''; + return ( + '
' + + badge + + '

' + f.hizmet + '

' + + '
' + f.fiyat + ' ' + (f.not || '') + '
' + + '
' + ); + }).join(''); + } + } + + /* ---------- Ortak form gönderimi ---------- */ + async function gonderRandevu(payload, msgId) { + setMsg(msgId, 'Gönderiliyor…', true); + try { + const res = await fetch(API_RANDEVU, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + const out = await res.json().catch(function () { return { mesaj: 'Beklenmeyen yanıt.' }; }); + if (res.ok && out.ok) { + setMsg(msgId, '✔ ' + out.mesaj, true); + return true; + } + setMsg(msgId, '⚠ ' + (out.mesaj || 'İşlem başarısız, lütfen tekrar deneyin.'), false); + return false; + } catch (err) { + console.error(err); + setMsg(msgId, '⚠ Sunucuya ulaşılamadı. Lütfen daha sonra deneyin ya da arayın.', false); + return false; + } + } + + /* ---------- Hızlı form (hero) ---------- */ + const quickForm = document.getElementById('quickForm'); + if (quickForm) { + quickForm.addEventListener('submit', function (e) { + e.preventDefault(); + const ad = document.getElementById('qAd').value.trim(); + const tel = document.getElementById('qTel').value.trim(); + const hizmet = document.getElementById('qHizmet').value; + const adresEl = document.getElementById('qAdres'); + const adres = adresEl.value.trim(); + + if (!ad || !hizmet || !adres) { + setMsg('quickMsg', 'Lütfen ad, hizmet ve adres alanlarını doldurun.', false); + return; + } + if (!telGecerli(tel)) { + setMsg('quickMsg', 'Lütfen geçerli bir cep telefonu girin (05xx…).', false); + return; + } + if (gonderRandevu({ ad: ad, telefon: tel, hizmet: hizmet, ilce: 'Sultanbeyli', adres: adres }, 'quickMsg')) { + quickForm.reset(); + } + }); + } + + /* ---------- Detaylı randevu formu ---------- */ + const appForm = document.getElementById('appForm'); + if (appForm) { + appForm.addEventListener('submit', function (e) { + e.preventDefault(); + const fd = new FormData(appForm); + const payload = Object.fromEntries(fd.entries()); + + if (!payload.ad || !payload.telefon || !payload.hizmet || !payload.adres) { + setMsg('appMsg', 'Lütfen zorunlu (*) alanları doldurun.', false); + return; + } + if (!telGecerli(payload.telefon)) { + setMsg('appMsg', 'Lütfen geçerli bir cep telefonu girin (05xx…).', false); + return; + } + gonderRandevu(payload, 'appMsg').then(function (tamam) { + if (tamam) appForm.reset(); + }); + }); + } + + /* ---------- Aktif bölüm vurgusu ---------- */ + const navLinks = document.querySelectorAll('.nav-link'); + const sections = ['hizmetler', 'yerinde', 'fiyat', 'iletisim']; + function aktifIle() { + const y = window.scrollY + 120; + let tersil = 'hizmetler'; + sections.forEach(function (id) { + const el = document.getElementById(id); + if (el && el.offsetTop <= y) tersil = id; + }); + navLinks.forEach(function (a) { + const ok = a.getAttribute('href') === '#' + tersil; + a.style.color = ok ? 'var(--accent)' : ''; + }); + } + window.addEventListener('scroll', aktifIle, { passive: true }); + + /* ---------- Başlat ---------- */ + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', yukle); + } else { + yukle(); + } +})();