@open-mercato/core 0.10.1-develop.7874.1.67e097d23a → 0.10.1-develop.7879.1.80d3740285

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -443,10 +443,6 @@ function DealsKanbanPage() {
443
443
  });
444
444
  const [extraCardsByStage, setExtraCardsByStage] = React.useState({});
445
445
  const [loadingMoreByStage, setLoadingMoreByStage] = React.useState({});
446
- React.useEffect(() => {
447
- setExtraCardsByStage({});
448
- setLoadingMoreByStage({});
449
- }, [selectedPipelineId, search, statusFilters, ownerFilters, peopleFilters, companyFilters, closeDateFilter, currencyFilter]);
450
446
  const filterSignature = React.useMemo(
451
447
  () => ({
452
448
  pipelineId: selectedPipelineId,
@@ -526,28 +522,38 @@ function DealsKanbanPage() {
526
522
  const mapped = mapSortOptionToApi(sortBy);
527
523
  return mapped ?? { sortField: "updatedAt", sortDir: "desc" };
528
524
  }, [sortBy]);
525
+ const laneQueryKey = React.useMemo(
526
+ () => [
527
+ "customers",
528
+ "deals",
529
+ "kanban-lane",
530
+ `scope:${scopeVersion}`,
531
+ `organization:${activeOrgId ?? "none"}`,
532
+ `pipeline:${filterSignature.pipelineId ?? "none"}`,
533
+ `search:${filterSignature.search}`,
534
+ `status:${filterSignature.status}`,
535
+ `owners:${filterSignature.owners}`,
536
+ `people:${filterSignature.people}`,
537
+ `companies:${filterSignature.companies}`,
538
+ `close:${filterSignature.closeFrom}-${filterSignature.closeTo}`,
539
+ `sort:${apiSort.sortField}:${apiSort.sortDir}`,
540
+ `currency:${filterSignature.currency}`
541
+ ],
542
+ [scopeVersion, activeOrgId, filterSignature, apiSort]
543
+ );
544
+ const paginationGeneration = React.useRef(0);
545
+ React.useEffect(() => {
546
+ paginationGeneration.current += 1;
547
+ setExtraCardsByStage({});
548
+ setLoadingMoreByStage({});
549
+ return () => {
550
+ paginationGeneration.current += 1;
551
+ };
552
+ }, [laneQueryKey]);
529
553
  const laneQueries = useQueries({
530
554
  queries: lanes.map((stage) => {
531
555
  return {
532
- queryKey: [
533
- "customers",
534
- "deals",
535
- "kanban-lane",
536
- `scope:${scopeVersion}`,
537
- `pipeline:${filterSignature.pipelineId ?? "none"}`,
538
- `search:${filterSignature.search}`,
539
- `status:${filterSignature.status}`,
540
- `owners:${filterSignature.owners}`,
541
- `people:${filterSignature.people}`,
542
- `companies:${filterSignature.companies}`,
543
- `close:${filterSignature.closeFrom}-${filterSignature.closeTo}`,
544
- // Sort affects which 25 deals come back on page 1, so it MUST be in the key —
545
- // otherwise switching from "Value (high to low)" to "Close (soonest)" reuses
546
- // the old (wrong-sort) cache and silently keeps the wrong slice on screen.
547
- `sort:${apiSort.sortField}:${apiSort.sortDir}`,
548
- `currency:${filterSignature.currency}`,
549
- `stage:${stage.id}`
550
- ],
556
+ queryKey: [...laneQueryKey, `stage:${stage.id}`],
551
557
  enabled: !!selectedPipelineId,
552
558
  staleTime: 3e4,
553
559
  queryFn: async () => {
@@ -688,6 +694,7 @@ function DealsKanbanPage() {
688
694
  if (loadingMoreByStage[stageId]) return;
689
695
  const already = extraCardsByStage[stageId]?.length ?? 0;
690
696
  const nextPage = Math.floor((LANE_PAGE_SIZE + already) / LANE_PAGE_SIZE) + 1;
697
+ const requestGeneration = paginationGeneration.current;
691
698
  setLoadingMoreByStage((prev) => ({ ...prev, [stageId]: true }));
692
699
  try {
693
700
  const params = new URLSearchParams();
@@ -708,18 +715,20 @@ function DealsKanbanPage() {
708
715
  const call = await apiCall(
709
716
  `/api/customers/deals?${params.toString()}`
710
717
  );
711
- if (!call.ok) return;
718
+ if (requestGeneration !== paginationGeneration.current || !call.ok) return;
712
719
  const items = Array.isArray(call.result?.items) ? call.result.items : [];
713
720
  setExtraCardsByStage((prev) => ({
714
721
  ...prev,
715
722
  [stageId]: [...prev[stageId] ?? [], ...items]
716
723
  }));
717
724
  } finally {
718
- setLoadingMoreByStage((prev) => {
719
- const next = { ...prev };
720
- delete next[stageId];
721
- return next;
722
- });
725
+ if (requestGeneration === paginationGeneration.current) {
726
+ setLoadingMoreByStage((prev) => {
727
+ const next = { ...prev };
728
+ delete next[stageId];
729
+ return next;
730
+ });
731
+ }
723
732
  }
724
733
  },
725
734
  [
@@ -733,7 +742,9 @@ function DealsKanbanPage() {
733
742
  companyFilters,
734
743
  closeDateFilter.from,
735
744
  closeDateFilter.to,
736
- apiSort
745
+ currencyFilter,
746
+ apiSort,
747
+ laneQueryKey
737
748
  ]
738
749
  );
739
750
  const isInitialLoading = !!selectedPipelineId && lanes.length === 0 ? stagesQuery.isLoading : laneQueries.some((laneQuery) => laneQuery.isLoading && !laneQuery.data);