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
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,
|
|
};
|
|
};
|
|
|