Skip to content

Commit

Permalink
Reorganization of dashboard util functions
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinmonisit committed Jan 6, 2025
1 parent 0ee6e57 commit 8599236
Show file tree
Hide file tree
Showing 17 changed files with 180 additions and 159 deletions.
6 changes: 3 additions & 3 deletions app/(pages)/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
'use client';

import RightPanel from '@/app/features/rightPanel/RightPanel';
import LeftPanel from '@/app/features/leftPanel/LeftPanel';
import { MiddlePanel } from '@/app/features/middlePanel/MiddlePanel';
import { coordinateGetter } from '@/app/features/middlePanel/dashboard/components/multipleContainersKeyboardCoordinates';
import { collisionDetectionStrategy as detectionStrategy } from '@/app/features/middlePanel/dashboard/helpers/logic';
import { collisionDetectionStrategy as detectionStrategy } from '@/app/features/middlePanel/dashboard/utils/dnd';
import useDragHandlers from '@/app/features/middlePanel/dashboard/helpers/hooks/useDragHandlers';
import useAuxiliaryStore from '@/lib/hooks/stores/useAuxiliaryStore';
import { useScheduleStore } from '@/lib/hooks/stores/useScheduleStore';
import { CoursesBySemesterID } from '@/types/models';
import { CollisionDetection, DndContext, KeyboardSensor, MeasuringStrategy, MouseSensor, TouchSensor, UniqueIdentifier, useSensor, useSensors } from '@dnd-kit/core';
import { useCallback, useEffect, useRef, useState } from 'react';
import LeftPanel from '@/app/features/leftPanel/LeftPanel';
import RightPanel from '@/app/features/rightPanel/RightPanel';
import { useKeyboardShortcuts } from '@/lib/hooks/useKeyboardShortcuts';

const Page: React.FC = () => {
Expand Down
76 changes: 41 additions & 35 deletions app/features/middlePanel/dashboard/ScheduleBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
} from "@dnd-kit/sortable";
import { coordinateGetter as multipleContainersCoordinateGetter } from "./components/multipleContainersKeyboardCoordinates";
import SortableItem from "./components/SortableItem";
import { getColor, dropAnimation } from "./helpers/utilities";
import useOverlayComponents from "./helpers/hooks/useOverlayComponents";
import DroppableContainer from "./components/DroppableContainer";
import { useScheduleStore } from "@/lib/hooks/stores/useScheduleStore";
Expand All @@ -27,6 +26,8 @@ import useScheduleHandlers from "./helpers/hooks/useScheduleHandlers";
import { EMPTY, PLACEHOLDER_ID } from "@/lib/constants";
import { CoursesBySemesterID } from "@/types/models";
import { Button } from "./components/ui";
import { calculateSemesterCredits, calculateRunningCredits } from "./utils/credits";
import { getColor, dropAnimation } from "./utils/dnd";

