'use client';
import { useState } from 'react';
import Link from 'next/link';
import { ChevronRight, Loader2 } from 'lucide-react';
import type { TreeNode } from '@/lib/queries/taxonomy';
/** Lazily expandable hierarchy tree. Children are fetched on first expand from /api/taxonomy/children. */
export function Tree({ roots, hierarchyType }: { roots: TreeNode[]; hierarchyType: string }) {
return (
);
}
function Node({ node, hierarchyType, depth }: { node: TreeNode; hierarchyType: string; depth: number }) {
const [open, setOpen] = useState(false);
const [children, setChildren] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const toggle = async () => {
const next = !open;
setOpen(next);
if (next && children == null && node.child_count > 0) {
setLoading(true);
setError(null);
try {
const r = await fetch(`/api/taxonomy/children?id=${encodeURIComponent(node.id)}&type=${encodeURIComponent(hierarchyType)}`);
if (!r.ok) throw new Error(`HTTP ${r.status}`);
const j = (await r.json()) as { data: TreeNode[] };
setChildren(j.data);
} catch (e) {
setError((e as Error).message);
} finally {
setLoading(false);
}
}
};
return (
0 ? open : undefined} aria-level={depth + 1}>
{node.child_count > 0 ? (
{loading ? : }
) : (
)}
{node.canonical_name}
{node.primary_oncotree_code && hierarchyType === 'oncotree' ? {node.primary_oncotree_code} : null}
{node.primary_ncit_code && hierarchyType === 'ncit' ? {node.primary_ncit_code} : null}
{node.child_count > 0 ? {node.child_count} : null}
{open && error ? (
Could not load children ({error}).
) : null}
{open && children ? (
{children.map((c) => (
))}
) : null}
);
}