feat(5.16+5.17): tipografie/antet branded + tipuri cont, planuri si enforcement
PRD 5.16 — propagare design finalizata (system font stack, fara IBM Plex self-hostat): - US-001/002/008: tokeni --font-ui/--font-mono (system stack) + scala --fs-*; zero @font-face si zero /static/fonts/; landing aliniat la acelasi stack - US-003: RAR online = dot compact in antet + meniu burger; banda rosie DOAR pe blocat (invariant zero-silent-failures pastrat) - US-010: antet "ROMFAST AUTOPASS" + nume service + /login brandeit 2 coloane + badge plan; meniu burger cu separatoare; gate strict pe is_authenticated - US-011: selector tema pill icon+eticheta (reuse THEMES) - US-004/005/006/007: bug-fix editor prestatii (picker cod+denumire, add_extra in mod operatii, cod ales se salveaza fara "+", Renunta inchide via closest) - US-012/013: landing Autentificare->/login; wizard import colapsat + 4 pasi pe tokeni - fix VERIFY E2E: contoare duplicate pe 390px (inline display:flex batea @media) -> CSS + test-lock PRD 5.17 — tipuri de cont + trial Pro 30z + enforcement DUR: - US-001/002/008: accounts.tier + trial_until (migrare aditiva defensiva); app/plans.py sursa unica (PLANS, FREE_MONTHLY_LIMIT=60, effective_tier(now injectabil), monthly_usage, CONSUMED_STATUSES); create_account trial Pro 30z; CLI set-tier (protejat id=1, audit) - US-003/004/005: enforce volum 60/luna INAINTE de build_key pe ambele canale (PLAN_LIMITA_LUNARA, 3 niveluri + log_event); gate API Pro+ (PLAN_FARA_API 403 actionabil); valideaza/nomenclator raman permise; downgrade lazy; flag AUTOPASS_ENFORCE_PLANS (kill-switch) - US-006: badge plan antet + linie burger + consum N/60 + warn>=80% + 6 stari + copy RO pluralizat + banner one-time trial->Gratuit + pagina Cont Regresie: 1380 passed, 0 failed, 1 deselected (live). E2E browser pe 390/1280 confirmat. Backend trimitere (worker/masina stari/idempotenta/contract RAR) NEATINS. Lucrul 5.18 (corpus kNN) ramane separat, necomis. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,11 +10,11 @@
|
||||
{% set pas = 3 %}{% include '_stepper.html' %}
|
||||
<div class="card">
|
||||
<div style="display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:12px;">
|
||||
<h2 style="font-size:15px; margin:0;">
|
||||
<h2 style="font-size:var(--fs-md); margin:0;">
|
||||
Preview —
|
||||
<span class="muted" style="font-weight:400;">{{ filename or ("import #" ~ import_id) }}</span>
|
||||
</h2>
|
||||
<span class="muted" style="margin-left:auto; font-size:13px;">{{ total }} randuri</span>
|
||||
<span class="muted" style="margin-left:auto; font-size:var(--fs-sm);">{{ total }} randuri</span>
|
||||
</div>
|
||||
|
||||
{% if message %}
|
||||
@@ -37,7 +37,8 @@
|
||||
{% for status_key, label in status_labels %}
|
||||
{%- set cnt = summary.get(status_key, 0) -%}
|
||||
{% if cnt > 0 %}
|
||||
<span class="pill s-{{ status_key }}">{{ cnt }} {{ label | lower }}</span>
|
||||
<span class="pill s-{{ status_key }}" style="display:inline-flex; align-items:center; gap:5px; font-size:var(--fs-xs);">
|
||||
<span aria-hidden="true" style="display:inline-block; width:7px; height:7px; border-radius:99px; background:currentColor; flex-shrink:0;"></span>{{ cnt }} {{ label | lower }}</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
@@ -46,14 +47,14 @@
|
||||
<div style="display:flex; gap:6px; flex-wrap:wrap; margin-bottom:10px;" role="group"
|
||||
aria-label="Filtrare dupa stare">
|
||||
<button type="button" class="filter-btn" data-filter="all"
|
||||
style="min-height:36px; font-size:13px; padding:4px 12px;">
|
||||
style="min-height:36px; font-size:var(--fs-sm); padding:4px 12px;">
|
||||
Toate ({{ total }})
|
||||
</button>
|
||||
{% for status_key, label in status_labels %}
|
||||
{%- set cnt = summary.get(status_key, 0) -%}
|
||||
{% if cnt > 0 %}
|
||||
<button type="button" class="filter-btn" data-filter="{{ status_key }}"
|
||||
style="min-height:36px; font-size:13px; padding:4px 12px;
|
||||
style="min-height:36px; font-size:var(--fs-sm); padding:4px 12px;
|
||||
background:transparent; border-color:var(--line); color:var(--ink);">
|
||||
{{ label }} ({{ cnt }})
|
||||
</button>
|
||||
@@ -66,7 +67,7 @@
|
||||
{% if unmapped_ops %}
|
||||
<div class="card" style="border-color:var(--err); background:color-mix(in srgb, var(--err) 12%, var(--card)); margin-bottom:14px;">
|
||||
<h3 style="font-size:14px; margin:0 0 6px;">Operatii de mapat la cod RAR</h3>
|
||||
<p class="muted" style="margin:0 0 12px; font-size:13px;">
|
||||
<p class="muted" style="margin:0 0 12px; font-size:var(--fs-sm);">
|
||||
Aceste operatii din fisier nu au inca un cod RAR. Alege codul (sugestia e
|
||||
preselectata) si salveaza — randurile blocate trec automat in
|
||||
<span class="s-ok">ok</span> si maparea se retine pentru fisierele viitoare.
|
||||
@@ -167,7 +168,7 @@
|
||||
</table>
|
||||
<!-- Mesaj "filtrat la zero": afisat de JS cand filtrul ascunde toate randurile -->
|
||||
<p id="preview-zero-message" class="muted"
|
||||
style="display:none; text-align:center; padding:24px 16px; font-size:14px;">
|
||||
style="display:none; text-align:center; padding:24px 16px; font-size:var(--fs-md);">
|
||||
Niciun rand nu corespunde filtrului selectat.
|
||||
</p>
|
||||
</div>
|
||||
@@ -190,7 +191,7 @@
|
||||
|
||||
<div style="display:flex; gap:8px; align-items:center; flex-wrap:wrap;">
|
||||
<label for="n-confirmat"
|
||||
style="font-size:13px; color:var(--muted);">
|
||||
style="font-size:var(--fs-sm); color:var(--muted);">
|
||||
Confirma numarul
|
||||
</label>
|
||||
<input type="number" id="n-confirmat" name="n_confirmat"
|
||||
@@ -198,7 +199,7 @@
|
||||
min="0" required
|
||||
style="max-width:80px;"
|
||||
aria-describedby="n-hint">
|
||||
<span id="n-hint" class="muted" style="font-size:12px;">
|
||||
<span id="n-hint" class="muted" style="font-size:var(--fs-xs);">
|
||||
din <span id="n-hint-ok">{{ summary.get('ok', 0) }}</span> gata de trimis
|
||||
</span>
|
||||
</div>
|
||||
@@ -207,13 +208,13 @@ din <span id="n-hint-ok">{{ summary.get('ok', 0) }}</span> gata de trimis
|
||||
<div style="display:flex; flex-direction:column; gap:6px; align-self:flex-end;">
|
||||
<button type="submit"
|
||||
id="confirm-btn"
|
||||
style="min-height:44px; padding:10px 28px; font-size:14px;"
|
||||
style="min-height:44px; padding:10px 28px; font-size:var(--fs-md);"
|
||||
{% if not summary.get('ok', 0) %}disabled title="Niciun rand ok de trimis"{% endif %}>
|
||||
Trimite la RAR
|
||||
</button>
|
||||
{% if summary.get('needs_data', 0) or summary.get('needs_mapping', 0) or summary.get('needs_review', 0) %}
|
||||
<a href="/v1/import/{{ import_id }}/export-failed" download
|
||||
style="font-size:12px; text-align:center;">
|
||||
style="font-size:var(--fs-xs); text-align:center;">
|
||||
descarca randuri cu probleme (CSV)
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -226,7 +227,7 @@ din <span id="n-hint-ok">{{ summary.get('ok', 0) }}</span> gata de trimis
|
||||
<span id="preview-ok-count" data-ok="{{ summary.get('ok', 0) }}" hidden></span>
|
||||
|
||||
<div style="padding:8px 0 4px;">
|
||||
<a href="#" class="muted" style="font-size:13px;"
|
||||
<a href="#" class="muted" style="font-size:var(--fs-sm);"
|
||||
hx-get="/_import/reset" hx-target="#import-section" hx-swap="outerHTML">Incarca alt fisier</a>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user