Skip to content

Instantly share code, notes, and snippets.

@pradhumgp
Created September 16, 2024 05:49
Show Gist options
  • Save pradhumgp/66a17c49e969b7fe712bf6c9b4334f52 to your computer and use it in GitHub Desktop.
Save pradhumgp/66a17c49e969b7fe712bf6c9b4334f52 to your computer and use it in GitHub Desktop.
import { useState } from 'react';
// Recursive component to render tree nodes
const RenderTree = ({ node }) => {
const [isOpen, setIsOpen] = useState(true);
const toggle = () => setIsOpen(!isOpen);
return (
<div style={{ marginLeft: '20px' }}>
{/* Render current node */}
<div onClick={toggle} style={{ cursor: 'pointer', fontWeight: 'bold' }}>
{node.name || node.category_name || node.sub_category_name || node.sub_sub_category_name}
</div>
{/* If the node is open, render its children recursively */}
{isOpen && (
<div>
{node.categories?.map((child, index) => (
<RenderTree key={index} node={child} />
))}
{node.sub_categories?.map((child, index) => (
<RenderTree key={index} node={child} />
))}
{node.sub_sub_categories?.map((child, index) => (
<RenderTree key={index} node={child} />
))}
{node.sub_sub_sub_categories && (
<ul>
{node.sub_sub_sub_categories.map((item, index) => (
<li key={index}>{item.name}</li>
))}
</ul>
)}
</div>
)}
</div>
);
};
// Main component to handle search and display the tree
const CatalogTree = ({ data }) => {
const [searchQuery, setSearchQuery] = useState("");
const handleSearchChange = (e) => setSearchQuery(e.target.value);
// Recursive search function to filter the tree
const filterTree = (node, query) => {
const nodeName = node.name || node.category_name || node.sub_category_name || node.sub_sub_category_name;
// If node name contains the search query, keep this node
if (nodeName.toLowerCase().includes(query.toLowerCase())) return node;
// Otherwise, recursively filter the children
const filteredCategories = node.categories?.map(child => filterTree(child, query)).filter(Boolean);
const filteredSubCategories = node.sub_categories?.map(child => filterTree(child, query)).filter(Boolean);
const filteredSubSubCategories = node.sub_sub_categories?.map(child => filterTree(child, query)).filter(Boolean);
if (
(filteredCategories && filteredCategories.length > 0) ||
(filteredSubCategories && filteredSubCategories.length > 0) ||
(filteredSubSubCategories && filteredSubSubCategories.length > 0)
) {
return {
...node,
categories: filteredCategories,
sub_categories: filteredSubCategories,
sub_sub_categories: filteredSubSubCategories,
};
}
// Check items in the deepest level
const filteredItems = node.sub_sub_sub_categories?.filter(item =>
item.name.toLowerCase().includes(query.toLowerCase())
);
if (filteredItems && filteredItems.length > 0) {
return { ...node, sub_sub_sub_categories: filteredItems };
}
return null;
};
// Filter the catalog data
const filteredData = data
.map(catalog => filterTree(catalog, searchQuery))
.filter(Boolean); // Remove null values from the array
return (
<div>
{/* Search bar */}
<input
type="text"
placeholder="Search..."
value={searchQuery}
onChange={handleSearchChange}
style={{ marginBottom: '20px', padding: '10px', width: '300px' }}
/>
{/* Render the filtered catalog */}
{filteredData.length > 0 ? (
filteredData.map((catalog, index) => (
<RenderTree key={index} node={catalog} />
))
) : (
<div>No results found</div>
)}
</div>
);
};
export default CatalogTree;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment