refactor: move PipelineItems from Zustand to Provider→Service→React Query

PipelineItems are domain data and must not live in Zustand. Moves the
full stack to the correct layer: MockupPipelineProvider (localStorage
persistence + seed fallback) → pipelineService → usePipeline hooks
(useQuery for reads, useMutation for writes with cache invalidation).

pipelineStore is now UI-only: dialogOpen, pendingItem, openSavedDialog,
closeSavedDialog. All consumers updated to use the new hooks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-05-24 12:32:57 +02:00
parent 0582031930
commit 723f553939
12 changed files with 303 additions and 115 deletions
+9 -8
View File
@@ -6,7 +6,7 @@ import {
} from '@mui/material'
import { Search, Send, Paperclip, ArrowLeft, Bot, Building2, Kanban } from 'lucide-react'
import { mockInquiries } from '../../mock-data/inquiries'
import { usePipelineStore } from '../../stores/pipelineStore'
import { usePipelineItems, useMoveStage } from '../../hooks/usePipeline'
import { useToastStore } from '../../stores/toastStore'
import type { InquiryMessage } from '../../domain/inquiry'
import { STAGE_ORDER, STAGE_LABELS, detectKiStage } from './anfragenKiDetection'
@@ -34,7 +34,8 @@ const FILTER_TABS = [
export default function Anfragen() {
const navigate = useNavigate()
const [searchParams] = useSearchParams()
const { findByPropertyId, findByInquiryId, moveStage } = usePipelineStore()
const { data: pipelineItems = [] } = usePipelineItems()
const { mutate: moveStage } = useMoveStage()
const showToast = useToastStore(s => s.showToast)
const preselectedId = searchParams.get('inquiry')
@@ -65,8 +66,8 @@ export default function Anfragen() {
// Pipeline link for currently selected inquiry
const linkedPipelineItem = selected?.propertyId
? findByPropertyId(selected.propertyId)
: (selected ? findByInquiryId(selected.id) : undefined)
? pipelineItems.find(i => i.propertyId === selected.propertyId)
: (selected ? pipelineItems.find(i => i.inquiryId === selected.id) : undefined)
useEffect(() => {
if (threadRef.current) {
@@ -112,13 +113,13 @@ export default function Anfragen() {
const ki = detectKiStage(text)
if (ki && selected) {
const pipelineItem = selected.propertyId
? findByPropertyId(selected.propertyId)
: findByInquiryId(selectedId)
? pipelineItems.find(i => i.propertyId === selected.propertyId)
: pipelineItems.find(i => i.inquiryId === selectedId)
if (pipelineItem) {
const currentIdx = STAGE_ORDER.indexOf(pipelineItem.stage)
const targetIdx = STAGE_ORDER.indexOf(ki.stage)
if (targetIdx > currentIdx) {
moveStage(pipelineItem.id, ki.stage)
moveStage({ id: pipelineItem.id, stage: ki.stage })
setKiAlert({ title: pipelineItem.title, stage: STAGE_LABELS[ki.stage] })
}
}
@@ -180,7 +181,7 @@ export default function Anfragen() {
key={inq.id}
inq={inq}
isSelected={inq.id === selectedId}
hasPipeline={!!(inq.propertyId ? findByPropertyId(inq.propertyId) : findByInquiryId(inq.id))}
hasPipeline={!!(inq.propertyId ? pipelineItems.find(i => i.propertyId === inq.propertyId) : pipelineItems.find(i => i.inquiryId === inq.id))}
onSelect={handleSelect}
/>
))}
+4 -3
View File
@@ -8,7 +8,7 @@ import {
} from '@dnd-kit/core'
import type { DragEndEvent, DragStartEvent } from '@dnd-kit/core'
import { TrendingUp } from 'lucide-react'
import { usePipelineStore } from '../../stores/pipelineStore'
import { usePipelineItems, useMoveStage } from '../../hooks/usePipeline'
import { AddToPipelineDialog } from '../../components/shortlist'
import type { PipelineItem, PipelineStage } from '../../domain/pipeline'
import { STAGES } from '../../components/pipeline/pipelineConstants'
@@ -20,7 +20,8 @@ import { DetailPanel } from '../../components/pipeline/PipelineDetailPanel'
export default function Pipeline() {
const navigate = useNavigate()
const { items, moveStage } = usePipelineStore()
const { data: items = [] } = usePipelineItems()
const { mutate: moveStage } = useMoveStage()
const [selectedItem, setSelectedItem] = useState<PipelineItem | null>(null)
const [activeId, setActiveId] = useState<string | null>(null)
const [overId, setOverId] = useState<string | null>(null)
@@ -53,7 +54,7 @@ export default function Pipeline() {
const targetStage = over.id as PipelineStage
const item = items.find(i => i.id === active.id)
if (item && item.stage !== targetStage) {
moveStage(item.id, targetStage)
moveStage({ id: item.id, stage: targetStage })
}
}