Improves drag-and-drop event handling

Enhances the drag-and-drop experience for event elements by
introducing snapping to a configurable time interval and fading out
the original element upon successful drop.

This change allows users to configure the snap interval in minutes,
making it easier to align events to specific time slots.  It also
adds visual feedback by making the original event transparent during
the drag and fading it out on drop, providing a clearer indication
of the event's movement.
This commit is contained in:
Janus Knudsen 2025-08-24 21:31:52 +02:00
parent 906616fe7b
commit 457e222262

View file

@ -8,11 +8,54 @@ export class ColumnDetector {
private lastMousePosition = { x: 0, y: 0 };
private lastLoggedPosition = { x: 0, y: 0 };
private draggedClone: HTMLElement | null = null;
private originalEvent: HTMLElement | null = null;
private mouseOffset = { x: 0, y: 0 };
// Konfiguration for snap interval
private snapIntervalMinutes = 15; // 15 minutter
private hourHeightPx = 60; // Fra CSS --hour-height
private get snapDistancePx(): number {
return (this.snapIntervalMinutes / 60) * this.hourHeightPx; // 15/60 * 60 = 15px
}
constructor() {
this.init();
}
/**
* Konfigurer snap interval
*/
public setSnapInterval(minutes: number): void {
this.snapIntervalMinutes = minutes;
console.log(`Snap interval set to ${minutes} minutes (${this.snapDistancePx}px)`);
}
/**
* Fade out og fjern element fra DOM
*/
private fadeOutAndRemove(element: HTMLElement): void {
element.style.transition = 'opacity 0.3s ease-out';
element.style.opacity = '0';
setTimeout(() => {
element.remove();
}, 300);
}
/**
* Fjern "clone-" prefix fra event ID og gendan pointer events
*/
private removeClonePrefix(clone: HTMLElement): void {
const cloneId = clone.dataset.eventId;
if (cloneId && cloneId.startsWith('clone-')) {
const originalId = cloneId.replace('clone-', '');
clone.dataset.eventId = originalId;
console.log(`Removed clone prefix: ${cloneId} -> ${originalId}`);
}
// Gendan pointer events så klonen kan dragges igen
clone.style.pointerEvents = '';
}
private init(): void {
// Lyt til mouse move på hele body
@ -27,19 +70,20 @@ export class ColumnDetector {
}
private handleMouseMove(event: MouseEvent): void {
// Hvis musen er holdt nede, tjek for 25px vertikal bevægelse
// Hvis musen er holdt nede, tjek for snap interval vertikal bevægelse
if (this.isMouseDown) {
const deltaY = Math.abs(event.clientY - this.lastLoggedPosition.y);
if (deltaY >= 25) {
console.log('Mouse dragged 25px vertically:', {
if (deltaY >= this.snapDistancePx) {
console.log(`Mouse dragged ${this.snapIntervalMinutes} minutes (${this.snapDistancePx}px) vertically:`, {
from: this.lastLoggedPosition,
to: { x: event.clientX, y: event.clientY },
verticalDistance: Math.round(deltaY)
verticalDistance: Math.round(deltaY),
snapInterval: `${this.snapIntervalMinutes} minutes`
});
this.lastLoggedPosition = { x: event.clientX, y: event.clientY };
// Opdater klonens Y-position ved 25px snap (relativt til kolonne)
// Opdater klonens Y-position ved snap interval (relativt til kolonne)
if (this.draggedClone && this.draggedClone.parentElement) {
const columnRect = this.draggedClone.parentElement.getBoundingClientRect();
const relativeY = event.clientY - columnRect.top - this.mouseOffset.y;
@ -149,7 +193,12 @@ export class ColumnDetector {
// Hvis vi fandt et event, lav en clone
if (eventElement) {
// Gem reference til original event
this.originalEvent = eventElement;
this.cloneEvent(eventElement, event);
// Sæt originalen til gennemsigtig og forhindre text selection mens der trækkes
eventElement.style.opacity = '0.6';
eventElement.style.userSelect = 'none';
}
}
@ -208,12 +257,27 @@ export class ColumnDetector {
this.isMouseDown = false;
console.log('Mouse up at:', { x: event.clientX, y: event.clientY });
// Ryd op - fjern klonen (DISABLED FOR DEBUGGING)
// if (this.draggedClone) {
// this.draggedClone.remove();
// this.draggedClone = null;
// console.log('Removed clone');
// }
// Drop operationen: fade out original og remove clone suffix
if (this.originalEvent && this.draggedClone) {
// Fade out og fjern originalen
this.fadeOutAndRemove(this.originalEvent);
// Fjern clone suffix fra klonen
this.removeClonePrefix(this.draggedClone);
// Ryd op
this.originalEvent = null;
this.draggedClone = null;
console.log('Drop completed: original faded out and removed, clone became permanent');
}
// Cleanup hvis ingen drop (ingen clone var aktiv)
if (this.originalEvent && !this.draggedClone) {
this.originalEvent.style.opacity = '';
this.originalEvent.style.userSelect = '';
this.originalEvent = null;
}
}
public destroy(): void {