DocUA commited on
Commit
a4b216f
·
1 Parent(s): fc7f010

fix(ui): consent modal was trapped under the samples modal

Browse files

- згода піднята над модалками (z-index 70)
- для вбудованого зразка згоди не питаємо (наш синтетичний файл)
- + «Зберегти бланк на пристрій»

Files changed (1) hide show
  1. livemedcard/static/index.html +19 -9
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:60;opacity:0;pointer-events:none;
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
- <button class="ghost" id="samples-photo-btn"></button>
 
 
 
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
- // Той самий бланк, що в кліпі: журі бачить його очима, потім віддає справжньому OCR.
 
 
 
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();