diff --git a/kontakt/contact-scrape.go b/kontakt/contact-scrape.go index 5ec71b5..4805f88 100644 --- a/kontakt/contact-scrape.go +++ b/kontakt/contact-scrape.go @@ -195,15 +195,19 @@ func parseExcelFile(filename string) ([]Contact, error) { var contacts []Contact // Parse first table (A-D columns) - contacts = append(contacts, parseTable(f, sheetName)...) + contacts = append(contacts, parseTable(f, sheetName, "A", "D", 1)...) + + // Parse second table (F-H columns) + contacts = append(contacts, parseTable(f, sheetName, "F", "H", 2)...) return contacts, nil } -func parseTable(f *excelize.File, sheetName string) []Contact { +func parseTable(f *excelize.File, sheetName, startCol, endCol string, tableNum int) []Contact { var contacts []Contact var currentContact *Contact + // Get all rows in the sheet rows, err := f.GetRows(sheetName) if err != nil { log.Printf("Error getting rows: %v", err) @@ -217,23 +221,48 @@ func parseTable(f *excelize.File, sheetName string) []Contact { return nil } + // Column indices + const ( + nameCol = 0 + phoneCol = 2 + servicePhoneCol = 3 + mobileKlapkaCol = 4 + ) + for i := startRow; i < endRow; i++ { row := rows[i] - if len(row) < 5 { // Ensure we have all required columns + + // Skip if row is too short + if len(row) <= nameCol { continue } + // Check for "Aktualizace" - end of data + if len(row) > nameCol && strings.Contains(strings.ToLower(row[nameCol]), "aktualizace") { + break + } + + // Check for special formatting rows (like "*02(xx)") + if len(row) > 1 && strings.Contains(row[1], "*") { + continue + } + + // Get values from columns (new structure: name, position, phone, service phone, mobile) name := strings.TrimSpace(row[0]) position := strings.TrimSpace(row[1]) phone := strings.TrimSpace(row[2]) servicePhone := strings.TrimSpace(row[3]) - mobileKlapka := strings.TrimSpace(row[4]) + mobileKlapka := "" + if len(row) > 4 { + mobileKlapka = strings.TrimSpace(row[4]) + } // Clean phone numbers phone = cleanPhoneNumber(phone) servicePhone = cleanPhoneNumber(servicePhone) - if name != "" { + // If we have a name, create new contact + if name != "" && !strings.Contains(name, "(") { currentContact = &Contact{ Name: name, Position: position, diff --git a/kontakt/index.html b/kontakt/index.html index 90ad4dc..63b3dec 100644 --- a/kontakt/index.html +++ b/kontakt/index.html @@ -229,52 +229,26 @@ } function filterContacts() { - const searchQuery = document.getElementById('searchInput').value.toLowerCase(); + const query = document.getElementById('searchInput').value.toLowerCase().trim(); - fetch('/api/contacts') - .then(response => response.json()) - .then(data => { - // Filter both main and internal contacts - const filteredMain = data.contacts.filter(contact => - contact.name.toLowerCase().includes(searchQuery) || - (contact.position && contact.position.toLowerCase().includes(searchQuery)) || - (contact.phone && contact.phone.toLowerCase().includes(searchQuery)) || - (contact.service_phone && contact.service_phone.toLowerCase().includes(searchQuery)) - ); - - const filteredInternal = data.internal_contacts.filter(contact => - contact.name.toLowerCase().includes(searchQuery) || - (contact.position && contact.position.toLowerCase().includes(searchQuery)) || - (contact.phone && contact.phone.toLowerCase().includes(searchQuery)) || - (contact.service_phone && contact.service_phone.toLowerCase().includes(searchQuery)) - ); - - // Update display with filtered results - displayFilteredResults(filteredMain, filteredInternal, searchQuery); - }) - .catch(error => { - console.error('Error:', error); - }); - } - - function displayFilteredResults(mainContacts, internalContacts, searchQuery) { - const mainDiv = document.getElementById('contacts'); - const internalDiv = document.getElementById('internal-contacts'); - - mainDiv.innerHTML = mainContacts.map(contact => - formatContactCard(contact, searchQuery) - ).join(''); - - internalDiv.innerHTML = internalContacts.map(contact => - formatContactCard(contact, searchQuery) - ).join(''); - - // Show/hide no results message - if (mainContacts.length === 0 && internalContacts.length === 0) { - document.getElementById('noResults').classList.remove('hidden'); - } else { - document.getElementById('noResults').classList.add('hidden'); + // Apply table filter + let contacts = allContacts; + if (currentTableFilter !== 'all') { + contacts = contacts.filter(contact => contact.table == currentTableFilter); } + + // Apply search filter + if (query) { + contacts = contacts.filter(contact => + (contact.name && contact.name.toLowerCase().includes(query)) || + (contact.position && contact.position.toLowerCase().includes(query)) || + (contact.phone && contact.phone.replace(/\s/g, '').includes(query.replace(/\s/g, ''))) || + (contact.service_phone && contact.service_phone.replace(/\s/g, '').includes(query.replace(/\s/g, ''))) + ); + } + + filteredContacts = contacts; + displayContacts(filteredContacts, query); } function highlightText(text, query) { @@ -283,6 +257,28 @@ return text.replace(regex, '$1'); } + function displayContacts(contacts, searchQuery = '') { + const mainContacts = contacts.filter(contact => !contact.internal); + const internalContacts = contacts.filter(contact => contact.internal); + + const mainContactsDiv = document.getElementById('contacts'); + const internalContactsDiv = document.getElementById('internal-contacts'); + + mainContactsDiv.innerHTML = mainContacts.map(contact => + formatContactCard(contact, searchQuery) + ).join(''); + + internalContactsDiv.innerHTML = internalContacts.map(contact => + formatContactCard(contact, searchQuery) + ).join(''); + + if (mainContacts.length === 0 && internalContacts.length === 0) { + document.getElementById('noResults').classList.remove('hidden'); + } else { + document.getElementById('noResults').classList.add('hidden'); + } + } + function formatContactCard(contact, searchQuery) { const name = contact.name || 'Bez jména'; const position = contact.position || '';