-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathorderable-pivot-multi-select.tsx
More file actions
95 lines (80 loc) · 2.41 KB
/
Copy pathorderable-pivot-multi-select.tsx
File metadata and controls
95 lines (80 loc) · 2.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
"use client";
import { arrayMove } from "@dnd-kit/sortable";
import { useEffect, useRef } from "react";
import type { ComponentProps } from "react";
import { MultiSelect } from "@/components/ui/multi-select";
import { calculateNewSortValue } from "@/features/abstract-resource-list";
import type { Resource } from "@/features/resources";
import type {
OrderableResource,
PivotDataDefinition,
ResourceDataType,
ResourcePk,
ResourceRelation,
} from "@/features/resources/types";
import { usePivotRelationOrderMutation } from "../hooks/use-pivot-relation-order-mutation";
import { getItemPivotOrder, hasMeta } from "../utils/get-item-pivot-order";
export function OrderablePivotMultiSelect<
T extends Resource,
L extends ResourceRelation<T>,
>({
resource,
resourceRelation,
endpoint,
pivotData,
items,
multiSelectProps,
}: {
resource: T;
resourceRelation: L;
endpoint: string;
pivotData: PivotDataDefinition;
items: ResourceDataType<L>[];
multiSelectProps: ComponentProps<typeof MultiSelect>;
}) {
const itemsRef = useRef(items);
useEffect(() => {
itemsRef.current = items;
}, [items]);
const { mutateOrder } = usePivotRelationOrderMutation({
resource,
resourceRelation,
endpoint,
});
const handleReorder = (id: string, oldIndex: number, newIndex: number) => {
const mappedItems = itemsRef.current.map((item) => ({
...item,
order: getItemPivotOrder(item) ?? 0,
})) as ResourceDataType<OrderableResource>[];
const order = calculateNewSortValue(mappedItems, oldIndex, newIndex);
const originalItem = itemsRef.current.find(
(item) => String(item.id) === id,
);
if (originalItem == null) {
return;
}
const meta = hasMeta(originalItem) ? originalItem.meta : undefined;
const pivotKey = `pivot_${pivotData.field}`;
const pivotValue = meta?.[pivotKey];
if (pivotValue == null) {
return;
}
const reorderedItems = arrayMove(itemsRef.current, oldIndex, newIndex);
itemsRef.current = reorderedItems.map((item) => {
if (String(item.id) === id) {
return {
...item,
meta: {
...(hasMeta(item) ? item.meta : {}),
pivot_order: order,
},
};
}
return item;
});
void mutateOrder(id as ResourcePk, order, {
[pivotData.field]: pivotValue,
});
};
return <MultiSelect {...multiSelectProps} onReorder={handleReorder} />;
}