Spaces:
Sleeping
Sleeping
fix(ui): consent modal was trapped under the samples modal
Browse files- згода піднята над модалками (z-index 70)
- для вбудованого зразка згоди не питаємо (наш синтетичний файл)
- + «Зберегти бланк на пристрій»
livemedcard/static/index.html
CHANGED
|
@@ -354,11 +354,15 @@
|
|
| 354 |
.sphoto{border:1px dashed var(--line);border-radius:10px;padding:12px 14px;margin-top:14px}
|
| 355 |
.sphoto img{width:100%;max-width:420px;border-radius:8px;border:1px solid var(--line);display:block;margin:9px 0}
|
| 356 |
.sfoot{display:flex;gap:9px;justify-content:flex-end;padding:12px 18px;border-top:1px solid var(--line)}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 357 |
|
| 358 |
/* ── cloud consent (photo leaves the device — say so before it does) ── */
|
| 359 |
.consent{position:fixed;left:50%;top:50%;transform:translate(-50%,-46%) scale(.98);
|
| 360 |
width:min(470px,92vw);background:var(--panel);border:1px solid var(--line);border-radius:14px;
|
| 361 |
-
padding:22px 24px 18px;z-index:
|
| 362 |
box-shadow:0 24px 60px rgba(4,9,13,.28);transition:opacity .16s,transform .16s}
|
| 363 |
.consent.show{opacity:1;pointer-events:auto;transform:translate(-50%,-50%) scale(1)}
|
| 364 |
.consent h3{margin:0 0 10px;font-size:15.5px;color:var(--critical)}
|
|
@@ -525,7 +529,10 @@
|
|
| 525 |
<div class="sk" id="samples-photo-head"></div>
|
| 526 |
<p class="st" id="samples-photo-cap" style="margin:6px 0 0"></p>
|
| 527 |
<img id="samples-photo" alt="">
|
| 528 |
-
<
|
|
|
|
|
|
|
|
|
|
| 529 |
</div>
|
| 530 |
</div>
|
| 531 |
<div class="sfoot">
|
|
@@ -543,7 +550,7 @@
|
|
| 543 |
<div class="body" id="help-body"></div>
|
| 544 |
</aside>
|
| 545 |
|
| 546 |
-
<div class="drawer-back" id="consent-back"></div>
|
| 547 |
<div class="consent" id="consent" role="dialog" aria-modal="true" aria-labelledby="consent-title">
|
| 548 |
<h3 id="consent-title"></h3>
|
| 549 |
<p id="consent-body"></p>
|
|
@@ -624,8 +631,8 @@ const I18N = {
|
|
| 624 |
samplesHint:'Note the two dangerous medications sit in <b>different</b> documents, two visits apart. That combination is what the deterministic layer catches.',
|
| 625 |
samplesLoad:'Load into the card', samplesCancel:'Cancel',
|
| 626 |
samplesPhotoHead:'Or a photo of a lab form',
|
| 627 |
-
samplesPhotoCap:'Same comparison, harder path: this synthetic form is read by a real OCR model, not by a script with the answers.',
|
| 628 |
-
samplesPhotoBtn:'Read this photo (OCR)',
|
| 629 |
toastExport:'FHIR bundle downloaded', toastNeedInput:'Enter text or choose a photo',
|
| 630 |
ocrReading:'Reading (OCR)…', processing:'Processing…',
|
| 631 |
toastOcrWait:'Reading the photo on the cloud OCR lab — up to ~90 s',
|
|
@@ -728,8 +735,8 @@ const I18N = {
|
|
| 728 |
samplesHint:'Зверніть увагу: два небезпечні препарати лежать у <b>різних</b> документах, між ними — рік. Саме таку комбінацію й ловить детермінований шар.',
|
| 729 |
samplesLoad:'Завантажити в картку', samplesCancel:'Скасувати',
|
| 730 |
samplesPhotoHead:'Або фото лабораторного бланка',
|
| 731 |
-
samplesPhotoCap:'Те саме порівняння, складніший шлях: цей синтетичний бланк читає справжня OCR-модель, а не скрипт із готовими відповідями.',
|
| 732 |
-
samplesPhotoBtn:'Прочитати це фото (OCR)',
|
| 733 |
toastExport:'FHIR Bundle завантажено', toastNeedInput:'Введіть текст або виберіть фото',
|
| 734 |
ocrReading:'Зчитування (OCR)…', processing:'Опрацювання…',
|
| 735 |
toastOcrWait:'Фото читає хмарний OCR-лаб — до ~90 с',
|
|
@@ -1220,6 +1227,7 @@ async function openSamples(){
|
|
| 1220 |
$('#samples-photo-head').textContent=t.samplesPhotoHead;
|
| 1221 |
$('#samples-photo-cap').textContent=t.samplesPhotoCap;
|
| 1222 |
$('#samples-photo-btn').textContent=t.samplesPhotoBtn;
|
|
|
|
| 1223 |
$('#samples-photo').src='/samples/image';
|
| 1224 |
try{
|
| 1225 |
const d=await api('/samples?lang='+(LANG==='ua'?'uk':'en'));
|
|
@@ -1246,10 +1254,12 @@ $('#samples-load').onclick=async()=>{
|
|
| 1246 |
finally{b.disabled=false;b.textContent=orig;}
|
| 1247 |
};
|
| 1248 |
|
| 1249 |
-
/
|
|
|
|
|
|
|
|
|
|
| 1250 |
$('#samples-photo-btn').onclick=async()=>{
|
| 1251 |
const t=I18N[LANG], b=$('#samples-photo-btn'), orig=b.textContent;
|
| 1252 |
-
if(!await askCloudConsent()) return;
|
| 1253 |
b.disabled=true; b.textContent=t.ocrReading; toast(t.toastOcrWait);
|
| 1254 |
try{
|
| 1255 |
const blob=await (await fetch('/samples/image')).blob();
|
|
|
|
| 354 |
.sphoto{border:1px dashed var(--line);border-radius:10px;padding:12px 14px;margin-top:14px}
|
| 355 |
.sphoto img{width:100%;max-width:420px;border-radius:8px;border:1px solid var(--line);display:block;margin:9px 0}
|
| 356 |
.sfoot{display:flex;gap:9px;justify-content:flex-end;padding:12px 18px;border-top:1px solid var(--line)}
|
| 357 |
+
a#samples-photo-dl{display:inline-flex;align-items:center;text-decoration:none;cursor:pointer;
|
| 358 |
+
font:inherit;font-weight:550;border:1px solid var(--line);border-radius:10px;padding:9px 15px;
|
| 359 |
+
background:transparent;color:var(--ink);transition:.14s}
|
| 360 |
+
a#samples-photo-dl:hover{border-color:var(--accent);color:var(--accent)}
|
| 361 |
|
| 362 |
/* ── cloud consent (photo leaves the device — say so before it does) ── */
|
| 363 |
.consent{position:fixed;left:50%;top:50%;transform:translate(-50%,-46%) scale(.98);
|
| 364 |
width:min(470px,92vw);background:var(--panel);border:1px solid var(--line);border-radius:14px;
|
| 365 |
+
padding:22px 24px 18px;z-index:70;opacity:0;pointer-events:none;
|
| 366 |
box-shadow:0 24px 60px rgba(4,9,13,.28);transition:opacity .16s,transform .16s}
|
| 367 |
.consent.show{opacity:1;pointer-events:auto;transform:translate(-50%,-50%) scale(1)}
|
| 368 |
.consent h3{margin:0 0 10px;font-size:15.5px;color:var(--critical)}
|
|
|
|
| 529 |
<div class="sk" id="samples-photo-head"></div>
|
| 530 |
<p class="st" id="samples-photo-cap" style="margin:6px 0 0"></p>
|
| 531 |
<img id="samples-photo" alt="">
|
| 532 |
+
<div style="display:flex;gap:9px;flex-wrap:wrap">
|
| 533 |
+
<button class="ghost" id="samples-photo-btn"></button>
|
| 534 |
+
<a class="ghost" id="samples-photo-dl" href="/samples/image" download="livemedcard_sample_lab_report.jpg"></a>
|
| 535 |
+
</div>
|
| 536 |
</div>
|
| 537 |
</div>
|
| 538 |
<div class="sfoot">
|
|
|
|
| 550 |
<div class="body" id="help-body"></div>
|
| 551 |
</aside>
|
| 552 |
|
| 553 |
+
<div class="drawer-back" id="consent-back" style="z-index:69"></div>
|
| 554 |
<div class="consent" id="consent" role="dialog" aria-modal="true" aria-labelledby="consent-title">
|
| 555 |
<h3 id="consent-title"></h3>
|
| 556 |
<p id="consent-body"></p>
|
|
|
|
| 631 |
samplesHint:'Note the two dangerous medications sit in <b>different</b> documents, two visits apart. That combination is what the deterministic layer catches.',
|
| 632 |
samplesLoad:'Load into the card', samplesCancel:'Cancel',
|
| 633 |
samplesPhotoHead:'Or a photo of a lab form',
|
| 634 |
+
samplesPhotoCap:'Same comparison, harder path: this synthetic form is read by a real OCR model, not by a script with the answers. It is our own synthetic file — nothing of yours leaves your device — so we do not ask for consent here. The cloud OCR lab takes up to ~90 s.',
|
| 635 |
+
samplesPhotoBtn:'Read this photo (OCR)', samplesPhotoDl:'Save the form to my device',
|
| 636 |
toastExport:'FHIR bundle downloaded', toastNeedInput:'Enter text or choose a photo',
|
| 637 |
ocrReading:'Reading (OCR)…', processing:'Processing…',
|
| 638 |
toastOcrWait:'Reading the photo on the cloud OCR lab — up to ~90 s',
|
|
|
|
| 735 |
samplesHint:'Зверніть увагу: два небезпечні препарати лежать у <b>різних</b> документах, між ними — рік. Саме таку комбінацію й ловить детермінований шар.',
|
| 736 |
samplesLoad:'Завантажити в картку', samplesCancel:'Скасувати',
|
| 737 |
samplesPhotoHead:'Або фото лабораторного бланка',
|
| 738 |
+
samplesPhotoCap:'Те саме порівняння, складніший шлях: цей синтетичний бланк читає справжня OCR-модель, а не скрипт із готовими відповідями. Це наш власний синтетичний файл — ваш пристрій нічого не покидає, — тож згоди тут не питаємо. Хмарний OCR-лаб читає його до ~90 с.',
|
| 739 |
+
samplesPhotoBtn:'Прочитати це фото (OCR)', samplesPhotoDl:'Зберегти бланк на пристрій',
|
| 740 |
toastExport:'FHIR Bundle завантажено', toastNeedInput:'Введіть текст або виберіть фото',
|
| 741 |
ocrReading:'Зчитування (OCR)…', processing:'Опрацювання…',
|
| 742 |
toastOcrWait:'Фото читає хмарний OCR-лаб — до ~90 с',
|
|
|
|
| 1227 |
$('#samples-photo-head').textContent=t.samplesPhotoHead;
|
| 1228 |
$('#samples-photo-cap').textContent=t.samplesPhotoCap;
|
| 1229 |
$('#samples-photo-btn').textContent=t.samplesPhotoBtn;
|
| 1230 |
+
$('#samples-photo-dl').textContent=t.samplesPhotoDl;
|
| 1231 |
$('#samples-photo').src='/samples/image';
|
| 1232 |
try{
|
| 1233 |
const d=await api('/samples?lang='+(LANG==='ua'?'uk':'en'));
|
|
|
|
| 1254 |
finally{b.disabled=false;b.textContent=orig;}
|
| 1255 |
};
|
| 1256 |
|
| 1257 |
+
/* Той самий бланк, що в кліпі: журі бачить його очима, потім віддає справжньому OCR.
|
| 1258 |
+
Згоди НЕ питаємо: це наш власний синтетичний файл, пристрій користувача нічого не
|
| 1259 |
+
покидає. Згода існує, щоб захистити ЙОГО дані, — а тут захищати нічого. Але про
|
| 1260 |
+
хмару й ~90 с усе одно кажемо в підписі: мовчати про це було б обманом. */
|
| 1261 |
$('#samples-photo-btn').onclick=async()=>{
|
| 1262 |
const t=I18N[LANG], b=$('#samples-photo-btn'), orig=b.textContent;
|
|
|
|
| 1263 |
b.disabled=true; b.textContent=t.ocrReading; toast(t.toastOcrWait);
|
| 1264 |
try{
|
| 1265 |
const blob=await (await fetch('/samples/image')).blob();
|