Files
TaskHybrid/salesbook.Shared/wwwroot/js/notifications.js
2025-09-11 16:06:19 +02:00

169 lines
5.7 KiB
JavaScript

const FIRST_THRESHOLD = 80;
const SECOND_THRESHOLD = 160;
const CLOSE_THRESHOLD = 40;
const MAX_SWIPE = 200;
let dotnetHelper;
window.initNotifications = (dotnetRef) => {
dotnetHelper = dotnetRef;
document.querySelectorAll('.row').forEach(initRow);
};
function initRow(row) {
const card = row.querySelector('.notification-card');
const btnTrash = row.querySelector('.trash-btn');
const btnRead = row.querySelector('.read-btn');
const behindRight = row.querySelector('.behind-right'); // cestino
const behindLeft = row.querySelector('.behind-left'); // mark as read
let startX = 0, currentX = 0, dragging = false;
let open = null; // "left", "right" oppure null
// inizializza nascosti
behindRight.style.visibility = "hidden";
behindLeft.style.visibility = "hidden";
// funzione di utilità → controlla se c'è unread-dot
function canMarkAsRead() {
return row.querySelector('.unread-dot') !== null;
}
card.addEventListener('pointerdown', (e) => {
if (e.pointerType === 'mouse' && e.button !== 0) return;
dragging = true;
startX = e.clientX;
card.setPointerCapture(e.pointerId);
card.style.transition = 'none';
});
card.addEventListener('pointermove', (e) => {
if (!dragging) return;
const dx = e.clientX - startX;
if (dx > 0 && !canMarkAsRead() && !open) {
currentX = 0;
return; // niente movimento
}
let translate = dx;
if (!open) {
translate = Math.max(-MAX_SWIPE, Math.min(MAX_SWIPE, dx));
} else if (open === "left") {
translate = Math.min(MAX_SWIPE, FIRST_THRESHOLD + dx);
} else if (open === "right") {
translate = Math.max(-MAX_SWIPE, -FIRST_THRESHOLD + dx);
}
currentX = translate;
card.style.transform = `translateX(${translate}px)`;
// mostra/nascondi i behind in tempo reale
if (currentX < 0) {
behindRight.style.visibility = "visible"; // cestino
behindLeft.style.visibility = "hidden";
} else if (currentX > 0) {
behindLeft.style.visibility = "visible"; // mark as read
behindRight.style.visibility = "hidden";
} else {
behindLeft.style.visibility = "hidden";
behindRight.style.visibility = "hidden";
}
});
function endDrag() {
if (!dragging) return;
dragging = false;
card.style.transition = 'transform .2s ease';
// blocca swipe destro se non consentito
if (currentX > 0 && !canMarkAsRead() && !open) {
card.style.transform = 'translateX(0)';
currentX = 0;
open = null;
behindRight.style.visibility = "hidden";
behindLeft.style.visibility = "hidden";
return;
}
// Swipe a sinistra → elimina
if (!open && currentX < 0) {
if (currentX < -SECOND_THRESHOLD) {
card.style.transform = `translateX(-${MAX_SWIPE}px)`;
setTimeout(() => removeRow(row), 200);
} else if (currentX < -FIRST_THRESHOLD) {
card.style.transform = `translateX(-${FIRST_THRESHOLD}px)`;
open = "right";
} else {
card.style.transform = 'translateX(0)';
open = null;
behindRight.style.visibility = "hidden";
behindLeft.style.visibility = "hidden";
}
}
// Swipe a destra → mark as read SOLO se consentito
else if (!open && currentX > 0) {
if (currentX > SECOND_THRESHOLD) {
card.style.transform = `translateX(${MAX_SWIPE}px)`;
setTimeout(() => markAsRead(row), 200);
} else if (currentX > FIRST_THRESHOLD) {
card.style.transform = `translateX(${FIRST_THRESHOLD}px)`;
open = "left";
} else {
card.style.transform = 'translateX(0)';
open = null;
behindRight.style.visibility = "hidden";
behindLeft.style.visibility = "hidden";
}
}
// Se già aperta, gestisci chiusura
else {
if (open === "right" && currentX > -FIRST_THRESHOLD + CLOSE_THRESHOLD) {
card.style.transform = 'translateX(0)';
open = null;
behindRight.style.visibility = "hidden";
behindLeft.style.visibility = "hidden";
} else if (open === "left" && currentX < FIRST_THRESHOLD - CLOSE_THRESHOLD) {
card.style.transform = 'translateX(0)';
open = null;
behindRight.style.visibility = "hidden";
behindLeft.style.visibility = "hidden";
} else if (open) {
card.style.transform = `translateX(${open === "right" ? -FIRST_THRESHOLD : FIRST_THRESHOLD}px)`;
}
}
}
card.addEventListener('pointerup', endDrag);
card.addEventListener('pointercancel', endDrag);
btnTrash.addEventListener('click', () => removeRow(row));
btnRead.addEventListener('click', () => markAsRead(row));
}
function removeRow(row) {
//collapseAndRemove(row);
dotnetHelper.invokeMethodAsync('Delete', row.id);
}
function markAsRead(row) {
//collapseAndRemove(row);
dotnetHelper.invokeMethodAsync('MarkAsRead', row.id);
}
function collapseAndRemove(row) {
const h = row.getBoundingClientRect().height;
row.style.height = h + 'px';
row.classList.add('collapsing');
requestAnimationFrame(() => {
row.style.opacity = '0';
row.style.marginTop = '0';
row.style.marginBottom = '0';
row.style.height = '0';
});
setTimeout(() => row.remove(), 220);
}