function UndoRedoControls() {
const { undo, redo, past, future } = useHistoryStore();
Expand Down Expand Up @@ -99,6 +100,7 @@ export function ScheduleBoard({

const semesterOrder = useScheduleStore((state) => state.semesterOrder);
const coursesBySemesterID = useScheduleStore((state) => state.coursesBySemesterID);
const courses = useScheduleStore((state) => state.courses);

const { recentlyMovedToNewContainer, activeID } = useAuxiliaryStore.getState();

Expand Down Expand Up @@ -151,41 +153,45 @@ export function ScheduleBoard({
<div className="flex flex-col items-center max-w-[900px] mx-auto mt-[100px]">
<UndoRedoControls />
<div className="flex flex-wrap w-full">
{semesterOrder.map((containerId) => (
<DroppableContainer
key={containerId}
id={containerId}
label={minimal ? undefined : `Column ${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) => {
{semesterOrder.map((containerId) => {
const semesterCredits = calculateSemesterCredits(coursesBySemesterID[containerId] || [], courses);
const runningCredits = calculateRunningCredits(semesterOrder, coursesBySemesterID, courses, containerId);

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>
))}
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>
);
})}
{minimal ? undefined : (
<>
<DroppableContainer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { UniqueIdentifier } from "@dnd-kit/core";
import { useSortable } from "@dnd-kit/sortable";
import { animateLayoutChanges } from "../helpers/utilities";
import { animateLayoutChanges } from "../utils/dnd";
import { ContainerProps, Container } from "./ui";
import { CSS } from "@dnd-kit/utilities";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import useMountStatus from "@/lib/hooks/useMountStatus";
import { UniqueIdentifier } from "@dnd-kit/core";
import { useSortable } from "@dnd-kit/sortable";
import { Item } from "./ui";
import { getColor } from "../helpers/utilities";
import { getColor } from "../utils/dnd";
import useScheduleHandlers from "../helpers/hooks/useScheduleHandlers";
import { useScheduleStore } from "@/lib/hooks/stores/useScheduleStore";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DragOverEvent } from '@dnd-kit/core';
import React from 'react';
import { findContainer, getNextContainerId } from '../utilities';
import { findContainer, getNextContainerId } from '../../utils/dnd';
import { arrayMove } from '@dnd-kit/sortable';
import { unstable_batchedUpdates } from 'react-dom';
import { CoursesBySemesterID, SemesterOrder } from '@/types/models';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { UniqueIdentifier } from '@dnd-kit/core';
import React from 'react';
import { Container, Item } from '../../components/ui';
import { findContainer, getIndex } from '../utilities';
import { findContainer, getIndex } from '../../utils/dnd';
import { CoursesBySemesterID } from '@/types/models';
import { useScheduleStore } from '@/lib/hooks/stores/useScheduleStore';

Expand Down
83 changes: 0 additions & 83 deletions app/features/middlePanel/dashboard/helpers/utilities.tsx

This file was deleted.

23 changes: 23 additions & 0 deletions app/features/middlePanel/dashboard/utils/credits/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { CourseID, SemesterID, Course, CoursesBySemesterID } from "@/types/models";

export function calculateSemesterCredits(courseIds: CourseID[], courses: Record<CourseID, Course>): number {
return courseIds.reduce((total: number, courseId) => {
const course = courses[courseId];
return total + (course ? course.credits : 0);
}, 0);
}

export function calculateRunningCredits(
semesterOrder: SemesterID[],
coursesBySemesterID: CoursesBySemesterID,
courses: Record<CourseID, Course>,
currentSemesterId: SemesterID
): number {
let total = 0;
for (const semesterId of semesterOrder) {
const credits = calculateSemesterCredits(coursesBySemesterID[semesterId] || [], courses);
total += credits;
if (semesterId === currentSemesterId) break;
}
return total;
}
15 changes: 15 additions & 0 deletions app/features/middlePanel/dashboard/utils/dnd/animations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { DropAnimation, defaultDropAnimationSideEffects } from "@dnd-kit/core";
import { AnimateLayoutChanges, defaultAnimateLayoutChanges } from "@dnd-kit/sortable";

export const dropAnimation: DropAnimation = {
sideEffects: defaultDropAnimationSideEffects({
styles: {
active: {
opacity: "0.5",
},
},
}),
};

export const animateLayoutChanges: AnimateLayoutChanges = (args) =>
defaultAnimateLayoutChanges({ ...args, wasDragging: true });
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { closestCenter, pointerWithin, rectIntersection, getFirstCollision, CollisionDetection, UniqueIdentifier } from "@dnd-kit/core";
import { Items } from "../types";
import { TRASH_ID } from "@/lib/constants";
import { RefObject } from "react";

type Items = Record<UniqueIdentifier, UniqueIdentifier[]>;

/**
* Custom collision detection strategy optimized for multiple containers
Expand All @@ -13,11 +15,10 @@ import { TRASH_ID } from "@/lib/constants";
export const collisionDetectionStrategy = (
args: Parameters<CollisionDetection>[0],
activeId: UniqueIdentifier | null,
lastOverId: React.MutableRefObject<UniqueIdentifier | null>,
lastOverId: RefObject<UniqueIdentifier | null>,
items: Items,
recentlyMovedToNewContainer: React.MutableRefObject<boolean> | null
recentlyMovedToNewContainer: RefObject<boolean> | null
) => {

if (recentlyMovedToNewContainer == null) {
console.error('recentlyMovedToNewContainer is null! Was it set correctly with useRef?');
return [];
Expand All @@ -44,7 +45,6 @@ export const collisionDetectionStrategy = (
if (overId != null) {
if (overId === TRASH_ID) {
// If the intersecting droppable is the trash, return early
// Remove this if you're not using trashable functionality in your app
return intersections;
}

Expand Down Expand Up @@ -80,4 +80,4 @@ export const collisionDetectionStrategy = (

// If no droppable is matched, return the last match
return lastOverId.current ? [{ id: lastOverId.current }] : [];
}
}
43 changes: 43 additions & 0 deletions app/features/middlePanel/dashboard/utils/dnd/containers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { COURSE_CREATION_CONTAINER_ID } from "@/app/features/leftPanel/courseCreation/CourseCreation";
import { CoursesBySemesterID } from "@/types/models";
import { UniqueIdentifier } from "@dnd-kit/core";

export const findContainer = (
items: CoursesBySemesterID,
id: UniqueIdentifier
) => {
if (id in items) {
return id;
}

const container = Object.keys(items).find((key) => items[key].includes(id));
return container;
};

export const getIndex = (
items: CoursesBySemesterID,
id: UniqueIdentifier
) => {
const container = findContainer(items, id);

if (container === COURSE_CREATION_CONTAINER_ID) {
return 0;
}

if (!container) {
return -1;
}

const index = items[container].indexOf(id);

return index;
}

export const getNextContainerId = (
items: CoursesBySemesterID
) => {
const containerIds = Object.keys(items);
const lastContainerId = containerIds[containerIds.length - 1];

return String.fromCharCode(lastContainerId.charCodeAt(0) + 1);
}
4 changes: 4 additions & 0 deletions app/features/middlePanel/dashboard/utils/dnd/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './animations';
export * from './collisions';
export * from './containers';
export * from './styles';
Loading

0 comments on commit 8599236

Please sign in to comment.