diff --git a/api.php b/api.php index 235673f..6c40b6b 100644 --- a/api.php +++ b/api.php @@ -1215,12 +1215,48 @@ switch ($action) { } } + // Tallenna kysely tietokantaan + try { + _dbExecute( + "INSERT INTO availability_queries (company_id, osoite, postinumero, kaupunki, saatavilla, ip_address, user_agent, referer, created_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", + [ + $matchedCompany['id'], + $_GET['osoite'] ?? '', + $_GET['postinumero'] ?? '', + $_GET['kaupunki'] ?? '', + $found ? 1 : 0, + getClientIp(), + substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 500), + substr($_SERVER['HTTP_REFERER'] ?? '', 0, 500), + date('Y-m-d H:i:s'), + ] + ); + } catch (\Throwable $e) { /* logitus ei saa kaataa API-vastausta */ } + echo json_encode(['saatavilla' => $found]); break; + // ---------- SAATAVUUSKYSELYT ---------- + case 'availability_queries': + requireAuth(); + $companyId = requireCompanyOrParam(); + $limit = (int)($_GET['limit'] ?? 100); + $offset = (int)($_GET['offset'] ?? 0); + if ($limit > 500) $limit = 500; + + $total = (int)_dbFetchScalar("SELECT COUNT(*) FROM availability_queries WHERE company_id = ?", [$companyId]); + $rows = _dbFetchAll( + "SELECT id, osoite, postinumero, kaupunki, saatavilla, ip_address, referer, created_at + FROM availability_queries WHERE company_id = ? ORDER BY created_at DESC LIMIT ? OFFSET ?", + [$companyId, $limit, $offset] + ); + echo json_encode(['total' => $total, 'queries' => $rows]); + break; + // ---------- CONFIG (admin, yrityskohtainen) ---------- case 'config': - requireAdmin(); + requireAuth(); $companyId = requireCompany(); $globalConf = dbLoadConfig(); echo json_encode([ diff --git a/db.php b/db.php index cfeb4fb..55bd96e 100644 --- a/db.php +++ b/db.php @@ -614,6 +614,23 @@ function initDatabase(): void { UNIQUE KEY uk_company_type (company_id, type), INDEX idx_company (company_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci", + + "CREATE TABLE IF NOT EXISTS availability_queries ( + id INT AUTO_INCREMENT PRIMARY KEY, + company_id VARCHAR(50) NOT NULL, + osoite VARCHAR(255) NOT NULL, + postinumero VARCHAR(20) NOT NULL, + kaupunki VARCHAR(100) NOT NULL, + saatavilla BOOLEAN NOT NULL DEFAULT FALSE, + ip_address VARCHAR(45) DEFAULT '', + user_agent VARCHAR(500) DEFAULT '', + referer VARCHAR(500) DEFAULT '', + created_at DATETIME NOT NULL, + INDEX idx_company (company_id), + INDEX idx_created (created_at), + INDEX idx_postinumero (postinumero), + FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci", ]; foreach ($tables as $i => $sql) { diff --git a/index.html b/index.html index 19e157a..d2621f1 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ Noxus HUB - + @@ -93,6 +93,7 @@
+
@@ -189,6 +190,34 @@
+ +
+
+
+
+
+

Saatavuuskyselyt

+

Nettisivujen kautta tehdyt saatavuustarkistukset

+
+ +
+ + + + + + + + + + + + +
AikaOsoitePostinumeroKaupunkiTulosLähde
+
+
+
+
@@ -2233,6 +2262,6 @@ - + diff --git a/script.js b/script.js index 70965ae..554f68e 100644 --- a/script.js +++ b/script.js @@ -281,6 +281,8 @@ function switchToTab(target, subTab) { loadCustomers(); if (subTab === 'archive') { switchCustomerSubTab('customers-archive'); + } else if (subTab === 'availability') { + switchCustomerSubTab('customers-availability'); } else { switchCustomerSubTab('customers-list'); } @@ -3495,6 +3497,7 @@ function switchCustomerSubTab(target) { const content = document.getElementById('subtab-' + target); if (content) content.classList.add('active'); if (target === 'customers-archive') { loadArchive(); window.location.hash = 'customers/archive'; } + else if (target === 'customers-availability') { loadAvailabilityQueries(); window.location.hash = 'customers/availability'; } else { window.location.hash = 'customers'; } } @@ -3502,6 +3505,61 @@ document.querySelectorAll('#customers-sub-tab-bar .sub-tab').forEach(btn => { btn.addEventListener('click', () => switchCustomerSubTab(btn.dataset.custSubtab)); }); +// ==================== SAATAVUUSKYSELYT ==================== + +let availabilityPage = 0; +const AVAILABILITY_PER_PAGE = 50; + +async function loadAvailabilityQueries(page = 0) { + availabilityPage = page; + const offset = page * AVAILABILITY_PER_PAGE; + try { + const data = await apiCall(`availability_queries&limit=${AVAILABILITY_PER_PAGE}&offset=${offset}`); + const tbody = document.querySelector('#availability-queries-table tbody'); + const countEl = document.getElementById('availability-query-count'); + countEl.textContent = `Yhteensä ${data.total} kyselyä`; + + if (data.queries.length === 0) { + tbody.innerHTML = 'Ei vielä kyselyjä'; + } else { + tbody.innerHTML = data.queries.map(q => { + const date = q.created_at ? q.created_at.replace('T', ' ').substring(0, 16) : ''; + const found = q.saatavilla == 1; + const badge = found + ? 'Saatavilla' + : 'Ei saatavilla'; + let source = ''; + if (q.referer) { + try { source = new URL(q.referer).hostname; } catch(e) { source = q.referer.substring(0, 30); } + } + return ` + ${esc(date)} + ${esc(q.osoite)} + ${esc(q.postinumero)} + ${esc(q.kaupunki)} + ${badge} + ${esc(source)} + `; + }).join(''); + } + + // Sivutus + const totalPages = Math.ceil(data.total / AVAILABILITY_PER_PAGE); + const pagination = document.getElementById('availability-pagination'); + if (totalPages > 1) { + let pagHtml = ''; + if (page > 0) pagHtml += ``; + pagHtml += `Sivu ${page + 1} / ${totalPages}`; + if (page < totalPages - 1) pagHtml += ``; + pagination.innerHTML = pagHtml; + } else { + pagination.innerHTML = ''; + } + } catch (e) { + console.error('Saatavuuskyselyjen lataus epäonnistui:', e); + } +} + // ==================== SIJAINNIT — YHDISTETTY LAITETILOIHIN ==================== // Sites-koodi poistettu: sijainnit hallitaan nyt Laitetilat-välilehdellä.