fix: fixed rerender of boards component after changes in statuses

This commit is contained in:
2025-08-01 11:08:53 +04:00
parent 5fe9ea6747
commit 5137836265
6 changed files with 75 additions and 31 deletions

View File

@ -14,7 +14,9 @@ const Boards = () => {
return <Board board={board} />; return <Board board={board} />;
}; };
const onDragEnd = (itemId: number, newLexorank: string) => {}; const onDragEnd = (itemId: number, newLexorank: string) => {
console.log("onDragEnd:", itemId, newLexorank);
};
return ( return (
<ScrollArea <ScrollArea

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react"; import React, { useMemo } from "react";
import { useDroppable } from "@dnd-kit/core"; import { useDroppable } from "@dnd-kit/core";
import { import {
SortableContext, SortableContext,
@ -18,11 +18,8 @@ type BoardSectionProps = {
const StatusColumn = ({ id, title, deals }: BoardSectionProps) => { const StatusColumn = ({ id, title, deals }: BoardSectionProps) => {
const { setNodeRef } = useDroppable({ id }); const { setNodeRef } = useDroppable({ id });
const [sortedDeals, setSortedDeals] = useState<DealSchema[]>([]);
useEffect(() => { const sortedDeals = useMemo(() => sortByLexorank(deals), [deals]);
setSortedDeals(sortByLexorank(deals));
}, [deals]);
return ( return (
<Box style={{ backgroundColor: "#eee", padding: 2 }}> <Box style={{ backgroundColor: "#eee", padding: 2 }}>

View File

@ -18,7 +18,7 @@ import { LexoRank } from "lexorank";
import { Group } from "@mantine/core"; import { Group } from "@mantine/core";
import DealCard from "@/app/deals/components/DealCard/DealCard"; import DealCard from "@/app/deals/components/DealCard/DealCard";
import StatusColumn from "@/app/deals/components/StatusColumn/StatusColumn"; import StatusColumn from "@/app/deals/components/StatusColumn/StatusColumn";
import { useBoardsContext } from "@/app/deals/contexts/BoardsContext"; import { useStatusesContext } from "@/app/deals/contexts/StatusesContext";
import { DealSchema } from "@/types/DealSchema"; import { DealSchema } from "@/types/DealSchema";
import { getNewLexorank, sortByLexorank } from "@/utils/lexorank"; import { getNewLexorank, sortByLexorank } from "@/utils/lexorank";
@ -31,8 +31,8 @@ type Props = {
}; };
const StatusColumnsDnd: FC<Props> = props => { const StatusColumnsDnd: FC<Props> = props => {
const { statuses, deals, setDeals } = useBoardsContext(); const { statuses, deals, setDeals } = useStatusesContext();
const [activeDealId, setActiveDealId] = useState<null | number>(null); const [activeDeal, setActiveDeal] = useState<DealSchema | null>(null);
const sensors = useSensors( const sensors = useSensors(
useSensor(PointerSensor), useSensor(PointerSensor),
@ -42,7 +42,9 @@ const StatusColumnsDnd: FC<Props> = props => {
); );
const handleDragStart = ({ active }: DragStartEvent) => { const handleDragStart = ({ active }: DragStartEvent) => {
setActiveDealId(active.id as number); setActiveDeal(
deals.find(deal => deal.id === (active.id as number)) ?? null
);
}; };
const getStatusByDealId = (dealId: number) => { const getStatusByDealId = (dealId: number) => {
@ -158,7 +160,7 @@ const StatusColumnsDnd: FC<Props> = props => {
}; };
const handleDragEnd = ({ active, over }: DragOverEvent) => { const handleDragEnd = ({ active, over }: DragOverEvent) => {
setActiveDealId(null); setActiveDeal(null);
if (!over?.id) return; if (!over?.id) return;
const activeDealId = Number(active.id); const activeDealId = Number(active.id);
@ -175,10 +177,6 @@ const StatusColumnsDnd: FC<Props> = props => {
props.onDealDragEnd(activeDealId, overStatusId, newLexorank); props.onDealDragEnd(activeDealId, overStatusId, newLexorank);
}; };
const deal = activeDealId
? deals.find(deal => deal.id === activeDealId)
: null;
return ( return (
<DndContext <DndContext
sensors={sensors} sensors={sensors}
@ -200,7 +198,7 @@ const StatusColumnsDnd: FC<Props> = props => {
/> />
))} ))}
<DragOverlay dropAnimation={defaultDropAnimation}> <DragOverlay dropAnimation={defaultDropAnimation}>
{deal ? <DealCard deal={deal} /> : null} {activeDeal ? <DealCard deal={activeDeal} /> : null}
</DragOverlay> </DragOverlay>
</Group> </Group>
</DndContext> </DndContext>

View File

@ -9,21 +9,13 @@ import React, {
} from "react"; } from "react";
import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext"; import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext";
import useBoards from "@/app/deals/hooks/useBoards"; 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 { BoardSchema } from "@/types/BoardSchema";
import { DealSchema } from "@/types/DealSchema";
import { StatusSchema } from "@/types/StatusSchema";
type BoardsContextState = { type BoardsContextState = {
boards: BoardSchema[]; boards: BoardSchema[];
setBoards: React.Dispatch<React.SetStateAction<BoardSchema[]>>; setBoards: React.Dispatch<React.SetStateAction<BoardSchema[]>>;
selectedBoard: BoardSchema | null; selectedBoard: BoardSchema | null;
setSelectedBoard: React.Dispatch<React.SetStateAction<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 BoardsContext = createContext<BoardsContextState | undefined>(undefined);
@ -34,8 +26,6 @@ const useBoardsContextState = () => {
null null
); );
const { selectedProject: project } = useProjectsContext(); const { selectedProject: project } = useProjectsContext();
const { statuses, setStatuses } = useStatuses();
const { deals, setDeals } = useDeals();
useEffect(() => { useEffect(() => {
if (boards.length > 0 && selectedBoard === null) { if (boards.length > 0 && selectedBoard === null) {
@ -58,10 +48,6 @@ const useBoardsContextState = () => {
setBoards, setBoards,
selectedBoard, selectedBoard,
setSelectedBoard, setSelectedBoard,
statuses,
setStatuses,
deals,
setDeals,
}; };
}; };

View File

@ -0,0 +1,58 @@
"use client";
import React, { createContext, FC, useContext } from "react";
import { useBoardsContext } from "@/app/deals/contexts/BoardsContext";
import useDeals from "@/app/deals/hooks/useDeals";
import useStatuses from "@/app/deals/hooks/useStatuses";
import { DealSchema } from "@/types/DealSchema";
import { StatusSchema } from "@/types/StatusSchema";
type StatusesContextState = {
statuses: StatusSchema[];
setStatuses: React.Dispatch<React.SetStateAction<StatusSchema[]>>;
deals: DealSchema[];
setDeals: React.Dispatch<React.SetStateAction<DealSchema[]>>;
};
const StatusesContext = createContext<StatusesContextState | undefined>(
undefined
);
const useStatusesContextState = () => {
const { statuses, setStatuses } = useStatuses();
const { deals, setDeals } = useDeals();
const { selectedBoard } = useBoardsContext();
return {
statuses,
setStatuses,
deals,
setDeals,
};
};
type StatusesContextProviderProps = {
children: React.ReactNode;
};
export const StatusesContextProvider: FC<StatusesContextProviderProps> = ({
children,
}) => {
const state = useStatusesContextState();
return (
<StatusesContext.Provider value={state}>
{children}
</StatusesContext.Provider>
);
};
export const useStatusesContext = () => {
const context = useContext(StatusesContext);
if (!context) {
throw new Error(
"useStatusesContext must be used within a StatusesContextProvider"
);
}
return context;
};

View File

@ -4,6 +4,7 @@ import Header from "@/app/deals/components/Header/Header";
import StatusColumns from "@/app/deals/components/StatusColumns/StatusColumns"; import StatusColumns from "@/app/deals/components/StatusColumns/StatusColumns";
import { BoardsContextProvider } from "@/app/deals/contexts/BoardsContext"; import { BoardsContextProvider } from "@/app/deals/contexts/BoardsContext";
import { ProjectsContextProvider } from "@/app/deals/contexts/ProjectsContext"; import { ProjectsContextProvider } from "@/app/deals/contexts/ProjectsContext";
import { StatusesContextProvider } from "@/app/deals/contexts/StatusesContext";
import PageBlock from "@/components/PageBlock/PageBlock"; import PageBlock from "@/components/PageBlock/PageBlock";
import PageContainer from "@/components/PageContainer/PageContainer"; import PageContainer from "@/components/PageContainer/PageContainer";
@ -16,7 +17,9 @@ export default function DealsPage() {
<Header /> <Header />
<Boards /> <Boards />
<Divider my={"xl"} /> <Divider my={"xl"} />
<StatusColumns /> <StatusesContextProvider>
<StatusColumns />
</StatusesContextProvider>
</BoardsContextProvider> </BoardsContextProvider>
</ProjectsContextProvider> </ProjectsContextProvider>
</PageBlock> </PageBlock>