feat: raw deals dnd between statuses
This commit is contained in:
@ -3,12 +3,12 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { ScrollArea } from "@mantine/core";
|
import { ScrollArea } from "@mantine/core";
|
||||||
import Board from "@/app/deals/components/Board/Board";
|
import Board from "@/app/deals/components/Board/Board";
|
||||||
import useBoards from "@/app/deals/hooks/useBoards";
|
import { useBoardsContext } from "@/app/deals/contexts/BoardsContext";
|
||||||
import SortableDnd from "@/components/SortableDnd";
|
import SortableDnd from "@/components/SortableDnd";
|
||||||
import { BoardSchema } from "@/types/BoardSchema";
|
import { BoardSchema } from "@/types/BoardSchema";
|
||||||
|
|
||||||
const Boards = () => {
|
const Boards = () => {
|
||||||
const { boards, setBoards } = useBoards();
|
const { boards } = useBoardsContext();
|
||||||
|
|
||||||
const renderBoard = (board: BoardSchema) => {
|
const renderBoard = (board: BoardSchema) => {
|
||||||
return <Board board={board} />;
|
return <Board board={board} />;
|
||||||
|
|||||||
12
src/app/deals/components/DealCard/DealCard.tsx
Normal file
12
src/app/deals/components/DealCard/DealCard.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { Card } from "@mantine/core";
|
||||||
|
import { DealSchema } from "@/types/DealSchema";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
deal: DealSchema;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DealCard = ({ deal }: Props) => {
|
||||||
|
return <Card>{deal.name}</Card>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DealCard;
|
||||||
37
src/app/deals/components/SortableItem/SortableItem.tsx
Normal file
37
src/app/deals/components/SortableItem/SortableItem.tsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { useSortable } from "@dnd-kit/sortable";
|
||||||
|
import { CSS } from "@dnd-kit/utilities";
|
||||||
|
|
||||||
|
type SortableTaskItemProps = {
|
||||||
|
children: React.ReactNode;
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const SortableItem = ({ children, id }: SortableTaskItemProps) => {
|
||||||
|
const {
|
||||||
|
attributes,
|
||||||
|
listeners,
|
||||||
|
setNodeRef,
|
||||||
|
transform,
|
||||||
|
transition,
|
||||||
|
isDragging,
|
||||||
|
} = useSortable({ id });
|
||||||
|
|
||||||
|
const style = {
|
||||||
|
transform: CSS.Transform.toString(transform),
|
||||||
|
transition,
|
||||||
|
opacity: isDragging ? 0 : 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={setNodeRef}
|
||||||
|
style={style}
|
||||||
|
{...attributes}
|
||||||
|
{...listeners}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SortableItem;
|
||||||
48
src/app/deals/components/StatusColumn/StatusColumn.tsx
Normal file
48
src/app/deals/components/StatusColumn/StatusColumn.tsx
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { useDroppable } from "@dnd-kit/core";
|
||||||
|
import {
|
||||||
|
SortableContext,
|
||||||
|
verticalListSortingStrategy,
|
||||||
|
} from "@dnd-kit/sortable";
|
||||||
|
import { Box, Text } from "@mantine/core";
|
||||||
|
import DealCard from "@/app/deals/components/DealCard/DealCard";
|
||||||
|
import { SortableItem } from "@/components/SortableDnd/SortableItem";
|
||||||
|
import { DealSchema } from "@/types/DealSchema";
|
||||||
|
import { sortByLexorank } from "@/utils/lexorank";
|
||||||
|
|
||||||
|
type BoardSectionProps = {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
deals: DealSchema[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const StatusColumn = ({ id, title, deals }: BoardSectionProps) => {
|
||||||
|
const { setNodeRef } = useDroppable({ id });
|
||||||
|
const [sortedDeals, setSortedDeals] = useState<DealSchema[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSortedDeals(sortByLexorank(deals));
|
||||||
|
}, [deals]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box style={{ backgroundColor: "#eee", padding: 2 }}>
|
||||||
|
<Text>{title}</Text>
|
||||||
|
<SortableContext
|
||||||
|
id={id}
|
||||||
|
items={sortedDeals}
|
||||||
|
strategy={verticalListSortingStrategy}>
|
||||||
|
<div ref={setNodeRef}>
|
||||||
|
{sortedDeals.map(deal => (
|
||||||
|
<Box key={deal.id}>
|
||||||
|
<SortableItem id={deal.id}>
|
||||||
|
<DealCard deal={deal} />
|
||||||
|
</SortableItem>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</SortableContext>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StatusColumn;
|
||||||
25
src/app/deals/components/StatusColumns/StatusColumns.tsx
Normal file
25
src/app/deals/components/StatusColumns/StatusColumns.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import StatusColumnsDnd from "@/app/deals/components/StatusColumnsDnd/StatusColumnsDnd";
|
||||||
|
|
||||||
|
const StatusColumns = () => {
|
||||||
|
const onDealDragEnd = (
|
||||||
|
dealId: number,
|
||||||
|
statusId: number,
|
||||||
|
lexorank?: string
|
||||||
|
) => {
|
||||||
|
// Send request to server
|
||||||
|
console.log(
|
||||||
|
"onDealDragEnd. dealId =",
|
||||||
|
dealId,
|
||||||
|
", statusId =",
|
||||||
|
statusId,
|
||||||
|
", lexorank =",
|
||||||
|
lexorank
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return <StatusColumnsDnd onDealDragEnd={onDealDragEnd} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StatusColumns;
|
||||||
210
src/app/deals/components/StatusColumnsDnd/StatusColumnsDnd.tsx
Normal file
210
src/app/deals/components/StatusColumnsDnd/StatusColumnsDnd.tsx
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React, { FC, useState } from "react";
|
||||||
|
import {
|
||||||
|
closestCorners,
|
||||||
|
defaultDropAnimation,
|
||||||
|
DndContext,
|
||||||
|
DragOverEvent,
|
||||||
|
DragOverlay,
|
||||||
|
DragStartEvent,
|
||||||
|
KeyboardSensor,
|
||||||
|
PointerSensor,
|
||||||
|
useSensor,
|
||||||
|
useSensors,
|
||||||
|
} from "@dnd-kit/core";
|
||||||
|
import { sortableKeyboardCoordinates } from "@dnd-kit/sortable";
|
||||||
|
import { LexoRank } from "lexorank";
|
||||||
|
import { Group } from "@mantine/core";
|
||||||
|
import DealCard from "@/app/deals/components/DealCard/DealCard";
|
||||||
|
import StatusColumn from "@/app/deals/components/StatusColumn/StatusColumn";
|
||||||
|
import { useBoardsContext } from "@/app/deals/contexts/BoardsContext";
|
||||||
|
import { DealSchema } from "@/types/DealSchema";
|
||||||
|
import { getNewLexorank, sortByLexorank } from "@/utils/lexorank";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
onDealDragEnd: (
|
||||||
|
dealId: number,
|
||||||
|
statusId: number,
|
||||||
|
lexorank?: string
|
||||||
|
) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StatusColumnsDnd: FC<Props> = props => {
|
||||||
|
const { statuses, deals, setDeals } = useBoardsContext();
|
||||||
|
const [activeDealId, setActiveDealId] = useState<null | number>(null);
|
||||||
|
|
||||||
|
const sensors = useSensors(
|
||||||
|
useSensor(PointerSensor),
|
||||||
|
useSensor(KeyboardSensor, {
|
||||||
|
coordinateGetter: sortableKeyboardCoordinates,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleDragStart = ({ active }: DragStartEvent) => {
|
||||||
|
setActiveDealId(active.id as number);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusByDealId = (dealId: number) => {
|
||||||
|
const deal = deals.find(deal => deal.id === dealId);
|
||||||
|
if (!deal) return;
|
||||||
|
return statuses.find(status => status.id === deal.statusId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDragOver = ({ active, over }: DragOverEvent) => {
|
||||||
|
if (!over?.id) return;
|
||||||
|
|
||||||
|
const activeDealId = Number(active.id);
|
||||||
|
const activeStatusId = getStatusByDealId(activeDealId)?.id;
|
||||||
|
if (!activeStatusId) return;
|
||||||
|
|
||||||
|
const { overStatusId, newLexorank } = getDropTarget(
|
||||||
|
over.id,
|
||||||
|
activeDealId,
|
||||||
|
activeStatusId
|
||||||
|
);
|
||||||
|
if (!overStatusId) return;
|
||||||
|
|
||||||
|
setDeals(deals =>
|
||||||
|
deals.map(deal =>
|
||||||
|
deal.id === activeDealId
|
||||||
|
? {
|
||||||
|
...deal,
|
||||||
|
statusId: overStatusId,
|
||||||
|
rank: newLexorank || deal.rank,
|
||||||
|
}
|
||||||
|
: deal
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDropTarget = (
|
||||||
|
overId: string | number,
|
||||||
|
activeDealId: number,
|
||||||
|
activeStatusId: number
|
||||||
|
) => {
|
||||||
|
if (typeof overId === "string") {
|
||||||
|
return {
|
||||||
|
overStatusId: Number(overId.replace(/-status$/, "")),
|
||||||
|
newLexorank: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const overDealId = Number(overId);
|
||||||
|
const overStatusId = getStatusByDealId(overDealId)?.id;
|
||||||
|
|
||||||
|
if (!overStatusId || activeDealId === overDealId) {
|
||||||
|
return { overStatusId: undefined, newLexorank: undefined };
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusDeals = sortByLexorank(
|
||||||
|
deals.filter(deal => deal.statusId === overStatusId)
|
||||||
|
);
|
||||||
|
const overDealIndex = statusDeals.findIndex(
|
||||||
|
deal => deal.id === overDealId
|
||||||
|
);
|
||||||
|
|
||||||
|
let newLexorank;
|
||||||
|
if (activeStatusId === overStatusId) {
|
||||||
|
newLexorank = getNewRankForSameStatus(
|
||||||
|
statusDeals,
|
||||||
|
overDealIndex,
|
||||||
|
activeDealId
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
newLexorank = getNewRankForAnotherStatus(
|
||||||
|
statusDeals,
|
||||||
|
overDealIndex
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { overStatusId, newLexorank };
|
||||||
|
};
|
||||||
|
|
||||||
|
const getNewRankForSameStatus = (
|
||||||
|
statusDeals: DealSchema[],
|
||||||
|
overDealIndex: number,
|
||||||
|
activeDealId: number
|
||||||
|
) => {
|
||||||
|
const activeDealIndex = statusDeals.findIndex(
|
||||||
|
deal => deal.id === activeDealId
|
||||||
|
);
|
||||||
|
const [leftIndex, rightIndex] =
|
||||||
|
overDealIndex < activeDealIndex
|
||||||
|
? [overDealIndex - 1, overDealIndex]
|
||||||
|
: [overDealIndex, overDealIndex + 1];
|
||||||
|
|
||||||
|
const leftLexorank =
|
||||||
|
leftIndex >= 0 ? LexoRank.parse(deals[leftIndex].rank) : null;
|
||||||
|
const rightLexorank =
|
||||||
|
rightIndex < deals.length
|
||||||
|
? LexoRank.parse(deals[rightIndex].rank)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return getNewLexorank(leftLexorank, rightLexorank).toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getNewRankForAnotherStatus = (
|
||||||
|
statusDeals: DealSchema[],
|
||||||
|
overDealIndex: number
|
||||||
|
) => {
|
||||||
|
const leftLexorank =
|
||||||
|
overDealIndex > 0
|
||||||
|
? LexoRank.parse(statusDeals[overDealIndex - 1].rank)
|
||||||
|
: null;
|
||||||
|
const rightLexorank = LexoRank.parse(statusDeals[overDealIndex].rank);
|
||||||
|
|
||||||
|
return getNewLexorank(leftLexorank, rightLexorank).toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDragEnd = ({ active, over }: DragOverEvent) => {
|
||||||
|
setActiveDealId(null);
|
||||||
|
if (!over?.id) return;
|
||||||
|
|
||||||
|
const activeDealId = Number(active.id);
|
||||||
|
const activeStatusId = getStatusByDealId(activeDealId)?.id;
|
||||||
|
if (!activeStatusId) return;
|
||||||
|
|
||||||
|
const { overStatusId, newLexorank } = getDropTarget(
|
||||||
|
over.id,
|
||||||
|
activeDealId,
|
||||||
|
activeStatusId
|
||||||
|
);
|
||||||
|
if (!overStatusId) return;
|
||||||
|
|
||||||
|
props.onDealDragEnd(activeDealId, overStatusId, newLexorank);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deal = activeDealId
|
||||||
|
? deals.find(deal => deal.id === activeDealId)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DndContext
|
||||||
|
sensors={sensors}
|
||||||
|
collisionDetection={closestCorners}
|
||||||
|
onDragStart={handleDragStart}
|
||||||
|
onDragOver={handleDragOver}
|
||||||
|
onDragEnd={handleDragEnd}>
|
||||||
|
<Group
|
||||||
|
gap={"xs"}
|
||||||
|
justify={"start"}>
|
||||||
|
{statuses.map(status => (
|
||||||
|
<StatusColumn
|
||||||
|
key={status.id}
|
||||||
|
id={`${status.id}-status`}
|
||||||
|
title={status.name}
|
||||||
|
deals={deals.filter(
|
||||||
|
deal => deal.statusId === status.id
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<DragOverlay dropAnimation={defaultDropAnimation}>
|
||||||
|
{deal ? <DealCard deal={deal} /> : null}
|
||||||
|
</DragOverlay>
|
||||||
|
</Group>
|
||||||
|
</DndContext>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StatusColumnsDnd;
|
||||||
92
src/app/deals/contexts/BoardsContext.tsx
Normal file
92
src/app/deals/contexts/BoardsContext.tsx
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React, {
|
||||||
|
createContext,
|
||||||
|
FC,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext";
|
||||||
|
import useBoards from "@/app/deals/hooks/useBoards";
|
||||||
|
import useDeals from "@/app/deals/hooks/useDeals";
|
||||||
|
import useStatuses from "@/app/deals/hooks/useStatuses";
|
||||||
|
import { BoardSchema } from "@/types/BoardSchema";
|
||||||
|
import { DealSchema } from "@/types/DealSchema";
|
||||||
|
import { StatusSchema } from "@/types/StatusSchema";
|
||||||
|
|
||||||
|
type BoardsContextState = {
|
||||||
|
boards: BoardSchema[];
|
||||||
|
setBoards: React.Dispatch<React.SetStateAction<BoardSchema[]>>;
|
||||||
|
selectedBoard: BoardSchema | null;
|
||||||
|
setSelectedBoard: React.Dispatch<React.SetStateAction<BoardSchema | null>>;
|
||||||
|
statuses: StatusSchema[];
|
||||||
|
setStatuses: React.Dispatch<React.SetStateAction<StatusSchema[]>>;
|
||||||
|
deals: DealSchema[];
|
||||||
|
setDeals: React.Dispatch<React.SetStateAction<DealSchema[]>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const BoardsContext = createContext<BoardsContextState | undefined>(undefined);
|
||||||
|
|
||||||
|
const useBoardsContextState = () => {
|
||||||
|
const { boards, setBoards } = useBoards();
|
||||||
|
const [selectedBoard, setSelectedBoard] = useState<BoardSchema | null>(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
const { selectedProject: project } = useProjectsContext();
|
||||||
|
const { statuses, setStatuses } = useStatuses();
|
||||||
|
const { deals, setDeals } = useDeals();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (boards.length > 0 && selectedBoard === null) {
|
||||||
|
setSelectedBoard(boards[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedBoard) {
|
||||||
|
let newBoard = boards.find(board => board.id === selectedBoard.id);
|
||||||
|
|
||||||
|
if (!newBoard && boards.length > 0) {
|
||||||
|
newBoard = boards[0];
|
||||||
|
}
|
||||||
|
setSelectedBoard(newBoard ?? null);
|
||||||
|
}
|
||||||
|
}, [boards]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
boards,
|
||||||
|
setBoards,
|
||||||
|
selectedBoard,
|
||||||
|
setSelectedBoard,
|
||||||
|
statuses,
|
||||||
|
setStatuses,
|
||||||
|
deals,
|
||||||
|
setDeals,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type BoardsContextProviderProps = {
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BoardsContextProvider: FC<BoardsContextProviderProps> = ({
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const state = useBoardsContextState();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BoardsContext.Provider value={state}>
|
||||||
|
{children}
|
||||||
|
</BoardsContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useBoardsContext = () => {
|
||||||
|
const context = useContext(BoardsContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error(
|
||||||
|
"useBoardsContext must be used within a BoardsContextProvider"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
37
src/app/deals/hooks/useDeals.ts
Normal file
37
src/app/deals/hooks/useDeals.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { DealSchema } from "@/types/DealSchema";
|
||||||
|
|
||||||
|
const useDeals = () => {
|
||||||
|
const [deals, setDeals] = useState<DealSchema[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const INITIAL_DEALS: DealSchema[] = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Deal 1",
|
||||||
|
rank: "0|gggggg:",
|
||||||
|
statusId: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Deal 2",
|
||||||
|
rank: "0|mmmmmm:",
|
||||||
|
statusId: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Deal 3",
|
||||||
|
rank: "0|ssssss:",
|
||||||
|
statusId: 2,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
setDeals(INITIAL_DEALS);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return {
|
||||||
|
deals,
|
||||||
|
setDeals,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useDeals;
|
||||||
22
src/app/deals/hooks/useStatuses.ts
Normal file
22
src/app/deals/hooks/useStatuses.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { StatusSchema } from "@/types/StatusSchema";
|
||||||
|
|
||||||
|
const useStatuses = () => {
|
||||||
|
const [statuses, setStatuses] = useState<StatusSchema[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setStatuses([
|
||||||
|
{ id: 1, name: "Todo", rank: "0|aaaaaa:" },
|
||||||
|
{ id: 2, name: "In progress", rank: "0|gggggg:" },
|
||||||
|
{ id: 3, name: "Testing", rank: "0|mmmmmm:" },
|
||||||
|
{ id: 4, name: "Ready", rank: "0|ssssss:" },
|
||||||
|
]);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statuses,
|
||||||
|
setStatuses,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useStatuses;
|
||||||
@ -1,5 +1,8 @@
|
|||||||
|
import { Divider } from "@mantine/core";
|
||||||
import Boards from "@/app/deals/components/Boards/Boards";
|
import Boards from "@/app/deals/components/Boards/Boards";
|
||||||
import Header from "@/app/deals/components/Header/Header";
|
import Header from "@/app/deals/components/Header/Header";
|
||||||
|
import StatusColumns from "@/app/deals/components/StatusColumns/StatusColumns";
|
||||||
|
import { BoardsContextProvider } from "@/app/deals/contexts/BoardsContext";
|
||||||
import { ProjectsContextProvider } from "@/app/deals/contexts/ProjectsContext";
|
import { ProjectsContextProvider } from "@/app/deals/contexts/ProjectsContext";
|
||||||
import PageBlock from "@/components/PageBlock/PageBlock";
|
import PageBlock from "@/components/PageBlock/PageBlock";
|
||||||
import PageContainer from "@/components/PageContainer/PageContainer";
|
import PageContainer from "@/components/PageContainer/PageContainer";
|
||||||
@ -9,8 +12,12 @@ export default function DealsPage() {
|
|||||||
<PageContainer>
|
<PageContainer>
|
||||||
<PageBlock>
|
<PageBlock>
|
||||||
<ProjectsContextProvider>
|
<ProjectsContextProvider>
|
||||||
<Header />
|
<BoardsContextProvider>
|
||||||
<Boards />
|
<Header />
|
||||||
|
<Boards />
|
||||||
|
<Divider my={"xl"} />
|
||||||
|
<StatusColumns />
|
||||||
|
</BoardsContextProvider>
|
||||||
</ProjectsContextProvider>
|
</ProjectsContextProvider>
|
||||||
</PageBlock>
|
</PageBlock>
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
|
|||||||
@ -54,7 +54,6 @@ const SortableDnd = <T extends BaseItem>({
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(sortByLexorank(initialItems));
|
|
||||||
setItems(sortByLexorank(initialItems));
|
setItems(sortByLexorank(initialItems));
|
||||||
}, [initialItems]);
|
}, [initialItems]);
|
||||||
|
|
||||||
|
|||||||
6
src/types/DealSchema.ts
Normal file
6
src/types/DealSchema.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export type DealSchema = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
rank: string;
|
||||||
|
statusId: number;
|
||||||
|
};
|
||||||
5
src/types/StatusSchema.ts
Normal file
5
src/types/StatusSchema.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export type StatusSchema = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
rank: string;
|
||||||
|
};
|
||||||
@ -27,10 +27,10 @@ export function getNewLexorank(
|
|||||||
): LexoRank {
|
): LexoRank {
|
||||||
if (right) {
|
if (right) {
|
||||||
if (left) return left?.between(right);
|
if (left) return left?.between(right);
|
||||||
return right.genPrev();
|
return right.between(LexoRank.min());
|
||||||
}
|
}
|
||||||
if (left) {
|
if (left) {
|
||||||
return left.genNext();
|
return left.between(LexoRank.max());
|
||||||
}
|
}
|
||||||
return LexoRank.middle();
|
return LexoRank.middle();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user