favourites button
This commit is contained in:
@@ -130,6 +130,55 @@
|
|||||||
color: #6c757d;
|
color: #6c757d;
|
||||||
padding: 10px 0;
|
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;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@@ -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 sizeClass = getSizeClass(template.button_size);
|
||||||
const sourceType = (template.source_type || '').toUpperCase();
|
const sourceType = (template.source_type || '').toUpperCase();
|
||||||
const iconClass = getTemplateIcon(sourceType);
|
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");
|
const btn = document.createElement("a");
|
||||||
btn.href = `import_xls2.php?id=${template.id}`;
|
btn.href = `import_xls2.php?id=${template.id}`;
|
||||||
@@ -245,17 +304,62 @@
|
|||||||
btn.setAttribute("data-source-type", sourceType);
|
btn.setAttribute("data-source-type", sourceType);
|
||||||
|
|
||||||
btn.innerHTML = `
|
btn.innerHTML = `
|
||||||
<i class="${iconClass} template-icon"></i>
|
<i class="${iconClass} template-icon"></i>
|
||||||
<span>${escapeHtml(template.button_label || 'Unnamed')}</span>
|
<span>${escapeHtml(template.button_label || 'Unnamed')}</span>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return btn;
|
const star = document.createElement("span");
|
||||||
|
star.className = "favorite-star" + (isFavorite ? " active" : "");
|
||||||
|
star.innerHTML = `<i class="bx ${isFavorite ? 'bxs-star' : 'bx-star'}"></i>`;
|
||||||
|
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) {
|
function toggleFavorite(templateId) {
|
||||||
const div = document.createElement('div');
|
const template = allTemplates.find(t => String(t.id) === String(templateId));
|
||||||
div.textContent = text;
|
if (!template) return;
|
||||||
return div.innerHTML;
|
|
||||||
|
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() {
|
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 = '') {
|
function renderTemplates(searchValue = '') {
|
||||||
clearContainers();
|
clearContainers();
|
||||||
|
|
||||||
@@ -295,9 +419,11 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
grouped[type].forEach(template => {
|
const favorites = grouped[type].filter(t => parseInt(t.is_favorite) === 1);
|
||||||
container.appendChild(createButton(template));
|
const others = grouped[type].filter(t => parseInt(t.is_favorite) !== 1);
|
||||||
});
|
|
||||||
|
renderSection(container, "★ Preferiti", favorites);
|
||||||
|
renderSection(container, "Altri", others);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
|
include('include/headscript.php');
|
||||||
require_once 'class/db-functions.php';
|
require_once 'class/db-functions.php';
|
||||||
|
|
||||||
$response = ["success" => false, "data" => [], "message" => ""];
|
$response = ["success" => false, "data" => [], "message" => ""];
|
||||||
@@ -12,11 +13,25 @@ try {
|
|||||||
throw new Exception('Database connection failed.');
|
throw new Exception('Database connection failed.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recupera solo i template attivi
|
$userId = $iduserlogin ?? 0;
|
||||||
$stmt = $pdo->query("SELECT id, button_label, button_size, button_bg_color, button_text_color, source_type
|
|
||||||
FROM excel_templates
|
// Recupera i template attivi, con flag is_favorite per l'utente corrente
|
||||||
WHERE status = 'active'
|
$stmt = $pdo->prepare("
|
||||||
ORDER BY button_label ASC");
|
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);
|
$templates = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
$response["success"] = true;
|
$response["success"] = true;
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
include('include/headscript.php');
|
||||||
|
require_once 'class/db-functions.php';
|
||||||
|
|
||||||
|
$response = ["success" => 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);
|
||||||
Reference in New Issue
Block a user