feat: add 'Osoby kontaktowe' section to company profile page
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
Shows portal users linked to a company with their contact details, role badges, Norda membership status, and direct messaging link. Respects individual privacy settings (show_phone, show_email). Addresses forum feedback from Jakub Bornowski (topic #18). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
80b9bf1fea
commit
9784248861
@ -241,6 +241,22 @@ def company_detail(company_id):
|
||||
Person.nazwisko
|
||||
).all()
|
||||
|
||||
# Load portal users linked to this company (for "Osoby kontaktowe" section)
|
||||
company_users = db.query(UserCompany).filter_by(
|
||||
company_id=company_id
|
||||
).join(User, UserCompany.user_id == User.id).filter(
|
||||
User.is_active == True
|
||||
).order_by(
|
||||
UserCompany.role.desc(), # MANAGER first, then EMPLOYEE
|
||||
User.name
|
||||
).all()
|
||||
# Eager-load user attributes before session close
|
||||
for uc in company_users:
|
||||
_ = uc.user.name, uc.user.email, uc.user.phone, uc.user.is_norda_member
|
||||
_ = uc.user.privacy_show_phone, uc.user.privacy_show_email
|
||||
_ = uc.user.contact_prefer_email, uc.user.contact_prefer_phone
|
||||
_ = uc.user.contact_prefer_portal, uc.user.contact_note
|
||||
|
||||
# Load GBP audit (most recent)
|
||||
gbp_audit = db.query(GBPAudit).filter_by(
|
||||
company_id=company_id
|
||||
@ -301,6 +317,7 @@ def company_detail(company_id):
|
||||
contacts=contacts,
|
||||
recommendations=recommendations,
|
||||
people=people,
|
||||
company_users=company_users,
|
||||
gbp_audit=gbp_audit,
|
||||
it_audit=it_audit,
|
||||
pkd_codes=pkd_codes,
|
||||
|
||||
@ -1520,6 +1520,84 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Osoby kontaktowe w firmie (portal users linked to company) -->
|
||||
{% set _contacts_hidden = company.is_section_hidden('company_users') %}
|
||||
{% if company_users and (not _contacts_hidden or can_edit_profile or is_admin) %}
|
||||
<div class="company-section {% if _contacts_hidden %}section-hidden{% endif %}">
|
||||
{% if _contacts_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">Osoby kontaktowe</h2>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--spacing-md);">
|
||||
{% for uc in company_users %}
|
||||
<div style="background: var(--background); border-radius: var(--radius-lg); padding: var(--spacing-lg); border: 1px solid var(--border); display: flex; flex-direction: column; gap: var(--spacing-sm);">
|
||||
{# Name + role header #}
|
||||
<div style="display: flex; align-items: center; gap: var(--spacing-sm); flex-wrap: wrap;">
|
||||
<div style="width: 40px; height: 40px; border-radius: 50%; background: linear-gradient(135deg, #3b82f6, #8b5cf6); display: flex; align-items: center; justify-content: center; flex-shrink: 0;">
|
||||
<svg width="20" height="20" fill="white" viewBox="0 0 24 24"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></svg>
|
||||
</div>
|
||||
<div style="flex: 1; min-width: 0;">
|
||||
<div style="font-weight: 600; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
{{ uc.user.name or 'Użytkownik' }}
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: var(--spacing-xs); flex-wrap: wrap; margin-top: 2px;">
|
||||
{% if uc.role == 'MANAGER' %}
|
||||
<span style="font-size: 11px; background: #dbeafe; color: #1d4ed8; padding: 2px 8px; border-radius: 4px; font-weight: 600;">Zarządzający</span>
|
||||
{% elif uc.role == 'OWNER' %}
|
||||
<span style="font-size: 11px; background: #fef3c7; color: #92400e; padding: 2px 8px; border-radius: 4px; font-weight: 600;">Właściciel</span>
|
||||
{% elif uc.role == 'EMPLOYEE' %}
|
||||
<span style="font-size: 11px; background: #f3f4f6; color: #4b5563; padding: 2px 8px; border-radius: 4px; font-weight: 600;">Pracownik</span>
|
||||
{% endif %}
|
||||
{% if uc.user.is_norda_member %}
|
||||
<span style="font-size: 11px; background: #ecfdf5; color: #065f46; padding: 2px 8px; border-radius: 4px; font-weight: 600;">Norda</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Contact details (respecting privacy) #}
|
||||
<div style="display: flex; flex-direction: column; gap: 4px; font-size: var(--font-size-sm); color: var(--text-secondary);">
|
||||
{% if uc.user.email and uc.user.privacy_show_email != False %}
|
||||
<div style="display: flex; align-items: center; gap: var(--spacing-xs);">
|
||||
<svg width="14" height="14" fill="currentColor" viewBox="0 0 24 24"><path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></svg>
|
||||
<a href="mailto:{{ uc.user.email }}" style="color: var(--primary); text-decoration: none;">{{ uc.user.email }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if uc.user.phone and uc.user.privacy_show_phone != False %}
|
||||
<div style="display: flex; align-items: center; gap: var(--spacing-xs);">
|
||||
<svg width="14" height="14" fill="currentColor" viewBox="0 0 24 24"><path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"/></svg>
|
||||
<a href="tel:{{ uc.user.phone }}" style="color: var(--primary); text-decoration: none;">{{ uc.user.phone }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if uc.user.contact_note %}
|
||||
<div style="font-size: var(--font-size-xs); color: var(--text-muted); font-style: italic; margin-top: 2px;">
|
||||
{{ uc.user.contact_note }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{# Contact preferences + message button #}
|
||||
<div style="display: flex; align-items: center; gap: var(--spacing-sm); margin-top: auto; padding-top: var(--spacing-sm); border-top: 1px solid var(--border);">
|
||||
{% if uc.user.contact_prefer_email or uc.user.contact_prefer_phone or uc.user.contact_prefer_portal %}
|
||||
<span style="font-size: var(--font-size-xs); color: var(--text-muted);">
|
||||
Preferuje:
|
||||
{% if uc.user.contact_prefer_email %}email{% endif %}
|
||||
{% if uc.user.contact_prefer_phone %}{% if uc.user.contact_prefer_email %}, {% endif %}telefon{% endif %}
|
||||
{% if uc.user.contact_prefer_portal %}{% if uc.user.contact_prefer_email or uc.user.contact_prefer_phone %}, {% endif %}portal{% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
<a href="{{ url_for('messages.messages_new', to=uc.user.id) }}" style="margin-left: auto; display: inline-flex; align-items: center; gap: 4px; font-size: var(--font-size-sm); color: var(--primary); text-decoration: none; padding: 4px 10px; border-radius: var(--radius); border: 1px solid var(--primary); transition: all 0.2s;" onmouseover="this.style.background='var(--primary)';this.style.color='white'" onmouseout="this.style.background='transparent';this.style.color='var(--primary)'">
|
||||
<svg width="14" height="14" fill="currentColor" viewBox="0 0 24 24"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z"/></svg>
|
||||
Napisz
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- DANE Z REJESTRÓW URZĘDOWYCH (CEIDG / KRS) -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
Loading…
Reference in New Issue
Block a user