// ===== Supabase Config ===== const SUPABASE_URL = "PASTE_SUPABASE_PROJECT_URL"; const SUPABASE_ANON_KEY = "PASTE_SUPABASE_ANON_KEY"; // CDN client exposed as "supabase" global, we create instance as "sb" const sb = window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY); // ===== Helpers ===== function toDateStr(d) { const dt = new Date(d); const y = dt.getFullYear(); const m = String(dt.getMonth() + 1).padStart(2, "0"); const day = String(dt.getDate()).padStart(2, "0"); return `${y}-${m}-${day}`; } function addMonths(dateStr, months) { const d = new Date(dateStr); const day = d.getDate(); d.setMonth(d.getMonth() + months); if (d.getDate() < day) d.setDate(0); return toDateStr(d); } function addYears(dateStr, years) { const d = new Date(dateStr); const m = d.getMonth(); d.setFullYear(d.getFullYear() + years); if (d.getMonth() !== m) d.setDate(0); return toDateStr(d); } function daysLeft(renewalDateStr) { const today = new Date(); today.setHours(0,0,0,0); const r = new Date(renewalDateStr); r.setHours(0,0,0,0); return Math.ceil((r - today) / (1000 * 60 * 60 * 24)); } function statusFromDays(d) { if (d < 0) return "overdue"; if (d <= 7) return "urgent"; if (d <= 30) return "due"; return "ok"; } function badgeHTML(st, d) { if (st === "overdue") return `Overdue (${d})`; if (st === "urgent") return `Urgent (${d})`; if (st === "due") return `Due Soon (${d})`; return `Active (${d})`; } function escapeHtml(str){ return String(str ?? "").replace(/[&<>"']/g, s => ({ "&":"&","<":"<",">":">",'"':""","'":"'" }[s])); } // ===== Backup / Anti-Data-Loss (JSON Export from DB) ===== async function exportBackupJSON(){ const [clients, services, payments] = await Promise.all([ sb.from("clients").select("*").order("created_at", {ascending:false}), sb.from("services").select("*").order("created_at", {ascending:false}), sb.from("payments").select("*").order("created_at", {ascending:false}), ]); if (clients.error || services.error || payments.error) { alert("Backup export failed. Check console."); console.error(clients.error, services.error, payments.error); return; } const payload = { exported_at: new Date().toISOString(), clients: clients.data, services: services.data, payments: payments.data }; const blob = new Blob([JSON.stringify(payload, null, 2)], {type:"application/json"}); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "hosting-renewals-backup.json"; a.click(); URL.revokeObjectURL(url); }