Improves scroll and interaction behavior in schedule view
Enhances dragging and clicking interactions for schedule containers - Adds drag threshold to prevent unintended scrolling - Prevents click events during dragging - Updates time badge selectors for consistent element handling Fixes potential usability issues with schedule cell interactions
This commit is contained in:
parent
531c681b7d
commit
408e590922
1 changed files with 34 additions and 10 deletions
|
|
@ -448,6 +448,7 @@ class ScheduleController {
|
|||
scrollContainers.forEach(container => {
|
||||
const el = container as HTMLElement;
|
||||
let isDown = false;
|
||||
let hasDragged = false;
|
||||
let startX = 0;
|
||||
let scrollLeft = 0;
|
||||
|
||||
|
|
@ -456,7 +457,7 @@ class ScheduleController {
|
|||
if ((e.target as HTMLElement).closest('swp-btn, input, select')) return;
|
||||
|
||||
isDown = true;
|
||||
el.classList.add('dragging');
|
||||
hasDragged = false;
|
||||
startX = e.clientX;
|
||||
scrollLeft = el.scrollLeft;
|
||||
};
|
||||
|
|
@ -464,20 +465,43 @@ class ScheduleController {
|
|||
const onMouseUp = () => {
|
||||
isDown = false;
|
||||
el.classList.remove('dragging');
|
||||
|
||||
// Reset hasDragged after a short delay to allow click events to check it
|
||||
setTimeout(() => { hasDragged = false; }, 0);
|
||||
};
|
||||
|
||||
const onMouseMove = (e: MouseEvent) => {
|
||||
if (!isDown) return;
|
||||
e.preventDefault();
|
||||
|
||||
const x = e.clientX;
|
||||
const diff = Math.abs(startX - x);
|
||||
|
||||
// Only start dragging after moving 5px (allows clicks/double-clicks)
|
||||
if (!hasDragged && diff > 5) {
|
||||
hasDragged = true;
|
||||
el.classList.add('dragging');
|
||||
}
|
||||
|
||||
if (!hasDragged) return;
|
||||
|
||||
e.preventDefault();
|
||||
const walk = (startX - x) * 1.5;
|
||||
el.scrollLeft = scrollLeft + walk;
|
||||
};
|
||||
|
||||
// Prevent click events if we just dragged
|
||||
const onClick = (e: MouseEvent) => {
|
||||
if (hasDragged) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
el.addEventListener('mousedown', onMouseDown);
|
||||
el.addEventListener('mouseup', onMouseUp);
|
||||
el.addEventListener('mouseleave', onMouseUp);
|
||||
el.addEventListener('mousemove', onMouseMove);
|
||||
el.addEventListener('click', onClick, true); // capture phase
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -741,13 +765,13 @@ class ScheduleController {
|
|||
* Prefill form from cell data
|
||||
*/
|
||||
private prefillFormFromCell(cell: HTMLElement): void {
|
||||
const timeDisplay = cell.querySelector('swp-time-display');
|
||||
if (!timeDisplay) return;
|
||||
const timeBadge = cell.querySelector('swp-time-badge');
|
||||
if (!timeBadge) return;
|
||||
|
||||
let status = 'work';
|
||||
if (timeDisplay.classList.contains('off')) status = 'off';
|
||||
else if (timeDisplay.classList.contains('vacation')) status = 'vacation';
|
||||
else if (timeDisplay.classList.contains('sick')) status = 'sick';
|
||||
if (timeBadge.classList.contains('off')) status = 'off';
|
||||
else if (timeBadge.classList.contains('vacation')) status = 'vacation';
|
||||
else if (timeBadge.classList.contains('sick')) status = 'sick';
|
||||
|
||||
// Update status options
|
||||
document.querySelectorAll('#scheduleStatusOptions swp-status-option').forEach(opt => {
|
||||
|
|
@ -760,7 +784,7 @@ class ScheduleController {
|
|||
|
||||
// Parse time if work status
|
||||
if (status === 'work') {
|
||||
const timeText = timeDisplay.textContent?.trim() || '';
|
||||
const timeText = timeBadge.textContent?.trim() || '';
|
||||
const timeMatch = timeText.match(/(\d{2}:\d{2})\s*-\s*(\d{2}:\d{2})/);
|
||||
if (timeMatch) {
|
||||
this.setTimeRange(timeMatch[1], timeMatch[2]);
|
||||
|
|
@ -1008,7 +1032,7 @@ class ScheduleController {
|
|||
const formattedTime = `${startTime} - ${endTime}`;
|
||||
|
||||
this.selectedCells.forEach(cell => {
|
||||
const timeDisplay = cell.querySelector('swp-time-display');
|
||||
const timeDisplay = cell.querySelector('swp-time-badge');
|
||||
if (timeDisplay && !timeDisplay.classList.contains('off') &&
|
||||
!timeDisplay.classList.contains('vacation') &&
|
||||
!timeDisplay.classList.contains('sick')) {
|
||||
|
|
@ -1032,7 +1056,7 @@ class ScheduleController {
|
|||
const endTime = endInput ? this.valueToTime(parseInt(endInput.value)) : '17:00';
|
||||
|
||||
this.selectedCells.forEach(cell => {
|
||||
const timeDisplay = cell.querySelector('swp-time-display');
|
||||
const timeDisplay = cell.querySelector('swp-time-badge');
|
||||
if (!timeDisplay) return;
|
||||
|
||||
timeDisplay.classList.remove('off', 'off-override', 'vacation', 'sick');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue