331 lines
13 KiB
JavaScript
Executable File
331 lines
13 KiB
JavaScript
Executable File
import {
|
||
gregorianToHijri,
|
||
calculateMissedPrayers,
|
||
getHijriAge,
|
||
getHijriBirthDate,
|
||
} from "../utils/hijri.js";
|
||
|
||
const PRAYERS = [
|
||
{ id: "fajr", name: "SABAH", arabic: "Fecr" },
|
||
{ id: "dhuhr", name: "ÖĞLE", arabic: "Zuhur" },
|
||
{ 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" },
|
||
];
|
||
|
||
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;
|
||
|
||
const html = `
|
||
<div class="bg-slate-900/60 backdrop-blur-2xl border border-white/10 p-8 rounded-3xl shadow-2xl max-w-4xl w-full h-[80vh] flex flex-col">
|
||
<button id="closeBtn" class="absolute top-4 right-4 bg-rose-500/20 hover:bg-rose-500/40 text-rose-300 border border-rose-500/30 w-8 h-8 rounded-full flex items-center justify-center font-bold text-xs transition-all">
|
||
✕
|
||
</button>
|
||
|
||
<h2 class="text-2xl font-bold text-white mb-1">🕌 Kaza Namaz Takibi</h2>
|
||
<p class="text-slate-400 text-sm mb-6">
|
||
Hicri yaşını ve kalan kaza namazını takip et.
|
||
</p>
|
||
|
||
${
|
||
!birthDate
|
||
? `
|
||
<div class="bg-slate-900/40 border border-white/10 p-6 rounded-2xl mb-6">
|
||
<h3 class="text-sm font-semibold text-slate-300 mb-4">Profil Bilgileri</h3>
|
||
<form id="profileForm" class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||
<div>
|
||
<label class="block text-xs text-slate-400 mb-1">Doğum Tarihi</label>
|
||
<input type="date" id="birthDate" required class="w-full bg-slate-950 border border-slate-800 rounded-xl px-4 py-2 text-white text-sm" />
|
||
</div>
|
||
<div>
|
||
<label class="block text-xs text-slate-400 mb-1">Cinsiyet</label>
|
||
<select id="gender" required class="w-full bg-slate-950 border border-slate-800 rounded-xl px-4 py-2 text-white text-sm">
|
||
<option value="male">Erkek</option>
|
||
<option value="female">Kadın</option>
|
||
</select>
|
||
</div>
|
||
<div class="flex items-end">
|
||
<button type="submit" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-xl text-sm font-medium transition-all">
|
||
Hesapla
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
`
|
||
: `
|
||
<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-3 mb-6">
|
||
<div class="bg-slate-900/40 border border-white/10 p-3 rounded-2xl text-center">
|
||
<p class="text-[10px] text-slate-400 mb-1">Hicri Doğum Tarihi</p>
|
||
<p class="text-sm font-bold text-white" id="hijriBirthDateDisplay">-</p>
|
||
</div>
|
||
${PRAYERS.map(
|
||
(p) => `
|
||
<div class="bg-slate-900/40 border border-white/10 p-3 rounded-2xl text-center">
|
||
<p class="text-[10px] text-slate-400 mb-1">${p.name}</p>
|
||
<p class="text-xs text-white">Kalan: <span id="remaining-${p.id}" class="font-bold text-emerald-300">-</span></p>
|
||
<p class="text-[10px] text-slate-500 mt-1">Toplam: <span id="total-${p.id}">-</span></p>
|
||
</div>
|
||
`,
|
||
).join("")}
|
||
</div>
|
||
|
||
<div class="bg-slate-900/40 border border-white/10 p-4 rounded-2xl mb-6">
|
||
<h3 class="text-sm font-semibold text-slate-300 mb-3">Kaza Namaz Ekle / Çıkar</h3>
|
||
<form id="addKazaForm" class="flex items-center gap-3">
|
||
<select id="kazaPrayerType" class="bg-slate-950 border border-slate-800 rounded-xl px-4 py-2 text-white text-sm">
|
||
${PRAYERS.map((p) => `<option value="${p.id}">${p.name}</option>`).join("")}
|
||
</select>
|
||
<input type="number" id="kazaCount" min="1" value="1" required class="w-20 bg-slate-950 border border-slate-800 rounded-xl px-4 py-2 text-white text-sm" />
|
||
<button type="button" id="addKazaBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-xl text-sm font-medium transition-all">
|
||
Ekle
|
||
</button>
|
||
<button type="button" id="removeKazaBtn" class="bg-rose-600 hover:bg-rose-700 text-white px-4 py-2 rounded-xl text-sm font-medium transition-all">
|
||
Çıkar
|
||
</button>
|
||
</form>
|
||
<p id="kazaMsg" class="text-xs mt-2 hidden"></p>
|
||
</div>
|
||
|
||
<div class="flex-1 overflow-y-auto pr-2">
|
||
<h3 class="text-sm font-semibold text-slate-300 mb-4">Bugünkü Namazlar</h3>
|
||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-3 mb-6">
|
||
${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 `
|
||
<div class="bg-slate-900/40 border ${alreadyDone ? "border-emerald-500/50 bg-emerald-500/10" : "border-white/10"} rounded-2xl p-4 text-center transition-all">
|
||
<p class="text-xs text-slate-400">${p.arabic}</p>
|
||
<p class="text-sm font-semibold text-white">${p.name}</p>
|
||
${alreadyDone ? "<p class='text-xs text-emerald-400 mt-1'>✓ Kılındı</p>" : ""}
|
||
</div>
|
||
`;
|
||
}).join("")}
|
||
</div>
|
||
|
||
<h3 class="text-sm font-semibold text-slate-300 mb-4">Son İşlemler</h3>
|
||
<div class="space-y-2" id="logsContainer">
|
||
<p class="text-xs text-slate-500">Yükleniyor...</p>
|
||
</div>
|
||
</div>
|
||
`
|
||
}
|
||
</div>
|
||
`;
|
||
|
||
return {
|
||
html,
|
||
initEvents: (container) => {
|
||
const closeBtn = container.querySelector("#closeBtn");
|
||
if (closeBtn) {
|
||
closeBtn.addEventListener("click", () => {
|
||
const event = new CustomEvent("navigate", { detail: "desktop" });
|
||
window.dispatchEvent(event);
|
||
});
|
||
}
|
||
|
||
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;
|
||
|
||
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);
|
||
});
|
||
}
|
||
} else {
|
||
refreshKazaStats(container, pb, birthDate, gender, profile);
|
||
|
||
const addBtn = container.querySelector("#addKazaBtn");
|
||
const removeBtn = container.querySelector("#removeKazaBtn");
|
||
|
||
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,
|
||
);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
},
|
||
};
|
||
}
|
||
|
||
async function refreshKazaStats(container, pb, birthDate, gender, profile) {
|
||
if (!birthDate) return;
|
||
|
||
const calc = calculateMissedPrayers(birthDate, gender);
|
||
const hijriBirth = getHijriBirthDate(birthDate);
|
||
|
||
const birthDateEl = container.querySelector("#hijriBirthDateDisplay");
|
||
if (birthDateEl) {
|
||
birthDateEl.textContent = `${hijriBirth.day} ${hijriBirth.monthName} ${hijriBirth.year}`;
|
||
}
|
||
|
||
let logs = [];
|
||
let logsByPrayer = {};
|
||
|
||
try {
|
||
const records = await pb.collection("kaza_logs").getFullList({
|
||
filter: `user = "${pb.authStore.model.id}"`,
|
||
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);
|
||
});
|
||
} catch (err) {
|
||
console.error("Loglar yüklenemedi:", err);
|
||
}
|
||
|
||
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 remaining = Math.max(0, missed - completed);
|
||
|
||
if (totalEl) totalEl.textContent = missed;
|
||
if (remainEl) remainEl.textContent = remaining;
|
||
});
|
||
|
||
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));
|
||
}
|
||
|
||
const logsContainer = container.querySelector("#logsContainer");
|
||
if (logsContainer) {
|
||
logsContainer.innerHTML =
|
||
logs
|
||
.slice(0, 20)
|
||
.map((log) => {
|
||
const prayer = PRAYERS.find((p) => p.id === log.prayerId);
|
||
return `
|
||
<div class="flex items-center justify-between bg-slate-900/20 border border-white/5 rounded-xl px-4 py-2">
|
||
<span class="text-xs text-slate-300">${prayer?.name || log.prayerId} x${log.count} - ${log.date}</span>
|
||
<span class="text-xs text-emerald-400">+${log.count}</span>
|
||
</div>
|
||
`;
|
||
})
|
||
.join("") || '<p class="text-xs text-slate-500">Henüz kayıt yok.</p>';
|
||
}
|
||
}
|
||
|
||
function showKazaMsg(el, text, success) {
|
||
el.textContent = text;
|
||
el.className = `text-xs mt-2 ${success ? "text-emerald-400" : "text-rose-400"}`;
|
||
el.classList.remove("hidden");
|
||
}
|