Small preact-based (like React.js) project https://inga-lovinde.github.io/static/komoot-demo/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

131 lines
3.5 KiB

import { nanoid } from 'nanoid';
import { Dispatch } from 'preact/hooks';
import { reorderElements } from '../shared/collections.js';
import { Coordinates } from '../shared/types';
import { Marker, ReducerAction, ReorderMarkersParams } from './types';
const reindexMarkers = (markers: Marker[]) =>
markers.map((marker, i) => {
const newLabel = `${i + 1}`;
if (marker.label === newLabel) {
return marker;
}
return {
...marker,
label: newLabel,
};
});
export const markersReducer = (
markers: Marker[],
action: ReducerAction,
): Marker[] => {
const type = action.type;
switch (action.type) {
case 'add': {
const key = nanoid(10);
return reindexMarkers([
...markers,
{
key,
label: 'placeholder',
remove: () => action.data.remove(key),
moveUp: () => action.data.moveUp(key),
moveDown: () => action.data.moveDown(key),
coordinates: action.data.coordinates,
},
]);
}
case 'remove': {
return reindexMarkers([
...markers.filter(({ key }) => key !== action.data.key),
]);
}
case 'moveUp': {
const oldIndex = markers.findIndex(
({ key }) => key === action.data.key,
);
if (oldIndex < 1) {
return markers;
}
return reindexMarkers(
reorderElements(markers, oldIndex, oldIndex - 1),
);
}
case 'moveDown': {
const oldIndex = markers.findIndex(
({ key }) => key === action.data.key,
);
if (oldIndex < 0 || oldIndex + 1 >= markers.length) {
return markers;
}
return reindexMarkers(
reorderElements(markers, oldIndex, oldIndex + 1),
);
}
case 'reorder': {
return reindexMarkers(
reorderElements(
markers,
action.data.oldIndex,
action.data.newIndex,
),
);
}
default:
throw new Error(`Unsupported type ${type}`);
}
};
export const createChangeStateMethods = (
dispatchMarkers: Dispatch<ReducerAction>,
) => {
const reorderMarkers = ({
oldIndex,
newIndex,
}: ReorderMarkersParams): void =>
dispatchMarkers({
type: 'reorder',
data: { oldIndex, newIndex },
});
const moveMarkerUp = (key: string) =>
dispatchMarkers({
type: 'moveUp',
data: { key },
});
const moveMarkerDown = (key: string) =>
dispatchMarkers({
type: 'moveDown',
data: { key },
});
const removeMarker = (key: string) =>
dispatchMarkers({
type: 'remove',
data: { key },
});
const addMarker = (coordinates: Coordinates) =>
dispatchMarkers({
type: 'add',
data: {
coordinates,
moveUp: moveMarkerUp,
moveDown: moveMarkerDown,
remove: removeMarker,
},
});
return {
reorderMarkers,
moveMarkerUp,
moveMarkerDown,
removeMarker,
addMarker,
};
};