feat: complete stage 2 core refactor
This commit is contained in:
102
src/hooks/useDragSort.ts
Normal file
102
src/hooks/useDragSort.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { useCallback, useMemo } from "react";
|
||||
import {
|
||||
KeyboardSensor,
|
||||
PointerSensor,
|
||||
useSensor,
|
||||
useSensors,
|
||||
type DragEndEvent,
|
||||
} from "@dnd-kit/core";
|
||||
import { arrayMove, sortableKeyboardCoordinates } from "@dnd-kit/sortable";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { Provider } from "@/types";
|
||||
import { providersApi, type AppType } from "@/lib/api";
|
||||
|
||||
export function useDragSort(
|
||||
providers: Record<string, Provider>,
|
||||
appType: AppType,
|
||||
) {
|
||||
const queryClient = useQueryClient();
|
||||
const { t, i18n } = useTranslation();
|
||||
|
||||
const sortedProviders = useMemo(() => {
|
||||
const locale = i18n.language === "zh" ? "zh-CN" : "en-US";
|
||||
return Object.values(providers).sort((a, b) => {
|
||||
if (a.sortIndex !== undefined && b.sortIndex !== undefined) {
|
||||
return a.sortIndex - b.sortIndex;
|
||||
}
|
||||
if (a.sortIndex !== undefined) return -1;
|
||||
if (b.sortIndex !== undefined) return 1;
|
||||
|
||||
const timeA = a.createdAt ?? 0;
|
||||
const timeB = b.createdAt ?? 0;
|
||||
if (timeA && timeB && timeA !== timeB) {
|
||||
return timeA - timeB;
|
||||
}
|
||||
|
||||
return a.name.localeCompare(b.name, locale);
|
||||
});
|
||||
}, [providers, i18n.language]);
|
||||
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor, {
|
||||
activationConstraint: { distance: 8 },
|
||||
}),
|
||||
useSensor(KeyboardSensor, {
|
||||
coordinateGetter: sortableKeyboardCoordinates,
|
||||
}),
|
||||
);
|
||||
|
||||
const handleDragEnd = useCallback(
|
||||
async (event: DragEndEvent) => {
|
||||
const { active, over } = event;
|
||||
if (!over || active.id === over.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldIndex = sortedProviders.findIndex(
|
||||
(provider) => provider.id === active.id,
|
||||
);
|
||||
const newIndex = sortedProviders.findIndex(
|
||||
(provider) => provider.id === over.id,
|
||||
);
|
||||
|
||||
if (oldIndex === -1 || newIndex === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const reordered = arrayMove(sortedProviders, oldIndex, newIndex);
|
||||
const updates = reordered.map((provider, index) => ({
|
||||
id: provider.id,
|
||||
sortIndex: index,
|
||||
}));
|
||||
|
||||
try {
|
||||
await providersApi.updateSortOrder(updates, appType);
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ["providers", appType],
|
||||
});
|
||||
toast.success(
|
||||
t("provider.sortUpdated", {
|
||||
defaultValue: "排序已更新",
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Failed to update provider sort order", error);
|
||||
toast.error(
|
||||
t("provider.sortUpdateFailed", {
|
||||
defaultValue: "排序更新失败",
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
[sortedProviders, appType, queryClient, t],
|
||||
);
|
||||
|
||||
return {
|
||||
sortedProviders,
|
||||
sensors,
|
||||
handleDragEnd,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user