refactor(UserSchedule): index by a unique id rather than name (#166)

* refactor(UserSchedule): index by a unique id rather than name

* refactor: Update parameter names in schedule function jsdocs

* refactor: change more instances of .name to .id

* refactor: Fix typo in variable name and update references

* refactor: Remove console.log statement

* fix(chromatic): Update ScheduleListItem story

* refactor: remove unused eslint rule
This commit is contained in:
Razboy20
2024-03-14 23:09:04 -05:00
committed by GitHub
parent 5714ed16d7
commit 85769e9d2c
31 changed files with 182 additions and 304 deletions

View File

@@ -3,6 +3,8 @@ import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd';
import type { ReactElement } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import ExtensionRoot from '../ExtensionRoot/ExtensionRoot';
/*
* Ctrl + f dragHandleProps on PopupCourseBlock.tsx for example implementation of drag handle (two lines of code)
*/
@@ -14,13 +16,13 @@ export interface ListProps<T> {
draggables: T[];
children: (draggable: T, handleProps: DraggableProvidedDragHandleProps) => ReactElement;
onReordered: (elements: T[]) => void;
equalityCheck?: (a: T, b: T) => boolean;
itemKey: (item: T) => React.Key;
gap?: number; // Impacts the spacing between items in the list
}
function wrap<T>(draggableElements: T[]) {
return draggableElements.map((element, index) => ({
id: `id:${index}`,
function wrap<T>(draggableElements: T[], keyTransform: ListProps<T>['itemKey']) {
return draggableElements.map(element => ({
id: keyTransform(element),
content: element,
}));
}
@@ -68,20 +70,19 @@ function Item<T>(props: {
* <List draggableElements={elements} />
*/
function List<T>(props: ListProps<T>): JSX.Element {
const [items, setItems] = useState(wrap(props.draggables));
const [items, setItems] = useState(wrap(props.draggables, props.itemKey));
const equalityCheck = props.equalityCheck || ((a, b) => a === b);
const transformFunction = props.children;
useEffect(() => {
// check if the draggables content has *actually* changed
if (
props.draggables.length === items.length &&
props.draggables.every((element, index) => equalityCheck(element, items[index].content))
props.draggables.every((element, index) => props.itemKey(element) === items[index].id)
) {
return;
}
setItems(wrap(props.draggables));
setItems(wrap(props.draggables, props.itemKey));
}, [props.draggables]);
const onDragEnd: OnDragEndResponder = useCallback(
@@ -123,7 +124,9 @@ function List<T>(props: ListProps<T>): JSX.Element {
...style,
}}
>
{transformFunction(items[rubric.source.index].content, provided.dragHandleProps)}
<ExtensionRoot>
{transformFunction(items[rubric.source.index].content, provided.dragHandleProps)}
</ExtensionRoot>
</Item>
);
}}
@@ -135,7 +138,7 @@ function List<T>(props: ListProps<T>): JSX.Element {
style={{ marginBottom: `-${props.gap}px` }}
>
{items.map((item, index) => (
<Draggable key={item.id} draggableId={item.id} index={index}>
<Draggable key={item.id} draggableId={item.id.toString()} index={index}>
{draggableProvided => (
<div
ref={draggableProvided.innerRef}

View File

@@ -1,3 +1,4 @@
import type { UserSchedule } from '@shared/types/UserSchedule';
import Text from '@views/components/common/Text/Text';
import useSchedules from '@views/hooks/useSchedules';
import clsx from 'clsx';
@@ -10,7 +11,7 @@ import DragIndicatorIcon from '~icons/material-symbols/drag-indicator';
*/
export type Props = {
style?: React.CSSProperties;
name: string;
schedule: UserSchedule;
dragHandleProps?: Omit<React.HTMLAttributes<HTMLDivElement>, 'className'>;
onClick?: React.DOMAttributes<HTMLDivElement>['onClick'];
};
@@ -18,10 +19,10 @@ export type Props = {
/**
* This is a reusable dropdown component that can be used to toggle the visiblity of information
*/
export default function ScheduleListItem({ style, name, dragHandleProps, onClick }: Props): JSX.Element {
export default function ScheduleListItem({ style, schedule, dragHandleProps, onClick }: Props): JSX.Element {
const [activeSchedule] = useSchedules();
const isActive = useMemo(() => activeSchedule.name === name, [activeSchedule, name]);
const isActive = useMemo(() => activeSchedule.id === schedule.id, [activeSchedule, schedule]);
return (
<div style={{ ...style }} className='items-center rounded bg-white'>
@@ -42,7 +43,7 @@ export default function ScheduleListItem({ style, name, dragHandleProps, onClick
}
)}
/>
<Text variant='p'>{name}</Text>
<Text variant='p'>{schedule.name}</Text>
</div>
</div>
</li>