kaza namazı hesaplama düzeltildi.

This commit is contained in:
2026-07-31 04:24:10 +02:00
parent ff6191a473
commit d533c6a196
3 changed files with 156 additions and 86 deletions
+25 -18
View File
@@ -1,4 +1,4 @@
import { gregorianToHijri, calculateMissedPrayers } from "../utils/hijri.js"; import { gregorianToHijri } from "../utils/hijri.js";
import { import {
fetchWeather, fetchWeather,
getWeatherIcon, getWeatherIcon,
@@ -21,7 +21,7 @@ export function renderDesktop(selectedCity = "Edremit", pb) {
<div class="fixed top-0 right-0 h-screen w-80 md:w-96 bg-slate-900/85 border-l border-white/10 p-6 shadow-2xl z-20 flex flex-col justify-between overflow-y-auto"> <div class="fixed top-0 right-0 h-screen w-80 md:w-96 bg-slate-900/85 border-l border-white/10 p-6 shadow-2xl z-20 flex flex-col justify-between overflow-y-auto">
<div class="space-y-6"> <div class="space-y-6">
<!-- CANLI DİJİTAL SAAT WİDGET'I --> <!-- CANLI DİJİTAL SAAT WIDGET'I -->
<div class="bg-slate-950/60 border border-white/10 p-5 rounded-3xl text-center space-y-1 shadow-inner"> <div class="bg-slate-950/60 border border-white/10 p-5 rounded-3xl text-center space-y-1 shadow-inner">
<p class="text-xs font-semibold text-indigo-400 tracking-widest uppercase">CANLI SAAT</p> <p class="text-xs font-semibold text-indigo-400 tracking-widest uppercase">CANLI SAAT</p>
<div id="liveClock" class="text-4xl font-black text-white tracking-wider font-mono"> <div id="liveClock" class="text-4xl font-black text-white tracking-wider font-mono">
@@ -30,11 +30,11 @@ export function renderDesktop(selectedCity = "Edremit", pb) {
<p class="text-[11px] text-slate-400 font-medium">${dateStr}</p> <p class="text-[11px] text-slate-400 font-medium">${dateStr}</p>
</div> </div>
<!-- GENEL KAZA İLERLEME WİDGET'I --> <!-- GENEL KAZA İLERLEME WIDGET'I -->
<div id="desktopKazaProgressWidget" class="bg-slate-950/60 border border-white/10 p-4 rounded-2xl space-y-2"> <div id="desktopKazaProgressWidget" class="bg-slate-950/60 border border-white/10 p-4 rounded-2xl space-y-2">
<div class="flex items-center justify-between text-xs"> <div class="flex items-center justify-between text-xs">
<span class="font-bold text-indigo-300 flex items-center gap-1.5"> <span class="font-bold text-indigo-300 flex items-center gap-1.5">
<span>🎯</span> KAZA İLERLEMESİ <span>📊</span> KAZA İLERLEMESİ
</span> </span>
<span id="desktopKazaPct" class="font-extrabold text-emerald-400">%0</span> <span id="desktopKazaPct" class="font-extrabold text-emerald-400">%0</span>
</div> </div>
@@ -49,7 +49,7 @@ export function renderDesktop(selectedCity = "Edremit", pb) {
<!-- HİCRİ TAKVİM --> <!-- HİCRİ TAKVİM -->
<div class="space-y-1"> <div class="space-y-1">
<div class="flex items-center gap-2 text-xs font-semibold text-emerald-400"> <div class="flex items-center gap-2 text-xs font-semibold text-emerald-400">
<span>📅</span> HİCRİ TAKVİM <span>🌙</span> HİCRİ TAKVİM
</div> </div>
<p class="text-white font-bold text-base">${hijri.day} ${hijri.monthName} ${hijri.year}</p> <p class="text-white font-bold text-base">${hijri.day} ${hijri.monthName} ${hijri.year}</p>
<p class="text-xs text-slate-400">${hijri.weekday}</p> <p class="text-xs text-slate-400">${hijri.weekday}</p>
@@ -81,7 +81,6 @@ export function renderDesktop(selectedCity = "Edremit", pb) {
</div> </div>
<span class="text-slate-400 group-hover:translate-x-1 transition-transform text-xs">➔</span> <span class="text-slate-400 group-hover:translate-x-1 transition-transform text-xs">➔</span>
</div> </div>
</div> </div>
`; `;
@@ -106,33 +105,36 @@ export function renderDesktop(selectedCity = "Edremit", pb) {
function startClock(container) { function startClock(container) {
const clockEl = container.querySelector("#liveClock"); const clockEl = container.querySelector("#liveClock");
if (!clockEl) return; if (!clockEl) return;
const update = () => { const update = () => {
const now = new Date(); const now = new Date();
clockEl.textContent = now.toLocaleTimeString("tr-TR"); clockEl.textContent = now.toLocaleTimeString("tr-TR");
}; };
update(); update();
setInterval(update, 1000); setInterval(update, 1000);
} }
// PocketBase üzerindeki sabit hedeflere (target_*) göre kaza durumunu okuma
async function loadDesktopKazaProgress(container, pb) { async function loadDesktopKazaProgress(container, pb) {
const user = pb.authStore.model; const user = pb.authStore.model;
if (!user) return; if (!user) return;
const birthDate = user.birthDate || user.birthdate;
if (!birthDate) return;
const calc = calculateMissedPrayers(birthDate, user.gender || "male", 12); let totalTarget = 0;
let totalMissed =
calc.fajr + calc.dhuhr + calc.asr + calc.maghrib + calc.isha + calc.vitr ||
0;
let totalCompleted = 0; let totalCompleted = 0;
try { try {
const record = await pb const record = await pb
.collection("kaza_logs") .collection("kaza_logs")
.getFirstListItem(`user = "${user.id}"`); .getFirstListItem(`user = "${user.id}"`);
if (record) { if (record) {
totalTarget =
(record.target_fajr || 0) +
(record.target_dhuhr || 0) +
(record.target_asr || 0) +
(record.target_maghrib || 0) +
(record.target_isha || 0) +
(record.target_vitr || 0);
totalCompleted = totalCompleted =
(record.fajr || 0) + (record.fajr || 0) +
(record.dhuhr || 0) + (record.dhuhr || 0) +
@@ -143,10 +145,11 @@ async function loadDesktopKazaProgress(container, pb) {
} }
} catch {} } catch {}
const remaining = Math.max(0, totalTarget - totalCompleted);
const pct = const pct =
totalMissed > 0 totalTarget > 0
? Math.min(100, Math.round((totalCompleted / totalMissed) * 100)) ? Math.min(100, Math.round((totalCompleted / totalTarget) * 100))
: 100; : 0;
const bar = container.querySelector("#desktopKazaBar"); const bar = container.querySelector("#desktopKazaBar");
const pctText = container.querySelector("#desktopKazaPct"); const pctText = container.querySelector("#desktopKazaPct");
@@ -155,20 +158,23 @@ async function loadDesktopKazaProgress(container, pb) {
if (bar) bar.style.width = `${pct}%`; if (bar) bar.style.width = `${pct}%`;
if (pctText) pctText.textContent = `%${pct}`; if (pctText) pctText.textContent = `%${pct}`;
if (subText) if (subText)
subText.textContent = `${totalCompleted} kılınan / ${Math.max(0, totalMissed - totalCompleted)} kalan`; subText.textContent = `${totalCompleted} kılınan / ${remaining} kalan`;
} }
async function loadWeather(container, selectedCity) { async function loadWeather(container, selectedCity) {
const widget = container.querySelector("#weatherWidget"); const widget = container.querySelector("#weatherWidget");
if (!widget) return; if (!widget) return;
const data = await fetchWeather(selectedCity); const data = await fetchWeather(selectedCity);
if (!data) { if (!data) {
widget.innerHTML = `<span class="text-xs text-rose-400">Hava durumu alınamadı</span>`; widget.innerHTML = `<span class="text-xs text-rose-400">Hava durumu alınamadı</span>`;
return; return;
} }
const icon = getWeatherIcon(data.weathercode); const icon = getWeatherIcon(data.weathercode);
const desc = getWeatherDesc(data.weathercode); const desc = getWeatherDesc(data.weathercode);
const temp = Math.round(data.temperature); const temp = Math.round(data.temperature);
widget.innerHTML = ` widget.innerHTML = `
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div> <div>
@@ -188,6 +194,7 @@ async function loadWeather(container, selectedCity) {
async function loadImsakiye(container, selectedCity) { async function loadImsakiye(container, selectedCity) {
const widget = container.querySelector("#imsakiyeWidget"); const widget = container.querySelector("#imsakiyeWidget");
if (!widget) return; if (!widget) return;
const times = await fetchPrayerTimes(selectedCity); const times = await fetchPrayerTimes(selectedCity);
if (!times) { if (!times) {
widget.innerHTML = `<span class="text-xs text-rose-400">Vakitler alınamadı</span>`; widget.innerHTML = `<span class="text-xs text-rose-400">Vakitler alınamadı</span>`;
+130 -67
View File
@@ -24,7 +24,7 @@ export function renderKaza(pb) {
<span class="text-3xl">📿</span> <span class="text-3xl">📿</span>
<div> <div>
<h2 class="text-2xl font-bold text-white">Kaza Namazı Sayaç & Takip</h2> <h2 class="text-2xl font-bold text-white">Kaza Namazı Sayaç & Takip</h2>
<p class="text-slate-400 text-xs">Tamamladığın vakitler anlık olarak PocketBase hesabında güncellenir.</p> <p class="text-slate-400 text-xs">Kaza namazı borçlarınızı sabitleyin ve kıldıkça düşün.</p>
</div> </div>
</div> </div>
@@ -47,26 +47,38 @@ export function renderKaza(pb) {
</select> </select>
</div> </div>
<button type="submit" class="w-full bg-indigo-600 hover:bg-indigo-500 text-white py-2.5 rounded-xl text-sm font-semibold transition-all"> <button type="submit" class="w-full bg-indigo-600 hover:bg-indigo-500 text-white py-2.5 rounded-xl text-sm font-semibold transition-all">
Hesapla ve Başla Kaydet
</button> </button>
</form> </form>
</div> </div>
` `
: ` : `
<!-- GENEL İLERLEME BARI (XP/PERCENTAGE) --> <!-- HESAPLAMA VE İLERLEME BARI -->
<div class="bg-slate-950/60 border border-white/10 p-5 rounded-2xl mb-6 mt-2"> <div class="bg-slate-950/60 border border-white/10 p-5 rounded-2xl mb-6 mt-2 flex flex-col gap-4">
<div class="flex items-center justify-between mb-2"> <div class="flex flex-wrap items-center justify-between gap-2 border-b border-white/10 pb-3">
<span class="text-xs font-bold text-indigo-300 flex items-center gap-1.5"> <div>
<span>🎯</span> GENEL KAZA BİTİRME ORANI <h3 class="text-xs font-bold text-indigo-300 uppercase tracking-wider">Borç Tanımlama</h3>
</span> <p class="text-[11px] text-slate-400">Doğum tarihinize göre kaza borcunuzu hesaplayıp veritabanına sabitler.</p>
<span id="overallPercentage" class="text-sm font-extrabold text-emerald-400">%0</span> </div>
<button id="calcAndSaveBtn" class="bg-indigo-600 hover:bg-indigo-500 text-white px-4 py-2 rounded-xl text-xs font-semibold transition-all shadow-md active:scale-95">
⚡ Kaza Borçlarını Otomatik Hesapla & Kaydet
</button>
</div> </div>
<div class="w-full h-4 bg-slate-900 rounded-full overflow-hidden border border-white/5 p-0.5">
<div id="overallProgressBar" class="h-full bg-linear-to-r from-indigo-500 via-purple-500 to-emerald-400 rounded-full transition-all duration-700 ease-out w-[0%]"></div> <div>
</div> <div class="flex items-center justify-between mb-2">
<div class="flex justify-between items-center text-[11px] text-slate-400 mt-2.5"> <span class="text-xs font-bold text-indigo-300 flex items-center gap-1.5">
<span>Kılınan Toplam: <b id="totalCompletedText" class="text-emerald-400">0</b> vakit</span> <span>📊</span> GENEL KAZA BİTİRME ORANI
<span>Kalan Toplam Borç: <b id="totalRemainingText" class="text-amber-400">0</b> vakit</span> </span>
<span id="overallPercentage" class="text-sm font-extrabold text-emerald-400">%0</span>
</div>
<div class="w-full h-4 bg-slate-900 rounded-full overflow-hidden border border-white/5 p-0.5">
<div id="overallProgressBar" class="h-full bg-linear-to-r from-indigo-500 via-purple-500 to-emerald-400 rounded-full transition-all duration-700 ease-out w-[0%]"></div>
</div>
<div class="flex justify-between items-center text-[11px] text-slate-400 mt-2.5">
<span>Kılınan Toplam: <b id="totalCompletedText" class="text-emerald-400">0</b> vakit</span>
<span>Kalan Toplam Borç: <b id="totalRemainingText" class="text-amber-400">0</b> vakit</span>
</div>
</div> </div>
</div> </div>
@@ -76,8 +88,8 @@ export function renderKaza(pb) {
(p) => ` (p) => `
<div class="bg-slate-950/40 border border-white/10 p-3.5 rounded-2xl text-center relative overflow-hidden group"> <div class="bg-slate-950/40 border border-white/10 p-3.5 rounded-2xl text-center relative overflow-hidden group">
<p class="text-[11px] font-bold text-slate-300 mb-1">${p.name}</p> <p class="text-[11px] font-bold text-slate-300 mb-1">${p.name}</p>
<p class="text-xs text-slate-400">Kalan: <span id="remaining-${p.id}" class="font-extrabold text-emerald-300">-</span></p> <p class="text-xs text-slate-400">Kalan: <span id="remaining-${p.id}" class="font-extrabold text-amber-300">-</span></p>
<p class="text-[10px] text-slate-500 mt-0.5">Kılınan: <span id="completed-${p.id}" class="text-slate-300">0</span></p> <p class="text-[10px] text-slate-500 mt-0.5">Kılınan: <span id="completed-${p.id}" class="text-emerald-400">0</span></p>
<div class="w-full bg-slate-800 h-1.5 rounded-full mt-2.5 overflow-hidden"> <div class="w-full bg-slate-800 h-1.5 rounded-full mt-2.5 overflow-hidden">
<div id="progress-${p.id}" class="bg-emerald-400 h-full w-[0%] transition-all duration-500"></div> <div id="progress-${p.id}" class="bg-emerald-400 h-full w-[0%] transition-all duration-500"></div>
</div> </div>
@@ -88,7 +100,7 @@ export function renderKaza(pb) {
<!-- HIZLI SAYAÇ GÜNCELLEME ALANI --> <!-- HIZLI SAYAÇ GÜNCELLEME ALANI -->
<div class="bg-slate-950/40 border border-white/10 p-5 rounded-2xl mb-auto"> <div class="bg-slate-950/40 border border-white/10 p-5 rounded-2xl mb-auto">
<h3 class="text-xs font-bold text-slate-300 uppercase tracking-wider mb-3">Kaza Sayacı İşlem</h3> <h3 class="text-xs font-bold text-slate-300 uppercase tracking-wider mb-3">Kaza Kıldım / Düzenle</h3>
<form id="addKazaForm" class="flex flex-wrap items-center gap-3"> <form id="addKazaForm" class="flex flex-wrap items-center gap-3">
<select id="kazaPrayerType" class="bg-slate-900 border border-slate-800 rounded-xl px-4 py-2.5 text-white text-sm focus:outline-none"> <select id="kazaPrayerType" class="bg-slate-900 border border-slate-800 rounded-xl px-4 py-2.5 text-white text-sm focus:outline-none">
${PRAYERS.map((p) => `<option value="${p.id}">${p.name}</option>`).join("")} ${PRAYERS.map((p) => `<option value="${p.id}">${p.name}</option>`).join("")}
@@ -96,7 +108,7 @@ export function renderKaza(pb) {
<input type="number" id="kazaCount" min="1" value="1" required class="w-24 bg-slate-900 border border-slate-800 rounded-xl px-4 py-2.5 text-white text-sm text-center focus:outline-none font-bold" /> <input type="number" id="kazaCount" min="1" value="1" required class="w-24 bg-slate-900 border border-slate-800 rounded-xl px-4 py-2.5 text-white text-sm text-center focus:outline-none font-bold" />
<button type="button" id="addKazaBtn" class="bg-emerald-600 hover:bg-emerald-500 text-white px-5 py-2.5 rounded-xl text-sm font-semibold transition-all shadow-lg active:scale-95 flex items-center gap-1.5"> <button type="button" id="addKazaBtn" class="bg-emerald-600 hover:bg-emerald-500 text-white px-5 py-2.5 rounded-xl text-sm font-semibold transition-all shadow-lg active:scale-95 flex items-center gap-1.5">
<span>✓</span> Kıldım / Ekle (+) <span>✓</span> Kıldım (+1)
</button> </button>
<button type="button" id="removeKazaBtn" class="bg-rose-600/30 hover:bg-rose-600/50 text-rose-300 border border-rose-500/30 px-4 py-2.5 rounded-xl text-sm font-medium transition-all active:scale-95"> <button type="button" id="removeKazaBtn" class="bg-rose-600/30 hover:bg-rose-600/50 text-rose-300 border border-rose-500/30 px-4 py-2.5 rounded-xl text-sm font-medium transition-all active:scale-95">
Geri Al (-) Geri Al (-)
@@ -125,7 +137,6 @@ export function renderKaza(pb) {
e.preventDefault(); e.preventDefault();
const bInput = container.querySelector("#birthDateInput").value; const bInput = container.querySelector("#birthDateInput").value;
const gInput = container.querySelector("#genderInput").value; const gInput = container.querySelector("#genderInput").value;
try { try {
await pb.collection("users").update(pb.authStore.model.id, { await pb.collection("users").update(pb.authStore.model.id, {
birthdate: bInput, birthdate: bInput,
@@ -138,31 +149,83 @@ export function renderKaza(pb) {
new CustomEvent("navigate", { detail: "kaza" }), new CustomEvent("navigate", { detail: "kaza" }),
); );
} catch (err) { } catch (err) {
alert( alert("Profil kaydedilemedi.");
"Profil kaydedilemedi. PocketBase alan adlarını kontrol edin.",
);
} }
}); });
} else { } else {
refreshKazaStats(container, pb, birthDate, gender); refreshKazaStats(container, pb);
// Hesapla & Kaydet Butonu Tıklanması
container
.querySelector("#calcAndSaveBtn")
?.addEventListener("click", async () => {
if (
confirm(
"Kaza borçlarınız doğum tarihinize göre yeniden hesaplanıp veritabanına sabitlenecek. Onaylıyor musunuz?",
)
) {
await initAndSaveInitialKaza(pb, birthDate, gender);
await refreshKazaStats(container, pb);
showKazaMsg(
container.querySelector("#kazaMsg"),
"Kaza borçları hesaplandı ve PocketBase'e kaydedildi!",
true,
);
}
});
container container
.querySelector("#addKazaBtn") .querySelector("#addKazaBtn")
?.addEventListener("click", async () => { ?.addEventListener("click", async () => {
await updateKazaCount(container, pb, birthDate, gender, 1); await updateKazaCount(container, pb, 1);
}); });
container container
.querySelector("#removeKazaBtn") .querySelector("#removeKazaBtn")
?.addEventListener("click", async () => { ?.addEventListener("click", async () => {
await updateKazaCount(container, pb, birthDate, gender, -1); await updateKazaCount(container, pb, -1);
}); });
} }
}, },
}; };
} }
async function updateKazaCount(container, pb, birthDate, gender, direction) { // Otomatik hesaplayıp PocketBase'e toplam borç olarak kaydetme
async function initAndSaveInitialKaza(pb, birthDate, gender) {
const calc = calculateMissedPrayers(birthDate, gender, 12);
const userId = pb.authStore.model.id;
let userRecord = null;
try {
userRecord = await pb
.collection("kaza_logs")
.getFirstListItem(`user = "${userId}"`);
} catch {}
const initialData = {
user: userId,
target_fajr: calc.fajr,
target_dhuhr: calc.dhuhr,
target_asr: calc.asr,
target_maghrib: calc.maghrib,
target_isha: calc.isha,
target_vitr: calc.vitr,
fajr: userRecord?.fajr || 0,
dhuhr: userRecord?.dhuhr || 0,
asr: userRecord?.asr || 0,
maghrib: userRecord?.maghrib || 0,
isha: userRecord?.isha || 0,
vitr: userRecord?.vitr || 0,
};
if (userRecord) {
await pb.collection("kaza_logs").update(userRecord.id, initialData);
} else {
await pb.collection("kaza_logs").create(initialData);
}
}
async function updateKazaCount(container, pb, direction) {
const prayerId = container.querySelector("#kazaPrayerType").value; const prayerId = container.querySelector("#kazaPrayerType").value;
const countInput = container.querySelector("#kazaCount"); const countInput = container.querySelector("#kazaCount");
const amount = const amount =
@@ -171,22 +234,15 @@ async function updateKazaCount(container, pb, birthDate, gender, direction) {
try { try {
const userId = pb.authStore.model.id; const userId = pb.authStore.model.id;
let userRecord = null; let userRecord = await pb
.collection("kaza_logs")
.getFirstListItem(`user = "${userId}"`);
try { if (!userRecord) {
userRecord = await pb alert(
.collection("kaza_logs") "Önce 'Kaza Borçlarını Otomatik Hesapla & Kaydet' butonuna basmalısınız.",
.getFirstListItem(`user = "${userId}"`); );
} catch { return;
userRecord = await pb.collection("kaza_logs").create({
user: userId,
fajr: 0,
dhuhr: 0,
asr: 0,
maghrib: 0,
isha: 0,
vitr: 0,
});
} }
const currentCompleted = userRecord[prayerId] || 0; const currentCompleted = userRecord[prayerId] || 0;
@@ -199,44 +255,49 @@ async function updateKazaCount(container, pb, birthDate, gender, direction) {
showKazaMsg( showKazaMsg(
msg, msg,
amount > 0 amount > 0
? `🎉 ${amount} vakit kılınanlara eklendi!` ? ` ${amount} vakit kılınanlara eklendi!`
: `${Math.abs(amount)} vakit düşüldü.`, : `${Math.abs(amount)} vakit düşüldü.`,
true, true,
); );
if (countInput) countInput.value = "1"; if (countInput) countInput.value = "1";
await refreshKazaStats(container, pb, birthDate, gender); await refreshKazaStats(container, pb);
} catch (err) { } catch (err) {
console.error("Sayaç güncelleme hatası:", err); console.error("Güncelleme hatası:", err);
showKazaMsg( showKazaMsg(msg, "Güncelleme başarısız. Lütfen kontrol edin.", false);
msg,
"Güncelleme başarısız! PocketBase alanlarını kontrol edin.",
false,
);
} }
} }
async function refreshKazaStats(container, pb, birthDate, gender) { async function refreshKazaStats(container, pb) {
const calc = calculateMissedPrayers(birthDate, gender, 12);
const userId = pb.authStore.model.id; const userId = pb.authStore.model.id;
let userRecord = null;
let userRecord = { fajr: 0, dhuhr: 0, asr: 0, maghrib: 0, isha: 0, vitr: 0 };
try { try {
const record = await pb userRecord = await pb
.collection("kaza_logs") .collection("kaza_logs")
.getFirstListItem(`user = "${userId}"`); .getFirstListItem(`user = "${userId}"`);
if (record) userRecord = record;
} catch (err) {} } catch (err) {}
let grandTotalMissed = 0; if (!userRecord) {
// Kayıt yoksa kartları sıfır göster
PRAYERS.forEach((p) => {
const remainEl = container.querySelector(`#remaining-${p.id}`);
const completedEl = container.querySelector(`#completed-${p.id}`);
if (remainEl) remainEl.textContent = "Hesaplanmadı";
if (completedEl) completedEl.textContent = "0";
});
return;
}
let grandTotalTarget = 0;
let grandTotalCompleted = 0; let grandTotalCompleted = 0;
PRAYERS.forEach((p) => { PRAYERS.forEach((p) => {
const totalMissed = calc[p.id] || 0; const target = userRecord[`target_${p.id}`] || 0;
const completed = userRecord[p.id] || 0; const completed = userRecord[p.id] || 0;
const remaining = Math.max(0, totalMissed - completed); const remaining = Math.max(0, target - completed);
grandTotalMissed += totalMissed; grandTotalTarget += target;
grandTotalCompleted += completed; grandTotalCompleted += completed;
const remainEl = container.querySelector(`#remaining-${p.id}`); const remainEl = container.querySelector(`#remaining-${p.id}`);
@@ -245,21 +306,24 @@ async function refreshKazaStats(container, pb, birthDate, gender) {
if (remainEl) remainEl.textContent = remaining; if (remainEl) remainEl.textContent = remaining;
if (completedEl) completedEl.textContent = completed; if (completedEl) completedEl.textContent = completed;
if (progressEl) { if (progressEl) {
const pct = const pct =
totalMissed > 0 target > 0
? Math.min(100, Math.round((completed / totalMissed) * 100)) ? Math.min(100, Math.round((completed / target) * 100))
: 100; : 100;
progressEl.style.width = `${pct}%`; progressEl.style.width = `${pct}%`;
} }
}); });
const grandTotalRemaining = Math.max(
0,
grandTotalTarget - grandTotalCompleted,
);
const overallPct = const overallPct =
grandTotalMissed > 0 grandTotalTarget > 0
? Math.min( ? Math.min(
100, 100,
Math.round((grandTotalCompleted / grandTotalMissed) * 100), Math.round((grandTotalCompleted / grandTotalTarget) * 100),
) )
: 100; : 100;
@@ -271,8 +335,7 @@ async function refreshKazaStats(container, pb, birthDate, gender) {
if (bar) bar.style.width = `${overallPct}%`; if (bar) bar.style.width = `${overallPct}%`;
if (pctText) pctText.textContent = `%${overallPct}`; if (pctText) pctText.textContent = `%${overallPct}`;
if (compText) compText.textContent = grandTotalCompleted; if (compText) compText.textContent = grandTotalCompleted;
if (remText) if (remText) remText.textContent = grandTotalRemaining;
remText.textContent = Math.max(0, grandTotalMissed - grandTotalCompleted);
} }
function showKazaMsg(el, text, success) { function showKazaMsg(el, text, success) {
+1 -1
View File
@@ -61,7 +61,7 @@ export async function renderSettings(pb, currentBg, onBgSelect, currentCity, onC
(bg) => ` (bg) => `
<div data-url="${bg.url}" class="group relative h-40 rounded-2xl overflow-hidden border-2 cursor-pointer transition-all duration-300 hover:scale-[1.02] ${currentBg === bg.url ? "border-indigo-500 ring-4 ring-indigo-500/20" : "border-white/10 hover:border-white/30"}"> <div data-url="${bg.url}" class="group relative h-40 rounded-2xl overflow-hidden border-2 cursor-pointer transition-all duration-300 hover:scale-[1.02] ${currentBg === bg.url ? "border-indigo-500 ring-4 ring-indigo-500/20" : "border-white/10 hover:border-white/30"}">
<img src="${bg.url}" alt="${bg.title}" class="w-full h-full object-cover" /> <img src="${bg.url}" alt="${bg.title}" class="w-full h-full object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-slate-950/80 via-transparent to-transparent opacity-80 group-hover:opacity-100 transition-opacity flex items-end p-3"> <div class="absolute inset-0 bg-linear-to-t from-slate-950/80 via-transparent to-transparent opacity-80 group-hover:opacity-100 transition-opacity flex items-end p-3">
<span class="text-xs font-medium text-white truncate">${bg.title}</span> <span class="text-xs font-medium text-white truncate">${bg.title}</span>
</div> </div>
</div> </div>