Skip to content

Commit

Permalink
Resizing panels and buggy overlay drop
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinmonisit committed Jan 6, 2025
1 parent 8599236 commit ece5177
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 64 deletions.
66 changes: 62 additions & 4 deletions app/(pages)/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ const Page: React.FC = () => {
} = useAuxiliaryStore.getState();

const recentlyMovedToNewContainerInstance = useRef(false);
const [leftWidth, setLeftWidth] = useState(250); // minimum width for left panel
const [rightWidth, setRightWidth] = useState(300); // minimum width for right panel
const [isDraggingLeft, setIsDraggingLeft] = useState(false);
const [isDraggingRight, setIsDraggingRight] = useState(false);

useEffect(() => {
setRecentlyMovedToNewContainer(recentlyMovedToNewContainerInstance);
Expand Down Expand Up @@ -72,6 +76,33 @@ const Page: React.FC = () => {
[activeID, coursesBySemesterID, recentlyMovedToNewContainer]
);

const handleMouseMove = useCallback((e: MouseEvent) => {
if (isDraggingLeft) {
const newWidth = Math.max(200, e.clientX);
setLeftWidth(newWidth);
}
if (isDraggingRight) {
const newWidth = Math.max(250, window.innerWidth - e.clientX);
setRightWidth(newWidth);
}
}, [isDraggingLeft, isDraggingRight]);

const handleMouseUp = useCallback(() => {
setIsDraggingLeft(false);
setIsDraggingRight(false);
}, []);

useEffect(() => {
if (isDraggingLeft || isDraggingRight) {
window.addEventListener('mousemove', handleMouseMove);
window.addEventListener('mouseup', handleMouseUp);
}
return () => {
window.removeEventListener('mousemove', handleMouseMove);
window.removeEventListener('mouseup', handleMouseUp);
};
}, [isDraggingLeft, isDraggingRight, handleMouseMove, handleMouseUp]);

return (
<DndContext
sensors={sensors}
Expand All @@ -87,10 +118,37 @@ const Page: React.FC = () => {
onDragCancel={handleDragCancel}
>
<h1>Dashboard Page Test</h1>
<div className="bg-gray-100 w-full h-screen flex flex-row">
<LeftPanel />
<MiddlePanel />
<RightPanel />
<div className="w-full h-screen flex flex-row relative">
{/* Left Panel */}
<div style={{ width: leftWidth, minWidth: 200 }} className="flex-shrink-0 h-full overflow-hidden">
<LeftPanel />
</div>

{/* Left Resize Handle */}
<div
className="w-1 hover:bg-blue-400 cursor-col-resize relative group"
onMouseDown={() => setIsDraggingLeft(true)}
>
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-4 h-8 bg-gray-300 rounded group-hover:bg-blue-400 opacity-0 group-hover:opacity-100 transition-opacity" />
</div>

{/* Middle Panel */}
<div className="flex-grow h-full overflow-hidden">
<MiddlePanel />
</div>

{/* Right Resize Handle */}
<div
className="w-1 hover:bg-blue-400 cursor-col-resize relative group"
onMouseDown={() => setIsDraggingRight(true)}
>
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-4 h-8 bg-gray-300 rounded group-hover:bg-blue-400 opacity-0 group-hover:opacity-100 transition-opacity" />
</div>

{/* Right Panel */}
<div style={{ width: rightWidth, minWidth: 250 }} className="flex-shrink-0 h-full overflow-hidden">
<RightPanel />
</div>
</div>
</DndContext>
);
Expand Down
2 changes: 1 addition & 1 deletion app/features/leftPanel/LeftPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import CourseCreation from "./courseCreation/CourseCreation";

export default function LeftPanel() {
return (
<div className="bg-red-100 w-1/6 h-full">
<div className="bg-white h-full w-full border-r border-gray-200">
<h1>Left Panel</h1>
<CourseCreation />
</div>
Expand Down
119 changes: 62 additions & 57 deletions app/features/middlePanel/dashboard/ScheduleBoard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import React, { useEffect } from "react";
import React, { useEffect, useRef } from "react";
import { createPortal } from "react-dom";
import {
CancelDrop,
Expand Down Expand Up @@ -103,6 +103,26 @@ export function ScheduleBoard({
const courses = useScheduleStore((state) => state.courses);

const { recentlyMovedToNewContainer, activeID } = useAuxiliaryStore.getState();
const setRecentlyMovedToNewContainer = useAuxiliaryStore((state) => state.setRecentlyMovedToNewContainer);
const moveRef = useRef(false);

useEffect(() => {
if (!moveRef.current) {
moveRef.current = true;
setRecentlyMovedToNewContainer(moveRef);
}
}, [setRecentlyMovedToNewContainer]);

useEffect(() => {
requestAnimationFrame(() => {
if (recentlyMovedToNewContainer == null) {
console.error('recentlyMovedToNewContainer is null! Was it set correctly with useRef?');
return;
}

moveRef.current = false;
});
}, [coursesBySemesterID]);

const isSortingContainer = activeID ? semesterOrder.includes(activeID) : false;
const {
Expand All @@ -123,75 +143,60 @@ export function ScheduleBoard({
handlePopulateSchedule,
} = useScheduleHandlers();

useEffect(() => {
requestAnimationFrame(() => {
if (recentlyMovedToNewContainer == null) {
console.error('recentlyMovedToNewContainer is null! Was it set correctly with useRef?');
return;
}

console.log('recentlyMovedToNewContainer.current', recentlyMovedToNewContainer.current);

recentlyMovedToNewContainer.current = false;
});
}, [coursesBySemesterID, recentlyMovedToNewContainer]);

return (
<>
<div
style={{
display: "inline-grid",
display: "flex",
flexDirection: "column",
boxSizing: "border-box",
padding: 20,
gridAutoFlow: vertical ? "row" : "column",
width: "100%",
height: "100%",
overflow: "auto"
}}
>
<SortableContext
items={[...semesterOrder, PLACEHOLDER_ID]}
strategy={rectSortingStrategy}
>
<div className="flex flex-col items-center max-w-[900px] mx-auto mt-[100px]">
<div className="flex flex-col w-full h-full">
<UndoRedoControls />
<div className="flex flex-wrap w-full">
{semesterOrder.map((containerId) => {
const semesterCredits = calculateSemesterCredits(coursesBySemesterID[containerId] || [], courses);
const runningCredits = calculateRunningCredits(semesterOrder, coursesBySemesterID, courses, containerId);

return (
<DroppableContainer
key={containerId}
id={containerId}
label={minimal ? undefined : `${containerId} (${semesterCredits} credits, Total: ${runningCredits})`}
columns={columns}
items={coursesBySemesterID[containerId]}
scrollable={scrollable}
style={containerStyle}
unstyled={minimal}
onRemove={() => handleRemove(containerId)}
>
<SortableContext items={coursesBySemesterID[containerId]} strategy={strategy}>
{coursesBySemesterID[containerId].map((value, index) => {
return (
<SortableItem
disabled={isSortingContainer}
key={value}
id={value}
index={index}
handle={handle}
style={getItemStyles}
wrapperStyle={wrapperStyle}
renderItem={renderItem}
containerId={containerId}
getIndex={(id) => {
return 0;
}}
/>
);
})}
</SortableContext>
</DroppableContainer>
);
})}
<div className="grid grid-cols-[repeat(auto-fit,minmax(330px,1fr))] gap-x-8 gap-y-4 w-full px-4">
{semesterOrder.map((containerId) => (
<DroppableContainer
key={containerId}
id={containerId}
label={minimal ? undefined : `${containerId} (${calculateSemesterCredits(coursesBySemesterID[containerId] || [], courses)} credits, Total: ${calculateRunningCredits(semesterOrder, coursesBySemesterID, courses, containerId)})`}
columns={columns}
items={coursesBySemesterID[containerId]}
scrollable={scrollable}
style={containerStyle}
unstyled={minimal}
onRemove={() => handleRemove(containerId)}
>
<SortableContext items={coursesBySemesterID[containerId]} strategy={strategy}>
{coursesBySemesterID[containerId].map((value, index) => {
return (
<SortableItem
disabled={isSortingContainer}
key={value}
id={value}
index={index}
handle={handle}
style={getItemStyles}
wrapperStyle={wrapperStyle}
renderItem={renderItem}
containerId={containerId}
getIndex={(id) => {
return 0;
}}
/>
);
})}
</SortableContext>
</DroppableContainer>
))}
{minimal ? undefined : (
<>
<DroppableContainer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Container, Item } from '../../components/ui';
import { findContainer, getIndex } from '../../utils/dnd';
import { CoursesBySemesterID } from '@/types/models';
import { useScheduleStore } from '@/lib/hooks/stores/useScheduleStore';
import { calculateSemesterCredits, calculateRunningCredits } from '../../utils/credits';

export const COLUMNS_DEPRECATED_DO_NOT_USE = 5;

Expand All @@ -16,6 +17,7 @@ export default function useOverlayComponents(
wrapperStyle: (args: any) => React.CSSProperties,
) {
const courses = useScheduleStore((state) => state.courses);
const semesterOrder = useScheduleStore((state) => state.semesterOrder);

function renderSortableItemDragOverlay(id: UniqueIdentifier) {
const courseName = courses[id]?.name ?? "Loading...";
Expand Down Expand Up @@ -44,9 +46,12 @@ export default function useOverlayComponents(
function renderContainerDragOverlay(
containerId: UniqueIdentifier,
) {
const semesterCredits = calculateSemesterCredits(items[containerId] || [], courses);
const totalCredits = calculateRunningCredits(semesterOrder, items, courses, containerId);

return (
<Container
label={`Column ${containerId}`}
label={`${containerId} (${semesterCredits} credits, Total: ${totalCredits})`}
columns={1}
style={{
height: "100%",
Expand Down
2 changes: 1 addition & 1 deletion app/features/rightPanel/RightPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default function RightPanel() {
};

return (
<div className="w-1/4 h-full bg-white border-l border-gray-200">
<div className="h-full w-full bg-white border-l border-gray-200">
{/* Tab Headers */}
<div className="flex border-b border-gray-200">
<TabButton
Expand Down

0 comments on commit ece5177

Please sign in to comment.