feat(5.13): carduri compacte mobil/tableta + fix editare preview (OOB tr) + toast
Dogfood pe import + Trimiteri (mobil/tableta <1024px), pur CSS + markup, backend
trimitere neatins:
- Card compact real pentru .tabel-trimiteri (preview + Trimiteri): vehicul=titlu,
stare=pill dreapta-sus, operatie+cod, meta data/km muted, nota mica. Inlocuieste
stiva generica eticheta+valoare (carduri de ~450px -> ~135px). Anuleaza regula
desktop tr.trimitere-row > td{padding:11px} in blocul compact.
- FIX editare preview: OOB swap pe <tr> esua tacit in htmx 1.9 (un <tr> brut se
pierde la parsarea unui fragment fara context de tabel) -> randul ramanea cu
starea veche dupa salvare. Inlocuit cu reload complet al preview-ului prin
HX-Trigger:reincarcaPreview + detalii randSalvat. /editeaza si /confirma-review
folosesc helper-ul _raspuns_rand_salvat.
- Feedback post-salvare: toast global "Randul N actualizat · <stare>" + scroll +
flash pe randul actualizat (base.html window.arataToast + listener randSalvat).
- Modal editare: Salveaza + Anuleaza pe acelasi rand (sistem .act): desktop text,
mobil doua iconite Lucide 44px alaturate (save/x). Macro icon('x') + .act-primary.
- Randuri deja-trimise/duplicate colapsate implicit in preview + toggle "Arata N".
- Select "Operatii de mapat" full-width pe mobil (nu mai iese din viewport).
- Bara de filtre Trimiteri adaptata mobil: pills pe banda cu scroll orizontal,
cautare vehicul proeminenta (nu 8 butoane full-width stivuite).
- Nota preview = culoarea camp-fix (accent) ca sa atraga atentia; hint-urile
camp-fix per-camp scoase (campul Note e self-explanatory).
- Confirmare trimitere: scos campul email (Declarant); text mai clar
("Confirma numarul din N gata de trimis"). Backend confirmed_by ramane optional.
Teste: contractul OOB (rupt in browser) inlocuit cu noul contract
(reincarcaPreview + randSalvat) in test_web_preview_edit / test_preview_edit_ui /
test_import_review. Suita: 992 passed (exclus live).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -177,7 +177,7 @@
|
||||
.banner.warn { border-left-color:var(--warn); background:color-mix(in srgb, var(--warn) 12%, var(--card)); }
|
||||
/* Bara confirmare sticky */
|
||||
.sticky-bar { position:sticky; bottom:0; background:var(--card); border-top:1px solid var(--line);
|
||||
padding:12px 16px; display:flex; align-items:flex-start; gap:16px;
|
||||
padding:10px 14px; display:flex; align-items:flex-start; gap:12px;
|
||||
flex-wrap:wrap; z-index:10; }
|
||||
/* Indicator HTMX — ascuns pana la request */
|
||||
.htmx-indicator { display:none; }
|
||||
@@ -199,6 +199,83 @@
|
||||
select { max-width:340px; }
|
||||
button { background:var(--accent); border-color:var(--accent); color:#fff; cursor:pointer; }
|
||||
button:hover { filter:brightness(1.08); }
|
||||
/* Sistem butoane unificat (design.md §5.1). Primarul = `button`/`.btn` (deja stilat). */
|
||||
.btn-secondary { background:transparent; color:var(--ink); border:1px solid var(--line); border-radius:6px;
|
||||
padding:8px 14px; font:inherit; font-weight:500; cursor:pointer; min-height:36px;
|
||||
display:inline-flex; align-items:center; justify-content:center; gap:6px; }
|
||||
.btn-secondary:hover { background:var(--line); filter:none; }
|
||||
.btn-ghost { background:transparent; color:var(--accent); border:1px solid transparent; border-radius:6px;
|
||||
padding:8px 14px; font:inherit; font-weight:500; cursor:pointer; min-height:36px;
|
||||
display:inline-flex; align-items:center; justify-content:center; gap:6px; }
|
||||
.btn-ghost:hover { background:var(--line); filter:none; }
|
||||
.btn-danger { background:transparent; color:var(--err); border:1px solid var(--err); border-radius:6px;
|
||||
padding:8px 14px; font:inherit; font-weight:500; cursor:pointer; min-height:36px;
|
||||
display:inline-flex; align-items:center; justify-content:center; gap:6px; }
|
||||
.btn-danger:hover, .btn-danger:focus-visible { background:var(--err); color:#fff; filter:none; }
|
||||
.btn-sm { padding:5px 10px; min-height:32px; font-size:13px; }
|
||||
button:focus-visible, .btn-secondary:focus-visible, .btn-ghost:focus-visible, .btn-danger:focus-visible {
|
||||
outline:2px solid var(--accent); outline-offset:2px; }
|
||||
/* Actiuni de rand (design.md §5.1): desktop = text, mobil = iconita patrata 44px.
|
||||
act_btn randeaza si .act-tx (text) si .act-ic (svg); CSS ascunde unul per breakpoint. */
|
||||
.act { display:inline-flex; align-items:center; justify-content:center; gap:6px; font:inherit; font-weight:500;
|
||||
border-radius:7px; padding:6px 12px; min-height:36px; cursor:pointer; background:transparent;
|
||||
border:1px solid var(--line); color:var(--ink); }
|
||||
.act:hover { background:var(--line); filter:none; }
|
||||
.act:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
|
||||
.act .act-ic { width:18px; height:18px; display:none; }
|
||||
.act .act-tx { display:inline; }
|
||||
.act-save.dirty { background:var(--accent); color:#fff; border-color:var(--accent); }
|
||||
.act-save.dirty:hover { filter:brightness(.92); }
|
||||
/* Variant primar mereu-accent (ex. Salveaza in modalul de editare). */
|
||||
.act-primary { background:var(--accent); color:#fff; border-color:var(--accent); }
|
||||
.act-primary:hover { filter:brightness(.92); background:var(--accent); }
|
||||
.act-del { color:var(--err); border-color:var(--err); }
|
||||
.act-del:hover, .act-del:focus-visible { background:var(--err); color:#fff; }
|
||||
.act-group { display:inline-flex; gap:8px; align-items:center; }
|
||||
.btn-editeaza { white-space:nowrap; }
|
||||
/* Toast global (feedback tranzitoriu post-actiune). */
|
||||
#toast { position:fixed; left:50%; bottom:24px; transform:translateX(-50%) translateY(8px);
|
||||
z-index:1300; max-width:90vw; padding:11px 18px; border-radius:10px;
|
||||
background:var(--ink); color:var(--card); font-size:14px; font-weight:500;
|
||||
box-shadow:0 8px 28px rgba(0,0,0,.28); display:flex; align-items:center; gap:9px;
|
||||
opacity:0; pointer-events:none; transition:opacity .2s, transform .2s; }
|
||||
#toast[hidden] { display:none; }
|
||||
#toast.show { opacity:1; transform:translateX(-50%) translateY(0); }
|
||||
#toast::before { content:""; width:9px; height:9px; border-radius:50%; background:var(--ok); flex:0 0 auto; }
|
||||
#toast.t-err::before, #toast.t-s-error::before, #toast.t-s-needs_data::before,
|
||||
#toast.t-s-needs_mapping::before { background:var(--err); }
|
||||
#toast.t-warn::before, #toast.t-s-needs_review::before { background:var(--warn); }
|
||||
/* Rand de preview tocmai actualizat: flash scurt ca userul sa-l localizeze. */
|
||||
@keyframes rand-flash { 0% { background:color-mix(in srgb, var(--accent) 26%, var(--card)); }
|
||||
100% { background:transparent; } }
|
||||
.tabel-trimiteri tr.rand-actualizat { animation:rand-flash 1.6s ease-out; }
|
||||
/* Randuri deja-trimise / duplicate in preview: colapsate implicit (nu ocupa loc).
|
||||
Reafisate cand userul apasa toggle-ul -> .preview-arata-trimise pe container.
|
||||
!important fiindca regulile compacte mobil/tableta seteaza `tr{display:flex}`. */
|
||||
.tabel-trimiteri tr.preview-sent-row { display:none !important; }
|
||||
.tabel-trimiteri.preview-arata-trimise tr.preview-sent-row { display:table-row !important; }
|
||||
/* Stepper import compact (design.md §5.4). >=1024px: bara slim. <1024px: "Pasul N din 4" + progres. */
|
||||
.stepper { margin-bottom:16px; }
|
||||
.stepper-track { display:flex; align-items:stretch; border:1px solid var(--line); border-radius:8px;
|
||||
overflow:hidden; background:var(--card); }
|
||||
.stepper-step { flex:1; display:flex; align-items:center; gap:8px; padding:10px 14px; min-height:44px;
|
||||
border-right:1px solid var(--line); }
|
||||
.stepper-step:last-child { border-right:none; }
|
||||
.stepper-nr { display:inline-flex; align-items:center; justify-content:center; width:20px; height:20px;
|
||||
border-radius:50%; font-size:11px; font-weight:700; flex-shrink:0;
|
||||
background:var(--line); color:var(--muted); }
|
||||
.stepper-tx { font-size:13px; color:var(--muted); white-space:nowrap; }
|
||||
.stepper-step.is-active { background:color-mix(in srgb, var(--accent) 10%, transparent); }
|
||||
.stepper-step.is-active .stepper-nr { background:var(--accent); color:#fff; }
|
||||
.stepper-step.is-active .stepper-tx { color:var(--ink); font-weight:600; }
|
||||
.stepper-step.is-done .stepper-nr { background:var(--ok); color:#fff; }
|
||||
.stepper-step.is-done .stepper-tx { color:var(--ink); }
|
||||
.stepper-help { margin:6px 2px 0; font-size:12px; color:var(--muted); }
|
||||
.stepper-collapsed { display:none; }
|
||||
.stepper-current { font-size:14px; font-weight:600; margin-bottom:6px; }
|
||||
.stepper-current .muted { font-weight:400; }
|
||||
.stepper-progress { height:5px; border-radius:99px; background:var(--line); overflow:hidden; }
|
||||
.stepper-progress > span { display:block; height:100%; background:var(--accent); border-radius:99px; }
|
||||
.chk { font-size:13px; color:var(--muted); display:flex; align-items:center; gap:6px; }
|
||||
/* Tab-bar */
|
||||
.tab-bar { display:flex; gap:2px; overflow-x:auto; -webkit-overflow-scrolling:touch;
|
||||
@@ -341,9 +418,12 @@
|
||||
.tabel-trimiteri tr.trimitere-row:hover { background:color-mix(in srgb, var(--accent) 6%, transparent); }
|
||||
.tabel-trimiteri tr.trimitere-row:focus,
|
||||
.tabel-trimiteri tr.trimitere-row:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
|
||||
/* 768-1024px: ascunde Actualizat (e in detaliu) -> 7 coloane, fara scroll */
|
||||
/* col-actualizat ca linie meta mica in carduri (decizie 5.13 #8). */
|
||||
.tabel-trimiteri td.col-actualizat { font-size:12px; }
|
||||
/* Stepper: sub 1024px ascunde track-ul slim, arata forma colapsata (decizie 5.13 #11). */
|
||||
@media (max-width:1024px) {
|
||||
.tabel-trimiteri .col-actualizat { display:none; }
|
||||
.stepper-track { display:none; }
|
||||
.stepper-collapsed { display:block; }
|
||||
}
|
||||
/* Tableta (768–1024px): header compact fara suprapuneri.
|
||||
Grila 3-coloane se pastreaza; logo si titlu mai mici; versiunea ascunsa
|
||||
@@ -358,6 +438,43 @@
|
||||
ascunsa pentru a elibera spatiu in celula dreapta. */
|
||||
.header-right > .muted { display:none; }
|
||||
}
|
||||
/* Tableta 768-1024px: listele actionabile raman O COLOANA, cardificate (nu tabel storcit,
|
||||
nu 2/rand). Decizie 5.13 (premisa user). Tabelele dense read-only raman .tablewrap. */
|
||||
@media (min-width:768px) and (max-width:1024px) {
|
||||
.tabel-trimiteri table, .tabel-card table { table-layout:auto; }
|
||||
.tabel-trimiteri thead, .tabel-card thead { display:none; }
|
||||
.tabel-trimiteri table, .tabel-trimiteri tbody, .tabel-trimiteri tr, .tabel-trimiteri td,
|
||||
.tabel-card table, .tabel-card tbody, .tabel-card tr, .tabel-card td { display:block; width:auto; }
|
||||
.tabel-trimiteri tr, .tabel-card tr { border:1px solid var(--line); border-radius:8px;
|
||||
padding:10px 12px; margin-bottom:10px; }
|
||||
.tabel-trimiteri td, .tabel-card td { border-bottom:none; padding:3px 0; }
|
||||
.tabel-trimiteri td::before, .tabel-card td::before { content:attr(data-eticheta); display:block;
|
||||
color:var(--muted); font-size:12px; margin-bottom:2px; }
|
||||
.tabel-trimiteri td.col-chk, .tabel-trimiteri td.col-id { display:none; }
|
||||
.tabel-trimiteri td[data-eticheta=""]::before, .tabel-card td[data-eticheta=""]::before,
|
||||
.tabel-card td:not([data-eticheta])::before { display:none; }
|
||||
.tabel-card td select, .tabel-card td input[type=text], .tabel-card td input[type=search] {
|
||||
width:100%; max-width:none; }
|
||||
/* Card compact si pe tableta (acelasi layout ca pe mobil) pentru `.tabel-trimiteri`. */
|
||||
.tabel-trimiteri tr { display:flex; flex-wrap:wrap; align-items:baseline; gap:1px 8px; }
|
||||
.tabel-trimiteri td { padding:0; }
|
||||
/* Regula desktop `tr.trimitere-row > td { padding:11px }` e mai specifica -> o anulam
|
||||
in cardul compact, altfel randurile de Trimiteri raman inalte/aerisite. */
|
||||
.tabel-trimiteri tr.trimitere-row > td { padding-top:0; padding-bottom:0; }
|
||||
.tabel-trimiteri td::before { display:none; }
|
||||
.tabel-trimiteri td.col-vehicul { order:1; flex:1 1 55%; min-width:0; font-weight:600; font-size:15px; line-height:1.25; }
|
||||
.tabel-trimiteri td.col-vehicul .muted { font-weight:400; }
|
||||
.tabel-trimiteri td.col-stare { order:2; flex:0 0 auto; margin-left:auto; align-self:flex-start; }
|
||||
.tabel-trimiteri td.col-operatie { order:3; flex:1 1 100%; font-size:13px; line-height:1.3; margin-top:1px; }
|
||||
.tabel-trimiteri td.col-data, .tabel-trimiteri td.col-km, .tabel-trimiteri td.col-rar { font-size:12px; color:var(--muted); }
|
||||
.tabel-trimiteri td.col-data { order:4; } .tabel-trimiteri td.col-km { order:5; } .tabel-trimiteri td.col-rar { order:6; }
|
||||
.tabel-trimiteri td.col-km::before { content:"· "; display:inline; color:var(--muted); }
|
||||
.tabel-trimiteri td.col-actualizat { order:7; flex:1 1 100%; font-size:12px; color:var(--muted); }
|
||||
.tabel-trimiteri td.col-note { order:8; flex:1 1 100%; font-size:12px; color:var(--accent); line-height:1.3; margin-top:1px; }
|
||||
.tabel-trimiteri td.col-actiuni { order:9; flex:0 0 auto; margin-left:auto; margin-top:4px; text-align:right; }
|
||||
.tabel-trimiteri td.col-actiuni button, .tabel-trimiteri td.col-actiuni .act { width:auto; min-height:32px; padding:5px 14px; }
|
||||
.tabel-trimiteri.preview-arata-trimise tr.preview-sent-row { display:flex !important; }
|
||||
}
|
||||
/* === Preview import: coloane extra fata de tabelul Trimiteri.
|
||||
SCOPAT prin .tabel-trimiteri (clasa partajata). Regiune separata —
|
||||
nu atinge coloanele existente (col-chk/id/stare/data/rar/actualizat).
|
||||
@@ -367,7 +484,12 @@
|
||||
Restul (~680px la 1280px) revine lui col-vehicul + col-operatie (fluid). === */
|
||||
.tabel-trimiteri .col-km { width:76px; }
|
||||
.tabel-trimiteri .col-note { width:176px; }
|
||||
.tabel-trimiteri .col-actiuni { width:92px; }
|
||||
/* Nota preview = culoarea camp-fix (accent), ca sa atraga atentia (dogfood 5.13):
|
||||
campul Note e self-explanatory, asa ca hint-urile per-camp au fost scoase. */
|
||||
.tabel-trimiteri td.col-note { color:var(--accent); }
|
||||
/* Pill-ul de stare nu se rupe pe doua randuri in cardul compact. */
|
||||
.tabel-trimiteri td.col-stare .pill { white-space:nowrap; }
|
||||
.tabel-trimiteri .col-actiuni { width:104px; }
|
||||
/* Randul de editare inline iese din grila table-layout:fixed (display:block),
|
||||
astfel formularul nu e constrans de latimile coloanelor individuale.
|
||||
Salveaza/Anuleaza sunt mereu vizibile (overflow:visible, nu clip). */
|
||||
@@ -401,16 +523,51 @@
|
||||
Breakpoint unic 767px (vezi conventia de sus). Cuprinde: card per rand pe tabelul
|
||||
de trimiteri, modal full-screen, header/nav colapsat cu tinte touch
|
||||
>=44px. Desktop (>=1024px) ramane neschimbat — regulile de baza nu se modifica. */
|
||||
/* SENTINEL-TESTE-MOBIL: blocul mobil principal incepe mai jos; testele ancoreaza pe acest marker si feliaza pana la sfarsitul stilului. NU muta/sterge. */
|
||||
@media (max-width:767px) {
|
||||
/* Tabel trimiteri: card per rand (eticheta:valoare stivuit) -> fara scroll orizontal */
|
||||
.tabel-trimiteri table { table-layout:auto; }
|
||||
.tabel-trimiteri thead { display:none; }
|
||||
.tabel-trimiteri table, .tabel-trimiteri tbody, .tabel-trimiteri tr, .tabel-trimiteri td { display:block; width:auto; }
|
||||
.tabel-trimiteri tr { border:1px solid var(--line); border-radius:8px; padding:8px 12px; margin-bottom:10px; }
|
||||
.tabel-trimiteri td { border-bottom:none; padding:4px 0; display:flex; gap:10px; align-items:baseline; }
|
||||
.tabel-trimiteri td::before { content:attr(data-eticheta); color:var(--muted); font-size:12px;
|
||||
flex:0 0 auto; min-width:120px; }
|
||||
.tabel-trimiteri td.col-chk { display:none; }
|
||||
.tabel-trimiteri td { border-bottom:none; padding:3px 0; display:block; }
|
||||
.tabel-trimiteri td::before { content:attr(data-eticheta); display:block; color:var(--muted);
|
||||
font-size:12px; margin-bottom:2px; }
|
||||
.tabel-trimiteri td.col-chk, .tabel-trimiteri td.col-id { display:none; }
|
||||
|
||||
/* === Card COMPACT (PRD 5.13, corectie dogfood) ===
|
||||
Inlocuieste stiva generica eticheta+valoare (prea inalta) cu un card
|
||||
scanabil la prima vedere: vehicul = titlu, stare = pill dreapta-sus,
|
||||
operatie+cod pe rand, meta (data/km/rar) muted mic, nota mica. Fara
|
||||
etichete-zgomot. Override DUPA regulile de baza (cascada: ultimul castiga). */
|
||||
.tabel-trimiteri tr { display:flex; flex-wrap:wrap; align-items:baseline;
|
||||
gap:1px 8px; padding:9px 12px; }
|
||||
.tabel-trimiteri td { display:block; padding:0; }
|
||||
.tabel-trimiteri tr.trimitere-row > td { padding-top:0; padding-bottom:0; }
|
||||
.tabel-trimiteri td::before { display:none; } /* compact: fara etichete */
|
||||
.tabel-trimiteri td.col-vehicul { order:1; flex:1 1 55%; min-width:0;
|
||||
font-weight:600; font-size:15px; line-height:1.25; }
|
||||
.tabel-trimiteri td.col-vehicul .muted { font-weight:400; }
|
||||
.tabel-trimiteri td.col-stare { order:2; flex:0 0 auto; margin-left:auto;
|
||||
align-self:flex-start; }
|
||||
.tabel-trimiteri td.col-operatie { order:3; flex:1 1 100%; font-size:13px;
|
||||
line-height:1.3; margin-top:1px; }
|
||||
.tabel-trimiteri td.col-data,
|
||||
.tabel-trimiteri td.col-km,
|
||||
.tabel-trimiteri td.col-rar { font-size:12px; color:var(--muted); }
|
||||
.tabel-trimiteri td.col-data { order:4; }
|
||||
.tabel-trimiteri td.col-km { order:5; }
|
||||
.tabel-trimiteri td.col-km::before { content:"· "; display:inline; color:var(--muted); }
|
||||
.tabel-trimiteri td.col-rar { order:6; }
|
||||
.tabel-trimiteri td.col-actualizat { order:7; flex:1 1 100%; font-size:12px;
|
||||
color:var(--muted); }
|
||||
.tabel-trimiteri td.col-note { order:8; flex:1 1 100%; font-size:12px;
|
||||
color:var(--accent); line-height:1.3; margin-top:1px; }
|
||||
.tabel-trimiteri td.col-actiuni { order:9; flex:0 0 auto; margin-left:auto;
|
||||
margin-top:4px; text-align:right; }
|
||||
.tabel-trimiteri td.col-actiuni button,
|
||||
.tabel-trimiteri td.col-actiuni .act { width:auto; min-height:32px; padding:5px 14px; }
|
||||
.tabel-trimiteri.preview-arata-trimise tr.preview-sent-row { display:flex !important; }
|
||||
|
||||
/* Modal full-screen: ocupa tot ecranul, fara backdrop lateral (overlay fara
|
||||
padding, dialog la latime/inaltime pline, fara colturi/umbra). Scroll intern
|
||||
@@ -483,16 +640,40 @@
|
||||
#import-section #upload-btn { width:100%; min-height:44px; }
|
||||
/* Bara de status: contoarele/randurile raman aliniate la stanga, fara scroll orizontal. */
|
||||
#status-bar > div { gap:10px; }
|
||||
/* Bara de filtre trimiteri: o coloana, fiecare control full-width, buton >=44px.
|
||||
!important suprascrie latimile inline (ex. max-width:180px pe vehicul) DOAR pe mobil. */
|
||||
#filtre-trimiteri { flex-direction:column; align-items:stretch; }
|
||||
/* Bara de filtre trimiteri ADAPTATA pentru mobil (nu doar stivuita):
|
||||
- cautarea vehicul = rand propriu prioritar (input + buton pe acelasi rand);
|
||||
- grupurile de pill-uri (data + stare) = scroll orizontal, compacte (nu 8 butoane
|
||||
full-width unul sub altul). !important suprascrie latimile inline doar pe mobil. */
|
||||
#filtre-trimiteri { flex-direction:column; align-items:stretch; gap:8px; }
|
||||
#filtre-trimiteri > div { width:100%; }
|
||||
#filtre-trimiteri select, #filtre-trimiteri input[type=text],
|
||||
#filtre-trimiteri input[type=date] { width:100% !important; max-width:none !important; }
|
||||
#filtre-trimiteri button { width:100%; min-height:44px; }
|
||||
/* Cautarea vehicul: input creste, butonul Filtreaza compact langa el. */
|
||||
#filtre-trimiteri input[type=text] { flex:1 1 auto; width:auto !important; max-width:none !important; min-height:44px; }
|
||||
#filtre-trimiteri input[type=date] { width:100% !important; max-width:none !important; min-height:44px; }
|
||||
#filtre-trimiteri button[type=submit] { flex:0 0 auto; width:auto; min-height:44px; }
|
||||
/* Grupurile de pill-uri: o singura banda scrolabila orizontal, compacta. */
|
||||
#filtre-trimiteri .pills-categorii { margin-left:0 !important; flex-wrap:nowrap;
|
||||
overflow-x:auto; -webkit-overflow-scrolling:touch; padding-bottom:2px; }
|
||||
#filtre-trimiteri .pill-cat { flex:0 0 auto; }
|
||||
|
||||
/* Operatii de mapat (preview import): randul de mapare stiva pe o coloana,
|
||||
select-ul full-width (altfel max-width:340px global il scoate din viewport). */
|
||||
.maprow { gap:6px 12px; padding:10px 0; }
|
||||
.maprow .mapcol { flex:1 1 100%; min-width:0; }
|
||||
.maprow select { width:100% !important; max-width:none !important; }
|
||||
.maprow button { width:100%; min-height:44px; }
|
||||
|
||||
/* Card de autentificare (login/signup): centrat si nu depaseste viewport-ul pe mobil. */
|
||||
.auth-card { max-width:100%; margin:24px auto; }
|
||||
/* Versiunea ascunsa pe mobil (la fel ca pe tableta). */
|
||||
.header-right > .muted { display:none; }
|
||||
/* Actiuni .act pe mobil: iconita patrata 44px, textul ascuns. */
|
||||
.act { min-width:44px; min-height:44px; width:44px; padding:0; }
|
||||
.act .act-tx { display:none; }
|
||||
.act .act-ic { display:inline-block; }
|
||||
.act-group { gap:10px; }
|
||||
/* Bara confirmare compacta pe mobil. */
|
||||
.sticky-bar { padding:10px 12px; gap:10px; }
|
||||
.sticky-bar button { width:100%; min-height:44px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
@@ -551,6 +732,9 @@
|
||||
{# aria-live pentru anuntarea schimbarilor de tema (accesibilitate) #}
|
||||
<span id="tema-live" role="status" aria-live="polite"
|
||||
style="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;"></span>
|
||||
{# Toast global: feedback tranzitoriu (ex. dupa salvarea unui rand de import).
|
||||
aria-live=polite -> citit de screen-reader. window.arataToast(text, stareCss). #}
|
||||
<div id="toast" role="status" aria-live="polite" hidden></div>
|
||||
<main>{% block content %}{% endblock %}</main>
|
||||
{# Modal detaliu trimitere: container global, SIBLING al <main> (nu descendent),
|
||||
ca `inert`+`aria-hidden` pe <main> sa nu-l prinda si pe el. Corpul
|
||||
@@ -696,6 +880,39 @@
|
||||
if (saveBtn) saveBtn.classList.add('dirty');
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
// Toast global: feedback tranzitoriu vizibil + accesibil (aria-live).
|
||||
// window.arataToast(text, stareCss) — stareCss (ex. "s-error"/"s-needs_review")
|
||||
// coloreaza punctul indicator (rosu/galben/verde). Auto-dispare dupa ~3.2s.
|
||||
(function() {
|
||||
var t = document.getElementById('toast');
|
||||
var timer = null;
|
||||
window.arataToast = function(text, stareCss) {
|
||||
if (!t) return;
|
||||
t.className = '';
|
||||
if (stareCss) t.classList.add('t-' + stareCss);
|
||||
t.textContent = text;
|
||||
t.hidden = false;
|
||||
void t.offsetWidth; // reflow -> tranzitia porneste
|
||||
t.classList.add('show');
|
||||
if (timer) clearTimeout(timer);
|
||||
timer = setTimeout(function() {
|
||||
t.classList.remove('show');
|
||||
setTimeout(function() { t.hidden = true; }, 220);
|
||||
}, 3200);
|
||||
};
|
||||
})();
|
||||
|
||||
// Feedback dupa salvarea/confirmarea unui rand de import (HX-Trigger 'randSalvat').
|
||||
// Toast imediat (ce rand + ce stare are acum); evidentierea randului se aplica dupa
|
||||
// ce preview-ul se reincarca (reincarcaPreview), de scriptul din _preview_import.
|
||||
document.body.addEventListener('randSalvat', function(e) {
|
||||
var d = e.detail || {};
|
||||
if (window.arataToast)
|
||||
window.arataToast('Randul ' + d.nr + ' actualizat · ' + (d.stare || ''), d.stareCss || '');
|
||||
window.__randSalvat = d;
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
// Cautare + paginare client-side pentru tabele mari (data-dt="<page_size>"). Filtreaza si
|
||||
// pagineaza DOM-ul deja randat (fara cereri server) — potrivit pentru maparile care pot creste
|
||||
|
||||
Reference in New Issue
Block a user