nordabiz/templates/company_edit.html
Maciej Pienczyn 2e6eca55e7
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
feat(multi-company): Allow users to be associated with multiple companies
Adds user_companies table with BEFORE/AFTER triggers to sync primary
company to users.company_id. Dashboard shows all user's companies with
edit buttons. Company edit routes accept optional company_id parameter.
Admin API endpoints for managing user-company associations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 19:13:10 +01:00

701 lines
34 KiB
HTML

{% extends "base.html" %}
{% block title %}Edytuj profil — {{ company.name }}{% endblock %}
{% block extra_css %}
<style>
.ce-container {
max-width: 860px;
margin: 0 auto;
padding: var(--spacing-md) var(--spacing-lg);
}
/* Header card */
.ce-header {
background: var(--surface, #fff);
border-radius: var(--radius-lg, 0.75rem);
padding: var(--spacing-xl);
box-shadow: var(--shadow);
margin-bottom: var(--spacing-lg);
display: flex;
align-items: center;
gap: var(--spacing-lg);
}
.ce-header-icon {
width: 56px;
height: 56px;
border-radius: 50%;
background: linear-gradient(135deg, var(--primary, #2E4872), var(--primary-light, #4a6999));
color: white;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.ce-header-icon svg { width: 28px; height: 28px; }
.ce-header-info h1 {
font-size: var(--font-size-2xl, 1.5rem);
color: var(--text-primary, #303030);
margin: 0 0 var(--spacing-xs);
}
.ce-header-info p {
color: var(--text-secondary, #464646);
margin: 0;
font-size: var(--font-size-sm);
}
.ce-header-actions {
margin-left: auto;
}
/* Main form card */
.ce-card {
background: var(--surface, #fff);
border-radius: var(--radius-lg, 0.75rem);
box-shadow: var(--shadow);
overflow: hidden;
}
/* Tabs */
.ce-tabs {
display: flex;
background: var(--background, #EDF0F5);
border-bottom: 1px solid var(--border, #e0e4eb);
overflow-x: auto;
}
.ce-tab {
display: flex;
align-items: center;
gap: var(--spacing-sm);
padding: var(--spacing-md) var(--spacing-lg);
border: none;
background: none;
cursor: pointer;
font-size: var(--font-size-sm);
font-family: var(--font-family);
color: var(--text-secondary, #464646);
white-space: nowrap;
transition: all 0.2s;
border-bottom: 3px solid transparent;
margin-bottom: -1px;
font-weight: 500;
}
.ce-tab svg { width: 18px; height: 18px; flex-shrink: 0; opacity: 0.7; }
.ce-tab:hover {
color: var(--text-primary, #303030);
background: rgba(255,255,255,0.5);
}
.ce-tab.active {
color: var(--primary, #2E4872);
background: var(--surface, #fff);
border-bottom-color: var(--primary, #2E4872);
font-weight: 600;
}
.ce-tab.active svg { opacity: 1; }
/* Tab content */
.ce-tab-content { display: none; padding: var(--spacing-xl); }
.ce-tab-content.active { display: block; }
/* Section headers inside tabs */
.ce-section-title {
font-size: var(--font-size-lg, 1.125rem);
font-weight: 600;
color: var(--text-primary, #303030);
margin: 0 0 var(--spacing-md);
padding-bottom: var(--spacing-sm);
border-bottom: 2px solid var(--primary, #2E4872);
display: inline-block;
}
/* Form overrides for this page */
.ce-card .form-group { margin-bottom: var(--spacing-lg); }
.ce-card .form-label {
display: block;
font-weight: 500;
margin-bottom: var(--spacing-sm);
color: var(--text-primary, #303030);
font-size: var(--font-size-sm);
}
.ce-card .form-input {
width: 100%;
padding: 10px 14px;
border: 1px solid var(--border, #e0e4eb);
border-radius: var(--radius, 0.5rem);
font-size: var(--font-size-base, 1rem);
font-family: var(--font-family);
transition: var(--transition);
background: var(--surface, #fff);
color: var(--text-primary, #303030);
box-sizing: border-box;
}
.ce-card .form-input:focus {
outline: none;
border-color: var(--primary, #2E4872);
box-shadow: 0 0 0 3px rgba(46, 72, 114, 0.1);
}
.ce-card .form-input:disabled {
background: var(--background, #EDF0F5);
color: var(--text-secondary);
cursor: not-allowed;
}
.ce-card select.form-input {
cursor: pointer;
appearance: auto;
}
.ce-card textarea.form-input {
resize: vertical;
min-height: 100px;
line-height: 1.6;
}
.ce-card .form-help {
font-size: var(--font-size-sm, 0.875rem);
color: var(--text-secondary, #464646);
margin-top: var(--spacing-xs);
}
.ce-card .form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--spacing-md);
}
/* Char counter */
.char-counter {
font-size: var(--font-size-sm);
color: var(--text-secondary);
text-align: right;
margin-top: var(--spacing-xs);
}
.char-counter.warning { color: var(--warning, #f59e0b); }
.char-counter.error { color: var(--error, #ef4444); }
/* Fieldset */
fieldset { border: none; padding: 0; margin: 0; }
fieldset[disabled] { opacity: 0.5; pointer-events: none; }
/* Permission warning */
.ce-no-permission {
background: #fef3c7;
border: 1px solid #fde68a;
border-radius: var(--radius);
padding: var(--spacing-md);
margin-bottom: var(--spacing-lg);
font-size: var(--font-size-sm);
color: #92400e;
display: flex;
align-items: center;
gap: var(--spacing-sm);
}
.ce-no-permission svg { width: 20px; height: 20px; flex-shrink: 0; }
/* Info box */
.ce-info-box {
background: #f0f9ff;
border: 1px solid #bae6fd;
border-radius: var(--radius);
padding: var(--spacing-md);
margin-bottom: var(--spacing-lg);
font-size: var(--font-size-sm);
color: #0369a1;
}
.ce-info-box strong { display: block; margin-bottom: var(--spacing-xs); }
.ce-info-box ul { margin: var(--spacing-xs) 0 0; padding-left: var(--spacing-lg); }
.ce-info-box li { margin-bottom: 2px; }
.ce-info-box a { color: #0369a1; font-weight: 500; }
/* Dynamic rows (contacts, social) */
.ce-dynamic-section {
margin-top: var(--spacing-lg);
padding-top: var(--spacing-lg);
border-top: 1px solid var(--border, #e0e4eb);
}
.ce-dynamic-title {
font-size: var(--font-size-base);
font-weight: 600;
color: var(--text-primary);
margin: 0 0 var(--spacing-xs);
}
.ce-dynamic-help {
font-size: var(--font-size-sm);
color: var(--text-secondary);
margin: 0 0 var(--spacing-md);
}
.contact-row, .social-row {
display: flex;
gap: var(--spacing-sm);
align-items: center;
margin-bottom: var(--spacing-sm);
padding: var(--spacing-sm);
background: var(--background, #EDF0F5);
border-radius: var(--radius);
border: 1px solid var(--border, #e0e4eb);
}
.contact-type-select, .social-platform-select { flex: 0 0 140px; }
.contact-value-input, .social-url-input { flex: 1; }
.contact-purpose-input { flex: 0 0 170px; }
.btn-remove {
flex: 0 0 36px;
height: 36px;
border: 1px solid var(--border, #e0e4eb);
background: var(--surface, #fff);
color: var(--text-secondary);
border-radius: var(--radius);
cursor: pointer;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
}
.btn-remove:hover {
background: #fee2e2;
color: #dc2626;
border-color: #fca5a5;
}
.btn-add {
display: inline-flex;
align-items: center;
gap: var(--spacing-xs);
padding: var(--spacing-sm) var(--spacing-md);
background: var(--surface, #fff);
border: 1px dashed var(--primary, #2E4872);
border-radius: var(--radius);
color: var(--primary, #2E4872);
font-size: var(--font-size-sm);
font-family: var(--font-family);
cursor: pointer;
transition: all 0.2s;
margin-top: var(--spacing-sm);
}
.btn-add:hover {
background: rgba(46, 72, 114, 0.05);
border-style: solid;
}
.btn-add svg { width: 16px; height: 16px; }
/* Social platform icon hints */
.social-row .social-platform-select { font-weight: 500; }
/* Form actions (sticky bottom) */
.ce-actions {
display: flex;
gap: var(--spacing-md);
padding: var(--spacing-lg) var(--spacing-xl);
border-top: 1px solid var(--border, #e0e4eb);
background: var(--background, #EDF0F5);
}
/* Responsive */
@media (max-width: 768px) {
.ce-header { flex-direction: column; text-align: center; }
.ce-header-actions { margin-left: 0; }
.ce-card .form-row { grid-template-columns: 1fr; }
.contact-row, .social-row { flex-wrap: wrap; }
.contact-type-select, .social-platform-select { flex: 1 1 100%; }
.contact-purpose-input { flex: 1 1 100%; }
.ce-tab { padding: var(--spacing-sm) var(--spacing-md); font-size: 13px; }
.ce-tab span.tab-label { display: none; }
}
</style>
{% endblock %}
{% block content %}
<div class="ce-container">
<!-- Header -->
<div class="ce-header">
<div class="ce-header-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
</svg>
</div>
<div class="ce-header-info">
<h1>{{ company.name }}</h1>
<p>Edytuj dane profilu firmy widoczne w katalogu Izby NORDA</p>
</div>
<div class="ce-header-actions">
<a href="{{ url_for('public.company_detail', company_id=company.id) }}" class="btn btn-outline btn-sm">
← Powrót do profilu
</a>
</div>
</div>
<!-- Main card -->
<div class="ce-card">
<!-- Tabs -->
<div class="ce-tabs">
<button type="button" class="ce-tab active" data-tab="description">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
<span class="tab-label">Opis</span>
</button>
<button type="button" class="ce-tab" data-tab="services">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>
<span class="tab-label">Usługi</span>
</button>
<button type="button" class="ce-tab" data-tab="contacts">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span class="tab-label">Kontakt</span>
</button>
<button type="button" class="ce-tab" data-tab="social">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>
<span class="tab-label">Social Media</span>
</button>
</div>
<form method="POST" action="{{ url_for('public.company_edit_save', company_id=company.id) }}" id="companyEditForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="active_tab" id="activeTabInput" value="description">
<!-- TAB 1: Opis -->
<div class="ce-tab-content active" id="tab-description">
{% if not permissions.description %}
<div class="ce-no-permission">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
Nie masz uprawnień do edycji tej sekcji. Skontaktuj się z managerem firmy.
</div>
{% endif %}
<fieldset {% if not permissions.description %}disabled{% endif %}>
<div class="form-group">
<label for="category_id" class="form-label">Kategoria działalności</label>
<select id="category_id" name="category_id" class="form-input">
<option value="">— Wybierz kategorię —</option>
{% for cat in categories %}
{% if cat.parent_id is none %}
{% set children = categories | selectattr('parent_id', 'equalto', cat.id) | list %}
{% if children %}
<optgroup label="{{ cat.name }}">
{% for sub in children %}
<option value="{{ sub.id }}" {% if company.category_id == sub.id %}selected{% endif %}>{{ sub.name }}</option>
{% endfor %}
</optgroup>
{% else %}
<option value="{{ cat.id }}" {% if company.category_id == cat.id %}selected{% endif %}>{{ cat.name }}</option>
{% endif %}
{% endif %}
{% endfor %}
</select>
<p class="form-help">Główna kategoria widoczna przy nazwie firmy w katalogu</p>
</div>
<div class="form-group">
<label for="description_short" class="form-label">Krótki opis firmy</label>
<textarea id="description_short" name="description_short" class="form-input" rows="3" maxlength="500" placeholder="Np. Specjalizujemy się w usługach IT dla firm z Pomorza...">{{ company.description_short or '' }}</textarea>
<div class="char-counter" id="shortDescCounter">
<span id="shortDescCount">{{ (company.description_short or '') | length }}</span>/500 znaków
</div>
<p class="form-help">Widoczny na liście firm i w wynikach wyszukiwania</p>
</div>
<div class="form-group">
<label for="description_full" class="form-label">Pełny opis działalności</label>
<textarea id="description_full" name="description_full" class="form-input" rows="10" placeholder="Szczegółowy opis tego czym zajmuje się firma, jakie ma doświadczenie i co ją wyróżnia...">{{ company.description_full or '' }}</textarea>
<p class="form-help">Główny opis na stronie profilu firmy. Dozwolone tagi HTML: &lt;p&gt;, &lt;strong&gt;, &lt;em&gt;, &lt;ul&gt;, &lt;li&gt;, &lt;a&gt;</p>
</div>
<div class="form-group">
<label for="founding_history" class="form-label">Historia i doświadczenie</label>
<textarea id="founding_history" name="founding_history" class="form-input" rows="5" placeholder="Kiedy firma powstała, jakie ma doświadczenie, kluczowe osiągnięcia...">{{ company.founding_history or '' }}</textarea>
</div>
<div class="form-group">
<label for="core_values" class="form-label">Wartości i misja</label>
<textarea id="core_values" name="core_values" class="form-input" rows="4" placeholder="Kluczowe wartości firmy, misja, podejście do klienta...">{{ company.core_values or '' }}</textarea>
</div>
</fieldset>
</div>
<!-- TAB 2: Usługi -->
<div class="ce-tab-content" id="tab-services">
{% if not permissions.services %}
<div class="ce-no-permission">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
Nie masz uprawnień do edycji tej sekcji. Skontaktuj się z managerem firmy.
</div>
{% endif %}
<fieldset {% if not permissions.services %}disabled{% endif %}>
<div class="form-group">
<label for="services_offered" class="form-label">Oferowane usługi i produkty</label>
<textarea id="services_offered" name="services_offered" class="form-input" rows="8" placeholder="Wymień główne usługi i produkty oferowane przez firmę...">{{ company.services_offered or '' }}</textarea>
<p class="form-help">Lista usług pomagająca klientom znaleźć Twoją firmę</p>
</div>
<div class="form-group">
<label for="technologies_used" class="form-label">Technologie i specjalizacje</label>
<textarea id="technologies_used" name="technologies_used" class="form-input" rows="4" placeholder="Używane technologie, narzędzia, certyfikaty...">{{ company.technologies_used or '' }}</textarea>
</div>
<div class="form-row">
<div class="form-group">
<label for="operational_area" class="form-label">Obszar działania</label>
<input type="text" id="operational_area" name="operational_area" class="form-input" value="{{ company.operational_area or '' }}" placeholder="np. Wejherowo, Trójmiasto, cała Polska" maxlength="500">
<p class="form-help">Gdzie firma świadczy usługi</p>
</div>
<div class="form-group">
<label for="languages_offered" class="form-label">Języki obsługi</label>
<input type="text" id="languages_offered" name="languages_offered" class="form-input" value="{{ company.languages_offered or '' }}" placeholder="np. Polski, Angielski, Niemiecki" maxlength="200">
</div>
</div>
<div class="form-group">
<label for="employee_count_range" class="form-label">Liczba pracowników</label>
<select id="employee_count_range" name="employee_count_range" class="form-input" style="max-width: 300px;">
<option value="">— Wybierz przedział —</option>
{% for range_val in ['1-5', '6-10', '11-25', '26-50', '51-100', '101-250', '250+'] %}
<option value="{{ range_val }}" {% if company.employee_count_range == range_val %}selected{% endif %}>{{ range_val }} pracowników</option>
{% endfor %}
</select>
</div>
</fieldset>
</div>
<!-- TAB 3: Kontakt -->
<div class="ce-tab-content" id="tab-contacts">
{% if not permissions.contacts %}
<div class="ce-no-permission">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
Nie masz uprawnień do edycji tej sekcji. Skontaktuj się z managerem firmy.
</div>
{% endif %}
<fieldset {% if not permissions.contacts %}disabled{% endif %}>
<span class="ce-section-title">Dane kontaktowe</span>
<div class="form-row">
<div class="form-group">
<label for="website" class="form-label">Strona internetowa</label>
<input type="url" id="website" name="website" class="form-input" value="{{ company.website or '' }}" placeholder="https://www.twojafirma.pl">
</div>
<div class="form-group">
<label for="email" class="form-label">Email firmowy</label>
<input type="email" id="email" name="email" class="form-input" value="{{ company.email or '' }}" placeholder="kontakt@twojafirma.pl">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="phone" class="form-label">Telefon główny</label>
<input type="tel" id="phone" name="phone" class="form-input" value="{{ company.phone or '' }}" placeholder="+48 58 123 45 67" maxlength="50">
</div>
<div class="form-group"></div>
</div>
<span class="ce-section-title" style="margin-top: var(--spacing-lg);">Adres siedziby</span>
<div class="form-group">
<label for="address_street" class="form-label">Ulica i numer</label>
<input type="text" id="address_street" name="address_street" class="form-input" value="{{ company.address_street or '' }}" placeholder="ul. Dworcowa 7/3" maxlength="255">
</div>
<div class="form-row">
<div class="form-group">
<label for="address_postal" class="form-label">Kod pocztowy</label>
<input type="text" id="address_postal" name="address_postal" class="form-input" value="{{ company.address_postal or '' }}" placeholder="84-200" maxlength="10" style="max-width: 150px;">
</div>
<div class="form-group">
<label for="address_city" class="form-label">Miasto</label>
<input type="text" id="address_city" name="address_city" class="form-input" value="{{ company.address_city or '' }}" placeholder="Wejherowo" maxlength="100">
</div>
</div>
<!-- Dynamic contacts -->
<div class="ce-dynamic-section">
<p class="ce-dynamic-title">Dodatkowe numery i adresy email</p>
<p class="ce-dynamic-help">Dodaj kolejne numery telefonów, adresy email lub fax z opisem przeznaczenia.</p>
<div id="contactsList">
{% for contact in contacts %}
<div class="contact-row">
<select name="contact_types[]" class="form-input contact-type-select">
<option value="phone" {% if contact.contact_type == 'phone' %}selected{% endif %}>📞 Telefon</option>
<option value="mobile" {% if contact.contact_type == 'mobile' %}selected{% endif %}>📱 Komórka</option>
<option value="email" {% if contact.contact_type == 'email' %}selected{% endif %}>✉️ Email</option>
<option value="fax" {% if contact.contact_type == 'fax' %}selected{% endif %}>📠 Fax</option>
</select>
<input type="text" name="contact_values[]" class="form-input contact-value-input" value="{{ contact.value }}" placeholder="Numer lub adres">
<input type="text" name="contact_purposes[]" class="form-input contact-purpose-input" value="{{ contact.purpose or '' }}" placeholder="np. Biuro, Sprzedaż">
<button type="button" class="btn-remove" onclick="this.parentElement.remove()" title="Usuń">&#x2715;</button>
</div>
{% endfor %}
</div>
<button type="button" class="btn-add" id="addContactBtn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
Dodaj kontakt
</button>
</div>
</fieldset>
</div>
<!-- TAB 4: Social Media -->
<div class="ce-tab-content" id="tab-social">
{% if not permissions.social %}
<div class="ce-no-permission">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
Nie masz uprawnień do edycji tej sekcji. Skontaktuj się z managerem firmy.
</div>
{% endif %}
<fieldset {% if not permissions.social %}disabled{% endif %}>
<p class="ce-dynamic-help" style="margin-top: 0;">Dodaj linki do profili firmy w mediach społecznościowych.</p>
<div id="socialList">
{% for sm in social_media %}
{% if sm.source is none or sm.source == 'manual_edit' or sm.source == 'manual' %}
<div class="social-row">
<select name="social_platforms[]" class="form-input social-platform-select">
<option value="facebook" {% if sm.platform == 'facebook' %}selected{% endif %}>Facebook</option>
<option value="linkedin" {% if sm.platform == 'linkedin' %}selected{% endif %}>LinkedIn</option>
<option value="instagram" {% if sm.platform == 'instagram' %}selected{% endif %}>Instagram</option>
<option value="youtube" {% if sm.platform == 'youtube' %}selected{% endif %}>YouTube</option>
<option value="twitter" {% if sm.platform == 'twitter' %}selected{% endif %}>X (Twitter)</option>
<option value="tiktok" {% if sm.platform == 'tiktok' %}selected{% endif %}>TikTok</option>
</select>
<input type="url" name="social_urls[]" class="form-input social-url-input" value="{{ sm.url }}" placeholder="https://facebook.com/twojafirma">
<button type="button" class="btn-remove" onclick="this.parentElement.remove()" title="Usuń">&#x2715;</button>
</div>
{% endif %}
{% endfor %}
</div>
<button type="button" class="btn-add" id="addSocialBtn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
Dodaj profil
</button>
{% set ns = namespace(has_auto=false) %}
{% for sm in social_media %}
{% if sm.source is not none and sm.source != 'manual_edit' and sm.source != 'manual' %}
{% set ns.has_auto = true %}
{% endif %}
{% endfor %}
{% if ns.has_auto %}
<div class="ce-info-box" style="margin-top: var(--spacing-lg);">
<strong>Profile wykryte automatycznie</strong>
Te profile zostały wykryte przez system i nie podlegają ręcznej edycji:
<ul>
{% for sm in social_media %}
{% if sm.source is not none and sm.source != 'manual_edit' and sm.source != 'manual' %}
<li><strong>{{ sm.platform | capitalize }}</strong>: <a href="{{ sm.url }}" target="_blank" rel="noopener">{{ sm.url | truncate(60) }}</a></li>
{% endif %}
{% endfor %}
</ul>
</div>
{% endif %}
</fieldset>
</div>
<!-- Form actions -->
<div class="ce-actions">
<button type="submit" class="btn btn-primary">
Zapisz zmiany
</button>
<a href="{{ url_for('public.company_detail', company_id=company.id) }}" class="btn btn-outline">Anuluj</a>
</div>
</form>
</div>
</div>
{% endblock %}
{% block extra_js %}
// Company Edit — tabs, dynamic fields, validation
(function() {
// Tab switching
var tabs = document.querySelectorAll('.ce-tab');
var contents = document.querySelectorAll('.ce-tab-content');
var activeTabInput = document.getElementById('activeTabInput');
tabs.forEach(function(tab) {
tab.addEventListener('click', function() {
var target = this.getAttribute('data-tab');
tabs.forEach(function(t) { t.classList.remove('active'); });
this.classList.add('active');
contents.forEach(function(c) { c.classList.remove('active'); });
document.getElementById('tab-' + target).classList.add('active');
activeTabInput.value = target;
});
});
// Character counter for short description
var shortDesc = document.getElementById('description_short');
var shortCount = document.getElementById('shortDescCount');
var shortCounter = document.getElementById('shortDescCounter');
if (shortDesc && shortCount) {
shortDesc.addEventListener('input', function() {
var len = this.value.length;
shortCount.textContent = len;
shortCounter.className = 'char-counter' + (len > 450 ? (len >= 500 ? ' error' : ' warning') : '');
});
}
// Helper: create contact row HTML
function makeContactRow() {
var row = document.createElement('div');
row.className = 'contact-row';
row.innerHTML =
'<select name="contact_types[]" class="form-input contact-type-select">' +
'<option value="phone">\uD83D\uDCDE Telefon</option>' +
'<option value="mobile">\uD83D\uDCF1 Kom\u00f3rka</option>' +
'<option value="email">\u2709\uFE0F Email</option>' +
'<option value="fax">\uD83D\uDCE0 Fax</option>' +
'</select>' +
'<input type="text" name="contact_values[]" class="form-input contact-value-input" placeholder="Numer lub adres">' +
'<input type="text" name="contact_purposes[]" class="form-input contact-purpose-input" placeholder="np. Biuro, Sprzeda\u017c">' +
'<button type="button" class="btn-remove" onclick="this.parentElement.remove()" title="Usu\u0144">\u2715</button>';
return row;
}
// Helper: create social row HTML
function makeSocialRow() {
var row = document.createElement('div');
row.className = 'social-row';
row.innerHTML =
'<select name="social_platforms[]" class="form-input social-platform-select">' +
'<option value="facebook">Facebook</option>' +
'<option value="linkedin">LinkedIn</option>' +
'<option value="instagram">Instagram</option>' +
'<option value="youtube">YouTube</option>' +
'<option value="twitter">X (Twitter)</option>' +
'<option value="tiktok">TikTok</option>' +
'</select>' +
'<input type="url" name="social_urls[]" class="form-input social-url-input" placeholder="https://...">' +
'<button type="button" class="btn-remove" onclick="this.parentElement.remove()" title="Usu\u0144">\u2715</button>';
return row;
}
// Add contact
var addContactBtn = document.getElementById('addContactBtn');
if (addContactBtn) {
addContactBtn.addEventListener('click', function() {
document.getElementById('contactsList').appendChild(makeContactRow());
});
}
// Add social
var addSocialBtn = document.getElementById('addSocialBtn');
if (addSocialBtn) {
addSocialBtn.addEventListener('click', function() {
document.getElementById('socialList').appendChild(makeSocialRow());
});
}
// Client-side validation
document.getElementById('companyEditForm').addEventListener('submit', function(e) {
var emailField = document.getElementById('email');
if (emailField && emailField.value.trim()) {
var emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (!emailPattern.test(emailField.value.trim())) {
e.preventDefault();
emailField.focus();
emailField.style.borderColor = 'var(--error, #ef4444)';
emailField.style.boxShadow = '0 0 0 3px rgba(239,68,68,0.1)';
return;
}
}
var websiteField = document.getElementById('website');
if (websiteField && websiteField.value.trim() && !websiteField.value.match(/^https?:\/\//)) {
websiteField.value = 'https://' + websiteField.value.trim();
}
});
})();
{% endblock %}