feat(setari): meniu grupat + pagina Setari cu sub-taburi + schimbare parola
Meniu hamburger reorganizat pe grupuri cu etichete (LUCRU / CONT) cu iconite SVG discrete; "Cont" redenumit "Setari" (URL ?tab=cont pastrat, zero rute moarte). Pagina Setari restructurata in sub-taburi interne: Date firma / Credentiale RAR / Cheie API / Cont (plan + schimbare parola), cu indicator de stare per tab. Sub-tabul activ e pastrat server-side (activ_subtab) dupa fiecare swap HTMX; comutarea intre taburi e client-side, delegata pe document (supravietuieste swap-urilor). Credentiale RAR: mediile Testare/Productie ca doua carduri paralele. Schimbare parola de acces din sub-tabul Cont (functie noua, lipsea): - users.change_password (scrypt): verifica parola actuala constant-time, valideaza noua (10..128, diferita), rescrie hash+salt nou; - ruta POST /cont/schimba-parola, scoped pe user_id din sesiune, CSRF enforce, parola niciodata re-pusa in raspuns, jurnal 'parola_schimbata'. Referinte copy "Meniu cont > Cont" -> "Setari". Teste: schimbare parola (succes / parola actuala gresita / confirmare nepotrivita / lungime) + izolare rate-limit login in fixture-ul clientului. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,228 +1,235 @@
|
||||
<div class="card" id="card-cont">
|
||||
<h2 style="font-size:15px; margin:0 0 16px;">Contul meu</h2>
|
||||
|
||||
<!-- Sectiunea: Plan curent (US-006 PRD 5.17) -->
|
||||
{% if plan_linie is defined %}
|
||||
<div id="sectiune-plan" style="margin-bottom:20px; padding-bottom:20px; border-bottom:1px solid var(--line);">
|
||||
<h3 style="font-size:var(--fs-sm); color:var(--muted); font-weight:500; margin:0 0 10px;
|
||||
text-transform:uppercase; letter-spacing:.04em;">Plan curent</h3>
|
||||
|
||||
<div style="font-size:var(--fs-md); font-weight:600; margin-bottom:6px;
|
||||
color:{% if plan_limita_atinsa|default(false) %}var(--err){% elif plan_warn|default(false) %}var(--warn){% else %}var(--ink){% endif %};">
|
||||
{{ plan_linie }}
|
||||
</div>
|
||||
|
||||
{% if monthly_limit_val is defined and monthly_limit_val is not none and effective_tier_name|default('') == 'free' %}
|
||||
<div style="font-size:var(--fs-sm); color:var(--muted); margin-bottom:8px;">
|
||||
Planul Gratuit include {{ monthly_limit_val }} prestatii/luna prin dashboard-ul web.
|
||||
{% if plan_limita_atinsa|default(false) %}
|
||||
Limita lunara a fost atinsa — trimiterile noi sunt blocate pana la inceputul lunii urmatoare.
|
||||
{% elif plan_warn|default(false) %}
|
||||
Te apropii de limita lunara.
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div style="font-size:var(--fs-sm); color:var(--muted); padding:8px 10px;
|
||||
border:1px solid var(--line); border-radius:6px; margin-top:4px;">
|
||||
Vrei sa treci pe Standard, Pro sau Premium?
|
||||
Contacteaza-ne pentru alocare manuala — nu exista inca plata self-service.
|
||||
<strong>Pro</strong> adauga import prin API; <strong>Standard</strong> si
|
||||
<strong>Premium</strong> ridica limita de volum.
|
||||
</div>
|
||||
{# Pagina Setari: sub-taburi interne — Date firma / Credentiale RAR / Cheie API /
|
||||
Cont (plan + parola). `activ_subtab` (server) alege panoul activ dupa fiecare
|
||||
swap HTMX, ca re-randarea sa nu resete la primul tab. Comutarea intre taburi
|
||||
fara server = JS delegat in base.html (#card-cont). #}
|
||||
{% set _firma_ok = account_meta.name and account_meta.email and account_meta.cui %}
|
||||
{% set _rar_ok = medii_disponibile and medii_disponibile|length > 0 %}
|
||||
<div class="card" id="card-cont" data-activ-subtab="{{ activ_subtab|default('firma') }}">
|
||||
<div class="setari-head">
|
||||
<h2 class="setari-title">
|
||||
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M2 12h3M19 12h3M4.6 4.6l2.1 2.1M17.3 17.3l2.1 2.1M4.6 19.4l2.1-2.1M17.3 6.7l2.1-2.1"/></svg>
|
||||
Setari
|
||||
</h2>
|
||||
<p class="setari-sub">Datele firmei, credentialele RAR, cheia API si contul tau.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Sectiunea: Date firma (US-002) -->
|
||||
<div style="margin-bottom:20px; padding-bottom:20px; border-bottom:1px solid var(--line);">
|
||||
<h3 style="font-size:13px; color:var(--muted); font-weight:500; margin:0 0 8px; text-transform:uppercase; letter-spacing:.04em;">Date firma</h3>
|
||||
<div class="setari-subtabs" role="tablist" aria-label="Sectiuni setari">
|
||||
<button type="button" class="setari-subtab{{ ' is-active' if activ_subtab|default('firma') == 'firma' else '' }}" role="tab" data-subtab="firma"
|
||||
aria-selected="{{ 'true' if activ_subtab|default('firma') == 'firma' else 'false' }}">
|
||||
<span class="st-dot {{ 'ok' if _firma_ok else 'warn' }}" aria-hidden="true"></span>Date firma</button>
|
||||
<button type="button" class="setari-subtab{{ ' is-active' if activ_subtab|default('firma') == 'rar' else '' }}" role="tab" data-subtab="rar"
|
||||
aria-selected="{{ 'true' if activ_subtab|default('firma') == 'rar' else 'false' }}">
|
||||
<span class="st-dot {{ 'ok' if _rar_ok else 'warn' }}" aria-hidden="true"></span>Credentiale RAR</button>
|
||||
<button type="button" class="setari-subtab{{ ' is-active' if activ_subtab|default('firma') == 'api' else '' }}" role="tab" data-subtab="api"
|
||||
aria-selected="{{ 'true' if activ_subtab|default('firma') == 'api' else 'false' }}">
|
||||
<span class="st-dot {{ 'ok' if are_cheie else 'warn' }}" aria-hidden="true"></span>Cheie API</button>
|
||||
<button type="button" class="setari-subtab{{ ' is-active' if activ_subtab|default('firma') == 'cont' else '' }}" role="tab" data-subtab="cont"
|
||||
aria-selected="{{ 'true' if activ_subtab|default('firma') == 'cont' else 'false' }}">
|
||||
<span class="st-dot info" aria-hidden="true"></span>Cont</button>
|
||||
</div>
|
||||
|
||||
{% if date_firma_mesaj %}
|
||||
<div class="flash" style="margin-bottom:12px;">{{ date_firma_mesaj }}</div>
|
||||
{% endif %}
|
||||
{# ============================ Sub-tab: Date firma ============================ #}
|
||||
<div class="setari-pane" data-subpane="firma" role="tabpanel"
|
||||
{% if activ_subtab|default('firma') != 'firma' %}hidden{% endif %}>
|
||||
<div class="setari-zone-title">
|
||||
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 21V4a1 1 0 0 1 1-1h9a1 1 0 0 1 1 1v17"/><path d="M15 9h4a1 1 0 0 1 1 1v11"/><path d="M2 21h20"/><path d="M8 7h3M8 11h3M8 15h3"/></svg>
|
||||
Date firma
|
||||
<span class="setari-badge {{ 'sb-ok' if _firma_ok else 'sb-warn' }}">{{ 'complet' if _firma_ok else 'incomplet' }}</span>
|
||||
</div>
|
||||
<p class="setari-zone-desc">Apar pe declaratiile catre RAR si pe facturile de plan.</p>
|
||||
|
||||
{% if date_firma_eroare %}
|
||||
<div class="banner" style="margin-bottom:12px; padding:8px 12px;">{{ date_firma_eroare }}</div>
|
||||
{% endif %}
|
||||
{% if date_firma_mesaj %}<div class="flash" style="margin-bottom:12px;">{{ date_firma_mesaj }}</div>{% endif %}
|
||||
{% if date_firma_eroare %}<div class="banner" style="margin-bottom:12px; padding:8px 12px;">{{ date_firma_eroare }}</div>{% endif %}
|
||||
|
||||
<form hx-post="/cont/date-firma"
|
||||
hx-target="#card-cont"
|
||||
hx-swap="outerHTML">
|
||||
<form hx-post="/cont/date-firma" hx-target="#card-cont" hx-swap="outerHTML">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
<p style="margin:0 0 8px;">
|
||||
<label style="font-size:13px; color:var(--muted);">Companie</label><br>
|
||||
<input type="text" name="companie" required
|
||||
value="{{ account_meta.name or '' }}"
|
||||
style="width:100%; max-width:340px;"
|
||||
placeholder="Numele firmei (ex. Service Auto SRL)">
|
||||
<input type="text" name="companie" required value="{{ account_meta.name or '' }}"
|
||||
style="width:100%; max-width:340px;" placeholder="Numele firmei (ex. Service Auto SRL)">
|
||||
</p>
|
||||
<p style="margin:0 0 8px;">
|
||||
<label style="font-size:13px; color:var(--muted);">Email contact</label><br>
|
||||
<input type="email" name="email" required
|
||||
value="{{ account_meta.email or '' }}"
|
||||
style="width:100%; max-width:340px;"
|
||||
placeholder="contact@firma.ro">
|
||||
<input type="email" name="email" required value="{{ account_meta.email or '' }}"
|
||||
style="width:100%; max-width:340px;" placeholder="contact@firma.ro">
|
||||
</p>
|
||||
<p style="margin:0 0 12px;">
|
||||
<label style="font-size:13px; color:var(--muted);">CUI (cod unic de identificare)</label><br>
|
||||
<input type="text" name="cui" required
|
||||
value="{{ account_meta.cui or '' }}"
|
||||
style="width:100%; max-width:340px;"
|
||||
placeholder="RO12345678">
|
||||
<input type="text" name="cui" required value="{{ account_meta.cui or '' }}"
|
||||
style="width:100%; max-width:340px;" placeholder="RO12345678">
|
||||
</p>
|
||||
<button type="submit">Salveaza datele firmei</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Sectiunea: Cheia mea API -->
|
||||
<div style="margin-bottom:20px; padding-bottom:20px; border-bottom:1px solid var(--line);">
|
||||
<h3 style="font-size:13px; color:var(--muted); font-weight:500; margin:0 0 8px; text-transform:uppercase; letter-spacing:.04em;">Cheia mea API</h3>
|
||||
|
||||
{% if api_key %}
|
||||
<div class="flash" style="margin-bottom:12px;">Cheia a fost rotita. Salveaz-o acum — nu o vei mai putea vedea.</div>
|
||||
|
||||
<div class="card" style="font-family:monospace; word-break:break-all; font-size:14px; background:#0f1115; margin:0 0 8px;">
|
||||
{{ api_key }}
|
||||
</div>
|
||||
|
||||
<button type="button"
|
||||
data-key="{{ api_key }}"
|
||||
onclick="navigator.clipboard.writeText(this.dataset.key).then(()=>this.textContent='Copiat!')">
|
||||
Copiaza cheia
|
||||
</button>
|
||||
|
||||
<p style="font-size:13px; color:var(--warn); margin:10px 0 0;">
|
||||
Atentie: la urmatoarea vizita aceasta cheie dispare. Daca o pierzi, roteste din nou.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if rot_eroare %}
|
||||
<div class="banner" style="margin-bottom:12px; padding:8px 12px;">{{ rot_eroare }}</div>
|
||||
{% endif %}
|
||||
|
||||
<form hx-post="/cont/roteste-cheie"
|
||||
hx-target="#card-cont"
|
||||
hx-swap="outerHTML"
|
||||
style="margin-top:{% if api_key %}12px{% else %}0{% endif %};">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
<button type="submit" style="background:var(--card); color:var(--warn); border-color:var(--warn);">
|
||||
Roteste cheia API
|
||||
</button>
|
||||
<span style="font-size:12px; color:var(--muted); margin-left:8px;">Cheia veche se revoca imediat.</span>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Sectiunea: Credentiale RAR -->
|
||||
<div>
|
||||
<h3 style="font-size:13px; color:var(--muted); font-weight:500; margin:0 0 12px; text-transform:uppercase; letter-spacing:.04em;">Credentiale RAR (portal AUTOPASS)</h3>
|
||||
|
||||
<p class="muted" style="font-size:12px; margin:0 0 12px; line-height:1.5;">
|
||||
Configureaza mai jos mediile RAR — Testare si/sau Productie — fiecare cu credentialele
|
||||
lui, validate separat la salvare pe sistemul RAR corespunzator. Un mediu devine activ
|
||||
cand e bifat si are credentiale; abia atunci importul web poate trimite pe el. Fara
|
||||
niciun mediu activ, importul web nu are credentiale si trimiterile esueaza. (Canalul API
|
||||
ramane pe mediul global al instantei, {{ mediu_instanta() }}, pentru ca isi cara singur
|
||||
credentialele.)
|
||||
{# ========================= Sub-tab: Credentiale RAR ========================= #}
|
||||
<div class="setari-pane" data-subpane="rar" role="tabpanel"
|
||||
{% if activ_subtab|default('firma') != 'rar' %}hidden{% endif %}>
|
||||
<div class="setari-zone-title">
|
||||
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 11l1.5-4A2 2 0 0 1 8.4 5.6h7.2A2 2 0 0 1 17.5 7L19 11"/><path d="M4 11h16v6H4z"/><path d="M6 17v2M18 17v2"/><circle cx="7.5" cy="14" r="1"/><circle cx="16.5" cy="14" r="1"/></svg>
|
||||
Credentiale RAR (portal AUTOPASS)
|
||||
<span class="setari-badge {{ 'sb-ok' if _rar_ok else 'sb-warn' }}">{{ 'configurat' if _rar_ok else 'neconfigurat' }}</span>
|
||||
</div>
|
||||
<p class="setari-zone-desc">
|
||||
Configureaza mediile RAR — Testare si/sau Productie — fiecare cu credentialele lui,
|
||||
validate separat la salvare pe sistemul RAR corespunzator. Un mediu devine activ cand e
|
||||
bifat si are credentiale; abia atunci importul web poate trimite pe el. (Canalul API ramane
|
||||
pe mediul global al instantei, {{ mediu_instanta() }}, pentru ca isi cara singur credentialele.)
|
||||
</p>
|
||||
|
||||
{% if creds_mesaj %}
|
||||
<div class="flash" style="margin-bottom:12px;">{{ creds_mesaj }}</div>
|
||||
{% endif %}
|
||||
{% if creds_eroare %}
|
||||
<div class="banner" style="margin-bottom:12px; padding:8px 12px;">{{ creds_eroare }}</div>
|
||||
{% endif %}
|
||||
{% if creds_mesaj %}<div class="flash" style="margin-bottom:12px;">{{ creds_mesaj }}</div>{% endif %}
|
||||
{% if creds_eroare %}<div class="banner" style="margin-bottom:12px; padding:8px 12px;">{{ creds_eroare }}</div>{% endif %}
|
||||
|
||||
<form hx-post="/cont/rar-medii"
|
||||
hx-target="#card-cont"
|
||||
hx-swap="outerHTML">
|
||||
<form hx-post="/cont/rar-medii" hx-target="#card-cont" hx-swap="outerHTML">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
|
||||
<!-- Subsectiunea: Testare -->
|
||||
<div style="margin-bottom:16px; padding-bottom:16px; border-bottom:1px solid var(--line);">
|
||||
<p style="margin:0 0 6px;">
|
||||
<label style="font-size:13px; color:var(--muted); display:flex; align-items:center; gap:6px;">
|
||||
<div class="env-cards">
|
||||
<!-- Testare -->
|
||||
<div class="env-card{% if test_disponibil %} active-test{% endif %}">
|
||||
<h4>Testare
|
||||
{% if test_disponibil %}<span class="setari-badge sb-ok">configurat</span>{% else %}<span class="setari-badge sb-info">inactiv</span>{% endif %}
|
||||
</h4>
|
||||
<label class="env-sw">
|
||||
<input type="checkbox" name="test_enabled" value="1" {% if test_enabled %}checked{% endif %}>
|
||||
Activare Testare
|
||||
</label>
|
||||
{% if test_disponibil %}
|
||||
<span style="font-size:12px; color:var(--ok);">configurat</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
<p style="margin:0 0 8px;">
|
||||
<label style="font-size:13px; color:var(--muted);">Email RAR Testare</label><br>
|
||||
<input type="email" name="test_email" style="width:100%; max-width:340px;"
|
||||
placeholder="email@service.ro">
|
||||
</p>
|
||||
<p style="margin:0 0 8px;">
|
||||
<label style="font-size:13px; color:var(--muted);">Parola RAR Testare</label><br>
|
||||
<input type="password" name="test_parola" style="width:100%; max-width:340px;"
|
||||
autocomplete="new-password">
|
||||
</p>
|
||||
{% if creds_test_mesaj %}
|
||||
<div class="flash" style="margin-top:6px;">{{ creds_test_mesaj }}</div>
|
||||
{% endif %}
|
||||
{% if creds_test_eroare %}
|
||||
<div class="banner" style="margin-top:6px; padding:8px 12px;">{{ creds_test_eroare }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<label class="env-lbl">Email RAR Testare</label>
|
||||
<input type="email" name="test_email" placeholder="email@service.ro">
|
||||
<label class="env-lbl">Parola RAR Testare</label>
|
||||
<input type="password" name="test_parola" autocomplete="new-password">
|
||||
{% if creds_test_mesaj %}<div class="flash" style="margin-top:6px;">{{ creds_test_mesaj }}</div>{% endif %}
|
||||
{% if creds_test_eroare %}<div class="banner" style="margin-top:6px; padding:8px 12px;">{{ creds_test_eroare }}</div>{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Subsectiunea: Productie -->
|
||||
<div style="margin-bottom:16px; padding-bottom:16px; border-bottom:1px solid var(--line);">
|
||||
<p style="margin:0 0 6px;">
|
||||
<label style="font-size:13px; color:var(--muted); display:flex; align-items:center; gap:6px;">
|
||||
<!-- Productie -->
|
||||
<div class="env-card{% if not prod_disponibil %} inactive{% endif %}">
|
||||
<h4>Productie
|
||||
{% if prod_disponibil %}<span class="setari-badge sb-ok">configurat</span>{% else %}<span class="setari-badge sb-warn">inactiv</span>{% endif %}
|
||||
</h4>
|
||||
<label class="env-sw">
|
||||
<input type="checkbox" name="prod_enabled" value="1" {% if prod_enabled %}checked{% endif %}>
|
||||
Activare Productie
|
||||
</label>
|
||||
{% if prod_disponibil %}
|
||||
<span style="font-size:12px; color:var(--ok);">configurat</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
<p style="margin:0 0 8px;">
|
||||
<label style="font-size:13px; color:var(--muted);">Email RAR Productie</label><br>
|
||||
<input type="email" name="prod_email" style="width:100%; max-width:340px;"
|
||||
placeholder="email@service.ro">
|
||||
</p>
|
||||
<p style="margin:0 0 8px;">
|
||||
<label style="font-size:13px; color:var(--muted);">Parola RAR Productie</label><br>
|
||||
<input type="password" name="prod_parola" style="width:100%; max-width:340px;"
|
||||
autocomplete="new-password">
|
||||
</p>
|
||||
<p style="margin:0 0 8px;">
|
||||
<label style="font-size:13px; color:var(--muted); display:flex; align-items:flex-start; gap:6px;">
|
||||
<input type="checkbox" name="prod_confirmare" value="1" style="margin-top:2px; flex-shrink:0;">
|
||||
Inteleg ca trimiterile pe Productie sunt declaratii reale (L.142), finale si fara anulare.
|
||||
<label class="env-lbl">Email RAR Productie</label>
|
||||
<input type="email" name="prod_email" placeholder="email@service.ro">
|
||||
<label class="env-lbl">Parola RAR Productie</label>
|
||||
<input type="password" name="prod_parola" autocomplete="new-password">
|
||||
<label class="env-confirm">
|
||||
<input type="checkbox" name="prod_confirmare" value="1">
|
||||
<span>Inteleg ca trimiterile pe Productie sunt declaratii reale (L.142), finale si fara anulare.</span>
|
||||
</label>
|
||||
</p>
|
||||
{% if creds_prod_mesaj %}
|
||||
<div class="flash" style="margin-top:6px;">{{ creds_prod_mesaj }}</div>
|
||||
{% endif %}
|
||||
{% if creds_prod_eroare %}
|
||||
<div class="banner" style="margin-top:6px; padding:8px 12px;">{{ creds_prod_eroare }}</div>
|
||||
{% endif %}
|
||||
{% if creds_prod_mesaj %}<div class="flash" style="margin-top:6px;">{{ creds_prod_mesaj }}</div>{% endif %}
|
||||
{% if creds_prod_eroare %}<div class="banner" style="margin-top:6px; padding:8px 12px;">{{ creds_prod_eroare }}</div>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Selector mediu implicit -->
|
||||
<div style="margin-bottom:16px;">
|
||||
<label style="font-size:13px; color:var(--muted);">Mediu implicit pentru trimiteri</label><br>
|
||||
<div class="default-env">
|
||||
<label style="font-size:13px; color:var(--muted);">Mediu implicit pentru trimiteri</label>
|
||||
{% if medii_disponibile %}
|
||||
<select name="rar_env_default" style="width:100%; max-width:340px; margin-top:4px;">
|
||||
<select name="rar_env_default">
|
||||
{% for env in medii_disponibile %}
|
||||
<option value="{{ env }}"{% if env == rar_env_default %} selected{% endif %}>{{ "Testare" if env == "test" else "Productie" }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% else %}
|
||||
<p style="font-size:13px; color:var(--muted); margin:4px 0 0;">Activeaza si valideaza un mediu intai.</p>
|
||||
{% endif %}
|
||||
{% if creds_default_mesaj %}
|
||||
<div class="flash" style="margin-top:6px;">{{ creds_default_mesaj }}</div>
|
||||
{% endif %}
|
||||
{% if creds_default_eroare %}
|
||||
<div class="banner" style="margin-top:6px; padding:8px 12px;">{{ creds_default_eroare }}</div>
|
||||
<span style="font-size:13px; color:var(--muted);">Activeaza si valideaza un mediu intai.</span>
|
||||
{% endif %}
|
||||
{% if creds_default_mesaj %}<div class="flash" style="margin-top:6px; flex-basis:100%;">{{ creds_default_mesaj }}</div>{% endif %}
|
||||
{% if creds_default_eroare %}<div class="banner" style="margin-top:6px; padding:8px 12px; flex-basis:100%;">{{ creds_default_eroare }}</div>{% endif %}
|
||||
</div>
|
||||
|
||||
<button type="submit">Salveaza mediile RAR</button>
|
||||
<span style="font-size:12px; color:var(--muted); margin-left:8px;">Parolele stocate criptat, niciodata in clar.</span>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{# ============================ Sub-tab: Cheie API ============================ #}
|
||||
<div class="setari-pane" data-subpane="api" role="tabpanel"
|
||||
{% if activ_subtab|default('firma') != 'api' %}hidden{% endif %}>
|
||||
<div class="setari-zone-title">
|
||||
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><circle cx="8" cy="15" r="4"/><path d="M11 12l9-9"/><path d="M17 6l2.5 2.5M14 9l2.5 2.5"/></svg>
|
||||
Cheie API
|
||||
<span class="setari-badge {{ 'sb-ok' if are_cheie else 'sb-warn' }}">{{ 'activa' if are_cheie else 'lipsa' }}</span>
|
||||
</div>
|
||||
<p class="setari-zone-desc">
|
||||
O foloseste softul propriu / ROAAUTO ca sa trimita prezentari prin API. Se vede integral o
|
||||
singura data, la creare sau rotire.
|
||||
</p>
|
||||
|
||||
{% if api_key %}
|
||||
<div class="flash" style="margin-bottom:12px;">Cheia a fost rotita. Salveaz-o acum — nu o vei mai putea vedea.</div>
|
||||
<div class="keybox">{{ api_key }}</div>
|
||||
<button type="button" class="btn-secondary" style="margin-top:8px;"
|
||||
data-key="{{ api_key }}"
|
||||
onclick="navigator.clipboard.writeText(this.dataset.key).then(()=>this.textContent='Copiat!')">
|
||||
Copiaza cheia
|
||||
</button>
|
||||
<p style="font-size:13px; color:var(--warn); margin:10px 0 0;">
|
||||
Atentie: la urmatoarea vizita aceasta cheie dispare. Daca o pierzi, roteste din nou.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if rot_eroare %}<div class="banner" style="margin:12px 0; padding:8px 12px;">{{ rot_eroare }}</div>{% endif %}
|
||||
|
||||
<form hx-post="/cont/roteste-cheie" hx-target="#card-cont" hx-swap="outerHTML"
|
||||
style="margin-top:{% if api_key %}14px{% else %}0{% endif %};">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
<button type="submit" class="btn-warn">{{ 'Roteste cheia API' if are_cheie else 'Genereaza cheia API' }}</button>
|
||||
<span style="font-size:12px; color:var(--muted); margin-left:8px;">Cheia veche se revoca imediat.</span>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{# ========================= Sub-tab: Cont (plan + parola) ==================== #}
|
||||
<div class="setari-pane" data-subpane="cont" role="tabpanel"
|
||||
{% if activ_subtab|default('firma') != 'cont' %}hidden{% endif %}>
|
||||
|
||||
{# --- Plan curent --- #}
|
||||
{% if plan_linie is defined %}
|
||||
<div class="setari-zone-title">
|
||||
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3 3 8l9 5 9-5z"/><path d="M3 13l9 5 9-5"/></svg>
|
||||
Plan curent
|
||||
<span class="setari-badge sb-info">{{ tier_label|default('Gratuit') }}</span>
|
||||
</div>
|
||||
<div style="font-size:var(--fs-md); font-weight:600; margin-bottom:6px;
|
||||
color:{% if plan_limita_atinsa|default(false) %}var(--err){% elif plan_warn|default(false) %}var(--warn){% else %}var(--ink){% endif %};">
|
||||
{{ plan_linie }}
|
||||
</div>
|
||||
{% if plan_limita_atinsa|default(false) %}
|
||||
<p class="setari-zone-desc" style="color:var(--err);">Limita lunara a fost atinsa — trimiterile noi sunt blocate pana la inceputul lunii urmatoare.</p>
|
||||
{% elif plan_warn|default(false) %}
|
||||
<p class="setari-zone-desc" style="color:var(--warn);">Te apropii de limita lunara.</p>
|
||||
{% endif %}
|
||||
<p class="setari-zone-desc">
|
||||
Pentru mai mult volum sau import prin API, <a href="mailto:contact@romfast.ro">contacteaza-ne</a> — alocarea planurilor se face manual.
|
||||
</p>
|
||||
<hr class="setari-subzone-sep">
|
||||
{% endif %}
|
||||
|
||||
{# --- Parola de acces --- #}
|
||||
<div class="setari-zone-title">
|
||||
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="10" width="16" height="11" rx="2"/><path d="M8 10V7a4 4 0 0 1 8 0v3"/><circle cx="12" cy="15.5" r="1.2"/></svg>
|
||||
Parola de acces
|
||||
</div>
|
||||
<p class="setari-zone-desc">Parola cu care te autentifici in dashboard (separata de credentialele RAR). Minim 10 caractere.</p>
|
||||
|
||||
{% if parola_mesaj %}<div class="flash" style="margin-bottom:12px;">{{ parola_mesaj }}</div>{% endif %}
|
||||
{% if parola_eroare %}<div class="banner" style="margin-bottom:12px; padding:8px 12px;">{{ parola_eroare }}</div>{% endif %}
|
||||
|
||||
<form hx-post="/cont/schimba-parola" hx-target="#card-cont" hx-swap="outerHTML">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
<p style="margin:0 0 8px;">
|
||||
<label style="font-size:13px; color:var(--muted);">Parola actuala</label><br>
|
||||
<input type="password" name="parola_actuala" autocomplete="current-password" style="width:100%; max-width:340px;">
|
||||
</p>
|
||||
<p style="margin:0 0 8px;">
|
||||
<label style="font-size:13px; color:var(--muted);">Parola noua</label><br>
|
||||
<input type="password" name="parola_noua" autocomplete="new-password" style="width:100%; max-width:340px;">
|
||||
</p>
|
||||
<p style="margin:0 0 12px;">
|
||||
<label style="font-size:13px; color:var(--muted);">Confirma parola noua</label><br>
|
||||
<input type="password" name="parola_confirma" autocomplete="new-password" style="width:100%; max-width:340px;">
|
||||
</p>
|
||||
<button type="submit">Schimba parola</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user