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);