0.0.1.1
This commit is contained in:
+96
-66
@@ -33,7 +33,7 @@ interface FamilyContextType {
|
||||
const FamilyContext = createContext<FamilyContextType | undefined>(undefined)
|
||||
|
||||
export function FamilyProvider({ children }: { children: React.ReactNode }) {
|
||||
const { data: session } = useSession()
|
||||
const { data: session, status } = useSession()
|
||||
const searchParams = useSearchParams()
|
||||
const [searchResults, setSearchResults] = useState<FamilyMember[]>([])
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
@@ -46,45 +46,55 @@ export function FamilyProvider({ children }: { children: React.ReactNode }) {
|
||||
|
||||
// 监听 URL 和 Session 变化,加载家族树
|
||||
useEffect(() => {
|
||||
const treeId = searchParams.get('treeId')
|
||||
console.log('FamilyContext - Effect triggered, treeId:', treeId, 'currentTree:', currentTree?.id)
|
||||
|
||||
// 如果 session 不存在,清除所有数据
|
||||
if (!session?.user?.id) {
|
||||
console.log('FamilyContext - No session, clearing data')
|
||||
setCurrentTree(null)
|
||||
setTreeData({ rootId: "", members: {} })
|
||||
setIsLoading(false)
|
||||
return
|
||||
}
|
||||
const controller = new AbortController()
|
||||
const signal = controller.signal
|
||||
|
||||
// 如果 treeId 与当前树相同,跳过
|
||||
if (treeId && treeId === currentTree?.id) {
|
||||
console.log('FamilyContext - Same tree, skipping')
|
||||
return
|
||||
}
|
||||
|
||||
// 如果没有 treeId 且已有树,跳过
|
||||
if (!treeId && currentTree) {
|
||||
console.log('FamilyContext - No treeId but has currentTree, skipping')
|
||||
return
|
||||
}
|
||||
|
||||
// 需要加载新树
|
||||
const targetTreeId = treeId || 'first'
|
||||
console.log('FamilyContext - Loading tree:', targetTreeId)
|
||||
|
||||
setIsLoading(true)
|
||||
|
||||
const fetchUrl = targetTreeId === 'first'
|
||||
? '/api/trees'
|
||||
: `/api/trees/${targetTreeId}`
|
||||
|
||||
console.log('FamilyContext - Fetching URL:', fetchUrl)
|
||||
const loadTree = async () => {
|
||||
const treeId = searchParams.get('treeId')
|
||||
|
||||
fetch(fetchUrl)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
// 如果 session 正在加载,等待
|
||||
if (status === 'loading') {
|
||||
return
|
||||
}
|
||||
|
||||
// 如果 session 不存在(未登录),清除所有数据
|
||||
if (!session?.user?.id) {
|
||||
if (!signal.aborted) {
|
||||
setCurrentTree(null)
|
||||
setTreeData({ rootId: "", members: {} })
|
||||
setIsLoading(false)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 如果 treeId 与当前树相同,跳过
|
||||
if (treeId && treeId === currentTree?.id) {
|
||||
return
|
||||
}
|
||||
|
||||
// 如果没有 treeId 且已有树,跳过
|
||||
if (!treeId && currentTree) {
|
||||
return
|
||||
}
|
||||
|
||||
// 需要加载新树
|
||||
const targetTreeId = treeId || 'first'
|
||||
|
||||
if (!signal.aborted) setIsLoading(true)
|
||||
|
||||
const fetchUrl = targetTreeId === 'first'
|
||||
? '/api/trees'
|
||||
: `/api/trees/${targetTreeId}`
|
||||
|
||||
try {
|
||||
const res = await fetch(fetchUrl, { signal })
|
||||
if (!res.ok) {
|
||||
throw new Error(`HTTP error! status: ${res.status}`)
|
||||
}
|
||||
const data = await res.json()
|
||||
|
||||
if (signal.aborted) return
|
||||
|
||||
let tree = null
|
||||
if (targetTreeId === 'first') {
|
||||
tree = data.trees?.[0]
|
||||
@@ -92,43 +102,63 @@ export function FamilyProvider({ children }: { children: React.ReactNode }) {
|
||||
tree = data.tree
|
||||
}
|
||||
|
||||
console.log('FamilyContext - Fetched tree:', tree?.name, tree?.id)
|
||||
|
||||
if (tree) {
|
||||
setCurrentTree(tree)
|
||||
// 加载该树的成员数据
|
||||
return fetch(`/api/trees/${tree.id}/members`)
|
||||
.then(res => res.json())
|
||||
.then(memberData => {
|
||||
console.log('FamilyContext - Loaded members:', memberData.members?.length)
|
||||
if (memberData.members) {
|
||||
const membersMap = memberData.members.reduce(
|
||||
(acc: Record<string, FamilyMember>, member: FamilyMember) => {
|
||||
acc[member.id] = member
|
||||
return acc
|
||||
},
|
||||
{}
|
||||
)
|
||||
setTreeData({
|
||||
rootId: memberData.rootId || "",
|
||||
members: membersMap,
|
||||
})
|
||||
}
|
||||
})
|
||||
try {
|
||||
const memberRes = await fetch(`/api/trees/${tree.id}/members`, { signal })
|
||||
if (!memberRes.ok) {
|
||||
throw new Error(`Failed to load members: ${memberRes.status}`)
|
||||
}
|
||||
const memberData = await memberRes.json()
|
||||
|
||||
if (signal.aborted) return
|
||||
|
||||
if (memberData.members) {
|
||||
const membersMap = memberData.members.reduce(
|
||||
(acc: Record<string, FamilyMember>, member: FamilyMember) => {
|
||||
acc[member.id] = member
|
||||
return acc
|
||||
},
|
||||
{}
|
||||
)
|
||||
setTreeData({
|
||||
rootId: memberData.rootId || "",
|
||||
members: membersMap,
|
||||
})
|
||||
}
|
||||
} catch (err: any) {
|
||||
if (err.name === 'AbortError') return
|
||||
console.error('加载成员数据失败:', err)
|
||||
// 即使成员加载失败,也保留树的信息
|
||||
setTreeData({ rootId: "", members: {} })
|
||||
}
|
||||
} else {
|
||||
// 没找到树(可能是被删除了,或者没有权限)
|
||||
console.log('FamilyContext - Tree not found')
|
||||
setCurrentTree(null)
|
||||
setTreeData({ rootId: "", members: {} })
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('FamilyContext - Load failed:', err)
|
||||
} catch (err: any) {
|
||||
if (err.name === 'AbortError') return
|
||||
|
||||
// 忽略 Failed to fetch 错误,通常发生在页面跳转或网络问题时
|
||||
if (err.message === 'Failed to fetch' || err.toString().includes('Failed to fetch')) {
|
||||
return
|
||||
}
|
||||
|
||||
console.error('加载家族树失败:', err.message || err)
|
||||
setCurrentTree(null)
|
||||
setTreeData({ rootId: "", members: {} })
|
||||
})
|
||||
.finally(() => setIsLoading(false))
|
||||
}, [searchParams, session?.user?.id])
|
||||
} finally {
|
||||
if (!signal.aborted) setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
loadTree()
|
||||
|
||||
return () => {
|
||||
controller.abort()
|
||||
}
|
||||
}, [searchParams, session?.user?.id, status, currentTree?.id])
|
||||
|
||||
const getMember = useCallback(
|
||||
(id: string) => {
|
||||
|
||||
Reference in New Issue
Block a user