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:
@@ -0,0 +1,85 @@
|
||||
import { MockupPipelineProvider } from '../provider/MockupPipelineProvider'
|
||||
import type { PipelineItem, PipelineStage, PendingPipelineItem } from '../domain/pipeline'
|
||||
import type { ListResponse, ItemResponse } from './types'
|
||||
import { throwServiceError } from './errors'
|
||||
|
||||
const provider = MockupPipelineProvider
|
||||
|
||||
export const pipelineService = {
|
||||
async getAll(): Promise<ListResponse<PipelineItem>> {
|
||||
try {
|
||||
const data = await provider.getAll()
|
||||
return { data, meta: { total: data.length, page: 1, pageSize: data.length, hasMore: false } }
|
||||
} catch (err) {
|
||||
throwServiceError(err)
|
||||
}
|
||||
},
|
||||
|
||||
async confirmSaved(pending: PendingPipelineItem, notes?: string): Promise<ItemResponse<'added' | 'duplicate'>> {
|
||||
try {
|
||||
const items = await provider.getAll()
|
||||
const alreadyExists = items.some(
|
||||
i => i.id === pending.resultId || (pending.propertyId && i.propertyId === pending.propertyId)
|
||||
)
|
||||
if (alreadyExists) return { data: 'duplicate' }
|
||||
const newItem: PipelineItem = {
|
||||
id: pending.resultId,
|
||||
matchId: pending.resultId,
|
||||
title: pending.title,
|
||||
location: pending.location ?? '–',
|
||||
matchScore: pending.matchScore,
|
||||
resultType: pending.resultType,
|
||||
stage: 'SAVED',
|
||||
propertyId: pending.propertyId,
|
||||
unitId: pending.unitId,
|
||||
propertyAddress: pending.propertyAddress,
|
||||
areaLabel: pending.areaLabel,
|
||||
rentLabel: pending.rentLabel,
|
||||
availabilityLabel: pending.availabilityLabel,
|
||||
notes: notes || undefined,
|
||||
addedAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
}
|
||||
await provider.add(newItem)
|
||||
return { data: 'added' }
|
||||
} catch (err) {
|
||||
throwServiceError(err)
|
||||
}
|
||||
},
|
||||
|
||||
async moveStage(id: string, stage: PipelineStage): Promise<ItemResponse<void>> {
|
||||
try {
|
||||
await provider.moveStage(id, stage)
|
||||
return { data: undefined }
|
||||
} catch (err) {
|
||||
throwServiceError(err)
|
||||
}
|
||||
},
|
||||
|
||||
async updateNotes(id: string, notes: string): Promise<ItemResponse<void>> {
|
||||
try {
|
||||
await provider.updateNotes(id, notes)
|
||||
return { data: undefined }
|
||||
} catch (err) {
|
||||
throwServiceError(err)
|
||||
}
|
||||
},
|
||||
|
||||
async loseItem(id: string): Promise<ItemResponse<void>> {
|
||||
try {
|
||||
await provider.loseItem(id)
|
||||
return { data: undefined }
|
||||
} catch (err) {
|
||||
throwServiceError(err)
|
||||
}
|
||||
},
|
||||
|
||||
async linkInquiry(id: string, inquiryId: string): Promise<ItemResponse<void>> {
|
||||
try {
|
||||
await provider.linkInquiry(id, inquiryId)
|
||||
return { data: undefined }
|
||||
} catch (err) {
|
||||
throwServiceError(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user