55 lines
1.4 KiB
TypeScript
55 lines
1.4 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useRef } from 'react'
|
|
import { useSoloStore } from '@/stores/solo-store'
|
|
import type { SoloWorkspaceSnapshot } from '@/stores/solo-workspace/types'
|
|
|
|
interface SoloHydrationWrapperProps {
|
|
initialData: SoloWorkspaceSnapshot
|
|
children: React.ReactNode
|
|
}
|
|
|
|
function fingerprint(data: SoloWorkspaceSnapshot): string {
|
|
const taskPart = data.tasks
|
|
.map((task) => [
|
|
task.id,
|
|
task.status,
|
|
task.sort_order,
|
|
task.title,
|
|
task.implementation_plan ?? '',
|
|
task.verify_only ? '1' : '0',
|
|
task.verify_required,
|
|
task.story_id,
|
|
task.story_title,
|
|
task.story_code ?? '',
|
|
].join(':'))
|
|
.join(',')
|
|
const unassignedPart = data.unassignedStories
|
|
.map((story) => [
|
|
story.id,
|
|
story.title,
|
|
story.code ?? '',
|
|
story.tasks.map((task) => `${task.id}:${task.status}:${task.title}`).join('|'),
|
|
].join(':'))
|
|
.join(',')
|
|
return [
|
|
data.product.id,
|
|
data.sprint.id,
|
|
data.activeUserId,
|
|
taskPart,
|
|
unassignedPart,
|
|
].join('||')
|
|
}
|
|
|
|
export function SoloHydrationWrapper({ initialData, children }: SoloHydrationWrapperProps) {
|
|
const lastFingerprint = useRef<string>('')
|
|
|
|
useEffect(() => {
|
|
const fp = fingerprint(initialData)
|
|
if (fp === lastFingerprint.current) return
|
|
lastFingerprint.current = fp
|
|
useSoloStore.getState().hydrateSnapshot(initialData)
|
|
}, [initialData])
|
|
|
|
return <>{children}</>
|
|
}
|