Как отображать товары по категориям в React.js и при нажатии переходить на другую страницу
Добрый всем) получила все товары они вложены в категории и подкатегории как у поставщика апи, как мне реализовать чтобы при нажимании на категоию она открывалась на другой странице ? На данный момент при нажатии на категорию она разворачивается в низ с содержимым подкатегории в них товары, есть вложеность 3 уровня, есть 4 ! поскольку я прям новичек, то не могу понять как реализовать такой переход? Помогите плиз***
`api.js
`import React, { useEffect, useState } from "react";
import Search from "./SearchProducts/SearchProducts";
import AddProducts from "./AddProducts/AddProducts";
import CardBody from "./Card/CardBody";
import Button from "./Button/Button";
import CategoryButton from "./CategoryButton/CategoryButton";
import "./Api.css";
import axios from 'axios';
const CategoryTree = ({ section, toggleCategory, expandedCategories, categoryName, itemsByCategory, removeItem, addedItems, addItem, level }) => {
// рендеринг карточек товаров
const sectionItems = itemsByCategory[section.id] || [];
return (
<div className="api-row">
<CategoryButton
level={level}
onClick={() => toggleCategory(section.id)}
>
{categoryName(section.id)}
</CategoryButton>
{expandedCategories[section.id] && (
<div className="api-col" >
{sectionItems.length > 0 && (
<CardBody
category={section.name}
products={sectionItems}
addItem={addItem}
removeItem={removeItem}
addedItems={addedItems}
onClick={() => toggleCategory(section.id)}
/>
)}
{section.children.map((childSection) => (
<CategoryTree
key={childSection.id}
section={childSection}
level={level + 1}
toggleCategory={toggleCategory}
expandedCategories={expandedCategories}
categoryName={categoryName}
itemsByCategory={itemsByCategory}
addItem={addItem}
removeItem={removeItem}
addedItems={addedItems}
/>
))}
</div>
)}
</div>
);
};
const Api = () => {
const [items, setItems] = useState([]);
const [searchValue, setSearchValue] = useState("");
const [addedItems, setAddedItems] = useState([]);
const [showAddProducts, setShowAddProducts] = useState(false);
const [expandedCategories, setExpandedCategories] = useState({});
const [categoryTree, setCategoryTree] = useState([]);
const [categories, setCategories] = useState({});
const [currentCategory, setCurrentCategory] = useState(null);
const url = 'http://localhost:8000/products/';
useEffect(() => {
// Загрузка товаров
axios.get(url)
.then(response => {
const baseImageUrl = 'https://optfm.ru';
const newItems = response.data.response.items.map(item => ({
...item,
picture: baseImageUrl + item.picture
}));
setItems(newItems);
})
.catch(error => console.log(error));
// Загрузка категорий
axios.get('http://localhost:8000/sections')
.then(response => {
const sections = response.data.response.items;
const sectionsTree = buildCategoryTree(sections);
const sectionsMap = {};
sections.forEach(section => {
sectionsMap[section.id] = section.name;
});
setCategoryTree(sectionsTree);
setCategories(sectionsMap);
})
.catch(error => console.log(error));
}, []);
function changingSearchData(e) {
setSearchValue(e.target.value);
}
const itemsFilter = items.filter((item) => item.name.toLowerCase().includes(searchValue.toLowerCase()));
function addItem(item) {
item.addNumber = 1;
item.price = item.prices[1].price;
const newItems = [...addedItems, item];
setAddedItems(newItems);
}
function removeItem(item) {
const newItems = addedItems.filter((addedItem) => addedItem.id !== item.id);
setAddedItems(newItems);
}
// Функция для получения товаров по категориям
const getCategoryItems = (items) => {
const categoryItems = {};
items.forEach(item => {
if (!categoryItems[item.section_id]) {
categoryItems[item.section_id] = [item];
} else {
categoryItems[item.section_id].push(item);
}
});
return categoryItems;
};
// Получение товаров по категориям
const itemsByCategory = getCategoryItems(items);
const toggleCategory = (categoryId) => {
setExpandedCategories(prevState => ({
...prevState,
[categoryId]: !prevState[categoryId],
}));
};
const buildCategoryTree = (sections) => {
const tree = {};
sections.forEach((section) => {
tree[section.id] = { ...section, children: [] };
});
Object.values(tree).forEach((section) => {
if (section.parent_id) {
tree[section.parent_id].children.push(section);
}
});
return Object.values(tree).filter((section) => section.parent_id === null);
};
//
// Функция обработки выбора категории
const handleCategorySelect = (categoryId) => {
setCurrentCategory(categoryId);
};
// Функция возврата к списку категорий
const handleReturnToCategories = () => {
setCurrentCategory(null);
};
// Получаем список товаров текущей категории
const currentCategoryItems = items.filter((item) => item.section_id === currentCategory);
// имя категории
const categoryName = (categoryId) => {
return categories[categoryId] || "Категория не найдена";
};
return (
<div className="body__container">
<div className="navigation__api">
<div className="nav-right">
<Search value={searchValue} onChangeData={changingSearchData} />
<Button num={addedItems.length} click={() => setShowAddProducts(!showAddProducts)} />
</div>
</div>
<div className="add__products">
{showAddProducts && (
<div className="add__products">
<AddProducts
click={() => setShowAddProducts(!showAddProducts)}
items={addedItems}
removeItem={removeItem}
setAddedItems={setAddedItems}
/>
</div>
)}
{currentCategory === null ? (
categoryTree.map((section) => (
<CategoryTree
key={section.id}
section={section}
level={0}
toggleCategory={toggleCategory}
expandedCategories={expandedCategories}
categoryName={categoryName}
itemsByCategory={itemsByCategory}
addItem={addItem}
removeItem={removeItem}
addedItems={addedItems}
/>
))
) : (
categoryTree.filter(section => section.id === currentCategory).map((section) => (
<CategoryTree
key={section.id}
section={section}
toggleCategory={toggleCategory}
expandedCategories={expandedCategories}
categoryName={categoryName}
itemsByCategory={itemsByCategory}
addItem={addItem}
removeItem={removeItem}
addedItems={addedItems}
currentCategory={currentCategory}
/>
))
)}
</div>
</div>
);
};
export default Api;
cardBody.js
const CardBody = ({ category, products, addItem, removeItem, addedItems, subsectionName }) => {
return (
<div className="card__category">
<h2 className="card-text">{category}</h2>
<h3>{subsectionName}</h3>
<div className="card__grid">
{products.map((product) => (
<Card
key={product.id}
product={product}
addItem={addItem}
removeItem={removeItem}
addedItems={addedItems}
text={product.detail_text}
price={product.prices[1].price}
/>
))}
</div>
</div>
);
};
export default CardBody;`
`const CategoryButton = ({ children, onClick, category, level }) => {
const levelClass = `category-card-level-${level}`;
return (
<div className={`category-card ${levelClass}`} onClick={onClick}>
{children}
<h2>{category && category.name}</h2>
</div>
);
};
export default CategoryButton;`
`App.js роут
<Route path="/api" element={<Api />} />`
плюс остальные роуты не относящиеся к товарам