Add profile completeness indicator and two enrichment modes
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
1. Completeness bar above buttons: "Profil 65%" with missing field list
2. Two buttons:
- "Uzupełnij brakujące" (fill mode) — only fills empty fields,
skips existing data, all results pre-checked
- "Sprawdź aktualizacje" (full mode) — shows all changes including
updates to existing fields, changes unchecked by default
3. "Uzupełnij" button hidden when profile is 100% complete
4. Backend provides profile_filled, profile_total, profile_missing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c2fc5abe6d
commit
5ca0cdd139
@ -477,6 +477,19 @@ def company_detail(company_id):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Profile completeness for AI enrichment button
|
||||
profile_fields = {
|
||||
'Opis firmy': bool(ai_insights and ai_insights.business_summary) or bool(company.description_full),
|
||||
'Usługi': bool(ai_insights and ai_insights.services_list) or bool(company.services_offered),
|
||||
'Grupa docelowa': bool(ai_insights and ai_insights.target_market),
|
||||
'Wyróżniki firmy': bool(ai_insights and ai_insights.unique_selling_points),
|
||||
'Wartości firmy': bool(ai_insights and ai_insights.company_values),
|
||||
'Tagi branżowe': bool(ai_insights and ai_insights.industry_tags),
|
||||
}
|
||||
profile_filled = sum(1 for v in profile_fields.values() if v)
|
||||
profile_total = len(profile_fields)
|
||||
profile_missing = [k for k, v in profile_fields.items() if not v]
|
||||
|
||||
# For child brands — inherit NIP from parent for display/enrichment
|
||||
effective_nip = company.nip
|
||||
if not effective_nip and company.parent_company_id:
|
||||
@ -505,6 +518,9 @@ def company_detail(company_id):
|
||||
pkd_codes=pkd_codes,
|
||||
can_enrich=can_enrich,
|
||||
can_edit_profile=can_edit_profile,
|
||||
profile_filled=profile_filled,
|
||||
profile_total=profile_total,
|
||||
profile_missing=profile_missing,
|
||||
company_managers=company_managers,
|
||||
is_admin=current_user.is_authenticated and current_user.is_admin,
|
||||
zopk_links=zopk_links,
|
||||
|
||||
@ -940,7 +940,18 @@
|
||||
|
||||
<!-- AI Enrichment Button + Edit Profile (hidden for guests) -->
|
||||
{% if not is_guest %}
|
||||
<div style="margin: var(--spacing-md) 0; display: flex; gap: var(--spacing-sm); flex-wrap: wrap; align-items: center;">
|
||||
{% if can_enrich and profile_missing %}
|
||||
<div style="margin: var(--spacing-md) 0 var(--spacing-xs) 0; font-size: 13px; color: var(--text-secondary);">
|
||||
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 4px;">
|
||||
<span style="font-weight: 600;">Profil {{ ((profile_filled / profile_total) * 100)|int }}%</span>
|
||||
<div style="flex: 1; max-width: 120px; height: 6px; background: #e5e7eb; border-radius: 3px; overflow: hidden;">
|
||||
<div style="width: {{ ((profile_filled / profile_total) * 100)|int }}%; height: 100%; background: {% if profile_filled == profile_total %}#10b981{% elif profile_filled >= profile_total / 2 %}#f59e0b{% else %}#ef4444{% endif %}; border-radius: 3px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<span style="font-size: 12px;">Brakuje: {{ profile_missing|join(', ') }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div style="margin: var(--spacing-xs) 0 var(--spacing-md) 0; display: flex; gap: var(--spacing-sm); flex-wrap: wrap; align-items: center;">
|
||||
{% if can_edit_profile %}
|
||||
<a href="{{ url_for('company_edit', company_id=company.id) }}" class="ai-enrich-btn" style="text-decoration: none;">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
@ -958,12 +969,14 @@
|
||||
Edytuj profil
|
||||
</button>
|
||||
{% endif %}
|
||||
{% if can_enrich and profile_missing %}
|
||||
<button
|
||||
id="aiEnrichBtn"
|
||||
class="ai-enrich-btn"
|
||||
data-company-id="{{ company.id }}"
|
||||
title="Przeszukamy internet i stronę WWW firmy, żeby znaleźć brakujące informacje. Wyniki pokażemy do akceptacji — nic nie zostanie zmienione bez Twojej zgody."
|
||||
{% if not can_enrich %}disabled title="Tylko administrator lub właściciel firmy może wzbogacić dane"{% endif %}
|
||||
data-mode="fill"
|
||||
title="Wypełni tylko puste pola — istniejące dane nie zostaną zmienione."
|
||||
{% if not can_enrich %}disabled{% endif %}
|
||||
>
|
||||
<span class="spinner"></span>
|
||||
<svg class="btn-text" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
@ -971,8 +984,28 @@
|
||||
<path d="M2 17l10 5 10-5"/>
|
||||
<path d="M2 12l10 5 10-5"/>
|
||||
</svg>
|
||||
<span class="btn-text">Zbierz informacje o firmie</span>
|
||||
<span class="btn-text">Uzupełnij brakujące</span>
|
||||
</button>
|
||||
{% endif %}
|
||||
{% if can_enrich %}
|
||||
<button
|
||||
id="aiEnrichFullBtn"
|
||||
class="ai-enrich-btn"
|
||||
data-company-id="{{ company.id }}"
|
||||
data-mode="full"
|
||||
style="background: linear-gradient(135deg, #475569 0%, #334155 100%);"
|
||||
title="Porówna istniejące dane z nowymi źródłami — pokażemy różnice do akceptacji."
|
||||
{% if not can_enrich %}disabled{% endif %}
|
||||
>
|
||||
<span class="spinner"></span>
|
||||
<svg class="btn-text" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
|
||||
<path d="M2 17l10 5 10-5"/>
|
||||
<path d="M2 12l10 5 10-5"/>
|
||||
</svg>
|
||||
<span class="btn-text">Sprawdź aktualizacje</span>
|
||||
</button>
|
||||
{% endif %}
|
||||
{% if is_admin %}
|
||||
<button
|
||||
id="registryEnrichBtn"
|
||||
@ -4736,7 +4769,9 @@ function finishAiEnrichment(success) {
|
||||
|
||||
function showProposalApprovalButtons(companyId, proposalId, proposedData, currentData) {
|
||||
// Update modal title
|
||||
document.getElementById('aiModalTitle').textContent = 'Znalezione informacje — wybierz co dodać';
|
||||
document.getElementById('aiModalTitle').textContent = aiEnrichMode === 'fill'
|
||||
? 'Znalezione brakujące informacje'
|
||||
: 'Znalezione informacje — wybierz co dodać';
|
||||
document.getElementById('aiCancelBtn').style.display = 'none';
|
||||
document.getElementById('aiSpinner').style.display = 'none';
|
||||
|
||||
@ -4781,6 +4816,9 @@ function showProposalApprovalButtons(companyId, proposalId, proposedData, curren
|
||||
|
||||
if (isSame) continue; // Skip unchanged fields
|
||||
|
||||
// In "fill" mode, skip fields that already have data
|
||||
if (aiEnrichMode === 'fill' && !isNew) continue;
|
||||
|
||||
fieldCount++;
|
||||
|
||||
var statusBadge = isNew
|
||||
@ -4917,11 +4955,21 @@ function showProposalApprovalButtons(companyId, proposalId, proposedData, curren
|
||||
});
|
||||
}
|
||||
|
||||
var aiEnrichMode = 'full'; // 'fill' or 'full'
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const aiEnrichBtn = document.getElementById('aiEnrichBtn');
|
||||
if (aiEnrichBtn && !aiEnrichBtn.disabled) {
|
||||
aiEnrichBtn.addEventListener('click', async function() {
|
||||
const companyId = this.dataset.companyId;
|
||||
// Bind both buttons to the same flow
|
||||
['aiEnrichBtn', 'aiEnrichFullBtn'].forEach(function(btnId) {
|
||||
var btn = document.getElementById(btnId);
|
||||
if (btn && !btn.disabled) {
|
||||
btn.addEventListener('click', function() { startAiEnrich(this); });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
async function startAiEnrich(triggerBtn) {
|
||||
const companyId = triggerBtn.dataset.companyId;
|
||||
aiEnrichMode = triggerBtn.dataset.mode || 'full';
|
||||
const companyName = '{{ company.name }}';
|
||||
|
||||
// Open modal
|
||||
@ -4995,9 +5043,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
addAiLogEntry('Blad polaczenia: ' + error.message, 'error');
|
||||
finishAiEnrichment(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Registry enrichment button handler
|
||||
const registryEnrichBtn = document.getElementById('registryEnrichBtn');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user