diff --git a/public/userarea/import_dashboard.php b/public/userarea/import_dashboard.php index cae59801..e5844379 100644 --- a/public/userarea/import_dashboard.php +++ b/public/userarea/import_dashboard.php @@ -130,6 +130,55 @@ color: #6c757d; padding: 10px 0; } + + .section-title { + font-size: 13px; + font-weight: 600; + color: #6c757d; + text-transform: uppercase; + letter-spacing: 0.5px; + width: 100%; + margin-top: 6px; + margin-bottom: 2px; + padding-bottom: 4px; + border-bottom: 1px solid #eee; + } + + .section-title:first-child { + margin-top: 0; + } + + .template-btn-wrapper { + position: relative; + display: inline-flex; + } + + .favorite-star { + position: absolute; + top: -6px; + right: -6px; + width: 22px; + height: 22px; + background: #fff; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); + font-size: 13px; + color: #ccc; + z-index: 2; + transition: color 0.15s, transform 0.15s; + } + + .favorite-star:hover { + transform: scale(1.15); + } + + .favorite-star.active { + color: #ffc107; + } @@ -231,10 +280,20 @@ } } - function createButton(template) { + function escapeHtml(text) { + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; + } + + function createButtonWrapper(template) { const sizeClass = getSizeClass(template.button_size); const sourceType = (template.source_type || '').toUpperCase(); const iconClass = getTemplateIcon(sourceType); + const isFavorite = !!parseInt(template.is_favorite); + + const wrapper = document.createElement("div"); + wrapper.className = "template-btn-wrapper"; const btn = document.createElement("a"); btn.href = `import_xls2.php?id=${template.id}`; @@ -245,17 +304,62 @@ btn.setAttribute("data-source-type", sourceType); btn.innerHTML = ` - - ${escapeHtml(template.button_label || 'Unnamed')} - `; + + ${escapeHtml(template.button_label || 'Unnamed')} + `; - return btn; + const star = document.createElement("span"); + star.className = "favorite-star" + (isFavorite ? " active" : ""); + star.innerHTML = ``; + star.setAttribute("data-template-id", template.id); + star.title = isFavorite ? "Rimuovi dai preferiti" : "Aggiungi ai preferiti"; + + star.addEventListener("click", function(e) { + e.preventDefault(); + e.stopPropagation(); + toggleFavorite(template.id); + }); + + wrapper.appendChild(btn); + wrapper.appendChild(star); + + return wrapper; } - function escapeHtml(text) { - const div = document.createElement('div'); - div.textContent = text; - return div.innerHTML; + function toggleFavorite(templateId) { + const template = allTemplates.find(t => String(t.id) === String(templateId)); + if (!template) return; + + const newState = !parseInt(template.is_favorite); + + // Optimistic update + template.is_favorite = newState ? 1 : 0; + renderTemplates(document.getElementById("searchInput").value.toLowerCase().trim()); + + fetch("toggle_template_favorite.php", { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + template_id: templateId, + is_favorite: newState + }) + }) + .then(response => response.json()) + .then(data => { + if (!data.success) { + console.error("Failed to toggle favorite:", data.message); + // Rollback in caso di errore + template.is_favorite = newState ? 0 : 1; + renderTemplates(document.getElementById("searchInput").value.toLowerCase().trim()); + } + }) + .catch(error => { + console.error("Fetch error toggling favorite:", error); + template.is_favorite = newState ? 0 : 1; + renderTemplates(document.getElementById("searchInput").value.toLowerCase().trim()); + }); } function clearContainers() { @@ -264,6 +368,26 @@ }); } + function renderSection(container, title, templates) { + if (templates.length === 0) return; + + const heading = document.createElement("div"); + heading.className = "section-title"; + heading.textContent = title; + container.appendChild(heading); + + const group = document.createElement("div"); + group.className = "template-buttons"; + group.style.marginTop = "0"; + group.style.paddingTop = "0"; + + templates.forEach(template => { + group.appendChild(createButtonWrapper(template)); + }); + + container.appendChild(group); + } + function renderTemplates(searchValue = '') { clearContainers(); @@ -295,9 +419,11 @@ return; } - grouped[type].forEach(template => { - container.appendChild(createButton(template)); - }); + const favorites = grouped[type].filter(t => parseInt(t.is_favorite) === 1); + const others = grouped[type].filter(t => parseInt(t.is_favorite) !== 1); + + renderSection(container, "★ Preferiti", favorites); + renderSection(container, "Altri", others); }); } diff --git a/public/userarea/load_active_templates.php b/public/userarea/load_active_templates.php index 29680c9b..d6d37b0d 100644 --- a/public/userarea/load_active_templates.php +++ b/public/userarea/load_active_templates.php @@ -1,5 +1,6 @@ false, "data" => [], "message" => ""]; @@ -12,11 +13,25 @@ try { throw new Exception('Database connection failed.'); } - // Recupera solo i template attivi - $stmt = $pdo->query("SELECT id, button_label, button_size, button_bg_color, button_text_color, source_type -FROM excel_templates -WHERE status = 'active' -ORDER BY button_label ASC"); + $userId = $iduserlogin ?? 0; + + // Recupera i template attivi, con flag is_favorite per l'utente corrente + $stmt = $pdo->prepare(" + SELECT + et.id, + et.button_label, + et.button_size, + et.button_bg_color, + et.button_text_color, + et.source_type, + CASE WHEN uf.id IS NOT NULL THEN 1 ELSE 0 END AS is_favorite + FROM excel_templates et + LEFT JOIN user_template_favorites uf + ON uf.template_id = et.id AND uf.user_id = :user_id + WHERE et.status = 'active' + ORDER BY et.button_label ASC + "); + $stmt->execute(['user_id' => $userId]); $templates = $stmt->fetchAll(PDO::FETCH_ASSOC); $response["success"] = true; diff --git a/public/userarea/toggle_template_favorite.php b/public/userarea/toggle_template_favorite.php new file mode 100644 index 00000000..f7a268fc --- /dev/null +++ b/public/userarea/toggle_template_favorite.php @@ -0,0 +1,53 @@ + false, "message" => ""]; + +try { + $db = DBHandlerSelect::getInstance(); + $pdo = $db->getConnection(); + + if (!$pdo) { + throw new Exception('Database connection failed.'); + } + + $userId = $iduserlogin ?? 0; + if (!$userId) { + throw new Exception('User not authenticated.'); + } + + $data = json_decode(file_get_contents('php://input'), true); + $templateId = isset($data['template_id']) ? (int)$data['template_id'] : 0; + $isFavorite = !empty($data['is_favorite']); + + if ($templateId <= 0) { + throw new Exception('Invalid template_id.'); + } + + if ($isFavorite) { + // Aggiungi ai preferiti (ignora se già presente) + $stmt = $pdo->prepare(" + INSERT INTO user_template_favorites (user_id, template_id) + VALUES (:user_id, :template_id) + ON DUPLICATE KEY UPDATE id = id + "); + $stmt->execute(['user_id' => $userId, 'template_id' => $templateId]); + } else { + // Rimuovi dai preferiti + $stmt = $pdo->prepare(" + DELETE FROM user_template_favorites + WHERE user_id = :user_id AND template_id = :template_id + "); + $stmt->execute(['user_id' => $userId, 'template_id' => $templateId]); + } + + $response["success"] = true; +} catch (PDOException $e) { + $response["message"] = "Database error: " . $e->getMessage(); +} catch (Exception $e) { + $response["message"] = "Error: " . $e->getMessage(); +} + +echo json_encode($response);