From dc4af9cc1d69270a3335b77889d635ed9c33774f Mon Sep 17 00:00:00 2001 From: iontalp Date: Wed, 29 Jul 2026 04:01:21 +0200 Subject: [PATCH] =?UTF-8?q?genel=20olarak=20yap=C4=B1lan=20d=C3=BCzeltmele?= =?UTF-8?q?r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.js | 112 ++++++------ src/pages/desktop.js | 169 ++++++++--------- src/pages/kaza.js | 381 ++++++++++++++++----------------------- src/utils/prayerTimes.js | 45 +++-- 4 files changed, 319 insertions(+), 388 deletions(-) diff --git a/src/main.js b/src/main.js index 9a04d6c..18c0c5e 100755 --- a/src/main.js +++ b/src/main.js @@ -3,7 +3,7 @@ import PocketBase from "pocketbase"; import { renderSettings } from "./pages/settings.js"; import { renderDesktop } from "./pages/desktop.js"; import { renderKaza } from "./pages/kaza.js"; -import { getDefaultCity, getCityByName } from "./utils/locations.js"; +import { getDefaultCity } from "./utils/locations.js"; const pb = new PocketBase("https://pocketbase.iontalp.com"); const app = document.getElementById("app"); @@ -42,14 +42,20 @@ async function render() { let currentPage; if (activeTab === "settings") { - currentPage = await renderSettings(pb, currentBg, (newBg) => { - pb.authStore.model.selected_bg = newBg; - render(); - }, selectedCity, (city) => { - selectedCity = city; - localStorage.setItem("selected_city", city); - render(); - }); + currentPage = await renderSettings( + pb, + currentBg, + (newBg) => { + pb.authStore.model.selected_bg = newBg; + render(); + }, + selectedCity, + (city) => { + selectedCity = city; + localStorage.setItem("selected_city", city); + render(); + }, + ); } else if (activeTab === "kaza") { currentPage = renderKaza(pb); } else { @@ -59,32 +65,33 @@ async function render() { app.innerHTML = `
+ style="background-image: url('${currentBg}'); background-size: cover;">
-
+
- ${sidebarOpen ? `
` : ""} -
@@ -115,46 +122,35 @@ async function render() { const mainContent = document.getElementById("mainContent"); currentPage.initEvents(mainContent); - document.getElementById("navDesktop").addEventListener("click", () => { + document.getElementById("navDesktop")?.addEventListener("click", () => { activeTab = "desktop"; render(); }); - document.getElementById("navKaza").addEventListener("click", () => { + document.getElementById("navKaza")?.addEventListener("click", () => { activeTab = "kaza"; render(); }); - document.getElementById("navSettings").addEventListener("click", () => { + document.getElementById("navSettings")?.addEventListener("click", () => { activeTab = "settings"; render(); }); - document.getElementById("logoutBtn").addEventListener("click", () => { + + document.getElementById("logoutBtn")?.addEventListener("click", () => { pb.authStore.clear(); render(); }); - const globalToggle = document.getElementById("globalSidebarToggle"); - if (globalToggle) { - globalToggle.addEventListener("click", () => { + document + .getElementById("globalSidebarToggle") + ?.addEventListener("click", () => { sidebarOpen = !sidebarOpen; render(); }); - } - const overlay = document.getElementById("sidebarOverlay"); - if (overlay) { - overlay.addEventListener("click", () => { - sidebarOpen = false; - render(); - }); - } - - const closeBtn = document.getElementById("closeBtn"); - if (closeBtn) { - closeBtn.addEventListener("click", () => { - activeTab = "desktop"; - render(); - }); - } + document.getElementById("sidebarOverlay")?.addEventListener("click", () => { + sidebarOpen = false; + render(); + }); } window.addEventListener("navigate", (e) => { @@ -168,9 +164,9 @@ function renderLogin() {

Giriş Yap

- - - + + +
@@ -186,7 +182,7 @@ function renderLogin() { ); render(); } catch { - alert("Giriş başarısız!"); + alert("Giriş başarısız! Bilgilerinizi kontrol edin."); } }); } diff --git a/src/pages/desktop.js b/src/pages/desktop.js index fb22a6d..2bf9df5 100755 --- a/src/pages/desktop.js +++ b/src/pages/desktop.js @@ -1,9 +1,8 @@ import { gregorianToHijri } from "../utils/hijri.js"; import { fetchWeather, getWeatherIcon, getWeatherDesc } from "../utils/weather.js"; import { fetchPrayerTimes } from "../utils/prayerTimes.js"; -import { getCityByName } from "../utils/locations.js"; -export function renderDesktop(selectedCity = "İstanbul") { +export function renderDesktop(selectedCity = "Edremit") { const hijri = gregorianToHijri(); const today = new Date(); const dateStr = today.toLocaleDateString("tr-TR", { @@ -14,77 +13,58 @@ export function renderDesktop(selectedCity = "İstanbul") { }); const html = ` -
-
-
-
-
- ✨ -
-

Masaüstü

-
-

- Arka planı değiştirmek için sol menüdeki Ayarlar sekmesine geçebilirsin. -

+
+ +
+ + +
+

+ 🖥️ Masaüstü Araçları +

+ ${selectedCity}
-
-
-
-
-
- 📅 -
-

Hicri Takvim

+ +
+
+ 📅 HİCRİ TAKVİM
-

- ${hijri.weekday}
- ${hijri.day} ${hijri.monthName} ${hijri.year}
- ${dateStr} -

+

${hijri.day} ${hijri.monthName} ${hijri.year}

+

${dateStr} / ${hijri.weekday}

-
-
-
-
-
- 🌤️ -
-

Hava Durumu

-
-

- Yükleniyor... -

-
-
+
-
-
-
-
- 🌅 -
-

İmsakiye

+ +
+
+ Yükleniyor...
-

- Yükleniyor... -

-
-
-
-
-
- 🕌 -
-

Kaza Namaz

-
-

- Kaza namaz takibine geçmek için tıkla. -

+
+ + +
+
İMSAKİYE
+

Yükleniyor...

+ +
+ + +
+
+ 📿 +
+

Kaza Namazı Takibi

+

Kaydetmeye ve takibe başla

+
+
+ +
+
`; @@ -94,7 +74,10 @@ export function renderDesktop(selectedCity = "İstanbul") { initEvents: (container) => { loadWeather(container, selectedCity); loadImsakiye(container, selectedCity); - setupKazaShortcut(container); + + container.querySelector("#kazaShortcut")?.addEventListener("click", () => { + window.dispatchEvent(new CustomEvent("navigate", { detail: "kaza" })); + }); }, }; } @@ -102,51 +85,53 @@ export function renderDesktop(selectedCity = "İstanbul") { async function loadWeather(container, selectedCity) { const widget = container.querySelector("#weatherWidget"); if (!widget) return; - const data = await fetchWeather(selectedCity); if (!data) { - widget.innerHTML = "Hava durumu alınamadı."; + widget.innerHTML = `Hava durumu alınamadı`; return; } - const icon = getWeatherIcon(data.weathercode); const desc = getWeatherDesc(data.weathercode); const temp = Math.round(data.temperature); - widget.innerHTML = ` - ${icon} ${temp}°C -
- ${desc} (${data.cityName}) +
+
+
+ 🌤️ HAVA DURUMU +
+

${desc}

+
+
+ ${icon} + ${temp}°C +
+
`; } async function loadImsakiye(container, selectedCity) { const widget = container.querySelector("#imsakiyeWidget"); if (!widget) return; - - const city = getCityByName(selectedCity); - const times = await fetchPrayerTimes(selectedCity, city.lat, city.lon); + const times = await fetchPrayerTimes(selectedCity); if (!times) { - widget.innerHTML = "Namaz vakitleri alınamadı."; + widget.innerHTML = `Vakitler alınamadı`; return; } + const activeKey = times.currentPrayer?.key; + widget.innerHTML = ` - 🌅 İmsak: ${times.imsak}
- 🌅 Güneş: ${times.sunrise}
- 🌅 Öğle: ${times.dhuhr}
- 🌅 İkindi: ${times.asr}
- 🕌 Akşam: ${times.maghrib} - 🌅 Yatsı: ${times.isha}
+
+ 🕌 NAMAZ VAKİTLERİ + Şu an: ${times.currentPrayer?.name} +
+
+
İmsak: ${times.imsak}
+
Güneş: ${times.sunrise}
+
Öğle: ${times.dhuhr}
+
İkindi: ${times.asr}
+
Akşam: ${times.maghrib}
+
Yatsı: ${times.isha}
+
`; -} - -function setupKazaShortcut(container) { - const shortcut = container.querySelector("#kazaShortcut"); - if (!shortcut) return; - - shortcut.addEventListener("click", () => { - const event = new CustomEvent("navigate", { detail: "kaza" }); - window.dispatchEvent(event); - }); -} +} \ No newline at end of file diff --git a/src/pages/kaza.js b/src/pages/kaza.js index 2f607f0..f7cba6a 100755 --- a/src/pages/kaza.js +++ b/src/pages/kaza.js @@ -1,9 +1,4 @@ -import { - gregorianToHijri, - calculateMissedPrayers, - getHijriAge, - getHijriBirthDate, -} from "../utils/hijri.js"; +import { calculateMissedPrayers, getHijriBirthDate } from "../utils/hijri.js"; const PRAYERS = [ { id: "fajr", name: "SABAH", arabic: "Fecr" }, @@ -11,107 +6,107 @@ const PRAYERS = [ { id: "asr", name: "İKİNDİ", arabic: "Asr" }, { id: "maghrib", name: "AKŞAM", arabic: "Mağrib" }, { id: "isha", name: "YATSI", arabic: "İşa" }, - { id: "vitr", name: "VİTR", arabic: "Vitr" }, + { id: "vitr", name: "VİTİR", arabic: "Vitr" }, ]; export function renderKaza(pb) { - const pbBirthDate = pb.authStore.model?.birthdate; - const pbGender = pb.authStore.model?.gender; - const profileS = localStorage.getItem("kaza_profile"); - let profile = profileS ? JSON.parse(profileS) : null; - - const birthDate = pbBirthDate || profile?.birthDate; - const gender = pbGender || profile?.gender; + // Sıfır localStorage! Her şey PocketBase authStore modelinden okunuyor. + const user = pb.authStore.model; + const birthDate = user?.birthDate || user?.birthdate; + const gender = user?.gender || "male"; const html = ` -
+
- -

🕌 Kaza Namaz Takibi

-

- Hicri yaşını ve kalan kaza namazını takip et. -

+ +
+ 📿 +
+

Kaza Namazı Takibi

+

Tamamlanan namazlar anlık olarak PocketBase hesabınla eşzamanlanır.

+
+
${ !birthDate ? ` -
-

Profil Bilgileri

-
-
- - +
+

Doğum Tarihi Gerekli

+

Kaza namazı borcunu tam hesaplayabilmemiz için bilgilerinizi kaydedin.

+ +
+ +
-
- -
-
- -
+
` : ` -
-
-

Hicri Doğum Tarihi

-

-

+ +
+
+ + 🎯 TOPLAM İLERLEME (XP) + + %0
+
+
+
+
+ Kılınan: 0 vakit + Kalan Borç: 0 vakit +
+
+ + +
${PRAYERS.map( (p) => ` -
-

${p.name}

-

Kalan: -

-

Toplam: -

+
+

${p.name}

+

Kalan: -

+
+
+
- `, + ` ).join("")}
-
-

Kaza Namaz Ekle / Çıkar

-
- ${PRAYERS.map((p) => ``).join("")} - - -
- +
-
-

Bugünkü Namazlar

-
- ${PRAYERS.map((p) => { - const todayKey = new Date().toISOString().split("T")[0]; - const alreadyDone = profile?.todayLogs?.some( - (l) => l.prayerId === p.id && l.date === todayKey, - ); - return ` -
-

${p.arabic}

-

${p.name}

- ${alreadyDone ? "

✓ Kılındı

" : ""} -
- `; - }).join("")} -
- -

Son İşlemler

+ +
+

Son Kaza Geçmişi

Yükleniyor...

@@ -124,146 +119,69 @@ export function renderKaza(pb) { return { html, initEvents: (container) => { - const closeBtn = container.querySelector("#closeBtn"); - if (closeBtn) { - closeBtn.addEventListener("click", () => { - const event = new CustomEvent("navigate", { detail: "desktop" }); - window.dispatchEvent(event); - }); - } + container.querySelector("#closeBtn")?.addEventListener("click", () => { + window.dispatchEvent(new CustomEvent("navigate", { detail: "desktop" })); + }); if (!birthDate) { - const form = container.querySelector("#profileForm"); - const genderSelect = container.querySelector("#gender"); - if (gender && genderSelect) { - genderSelect.value = gender; - } - if (form) { - form.addEventListener("submit", async (e) => { - e.preventDefault(); - const birthDateInput = container.querySelector("#birthDate").value; - const genderInput = container.querySelector("#gender").value; + container.querySelector("#profileForm")?.addEventListener("submit", async (e) => { + e.preventDefault(); + const bInput = container.querySelector("#birthDateInput").value; + const gInput = container.querySelector("#genderInput").value; - if (!birthDateInput) { - alert("Lütfen doğum tarihinizi girin."); - return; - } - - try { - await pb.collection("users").update(pb.authStore.model.id, { - birthDate: birthDateInput, - gender: genderInput, - }); - } catch (err) { - console.error("PocketBase kaydedilemedi:", err); - } - - profile = { - gender: genderInput, - logs: profile?.logs || [], - todayLogs: profile?.todayLogs || [], - createdAt: profile?.createdAt || new Date().toISOString(), - }; - localStorage.setItem("kaza_profile", JSON.stringify(profile)); - - const event = new CustomEvent("navigate", { detail: "kaza" }); - window.dispatchEvent(event); - }); - } + try { + await pb.collection("users").update(pb.authStore.model.id, { + birthDate: bInput, + gender: gInput, + }); + pb.authStore.model.birthDate = bInput; + pb.authStore.model.gender = gInput; + window.dispatchEvent(new CustomEvent("navigate", { detail: "kaza" })); + } catch (err) { + alert("Profil kaydedilemedi. PocketBase bağlantısını kontrol edin."); + } + }); } else { - refreshKazaStats(container, pb, birthDate, gender, profile); + refreshKazaStats(container, pb, birthDate, gender); - const addBtn = container.querySelector("#addKazaBtn"); - const removeBtn = container.querySelector("#removeKazaBtn"); + container.querySelector("#addKazaBtn")?.addEventListener("click", async () => { + await handleKazaLog(container, pb, birthDate, gender, 1); + }); - if (addBtn) { - addBtn.addEventListener("click", async () => { - const prayerId = container.querySelector("#kazaPrayerType").value; - const countInput = container.querySelector("#kazaCount"); - const count = Math.max(1, parseInt(countInput?.value || "1", 10)); - const msg = container.querySelector("#kazaMsg"); - - try { - await pb.collection("kaza_logs").create({ - user: pb.authStore.model.id, - prayerId, - count, - date: new Date().toISOString().split("T")[0], - }); - - showKazaMsg(msg, `${count} kaza namaz eklendi!`, true); - if (countInput) countInput.value = "1"; - await refreshKazaStats(container, pb, birthDate, gender, profile); - } catch (err) { - console.error("Kaza eklenemedi:", err); - showKazaMsg( - msg, - "Eklenemedi. PocketBase bağlantısını kontrol et.", - false, - ); - } - }); - } - - if (removeBtn) { - removeBtn.addEventListener("click", async () => { - const prayerId = container.querySelector("#kazaPrayerType").value; - const countInput = container.querySelector("#kazaCount"); - const count = Math.max(1, parseInt(countInput?.value || "1", 10)); - const msg = container.querySelector("#kazaMsg"); - - try { - const records = await pb.collection("kaza_logs").getFullList({ - filter: `user = "${pb.authStore.model.id}" && prayerId = "${prayerId}"`, - sort: "-createdAt", - }); - - let remaining = count; - for (const record of records) { - if (remaining <= 0) break; - const recordCount = record.count || 1; - if (recordCount > remaining) { - await pb.collection("kaza_logs").update(record.id, { - count: recordCount - remaining, - }); - remaining = 0; - } else { - await pb.collection("kaza_logs").delete(record.id); - remaining -= recordCount; - } - } - - showKazaMsg(msg, `${count} kaza namaz çıkarıldı!`, true); - if (countInput) countInput.value = "1"; - await refreshKazaStats(container, pb, birthDate, gender, profile); - } catch (err) { - console.error("Kaza çıkarılamadı:", err); - showKazaMsg( - msg, - "Çıkarılamadı. PocketBase bağlantısını kontrol et.", - false, - ); - } - }); - } + container.querySelector("#removeKazaBtn")?.addEventListener("click", async () => { + await handleKazaLog(container, pb, birthDate, gender, -1); + }); } }, }; } -async function refreshKazaStats(container, pb, birthDate, gender, profile) { - if (!birthDate) return; +async function handleKazaLog(container, pb, birthDate, gender, multiplier) { + const prayerId = container.querySelector("#kazaPrayerType").value; + const countInput = container.querySelector("#kazaCount"); + const count = Math.max(1, parseInt(countInput?.value || "1", 10)) * multiplier; + const msg = container.querySelector("#kazaMsg"); - const calc = calculateMissedPrayers(birthDate, gender); - const hijriBirth = getHijriBirthDate(birthDate); + try { + await pb.collection("kaza_logs").create({ + user: pb.authStore.model.id, + prayerId, + count, + date: new Date().toISOString().split("T")[0], + }); - const birthDateEl = container.querySelector("#hijriBirthDateDisplay"); - if (birthDateEl) { - birthDateEl.textContent = `${hijriBirth.day} ${hijriBirth.monthName} ${hijriBirth.year}`; + showKazaMsg(msg, count > 0 ? `🎉 ${count} vakit kaza kılındı olarak işlendi!` : `${Math.abs(count)} vakit düşüldü.`, true); + if (countInput) countInput.value = "1"; + await refreshKazaStats(container, pb, birthDate, gender); + } catch (err) { + showKazaMsg(msg, "İşlem kaydedilemedi! PocketBase izinlerini veya bağlantısını kontrol edin.", false); } +} - let logs = []; +async function refreshKazaStats(container, pb, birthDate, gender) { + const calc = calculateMissedPrayers(birthDate, gender); let logsByPrayer = {}; + let logs = []; try { const records = await pb.collection("kaza_logs").getFullList({ @@ -271,60 +189,73 @@ async function refreshKazaStats(container, pb, birthDate, gender, profile) { sort: "-createdAt", }); - logs = records.map((r) => ({ - id: r.id, - prayerId: r.prayerId, - count: r.count || 1, - date: r.date, - createdAt: r.createdAt, - })); - - logs.forEach((l) => { - logsByPrayer[l.prayerId] = - (logsByPrayer[l.prayerId] || 0) + (l.count || 1); + logs = records; + records.forEach((l) => { + logsByPrayer[l.prayerId] = (logsByPrayer[l.prayerId] || 0) + (l.count || 0); }); } catch (err) { - console.error("Loglar yüklenemedi:", err); + console.error("Loglar çekilemedi:", err); } + let grandTotalMissed = 0; + let grandTotalCompleted = 0; + PRAYERS.forEach((p) => { - const totalEl = container.querySelector(`#total-${p.id}`); - const remainEl = container.querySelector(`#remaining-${p.id}`); const missed = calc[p.id] || 0; - const completed = logsByPrayer[p.id] || 0; + const completed = Math.max(0, logsByPrayer[p.id] || 0); const remaining = Math.max(0, missed - completed); - if (totalEl) totalEl.textContent = missed; + grandTotalMissed += missed; + grandTotalCompleted += completed; + + const remainEl = container.querySelector(`#remaining-${p.id}`); + const progressEl = container.querySelector(`#progress-${p.id}`); + if (remainEl) remainEl.textContent = remaining; + if (progressEl) { + const pct = missed > 0 ? Math.min(100, Math.round((completed / missed) * 100)) : 100; + progressEl.style.width = `${pct}%`; + } }); - const todayKey = new Date().toISOString().split("T")[0]; - const todayLogs = logs.filter((l) => l.date === todayKey); - if (profile) { - profile.todayLogs = todayLogs; - localStorage.setItem("kaza_profile", JSON.stringify(profile)); - } + // Genel İlerleme Çubuğu ve Yüzde Hesaplama + const overallPct = grandTotalMissed > 0 + ? Math.min(100, Math.round((grandTotalCompleted / grandTotalMissed) * 100)) + : 100; + const bar = container.querySelector("#overallProgressBar"); + const pctText = container.querySelector("#overallPercentage"); + const compText = container.querySelector("#totalCompletedText"); + const remText = container.querySelector("#totalRemainingText"); + + if (bar) bar.style.width = `${overallPct}%`; + if (pctText) pctText.textContent = `%${overallPct}`; + if (compText) compText.textContent = grandTotalCompleted; + if (remText) remText.textContent = Math.max(0, grandTotalMissed - grandTotalCompleted); + + // İşlem Geçmişi const logsContainer = container.querySelector("#logsContainer"); if (logsContainer) { logsContainer.innerHTML = logs - .slice(0, 20) + .slice(0, 10) .map((log) => { const prayer = PRAYERS.find((p) => p.id === log.prayerId); + const isPlus = log.count > 0; return ` -
- ${prayer?.name || log.prayerId} x${log.count} - ${log.date} - +${log.count} +
+ ${prayer?.name || log.prayerId} - ${log.date || ''} + ${isPlus ? '+' : ''}${log.count}
`; }) - .join("") || '

Henüz kayıt yok.

'; + .join("") || '

Henüz kayıt bulunmuyor.

'; } } function showKazaMsg(el, text, success) { + if (!el) return; el.textContent = text; - el.className = `text-xs mt-2 ${success ? "text-emerald-400" : "text-rose-400"}`; + el.className = `text-xs mt-2.5 ${success ? "text-emerald-400 font-medium" : "text-rose-400"}`; el.classList.remove("hidden"); -} +} \ No newline at end of file diff --git a/src/utils/prayerTimes.js b/src/utils/prayerTimes.js index b29f534..be90775 100755 --- a/src/utils/prayerTimes.js +++ b/src/utils/prayerTimes.js @@ -2,24 +2,16 @@ export async function fetchPrayerTimes(cityName = "Edremit", lat, lon) { try { let url; if (lat !== undefined && lon !== undefined) { - url = - "https://api.aladhan.com/v1/timings?latitude=" + - encodeURIComponent(lat) + - "&longitude=" + - encodeURIComponent(lon) + - "&method=13"; + url = `https://api.aladhan.com/v1/timings?latitude=${encodeURIComponent(lat)}&longitude=${encodeURIComponent(lon)}&method=13`; } else { - url = - "https://api.aladhan.com/v1/timingsByCity?city=" + - encodeURIComponent(cityName) + - "&country=Turkey&method=2"; + url = `https://api.aladhan.com/v1/timingsByCity?city=${encodeURIComponent(cityName)}&country=Turkey&method=13`; } const res = await fetch(url); - if (!res.ok) { - throw new Error("Namaz vakitleri alınamadı"); - } + if (!res.ok) throw new Error("Namaz vakitleri alınamadı"); + const data = await res.json(); const t = data.data.timings; + return { fajr: t.Fajr, sunrise: t.Sunrise, @@ -28,9 +20,36 @@ export async function fetchPrayerTimes(cityName = "Edremit", lat, lon) { maghrib: t.Maghrib, isha: t.Isha, imsak: t.Imsak, + currentPrayer: getCurrentPrayer(t), }; } catch (err) { console.error("Namaz vakti hatası:", err); return null; } } + +function getCurrentPrayer(timings) { + const now = new Date(); + const currentMinutes = now.getHours() * 60 + now.getMinutes(); + + const parseTime = (timeStr) => { + const [h, m] = timeStr.split(":").map(Number); + return h * 60 + m; + }; + + const imsak = parseTime(timings.Imsak); + const dhuhr = parseTime(timings.Dhuhr); + const asr = parseTime(timings.Asr); + const maghrib = parseTime(timings.Maghrib); + const isha = parseTime(timings.Isha); + + if (currentMinutes >= imsak && currentMinutes < dhuhr) + return { name: "Sabah", key: "fajr" }; + if (currentMinutes >= dhuhr && currentMinutes < asr) + return { name: "Öğle", key: "dhuhr" }; + if (currentMinutes >= asr && currentMinutes < maghrib) + return { name: "İkindi", key: "asr" }; + if (currentMinutes >= maghrib && currentMinutes < isha) + return { name: "Akşam", key: "maghrib" }; + return { name: "Yatsı", key: "isha" }; +}