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:
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user