154 lines
4.4 KiB
TypeScript
154 lines
4.4 KiB
TypeScript
import React, { useContext, useEffect, useMemo } from "react";
|
|
import { HolderOutlined } from "@ant-design/icons";
|
|
import type { DragEndEvent } from "@dnd-kit/core";
|
|
import { DndContext } from "@dnd-kit/core";
|
|
import type { SyntheticListenerMap } from "@dnd-kit/core/dist/hooks/utilities";
|
|
import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
|
|
import {
|
|
arrayMove,
|
|
SortableContext,
|
|
useSortable,
|
|
verticalListSortingStrategy,
|
|
} from "@dnd-kit/sortable";
|
|
import { CSS } from "@dnd-kit/utilities";
|
|
import { Button, Table } from "antd";
|
|
import type { TableColumnsType } from "antd";
|
|
import { useParams } from "react-router-dom";
|
|
import { ParamsEnum } from "../../enums/params";
|
|
import { useGetAllUnit } from "../../api/unit";
|
|
|
|
interface DataType {
|
|
id: string; // Unique identifier for each row
|
|
order: number;
|
|
name: string;
|
|
age: number;
|
|
address: string;
|
|
}
|
|
|
|
interface RowContextProps {
|
|
setActivatorNodeRef?: (element: HTMLElement | null) => void;
|
|
listeners?: SyntheticListenerMap;
|
|
}
|
|
|
|
const RowContext = React.createContext<RowContextProps>({});
|
|
|
|
const DragHandle: React.FC = () => {
|
|
const { setActivatorNodeRef, listeners } = useContext(RowContext);
|
|
return (
|
|
<Button
|
|
type="text"
|
|
size="small"
|
|
icon={<HolderOutlined />}
|
|
style={{ cursor: "move" }}
|
|
ref={setActivatorNodeRef}
|
|
{...listeners}
|
|
/>
|
|
);
|
|
};
|
|
|
|
const columns: TableColumnsType<DataType> = [
|
|
{ key: "sort", align: "center", width: 80, render: () => <DragHandle /> },
|
|
{ title: "Name", dataIndex: "name" },
|
|
{ title: "Age", dataIndex: "age" },
|
|
{ title: "Address", dataIndex: "address" },
|
|
];
|
|
|
|
interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {
|
|
"data-row-key": string;
|
|
}
|
|
|
|
const Row: React.FC<RowProps> = (props) => {
|
|
const {
|
|
attributes,
|
|
listeners,
|
|
setNodeRef,
|
|
setActivatorNodeRef,
|
|
transform,
|
|
transition,
|
|
isDragging,
|
|
} = useSortable({ id: props["data-row-key"] });
|
|
|
|
const style: React.CSSProperties = {
|
|
...props.style,
|
|
transform: CSS.Translate.toString(transform),
|
|
transition,
|
|
...(isDragging ? { position: "relative", zIndex: 9999 } : {}),
|
|
};
|
|
|
|
const contextValue = useMemo<RowContextProps>(
|
|
() => ({ setActivatorNodeRef, listeners }),
|
|
[setActivatorNodeRef, listeners],
|
|
);
|
|
|
|
return (
|
|
<RowContext.Provider value={contextValue}>
|
|
<tr {...props} ref={setNodeRef} style={style} {...attributes} />
|
|
</RowContext.Provider>
|
|
);
|
|
};
|
|
|
|
const DrapableTable: React.FC = () => {
|
|
const { subject_id } = useParams<ParamsEnum>();
|
|
const response = useGetAllUnit({ subject_id: subject_id, pagination: false });
|
|
|
|
// Assuming the response contains a unique id for each item
|
|
const data =
|
|
response?.data?.data?.map((item: any, index: number) => ({
|
|
id: item.id, // Ensure this is a unique identifier
|
|
order: index + 1, // Assign order based on index
|
|
name: item.name,
|
|
age: item.age,
|
|
address: item.address,
|
|
})) ?? [];
|
|
|
|
const [dataSource, setDataSource] = React.useState<DataType[]>(data);
|
|
console.log(dataSource, "dataSource");
|
|
|
|
useEffect(() => {
|
|
// Update dataSource when the fetched data changes
|
|
const sortedData = data.sort((a: any, b: any) => a.order - b.order);
|
|
setDataSource(sortedData);
|
|
}, [response?.data?.data]);
|
|
|
|
const onDragEnd = ({ active, over }: DragEndEvent) => {
|
|
if (active.id !== over?.id) {
|
|
setDataSource((prevState) => {
|
|
const activeIndex = prevState.findIndex(
|
|
(record) => record.id === active.id,
|
|
);
|
|
const overIndex = prevState.findIndex(
|
|
(record) => record.id === over.id,
|
|
);
|
|
|
|
// Move the items in the array
|
|
const newState = arrayMove(prevState, activeIndex, overIndex);
|
|
|
|
// Update the order based on the new positions
|
|
return newState.map((item, index) => ({
|
|
...item,
|
|
order: index + 1, // Update the order based on the new index
|
|
}));
|
|
});
|
|
}
|
|
};
|
|
|
|
return (
|
|
<DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={onDragEnd}>
|
|
<SortableContext
|
|
items={dataSource.map((i) => i.id)}
|
|
strategy={verticalListSortingStrategy}
|
|
>
|
|
<Table
|
|
rowKey="id"
|
|
components={{ body: { row: Row } }}
|
|
columns={columns}
|
|
dataSource={dataSource.sort((a, b) => a.order - b.order)} // Sort by order for rendering
|
|
pagination={false}
|
|
/>
|
|
</SortableContext>
|
|
</DndContext>
|
|
);
|
|
};
|
|
|
|
export default DrapableTable;
|