feat: Refine month view: fade non-current month days and add auto-scroll to drop overlay

This commit is contained in:
poduck
2025-11-27 20:21:22 -05:00
parent d7cc83ebdd
commit d54d9eee6b

View File

@@ -116,6 +116,7 @@ const OwnerScheduler: React.FC<OwnerSchedulerProps> = ({ user, business }) => {
const [historyIndex, setHistoryIndex] = useState(-1); const [historyIndex, setHistoryIndex] = useState(-1);
const scrollContainerRef = useRef<HTMLDivElement>(null); const scrollContainerRef = useRef<HTMLDivElement>(null);
const overlayScrollRef = useRef<HTMLDivElement>(null); // Ref for the MonthDropOverlay's scrollable area
// Keyboard shortcuts for undo/redo // Keyboard shortcuts for undo/redo
useEffect(() => { useEffect(() => {
@@ -605,6 +606,24 @@ const OwnerScheduler: React.FC<OwnerSchedulerProps> = ({ user, business }) => {
setDraggedAppointmentId(null); setDraggedAppointmentId(null);
}; };
const handleOverlayScroll = (e: React.DragEvent) => {
if (!overlayScrollRef.current) return;
const rect = overlayScrollRef.current.getBoundingClientRect();
const mouseY = e.clientY;
const scrollThreshold = 30; // pixels from edge to start scrolling
const scrollSpeed = 10; // pixels per scroll step
if (mouseY < rect.top + scrollThreshold && overlayScrollRef.current.scrollTop > 0) {
// Scroll up
overlayScrollRef.current.scrollTop -= scrollSpeed;
} else if (mouseY > rect.bottom - scrollThreshold && overlayScrollRef.current.scrollTop < overlayScrollRef.current.scrollHeight - overlayScrollRef.current.clientHeight) {
// Scroll down
overlayScrollRef.current.scrollTop += scrollSpeed;
}
};
const handleAppointmentClick = (appointment: Appointment) => { const handleAppointmentClick = (appointment: Appointment) => {
// Only open modal if we didn't actually drag or resize // Only open modal if we didn't actually drag or resize
if (!isDragging && !isResizing) { if (!isDragging && !isResizing) {
@@ -892,7 +911,7 @@ const OwnerScheduler: React.FC<OwnerSchedulerProps> = ({ user, business }) => {
key={index} key={index}
className={`bg-white dark:bg-gray-900 min-h-[120px] p-2 transition-colors relative ${ className={`bg-white dark:bg-gray-900 min-h-[120px] p-2 transition-colors relative ${
date ? 'hover:bg-gray-50 dark:hover:bg-gray-800' : 'bg-gray-50 dark:bg-gray-800/50' date ? 'hover:bg-gray-50 dark:hover:bg-gray-800' : 'bg-gray-50 dark:bg-gray-800/50'
} ${monthDropTarget?.date.getTime() === date?.getTime() ? 'ring-2 ring-brand-500 ring-inset bg-brand-50 dark:bg-brand-900/20' : ''}`} } ${date && date.getMonth() !== viewDate.getMonth() ? 'opacity-50' : ''} ${monthDropTarget?.date.getTime() === date?.getTime() ? 'ring-2 ring-brand-500 ring-inset bg-brand-50 dark:bg-brand-900/20' : ''}`}
onClick={() => { if (date) { setViewDate(date); setViewMode('day'); } }} onClick={() => { if (date) { setViewDate(date); setViewMode('day'); } }}
onDragOver={(e) => date && handleMonthCellDragOver(e, date)} onDragOver={(e) => date && handleMonthCellDragOver(e, date)}
> >
@@ -966,7 +985,7 @@ const OwnerScheduler: React.FC<OwnerSchedulerProps> = ({ user, business }) => {
Drop in slot Drop in slot
</div> </div>
</div> </div>
<div className="flex-1 overflow-y-auto p-1 custom-scrollbar"> <div className="flex-1 overflow-y-auto p-1 custom-scrollbar" ref={overlayScrollRef} onDragOver={handleOverlayScroll}>
{Array.from({ length: END_HOUR - START_HOUR }, (_, i) => START_HOUR + i).map(hour => { {Array.from({ length: END_HOUR - START_HOUR }, (_, i) => START_HOUR + i).map(hour => {
// Check if we have conflicts (simple check) // Check if we have conflicts (simple check)
const dayStart = new Date(monthDropTarget.date); const dayStart = new Date(monthDropTarget.date);