сбор результатов оценки через FormSubmit (анонимно, с согласием)
This commit is contained in:
parent
d13dd11880
commit
d5de36fc94
113
index.html
113
index.html
@ -200,6 +200,28 @@ footer a{color:var(--cyan);text-decoration:none;font-weight:600}
|
|||||||
.res-base ul li::before{content:"✓";position:absolute;left:0;top:0;color:#0B7C8C;font-weight:800}
|
.res-base ul li::before{content:"✓";position:absolute;left:0;top:0;color:#0B7C8C;font-weight:800}
|
||||||
.lag-hint{display:none;margin-top:14px;font-size:13px;font-weight:700;color:#B23A18;background:#FFEDE7;border-radius:8px;padding:8px 12px;text-align:center}
|
.lag-hint{display:none;margin-top:14px;font-size:13px;font-weight:700;color:#B23A18;background:#FFEDE7;border-radius:8px;padding:8px 12px;text-align:center}
|
||||||
.lag-hint.show{display:block}
|
.lag-hint.show{display:block}
|
||||||
|
|
||||||
|
/* ---------- Collect panel ---------- */
|
||||||
|
.tool-collect{border-top:1px solid var(--gray-100);padding:26px 28px 30px;background:#fff}
|
||||||
|
.collect-head{display:flex;gap:16px;margin-bottom:18px}
|
||||||
|
.collect-head .ch-ic{width:46px;height:46px;border-radius:12px;background:var(--cyan-50);display:grid;place-items:center;font-size:24px;flex:none}
|
||||||
|
.collect-head h3{font-size:18px;font-weight:700;margin-bottom:4px}
|
||||||
|
.collect-head p{font-size:14px;color:var(--gray-500);max-width:640px}
|
||||||
|
.collect-form{display:grid;gap:14px;max-width:560px}
|
||||||
|
.cfield{display:grid;gap:6px;font-size:14px;font-weight:600}
|
||||||
|
.cfield small{font-weight:400;color:var(--gray-500)}
|
||||||
|
.cfield input{padding:11px 13px;border:1.5px solid var(--gray-200);border-radius:9px;font-size:15px;font-family:inherit}
|
||||||
|
.cfield input:focus{outline:none;border-color:var(--cyan)}
|
||||||
|
.cconsent{display:flex;gap:10px;align-items:flex-start;font-size:14px;color:var(--gray-500);cursor:pointer}
|
||||||
|
.cconsent input{margin-top:2px;width:18px;height:18px;flex:none;cursor:pointer}
|
||||||
|
.collect-actions{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
|
||||||
|
.collect-actions .btn{cursor:pointer;border:none;font-family:inherit;font-size:15px}
|
||||||
|
.cmsg{font-size:14px;font-weight:600;color:var(--gray-500);min-height:18px}
|
||||||
|
.cmsg.ok{color:var(--phys)}
|
||||||
|
.cmsg.err{color:#D4441E}
|
||||||
|
.collect-priv{font-size:12.5px;color:var(--gray-500);margin-top:2px;line-height:1.5}
|
||||||
|
.collect-off{background:var(--gray-100);border-radius:12px;padding:16px 18px;font-size:14.5px;color:var(--gray-500);line-height:1.5}
|
||||||
|
.collect-off b{color:var(--ink)}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -296,6 +318,31 @@ footer a{color:var(--cyan);text-decoration:none;font-weight:600}
|
|||||||
<div class="milestones" id="milestones"></div>
|
<div class="milestones" id="milestones"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tool-results" id="toolResults"></div>
|
<div class="tool-results" id="toolResults"></div>
|
||||||
|
<div class="tool-collect" id="toolCollect">
|
||||||
|
<div class="collect-head">
|
||||||
|
<div class="ch-ic">📨</div>
|
||||||
|
<div>
|
||||||
|
<h3>Отправить результат для аналитики</h3>
|
||||||
|
<p>Помогите улучшить гид — отправьте обезличенный результат оценки. Мы не собираем имена и контакты детей, только возраст и отметки навыков.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="collect-form" id="collectForm">
|
||||||
|
<label class="cfield">
|
||||||
|
<span>Ваш email <small>(необязательно — если хотите получить копию результата)</small></span>
|
||||||
|
<input type="email" id="cEmail" placeholder="you@example.com">
|
||||||
|
</label>
|
||||||
|
<label class="cconsent">
|
||||||
|
<input type="checkbox" id="cConsent">
|
||||||
|
<span>Я согласен(на) на анонимную обработку данных оценки развития ребёнка в образовательных и исследовательских целях.</span>
|
||||||
|
</label>
|
||||||
|
<div class="collect-actions">
|
||||||
|
<button class="btn" id="cSubmit" type="button">Отправить результат</button>
|
||||||
|
<span class="cmsg" id="cMsg"></span>
|
||||||
|
</div>
|
||||||
|
<div class="collect-priv">Данные уходят через сервис FormSubmit. Первая отправка активируется по ссылке в письме владельцу сайта. Анализировать потом удобно в Google Таблицах: FormSubmit → экспорт в CSV.</div>
|
||||||
|
</div>
|
||||||
|
<div class="collect-off" id="collectOff"><b>Сбор данных скоро будет подключён.</b> Владельцу сайта нужно указать email для получения результатов — после этого форма станет активной.</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@ -758,6 +805,72 @@ function render(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
render();
|
render();
|
||||||
|
|
||||||
|
/* ====== Сбор результатов через FormSubmit (без регистрации) ====== */
|
||||||
|
const COLLECT_EMAIL = ""; // ← email владельца сайта для получения результатов, напр. "tsai.e@amu.kz"
|
||||||
|
const collectForm = document.getElementById('collectForm');
|
||||||
|
const collectOff = document.getElementById('collectOff');
|
||||||
|
const cEmail = document.getElementById('cEmail');
|
||||||
|
const cConsent = document.getElementById('cConsent');
|
||||||
|
const cSubmit = document.getElementById('cSubmit');
|
||||||
|
const cMsg = document.getElementById('cMsg');
|
||||||
|
|
||||||
|
if(COLLECT_EMAIL){
|
||||||
|
collectForm.style.display = 'grid';
|
||||||
|
collectOff.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
collectForm.style.display = 'none';
|
||||||
|
collectOff.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildPayload(){
|
||||||
|
const block = DATA[currentAge];
|
||||||
|
const res = {'Возраст': currentAge};
|
||||||
|
let total=0, done=0;
|
||||||
|
Object.keys(SPHERES).forEach(key=>{
|
||||||
|
const items = block[key]||[];
|
||||||
|
let d=0; const got=[], miss=[];
|
||||||
|
items.forEach((it,i)=>{
|
||||||
|
const id=currentAge+'|'+key+'|'+i;
|
||||||
|
if(checked[id]){d++; got.push(it[0]);} else {miss.push(it[0]);}
|
||||||
|
});
|
||||||
|
total+=items.length; done+=d;
|
||||||
|
const p = items.length?Math.round(d/items.length*100):0;
|
||||||
|
const st = p>=70?'Хорошо':(p>=40?'Осваивается':'Отстаёт');
|
||||||
|
res['Сфера: '+SPHERES[key].name] = d+' / '+items.length+' ('+st+', '+p+'%)';
|
||||||
|
res[SPHERES[key].name+' — освоено'] = got.join('; ')||'—';
|
||||||
|
res[SPHERES[key].name+' — не освоено'] = miss.join('; ')||'—';
|
||||||
|
});
|
||||||
|
const pct = total?Math.round(done/total*100):0;
|
||||||
|
const overall = pct>=70?'Развитие идёт хорошо':(pct>=40?'Некоторые навыки осваиваются':'Есть сферы, требующие внимания');
|
||||||
|
res['Общий статус'] = overall+' ('+done+'/'+total+', '+pct+'%)';
|
||||||
|
res['Дата отправки'] = new Date().toLocaleString('ru-RU');
|
||||||
|
if(cEmail.value.trim()){ res['Email родителя (необязательно)'] = cEmail.value.trim(); }
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
cSubmit.onclick = async () => {
|
||||||
|
if(!COLLECT_EMAIL){ cMsg.textContent='Сбор данных ещё не подключён.'; cMsg.className='cmsg err'; return; }
|
||||||
|
let done=0; Object.keys(checked).forEach(k=>{ if(k.startsWith(currentAge+'|')&&checked[k]) done++; });
|
||||||
|
if(done===0){ cMsg.textContent='Сначала отметьте хотя бы один навык выше.'; cMsg.className='cmsg err'; return; }
|
||||||
|
if(!cConsent.checked){ cMsg.textContent='Подтвердите согласие на обработку данных.'; cMsg.className='cmsg err'; return; }
|
||||||
|
const payload = buildPayload();
|
||||||
|
payload._subject = 'Оценка развития ребёнка — '+currentAge;
|
||||||
|
payload._template = 'table';
|
||||||
|
payload._captcha = 'false';
|
||||||
|
cSubmit.disabled = true;
|
||||||
|
cMsg.textContent='Отправляем…'; cMsg.className='cmsg';
|
||||||
|
try{
|
||||||
|
const r = await fetch('https://formsubmit.co/ajax/'+encodeURIComponent(COLLECT_EMAIL), {
|
||||||
|
method:'POST',
|
||||||
|
headers:{'Content-Type':'application/json','Accept':'application/json'},
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
});
|
||||||
|
if(r.ok){ cMsg.textContent='✓ Спасибо! Результат отправлен.'; cMsg.className='cmsg ok'; cConsent.checked=false; }
|
||||||
|
else { cMsg.textContent='Не удалось отправить. Попробуйте позже.'; cMsg.className='cmsg err'; }
|
||||||
|
}catch(e){ cMsg.textContent='Нет связи с сервером. Проверьте интернет.'; cMsg.className='cmsg err'; }
|
||||||
|
cSubmit.disabled = false;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user