feat: services table with dnd

This commit is contained in:
2025-10-03 09:07:02 +04:00
parent f3a0179467
commit 1a2895da59
29 changed files with 450 additions and 272 deletions

View File

@ -1,52 +0,0 @@
import { LexoRank } from "lexorank";
type LexorankSortable = {
lexorank: string;
};
export function compareByLexorank<T extends LexorankSortable>(
a: T,
b: T
): -1 | 1 | 0 {
if (a.lexorank < b.lexorank) {
return -1;
}
if (a.lexorank > b.lexorank) {
return 1;
}
return 0;
}
export function sortByLexorank<T extends LexorankSortable>(items: T[]): T[] {
return items.sort(compareByLexorank);
}
export function getMaxByLexorank<T extends LexorankSortable>(
items: T[]
): T | null {
return items.reduce(
(max, item) => (!max || item.lexorank > max.lexorank ? item : max),
null as T | null
);
}
export function getMaxLexorankByKey<T>(items: T[], key: keyof T): T | null {
return items.reduce(
(max, item) => (!max || item[key] > max[key] ? item : max),
null as T | null
);
}
export function getNewLexorank(
left?: LexoRank | null,
right?: LexoRank | null
): LexoRank {
if (right) {
if (left) return left?.between(right);
return right.between(LexoRank.min());
}
if (left) {
return left.between(LexoRank.max());
}
return LexoRank.middle();
}

View File

@ -0,0 +1,22 @@
import { LexorankSortable } from "@/utils/lexorank/types";
export function compareByLexorank<T extends LexorankSortable>(
a: T,
b: T
): -1 | 1 | 0 {
return compareByLexorankWithKey<T>(a, b, "lexorank");
}
export function compareByLexorankWithKey<T>(
a: T,
b: T,
key: keyof T
): -1 | 1 | 0 {
if (a[key] < b[key]) {
return -1;
}
if (a[key] > b[key]) {
return 1;
}
return 0;
}

View File

@ -0,0 +1,38 @@
import { LexoRank } from "lexorank";
export function getNewLexorank(
left?: LexoRank | null,
right?: LexoRank | null
): LexoRank {
if (right) {
if (left) return left?.between(right);
return right.between(LexoRank.min());
}
if (left) {
return left.between(LexoRank.max());
}
return LexoRank.middle();
}
export const getNewDndLexorank = <T>(
sourceIdx: number,
targetIdx: number,
items: T[],
key: keyof T
): string => {
let leftIndex = targetIdx;
let rightIndex = targetIdx + 1;
if (targetIdx < sourceIdx) {
leftIndex = targetIdx - 1;
rightIndex = targetIdx;
}
const leftLexorank: LexoRank | null =
leftIndex >= 0 ? LexoRank.parse(items[leftIndex][key] as string) : null;
const rightLexorank: LexoRank | null =
rightIndex < items.length
? LexoRank.parse(items[rightIndex][key] as string)
: null;
return getNewLexorank(leftLexorank, rightLexorank).toString();
};

17
src/utils/lexorank/max.ts Normal file
View File

@ -0,0 +1,17 @@
import { LexorankSortable } from "@/utils/lexorank/types";
export function getMaxByLexorank<T extends LexorankSortable>(
items: T[]
): T | null {
return items.reduce(
(max, item) => (!max || item.lexorank > max.lexorank ? item : max),
null as T | null
);
}
export function getMaxLexorankByKey<T>(items: T[], key: keyof T): T | null {
return items.reduce(
(max, item) => (!max || item[key] > max[key] ? item : max),
null as T | null
);
}

View File

@ -0,0 +1,10 @@
import { compareByLexorankWithKey } from "@/utils/lexorank/compare";
import { LexorankSortable } from "@/utils/lexorank/types";
export function sortByLexorank<T extends LexorankSortable>(items: T[]): T[] {
return sortByLexorankWithKey(items, "lexorank");
}
export function sortByLexorankWithKey<T>(items: T[], key: keyof T): T[] {
return items.sort((a, b) => compareByLexorankWithKey(a, b, key));
}

View File

@ -0,0 +1,3 @@
export type LexorankSortable = {
lexorank: string;
};