@@ -552,75 +676,167 @@
emailStatus.style.display = 'block';
}
- // NIP verification
- const verifyNipBtn = document.getElementById('verifyNipBtn');
- const nipInput = document.getElementById('company_nip');
- const nipStatus = document.getElementById('nipStatus');
- let nipVerified = false;
- let isNordaMember = false;
+ // ============================================
+ // Company Autocomplete with Real-time Filtering
+ // ============================================
- verifyNipBtn.addEventListener('click', function() {
- const nip = nipInput.value.trim();
+ const companySearch = document.getElementById('company_search');
+ const companyDropdown = document.getElementById('companyDropdown');
+ const companySelected = document.getElementById('companySelected');
+ const selectedCompanyName = document.getElementById('selectedCompanyName');
+ const selectedCompanyNip = document.getElementById('selectedCompanyNip');
+ const clearCompanyBtn = document.getElementById('clearCompanyBtn');
+ const nipHiddenInput = document.getElementById('company_nip');
- // Validate NIP format (10 digits)
- if (!/^\d{10}$/.test(nip)) {
- showNipStatus('error', '❌ Nieprawidłowy format NIP. Podaj 10 cyfr.');
+ let companies = []; // Will be loaded from API
+ let selectedCompany = null;
+
+ // Load companies on page load
+ loadCompanies();
+
+ async function loadCompanies() {
+ try {
+ const response = await fetch('/api/companies');
+ const data = await response.json();
+ companies = data.companies || data;
+ console.log(`Loaded ${companies.length} companies for autocomplete`);
+ } catch (error) {
+ console.error('Failed to load companies:', error);
+ companies = [];
+ }
+ }
+
+ // Filter and show dropdown on input
+ companySearch.addEventListener('input', function() {
+ const query = this.value.trim().toLowerCase();
+
+ if (query.length === 0) {
+ hideDropdown();
return;
}
- // Show loading state
- showNipStatus('loading', '⏳ Sprawdzam NIP...');
- verifyNipBtn.disabled = true;
+ // Filter companies - match anywhere in name
+ const filtered = companies.filter(company =>
+ company.name.toLowerCase().includes(query)
+ ).slice(0, 10); // Limit to 10 results
- // Get CSRF token from form
- const csrfToken = document.querySelector('input[name="csrf_token"]').value;
-
- // Call API
- fetch('/api/verify-nip', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'X-CSRFToken': csrfToken
- },
- body: JSON.stringify({ nip: nip })
- })
- .then(response => response.json())
- .then(data => {
- nipVerified = true;
- isNordaMember = data.is_member;
-
- if (data.is_member) {
- showNipStatus('norda-member',
- `✅ ${data.company_name}
Firma należy do sieci NORDA - Konto uprzywilejowane`
- );
- } else {
- showNipStatus('non-member',
- `✅ NIP zweryfikowany
Firma spoza sieci NORDA - Konto standardowe`
- );
- }
- })
- .catch(error => {
- console.error('NIP verification error:', error);
- showNipStatus('error', '❌ Błąd weryfikacji NIP. Spróbuj ponownie.');
- nipVerified = false;
- })
- .finally(() => {
- verifyNipBtn.disabled = false;
- });
+ showDropdown(filtered, query);
});
- function showNipStatus(statusClass, message) {
- nipStatus.className = 'nip-status ' + statusClass;
- nipStatus.innerHTML = '
' + message;
- nipStatus.style.display = 'flex';
- }
-
- // Clear status when NIP is modified
- nipInput.addEventListener('input', function() {
- if (nipVerified) {
- nipStatus.style.display = 'none';
- nipVerified = false;
- isNordaMember = false;
+ // Show dropdown on focus if there's text
+ companySearch.addEventListener('focus', function() {
+ if (this.value.trim().length > 0 && !selectedCompany) {
+ const query = this.value.trim().toLowerCase();
+ const filtered = companies.filter(c => c.name.toLowerCase().includes(query)).slice(0, 10);
+ showDropdown(filtered, query);
}
});
+
+ function showDropdown(filteredCompanies, query) {
+ if (filteredCompanies.length === 0) {
+ companyDropdown.innerHTML = '
Nie znaleziono firmy o nazwie "' + escapeHtml(query) + '"
';
+ companyDropdown.classList.add('show');
+ return;
+ }
+
+ companyDropdown.innerHTML = filteredCompanies.map(company => `
+
+ ${highlightMatch(company.name, query)}
+ ${company.city || ''}
+
+ `).join('');
+
+ // Add click handlers
+ companyDropdown.querySelectorAll('.company-option').forEach(option => {
+ option.addEventListener('click', function() {
+ selectCompany(this.dataset.name, this.dataset.nip);
+ });
+ });
+
+ companyDropdown.classList.add('show');
+ }
+
+ function hideDropdown() {
+ companyDropdown.classList.remove('show');
+ }
+
+ function selectCompany(name, nip) {
+ selectedCompany = { name, nip };
+
+ // Update hidden NIP field
+ nipHiddenInput.value = nip;
+
+ // Show selected company card
+ selectedCompanyName.textContent = name;
+ selectedCompanyNip.textContent = nip;
+ companySelected.style.display = 'flex';
+
+ // Hide search input and dropdown
+ companySearch.style.display = 'none';
+ hideDropdown();
+
+ console.log(`Selected company: ${name} (NIP: ${nip})`);
+ }
+
+ // Clear selection
+ clearCompanyBtn.addEventListener('click', function() {
+ selectedCompany = null;
+ nipHiddenInput.value = '';
+ companySelected.style.display = 'none';
+ companySearch.style.display = 'block';
+ companySearch.value = '';
+ companySearch.focus();
+ });
+
+ // Hide dropdown when clicking outside
+ document.addEventListener('click', function(e) {
+ if (!companySearch.contains(e.target) && !companyDropdown.contains(e.target)) {
+ hideDropdown();
+ }
+ });
+
+ // Keyboard navigation
+ companySearch.addEventListener('keydown', function(e) {
+ const options = companyDropdown.querySelectorAll('.company-option');
+ const active = companyDropdown.querySelector('.company-option:hover, .company-option.active');
+
+ if (e.key === 'ArrowDown') {
+ e.preventDefault();
+ if (options.length > 0) {
+ const next = active ? active.nextElementSibling || options[0] : options[0];
+ options.forEach(o => o.classList.remove('active'));
+ next.classList.add('active');
+ next.scrollIntoView({ block: 'nearest' });
+ }
+ } else if (e.key === 'ArrowUp') {
+ e.preventDefault();
+ if (options.length > 0) {
+ const prev = active ? active.previousElementSibling || options[options.length - 1] : options[options.length - 1];
+ options.forEach(o => o.classList.remove('active'));
+ prev.classList.add('active');
+ prev.scrollIntoView({ block: 'nearest' });
+ }
+ } else if (e.key === 'Enter') {
+ e.preventDefault();
+ const activeOption = companyDropdown.querySelector('.company-option.active');
+ if (activeOption) {
+ selectCompany(activeOption.dataset.name, activeOption.dataset.nip);
+ }
+ } else if (e.key === 'Escape') {
+ hideDropdown();
+ }
+ });
+
+ // Helper functions
+ function escapeHtml(text) {
+ const div = document.createElement('div');
+ div.textContent = text;
+ return div.innerHTML;
+ }
+
+ function highlightMatch(text, query) {
+ if (!query) return escapeHtml(text);
+ const regex = new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
+ return escapeHtml(text).replace(regex, '
$1');
+ }
{% endblock %}
diff --git a/templates/base.html b/templates/base.html
index 56586b3..14f443a 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -17,6 +17,11 @@
+
+
+
+
+
-
-
-
-