Прямой REST API Supabase вместо JS-клиента
This commit is contained in:
parent
4789eb558e
commit
faa69e8cbd
44
app.html
44
app.html
@ -87,36 +87,46 @@ td{padding:8px 12px;border-bottom:1px solid #F2F4F7}tr:hover td{background:#F2F4
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var SB=supabase.createClient("https://znexbjafkvyjffffbhlf.supabase.co","eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InpuZXhiamFma3Z5amZmZmZiaGhsZiIsInJvbGUiOiJhbm9uIiwiaWF0IjoxNzgwNjQ0MTgyLCJleHAiOjIwOTYyMjAxODJ9.fhKixmi5Tx6yB-rRkGqHzOdepbXq3BoETdh7s__aDRk");
|
||||
var SB_URL="https://znexbjafkvyjffffbhlf.supabase.co";
|
||||
var SB_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InpuZXhiamFma3Z5amZmZmZiaGhsZiIsInJvbGUiOiJhbm9uIiwiaWF0IjoxNzgwNjQ0MTgyLCJleHAiOjIwOTYyMjAxODJ9.fhKixmi5Tx6yB-rRkGqHzOdepbXq3BoETdh7s__aDRk";
|
||||
var SB=supabase.createClient(SB_URL,SB_KEY);
|
||||
var U,editId,lastSubmitted;
|
||||
try{U=JSON.parse(sessionStorage.getItem("pab_user"));if(!U)location.href="index.html"}catch(e){location.href="index.html"}
|
||||
document.getElementById("dn").textContent=U.login;
|
||||
function isA(){return U&&U.login==="admin"}
|
||||
|
||||
// ===== DATA: Supabase + localStorage =====
|
||||
// ===== DATA: Supabase REST API + localStorage =====
|
||||
function getU(){return JSON.parse(localStorage.getItem("pab_users")||"{}")}
|
||||
function saveU(d){localStorage.setItem("pab_users",JSON.stringify(d))}
|
||||
function allU(){var r=getU();r.admin={pass:"admin",name:"Администратор",role:"Руководитель",email:"admin@telecom.kz",branch:"АО «Казахтелеком»",dept:"ЦА",region:"Центральный",oblast:"—",city:"г. Астана"};return r}
|
||||
function getA(){return JSON.parse(localStorage.getItem("pab_audits")||"[]")}
|
||||
function saveA(d){localStorage.setItem("pab_audits",JSON.stringify(d))}
|
||||
|
||||
// Sync: push localStorage to Supabase, then pull Supabase to localStorage
|
||||
// Supabase REST API helpers
|
||||
async function sbFetch(method,table,body){
|
||||
try{
|
||||
var url=SB_URL+"/rest/v1/"+table;
|
||||
var headers={"apikey":SB_KEY,"Authorization":"Bearer "+SB_KEY,"Content-Type":"application/json","Prefer":"return=minimal"};
|
||||
var opts={method:method,headers:headers};
|
||||
if(method==="PATCH"||method==="POST"){headers["Prefer"]="resolution=merge-duplicates";opts.body=JSON.stringify(body)}
|
||||
var r=await fetch(url,opts);
|
||||
if(!r.ok){console.error("SB error:",r.status,await r.text())}else{console.log("SB OK:",method,table)}
|
||||
return r;
|
||||
}catch(e){console.error("SB fetch error:",e)}
|
||||
}
|
||||
async function sbUpsert(table,data){await sbFetch("POST",table,data)}
|
||||
async function sbDeleteT(table,col,val){try{await fetch(SB_URL+"/rest/v1/"+table+"?"+col+"=eq."+encodeURIComponent(val),{method:"DELETE",headers:{"apikey":SB_KEY,"Authorization":"Bearer "+SB_KEY}})}catch(e){}}
|
||||
|
||||
// Sync
|
||||
async function syncFromSB(){
|
||||
try{
|
||||
// 1. Push localStorage users to Supabase
|
||||
var lu=getU();for(var k in lu){await SB.from("users").upsert({login:k,pass:lu[k].pass,name:lu[k].name,email:lu[k].email,role:lu[k].role,freq:lu[k].freq,branch:lu[k].branch,dept:lu[k].dept,region:lu[k].region,oblast:lu[k].oblast,city:lu[k].city}).select();}
|
||||
// 2. Push localStorage audits to Supabase
|
||||
var la=getA();for(var i=0;i<la.length;i++){var a=la[i];await SB.from("audits").upsert({id:a.id,number:a.number,date:a.date,location:a.location,region:a.region,work_type:a.workType,worker_count:a.workerCount,observer:a.observer,observer_role:a.observerRole,overall_safe:a.overallSafe,categories:a.categories,total_violations:a.totalViolations,dialogue:a.dialogue,docs:a.docs,created_by:a.createdBy,created_at:a.createdAt}).select();}
|
||||
// 3. Pull from Supabase back to localStorage (to get data from other PCs)
|
||||
var su=await SB.from("users").select("*");if(su.data){var um={};su.data.forEach(function(x){um[x.login]={pass:x.pass,name:x.name,email:x.email,role:x.role,freq:x.freq,branch:x.branch,dept:x.dept,region:x.region,oblast:x.oblast,city:x.city}});saveU(um)}
|
||||
var sa=await SB.from("audits").select("*").order("created_at",{ascending:false});if(sa.data){var am=[];sa.data.forEach(function(x){am.push({id:x.id,number:x.number,date:x.date,location:x.location,region:x.region,workType:x.work_type,workerCount:x.worker_count,observer:x.observer,observerRole:x.observer_role,overallSafe:x.overall_safe,categories:x.categories,totalViolations:x.total_violations,dialogue:x.dialogue,docs:x.docs,createdBy:x.created_by,createdAt:x.created_at})});saveA(am)}
|
||||
console.log("Synced to/from Supabase")
|
||||
}catch(e){console.log("Sync error:",e)}
|
||||
var lu=getU();for(var k in lu){await sbUpsert("users",{login:k,pass:lu[k].pass,name:lu[k].name,email:lu[k].email,role:lu[k].role,freq:lu[k].freq,branch:lu[k].branch,dept:lu[k].dept,region:lu[k].region,oblast:lu[k].oblast,city:lu[k].city})}
|
||||
var la=getA();for(var i=0;i<la.length;i++){var a=la[i];await sbUpsert("audits",{id:a.id,number:a.number,date:a.date,location:a.location,region:a.region,work_type:a.workType,worker_count:a.workerCount,observer:a.observer,observer_role:a.observerRole,overall_safe:a.overallSafe,categories:a.categories,total_violations:a.totalViolations,dialogue:a.dialogue,docs:a.docs,created_by:a.createdBy,created_at:a.createdAt})}
|
||||
var su=await fetch(SB_URL+"/rest/v1/users?select=*",{headers:{"apikey":SB_KEY,"Authorization":"Bearer "+SB_KEY}});if(su.ok){var suj=await su.json();var um={};suj.forEach(function(x){um[x.login]={pass:x.pass,name:x.name,email:x.email,role:x.role,freq:x.freq,branch:x.branch,dept:x.dept,region:x.region,oblast:x.oblast,city:x.city}});saveU(um)}
|
||||
var sa=await fetch(SB_URL+"/rest/v1/audits?select=*&order=created_at.desc",{headers:{"apikey":SB_KEY,"Authorization":"Bearer "+SB_KEY}});if(sa.ok){var saj=await sa.json();var am=[];saj.forEach(function(x){am.push({id:x.id,number:x.number,date:x.date,location:x.location,region:x.region,workType:x.work_type,workerCount:x.worker_count,observer:x.observer,observerRole:x.observer_role,overallSafe:x.overall_safe,categories:x.categories,totalViolations:x.total_violations,dialogue:x.dialogue,docs:x.docs,createdBy:x.created_by,createdAt:x.created_at})});saveA(am)}
|
||||
}catch(e){console.error("Sync error:",e)}
|
||||
}
|
||||
|
||||
// Write to Supabase
|
||||
async function sbUpsert(table,data){try{var r=await SB.from(table).upsert(data);if(r.error)console.error("SB upsert error:",r.error);else console.log("SB upsert OK:",table)}catch(e){console.error("SB upsert failed:",e)}}
|
||||
async function sbDelete(table,id){try{var r=await SB.from(table).delete().eq("id",id);if(r.error)console.error("SB delete error:",r.error)}catch(e){}}
|
||||
syncFromSB().then(function(){rHS()});
|
||||
|
||||
// ===== SYNC ON LOAD =====
|
||||
syncFromSB().then(function(){rHS()});
|
||||
@ -207,7 +217,7 @@ function resetF(){
|
||||
|
||||
function exportCSV(){var a=getA();if(a.length===0){alert("Нет данных");return}var all=allU(),h="Бланк №;Дата;Место;Наблюдатель;Должность;Филиал;Регион;Город;Статус;Нарушений",rs=a.map(function(x){var u=all[x.createdBy]||{};return(x.number||"")+";"+x.date+";"+x.location+";"+x.observer+";"+(x.observerRole||"")+";"+(u.branch||"")+";"+(u.region||"")+";"+(u.city||"")+";"+(x.overallSafe?"Безопасно":"Нарушения")+";"+(x.totalViolations||0)}),csv="\uFEFF"+h+"\n"+rs.join("\n"),bl=new Blob([csv],{type:"text/csv"}),ur=URL.createObjectURL(bl),dl=document.createElement("a");dl.href=ur;dl.download="pab.csv";dl.click();URL.revokeObjectURL(ur)}
|
||||
function editA(id){if(!isA()){alert("Только админ");return}alert("Редактирование: аудит #"+id)}
|
||||
function delA(id){if(!isA()){alert("Только админ");return}if(!confirm("Удалить?"))return;saveA(getA().filter(function(a){return a.id!==id}));sbDelete("audits",id);rHS()}
|
||||
function delA(id){if(!isA()){alert("Только админ");return}if(!confirm("Удалить?"))return;saveA(getA().filter(function(a){return a.id!==id}));sbDeleteT("audits","id",id);rHS()}
|
||||
function downloadFullCSV(){var a=getA();if(a.length===0){alert("Нет данных");return}var all=allU(),h="Бланк №;Дата;Место;Наблюдатель;Филиал;Регион;Статус;Нарушений",rs=a.map(function(x){var u=all[x.createdBy]||{};return(x.number||"")+";"+x.date+";"+x.location+";"+x.observer+";"+(u.branch||"")+";"+(u.region||"")+";"+(x.overallSafe?"Безопасно":"Нарушения")+";"+(x.totalViolations||0)}),csv="\uFEFF"+h+"\n"+rs.join("\n"),bl=new Blob([csv],{type:"text/csv"}),ur=URL.createObjectURL(bl),dl=document.createElement("a");dl.href=ur;dl.download="pab-full.csv";dl.click();URL.revokeObjectURL(ur)}
|
||||
function showAllUsers(){if(!isA())return;var all=allU(),h="<h2>👥 Пользователи</h2><table style=\"width:100%;border-collapse:collapse;font-size:13px\"><tr style=\"background:#0F1218;color:#fff\"><th>Логин</th><th>ФИО</th><th>Должность</th><th>Филиал</th><th>Регион</th><th>Город</th></tr>";for(var k in all){var u=all[k];h+="<tr><td>"+k+(k==="admin"?" ⭐":"")+"</td><td>"+u.name+"</td><td>"+u.role+"</td><td>"+(u.branch||"—")+"</td><td>"+(u.region||"—")+"</td><td>"+(u.city||"—")+"</td></tr>"}h+="</table>";var w=window.open("","_blank","width=800,height=500");w.document.write("<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>Пользователи</title><style>body{font:14px/1.5 Arial;max-width:800px;margin:20px auto;padding:20px}</style></head><body>"+h+"</body></html>");w.document.close()}
|
||||
function downloadSummaryHTML(){var a=getA(),all=allU(),t=a.length;var w=window.open("","_blank","width=800,height=600");w.document.write("<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>Отчёт ПАБ</title><style>body{font:14px/1.5 Arial;max-width:900px;margin:20px auto;padding:20px}h1{font-size:22px}h2{font-size:16px;margin-top:20px}table{width:100%;border-collapse:collapse;font-size:12px}th{background:#0F1218;color:#fff;padding:8px}td{padding:6px 8px;border-bottom:1px solid #E2E6EB}@media print{button{display:none}}</style></head><body><button onclick=\"window.print()\" style=\"padding:8px 16px;margin-bottom:16px\">🖨️ Печать</button><h1>📊 Сводный отчёт ПАБ</h1><p>Сформирован: "+new Date().toLocaleString("ru")+" | Всего аудитов: "+t+"</p><h2>📋 Аудиты</h2><table><tr><th>№</th><th>Дата</th><th>Место</th><th>Наблюдатель</th><th>Статус</th><th>Нарушений</th></tr>"+a.map(function(x){return"<tr><td>"+(x.number||"—")+"</td><td>"+x.date+"</td><td>"+x.location+"</td><td>"+x.observer+"</td><td>"+(x.overallSafe?"Безопасно":"Нарушения")+"</td><td>"+(x.totalViolations||0)+"</td></tr>"}).join("")+"</table></body></html>");w.document.close()}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user