As e-commerce grows every day, countless projects and libraries have been developed for e-commerce. These open-source e-commerce platforms have been built with Python, GraphQL, Django, React, and various other open-source languages and libraries.

Open-source coding assets for e-commerce offer impressive features such as offline shopping for PWAs, personalized user experience, secure and flexible payment and tax options combined with advanced payment methods, as well as additional features for SEO and analytics. Developers can create dynamic, fast, and custom shopping solutions using these components while developing beautiful online applications. WooCommerce is among the most popular open-source e-commerce solution widely used for developing shopping websites and portals. It powers over 37% of online stores and has been downloaded more than 15 million times.

Popular New Releases in Ecommerce

saleor

3.1.10

saleor

3.0.0-b.19

spree

Version 4.4.0

reaction

v4.1.8

magento2

Magento Release 2.3.7-p2

Popular Libraries in Ecommerce

saleor

by saleor doticonpythondoticon

star image 15729 doticonNOASSERTION

A modular, high performance, headless e-commerce platform built with Python, GraphQL, Django, and React.

saleor

by mirumee doticonpythondoticon

star image 13983 doticonNOASSERTION

A modular, high performance, headless e-commerce platform built with Python, GraphQL, Django, and React.

spree

by spree doticonrubydoticon

star image 11781 doticonNOASSERTION

Open Source headless multi-language/multi-currency/multi-store eCommerce platform. Developed by https://getvendo.com

reaction

by reactioncommerce doticonjavascriptdoticon

star image 11662 doticonGPL-3.0

Mailchimp Open Commerce is an API-first, headless commerce platform built using Node.js, React, GraphQL. Deployed via Docker and Kubernetes.

medusa

by medusajs doticonjavascriptdoticon

star image 11158 doticonMIT

The open-source Shopify alternative ⚡️

magento2

by magento doticonphpdoticon

star image 9995 doticonNOASSERTION

All Submissions you make to Magento Inc. ("Magento") through GitHub are subject to the following terms and conditions: (1) You grant Magento a perpetual, worldwide, non-exclusive, no charge, royalty free, irrevocable license under your applicable copyrights and patents to reproduce, prepare derivative works of, display, publically perform, sublicense and distribute any feedback, ideas, code, or other information (“Submission") you submit through GitHub. (2) Your Submission is an original work of authorship and you are the owner or are legally entitled to grant the license stated above. (3) You agree to the Contributor License Agreement found here: https://github.com/magento/magento2/blob/master/CONTRIBUTOR_LICENSE_AGREEMENT.html

vue-storefront

by vuestorefront doticontypescriptdoticon

star image 9340 doticonMIT

The open-source frontend for any eCommerce. Built with a PWA and headless approach, using a modern JS stack. We have custom integrations with Magento, commercetools, Shopware and Shopify and total coverage is just a matter of time. The API approach also allows you to merge VSF with any third-party tool like CMS, payment gateways or analytics. Newest updates: https://blog.vuestorefront.io. Always Open Source, MIT license.

woocommerce

by woocommerce doticonphpdoticon

star image 7769 doticonNOASSERTION

A customizable, open-source eCommerce platform built on WordPress. Build any commerce solution you can imagine.

nopCommerce

by nopSolutions doticoncsharpdoticon

star image 7145 doticonNOASSERTION

ASP.NET Core eCommerce software. nopCommerce is a free and open-source shopping cart.

Trending New libraries in Ecommerce

medusa

by medusajs doticonjavascriptdoticon

star image 11158 doticonMIT

The open-source Shopify alternative ⚡️

commerce

by vercel doticontypescriptdoticon

star image 5580 doticonMIT

Next.js Commerce

nextjs-subscription-payments

by vercel doticontypescriptdoticon

star image 1591 doticonMIT

Clone, deploy, and fully customize a SaaS subscription application with Next.js.

proshop_mern

by bradtraversy doticonjavascriptdoticon

star image 1298 doticon

Shopping cart built with MERN & Redux

covidpass

by covidpass-org doticontypescriptdoticon

star image 1241 doticonMIT

Web app for adding EU Digital COVID Certificates to your wallet apps

project_e_commerce

by adrianhajdin doticonjavascriptdoticon

star image 982 doticon

This is a code repository for the corresponding video tutorial. In this video, we're going to build a fully functional eCommerce application using commerce.js.

commercejs-nextjs-demo-store

by chec doticonjavascriptdoticon

star image 955 doticonBSD-3-Clause

Commerce demo store built for the Jamstack. Built with Commerce.js, Next.js, and can be one-click deployed to Netlify. Includes product catalog, customer login, categories, variants, cart, checkout, payments (Stripe) order confirmation, and printable receipts.

stripe-react-native

by stripe doticontypescriptdoticon

star image 833 doticonMIT

React Native library for Stripe.

laravel-crm

by krayin doticonphpdoticon

star image 752 doticonMIT

Free & Opensource Laravel CRM solution for SMEs and Enterprises for complete customer lifecycle management.

Top Authors in Ecommerce

1

mageplaza

63 Libraries

star icon1631

2

magepow

47 Libraries

star icon441

3

meanbee

43 Libraries

star icon762

4

yireo

41 Libraries

star icon1002

5

Shopify

39 Libraries

star icon13734

6

php-cuong

37 Libraries

star icon318

7

elgentos

35 Libraries

star icon574

8

stripe-samples

33 Libraries

star icon3232

9

magento-hackathon

31 Libraries

star icon1139

10

karliuka

29 Libraries

star icon422

1

63 Libraries

star icon1631

2

47 Libraries

star icon441

3

43 Libraries

star icon762

4

41 Libraries

star icon1002

5

39 Libraries

star icon13734

6

37 Libraries

star icon318

7

35 Libraries

star icon574

8

33 Libraries

star icon3232

9

31 Libraries

star icon1139

10

29 Libraries

star icon422

Trending Kits in Ecommerce

Java E-Commerce Libraries help build e-commerce websites. It provides various frameworks, tools, and utilities for developing online shopping websites. 


There are many Java E-Commerce libraries available in the market, which enable you to write your own e-commerce website in easy steps. Java E-Commerce Libraries like shopizer, micro-ecommerce, and keyist-ecommerce are also used for developing an eCommerce website. These libraries are used in e-commerce applications since they provide a platform for making payment gateways, shopping carts, and other functionalities of an e-commerce website.


Shopizer is the most popular Java e-commerce library that allows you to create a customized online store without any coding. It comes with integrated payment gateways, shipping plugins, and many other features, which make it one of the best options for small businesses looking to start an online store. Keyist-Ecommerce is an open-source Java library that allows you to build an online store with minimal effort and time. The library supports multiple languages, including English, Chinese, Japanese and Korean. It also offers integrated payment gateways, shipping plugins, and other features that make it easy for developers to build custom websites without having to write any code themselves. Micro-eCommerce is an open-source Java library that allows you to build an online store without any coding knowledge required by developers. It has over 350 features built in along with integrated payment gateways, shipping plugins, and many other features that make it easy for developers to create custom websites. Some of the most popular Java E-Commerce Libraries among developers are given below

shopizer:  

  • Shopizer is an open-source e-commerce software platform designed for building.  
  • It is a flexible and customizable solution for businesses.  
  • Shopizer is released under the Apache 2.0 license, making it open-source and free to use.  

eCommerce-order-service:  

  • eCommerce-order-service is a Java library typically used in websites and e-commerce applications.  
  • It has a Permissive License, and it has a medium support.  
  • It handles various aspects related to customer orders. 

micro-ecommerce:  

  • Micro-ecommerce might refer to the use of microservices architecture in the context.  
  • This architecture aims to improve scalability, maintainability, and agility in the development.  
  • Micro-ecommerce helps describe smaller or lighter e-commerce businesses.  

Keyist-Ecommerce:  

  • Keyist-Ecommerce is a term used within a specific context or community.  
  • It may be beneficial to seek information from sources associated with that context.  
  • This will provide the most accurate and up-to-date information about its features and functionalities.  

e-commerce-microservice:  

  • e-commerce microservice refers to the application of microservices architecture in the development.  
  • Microservices architecture is an approach where a large and complex application decomposes.  
  • Microservice in the e-commerce system handles a specific business capability.  

ddd-example-ecommerce:  

  • DDD is an approach to software development. It emphasizes understanding the business domain and modeling it in code.  
  • DDD often involves defining bounded contexts to encapsulate specific business domains.  
  • DDD distinguishes between entities and value objects. Entities have an identity and are mutable.  

Android-E-Commerce-Shopping-Application:  

  • Android-E-Commerce-Shopping-Application is a Java library. It is typically used in Retail, Security, Authentication, and Firebase applications.  
  • Android-E-Commerce-Shopping-Application has no bugs or vulnerabilities.  
  • It has a Permissive License, and it has low support.  

Ecommerce-Morningmist-Android:  

  • Ecommerce-Morningmist-Android is a Java library that is typically used in retail websites.  
  • Ecommerce-Morningmist-Android has no vulnerabilities reported, and its dependent libraries have no vulnerabilities reported. 

FAQ

1. What are Java E-commerce Libraries?  

Java E-commerce Libraries are sets of pre-built, reusable code components and functionalities. These libraries often include modules for product management, cart handling, and payment processing.  

  

2. Why use Java for E-commerce Development?  

Java is popular for its portability, scalability, and robustness. It's platform-independent, making it suitable for building enterprise-level applications. Java has a vast ecosystem and community support. It also contributes to its popularity in e-commerce.  

  

3. Which Java E-commerce Libraries are widely used?  

Some widely used Java E-commerce Libraries include:  

  1. Broadleaf Commerce: An open-source, customizable framework for building e-commerce solutions.  
  2. Hybris: A robust and scalable e-commerce platform.  
  3. Apache OFBiz (Open for Business): An open-source framework for building enterprise automation applications.  

  

4.  How can I integrate Payment Gateways with Java E-commerce Libraries?  

Java E-commerce Libraries often provide APIs or modules for integrating with popular payment. The Developers follow the documentation provided by the library in a specific way.  

  

5. Are there Java E-commerce Libraries suitable for small businesses?  

Yes, some Java E-commerce Libraries cater to the needs of small businesses. The Smaller libraries or frameworks may also be suitable for lightweight e-commerce requirements.  

Trending Discussions on Ecommerce

React state object turning into "[object Object]" on refresh using sessionStorage

Render all products that relate to one of subcategories of one category, in category page

UseParams() not working and not rendering data on screen

Problem with create table Category and get the url correctly PHP

proxy server working in one case and failed in another case

How to send previous items in cart such that my updateCart adds new items on top of previous products in cart

useReducer: dispatch action, show state in other component and update state when action is dispatched

connect spring boot to swagger

Can Django select_for_update be used to acquire a read lock?

Google Tag Manager / Enhanced E-commerce - Purchase tag dataLayer push working only on Tag Assistance

QUESTION

React state object turning into "[object Object]" on refresh using sessionStorage

Asked 2022-Mar-23 at 14:53

I'm working on a dummy fullstack ecommerce app using Postgres, Express and React whilst going through a fullstack course. This question is pretty specific to React.

On login to the app I can successfully create or retrieve a cart from the db and save it to state. It's being saved as a normal object:

Cart: {id: 2, user_id: 159, product_count: 0, price: '£0.00'}

-From Chrome Dev Tools: Extensions React Developer Tools.

I'm then using React useEffect hooks to persist this state in sessionStorage:

App.js

1 useEffect(() => {
2    if (sessionStorage["cart"]) {
3      setCart(window.sessionStorage.getItem("cart"));
4    }
5  }, []);
6
7  useEffect(() => {
8    window.sessionStorage.setItem("cart", cart);
9  }, [cart]);
10

Whenever I refresh the page or go to another route the normal object seems to be turning into the string: "[object Object]".

I know it has something to do with the way I'm saving the cart state variable into the localStorage but I'm not familiar with it enough to know exactly where this is happening or how to fix it so any help would be appreciated.

I've tried changing the assignment variables within the useEffect calls to include trying to save the item as an object, but I'm not familiar enough with sessionStorage to know what's happening behind the scenes.

ANSWER

Answered 2022-Mar-23 at 14:53

When you store the object to storage, call JSON.stringify(cart) to convert from an object to a string.

When you read the object from storage, it's const cart = JSON.parse(cartString) to convert from the string back into an object.

Like so:

1 useEffect(() => {
2    if (sessionStorage["cart"]) {
3      setCart(window.sessionStorage.getItem("cart"));
4    }
5  }, []);
6
7  useEffect(() => {
8    window.sessionStorage.setItem("cart", cart);
9  }, [cart]);
10  useEffect(() => {
11    if (sessionStorage["cart"]) {
12      setCart(JSON.parse(window.sessionStorage.getItem("cart")));
13    }
14  }, []);
15
16  useEffect(() => {
17    window.sessionStorage.setItem("cart", JSON.stringify(cart));
18  }, [cart]);
19

Source https://stackoverflow.com/questions/71589271

QUESTION

Render all products that relate to one of subcategories of one category, in category page

Asked 2022-Mar-07 at 16:38

I had a question. I am creating an ecommerce website in django. There, I have categories and subcategories. When I enter to subcategory page, I able to render all products that relate to this subcategory. But, when I wanted to render all product that relate on one parent category, I am having troubles. So, I have some subcategories in one category. In that category page, I want to render all products that relate to one of subcategories of this category. Can you help me please? models.py

1class Category(models.Model):
2    parent = models.ForeignKey('self', related_name='children', on_delete=models.CASCADE, blank=True, null=True)
3    title = models.CharField(max_length=255)
4    slug = models.SlugField(max_length=255)
5    image = models.ImageField(null=True, blank=True, verbose_name="Изображение")
6    ordering = models.IntegerField(default=0)
7    is_featured = models.BooleanField(default=False)
8
9    class Meta:
10        verbose_name_plural = 'Categories'
11        ordering = ('ordering',)
12
13    def __str__(self):
14        if self.parent is not None:
15            return f"{self.parent}/{self.title}"
16        return self.title
17    
18    @property
19    def imageURL(self):
20        try:
21            url = self.image.url
22        except:
23            url = ''
24        return url
25
26    def get_absolute_url(self):
27        return '/%s/' % (self.slug)
28
29
30class Product(models.Model):
31    category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
32    parent = models.ForeignKey('self', related_name='variants', on_delete=models.CASCADE, blank=True, null=True)
33    name = models.CharField(max_length=200, verbose_name="Название продукта")
34    price = models.IntegerField(verbose_name="Цена")
35    slug = models.SlugField(max_length=255)
36    description = models.CharField(max_length=5000,blank=True, verbose_name="Описание:")
37    image = models.ImageField(null=True, blank=True, verbose_name="Изображение")
38    novinki = models.BooleanField(default=False, verbose_name="Новинки")
39    popularnye = models.BooleanField(default=False, verbose_name="Популарные")
40    def __str__(self):
41        return self.name
42
43    class Meta:
44        verbose_name = 'Продукты'
45        verbose_name_plural = "Продукты"
46        
47
48    @property
49    def imageURL(self):
50        try:
51            url = self.image.url
52        except:
53            url = ''
54        return url
55

views.py

1class Category(models.Model):
2    parent = models.ForeignKey('self', related_name='children', on_delete=models.CASCADE, blank=True, null=True)
3    title = models.CharField(max_length=255)
4    slug = models.SlugField(max_length=255)
5    image = models.ImageField(null=True, blank=True, verbose_name="Изображение")
6    ordering = models.IntegerField(default=0)
7    is_featured = models.BooleanField(default=False)
8
9    class Meta:
10        verbose_name_plural = 'Categories'
11        ordering = ('ordering',)
12
13    def __str__(self):
14        if self.parent is not None:
15            return f"{self.parent}/{self.title}"
16        return self.title
17    
18    @property
19    def imageURL(self):
20        try:
21            url = self.image.url
22        except:
23            url = ''
24        return url
25
26    def get_absolute_url(self):
27        return '/%s/' % (self.slug)
28
29
30class Product(models.Model):
31    category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
32    parent = models.ForeignKey('self', related_name='variants', on_delete=models.CASCADE, blank=True, null=True)
33    name = models.CharField(max_length=200, verbose_name="Название продукта")
34    price = models.IntegerField(verbose_name="Цена")
35    slug = models.SlugField(max_length=255)
36    description = models.CharField(max_length=5000,blank=True, verbose_name="Описание:")
37    image = models.ImageField(null=True, blank=True, verbose_name="Изображение")
38    novinki = models.BooleanField(default=False, verbose_name="Новинки")
39    popularnye = models.BooleanField(default=False, verbose_name="Популарные")
40    def __str__(self):
41        return self.name
42
43    class Meta:
44        verbose_name = 'Продукты'
45        verbose_name_plural = "Продукты"
46        
47
48    @property
49    def imageURL(self):
50        try:
51            url = self.image.url
52        except:
53            url = ''
54        return url
55def category_detail(request, slug):
56    data = cartData(request)
57
58    cartItems = data['cartItems']
59    order = data['order']
60    items = data['items']
61    categories_for_menu = Category.objects.filter(parent=None)[:3]
62    categories = Category.objects.filter(parent=None)
63    category = get_object_or_404(Category, slug=slug)
64    **products_all = Product.objects.filter(category.parent==category)**
65    
66    print(products_all)
67
68    products = category.products.all()
69    context = {'items' : items, 'order' : order, 'cartItems' : cartItems, 'products':products, 'category':category, 'categories':categories,'categories_for_menu':categories_for_menu,'products_all':products_all}
70    
71    return render(request, "store/categories.html", context)
72

Here I want to save all products that relate the category in products_all. Looking forward to your help!

ANSWER

Answered 2022-Mar-07 at 14:48

You can do it using Q function:

1class Category(models.Model):
2    parent = models.ForeignKey('self', related_name='children', on_delete=models.CASCADE, blank=True, null=True)
3    title = models.CharField(max_length=255)
4    slug = models.SlugField(max_length=255)
5    image = models.ImageField(null=True, blank=True, verbose_name="Изображение")
6    ordering = models.IntegerField(default=0)
7    is_featured = models.BooleanField(default=False)
8
9    class Meta:
10        verbose_name_plural = 'Categories'
11        ordering = ('ordering',)
12
13    def __str__(self):
14        if self.parent is not None:
15            return f"{self.parent}/{self.title}"
16        return self.title
17    
18    @property
19    def imageURL(self):
20        try:
21            url = self.image.url
22        except:
23            url = ''
24        return url
25
26    def get_absolute_url(self):
27        return '/%s/' % (self.slug)
28
29
30class Product(models.Model):
31    category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
32    parent = models.ForeignKey('self', related_name='variants', on_delete=models.CASCADE, blank=True, null=True)
33    name = models.CharField(max_length=200, verbose_name="Название продукта")
34    price = models.IntegerField(verbose_name="Цена")
35    slug = models.SlugField(max_length=255)
36    description = models.CharField(max_length=5000,blank=True, verbose_name="Описание:")
37    image = models.ImageField(null=True, blank=True, verbose_name="Изображение")
38    novinki = models.BooleanField(default=False, verbose_name="Новинки")
39    popularnye = models.BooleanField(default=False, verbose_name="Популарные")
40    def __str__(self):
41        return self.name
42
43    class Meta:
44        verbose_name = 'Продукты'
45        verbose_name_plural = "Продукты"
46        
47
48    @property
49    def imageURL(self):
50        try:
51            url = self.image.url
52        except:
53            url = ''
54        return url
55def category_detail(request, slug):
56    data = cartData(request)
57
58    cartItems = data['cartItems']
59    order = data['order']
60    items = data['items']
61    categories_for_menu = Category.objects.filter(parent=None)[:3]
62    categories = Category.objects.filter(parent=None)
63    category = get_object_or_404(Category, slug=slug)
64    **products_all = Product.objects.filter(category.parent==category)**
65    
66    print(products_all)
67
68    products = category.products.all()
69    context = {'items' : items, 'order' : order, 'cartItems' : cartItems, 'products':products, 'category':category, 'categories':categories,'categories_for_menu':categories_for_menu,'products_all':products_all}
70    
71    return render(request, "store/categories.html", context)
72from django.db.models import Q
73
74category = get_object_or_404(Category, slug=slug)
75products = Product.objects.filter(Q(category = category)|Q(category__parent = category))
76

Source https://stackoverflow.com/questions/71382220

QUESTION

UseParams() not working and not rendering data on screen

Asked 2022-Feb-17 at 08:58

I am working on an eCommerce website and I am stuck . I am mapping through a array and it renders Image and a link . I want to click the link(checkitem) on image and it should open the Image and detail in different page but its not working. I am using reactrouter for it and passing the id of the image to useparams() in my Fullcard component . In my Full card component i am filtering and mapping the array according to the id of the image , but it seems to not work .Can you guys help me.

Here is the CodeSandboxLink of the project : https://codesandbox.io/s/strange-driscoll-gpl629?file=/src/App.js

Here is my Appjs :

1import Hero from './Hero';
2import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
3import FullCard from "./FullCard";
4function App() {
5
6  const data = [
7    {
8      burh: "1fdsd",
9      id: 1,
10      img: "https://d3o2e4jr3mxnm3.cloudfront.net/Mens-Jake-Guitar-Vintage-Crusher-Tee_68382_1_lg.png",
11    },
12    {
13      burh: "1fdsd",
14      id: 2,
15      img: "https://cdn.shopify.com/s/files/1/0101/4832/products/Angela_Natural_Tee.png?v=1606780388",
16    },
17    {
18      burh: "1fdsd",
19      id: 3,
20      img: "https://www.prada.com/content/dam/pradanux_products/U/UCS/UCS319/1YOTF010O/UCS319_1YOT_F010O_S_182_SLF.png",
21    },
22    {
23      burh: "1fdsd",
24      id: 4,
25      img: "https://www.burdastyle.com/pub/media/catalog/product/cache/7bd3727382ce0a860b68816435d76e26/107/BUS-PAT-BURTE-1320516/1170x1470_BS_2016_05_132_front.png",
26    },
27  ];
28
29
30
31
32  return (
33    <Router>
34      <Routes>
35        <Route path="/" element={<Hero data={data}/>} />
36        <Route path="/products/:id" element={ <FullCard data={data} />} />
37      </Routes>
38    </Router>
39  );
40}
41
42export default App;
43

Here is my Card:

1import Hero from './Hero';
2import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
3import FullCard from "./FullCard";
4function App() {
5
6  const data = [
7    {
8      burh: "1fdsd",
9      id: 1,
10      img: "https://d3o2e4jr3mxnm3.cloudfront.net/Mens-Jake-Guitar-Vintage-Crusher-Tee_68382_1_lg.png",
11    },
12    {
13      burh: "1fdsd",
14      id: 2,
15      img: "https://cdn.shopify.com/s/files/1/0101/4832/products/Angela_Natural_Tee.png?v=1606780388",
16    },
17    {
18      burh: "1fdsd",
19      id: 3,
20      img: "https://www.prada.com/content/dam/pradanux_products/U/UCS/UCS319/1YOTF010O/UCS319_1YOT_F010O_S_182_SLF.png",
21    },
22    {
23      burh: "1fdsd",
24      id: 4,
25      img: "https://www.burdastyle.com/pub/media/catalog/product/cache/7bd3727382ce0a860b68816435d76e26/107/BUS-PAT-BURTE-1320516/1170x1470_BS_2016_05_132_front.png",
26    },
27  ];
28
29
30
31
32  return (
33    <Router>
34      <Routes>
35        <Route path="/" element={<Hero data={data}/>} />
36        <Route path="/products/:id" element={ <FullCard data={data} />} />
37      </Routes>
38    </Router>
39  );
40}
41
42export default App;
43// import { popularProducts } from "./data";
44import { Link } from "react-router-dom";
45import "./Card.css";
46
47const Card = ({ data }) => {
48  return (
49    <div className="Maincontainer">
50      <div className="CardContainer">
51        {data.map((items, index) => {
52          return (
53            <div className="cards" key={index}>
54              <img src={items.img} alt="/" />
55
56              <Link to={`/products/${items.id}`}>CheckItem</Link>
57            </div>
58          );
59        })}
60      </div>
61    </div>
62  );
63};
64
65export default Card;
66

Here is my Full card comp:

1import Hero from './Hero';
2import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
3import FullCard from "./FullCard";
4function App() {
5
6  const data = [
7    {
8      burh: "1fdsd",
9      id: 1,
10      img: "https://d3o2e4jr3mxnm3.cloudfront.net/Mens-Jake-Guitar-Vintage-Crusher-Tee_68382_1_lg.png",
11    },
12    {
13      burh: "1fdsd",
14      id: 2,
15      img: "https://cdn.shopify.com/s/files/1/0101/4832/products/Angela_Natural_Tee.png?v=1606780388",
16    },
17    {
18      burh: "1fdsd",
19      id: 3,
20      img: "https://www.prada.com/content/dam/pradanux_products/U/UCS/UCS319/1YOTF010O/UCS319_1YOT_F010O_S_182_SLF.png",
21    },
22    {
23      burh: "1fdsd",
24      id: 4,
25      img: "https://www.burdastyle.com/pub/media/catalog/product/cache/7bd3727382ce0a860b68816435d76e26/107/BUS-PAT-BURTE-1320516/1170x1470_BS_2016_05_132_front.png",
26    },
27  ];
28
29
30
31
32  return (
33    <Router>
34      <Routes>
35        <Route path="/" element={<Hero data={data}/>} />
36        <Route path="/products/:id" element={ <FullCard data={data} />} />
37      </Routes>
38    </Router>
39  );
40}
41
42export default App;
43// import { popularProducts } from "./data";
44import { Link } from "react-router-dom";
45import "./Card.css";
46
47const Card = ({ data }) => {
48  return (
49    <div className="Maincontainer">
50      <div className="CardContainer">
51        {data.map((items, index) => {
52          return (
53            <div className="cards" key={index}>
54              <img src={items.img} alt="/" />
55
56              <Link to={`/products/${items.id}`}>CheckItem</Link>
57            </div>
58          );
59        })}
60      </div>
61    </div>
62  );
63};
64
65export default Card;
66import { useParams  } from 'react-router-dom'
67
68const FullCard = ({data}) => {
69
70    const {id} = useParams();
71
72
73  return (
74    <div className='container'>
75        {data.filter(  (items )=> items.id === id ).map((items,index) =>{
76            return (
77                <div key={items} className="container2">
78                    <h1>{items.burh}</h1>
79                    {/* <img src={items.image} alt="/" /> */}
80                </div>
81            );
82        })}
83    </div>
84  )
85}
86

ANSWER

Answered 2022-Feb-17 at 06:32
Issue

The id properties in data are number types, but the id route match param will be a string. The data filtering in FullCard is failing because you are using strict equality, which requires both operands to be of the same type. In this case, either both numbers or both strings.

1import Hero from './Hero';
2import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
3import FullCard from "./FullCard";
4function App() {
5
6  const data = [
7    {
8      burh: "1fdsd",
9      id: 1,
10      img: "https://d3o2e4jr3mxnm3.cloudfront.net/Mens-Jake-Guitar-Vintage-Crusher-Tee_68382_1_lg.png",
11    },
12    {
13      burh: "1fdsd",
14      id: 2,
15      img: "https://cdn.shopify.com/s/files/1/0101/4832/products/Angela_Natural_Tee.png?v=1606780388",
16    },
17    {
18      burh: "1fdsd",
19      id: 3,
20      img: "https://www.prada.com/content/dam/pradanux_products/U/UCS/UCS319/1YOTF010O/UCS319_1YOT_F010O_S_182_SLF.png",
21    },
22    {
23      burh: "1fdsd",
24      id: 4,
25      img: "https://www.burdastyle.com/pub/media/catalog/product/cache/7bd3727382ce0a860b68816435d76e26/107/BUS-PAT-BURTE-1320516/1170x1470_BS_2016_05_132_front.png",
26    },
27  ];
28
29
30
31
32  return (
33    <Router>
34      <Routes>
35        <Route path="/" element={<Hero data={data}/>} />
36        <Route path="/products/:id" element={ <FullCard data={data} />} />
37      </Routes>
38    </Router>
39  );
40}
41
42export default App;
43// import { popularProducts } from "./data";
44import { Link } from "react-router-dom";
45import "./Card.css";
46
47const Card = ({ data }) => {
48  return (
49    <div className="Maincontainer">
50      <div className="CardContainer">
51        {data.map((items, index) => {
52          return (
53            <div className="cards" key={index}>
54              <img src={items.img} alt="/" />
55
56              <Link to={`/products/${items.id}`}>CheckItem</Link>
57            </div>
58          );
59        })}
60      </div>
61    </div>
62  );
63};
64
65export default Card;
66import { useParams  } from 'react-router-dom'
67
68const FullCard = ({data}) => {
69
70    const {id} = useParams();
71
72
73  return (
74    <div className='container'>
75        {data.filter(  (items )=> items.id === id ).map((items,index) =>{
76            return (
77                <div key={items} className="container2">
78                    <h1>{items.burh}</h1>
79                    {/* <img src={items.image} alt="/" /> */}
80                </div>
81            );
82        })}
83    </div>
84  )
85}
86{data
87  .filter((items) => items.id === id) // <-- type mismatch comparision
88  .map((items, index) => {
89    return (
90      <div key={items.id} className="container2">
91        <h1>{items.burh}</h1>
92        {/* <img src={items.image} alt="/" /> */}
93      </div>
94    );
95  })}
96
Solution

Either use loose equality, i.e. == so type coercion/conversion is attempted in determining equality

1import Hero from './Hero';
2import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
3import FullCard from "./FullCard";
4function App() {
5
6  const data = [
7    {
8      burh: "1fdsd",
9      id: 1,
10      img: "https://d3o2e4jr3mxnm3.cloudfront.net/Mens-Jake-Guitar-Vintage-Crusher-Tee_68382_1_lg.png",
11    },
12    {
13      burh: "1fdsd",
14      id: 2,
15      img: "https://cdn.shopify.com/s/files/1/0101/4832/products/Angela_Natural_Tee.png?v=1606780388",
16    },
17    {
18      burh: "1fdsd",
19      id: 3,
20      img: "https://www.prada.com/content/dam/pradanux_products/U/UCS/UCS319/1YOTF010O/UCS319_1YOT_F010O_S_182_SLF.png",
21    },
22    {
23      burh: "1fdsd",
24      id: 4,
25      img: "https://www.burdastyle.com/pub/media/catalog/product/cache/7bd3727382ce0a860b68816435d76e26/107/BUS-PAT-BURTE-1320516/1170x1470_BS_2016_05_132_front.png",
26    },
27  ];
28
29
30
31
32  return (
33    <Router>
34      <Routes>
35        <Route path="/" element={<Hero data={data}/>} />
36        <Route path="/products/:id" element={ <FullCard data={data} />} />
37      </Routes>
38    </Router>
39  );
40}
41
42export default App;
43// import { popularProducts } from "./data";
44import { Link } from "react-router-dom";
45import "./Card.css";
46
47const Card = ({ data }) => {
48  return (
49    <div className="Maincontainer">
50      <div className="CardContainer">
51        {data.map((items, index) => {
52          return (
53            <div className="cards" key={index}>
54              <img src={items.img} alt="/" />
55
56              <Link to={`/products/${items.id}`}>CheckItem</Link>
57            </div>
58          );
59        })}
60      </div>
61    </div>
62  );
63};
64
65export default Card;
66import { useParams  } from 'react-router-dom'
67
68const FullCard = ({data}) => {
69
70    const {id} = useParams();
71
72
73  return (
74    <div className='container'>
75        {data.filter(  (items )=> items.id === id ).map((items,index) =>{
76            return (
77                <div key={items} className="container2">
78                    <h1>{items.burh}</h1>
79                    {/* <img src={items.image} alt="/" /> */}
80                </div>
81            );
82        })}
83    </div>
84  )
85}
86{data
87  .filter((items) => items.id === id) // <-- type mismatch comparision
88  .map((items, index) => {
89    return (
90      <div key={items.id} className="container2">
91        <h1>{items.burh}</h1>
92        {/* <img src={items.image} alt="/" /> */}
93      </div>
94    );
95  })}
96.filter((items) => items.id == id)
97

or convert the items.id to a string and use string equality

1import Hero from './Hero';
2import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
3import FullCard from "./FullCard";
4function App() {
5
6  const data = [
7    {
8      burh: "1fdsd",
9      id: 1,
10      img: "https://d3o2e4jr3mxnm3.cloudfront.net/Mens-Jake-Guitar-Vintage-Crusher-Tee_68382_1_lg.png",
11    },
12    {
13      burh: "1fdsd",
14      id: 2,
15      img: "https://cdn.shopify.com/s/files/1/0101/4832/products/Angela_Natural_Tee.png?v=1606780388",
16    },
17    {
18      burh: "1fdsd",
19      id: 3,
20      img: "https://www.prada.com/content/dam/pradanux_products/U/UCS/UCS319/1YOTF010O/UCS319_1YOT_F010O_S_182_SLF.png",
21    },
22    {
23      burh: "1fdsd",
24      id: 4,
25      img: "https://www.burdastyle.com/pub/media/catalog/product/cache/7bd3727382ce0a860b68816435d76e26/107/BUS-PAT-BURTE-1320516/1170x1470_BS_2016_05_132_front.png",
26    },
27  ];
28
29
30
31
32  return (
33    <Router>
34      <Routes>
35        <Route path="/" element={<Hero data={data}/>} />
36        <Route path="/products/:id" element={ <FullCard data={data} />} />
37      </Routes>
38    </Router>
39  );
40}
41
42export default App;
43// import { popularProducts } from "./data";
44import { Link } from "react-router-dom";
45import "./Card.css";
46
47const Card = ({ data }) => {
48  return (
49    <div className="Maincontainer">
50      <div className="CardContainer">
51        {data.map((items, index) => {
52          return (
53            <div className="cards" key={index}>
54              <img src={items.img} alt="/" />
55
56              <Link to={`/products/${items.id}`}>CheckItem</Link>
57            </div>
58          );
59        })}
60      </div>
61    </div>
62  );
63};
64
65export default Card;
66import { useParams  } from 'react-router-dom'
67
68const FullCard = ({data}) => {
69
70    const {id} = useParams();
71
72
73  return (
74    <div className='container'>
75        {data.filter(  (items )=> items.id === id ).map((items,index) =>{
76            return (
77                <div key={items} className="container2">
78                    <h1>{items.burh}</h1>
79                    {/* <img src={items.image} alt="/" /> */}
80                </div>
81            );
82        })}
83    </div>
84  )
85}
86{data
87  .filter((items) => items.id === id) // <-- type mismatch comparision
88  .map((items, index) => {
89    return (
90      <div key={items.id} className="container2">
91        <h1>{items.burh}</h1>
92        {/* <img src={items.image} alt="/" /> */}
93      </div>
94    );
95  })}
96.filter((items) => items.id == id)
97.filter((items) => String(items.id) === id)
98

Edit useparams-not-working-and-not-rendering-data-on-screen

Source https://stackoverflow.com/questions/71153347

QUESTION

Problem with create table Category and get the url correctly PHP

Asked 2022-Feb-03 at 07:22

I am creating an ecommerce, which can have Men's Fashion, Women's Fashion or Children's Fashion, it could also have more in the fure like Sports, Electronics, etc.

But I don't know if I have, for example, to repeat the categories clothes, etc for each one or not, I don't know if there is a better way. Since I must also create the dynamic menu

My table structure is like this:

1CREATE TABLE `category`(
2   `category_id` smallint(3) unsigned not null auto_increment primary key,   
3   `category_name` VARCHAR(40) NOT NULL,
4   `category_url` VARCHAR(40) NOT NULL,
5   `icon`varchar(150) default null,
6   `gender` enum('Men','Woman','Baby') default null,
7   `parent` INT DEFAULT NULL
8)engine=InnoDB default charset=utf8mb4 collate=utf8mb4_spanish_ci;
9

Some posible inserts what i want:

1CREATE TABLE `category`(
2   `category_id` smallint(3) unsigned not null auto_increment primary key,   
3   `category_name` VARCHAR(40) NOT NULL,
4   `category_url` VARCHAR(40) NOT NULL,
5   `icon`varchar(150) default null,
6   `gender` enum('Men','Woman','Baby') default null,
7   `parent` INT DEFAULT NULL
8)engine=InnoDB default charset=utf8mb4 collate=utf8mb4_spanish_ci;
9INSERT INTO `category` (`category_id`, `category_name`, `category_url`, `icon`, `gender`, `parent`) VALUES
10-- Mens section
11(1, 'Mens Fashion', 'mens-fashion', null, null, null), -- Mens fasion
12-- clothes mens
13(2, 'Clothing', 'clothing', 'clothing.svg', null, 1), -- (level 2)
14(3, 'Shoes', 'Shoes', 'shoes.svg', null, 1), -- (level 2)
15(4, 'Complements', 'complements', 'complements.svg', null, 1), -- (level 2)
16
17(5, 'Shirts', 'shirts', null, null, 2), -- (level 3)
18(6, 'Casual shirts', 'casaul-shirts', null, null, 5), -- (level 4)
19(7, 'Suit shirts ', 'suit-shirts', null, null, 5), --(level 4)
20
21(8, 'Jeans', 'jeans', null, null, 2), -- (level 3)
22(9, 'Jeans skinny', 'jeans-skinny', null, null, 8), -- (level 4)
23(10, 'Jeans slim fit', 'jeans-slim-fit', null, null, 8), -- (level 4)
24
25(11, 'Underwear', 'Underwear', null, null, 2), -- (level 3)
26(12, 'Socks', 'socks', null, null, 11), -- (level 4)
27
28-- Woman section
29(13, 'Woman Fashion', 'woman-fasion', null, null, null), -- (level 1)
30-- Clothes woman
31(14, 'Clothing', 'clothing', 'clothing.svg', null, 13), -- (level 2)
32(15, 'Shoes', 'Shoes', 'shoes.svg', null, 13), -- (level 2)
33(16, 'Complements', 'complements', 'complements.svg', null, 13), -- (level 2)
34
35(17, 'Shirts', 'shirts', null, null, 13), -- (level 3)
36(18, 'Casual shirts', 'casaul-shirts', null, null, 17), -- (level 4)
37(19, 'Suit shirts', 'suit-shirts', null, null, 17), -- (level 4)
38(20, 'Top shirt', 'top-shirt', null, null, 17), -- (level 4)
39
40(21, 'Jeans', 'jeans', null, null, 13), -- (level 3)
41(22, 'Jeans skinny', 'jeans-skinny', null, null, 21), -- (level 4)
42(23, 'Jeans slim fit', 'jeans-slim-fit', null, null, 21), -- (level 4)
43
44(24, 'Underwear', 'Underwear', null, null, 13), -- (level 3)
45(25, 'Socks', 'socks', null, null, 24), -- (level 4)
46
47-- Childeren section
48(13, 'Childerens Fasion', 'childeren-fashion', null, null, null), -- (level 1)
49-- Clothes childeren etc..
50

It's that ok what I'm doing, repeat for each section the same categories as clothes, Jeans, etc.?

I really do this because otherwise I don't know how to create the menu gives the image that I leave below

Another question i have.

I am creating this menu, with said table, which is what I want to obtain.

enter image description here

Is there any way to get the url in this way:

mens-fashion/clothing/shirts

because for example shirts would be the url above.

So what i mean, if the category is level 4, the url would be: level1/level2/level3/level4.

What would be better:
To add it directly to my table the absolute path or
can i do that with PHP, i leave the code that I am using.

1CREATE TABLE `category`(
2   `category_id` smallint(3) unsigned not null auto_increment primary key,   
3   `category_name` VARCHAR(40) NOT NULL,
4   `category_url` VARCHAR(40) NOT NULL,
5   `icon`varchar(150) default null,
6   `gender` enum('Men','Woman','Baby') default null,
7   `parent` INT DEFAULT NULL
8)engine=InnoDB default charset=utf8mb4 collate=utf8mb4_spanish_ci;
9INSERT INTO `category` (`category_id`, `category_name`, `category_url`, `icon`, `gender`, `parent`) VALUES
10-- Mens section
11(1, 'Mens Fashion', 'mens-fashion', null, null, null), -- Mens fasion
12-- clothes mens
13(2, 'Clothing', 'clothing', 'clothing.svg', null, 1), -- (level 2)
14(3, 'Shoes', 'Shoes', 'shoes.svg', null, 1), -- (level 2)
15(4, 'Complements', 'complements', 'complements.svg', null, 1), -- (level 2)
16
17(5, 'Shirts', 'shirts', null, null, 2), -- (level 3)
18(6, 'Casual shirts', 'casaul-shirts', null, null, 5), -- (level 4)
19(7, 'Suit shirts ', 'suit-shirts', null, null, 5), --(level 4)
20
21(8, 'Jeans', 'jeans', null, null, 2), -- (level 3)
22(9, 'Jeans skinny', 'jeans-skinny', null, null, 8), -- (level 4)
23(10, 'Jeans slim fit', 'jeans-slim-fit', null, null, 8), -- (level 4)
24
25(11, 'Underwear', 'Underwear', null, null, 2), -- (level 3)
26(12, 'Socks', 'socks', null, null, 11), -- (level 4)
27
28-- Woman section
29(13, 'Woman Fashion', 'woman-fasion', null, null, null), -- (level 1)
30-- Clothes woman
31(14, 'Clothing', 'clothing', 'clothing.svg', null, 13), -- (level 2)
32(15, 'Shoes', 'Shoes', 'shoes.svg', null, 13), -- (level 2)
33(16, 'Complements', 'complements', 'complements.svg', null, 13), -- (level 2)
34
35(17, 'Shirts', 'shirts', null, null, 13), -- (level 3)
36(18, 'Casual shirts', 'casaul-shirts', null, null, 17), -- (level 4)
37(19, 'Suit shirts', 'suit-shirts', null, null, 17), -- (level 4)
38(20, 'Top shirt', 'top-shirt', null, null, 17), -- (level 4)
39
40(21, 'Jeans', 'jeans', null, null, 13), -- (level 3)
41(22, 'Jeans skinny', 'jeans-skinny', null, null, 21), -- (level 4)
42(23, 'Jeans slim fit', 'jeans-slim-fit', null, null, 21), -- (level 4)
43
44(24, 'Underwear', 'Underwear', null, null, 13), -- (level 3)
45(25, 'Socks', 'socks', null, null, 24), -- (level 4)
46
47-- Childeren section
48(13, 'Childerens Fasion', 'childeren-fashion', null, null, null), -- (level 1)
49-- Clothes childeren etc..
50$categories = $db->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
51$cat = $categories->fetchAll(PDO::FETCH_ASSOC);
52
53$arrayMenu = array();
54
55foreach($cat as $row){
56$arrayMenu[$row['category_id']] = array("parent" => $row['parent'], "category_name" => $row['category_name'], "category_url" => $row['category_url']);
57}
58
59function createTree($array, $curParent, $currLevel = 0, $prevLevel = -1) {
60
61    foreach ($array as $categoryId => $category) :
62
63        if ($curParent == $category['parent']) :
64
65            if($category['parent']==0) $class="dropdown"; else $class="sub_menu";
66            if ($currLevel > $prevLevel) echo " <ul class='$class'> ";
67
68
69            if ($currLevel == $prevLevel) echo " </li> ";
70
71            echo '<li id="'.$categoryId.'" ><a href="'.$category['category_url'].'">'.$category['category_name'].'</a>';
72
73            if ($currLevel > $prevLevel) { $prevLevel = $currLevel; }
74
75            $currLevel++;
76
77            createTree ($array, $categoryId, $currLevel, $prevLevel);
78
79            $currLevel--;
80        endif;
81    endforeach;
82
83    if ($currLevel == $prevLevel) echo " </li> </ul> ";
84}
85?>
86<div class="nav">
87<?php
88if ($cat != null) createTree($arrayMenu, 0);
89?>
90

I tried to add this line to get, for example, the level 1 url, but it doesn't:

$url_level1 = ($row['parent'] == 0) ? $row['category_url'] : '';

Edit:

The css with which I was testing: (It doesn't really have styles and it's outdated)

1CREATE TABLE `category`(
2   `category_id` smallint(3) unsigned not null auto_increment primary key,   
3   `category_name` VARCHAR(40) NOT NULL,
4   `category_url` VARCHAR(40) NOT NULL,
5   `icon`varchar(150) default null,
6   `gender` enum('Men','Woman','Baby') default null,
7   `parent` INT DEFAULT NULL
8)engine=InnoDB default charset=utf8mb4 collate=utf8mb4_spanish_ci;
9INSERT INTO `category` (`category_id`, `category_name`, `category_url`, `icon`, `gender`, `parent`) VALUES
10-- Mens section
11(1, 'Mens Fashion', 'mens-fashion', null, null, null), -- Mens fasion
12-- clothes mens
13(2, 'Clothing', 'clothing', 'clothing.svg', null, 1), -- (level 2)
14(3, 'Shoes', 'Shoes', 'shoes.svg', null, 1), -- (level 2)
15(4, 'Complements', 'complements', 'complements.svg', null, 1), -- (level 2)
16
17(5, 'Shirts', 'shirts', null, null, 2), -- (level 3)
18(6, 'Casual shirts', 'casaul-shirts', null, null, 5), -- (level 4)
19(7, 'Suit shirts ', 'suit-shirts', null, null, 5), --(level 4)
20
21(8, 'Jeans', 'jeans', null, null, 2), -- (level 3)
22(9, 'Jeans skinny', 'jeans-skinny', null, null, 8), -- (level 4)
23(10, 'Jeans slim fit', 'jeans-slim-fit', null, null, 8), -- (level 4)
24
25(11, 'Underwear', 'Underwear', null, null, 2), -- (level 3)
26(12, 'Socks', 'socks', null, null, 11), -- (level 4)
27
28-- Woman section
29(13, 'Woman Fashion', 'woman-fasion', null, null, null), -- (level 1)
30-- Clothes woman
31(14, 'Clothing', 'clothing', 'clothing.svg', null, 13), -- (level 2)
32(15, 'Shoes', 'Shoes', 'shoes.svg', null, 13), -- (level 2)
33(16, 'Complements', 'complements', 'complements.svg', null, 13), -- (level 2)
34
35(17, 'Shirts', 'shirts', null, null, 13), -- (level 3)
36(18, 'Casual shirts', 'casaul-shirts', null, null, 17), -- (level 4)
37(19, 'Suit shirts', 'suit-shirts', null, null, 17), -- (level 4)
38(20, 'Top shirt', 'top-shirt', null, null, 17), -- (level 4)
39
40(21, 'Jeans', 'jeans', null, null, 13), -- (level 3)
41(22, 'Jeans skinny', 'jeans-skinny', null, null, 21), -- (level 4)
42(23, 'Jeans slim fit', 'jeans-slim-fit', null, null, 21), -- (level 4)
43
44(24, 'Underwear', 'Underwear', null, null, 13), -- (level 3)
45(25, 'Socks', 'socks', null, null, 24), -- (level 4)
46
47-- Childeren section
48(13, 'Childerens Fasion', 'childeren-fashion', null, null, null), -- (level 1)
49-- Clothes childeren etc..
50$categories = $db->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
51$cat = $categories->fetchAll(PDO::FETCH_ASSOC);
52
53$arrayMenu = array();
54
55foreach($cat as $row){
56$arrayMenu[$row['category_id']] = array("parent" => $row['parent'], "category_name" => $row['category_name'], "category_url" => $row['category_url']);
57}
58
59function createTree($array, $curParent, $currLevel = 0, $prevLevel = -1) {
60
61    foreach ($array as $categoryId => $category) :
62
63        if ($curParent == $category['parent']) :
64
65            if($category['parent']==0) $class="dropdown"; else $class="sub_menu";
66            if ($currLevel > $prevLevel) echo " <ul class='$class'> ";
67
68
69            if ($currLevel == $prevLevel) echo " </li> ";
70
71            echo '<li id="'.$categoryId.'" ><a href="'.$category['category_url'].'">'.$category['category_name'].'</a>';
72
73            if ($currLevel > $prevLevel) { $prevLevel = $currLevel; }
74
75            $currLevel++;
76
77            createTree ($array, $categoryId, $currLevel, $prevLevel);
78
79            $currLevel--;
80        endif;
81    endforeach;
82
83    if ($currLevel == $prevLevel) echo " </li> </ul> ";
84}
85?>
86<div class="nav">
87<?php
88if ($cat != null) createTree($arrayMenu, 0);
89?>
90nav ul li { 
91    background:#f1f1f1; list-style: none;
92}
93ul.dropdown { 
94    position:relative; 
95    width:auto; 
96    font:12px Arial, Helvetica, sans-serif; 
97}
98ul.dropdown li { 
99    float:left; zoom:1; 
100    height:auto; 
101    min-height: 30px; 
102    padding:6px 2px 0 2px; 
103}
104
105ul.dropdown li li { 
106    border-right:1px solid #ccc; 
107    border-left:1px solid #ccc; 
108    margin-left:-30px;
109}
110ul.dropdown a:hover { 
111    color:#000; 
112} 
113ul.dropdown a:active { color:#ffa500; }
114
115ul.dropdown li a { 
116    display:block; 
117    padding:4px 8px; 
118    color:#000; 
119    text-decoration:none; 
120    font:bold 12px Arial, Helvetica, sans-serif; 
121}
122
123ul.dropdown li:last-child a { border-right:none;} /* Doesn't work in IE */
124ul.dropdown li:hover { 
125    color:#000; 
126    background:#e7e7e7; 
127    position:relative; }
128ul.dropdown li.hover a { color:#000; }
129ul.dropdown ul { 
130    text-align:left; 
131    visibility: hidden; 
132    position: absolute; 
133    left:-10px; 
134    top:36px; }
135ul.dropdown ul li { 
136    background:#f1f1f1; 
137    border-bottom:1px solid #ccc; 
138    float:none; width:120px; 
139    height:auto; 
140    min-height: 25px; 
141}
142ul.dropdown ul li a { 
143    border-right:none; 
144    width:100%; 
145    display:inline-block; color:#000; }
146ul.dropdown ul ul { 
147    left:100%; 
148    top:0; 
149}
150ul.dropdown li:hover > ul { visibility:visible; }
151

Note: What I realy was creating was something like this:

1CREATE TABLE `category`(
2   `category_id` smallint(3) unsigned not null auto_increment primary key,   
3   `category_name` VARCHAR(40) NOT NULL,
4   `category_url` VARCHAR(40) NOT NULL,
5   `icon`varchar(150) default null,
6   `gender` enum('Men','Woman','Baby') default null,
7   `parent` INT DEFAULT NULL
8)engine=InnoDB default charset=utf8mb4 collate=utf8mb4_spanish_ci;
9INSERT INTO `category` (`category_id`, `category_name`, `category_url`, `icon`, `gender`, `parent`) VALUES
10-- Mens section
11(1, 'Mens Fashion', 'mens-fashion', null, null, null), -- Mens fasion
12-- clothes mens
13(2, 'Clothing', 'clothing', 'clothing.svg', null, 1), -- (level 2)
14(3, 'Shoes', 'Shoes', 'shoes.svg', null, 1), -- (level 2)
15(4, 'Complements', 'complements', 'complements.svg', null, 1), -- (level 2)
16
17(5, 'Shirts', 'shirts', null, null, 2), -- (level 3)
18(6, 'Casual shirts', 'casaul-shirts', null, null, 5), -- (level 4)
19(7, 'Suit shirts ', 'suit-shirts', null, null, 5), --(level 4)
20
21(8, 'Jeans', 'jeans', null, null, 2), -- (level 3)
22(9, 'Jeans skinny', 'jeans-skinny', null, null, 8), -- (level 4)
23(10, 'Jeans slim fit', 'jeans-slim-fit', null, null, 8), -- (level 4)
24
25(11, 'Underwear', 'Underwear', null, null, 2), -- (level 3)
26(12, 'Socks', 'socks', null, null, 11), -- (level 4)
27
28-- Woman section
29(13, 'Woman Fashion', 'woman-fasion', null, null, null), -- (level 1)
30-- Clothes woman
31(14, 'Clothing', 'clothing', 'clothing.svg', null, 13), -- (level 2)
32(15, 'Shoes', 'Shoes', 'shoes.svg', null, 13), -- (level 2)
33(16, 'Complements', 'complements', 'complements.svg', null, 13), -- (level 2)
34
35(17, 'Shirts', 'shirts', null, null, 13), -- (level 3)
36(18, 'Casual shirts', 'casaul-shirts', null, null, 17), -- (level 4)
37(19, 'Suit shirts', 'suit-shirts', null, null, 17), -- (level 4)
38(20, 'Top shirt', 'top-shirt', null, null, 17), -- (level 4)
39
40(21, 'Jeans', 'jeans', null, null, 13), -- (level 3)
41(22, 'Jeans skinny', 'jeans-skinny', null, null, 21), -- (level 4)
42(23, 'Jeans slim fit', 'jeans-slim-fit', null, null, 21), -- (level 4)
43
44(24, 'Underwear', 'Underwear', null, null, 13), -- (level 3)
45(25, 'Socks', 'socks', null, null, 24), -- (level 4)
46
47-- Childeren section
48(13, 'Childerens Fasion', 'childeren-fashion', null, null, null), -- (level 1)
49-- Clothes childeren etc..
50$categories = $db->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
51$cat = $categories->fetchAll(PDO::FETCH_ASSOC);
52
53$arrayMenu = array();
54
55foreach($cat as $row){
56$arrayMenu[$row['category_id']] = array("parent" => $row['parent'], "category_name" => $row['category_name'], "category_url" => $row['category_url']);
57}
58
59function createTree($array, $curParent, $currLevel = 0, $prevLevel = -1) {
60
61    foreach ($array as $categoryId => $category) :
62
63        if ($curParent == $category['parent']) :
64
65            if($category['parent']==0) $class="dropdown"; else $class="sub_menu";
66            if ($currLevel > $prevLevel) echo " <ul class='$class'> ";
67
68
69            if ($currLevel == $prevLevel) echo " </li> ";
70
71            echo '<li id="'.$categoryId.'" ><a href="'.$category['category_url'].'">'.$category['category_name'].'</a>';
72
73            if ($currLevel > $prevLevel) { $prevLevel = $currLevel; }
74
75            $currLevel++;
76
77            createTree ($array, $categoryId, $currLevel, $prevLevel);
78
79            $currLevel--;
80        endif;
81    endforeach;
82
83    if ($currLevel == $prevLevel) echo " </li> </ul> ";
84}
85?>
86<div class="nav">
87<?php
88if ($cat != null) createTree($arrayMenu, 0);
89?>
90nav ul li { 
91    background:#f1f1f1; list-style: none;
92}
93ul.dropdown { 
94    position:relative; 
95    width:auto; 
96    font:12px Arial, Helvetica, sans-serif; 
97}
98ul.dropdown li { 
99    float:left; zoom:1; 
100    height:auto; 
101    min-height: 30px; 
102    padding:6px 2px 0 2px; 
103}
104
105ul.dropdown li li { 
106    border-right:1px solid #ccc; 
107    border-left:1px solid #ccc; 
108    margin-left:-30px;
109}
110ul.dropdown a:hover { 
111    color:#000; 
112} 
113ul.dropdown a:active { color:#ffa500; }
114
115ul.dropdown li a { 
116    display:block; 
117    padding:4px 8px; 
118    color:#000; 
119    text-decoration:none; 
120    font:bold 12px Arial, Helvetica, sans-serif; 
121}
122
123ul.dropdown li:last-child a { border-right:none;} /* Doesn't work in IE */
124ul.dropdown li:hover { 
125    color:#000; 
126    background:#e7e7e7; 
127    position:relative; }
128ul.dropdown li.hover a { color:#000; }
129ul.dropdown ul { 
130    text-align:left; 
131    visibility: hidden; 
132    position: absolute; 
133    left:-10px; 
134    top:36px; }
135ul.dropdown ul li { 
136    background:#f1f1f1; 
137    border-bottom:1px solid #ccc; 
138    float:none; width:120px; 
139    height:auto; 
140    min-height: 25px; 
141}
142ul.dropdown ul li a { 
143    border-right:none; 
144    width:100%; 
145    display:inline-block; color:#000; }
146ul.dropdown ul ul { 
147    left:100%; 
148    top:0; 
149}
150ul.dropdown li:hover > ul { visibility:visible; }
151// Tab header ///////
152function openPage(pageName, elmnt, color) {
153  // Hide all elements with class="tabcontent" by default */
154  var i, tabcontent, tablinks;
155  tabcontent = document.getElementsByClassName("tabcontent");
156  for (i = 0; i < tabcontent.length; i++) {
157    tabcontent[i].style.display = "none";
158  }
159
160  // Remove the background color of all tablinks/buttons
161  tablinks = document.getElementsByClassName("tablink");
162  for (i = 0; i < tablinks.length; i++) {
163    tablinks[i].style.background = "";
164  }
165
166  // Show the specific tab content
167  document.getElementById(pageName).style.display = "block";
168
169  // Add the specific color to the button used to open the tab content
170  elmnt.style.background = color;
171}
172
173// Get the element with id="defaultOpen" and click on it
174document.getElementById("defaultOpen").click();
175
176
177// Accordion ///////
178var acc = document.getElementsByClassName("accordion");
179var i;
180
181for (i = 0; i < acc.length; i++) {
182  acc[i].addEventListener("click", function() {
183    this.classList.toggle("active");
184    var panel = this.nextElementSibling;
185    if (panel.style.maxHeight) {
186      panel.style.maxHeight = null;
187    } else {
188      panel.style.maxHeight = panel.scrollHeight + "px";
189    }
190  });
191}
1CREATE TABLE `category`(
2   `category_id` smallint(3) unsigned not null auto_increment primary key,   
3   `category_name` VARCHAR(40) NOT NULL,
4   `category_url` VARCHAR(40) NOT NULL,
5   `icon`varchar(150) default null,
6   `gender` enum('Men','Woman','Baby') default null,
7   `parent` INT DEFAULT NULL
8)engine=InnoDB default charset=utf8mb4 collate=utf8mb4_spanish_ci;
9INSERT INTO `category` (`category_id`, `category_name`, `category_url`, `icon`, `gender`, `parent`) VALUES
10-- Mens section
11(1, 'Mens Fashion', 'mens-fashion', null, null, null), -- Mens fasion
12-- clothes mens
13(2, 'Clothing', 'clothing', 'clothing.svg', null, 1), -- (level 2)
14(3, 'Shoes', 'Shoes', 'shoes.svg', null, 1), -- (level 2)
15(4, 'Complements', 'complements', 'complements.svg', null, 1), -- (level 2)
16
17(5, 'Shirts', 'shirts', null, null, 2), -- (level 3)
18(6, 'Casual shirts', 'casaul-shirts', null, null, 5), -- (level 4)
19(7, 'Suit shirts ', 'suit-shirts', null, null, 5), --(level 4)
20
21(8, 'Jeans', 'jeans', null, null, 2), -- (level 3)
22(9, 'Jeans skinny', 'jeans-skinny', null, null, 8), -- (level 4)
23(10, 'Jeans slim fit', 'jeans-slim-fit', null, null, 8), -- (level 4)
24
25(11, 'Underwear', 'Underwear', null, null, 2), -- (level 3)
26(12, 'Socks', 'socks', null, null, 11), -- (level 4)
27
28-- Woman section
29(13, 'Woman Fashion', 'woman-fasion', null, null, null), -- (level 1)
30-- Clothes woman
31(14, 'Clothing', 'clothing', 'clothing.svg', null, 13), -- (level 2)
32(15, 'Shoes', 'Shoes', 'shoes.svg', null, 13), -- (level 2)
33(16, 'Complements', 'complements', 'complements.svg', null, 13), -- (level 2)
34
35(17, 'Shirts', 'shirts', null, null, 13), -- (level 3)
36(18, 'Casual shirts', 'casaul-shirts', null, null, 17), -- (level 4)
37(19, 'Suit shirts', 'suit-shirts', null, null, 17), -- (level 4)
38(20, 'Top shirt', 'top-shirt', null, null, 17), -- (level 4)
39
40(21, 'Jeans', 'jeans', null, null, 13), -- (level 3)
41(22, 'Jeans skinny', 'jeans-skinny', null, null, 21), -- (level 4)
42(23, 'Jeans slim fit', 'jeans-slim-fit', null, null, 21), -- (level 4)
43
44(24, 'Underwear', 'Underwear', null, null, 13), -- (level 3)
45(25, 'Socks', 'socks', null, null, 24), -- (level 4)
46
47-- Childeren section
48(13, 'Childerens Fasion', 'childeren-fashion', null, null, null), -- (level 1)
49-- Clothes childeren etc..
50$categories = $db->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
51$cat = $categories->fetchAll(PDO::FETCH_ASSOC);
52
53$arrayMenu = array();
54
55foreach($cat as $row){
56$arrayMenu[$row['category_id']] = array("parent" => $row['parent'], "category_name" => $row['category_name'], "category_url" => $row['category_url']);
57}
58
59function createTree($array, $curParent, $currLevel = 0, $prevLevel = -1) {
60
61    foreach ($array as $categoryId => $category) :
62
63        if ($curParent == $category['parent']) :
64
65            if($category['parent']==0) $class="dropdown"; else $class="sub_menu";
66            if ($currLevel > $prevLevel) echo " <ul class='$class'> ";
67
68
69            if ($currLevel == $prevLevel) echo " </li> ";
70
71            echo '<li id="'.$categoryId.'" ><a href="'.$category['category_url'].'">'.$category['category_name'].'</a>';
72
73            if ($currLevel > $prevLevel) { $prevLevel = $currLevel; }
74
75            $currLevel++;
76
77            createTree ($array, $categoryId, $currLevel, $prevLevel);
78
79            $currLevel--;
80        endif;
81    endforeach;
82
83    if ($currLevel == $prevLevel) echo " </li> </ul> ";
84}
85?>
86<div class="nav">
87<?php
88if ($cat != null) createTree($arrayMenu, 0);
89?>
90nav ul li { 
91    background:#f1f1f1; list-style: none;
92}
93ul.dropdown { 
94    position:relative; 
95    width:auto; 
96    font:12px Arial, Helvetica, sans-serif; 
97}
98ul.dropdown li { 
99    float:left; zoom:1; 
100    height:auto; 
101    min-height: 30px; 
102    padding:6px 2px 0 2px; 
103}
104
105ul.dropdown li li { 
106    border-right:1px solid #ccc; 
107    border-left:1px solid #ccc; 
108    margin-left:-30px;
109}
110ul.dropdown a:hover { 
111    color:#000; 
112} 
113ul.dropdown a:active { color:#ffa500; }
114
115ul.dropdown li a { 
116    display:block; 
117    padding:4px 8px; 
118    color:#000; 
119    text-decoration:none; 
120    font:bold 12px Arial, Helvetica, sans-serif; 
121}
122
123ul.dropdown li:last-child a { border-right:none;} /* Doesn't work in IE */
124ul.dropdown li:hover { 
125    color:#000; 
126    background:#e7e7e7; 
127    position:relative; }
128ul.dropdown li.hover a { color:#000; }
129ul.dropdown ul { 
130    text-align:left; 
131    visibility: hidden; 
132    position: absolute; 
133    left:-10px; 
134    top:36px; }
135ul.dropdown ul li { 
136    background:#f1f1f1; 
137    border-bottom:1px solid #ccc; 
138    float:none; width:120px; 
139    height:auto; 
140    min-height: 25px; 
141}
142ul.dropdown ul li a { 
143    border-right:none; 
144    width:100%; 
145    display:inline-block; color:#000; }
146ul.dropdown ul ul { 
147    left:100%; 
148    top:0; 
149}
150ul.dropdown li:hover > ul { visibility:visible; }
151// Tab header ///////
152function openPage(pageName, elmnt, color) {
153  // Hide all elements with class="tabcontent" by default */
154  var i, tabcontent, tablinks;
155  tabcontent = document.getElementsByClassName("tabcontent");
156  for (i = 0; i < tabcontent.length; i++) {
157    tabcontent[i].style.display = "none";
158  }
159
160  // Remove the background color of all tablinks/buttons
161  tablinks = document.getElementsByClassName("tablink");
162  for (i = 0; i < tablinks.length; i++) {
163    tablinks[i].style.background = "";
164  }
165
166  // Show the specific tab content
167  document.getElementById(pageName).style.display = "block";
168
169  // Add the specific color to the button used to open the tab content
170  elmnt.style.background = color;
171}
172
173// Get the element with id="defaultOpen" and click on it
174document.getElementById("defaultOpen").click();
175
176
177// Accordion ///////
178var acc = document.getElementsByClassName("accordion");
179var i;
180
181for (i = 0; i < acc.length; i++) {
182  acc[i].addEventListener("click", function() {
183    this.classList.toggle("active");
184    var panel = this.nextElementSibling;
185    if (panel.style.maxHeight) {
186      panel.style.maxHeight = null;
187    } else {
188      panel.style.maxHeight = panel.scrollHeight + "px";
189    }
190  });
191}/* TAB HEADER MENU */
192
193#wrapper-tablink {
194  display: flex;
195  flex-flow: row nowrap;
196  justify-content: center;
197  align-items: center;
198}
199
200
201/* Style tab links */
202
203.tablink {
204  background-color: #555;
205  color: white;
206  border: none;
207  outline: none;
208  cursor: pointer;
209  padding: 14px 16px;
210  font-size: 17px;
211  width: 25%;
212}
213
214.tablink:hover {
215  background-color: #777;
216}
217
218.tablink .active {
219  color: #000;
220}
221
222
223/* Style the tab content (and add height:100% for full page content) */
224
225.tabcontent {
226  color: white;
227  display: none;
228  padding: 100px 20px;
229  height: 100%;
230  overflow-y: auto;
231}
232
233
234/*
235#moda-mujer {background-color: var(--secundary-color);}
236#moda-hombre {background-color: #00cc99;}
237#electronica {background-color: #3399ff;}
238#cursos {background-color: #9933ff;}
239*/
240
241.wrapper-icons-bars {
242  display: flex;
243  flex-flow: row nowrap;
244  justify-content: center;
245  align-items: center;
246  margin: 10px 0 20px 0;
247}
248
249.wrapper-icons-bars a {
250  display: block;
251  position: relative;
252  background-color: #FFFFFF;
253  border-bottom: 3px solid var(--body-color);
254  border-right: 1px solid #F1F1F1;
255  padding: 20px;
256  transition: all 0.3s ease;
257}
258
259.wrapper-icons-bars a:hover {
260  display: block;
261  position: relative;
262  border-bottom: 3px solid var(--secundary-color);
263  padding: 25px;
264  transition: all 0.3s ease;
265}
266
267
268/* ACCORDIAN CONTENT */
269
270.wrapper-accordion {
271  display: flex;
272  justify-content: center;
273  width: 100%;
274  margin-bottom: 80px;
275}
276
277.accordion {
278  display: flex;
279  position: relative;
280  justify-content: center;
281  align-items: center;
282  background-color: #eee;
283  color: #444;
284  cursor: pointer;
285  padding: 18px;
286  width: 100%;
287  max-width: 500px;
288  min-width: 500px;
289  border: none;
290  text-align: left;
291  outline: none;
292  font-size: 15px;
293  transition: 0.4s;
294}
295
296.active,
297.accordion:hover {
298  background-color: #ccc;
299}
300
301.accordion:after {
302  content: '\002B';
303  color: #777;
304  font-weight: bold;
305  display: block;
306  position: absolute;
307  right: 25px;
308  margin-left: 5px;
309}
310
311.active:after {
312  content: "\2212";
313}
314
315.panel {
316  background-color: white;
317  color: var(--body-color);
318  max-height: 0;
319  width: 100%;
320  overflow: hidden;
321  transition: max-height 0.2s ease-out;
322}
323
324.inner-panel {
325  padding: 20px 20px;
326  width: 100%;
327  max-width: 500px;
328}
329
330.wrapper-accordion a {
331  color: var(--body-color);
332}
1CREATE TABLE `category`(
2   `category_id` smallint(3) unsigned not null auto_increment primary key,   
3   `category_name` VARCHAR(40) NOT NULL,
4   `category_url` VARCHAR(40) NOT NULL,
5   `icon`varchar(150) default null,
6   `gender` enum('Men','Woman','Baby') default null,
7   `parent` INT DEFAULT NULL
8)engine=InnoDB default charset=utf8mb4 collate=utf8mb4_spanish_ci;
9INSERT INTO `category` (`category_id`, `category_name`, `category_url`, `icon`, `gender`, `parent`) VALUES
10-- Mens section
11(1, 'Mens Fashion', 'mens-fashion', null, null, null), -- Mens fasion
12-- clothes mens
13(2, 'Clothing', 'clothing', 'clothing.svg', null, 1), -- (level 2)
14(3, 'Shoes', 'Shoes', 'shoes.svg', null, 1), -- (level 2)
15(4, 'Complements', 'complements', 'complements.svg', null, 1), -- (level 2)
16
17(5, 'Shirts', 'shirts', null, null, 2), -- (level 3)
18(6, 'Casual shirts', 'casaul-shirts', null, null, 5), -- (level 4)
19(7, 'Suit shirts ', 'suit-shirts', null, null, 5), --(level 4)
20
21(8, 'Jeans', 'jeans', null, null, 2), -- (level 3)
22(9, 'Jeans skinny', 'jeans-skinny', null, null, 8), -- (level 4)
23(10, 'Jeans slim fit', 'jeans-slim-fit', null, null, 8), -- (level 4)
24
25(11, 'Underwear', 'Underwear', null, null, 2), -- (level 3)
26(12, 'Socks', 'socks', null, null, 11), -- (level 4)
27
28-- Woman section
29(13, 'Woman Fashion', 'woman-fasion', null, null, null), -- (level 1)
30-- Clothes woman
31(14, 'Clothing', 'clothing', 'clothing.svg', null, 13), -- (level 2)
32(15, 'Shoes', 'Shoes', 'shoes.svg', null, 13), -- (level 2)
33(16, 'Complements', 'complements', 'complements.svg', null, 13), -- (level 2)
34
35(17, 'Shirts', 'shirts', null, null, 13), -- (level 3)
36(18, 'Casual shirts', 'casaul-shirts', null, null, 17), -- (level 4)
37(19, 'Suit shirts', 'suit-shirts', null, null, 17), -- (level 4)
38(20, 'Top shirt', 'top-shirt', null, null, 17), -- (level 4)
39
40(21, 'Jeans', 'jeans', null, null, 13), -- (level 3)
41(22, 'Jeans skinny', 'jeans-skinny', null, null, 21), -- (level 4)
42(23, 'Jeans slim fit', 'jeans-slim-fit', null, null, 21), -- (level 4)
43
44(24, 'Underwear', 'Underwear', null, null, 13), -- (level 3)
45(25, 'Socks', 'socks', null, null, 24), -- (level 4)
46
47-- Childeren section
48(13, 'Childerens Fasion', 'childeren-fashion', null, null, null), -- (level 1)
49-- Clothes childeren etc..
50$categories = $db->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
51$cat = $categories->fetchAll(PDO::FETCH_ASSOC);
52
53$arrayMenu = array();
54
55foreach($cat as $row){
56$arrayMenu[$row['category_id']] = array("parent" => $row['parent'], "category_name" => $row['category_name'], "category_url" => $row['category_url']);
57}
58
59function createTree($array, $curParent, $currLevel = 0, $prevLevel = -1) {
60
61    foreach ($array as $categoryId => $category) :
62
63        if ($curParent == $category['parent']) :
64
65            if($category['parent']==0) $class="dropdown"; else $class="sub_menu";
66            if ($currLevel > $prevLevel) echo " <ul class='$class'> ";
67
68
69            if ($currLevel == $prevLevel) echo " </li> ";
70
71            echo '<li id="'.$categoryId.'" ><a href="'.$category['category_url'].'">'.$category['category_name'].'</a>';
72
73            if ($currLevel > $prevLevel) { $prevLevel = $currLevel; }
74
75            $currLevel++;
76
77            createTree ($array, $categoryId, $currLevel, $prevLevel);
78
79            $currLevel--;
80        endif;
81    endforeach;
82
83    if ($currLevel == $prevLevel) echo " </li> </ul> ";
84}
85?>
86<div class="nav">
87<?php
88if ($cat != null) createTree($arrayMenu, 0);
89?>
90nav ul li { 
91    background:#f1f1f1; list-style: none;
92}
93ul.dropdown { 
94    position:relative; 
95    width:auto; 
96    font:12px Arial, Helvetica, sans-serif; 
97}
98ul.dropdown li { 
99    float:left; zoom:1; 
100    height:auto; 
101    min-height: 30px; 
102    padding:6px 2px 0 2px; 
103}
104
105ul.dropdown li li { 
106    border-right:1px solid #ccc; 
107    border-left:1px solid #ccc; 
108    margin-left:-30px;
109}
110ul.dropdown a:hover { 
111    color:#000; 
112} 
113ul.dropdown a:active { color:#ffa500; }
114
115ul.dropdown li a { 
116    display:block; 
117    padding:4px 8px; 
118    color:#000; 
119    text-decoration:none; 
120    font:bold 12px Arial, Helvetica, sans-serif; 
121}
122
123ul.dropdown li:last-child a { border-right:none;} /* Doesn't work in IE */
124ul.dropdown li:hover { 
125    color:#000; 
126    background:#e7e7e7; 
127    position:relative; }
128ul.dropdown li.hover a { color:#000; }
129ul.dropdown ul { 
130    text-align:left; 
131    visibility: hidden; 
132    position: absolute; 
133    left:-10px; 
134    top:36px; }
135ul.dropdown ul li { 
136    background:#f1f1f1; 
137    border-bottom:1px solid #ccc; 
138    float:none; width:120px; 
139    height:auto; 
140    min-height: 25px; 
141}
142ul.dropdown ul li a { 
143    border-right:none; 
144    width:100%; 
145    display:inline-block; color:#000; }
146ul.dropdown ul ul { 
147    left:100%; 
148    top:0; 
149}
150ul.dropdown li:hover > ul { visibility:visible; }
151// Tab header ///////
152function openPage(pageName, elmnt, color) {
153  // Hide all elements with class="tabcontent" by default */
154  var i, tabcontent, tablinks;
155  tabcontent = document.getElementsByClassName("tabcontent");
156  for (i = 0; i < tabcontent.length; i++) {
157    tabcontent[i].style.display = "none";
158  }
159
160  // Remove the background color of all tablinks/buttons
161  tablinks = document.getElementsByClassName("tablink");
162  for (i = 0; i < tablinks.length; i++) {
163    tablinks[i].style.background = "";
164  }
165
166  // Show the specific tab content
167  document.getElementById(pageName).style.display = "block";
168
169  // Add the specific color to the button used to open the tab content
170  elmnt.style.background = color;
171}
172
173// Get the element with id="defaultOpen" and click on it
174document.getElementById("defaultOpen").click();
175
176
177// Accordion ///////
178var acc = document.getElementsByClassName("accordion");
179var i;
180
181for (i = 0; i < acc.length; i++) {
182  acc[i].addEventListener("click", function() {
183    this.classList.toggle("active");
184    var panel = this.nextElementSibling;
185    if (panel.style.maxHeight) {
186      panel.style.maxHeight = null;
187    } else {
188      panel.style.maxHeight = panel.scrollHeight + "px";
189    }
190  });
191}/* TAB HEADER MENU */
192
193#wrapper-tablink {
194  display: flex;
195  flex-flow: row nowrap;
196  justify-content: center;
197  align-items: center;
198}
199
200
201/* Style tab links */
202
203.tablink {
204  background-color: #555;
205  color: white;
206  border: none;
207  outline: none;
208  cursor: pointer;
209  padding: 14px 16px;
210  font-size: 17px;
211  width: 25%;
212}
213
214.tablink:hover {
215  background-color: #777;
216}
217
218.tablink .active {
219  color: #000;
220}
221
222
223/* Style the tab content (and add height:100% for full page content) */
224
225.tabcontent {
226  color: white;
227  display: none;
228  padding: 100px 20px;
229  height: 100%;
230  overflow-y: auto;
231}
232
233
234/*
235#moda-mujer {background-color: var(--secundary-color);}
236#moda-hombre {background-color: #00cc99;}
237#electronica {background-color: #3399ff;}
238#cursos {background-color: #9933ff;}
239*/
240
241.wrapper-icons-bars {
242  display: flex;
243  flex-flow: row nowrap;
244  justify-content: center;
245  align-items: center;
246  margin: 10px 0 20px 0;
247}
248
249.wrapper-icons-bars a {
250  display: block;
251  position: relative;
252  background-color: #FFFFFF;
253  border-bottom: 3px solid var(--body-color);
254  border-right: 1px solid #F1F1F1;
255  padding: 20px;
256  transition: all 0.3s ease;
257}
258
259.wrapper-icons-bars a:hover {
260  display: block;
261  position: relative;
262  border-bottom: 3px solid var(--secundary-color);
263  padding: 25px;
264  transition: all 0.3s ease;
265}
266
267
268/* ACCORDIAN CONTENT */
269
270.wrapper-accordion {
271  display: flex;
272  justify-content: center;
273  width: 100%;
274  margin-bottom: 80px;
275}
276
277.accordion {
278  display: flex;
279  position: relative;
280  justify-content: center;
281  align-items: center;
282  background-color: #eee;
283  color: #444;
284  cursor: pointer;
285  padding: 18px;
286  width: 100%;
287  max-width: 500px;
288  min-width: 500px;
289  border: none;
290  text-align: left;
291  outline: none;
292  font-size: 15px;
293  transition: 0.4s;
294}
295
296.active,
297.accordion:hover {
298  background-color: #ccc;
299}
300
301.accordion:after {
302  content: '\002B';
303  color: #777;
304  font-weight: bold;
305  display: block;
306  position: absolute;
307  right: 25px;
308  margin-left: 5px;
309}
310
311.active:after {
312  content: "\2212";
313}
314
315.panel {
316  background-color: white;
317  color: var(--body-color);
318  max-height: 0;
319  width: 100%;
320  overflow: hidden;
321  transition: max-height 0.2s ease-out;
322}
323
324.inner-panel {
325  padding: 20px 20px;
326  width: 100%;
327  max-width: 500px;
328}
329
330.wrapper-accordion a {
331  color: var(--body-color);
332}<!-- Create Tab links header (Table: controllers) -->
333<div id="wrapper-tablink">
334  <button class="tablink" onclick="openPage('mens-fashion', this, 'blue')" id="defaultOpen">Mens Fashion</button>
335  <button class="tablink" onclick="openPage('womans-fashion', this, 'red')" id="defaultOpen">Womans Fashion</button>
336</div>
337
338<div id='mens-fashion' class='tabcontent' style='blue'>
339  <article class='wrapper-accordion'>
340    <div>
341      <h2><a href='mens-fashion/clothes'>Clothes</a></h2>
342      <div class='wrapper-icons-bars'>icons</div>
343      <button class='accordion active'>Clothes</button>
344      <div class='panel' style='max-height: 1000px;'>
345        <div class='inner-panel'>
346          <h5><a href='mens-fashion/clothes'>Clothes</a></h5>
347          <a>Tshirt </a>
348        </div>
349      </div>
350
351      <button class='accordion'>Shoes</button>
352      <div class='panel'>
353        <div class='inner-panel'>
354          <h5><a href='mens-fashion/shoes'>Shoes</a></h5>
355          <a>Deport shoes </a>
356        </div>
357      </div>
358
359      <button class='accordion'>Complements</button>
360      <div class='panel'>
361        <div class='inner-panel'>
362          <h5><a href='mens-fashion/complemnts'>Shoes</a></h5>
363          <a>Clock </a>
364        </div>
365      </div>
366    </div>
367  </article>
368
369</div>
370
371<div id='womans-fashion' class='tabcontent' style='red'>
372  <article class='wrapper-accordion'>
373    <div>
374      <h2><a href='womans-fashion/clothes'>Clothes</a></h2>
375      <div class='wrapper-icons-bars'>icons</div>
376      <button class='accordion active'>Clothes</button>
377      <div class='panel' style='max-height: 1000px;'>
378        <div class='inner-panel'>
379          <h5><a href='womans-fashion/clothes'>Clothes</a></h5>
380          <a>Tshirt </a>
381        </div>
382      </div>
383
384      <button class='accordion'>Shoes</button>
385      <div class='panel'>
386        <div class='inner-panel'>
387          <h5><a href='womans-fashion/shoes'>Shoes</a></h5>
388          <a>Deport shoes </a>
389        </div>
390      </div>
391
392      <button class='accordion'>Complements</button>
393      <div class='panel'>
394        <div class='inner-panel'>
395          <h5><a href='womans-fashion/complemnts'>Shoes</a></h5>
396          <a>Clock </a>
397        </div>
398      </div>
399    </div>
400  </article>
401
402</div>

enter image description here

ANSWER

Answered 2022-Feb-03 at 07:22

It's that ok what I'm doing, repeat for each section the same categories as clothes, Jeans, etc.?

Yes, It's perfectly okay to do that. Personally, that is what I prefer.

What would be better: To add it directly to my table the absolute path or can i do that with PHP

You can easily achieve it with PHP.

Kindly use these functions to generate the markup for the nested categories. You can modify the HTML to achieve your desired results.

1CREATE TABLE `category`(
2   `category_id` smallint(3) unsigned not null auto_increment primary key,   
3   `category_name` VARCHAR(40) NOT NULL,
4   `category_url` VARCHAR(40) NOT NULL,
5   `icon`varchar(150) default null,
6   `gender` enum('Men','Woman','Baby') default null,
7   `parent` INT DEFAULT NULL
8)engine=InnoDB default charset=utf8mb4 collate=utf8mb4_spanish_ci;
9INSERT INTO `category` (`category_id`, `category_name`, `category_url`, `icon`, `gender`, `parent`) VALUES
10-- Mens section
11(1, 'Mens Fashion', 'mens-fashion', null, null, null), -- Mens fasion
12-- clothes mens
13(2, 'Clothing', 'clothing', 'clothing.svg', null, 1), -- (level 2)
14(3, 'Shoes', 'Shoes', 'shoes.svg', null, 1), -- (level 2)
15(4, 'Complements', 'complements', 'complements.svg', null, 1), -- (level 2)
16
17(5, 'Shirts', 'shirts', null, null, 2), -- (level 3)
18(6, 'Casual shirts', 'casaul-shirts', null, null, 5), -- (level 4)
19(7, 'Suit shirts ', 'suit-shirts', null, null, 5), --(level 4)
20
21(8, 'Jeans', 'jeans', null, null, 2), -- (level 3)
22(9, 'Jeans skinny', 'jeans-skinny', null, null, 8), -- (level 4)
23(10, 'Jeans slim fit', 'jeans-slim-fit', null, null, 8), -- (level 4)
24
25(11, 'Underwear', 'Underwear', null, null, 2), -- (level 3)
26(12, 'Socks', 'socks', null, null, 11), -- (level 4)
27
28-- Woman section
29(13, 'Woman Fashion', 'woman-fasion', null, null, null), -- (level 1)
30-- Clothes woman
31(14, 'Clothing', 'clothing', 'clothing.svg', null, 13), -- (level 2)
32(15, 'Shoes', 'Shoes', 'shoes.svg', null, 13), -- (level 2)
33(16, 'Complements', 'complements', 'complements.svg', null, 13), -- (level 2)
34
35(17, 'Shirts', 'shirts', null, null, 13), -- (level 3)
36(18, 'Casual shirts', 'casaul-shirts', null, null, 17), -- (level 4)
37(19, 'Suit shirts', 'suit-shirts', null, null, 17), -- (level 4)
38(20, 'Top shirt', 'top-shirt', null, null, 17), -- (level 4)
39
40(21, 'Jeans', 'jeans', null, null, 13), -- (level 3)
41(22, 'Jeans skinny', 'jeans-skinny', null, null, 21), -- (level 4)
42(23, 'Jeans slim fit', 'jeans-slim-fit', null, null, 21), -- (level 4)
43
44(24, 'Underwear', 'Underwear', null, null, 13), -- (level 3)
45(25, 'Socks', 'socks', null, null, 24), -- (level 4)
46
47-- Childeren section
48(13, 'Childerens Fasion', 'childeren-fashion', null, null, null), -- (level 1)
49-- Clothes childeren etc..
50$categories = $db->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
51$cat = $categories->fetchAll(PDO::FETCH_ASSOC);
52
53$arrayMenu = array();
54
55foreach($cat as $row){
56$arrayMenu[$row['category_id']] = array("parent" => $row['parent'], "category_name" => $row['category_name'], "category_url" => $row['category_url']);
57}
58
59function createTree($array, $curParent, $currLevel = 0, $prevLevel = -1) {
60
61    foreach ($array as $categoryId => $category) :
62
63        if ($curParent == $category['parent']) :
64
65            if($category['parent']==0) $class="dropdown"; else $class="sub_menu";
66            if ($currLevel > $prevLevel) echo " <ul class='$class'> ";
67
68
69            if ($currLevel == $prevLevel) echo " </li> ";
70
71            echo '<li id="'.$categoryId.'" ><a href="'.$category['category_url'].'">'.$category['category_name'].'</a>';
72
73            if ($currLevel > $prevLevel) { $prevLevel = $currLevel; }
74
75            $currLevel++;
76
77            createTree ($array, $categoryId, $currLevel, $prevLevel);
78
79            $currLevel--;
80        endif;
81    endforeach;
82
83    if ($currLevel == $prevLevel) echo " </li> </ul> ";
84}
85?>
86<div class="nav">
87<?php
88if ($cat != null) createTree($arrayMenu, 0);
89?>
90nav ul li { 
91    background:#f1f1f1; list-style: none;
92}
93ul.dropdown { 
94    position:relative; 
95    width:auto; 
96    font:12px Arial, Helvetica, sans-serif; 
97}
98ul.dropdown li { 
99    float:left; zoom:1; 
100    height:auto; 
101    min-height: 30px; 
102    padding:6px 2px 0 2px; 
103}
104
105ul.dropdown li li { 
106    border-right:1px solid #ccc; 
107    border-left:1px solid #ccc; 
108    margin-left:-30px;
109}
110ul.dropdown a:hover { 
111    color:#000; 
112} 
113ul.dropdown a:active { color:#ffa500; }
114
115ul.dropdown li a { 
116    display:block; 
117    padding:4px 8px; 
118    color:#000; 
119    text-decoration:none; 
120    font:bold 12px Arial, Helvetica, sans-serif; 
121}
122
123ul.dropdown li:last-child a { border-right:none;} /* Doesn't work in IE */
124ul.dropdown li:hover { 
125    color:#000; 
126    background:#e7e7e7; 
127    position:relative; }
128ul.dropdown li.hover a { color:#000; }
129ul.dropdown ul { 
130    text-align:left; 
131    visibility: hidden; 
132    position: absolute; 
133    left:-10px; 
134    top:36px; }
135ul.dropdown ul li { 
136    background:#f1f1f1; 
137    border-bottom:1px solid #ccc; 
138    float:none; width:120px; 
139    height:auto; 
140    min-height: 25px; 
141}
142ul.dropdown ul li a { 
143    border-right:none; 
144    width:100%; 
145    display:inline-block; color:#000; }
146ul.dropdown ul ul { 
147    left:100%; 
148    top:0; 
149}
150ul.dropdown li:hover > ul { visibility:visible; }
151// Tab header ///////
152function openPage(pageName, elmnt, color) {
153  // Hide all elements with class="tabcontent" by default */
154  var i, tabcontent, tablinks;
155  tabcontent = document.getElementsByClassName("tabcontent");
156  for (i = 0; i < tabcontent.length; i++) {
157    tabcontent[i].style.display = "none";
158  }
159
160  // Remove the background color of all tablinks/buttons
161  tablinks = document.getElementsByClassName("tablink");
162  for (i = 0; i < tablinks.length; i++) {
163    tablinks[i].style.background = "";
164  }
165
166  // Show the specific tab content
167  document.getElementById(pageName).style.display = "block";
168
169  // Add the specific color to the button used to open the tab content
170  elmnt.style.background = color;
171}
172
173// Get the element with id="defaultOpen" and click on it
174document.getElementById("defaultOpen").click();
175
176
177// Accordion ///////
178var acc = document.getElementsByClassName("accordion");
179var i;
180
181for (i = 0; i < acc.length; i++) {
182  acc[i].addEventListener("click", function() {
183    this.classList.toggle("active");
184    var panel = this.nextElementSibling;
185    if (panel.style.maxHeight) {
186      panel.style.maxHeight = null;
187    } else {
188      panel.style.maxHeight = panel.scrollHeight + "px";
189    }
190  });
191}/* TAB HEADER MENU */
192
193#wrapper-tablink {
194  display: flex;
195  flex-flow: row nowrap;
196  justify-content: center;
197  align-items: center;
198}
199
200
201/* Style tab links */
202
203.tablink {
204  background-color: #555;
205  color: white;
206  border: none;
207  outline: none;
208  cursor: pointer;
209  padding: 14px 16px;
210  font-size: 17px;
211  width: 25%;
212}
213
214.tablink:hover {
215  background-color: #777;
216}
217
218.tablink .active {
219  color: #000;
220}
221
222
223/* Style the tab content (and add height:100% for full page content) */
224
225.tabcontent {
226  color: white;
227  display: none;
228  padding: 100px 20px;
229  height: 100%;
230  overflow-y: auto;
231}
232
233
234/*
235#moda-mujer {background-color: var(--secundary-color);}
236#moda-hombre {background-color: #00cc99;}
237#electronica {background-color: #3399ff;}
238#cursos {background-color: #9933ff;}
239*/
240
241.wrapper-icons-bars {
242  display: flex;
243  flex-flow: row nowrap;
244  justify-content: center;
245  align-items: center;
246  margin: 10px 0 20px 0;
247}
248
249.wrapper-icons-bars a {
250  display: block;
251  position: relative;
252  background-color: #FFFFFF;
253  border-bottom: 3px solid var(--body-color);
254  border-right: 1px solid #F1F1F1;
255  padding: 20px;
256  transition: all 0.3s ease;
257}
258
259.wrapper-icons-bars a:hover {
260  display: block;
261  position: relative;
262  border-bottom: 3px solid var(--secundary-color);
263  padding: 25px;
264  transition: all 0.3s ease;
265}
266
267
268/* ACCORDIAN CONTENT */
269
270.wrapper-accordion {
271  display: flex;
272  justify-content: center;
273  width: 100%;
274  margin-bottom: 80px;
275}
276
277.accordion {
278  display: flex;
279  position: relative;
280  justify-content: center;
281  align-items: center;
282  background-color: #eee;
283  color: #444;
284  cursor: pointer;
285  padding: 18px;
286  width: 100%;
287  max-width: 500px;
288  min-width: 500px;
289  border: none;
290  text-align: left;
291  outline: none;
292  font-size: 15px;
293  transition: 0.4s;
294}
295
296.active,
297.accordion:hover {
298  background-color: #ccc;
299}
300
301.accordion:after {
302  content: '\002B';
303  color: #777;
304  font-weight: bold;
305  display: block;
306  position: absolute;
307  right: 25px;
308  margin-left: 5px;
309}
310
311.active:after {
312  content: "\2212";
313}
314
315.panel {
316  background-color: white;
317  color: var(--body-color);
318  max-height: 0;
319  width: 100%;
320  overflow: hidden;
321  transition: max-height 0.2s ease-out;
322}
323
324.inner-panel {
325  padding: 20px 20px;
326  width: 100%;
327  max-width: 500px;
328}
329
330.wrapper-accordion a {
331  color: var(--body-color);
332}<!-- Create Tab links header (Table: controllers) -->
333<div id="wrapper-tablink">
334  <button class="tablink" onclick="openPage('mens-fashion', this, 'blue')" id="defaultOpen">Mens Fashion</button>
335  <button class="tablink" onclick="openPage('womans-fashion', this, 'red')" id="defaultOpen">Womans Fashion</button>
336</div>
337
338<div id='mens-fashion' class='tabcontent' style='blue'>
339  <article class='wrapper-accordion'>
340    <div>
341      <h2><a href='mens-fashion/clothes'>Clothes</a></h2>
342      <div class='wrapper-icons-bars'>icons</div>
343      <button class='accordion active'>Clothes</button>
344      <div class='panel' style='max-height: 1000px;'>
345        <div class='inner-panel'>
346          <h5><a href='mens-fashion/clothes'>Clothes</a></h5>
347          <a>Tshirt </a>
348        </div>
349      </div>
350
351      <button class='accordion'>Shoes</button>
352      <div class='panel'>
353        <div class='inner-panel'>
354          <h5><a href='mens-fashion/shoes'>Shoes</a></h5>
355          <a>Deport shoes </a>
356        </div>
357      </div>
358
359      <button class='accordion'>Complements</button>
360      <div class='panel'>
361        <div class='inner-panel'>
362          <h5><a href='mens-fashion/complemnts'>Shoes</a></h5>
363          <a>Clock </a>
364        </div>
365      </div>
366    </div>
367  </article>
368
369</div>
370
371<div id='womans-fashion' class='tabcontent' style='red'>
372  <article class='wrapper-accordion'>
373    <div>
374      <h2><a href='womans-fashion/clothes'>Clothes</a></h2>
375      <div class='wrapper-icons-bars'>icons</div>
376      <button class='accordion active'>Clothes</button>
377      <div class='panel' style='max-height: 1000px;'>
378        <div class='inner-panel'>
379          <h5><a href='womans-fashion/clothes'>Clothes</a></h5>
380          <a>Tshirt </a>
381        </div>
382      </div>
383
384      <button class='accordion'>Shoes</button>
385      <div class='panel'>
386        <div class='inner-panel'>
387          <h5><a href='womans-fashion/shoes'>Shoes</a></h5>
388          <a>Deport shoes </a>
389        </div>
390      </div>
391
392      <button class='accordion'>Complements</button>
393      <div class='panel'>
394        <div class='inner-panel'>
395          <h5><a href='womans-fashion/complemnts'>Shoes</a></h5>
396          <a>Clock </a>
397        </div>
398      </div>
399    </div>
400  </article>
401
402</div>// convert the categories array to parents with nested children
403function convertToLevels ($array) {
404    // First, convert the array so that the keys match the ids
405    $reKeyed = array();
406    foreach ($array as $item) {
407        $reKeyed[$item['category_id']] = $item;
408    }
409    // Next, use references to associate children with parents
410    foreach ($reKeyed as $id => $item) {
411        if (isset($item['parent'], $reKeyed[$item['parent']])) {
412            $reKeyed[$item['parent']]['children'][] =& $reKeyed[$id];
413        }
414    }
415    // Finally, go through and remove children from the outer level
416    foreach ($reKeyed as $id => $item) {
417        if (isset($item['parent'])) {
418            unset($reKeyed[$id]);
419        }
420    }
421    return $reKeyed;
422}
423
424// create menu li
425function createMenuItem($item, $url){
426    $html  = '';
427    $html .= '<li class="menu-item '.(!empty($item['children']) ? 'has-child' : '').'">';
428    $html .=    '<a href="'.$url.'" class="menu-link">';
429                    if(!empty($item['icon'])):
430    $html .=            '<i class="'.$item['icon'].'"></i>';
431                    endif;
432    $html .=        $item['category_name'];
433    $html .=    '</a>';
434                if(!empty($item['children'])):
435    $html .=        createMenu($item['children'], $url);
436                endif;
437    $html .= '</li>';
438    
439    return $html;
440}
441
442// menu
443function createMenu($menu, $url_prefix=''){
444    $html  = '';
445    $html .= '<ul class="menu">';
446                foreach($menu as $item):
447    $html .=        createMenuItem($item, $url_prefix.'/'.$item['category_url']);
448                endforeach;
449    $html .= '</ul>';
450
451    return $html;
452}
453

You can use it like so

1CREATE TABLE `category`(
2   `category_id` smallint(3) unsigned not null auto_increment primary key,   
3   `category_name` VARCHAR(40) NOT NULL,
4   `category_url` VARCHAR(40) NOT NULL,
5   `icon`varchar(150) default null,
6   `gender` enum('Men','Woman','Baby') default null,
7   `parent` INT DEFAULT NULL
8)engine=InnoDB default charset=utf8mb4 collate=utf8mb4_spanish_ci;
9INSERT INTO `category` (`category_id`, `category_name`, `category_url`, `icon`, `gender`, `parent`) VALUES
10-- Mens section
11(1, 'Mens Fashion', 'mens-fashion', null, null, null), -- Mens fasion
12-- clothes mens
13(2, 'Clothing', 'clothing', 'clothing.svg', null, 1), -- (level 2)
14(3, 'Shoes', 'Shoes', 'shoes.svg', null, 1), -- (level 2)
15(4, 'Complements', 'complements', 'complements.svg', null, 1), -- (level 2)
16
17(5, 'Shirts', 'shirts', null, null, 2), -- (level 3)
18(6, 'Casual shirts', 'casaul-shirts', null, null, 5), -- (level 4)
19(7, 'Suit shirts ', 'suit-shirts', null, null, 5), --(level 4)
20
21(8, 'Jeans', 'jeans', null, null, 2), -- (level 3)
22(9, 'Jeans skinny', 'jeans-skinny', null, null, 8), -- (level 4)
23(10, 'Jeans slim fit', 'jeans-slim-fit', null, null, 8), -- (level 4)
24
25(11, 'Underwear', 'Underwear', null, null, 2), -- (level 3)
26(12, 'Socks', 'socks', null, null, 11), -- (level 4)
27
28-- Woman section
29(13, 'Woman Fashion', 'woman-fasion', null, null, null), -- (level 1)
30-- Clothes woman
31(14, 'Clothing', 'clothing', 'clothing.svg', null, 13), -- (level 2)
32(15, 'Shoes', 'Shoes', 'shoes.svg', null, 13), -- (level 2)
33(16, 'Complements', 'complements', 'complements.svg', null, 13), -- (level 2)
34
35(17, 'Shirts', 'shirts', null, null, 13), -- (level 3)
36(18, 'Casual shirts', 'casaul-shirts', null, null, 17), -- (level 4)
37(19, 'Suit shirts', 'suit-shirts', null, null, 17), -- (level 4)
38(20, 'Top shirt', 'top-shirt', null, null, 17), -- (level 4)
39
40(21, 'Jeans', 'jeans', null, null, 13), -- (level 3)
41(22, 'Jeans skinny', 'jeans-skinny', null, null, 21), -- (level 4)
42(23, 'Jeans slim fit', 'jeans-slim-fit', null, null, 21), -- (level 4)
43
44(24, 'Underwear', 'Underwear', null, null, 13), -- (level 3)
45(25, 'Socks', 'socks', null, null, 24), -- (level 4)
46
47-- Childeren section
48(13, 'Childerens Fasion', 'childeren-fashion', null, null, null), -- (level 1)
49-- Clothes childeren etc..
50$categories = $db->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
51$cat = $categories->fetchAll(PDO::FETCH_ASSOC);
52
53$arrayMenu = array();
54
55foreach($cat as $row){
56$arrayMenu[$row['category_id']] = array("parent" => $row['parent'], "category_name" => $row['category_name'], "category_url" => $row['category_url']);
57}
58
59function createTree($array, $curParent, $currLevel = 0, $prevLevel = -1) {
60
61    foreach ($array as $categoryId => $category) :
62
63        if ($curParent == $category['parent']) :
64
65            if($category['parent']==0) $class="dropdown"; else $class="sub_menu";
66            if ($currLevel > $prevLevel) echo " <ul class='$class'> ";
67
68
69            if ($currLevel == $prevLevel) echo " </li> ";
70
71            echo '<li id="'.$categoryId.'" ><a href="'.$category['category_url'].'">'.$category['category_name'].'</a>';
72
73            if ($currLevel > $prevLevel) { $prevLevel = $currLevel; }
74
75            $currLevel++;
76
77            createTree ($array, $categoryId, $currLevel, $prevLevel);
78
79            $currLevel--;
80        endif;
81    endforeach;
82
83    if ($currLevel == $prevLevel) echo " </li> </ul> ";
84}
85?>
86<div class="nav">
87<?php
88if ($cat != null) createTree($arrayMenu, 0);
89?>
90nav ul li { 
91    background:#f1f1f1; list-style: none;
92}
93ul.dropdown { 
94    position:relative; 
95    width:auto; 
96    font:12px Arial, Helvetica, sans-serif; 
97}
98ul.dropdown li { 
99    float:left; zoom:1; 
100    height:auto; 
101    min-height: 30px; 
102    padding:6px 2px 0 2px; 
103}
104
105ul.dropdown li li { 
106    border-right:1px solid #ccc; 
107    border-left:1px solid #ccc; 
108    margin-left:-30px;
109}
110ul.dropdown a:hover { 
111    color:#000; 
112} 
113ul.dropdown a:active { color:#ffa500; }
114
115ul.dropdown li a { 
116    display:block; 
117    padding:4px 8px; 
118    color:#000; 
119    text-decoration:none; 
120    font:bold 12px Arial, Helvetica, sans-serif; 
121}
122
123ul.dropdown li:last-child a { border-right:none;} /* Doesn't work in IE */
124ul.dropdown li:hover { 
125    color:#000; 
126    background:#e7e7e7; 
127    position:relative; }
128ul.dropdown li.hover a { color:#000; }
129ul.dropdown ul { 
130    text-align:left; 
131    visibility: hidden; 
132    position: absolute; 
133    left:-10px; 
134    top:36px; }
135ul.dropdown ul li { 
136    background:#f1f1f1; 
137    border-bottom:1px solid #ccc; 
138    float:none; width:120px; 
139    height:auto; 
140    min-height: 25px; 
141}
142ul.dropdown ul li a { 
143    border-right:none; 
144    width:100%; 
145    display:inline-block; color:#000; }
146ul.dropdown ul ul { 
147    left:100%; 
148    top:0; 
149}
150ul.dropdown li:hover > ul { visibility:visible; }
151// Tab header ///////
152function openPage(pageName, elmnt, color) {
153  // Hide all elements with class="tabcontent" by default */
154  var i, tabcontent, tablinks;
155  tabcontent = document.getElementsByClassName("tabcontent");
156  for (i = 0; i < tabcontent.length; i++) {
157    tabcontent[i].style.display = "none";
158  }
159
160  // Remove the background color of all tablinks/buttons
161  tablinks = document.getElementsByClassName("tablink");
162  for (i = 0; i < tablinks.length; i++) {
163    tablinks[i].style.background = "";
164  }
165
166  // Show the specific tab content
167  document.getElementById(pageName).style.display = "block";
168
169  // Add the specific color to the button used to open the tab content
170  elmnt.style.background = color;
171}
172
173// Get the element with id="defaultOpen" and click on it
174document.getElementById("defaultOpen").click();
175
176
177// Accordion ///////
178var acc = document.getElementsByClassName("accordion");
179var i;
180
181for (i = 0; i < acc.length; i++) {
182  acc[i].addEventListener("click", function() {
183    this.classList.toggle("active");
184    var panel = this.nextElementSibling;
185    if (panel.style.maxHeight) {
186      panel.style.maxHeight = null;
187    } else {
188      panel.style.maxHeight = panel.scrollHeight + "px";
189    }
190  });
191}/* TAB HEADER MENU */
192
193#wrapper-tablink {
194  display: flex;
195  flex-flow: row nowrap;
196  justify-content: center;
197  align-items: center;
198}
199
200
201/* Style tab links */
202
203.tablink {
204  background-color: #555;
205  color: white;
206  border: none;
207  outline: none;
208  cursor: pointer;
209  padding: 14px 16px;
210  font-size: 17px;
211  width: 25%;
212}
213
214.tablink:hover {
215  background-color: #777;
216}
217
218.tablink .active {
219  color: #000;
220}
221
222
223/* Style the tab content (and add height:100% for full page content) */
224
225.tabcontent {
226  color: white;
227  display: none;
228  padding: 100px 20px;
229  height: 100%;
230  overflow-y: auto;
231}
232
233
234/*
235#moda-mujer {background-color: var(--secundary-color);}
236#moda-hombre {background-color: #00cc99;}
237#electronica {background-color: #3399ff;}
238#cursos {background-color: #9933ff;}
239*/
240
241.wrapper-icons-bars {
242  display: flex;
243  flex-flow: row nowrap;
244  justify-content: center;
245  align-items: center;
246  margin: 10px 0 20px 0;
247}
248
249.wrapper-icons-bars a {
250  display: block;
251  position: relative;
252  background-color: #FFFFFF;
253  border-bottom: 3px solid var(--body-color);
254  border-right: 1px solid #F1F1F1;
255  padding: 20px;
256  transition: all 0.3s ease;
257}
258
259.wrapper-icons-bars a:hover {
260  display: block;
261  position: relative;
262  border-bottom: 3px solid var(--secundary-color);
263  padding: 25px;
264  transition: all 0.3s ease;
265}
266
267
268/* ACCORDIAN CONTENT */
269
270.wrapper-accordion {
271  display: flex;
272  justify-content: center;
273  width: 100%;
274  margin-bottom: 80px;
275}
276
277.accordion {
278  display: flex;
279  position: relative;
280  justify-content: center;
281  align-items: center;
282  background-color: #eee;
283  color: #444;
284  cursor: pointer;
285  padding: 18px;
286  width: 100%;
287  max-width: 500px;
288  min-width: 500px;
289  border: none;
290  text-align: left;
291  outline: none;
292  font-size: 15px;
293  transition: 0.4s;
294}
295
296.active,
297.accordion:hover {
298  background-color: #ccc;
299}
300
301.accordion:after {
302  content: '\002B';
303  color: #777;
304  font-weight: bold;
305  display: block;
306  position: absolute;
307  right: 25px;
308  margin-left: 5px;
309}
310
311.active:after {
312  content: "\2212";
313}
314
315.panel {
316  background-color: white;
317  color: var(--body-color);
318  max-height: 0;
319  width: 100%;
320  overflow: hidden;
321  transition: max-height 0.2s ease-out;
322}
323
324.inner-panel {
325  padding: 20px 20px;
326  width: 100%;
327  max-width: 500px;
328}
329
330.wrapper-accordion a {
331  color: var(--body-color);
332}<!-- Create Tab links header (Table: controllers) -->
333<div id="wrapper-tablink">
334  <button class="tablink" onclick="openPage('mens-fashion', this, 'blue')" id="defaultOpen">Mens Fashion</button>
335  <button class="tablink" onclick="openPage('womans-fashion', this, 'red')" id="defaultOpen">Womans Fashion</button>
336</div>
337
338<div id='mens-fashion' class='tabcontent' style='blue'>
339  <article class='wrapper-accordion'>
340    <div>
341      <h2><a href='mens-fashion/clothes'>Clothes</a></h2>
342      <div class='wrapper-icons-bars'>icons</div>
343      <button class='accordion active'>Clothes</button>
344      <div class='panel' style='max-height: 1000px;'>
345        <div class='inner-panel'>
346          <h5><a href='mens-fashion/clothes'>Clothes</a></h5>
347          <a>Tshirt </a>
348        </div>
349      </div>
350
351      <button class='accordion'>Shoes</button>
352      <div class='panel'>
353        <div class='inner-panel'>
354          <h5><a href='mens-fashion/shoes'>Shoes</a></h5>
355          <a>Deport shoes </a>
356        </div>
357      </div>
358
359      <button class='accordion'>Complements</button>
360      <div class='panel'>
361        <div class='inner-panel'>
362          <h5><a href='mens-fashion/complemnts'>Shoes</a></h5>
363          <a>Clock </a>
364        </div>
365      </div>
366    </div>
367  </article>
368
369</div>
370
371<div id='womans-fashion' class='tabcontent' style='red'>
372  <article class='wrapper-accordion'>
373    <div>
374      <h2><a href='womans-fashion/clothes'>Clothes</a></h2>
375      <div class='wrapper-icons-bars'>icons</div>
376      <button class='accordion active'>Clothes</button>
377      <div class='panel' style='max-height: 1000px;'>
378        <div class='inner-panel'>
379          <h5><a href='womans-fashion/clothes'>Clothes</a></h5>
380          <a>Tshirt </a>
381        </div>
382      </div>
383
384      <button class='accordion'>Shoes</button>
385      <div class='panel'>
386        <div class='inner-panel'>
387          <h5><a href='womans-fashion/shoes'>Shoes</a></h5>
388          <a>Deport shoes </a>
389        </div>
390      </div>
391
392      <button class='accordion'>Complements</button>
393      <div class='panel'>
394        <div class='inner-panel'>
395          <h5><a href='womans-fashion/complemnts'>Shoes</a></h5>
396          <a>Clock </a>
397        </div>
398      </div>
399    </div>
400  </article>
401
402</div>// convert the categories array to parents with nested children
403function convertToLevels ($array) {
404    // First, convert the array so that the keys match the ids
405    $reKeyed = array();
406    foreach ($array as $item) {
407        $reKeyed[$item['category_id']] = $item;
408    }
409    // Next, use references to associate children with parents
410    foreach ($reKeyed as $id => $item) {
411        if (isset($item['parent'], $reKeyed[$item['parent']])) {
412            $reKeyed[$item['parent']]['children'][] =& $reKeyed[$id];
413        }
414    }
415    // Finally, go through and remove children from the outer level
416    foreach ($reKeyed as $id => $item) {
417        if (isset($item['parent'])) {
418            unset($reKeyed[$id]);
419        }
420    }
421    return $reKeyed;
422}
423
424// create menu li
425function createMenuItem($item, $url){
426    $html  = '';
427    $html .= '<li class="menu-item '.(!empty($item['children']) ? 'has-child' : '').'">';
428    $html .=    '<a href="'.$url.'" class="menu-link">';
429                    if(!empty($item['icon'])):
430    $html .=            '<i class="'.$item['icon'].'"></i>';
431                    endif;
432    $html .=        $item['category_name'];
433    $html .=    '</a>';
434                if(!empty($item['children'])):
435    $html .=        createMenu($item['children'], $url);
436                endif;
437    $html .= '</li>';
438    
439    return $html;
440}
441
442// menu
443function createMenu($menu, $url_prefix=''){
444    $html  = '';
445    $html .= '<ul class="menu">';
446                foreach($menu as $item):
447    $html .=        createMenuItem($item, $url_prefix.'/'.$item['category_url']);
448                endforeach;
449    $html .= '</ul>';
450
451    return $html;
452}
453$categories = $pdo->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
454$cat = convertToLevels($categories->fetchAll(PDO::FETCH_ASSOC));
455

Then in the HTML

1CREATE TABLE `category`(
2   `category_id` smallint(3) unsigned not null auto_increment primary key,   
3   `category_name` VARCHAR(40) NOT NULL,
4   `category_url` VARCHAR(40) NOT NULL,
5   `icon`varchar(150) default null,
6   `gender` enum('Men','Woman','Baby') default null,
7   `parent` INT DEFAULT NULL
8)engine=InnoDB default charset=utf8mb4 collate=utf8mb4_spanish_ci;
9INSERT INTO `category` (`category_id`, `category_name`, `category_url`, `icon`, `gender`, `parent`) VALUES
10-- Mens section
11(1, 'Mens Fashion', 'mens-fashion', null, null, null), -- Mens fasion
12-- clothes mens
13(2, 'Clothing', 'clothing', 'clothing.svg', null, 1), -- (level 2)
14(3, 'Shoes', 'Shoes', 'shoes.svg', null, 1), -- (level 2)
15(4, 'Complements', 'complements', 'complements.svg', null, 1), -- (level 2)
16
17(5, 'Shirts', 'shirts', null, null, 2), -- (level 3)
18(6, 'Casual shirts', 'casaul-shirts', null, null, 5), -- (level 4)
19(7, 'Suit shirts ', 'suit-shirts', null, null, 5), --(level 4)
20
21(8, 'Jeans', 'jeans', null, null, 2), -- (level 3)
22(9, 'Jeans skinny', 'jeans-skinny', null, null, 8), -- (level 4)
23(10, 'Jeans slim fit', 'jeans-slim-fit', null, null, 8), -- (level 4)
24
25(11, 'Underwear', 'Underwear', null, null, 2), -- (level 3)
26(12, 'Socks', 'socks', null, null, 11), -- (level 4)
27
28-- Woman section
29(13, 'Woman Fashion', 'woman-fasion', null, null, null), -- (level 1)
30-- Clothes woman
31(14, 'Clothing', 'clothing', 'clothing.svg', null, 13), -- (level 2)
32(15, 'Shoes', 'Shoes', 'shoes.svg', null, 13), -- (level 2)
33(16, 'Complements', 'complements', 'complements.svg', null, 13), -- (level 2)
34
35(17, 'Shirts', 'shirts', null, null, 13), -- (level 3)
36(18, 'Casual shirts', 'casaul-shirts', null, null, 17), -- (level 4)
37(19, 'Suit shirts', 'suit-shirts', null, null, 17), -- (level 4)
38(20, 'Top shirt', 'top-shirt', null, null, 17), -- (level 4)
39
40(21, 'Jeans', 'jeans', null, null, 13), -- (level 3)
41(22, 'Jeans skinny', 'jeans-skinny', null, null, 21), -- (level 4)
42(23, 'Jeans slim fit', 'jeans-slim-fit', null, null, 21), -- (level 4)
43
44(24, 'Underwear', 'Underwear', null, null, 13), -- (level 3)
45(25, 'Socks', 'socks', null, null, 24), -- (level 4)
46
47-- Childeren section
48(13, 'Childerens Fasion', 'childeren-fashion', null, null, null), -- (level 1)
49-- Clothes childeren etc..
50$categories = $db->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
51$cat = $categories->fetchAll(PDO::FETCH_ASSOC);
52
53$arrayMenu = array();
54
55foreach($cat as $row){
56$arrayMenu[$row['category_id']] = array("parent" => $row['parent'], "category_name" => $row['category_name'], "category_url" => $row['category_url']);
57}
58
59function createTree($array, $curParent, $currLevel = 0, $prevLevel = -1) {
60
61    foreach ($array as $categoryId => $category) :
62
63        if ($curParent == $category['parent']) :
64
65            if($category['parent']==0) $class="dropdown"; else $class="sub_menu";
66            if ($currLevel > $prevLevel) echo " <ul class='$class'> ";
67
68
69            if ($currLevel == $prevLevel) echo " </li> ";
70
71            echo '<li id="'.$categoryId.'" ><a href="'.$category['category_url'].'">'.$category['category_name'].'</a>';
72
73            if ($currLevel > $prevLevel) { $prevLevel = $currLevel; }
74
75            $currLevel++;
76
77            createTree ($array, $categoryId, $currLevel, $prevLevel);
78
79            $currLevel--;
80        endif;
81    endforeach;
82
83    if ($currLevel == $prevLevel) echo " </li> </ul> ";
84}
85?>
86<div class="nav">
87<?php
88if ($cat != null) createTree($arrayMenu, 0);
89?>
90nav ul li { 
91    background:#f1f1f1; list-style: none;
92}
93ul.dropdown { 
94    position:relative; 
95    width:auto; 
96    font:12px Arial, Helvetica, sans-serif; 
97}
98ul.dropdown li { 
99    float:left; zoom:1; 
100    height:auto; 
101    min-height: 30px; 
102    padding:6px 2px 0 2px; 
103}
104
105ul.dropdown li li { 
106    border-right:1px solid #ccc; 
107    border-left:1px solid #ccc; 
108    margin-left:-30px;
109}
110ul.dropdown a:hover { 
111    color:#000; 
112} 
113ul.dropdown a:active { color:#ffa500; }
114
115ul.dropdown li a { 
116    display:block; 
117    padding:4px 8px; 
118    color:#000; 
119    text-decoration:none; 
120    font:bold 12px Arial, Helvetica, sans-serif; 
121}
122
123ul.dropdown li:last-child a { border-right:none;} /* Doesn't work in IE */
124ul.dropdown li:hover { 
125    color:#000; 
126    background:#e7e7e7; 
127    position:relative; }
128ul.dropdown li.hover a { color:#000; }
129ul.dropdown ul { 
130    text-align:left; 
131    visibility: hidden; 
132    position: absolute; 
133    left:-10px; 
134    top:36px; }
135ul.dropdown ul li { 
136    background:#f1f1f1; 
137    border-bottom:1px solid #ccc; 
138    float:none; width:120px; 
139    height:auto; 
140    min-height: 25px; 
141}
142ul.dropdown ul li a { 
143    border-right:none; 
144    width:100%; 
145    display:inline-block; color:#000; }
146ul.dropdown ul ul { 
147    left:100%; 
148    top:0; 
149}
150ul.dropdown li:hover > ul { visibility:visible; }
151// Tab header ///////
152function openPage(pageName, elmnt, color) {
153  // Hide all elements with class="tabcontent" by default */
154  var i, tabcontent, tablinks;
155  tabcontent = document.getElementsByClassName("tabcontent");
156  for (i = 0; i < tabcontent.length; i++) {
157    tabcontent[i].style.display = "none";
158  }
159
160  // Remove the background color of all tablinks/buttons
161  tablinks = document.getElementsByClassName("tablink");
162  for (i = 0; i < tablinks.length; i++) {
163    tablinks[i].style.background = "";
164  }
165
166  // Show the specific tab content
167  document.getElementById(pageName).style.display = "block";
168
169  // Add the specific color to the button used to open the tab content
170  elmnt.style.background = color;
171}
172
173// Get the element with id="defaultOpen" and click on it
174document.getElementById("defaultOpen").click();
175
176
177// Accordion ///////
178var acc = document.getElementsByClassName("accordion");
179var i;
180
181for (i = 0; i < acc.length; i++) {
182  acc[i].addEventListener("click", function() {
183    this.classList.toggle("active");
184    var panel = this.nextElementSibling;
185    if (panel.style.maxHeight) {
186      panel.style.maxHeight = null;
187    } else {
188      panel.style.maxHeight = panel.scrollHeight + "px";
189    }
190  });
191}/* TAB HEADER MENU */
192
193#wrapper-tablink {
194  display: flex;
195  flex-flow: row nowrap;
196  justify-content: center;
197  align-items: center;
198}
199
200
201/* Style tab links */
202
203.tablink {
204  background-color: #555;
205  color: white;
206  border: none;
207  outline: none;
208  cursor: pointer;
209  padding: 14px 16px;
210  font-size: 17px;
211  width: 25%;
212}
213
214.tablink:hover {
215  background-color: #777;
216}
217
218.tablink .active {
219  color: #000;
220}
221
222
223/* Style the tab content (and add height:100% for full page content) */
224
225.tabcontent {
226  color: white;
227  display: none;
228  padding: 100px 20px;
229  height: 100%;
230  overflow-y: auto;
231}
232
233
234/*
235#moda-mujer {background-color: var(--secundary-color);}
236#moda-hombre {background-color: #00cc99;}
237#electronica {background-color: #3399ff;}
238#cursos {background-color: #9933ff;}
239*/
240
241.wrapper-icons-bars {
242  display: flex;
243  flex-flow: row nowrap;
244  justify-content: center;
245  align-items: center;
246  margin: 10px 0 20px 0;
247}
248
249.wrapper-icons-bars a {
250  display: block;
251  position: relative;
252  background-color: #FFFFFF;
253  border-bottom: 3px solid var(--body-color);
254  border-right: 1px solid #F1F1F1;
255  padding: 20px;
256  transition: all 0.3s ease;
257}
258
259.wrapper-icons-bars a:hover {
260  display: block;
261  position: relative;
262  border-bottom: 3px solid var(--secundary-color);
263  padding: 25px;
264  transition: all 0.3s ease;
265}
266
267
268/* ACCORDIAN CONTENT */
269
270.wrapper-accordion {
271  display: flex;
272  justify-content: center;
273  width: 100%;
274  margin-bottom: 80px;
275}
276
277.accordion {
278  display: flex;
279  position: relative;
280  justify-content: center;
281  align-items: center;
282  background-color: #eee;
283  color: #444;
284  cursor: pointer;
285  padding: 18px;
286  width: 100%;
287  max-width: 500px;
288  min-width: 500px;
289  border: none;
290  text-align: left;
291  outline: none;
292  font-size: 15px;
293  transition: 0.4s;
294}
295
296.active,
297.accordion:hover {
298  background-color: #ccc;
299}
300
301.accordion:after {
302  content: '\002B';
303  color: #777;
304  font-weight: bold;
305  display: block;
306  position: absolute;
307  right: 25px;
308  margin-left: 5px;
309}
310
311.active:after {
312  content: "\2212";
313}
314
315.panel {
316  background-color: white;
317  color: var(--body-color);
318  max-height: 0;
319  width: 100%;
320  overflow: hidden;
321  transition: max-height 0.2s ease-out;
322}
323
324.inner-panel {
325  padding: 20px 20px;
326  width: 100%;
327  max-width: 500px;
328}
329
330.wrapper-accordion a {
331  color: var(--body-color);
332}<!-- Create Tab links header (Table: controllers) -->
333<div id="wrapper-tablink">
334  <button class="tablink" onclick="openPage('mens-fashion', this, 'blue')" id="defaultOpen">Mens Fashion</button>
335  <button class="tablink" onclick="openPage('womans-fashion', this, 'red')" id="defaultOpen">Womans Fashion</button>
336</div>
337
338<div id='mens-fashion' class='tabcontent' style='blue'>
339  <article class='wrapper-accordion'>
340    <div>
341      <h2><a href='mens-fashion/clothes'>Clothes</a></h2>
342      <div class='wrapper-icons-bars'>icons</div>
343      <button class='accordion active'>Clothes</button>
344      <div class='panel' style='max-height: 1000px;'>
345        <div class='inner-panel'>
346          <h5><a href='mens-fashion/clothes'>Clothes</a></h5>
347          <a>Tshirt </a>
348        </div>
349      </div>
350
351      <button class='accordion'>Shoes</button>
352      <div class='panel'>
353        <div class='inner-panel'>
354          <h5><a href='mens-fashion/shoes'>Shoes</a></h5>
355          <a>Deport shoes </a>
356        </div>
357      </div>
358
359      <button class='accordion'>Complements</button>
360      <div class='panel'>
361        <div class='inner-panel'>
362          <h5><a href='mens-fashion/complemnts'>Shoes</a></h5>
363          <a>Clock </a>
364        </div>
365      </div>
366    </div>
367  </article>
368
369</div>
370
371<div id='womans-fashion' class='tabcontent' style='red'>
372  <article class='wrapper-accordion'>
373    <div>
374      <h2><a href='womans-fashion/clothes'>Clothes</a></h2>
375      <div class='wrapper-icons-bars'>icons</div>
376      <button class='accordion active'>Clothes</button>
377      <div class='panel' style='max-height: 1000px;'>
378        <div class='inner-panel'>
379          <h5><a href='womans-fashion/clothes'>Clothes</a></h5>
380          <a>Tshirt </a>
381        </div>
382      </div>
383
384      <button class='accordion'>Shoes</button>
385      <div class='panel'>
386        <div class='inner-panel'>
387          <h5><a href='womans-fashion/shoes'>Shoes</a></h5>
388          <a>Deport shoes </a>
389        </div>
390      </div>
391
392      <button class='accordion'>Complements</button>
393      <div class='panel'>
394        <div class='inner-panel'>
395          <h5><a href='womans-fashion/complemnts'>Shoes</a></h5>
396          <a>Clock </a>
397        </div>
398      </div>
399    </div>
400  </article>
401
402</div>// convert the categories array to parents with nested children
403function convertToLevels ($array) {
404    // First, convert the array so that the keys match the ids
405    $reKeyed = array();
406    foreach ($array as $item) {
407        $reKeyed[$item['category_id']] = $item;
408    }
409    // Next, use references to associate children with parents
410    foreach ($reKeyed as $id => $item) {
411        if (isset($item['parent'], $reKeyed[$item['parent']])) {
412            $reKeyed[$item['parent']]['children'][] =& $reKeyed[$id];
413        }
414    }
415    // Finally, go through and remove children from the outer level
416    foreach ($reKeyed as $id => $item) {
417        if (isset($item['parent'])) {
418            unset($reKeyed[$id]);
419        }
420    }
421    return $reKeyed;
422}
423
424// create menu li
425function createMenuItem($item, $url){
426    $html  = '';
427    $html .= '<li class="menu-item '.(!empty($item['children']) ? 'has-child' : '').'">';
428    $html .=    '<a href="'.$url.'" class="menu-link">';
429                    if(!empty($item['icon'])):
430    $html .=            '<i class="'.$item['icon'].'"></i>';
431                    endif;
432    $html .=        $item['category_name'];
433    $html .=    '</a>';
434                if(!empty($item['children'])):
435    $html .=        createMenu($item['children'], $url);
436                endif;
437    $html .= '</li>';
438    
439    return $html;
440}
441
442// menu
443function createMenu($menu, $url_prefix=''){
444    $html  = '';
445    $html .= '<ul class="menu">';
446                foreach($menu as $item):
447    $html .=        createMenuItem($item, $url_prefix.'/'.$item['category_url']);
448                endforeach;
449    $html .= '</ul>';
450
451    return $html;
452}
453$categories = $pdo->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
454$cat = convertToLevels($categories->fetchAll(PDO::FETCH_ASSOC));
455<?= createMenu($cat); ?>
456

To get part of the menu example Mens Fashion, you just have to filter the $cat array to get it. Example

1CREATE TABLE `category`(
2   `category_id` smallint(3) unsigned not null auto_increment primary key,   
3   `category_name` VARCHAR(40) NOT NULL,
4   `category_url` VARCHAR(40) NOT NULL,
5   `icon`varchar(150) default null,
6   `gender` enum('Men','Woman','Baby') default null,
7   `parent` INT DEFAULT NULL
8)engine=InnoDB default charset=utf8mb4 collate=utf8mb4_spanish_ci;
9INSERT INTO `category` (`category_id`, `category_name`, `category_url`, `icon`, `gender`, `parent`) VALUES
10-- Mens section
11(1, 'Mens Fashion', 'mens-fashion', null, null, null), -- Mens fasion
12-- clothes mens
13(2, 'Clothing', 'clothing', 'clothing.svg', null, 1), -- (level 2)
14(3, 'Shoes', 'Shoes', 'shoes.svg', null, 1), -- (level 2)
15(4, 'Complements', 'complements', 'complements.svg', null, 1), -- (level 2)
16
17(5, 'Shirts', 'shirts', null, null, 2), -- (level 3)
18(6, 'Casual shirts', 'casaul-shirts', null, null, 5), -- (level 4)
19(7, 'Suit shirts ', 'suit-shirts', null, null, 5), --(level 4)
20
21(8, 'Jeans', 'jeans', null, null, 2), -- (level 3)
22(9, 'Jeans skinny', 'jeans-skinny', null, null, 8), -- (level 4)
23(10, 'Jeans slim fit', 'jeans-slim-fit', null, null, 8), -- (level 4)
24
25(11, 'Underwear', 'Underwear', null, null, 2), -- (level 3)
26(12, 'Socks', 'socks', null, null, 11), -- (level 4)
27
28-- Woman section
29(13, 'Woman Fashion', 'woman-fasion', null, null, null), -- (level 1)
30-- Clothes woman
31(14, 'Clothing', 'clothing', 'clothing.svg', null, 13), -- (level 2)
32(15, 'Shoes', 'Shoes', 'shoes.svg', null, 13), -- (level 2)
33(16, 'Complements', 'complements', 'complements.svg', null, 13), -- (level 2)
34
35(17, 'Shirts', 'shirts', null, null, 13), -- (level 3)
36(18, 'Casual shirts', 'casaul-shirts', null, null, 17), -- (level 4)
37(19, 'Suit shirts', 'suit-shirts', null, null, 17), -- (level 4)
38(20, 'Top shirt', 'top-shirt', null, null, 17), -- (level 4)
39
40(21, 'Jeans', 'jeans', null, null, 13), -- (level 3)
41(22, 'Jeans skinny', 'jeans-skinny', null, null, 21), -- (level 4)
42(23, 'Jeans slim fit', 'jeans-slim-fit', null, null, 21), -- (level 4)
43
44(24, 'Underwear', 'Underwear', null, null, 13), -- (level 3)
45(25, 'Socks', 'socks', null, null, 24), -- (level 4)
46
47-- Childeren section
48(13, 'Childerens Fasion', 'childeren-fashion', null, null, null), -- (level 1)
49-- Clothes childeren etc..
50$categories = $db->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
51$cat = $categories->fetchAll(PDO::FETCH_ASSOC);
52
53$arrayMenu = array();
54
55foreach($cat as $row){
56$arrayMenu[$row['category_id']] = array("parent" => $row['parent'], "category_name" => $row['category_name'], "category_url" => $row['category_url']);
57}
58
59function createTree($array, $curParent, $currLevel = 0, $prevLevel = -1) {
60
61    foreach ($array as $categoryId => $category) :
62
63        if ($curParent == $category['parent']) :
64
65            if($category['parent']==0) $class="dropdown"; else $class="sub_menu";
66            if ($currLevel > $prevLevel) echo " <ul class='$class'> ";
67
68
69            if ($currLevel == $prevLevel) echo " </li> ";
70
71            echo '<li id="'.$categoryId.'" ><a href="'.$category['category_url'].'">'.$category['category_name'].'</a>';
72
73            if ($currLevel > $prevLevel) { $prevLevel = $currLevel; }
74
75            $currLevel++;
76
77            createTree ($array, $categoryId, $currLevel, $prevLevel);
78
79            $currLevel--;
80        endif;
81    endforeach;
82
83    if ($currLevel == $prevLevel) echo " </li> </ul> ";
84}
85?>
86<div class="nav">
87<?php
88if ($cat != null) createTree($arrayMenu, 0);
89?>
90nav ul li { 
91    background:#f1f1f1; list-style: none;
92}
93ul.dropdown { 
94    position:relative; 
95    width:auto; 
96    font:12px Arial, Helvetica, sans-serif; 
97}
98ul.dropdown li { 
99    float:left; zoom:1; 
100    height:auto; 
101    min-height: 30px; 
102    padding:6px 2px 0 2px; 
103}
104
105ul.dropdown li li { 
106    border-right:1px solid #ccc; 
107    border-left:1px solid #ccc; 
108    margin-left:-30px;
109}
110ul.dropdown a:hover { 
111    color:#000; 
112} 
113ul.dropdown a:active { color:#ffa500; }
114
115ul.dropdown li a { 
116    display:block; 
117    padding:4px 8px; 
118    color:#000; 
119    text-decoration:none; 
120    font:bold 12px Arial, Helvetica, sans-serif; 
121}
122
123ul.dropdown li:last-child a { border-right:none;} /* Doesn't work in IE */
124ul.dropdown li:hover { 
125    color:#000; 
126    background:#e7e7e7; 
127    position:relative; }
128ul.dropdown li.hover a { color:#000; }
129ul.dropdown ul { 
130    text-align:left; 
131    visibility: hidden; 
132    position: absolute; 
133    left:-10px; 
134    top:36px; }
135ul.dropdown ul li { 
136    background:#f1f1f1; 
137    border-bottom:1px solid #ccc; 
138    float:none; width:120px; 
139    height:auto; 
140    min-height: 25px; 
141}
142ul.dropdown ul li a { 
143    border-right:none; 
144    width:100%; 
145    display:inline-block; color:#000; }
146ul.dropdown ul ul { 
147    left:100%; 
148    top:0; 
149}
150ul.dropdown li:hover > ul { visibility:visible; }
151// Tab header ///////
152function openPage(pageName, elmnt, color) {
153  // Hide all elements with class="tabcontent" by default */
154  var i, tabcontent, tablinks;
155  tabcontent = document.getElementsByClassName("tabcontent");
156  for (i = 0; i < tabcontent.length; i++) {
157    tabcontent[i].style.display = "none";
158  }
159
160  // Remove the background color of all tablinks/buttons
161  tablinks = document.getElementsByClassName("tablink");
162  for (i = 0; i < tablinks.length; i++) {
163    tablinks[i].style.background = "";
164  }
165
166  // Show the specific tab content
167  document.getElementById(pageName).style.display = "block";
168
169  // Add the specific color to the button used to open the tab content
170  elmnt.style.background = color;
171}
172
173// Get the element with id="defaultOpen" and click on it
174document.getElementById("defaultOpen").click();
175
176
177// Accordion ///////
178var acc = document.getElementsByClassName("accordion");
179var i;
180
181for (i = 0; i < acc.length; i++) {
182  acc[i].addEventListener("click", function() {
183    this.classList.toggle("active");
184    var panel = this.nextElementSibling;
185    if (panel.style.maxHeight) {
186      panel.style.maxHeight = null;
187    } else {
188      panel.style.maxHeight = panel.scrollHeight + "px";
189    }
190  });
191}/* TAB HEADER MENU */
192
193#wrapper-tablink {
194  display: flex;
195  flex-flow: row nowrap;
196  justify-content: center;
197  align-items: center;
198}
199
200
201/* Style tab links */
202
203.tablink {
204  background-color: #555;
205  color: white;
206  border: none;
207  outline: none;
208  cursor: pointer;
209  padding: 14px 16px;
210  font-size: 17px;
211  width: 25%;
212}
213
214.tablink:hover {
215  background-color: #777;
216}
217
218.tablink .active {
219  color: #000;
220}
221
222
223/* Style the tab content (and add height:100% for full page content) */
224
225.tabcontent {
226  color: white;
227  display: none;
228  padding: 100px 20px;
229  height: 100%;
230  overflow-y: auto;
231}
232
233
234/*
235#moda-mujer {background-color: var(--secundary-color);}
236#moda-hombre {background-color: #00cc99;}
237#electronica {background-color: #3399ff;}
238#cursos {background-color: #9933ff;}
239*/
240
241.wrapper-icons-bars {
242  display: flex;
243  flex-flow: row nowrap;
244  justify-content: center;
245  align-items: center;
246  margin: 10px 0 20px 0;
247}
248
249.wrapper-icons-bars a {
250  display: block;
251  position: relative;
252  background-color: #FFFFFF;
253  border-bottom: 3px solid var(--body-color);
254  border-right: 1px solid #F1F1F1;
255  padding: 20px;
256  transition: all 0.3s ease;
257}
258
259.wrapper-icons-bars a:hover {
260  display: block;
261  position: relative;
262  border-bottom: 3px solid var(--secundary-color);
263  padding: 25px;
264  transition: all 0.3s ease;
265}
266
267
268/* ACCORDIAN CONTENT */
269
270.wrapper-accordion {
271  display: flex;
272  justify-content: center;
273  width: 100%;
274  margin-bottom: 80px;
275}
276
277.accordion {
278  display: flex;
279  position: relative;
280  justify-content: center;
281  align-items: center;
282  background-color: #eee;
283  color: #444;
284  cursor: pointer;
285  padding: 18px;
286  width: 100%;
287  max-width: 500px;
288  min-width: 500px;
289  border: none;
290  text-align: left;
291  outline: none;
292  font-size: 15px;
293  transition: 0.4s;
294}
295
296.active,
297.accordion:hover {
298  background-color: #ccc;
299}
300
301.accordion:after {
302  content: '\002B';
303  color: #777;
304  font-weight: bold;
305  display: block;
306  position: absolute;
307  right: 25px;
308  margin-left: 5px;
309}
310
311.active:after {
312  content: "\2212";
313}
314
315.panel {
316  background-color: white;
317  color: var(--body-color);
318  max-height: 0;
319  width: 100%;
320  overflow: hidden;
321  transition: max-height 0.2s ease-out;
322}
323
324.inner-panel {
325  padding: 20px 20px;
326  width: 100%;
327  max-width: 500px;
328}
329
330.wrapper-accordion a {
331  color: var(--body-color);
332}<!-- Create Tab links header (Table: controllers) -->
333<div id="wrapper-tablink">
334  <button class="tablink" onclick="openPage('mens-fashion', this, 'blue')" id="defaultOpen">Mens Fashion</button>
335  <button class="tablink" onclick="openPage('womans-fashion', this, 'red')" id="defaultOpen">Womans Fashion</button>
336</div>
337
338<div id='mens-fashion' class='tabcontent' style='blue'>
339  <article class='wrapper-accordion'>
340    <div>
341      <h2><a href='mens-fashion/clothes'>Clothes</a></h2>
342      <div class='wrapper-icons-bars'>icons</div>
343      <button class='accordion active'>Clothes</button>
344      <div class='panel' style='max-height: 1000px;'>
345        <div class='inner-panel'>
346          <h5><a href='mens-fashion/clothes'>Clothes</a></h5>
347          <a>Tshirt </a>
348        </div>
349      </div>
350
351      <button class='accordion'>Shoes</button>
352      <div class='panel'>
353        <div class='inner-panel'>
354          <h5><a href='mens-fashion/shoes'>Shoes</a></h5>
355          <a>Deport shoes </a>
356        </div>
357      </div>
358
359      <button class='accordion'>Complements</button>
360      <div class='panel'>
361        <div class='inner-panel'>
362          <h5><a href='mens-fashion/complemnts'>Shoes</a></h5>
363          <a>Clock </a>
364        </div>
365      </div>
366    </div>
367  </article>
368
369</div>
370
371<div id='womans-fashion' class='tabcontent' style='red'>
372  <article class='wrapper-accordion'>
373    <div>
374      <h2><a href='womans-fashion/clothes'>Clothes</a></h2>
375      <div class='wrapper-icons-bars'>icons</div>
376      <button class='accordion active'>Clothes</button>
377      <div class='panel' style='max-height: 1000px;'>
378        <div class='inner-panel'>
379          <h5><a href='womans-fashion/clothes'>Clothes</a></h5>
380          <a>Tshirt </a>
381        </div>
382      </div>
383
384      <button class='accordion'>Shoes</button>
385      <div class='panel'>
386        <div class='inner-panel'>
387          <h5><a href='womans-fashion/shoes'>Shoes</a></h5>
388          <a>Deport shoes </a>
389        </div>
390      </div>
391
392      <button class='accordion'>Complements</button>
393      <div class='panel'>
394        <div class='inner-panel'>
395          <h5><a href='womans-fashion/complemnts'>Shoes</a></h5>
396          <a>Clock </a>
397        </div>
398      </div>
399    </div>
400  </article>
401
402</div>// convert the categories array to parents with nested children
403function convertToLevels ($array) {
404    // First, convert the array so that the keys match the ids
405    $reKeyed = array();
406    foreach ($array as $item) {
407        $reKeyed[$item['category_id']] = $item;
408    }
409    // Next, use references to associate children with parents
410    foreach ($reKeyed as $id => $item) {
411        if (isset($item['parent'], $reKeyed[$item['parent']])) {
412            $reKeyed[$item['parent']]['children'][] =& $reKeyed[$id];
413        }
414    }
415    // Finally, go through and remove children from the outer level
416    foreach ($reKeyed as $id => $item) {
417        if (isset($item['parent'])) {
418            unset($reKeyed[$id]);
419        }
420    }
421    return $reKeyed;
422}
423
424// create menu li
425function createMenuItem($item, $url){
426    $html  = '';
427    $html .= '<li class="menu-item '.(!empty($item['children']) ? 'has-child' : '').'">';
428    $html .=    '<a href="'.$url.'" class="menu-link">';
429                    if(!empty($item['icon'])):
430    $html .=            '<i class="'.$item['icon'].'"></i>';
431                    endif;
432    $html .=        $item['category_name'];
433    $html .=    '</a>';
434                if(!empty($item['children'])):
435    $html .=        createMenu($item['children'], $url);
436                endif;
437    $html .= '</li>';
438    
439    return $html;
440}
441
442// menu
443function createMenu($menu, $url_prefix=''){
444    $html  = '';
445    $html .= '<ul class="menu">';
446                foreach($menu as $item):
447    $html .=        createMenuItem($item, $url_prefix.'/'.$item['category_url']);
448                endforeach;
449    $html .= '</ul>';
450
451    return $html;
452}
453$categories = $pdo->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
454$cat = convertToLevels($categories->fetchAll(PDO::FETCH_ASSOC));
455<?= createMenu($cat); ?>
456$men_cat = array_values(array_filter($cat, function($val){
457    return strtolower($val['category_name']) === 'mens fashion';
458}))[0]['children'] ?? [];
459

Then in the HTML

1CREATE TABLE `category`(
2   `category_id` smallint(3) unsigned not null auto_increment primary key,   
3   `category_name` VARCHAR(40) NOT NULL,
4   `category_url` VARCHAR(40) NOT NULL,
5   `icon`varchar(150) default null,
6   `gender` enum('Men','Woman','Baby') default null,
7   `parent` INT DEFAULT NULL
8)engine=InnoDB default charset=utf8mb4 collate=utf8mb4_spanish_ci;
9INSERT INTO `category` (`category_id`, `category_name`, `category_url`, `icon`, `gender`, `parent`) VALUES
10-- Mens section
11(1, 'Mens Fashion', 'mens-fashion', null, null, null), -- Mens fasion
12-- clothes mens
13(2, 'Clothing', 'clothing', 'clothing.svg', null, 1), -- (level 2)
14(3, 'Shoes', 'Shoes', 'shoes.svg', null, 1), -- (level 2)
15(4, 'Complements', 'complements', 'complements.svg', null, 1), -- (level 2)
16
17(5, 'Shirts', 'shirts', null, null, 2), -- (level 3)
18(6, 'Casual shirts', 'casaul-shirts', null, null, 5), -- (level 4)
19(7, 'Suit shirts ', 'suit-shirts', null, null, 5), --(level 4)
20
21(8, 'Jeans', 'jeans', null, null, 2), -- (level 3)
22(9, 'Jeans skinny', 'jeans-skinny', null, null, 8), -- (level 4)
23(10, 'Jeans slim fit', 'jeans-slim-fit', null, null, 8), -- (level 4)
24
25(11, 'Underwear', 'Underwear', null, null, 2), -- (level 3)
26(12, 'Socks', 'socks', null, null, 11), -- (level 4)
27
28-- Woman section
29(13, 'Woman Fashion', 'woman-fasion', null, null, null), -- (level 1)
30-- Clothes woman
31(14, 'Clothing', 'clothing', 'clothing.svg', null, 13), -- (level 2)
32(15, 'Shoes', 'Shoes', 'shoes.svg', null, 13), -- (level 2)
33(16, 'Complements', 'complements', 'complements.svg', null, 13), -- (level 2)
34
35(17, 'Shirts', 'shirts', null, null, 13), -- (level 3)
36(18, 'Casual shirts', 'casaul-shirts', null, null, 17), -- (level 4)
37(19, 'Suit shirts', 'suit-shirts', null, null, 17), -- (level 4)
38(20, 'Top shirt', 'top-shirt', null, null, 17), -- (level 4)
39
40(21, 'Jeans', 'jeans', null, null, 13), -- (level 3)
41(22, 'Jeans skinny', 'jeans-skinny', null, null, 21), -- (level 4)
42(23, 'Jeans slim fit', 'jeans-slim-fit', null, null, 21), -- (level 4)
43
44(24, 'Underwear', 'Underwear', null, null, 13), -- (level 3)
45(25, 'Socks', 'socks', null, null, 24), -- (level 4)
46
47-- Childeren section
48(13, 'Childerens Fasion', 'childeren-fashion', null, null, null), -- (level 1)
49-- Clothes childeren etc..
50$categories = $db->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
51$cat = $categories->fetchAll(PDO::FETCH_ASSOC);
52
53$arrayMenu = array();
54
55foreach($cat as $row){
56$arrayMenu[$row['category_id']] = array("parent" => $row['parent'], "category_name" => $row['category_name'], "category_url" => $row['category_url']);
57}
58
59function createTree($array, $curParent, $currLevel = 0, $prevLevel = -1) {
60
61    foreach ($array as $categoryId => $category) :
62
63        if ($curParent == $category['parent']) :
64
65            if($category['parent']==0) $class="dropdown"; else $class="sub_menu";
66            if ($currLevel > $prevLevel) echo " <ul class='$class'> ";
67
68
69            if ($currLevel == $prevLevel) echo " </li> ";
70
71            echo '<li id="'.$categoryId.'" ><a href="'.$category['category_url'].'">'.$category['category_name'].'</a>';
72
73            if ($currLevel > $prevLevel) { $prevLevel = $currLevel; }
74
75            $currLevel++;
76
77            createTree ($array, $categoryId, $currLevel, $prevLevel);
78
79            $currLevel--;
80        endif;
81    endforeach;
82
83    if ($currLevel == $prevLevel) echo " </li> </ul> ";
84}
85?>
86<div class="nav">
87<?php
88if ($cat != null) createTree($arrayMenu, 0);
89?>
90nav ul li { 
91    background:#f1f1f1; list-style: none;
92}
93ul.dropdown { 
94    position:relative; 
95    width:auto; 
96    font:12px Arial, Helvetica, sans-serif; 
97}
98ul.dropdown li { 
99    float:left; zoom:1; 
100    height:auto; 
101    min-height: 30px; 
102    padding:6px 2px 0 2px; 
103}
104
105ul.dropdown li li { 
106    border-right:1px solid #ccc; 
107    border-left:1px solid #ccc; 
108    margin-left:-30px;
109}
110ul.dropdown a:hover { 
111    color:#000; 
112} 
113ul.dropdown a:active { color:#ffa500; }
114
115ul.dropdown li a { 
116    display:block; 
117    padding:4px 8px; 
118    color:#000; 
119    text-decoration:none; 
120    font:bold 12px Arial, Helvetica, sans-serif; 
121}
122
123ul.dropdown li:last-child a { border-right:none;} /* Doesn't work in IE */
124ul.dropdown li:hover { 
125    color:#000; 
126    background:#e7e7e7; 
127    position:relative; }
128ul.dropdown li.hover a { color:#000; }
129ul.dropdown ul { 
130    text-align:left; 
131    visibility: hidden; 
132    position: absolute; 
133    left:-10px; 
134    top:36px; }
135ul.dropdown ul li { 
136    background:#f1f1f1; 
137    border-bottom:1px solid #ccc; 
138    float:none; width:120px; 
139    height:auto; 
140    min-height: 25px; 
141}
142ul.dropdown ul li a { 
143    border-right:none; 
144    width:100%; 
145    display:inline-block; color:#000; }
146ul.dropdown ul ul { 
147    left:100%; 
148    top:0; 
149}
150ul.dropdown li:hover > ul { visibility:visible; }
151// Tab header ///////
152function openPage(pageName, elmnt, color) {
153  // Hide all elements with class="tabcontent" by default */
154  var i, tabcontent, tablinks;
155  tabcontent = document.getElementsByClassName("tabcontent");
156  for (i = 0; i < tabcontent.length; i++) {
157    tabcontent[i].style.display = "none";
158  }
159
160  // Remove the background color of all tablinks/buttons
161  tablinks = document.getElementsByClassName("tablink");
162  for (i = 0; i < tablinks.length; i++) {
163    tablinks[i].style.background = "";
164  }
165
166  // Show the specific tab content
167  document.getElementById(pageName).style.display = "block";
168
169  // Add the specific color to the button used to open the tab content
170  elmnt.style.background = color;
171}
172
173// Get the element with id="defaultOpen" and click on it
174document.getElementById("defaultOpen").click();
175
176
177// Accordion ///////
178var acc = document.getElementsByClassName("accordion");
179var i;
180
181for (i = 0; i < acc.length; i++) {
182  acc[i].addEventListener("click", function() {
183    this.classList.toggle("active");
184    var panel = this.nextElementSibling;
185    if (panel.style.maxHeight) {
186      panel.style.maxHeight = null;
187    } else {
188      panel.style.maxHeight = panel.scrollHeight + "px";
189    }
190  });
191}/* TAB HEADER MENU */
192
193#wrapper-tablink {
194  display: flex;
195  flex-flow: row nowrap;
196  justify-content: center;
197  align-items: center;
198}
199
200
201/* Style tab links */
202
203.tablink {
204  background-color: #555;
205  color: white;
206  border: none;
207  outline: none;
208  cursor: pointer;
209  padding: 14px 16px;
210  font-size: 17px;
211  width: 25%;
212}
213
214.tablink:hover {
215  background-color: #777;
216}
217
218.tablink .active {
219  color: #000;
220}
221
222
223/* Style the tab content (and add height:100% for full page content) */
224
225.tabcontent {
226  color: white;
227  display: none;
228  padding: 100px 20px;
229  height: 100%;
230  overflow-y: auto;
231}
232
233
234/*
235#moda-mujer {background-color: var(--secundary-color);}
236#moda-hombre {background-color: #00cc99;}
237#electronica {background-color: #3399ff;}
238#cursos {background-color: #9933ff;}
239*/
240
241.wrapper-icons-bars {
242  display: flex;
243  flex-flow: row nowrap;
244  justify-content: center;
245  align-items: center;
246  margin: 10px 0 20px 0;
247}
248
249.wrapper-icons-bars a {
250  display: block;
251  position: relative;
252  background-color: #FFFFFF;
253  border-bottom: 3px solid var(--body-color);
254  border-right: 1px solid #F1F1F1;
255  padding: 20px;
256  transition: all 0.3s ease;
257}
258
259.wrapper-icons-bars a:hover {
260  display: block;
261  position: relative;
262  border-bottom: 3px solid var(--secundary-color);
263  padding: 25px;
264  transition: all 0.3s ease;
265}
266
267
268/* ACCORDIAN CONTENT */
269
270.wrapper-accordion {
271  display: flex;
272  justify-content: center;
273  width: 100%;
274  margin-bottom: 80px;
275}
276
277.accordion {
278  display: flex;
279  position: relative;
280  justify-content: center;
281  align-items: center;
282  background-color: #eee;
283  color: #444;
284  cursor: pointer;
285  padding: 18px;
286  width: 100%;
287  max-width: 500px;
288  min-width: 500px;
289  border: none;
290  text-align: left;
291  outline: none;
292  font-size: 15px;
293  transition: 0.4s;
294}
295
296.active,
297.accordion:hover {
298  background-color: #ccc;
299}
300
301.accordion:after {
302  content: '\002B';
303  color: #777;
304  font-weight: bold;
305  display: block;
306  position: absolute;
307  right: 25px;
308  margin-left: 5px;
309}
310
311.active:after {
312  content: "\2212";
313}
314
315.panel {
316  background-color: white;
317  color: var(--body-color);
318  max-height: 0;
319  width: 100%;
320  overflow: hidden;
321  transition: max-height 0.2s ease-out;
322}
323
324.inner-panel {
325  padding: 20px 20px;
326  width: 100%;
327  max-width: 500px;
328}
329
330.wrapper-accordion a {
331  color: var(--body-color);
332}<!-- Create Tab links header (Table: controllers) -->
333<div id="wrapper-tablink">
334  <button class="tablink" onclick="openPage('mens-fashion', this, 'blue')" id="defaultOpen">Mens Fashion</button>
335  <button class="tablink" onclick="openPage('womans-fashion', this, 'red')" id="defaultOpen">Womans Fashion</button>
336</div>
337
338<div id='mens-fashion' class='tabcontent' style='blue'>
339  <article class='wrapper-accordion'>
340    <div>
341      <h2><a href='mens-fashion/clothes'>Clothes</a></h2>
342      <div class='wrapper-icons-bars'>icons</div>
343      <button class='accordion active'>Clothes</button>
344      <div class='panel' style='max-height: 1000px;'>
345        <div class='inner-panel'>
346          <h5><a href='mens-fashion/clothes'>Clothes</a></h5>
347          <a>Tshirt </a>
348        </div>
349      </div>
350
351      <button class='accordion'>Shoes</button>
352      <div class='panel'>
353        <div class='inner-panel'>
354          <h5><a href='mens-fashion/shoes'>Shoes</a></h5>
355          <a>Deport shoes </a>
356        </div>
357      </div>
358
359      <button class='accordion'>Complements</button>
360      <div class='panel'>
361        <div class='inner-panel'>
362          <h5><a href='mens-fashion/complemnts'>Shoes</a></h5>
363          <a>Clock </a>
364        </div>
365      </div>
366    </div>
367  </article>
368
369</div>
370
371<div id='womans-fashion' class='tabcontent' style='red'>
372  <article class='wrapper-accordion'>
373    <div>
374      <h2><a href='womans-fashion/clothes'>Clothes</a></h2>
375      <div class='wrapper-icons-bars'>icons</div>
376      <button class='accordion active'>Clothes</button>
377      <div class='panel' style='max-height: 1000px;'>
378        <div class='inner-panel'>
379          <h5><a href='womans-fashion/clothes'>Clothes</a></h5>
380          <a>Tshirt </a>
381        </div>
382      </div>
383
384      <button class='accordion'>Shoes</button>
385      <div class='panel'>
386        <div class='inner-panel'>
387          <h5><a href='womans-fashion/shoes'>Shoes</a></h5>
388          <a>Deport shoes </a>
389        </div>
390      </div>
391
392      <button class='accordion'>Complements</button>
393      <div class='panel'>
394        <div class='inner-panel'>
395          <h5><a href='womans-fashion/complemnts'>Shoes</a></h5>
396          <a>Clock </a>
397        </div>
398      </div>
399    </div>
400  </article>
401
402</div>// convert the categories array to parents with nested children
403function convertToLevels ($array) {
404    // First, convert the array so that the keys match the ids
405    $reKeyed = array();
406    foreach ($array as $item) {
407        $reKeyed[$item['category_id']] = $item;
408    }
409    // Next, use references to associate children with parents
410    foreach ($reKeyed as $id => $item) {
411        if (isset($item['parent'], $reKeyed[$item['parent']])) {
412            $reKeyed[$item['parent']]['children'][] =& $reKeyed[$id];
413        }
414    }
415    // Finally, go through and remove children from the outer level
416    foreach ($reKeyed as $id => $item) {
417        if (isset($item['parent'])) {
418            unset($reKeyed[$id]);
419        }
420    }
421    return $reKeyed;
422}
423
424// create menu li
425function createMenuItem($item, $url){
426    $html  = '';
427    $html .= '<li class="menu-item '.(!empty($item['children']) ? 'has-child' : '').'">';
428    $html .=    '<a href="'.$url.'" class="menu-link">';
429                    if(!empty($item['icon'])):
430    $html .=            '<i class="'.$item['icon'].'"></i>';
431                    endif;
432    $html .=        $item['category_name'];
433    $html .=    '</a>';
434                if(!empty($item['children'])):
435    $html .=        createMenu($item['children'], $url);
436                endif;
437    $html .= '</li>';
438    
439    return $html;
440}
441
442// menu
443function createMenu($menu, $url_prefix=''){
444    $html  = '';
445    $html .= '<ul class="menu">';
446                foreach($menu as $item):
447    $html .=        createMenuItem($item, $url_prefix.'/'.$item['category_url']);
448                endforeach;
449    $html .= '</ul>';
450
451    return $html;
452}
453$categories = $pdo->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id');
454$cat = convertToLevels($categories->fetchAll(PDO::FETCH_ASSOC));
455<?= createMenu($cat); ?>
456$men_cat = array_values(array_filter($cat, function($val){
457    return strtolower($val['category_name']) === 'mens fashion';
458}))[0]['children'] ?? [];
459<?= createMenu($men_cat, '/mens-fashion'); ?>
460

Source https://stackoverflow.com/questions/70962454

QUESTION

proxy server working in one case and failed in another case

Asked 2022-Jan-23 at 14:57

So i am working on eCommerce website in react and Node. coming to the point, at the time of login the proxy works totally fine but when i made get request to API it shows an error. I spent 2 days resolving this but at last came here with the hope to get the answer. This is error i got

brief description of request

My server.js file

1const express = require ( 'express');
2const bodyParser = require('body-parser');
3const app = express();
4const {sequelize} = require('./models')
5const  cookieParser = require("cookie-parser");
6app.use(express.json());
7// app.use(express.urlencoded());
8
9// app.use(bodyParser.json());
10app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
11  extended: true
12}));
13const FarmerRoutes = require('./Routes/Farmer'); // Finished
14const AdminRoutes = require('./Routes/Entities'); //  Finished
15const Ecommerce = require('./Routes/Ecommerce'); // Finished
16const upload = require('./Controllers/ImageManagement')
17app.use(cookieParser())
18
19app.use(express.static('backend/uploads'))
20app.get('/', (req, res) => {
21res.send(" CattleTalk Api is active and running...")
22})
23
24app.use('/api/ecommerce',Ecommerce);
25app.use('/api/admin',AdminRoutes); 
26app.use('/api/farmers',FarmerRoutes);
27
28
29
30
31app.listen(5002,async()=>{
32    console.log("The app listening at 5002");
33    try {
34        await sequelize.authenticate();
35        console.log('Database Connection has been established successfully.');
36      } catch (error) {
37        console.error('Unable to connect to the database:', error);
38      }
39});
40

My package.json at frontend looks like this

1const express = require ( 'express');
2const bodyParser = require('body-parser');
3const app = express();
4const {sequelize} = require('./models')
5const  cookieParser = require("cookie-parser");
6app.use(express.json());
7// app.use(express.urlencoded());
8
9// app.use(bodyParser.json());
10app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
11  extended: true
12}));
13const FarmerRoutes = require('./Routes/Farmer'); // Finished
14const AdminRoutes = require('./Routes/Entities'); //  Finished
15const Ecommerce = require('./Routes/Ecommerce'); // Finished
16const upload = require('./Controllers/ImageManagement')
17app.use(cookieParser())
18
19app.use(express.static('backend/uploads'))
20app.get('/', (req, res) => {
21res.send(" CattleTalk Api is active and running...")
22})
23
24app.use('/api/ecommerce',Ecommerce);
25app.use('/api/admin',AdminRoutes); 
26app.use('/api/farmers',FarmerRoutes);
27
28
29
30
31app.listen(5002,async()=>{
32    console.log("The app listening at 5002");
33    try {
34        await sequelize.authenticate();
35        console.log('Database Connection has been established successfully.');
36      } catch (error) {
37        console.error('Unable to connect to the database:', error);
38      }
39});
40{
41  "name": "frontend",
42  "secure":false,
43  "version": "0.1.0",
44  "private": true,
45  "dependencies": {
46    "@popperjs/core": "^2.9.1",
47    "@testing-library/jest-dom": "^5.11.9",
48    "@testing-library/react": "^11.2.5",
49    "@testing-library/user-event": "^12.8.3",
50    "axios": "^0.21.1",
51    "bootstrap": "^5.0.2",
52    "formik": "^2.2.9",
53    "js-cookie": "^3.0.1",
54    "react": "^17.0.1",
55    "react-bootstrap": "^2.0.0-alpha.2",
56    "react-bootstrap-sidebar": "^0.0.1",
57    "react-dom": "^17.0.1",
58    "react-icons": "^4.2.0",
59    "react-router": "^5.2.0",
60    "react-router-bootstrap": "^0.25.0",
61    "react-router-dom": "^5.2.0",
62    "react-scripts": "4.0.3",
63    "web-vitals": "^1.1.1",
64    "yup": "^0.32.11"
65  },
66  "scripts": {
67    "start": "react-scripts start",
68    "build": "react-scripts build",
69    "test": "react-scripts test",
70    "eject": "react-scripts eject"
71  },
72  "eslintConfig": {
73    "extends": [
74      "react-app",
75      "react-app/jest"
76    ]
77  },
78  "browserslist": {
79    "production": [
80      ">0.2%",
81      "not dead",
82      "not op_mini all"
83    ],
84    "development": [
85      "last 1 chrome version",
86      "last 1 firefox version",
87      "last 1 safari version"
88    ]
89  },
90  "proxy": "http://localhost:5002/"
91}
92

ANSWER

Answered 2022-Jan-23 at 14:57

After hours of exploring the internet i couldn't get the answer of my problem, but debugging the code i found the problem. Actually it was one extra trailing slash in URL which made it to misbehave. I was like this before.

Wrong Link

enter image description here

The correct version will be.

correct Link

enter image description here

EXTRA NOTE: All those who have not found the solution from here should move forward to this link and look for trailing slash if found in your current URL, for making successful proxy you need to eliminate that trailing slash at the end of URL.

Source https://stackoverflow.com/questions/70816731

QUESTION

How to send previous items in cart such that my updateCart adds new items on top of previous products in cart

Asked 2022-Jan-18 at 16:03

I am creating a ecommerce product cart, while adding first order it creates order with createOrder and while adding next products it runs updateCart. I have to send the previous items in the cart while running update cart because currently on adding next product it's not working.

This is my service code:

1static createOrder(
2    order: Order,
3    onSuccess: Function,
4    onError: Function,
5    onFinal: Function
6  ) {
7    const orderJson = serialize(Order, order)
8    const URL = ApiRoutes.CREATE_ORDER
9    axiosInstance
10      .post(URL, { "order": orderJson })
11      .then((res) => {
12        // const data = deserialize(Cart, res.data.order);
13        //onSuccess(res.data.success);
14      })
15      .catch((err) => {
16        onError(err);
17      });
18  }
19
20  static updateCart(
21    order: Order,
22    orderId: string,
23    onSuccess: Function,
24
25    onError: Function,
26    onFinal: Function
27  ) {
28    const orderJson = serialize(Order, order)
29    const URL = ApiRoutes.UPDATE_CART.replace(":id", `${orderId}`)
30    axiosInstance
31      .put(URL, { "order": orderJson })
32      .then((res) => {
33        // const data = deserialize(Cart, res.data.order);
34        //onSuccess(res.data.success);
35      })
36      .catch((err) => {
37        onError(err);
38      });
39  }
40

This is how I am calling it:

1static createOrder(
2    order: Order,
3    onSuccess: Function,
4    onError: Function,
5    onFinal: Function
6  ) {
7    const orderJson = serialize(Order, order)
8    const URL = ApiRoutes.CREATE_ORDER
9    axiosInstance
10      .post(URL, { "order": orderJson })
11      .then((res) => {
12        // const data = deserialize(Cart, res.data.order);
13        //onSuccess(res.data.success);
14      })
15      .catch((err) => {
16        onError(err);
17      });
18  }
19
20  static updateCart(
21    order: Order,
22    orderId: string,
23    onSuccess: Function,
24
25    onError: Function,
26    onFinal: Function
27  ) {
28    const orderJson = serialize(Order, order)
29    const URL = ApiRoutes.UPDATE_CART.replace(":id", `${orderId}`)
30    axiosInstance
31      .put(URL, { "order": orderJson })
32      .then((res) => {
33        // const data = deserialize(Cart, res.data.order);
34        //onSuccess(res.data.success);
35      })
36      .catch((err) => {
37        onError(err);
38      });
39  }
40const addToBasket = () => {
41    dispatch({
42      type: 'ADD_TO_BASKET',
43      item: {
44        "id": product.id,
45        "title": product.name,
46        "price": product.price,
47        "image": product.imageUrl,
48      },
49    });
50
51    // CREATE ORDER ONCE CART IS EMPTY ELSE UPDATE CART
52
53    if (props?.userCart?.orderItems?.length) {
54      OrderService.updateCart(
55        {
56          orderItems: [{
57
58            productId: `${product?.id}`,
59            quantity: 1,
60            // taxMode:0,
61            // taxPercentage:0,
62            //discountPercentage: ""
63          }]
64        },
65        props?.userCart?.id,
66        () => { },
67        () => { },
68        () => { },
69      )
70    } else {
71      OrderService.createOrder(
72        {
73          userId: user?.id,
74          storeId: store?.id,
75          orderItems: [
76            {
77              productId: `${product?.id}`,
78              quantity: 1,
79              taxMode: 0,
80              taxPercentage: 0,
81              discountPercentage: ""
82            }
83          ]
84        },
85        () => { },
86        () => { },
87        () => { },
88      )
89    }
90  };
91

ANSWER

Answered 2022-Jan-18 at 16:03

Just add previous products to the end of array with spread operator like ...props.userCart.orderItems

1static createOrder(
2    order: Order,
3    onSuccess: Function,
4    onError: Function,
5    onFinal: Function
6  ) {
7    const orderJson = serialize(Order, order)
8    const URL = ApiRoutes.CREATE_ORDER
9    axiosInstance
10      .post(URL, { "order": orderJson })
11      .then((res) => {
12        // const data = deserialize(Cart, res.data.order);
13        //onSuccess(res.data.success);
14      })
15      .catch((err) => {
16        onError(err);
17      });
18  }
19
20  static updateCart(
21    order: Order,
22    orderId: string,
23    onSuccess: Function,
24
25    onError: Function,
26    onFinal: Function
27  ) {
28    const orderJson = serialize(Order, order)
29    const URL = ApiRoutes.UPDATE_CART.replace(":id", `${orderId}`)
30    axiosInstance
31      .put(URL, { "order": orderJson })
32      .then((res) => {
33        // const data = deserialize(Cart, res.data.order);
34        //onSuccess(res.data.success);
35      })
36      .catch((err) => {
37        onError(err);
38      });
39  }
40const addToBasket = () => {
41    dispatch({
42      type: 'ADD_TO_BASKET',
43      item: {
44        "id": product.id,
45        "title": product.name,
46        "price": product.price,
47        "image": product.imageUrl,
48      },
49    });
50
51    // CREATE ORDER ONCE CART IS EMPTY ELSE UPDATE CART
52
53    if (props?.userCart?.orderItems?.length) {
54      OrderService.updateCart(
55        {
56          orderItems: [{
57
58            productId: `${product?.id}`,
59            quantity: 1,
60            // taxMode:0,
61            // taxPercentage:0,
62            //discountPercentage: ""
63          }]
64        },
65        props?.userCart?.id,
66        () => { },
67        () => { },
68        () => { },
69      )
70    } else {
71      OrderService.createOrder(
72        {
73          userId: user?.id,
74          storeId: store?.id,
75          orderItems: [
76            {
77              productId: `${product?.id}`,
78              quantity: 1,
79              taxMode: 0,
80              taxPercentage: 0,
81              discountPercentage: ""
82            }
83          ]
84        },
85        () => { },
86        () => { },
87        () => { },
88      )
89    }
90  };
91OrderService.updateCart(  
92 {
93              orderItems: [{
94    
95                productId: `${product?.id}`,
96                quantity: 1,
97                // taxMode:0,
98                // taxPercentage:0,
99                //discountPercentage: ""
100              }, ...props.userCart.orderItems]
101            },
102            props?.userCart?.id,
103            () => { },
104            () => { },
105            () => { },
106          )
107    }
108

Source https://stackoverflow.com/questions/70758559

QUESTION

useReducer: dispatch action, show state in other component and update state when action is dispatched

Asked 2022-Jan-17 at 20:44

I have a problem which I can't figure it out. I'm building an ecommerce react app and using useReducer and useContext for state management. Client opens a product, picks number of items and then click button "Add to Cart" which dispatches an action. This part is working well, and the problem starts. I don't know how to show and update in Navbar.js component a total number of products in cart. It is showing after route changes, but I want it to update when clicking Add to Cart button. I tried useEffect but it doesn't work.

initial state looks like this

1const initialState = [
2  {
3    productName: '',
4    count: 0
5  }
6]
7

AddToCart.js works good

1const initialState = [
2  {
3    productName: '',
4    count: 0
5  }
6]
7import React, { useState, useContext } from 'react'
8import { ItemCounterContext } from '../../App'
9
10function AddToCart({ product }) {
11  const itemCounter = useContext(ItemCounterContext)
12  const [countItem, setCountItem] = useState(0)
13
14  const changeCount = (e) => {
15    if (e === '+') { setCountItem(countItem + 1) }
16    if (e === '-' && countItem > 0) { setCountItem(countItem - 1) }
17  }
18
19  return (
20    <div className='add margin-top-small'>
21      <div
22        className='add-counter'
23        onClick={(e) => changeCount(e.target.innerText)}
24        role='button'
25      >
26        -
27      </div>
28
29      <div className='add-counter'>{countItem}</div>
30
31      <div
32        className='add-counter'
33        onClick={(e) => changeCount(e.target.innerText)}
34        role='button'
35      >
36        +
37      </div>
38      <button
39        className='add-btn btnOrange'
40        onClick={() => itemCounter.dispatch({ type: 'addToCart', productName: product.name, count: countItem })}
41      >
42        Add to Cart
43      </button>
44    </div>
45  )
46}
47
48export default AddToCart
49

Navbar.js is where I have a problem

1const initialState = [
2  {
3    productName: '',
4    count: 0
5  }
6]
7import React, { useState, useContext } from 'react'
8import { ItemCounterContext } from '../../App'
9
10function AddToCart({ product }) {
11  const itemCounter = useContext(ItemCounterContext)
12  const [countItem, setCountItem] = useState(0)
13
14  const changeCount = (e) => {
15    if (e === '+') { setCountItem(countItem + 1) }
16    if (e === '-' && countItem > 0) { setCountItem(countItem - 1) }
17  }
18
19  return (
20    <div className='add margin-top-small'>
21      <div
22        className='add-counter'
23        onClick={(e) => changeCount(e.target.innerText)}
24        role='button'
25      >
26        -
27      </div>
28
29      <div className='add-counter'>{countItem}</div>
30
31      <div
32        className='add-counter'
33        onClick={(e) => changeCount(e.target.innerText)}
34        role='button'
35      >
36        +
37      </div>
38      <button
39        className='add-btn btnOrange'
40        onClick={() => itemCounter.dispatch({ type: 'addToCart', productName: product.name, count: countItem })}
41      >
42        Add to Cart
43      </button>
44    </div>
45  )
46}
47
48export default AddToCart
49import React, { useContext } from 'react'
50import { Link, useLocation } from 'react-router-dom'
51import NavList from './NavList'
52import { StoreContext, ItemCounterContext } from '../../App'
53import Logo from '../Logo/Logo'
54
55function Navbar() {
56  const store = useContext(StoreContext)
57  const itemCounter = useContext(ItemCounterContext)
58  const cartIcon = store[6].cart.desktop
59  const location = useLocation()
60  const path = location.pathname
61
62  const itemsSum = itemCounter.state
63    .map((item) => item.count)
64    .reduce((prev, curr) => prev + curr, 0)
65
66  const totalItemsInCart = (
67    <span className='navbar__elements-sum'>
68      {itemsSum}
69    </span>
70  )
71
72  return (
73    <div className={`navbar ${path === '/' ? 'navTransparent' : 'navBlack'}`}>
74      <nav className='navbar__elements'>
75        <Logo />
76        <NavList />
77        <Link className='link' to='/cart'>
78          <img className='navbar__elements-cart' src={cartIcon} alt='AUDIOPHILE CART ICON' />
79          {itemsSum > 0 ? totalItemsInCart : null}
80        </Link>
81      </nav>
82    </div>
83  )
84}
85
86export default Navbar
87

ANSWER

Answered 2022-Jan-14 at 17:06

Well, ItemCounterContext is important for this problem, just ignore StoreContext, it's for images... Here is a reducer function.

1const initialState = [
2  {
3    productName: '',
4    count: 0
5  }
6]
7import React, { useState, useContext } from 'react'
8import { ItemCounterContext } from '../../App'
9
10function AddToCart({ product }) {
11  const itemCounter = useContext(ItemCounterContext)
12  const [countItem, setCountItem] = useState(0)
13
14  const changeCount = (e) => {
15    if (e === '+') { setCountItem(countItem + 1) }
16    if (e === '-' && countItem > 0) { setCountItem(countItem - 1) }
17  }
18
19  return (
20    <div className='add margin-top-small'>
21      <div
22        className='add-counter'
23        onClick={(e) => changeCount(e.target.innerText)}
24        role='button'
25      >
26        -
27      </div>
28
29      <div className='add-counter'>{countItem}</div>
30
31      <div
32        className='add-counter'
33        onClick={(e) => changeCount(e.target.innerText)}
34        role='button'
35      >
36        +
37      </div>
38      <button
39        className='add-btn btnOrange'
40        onClick={() => itemCounter.dispatch({ type: 'addToCart', productName: product.name, count: countItem })}
41      >
42        Add to Cart
43      </button>
44    </div>
45  )
46}
47
48export default AddToCart
49import React, { useContext } from 'react'
50import { Link, useLocation } from 'react-router-dom'
51import NavList from './NavList'
52import { StoreContext, ItemCounterContext } from '../../App'
53import Logo from '../Logo/Logo'
54
55function Navbar() {
56  const store = useContext(StoreContext)
57  const itemCounter = useContext(ItemCounterContext)
58  const cartIcon = store[6].cart.desktop
59  const location = useLocation()
60  const path = location.pathname
61
62  const itemsSum = itemCounter.state
63    .map((item) => item.count)
64    .reduce((prev, curr) => prev + curr, 0)
65
66  const totalItemsInCart = (
67    <span className='navbar__elements-sum'>
68      {itemsSum}
69    </span>
70  )
71
72  return (
73    <div className={`navbar ${path === '/' ? 'navTransparent' : 'navBlack'}`}>
74      <nav className='navbar__elements'>
75        <Logo />
76        <NavList />
77        <Link className='link' to='/cart'>
78          <img className='navbar__elements-cart' src={cartIcon} alt='AUDIOPHILE CART ICON' />
79          {itemsSum > 0 ? totalItemsInCart : null}
80        </Link>
81      </nav>
82    </div>
83  )
84}
85
86export default Navbar
87export const reducer = (state, action) => {
88  // returns -1 if product doesn't exist
89  const indexOfProductInCart = state.findIndex((item) => item.productName === action.productName)
90  const newState = state
91
92  switch (action.type) {
93    case 'increment': {
94      if (indexOfProductInCart === -1) {
95        newState[state.length] = { productName: action.productName, count: state.count + 1 }
96        return newState
97      }
98      newState[indexOfProductInCart] = { productName: action.productName, count: state.count + 1 }
99      return newState
100    }
101    case 'decrement': {
102      if (indexOfProductInCart === -1) {
103        newState[state.length] = { productName: action.productName, count: state.count - 1 }
104        return newState
105      }
106      newState[indexOfProductInCart] = { productName: action.productName, count: state.count - 1 }
107      return newState
108    }
109    case 'addToCart': {
110      if (indexOfProductInCart === -1) {
111        newState[state.length] = { productName: action.productName, count: action.count }
112        return newState
113      }
114      newState[indexOfProductInCart] = { productName: action.productName, count: action.count }
115      return newState
116    }
117    case 'remove': return state.splice(indexOfProductInCart, 1)
118    default: return state
119  }
120}
121

And here is App.js where I share state to other components

1const initialState = [
2  {
3    productName: '',
4    count: 0
5  }
6]
7import React, { useState, useContext } from 'react'
8import { ItemCounterContext } from '../../App'
9
10function AddToCart({ product }) {
11  const itemCounter = useContext(ItemCounterContext)
12  const [countItem, setCountItem] = useState(0)
13
14  const changeCount = (e) => {
15    if (e === '+') { setCountItem(countItem + 1) }
16    if (e === '-' && countItem > 0) { setCountItem(countItem - 1) }
17  }
18
19  return (
20    <div className='add margin-top-small'>
21      <div
22        className='add-counter'
23        onClick={(e) => changeCount(e.target.innerText)}
24        role='button'
25      >
26        -
27      </div>
28
29      <div className='add-counter'>{countItem}</div>
30
31      <div
32        className='add-counter'
33        onClick={(e) => changeCount(e.target.innerText)}
34        role='button'
35      >
36        +
37      </div>
38      <button
39        className='add-btn btnOrange'
40        onClick={() => itemCounter.dispatch({ type: 'addToCart', productName: product.name, count: countItem })}
41      >
42        Add to Cart
43      </button>
44    </div>
45  )
46}
47
48export default AddToCart
49import React, { useContext } from 'react'
50import { Link, useLocation } from 'react-router-dom'
51import NavList from './NavList'
52import { StoreContext, ItemCounterContext } from '../../App'
53import Logo from '../Logo/Logo'
54
55function Navbar() {
56  const store = useContext(StoreContext)
57  const itemCounter = useContext(ItemCounterContext)
58  const cartIcon = store[6].cart.desktop
59  const location = useLocation()
60  const path = location.pathname
61
62  const itemsSum = itemCounter.state
63    .map((item) => item.count)
64    .reduce((prev, curr) => prev + curr, 0)
65
66  const totalItemsInCart = (
67    <span className='navbar__elements-sum'>
68      {itemsSum}
69    </span>
70  )
71
72  return (
73    <div className={`navbar ${path === '/' ? 'navTransparent' : 'navBlack'}`}>
74      <nav className='navbar__elements'>
75        <Logo />
76        <NavList />
77        <Link className='link' to='/cart'>
78          <img className='navbar__elements-cart' src={cartIcon} alt='AUDIOPHILE CART ICON' />
79          {itemsSum > 0 ? totalItemsInCart : null}
80        </Link>
81      </nav>
82    </div>
83  )
84}
85
86export default Navbar
87export const reducer = (state, action) => {
88  // returns -1 if product doesn't exist
89  const indexOfProductInCart = state.findIndex((item) => item.productName === action.productName)
90  const newState = state
91
92  switch (action.type) {
93    case 'increment': {
94      if (indexOfProductInCart === -1) {
95        newState[state.length] = { productName: action.productName, count: state.count + 1 }
96        return newState
97      }
98      newState[indexOfProductInCart] = { productName: action.productName, count: state.count + 1 }
99      return newState
100    }
101    case 'decrement': {
102      if (indexOfProductInCart === -1) {
103        newState[state.length] = { productName: action.productName, count: state.count - 1 }
104        return newState
105      }
106      newState[indexOfProductInCart] = { productName: action.productName, count: state.count - 1 }
107      return newState
108    }
109    case 'addToCart': {
110      if (indexOfProductInCart === -1) {
111        newState[state.length] = { productName: action.productName, count: action.count }
112        return newState
113      }
114      newState[indexOfProductInCart] = { productName: action.productName, count: action.count }
115      return newState
116    }
117    case 'remove': return state.splice(indexOfProductInCart, 1)
118    default: return state
119  }
120}
121import React, { createContext, useMemo, useReducer } from 'react'
122import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
123import Navbar from './components/Navbar/Navbar'
124import Homepage from './pages/Homepage/Homepage'
125import Footer from './components/Footer/Footer'
126import ErrorPage from './pages/ErrorPage/ErrorPage'
127import SelectedCategory from './pages/SelectedCategory/SelectedCategory'
128import SingleProduct from './pages/SingleProduct/SingleProduct'
129import ScrollToTop from './services/ScrollToTop'
130import store from './services/data.json'
131import { reducer } from './services/ItemCounter'
132import './scss/main.scss'
133
134export const StoreContext = createContext(store)
135export const ItemCounterContext = createContext()
136
137function App() {
138  const initialState = [{ productName: '', count: 0 }]
139  const [state, dispatch] = useReducer(reducer, initialState)
140  const counter = useMemo(() => ({ state, dispatch }), [])
141
142  return (
143    <div className='app'>
144      <StoreContext.Provider value={store}>
145        <ItemCounterContext.Provider value={counter}>
146          <Router>
147            <ScrollToTop />
148            <Navbar />
149            <Routes>
150              <Route path='/' element={<Homepage />} />
151              <Route path='/:selectedCategory' element={<SelectedCategory />} />
152              <Route path='/:selectedCategory/:singleProduct' element={<SingleProduct />} />
153              <Route path='*' element={<ErrorPage />} />
154            </Routes>
155            <Footer />
156          </Router>
157        </ItemCounterContext.Provider>
158      </StoreContext.Provider>
159    </div>
160  )
161}
162
163export default App
164

Source https://stackoverflow.com/questions/70713866

QUESTION

connect spring boot to swagger

Asked 2022-Jan-05 at 20:10

I am trying to connect my e-commerce project backend to swagger2. I have installed all the dependencies, yet I still cannot do it.

This is the dependency declared in my pom.xml file:

1<dependency>
2    <groupId>io.springfox</groupId>
3    <artifactId>springfox-swagger2</artifactId>
4    <version>2.9.2</version>
5</dependency>
6
7<dependency>
8    <groupId>io.springfox</groupId>
9    <artifactId>springfox-swagger-ui</artifactId>
10    <version>2.9.2</version>
11</dependency>
12        <dependency>
13    <groupId>org.springframework.boot</groupId>
14    <artifactId>spring-boot-starter-data-mongodb</artifactId>
15</dependency>
16<dependency>
17    <groupId>org.springframework.boot</groupId>
18    <artifactId>spring-boot-starter-web</artifactId>
19</dependency>
20

This is one of my user controller files:

1<dependency>
2    <groupId>io.springfox</groupId>
3    <artifactId>springfox-swagger2</artifactId>
4    <version>2.9.2</version>
5</dependency>
6
7<dependency>
8    <groupId>io.springfox</groupId>
9    <artifactId>springfox-swagger-ui</artifactId>
10    <version>2.9.2</version>
11</dependency>
12        <dependency>
13    <groupId>org.springframework.boot</groupId>
14    <artifactId>spring-boot-starter-data-mongodb</artifactId>
15</dependency>
16<dependency>
17    <groupId>org.springframework.boot</groupId>
18    <artifactId>spring-boot-starter-web</artifactId>
19</dependency>
20@RestController
21@RequestMapping("/api")
22@CrossOrigin
23public class UserController {
24    @Autowired
25    private UserRepository userRepository;
26
27    @GetMapping("/")
28    public List<User> GetUsers() {
29        return userRepository.findAll();
30    }
31    @GetMapping("/{id}")
32    public User GetUser(@PathVariable String id) {
33        return userRepository.findById(id).orElse(null);
34    }
35    @PostMapping("/")
36    public User postMethodName(@RequestBody User user) {
37        return userRepository.save(user);
38    }
39    @PutMapping("/")
40    public User PutMapping(@RequestBody User newUser) {
41        User oldUser = userRepository.findById(newUser.getId()).orElse(null);
42        oldUser.setName(newUser.getName());
43        oldUser.setEmail(newUser.getEmail());
44        oldUser.setPassword(newUser.getPassword());
45        userRepository.save(oldUser);
46        return oldUser;
47    }
48    @DeleteMapping("/{id}")
49    public String DeleteUser(@PathVariable String id) {
50        userRepository.deleteById(id);
51        return id;
52    }
53}
54

This is the code of my main application:

1<dependency>
2    <groupId>io.springfox</groupId>
3    <artifactId>springfox-swagger2</artifactId>
4    <version>2.9.2</version>
5</dependency>
6
7<dependency>
8    <groupId>io.springfox</groupId>
9    <artifactId>springfox-swagger-ui</artifactId>
10    <version>2.9.2</version>
11</dependency>
12        <dependency>
13    <groupId>org.springframework.boot</groupId>
14    <artifactId>spring-boot-starter-data-mongodb</artifactId>
15</dependency>
16<dependency>
17    <groupId>org.springframework.boot</groupId>
18    <artifactId>spring-boot-starter-web</artifactId>
19</dependency>
20@RestController
21@RequestMapping("/api")
22@CrossOrigin
23public class UserController {
24    @Autowired
25    private UserRepository userRepository;
26
27    @GetMapping("/")
28    public List<User> GetUsers() {
29        return userRepository.findAll();
30    }
31    @GetMapping("/{id}")
32    public User GetUser(@PathVariable String id) {
33        return userRepository.findById(id).orElse(null);
34    }
35    @PostMapping("/")
36    public User postMethodName(@RequestBody User user) {
37        return userRepository.save(user);
38    }
39    @PutMapping("/")
40    public User PutMapping(@RequestBody User newUser) {
41        User oldUser = userRepository.findById(newUser.getId()).orElse(null);
42        oldUser.setName(newUser.getName());
43        oldUser.setEmail(newUser.getEmail());
44        oldUser.setPassword(newUser.getPassword());
45        userRepository.save(oldUser);
46        return oldUser;
47    }
48    @DeleteMapping("/{id}")
49    public String DeleteUser(@PathVariable String id) {
50        userRepository.deleteById(id);
51        return id;
52    }
53}
54package com.omazon.ecommerce;
55
56import org.springframework.boot.SpringApplication;
57import org.springframework.boot.autoconfigure.SpringBootApplication;
58
59import springfox.documentation.swagger2.annotations.EnableSwagger2;
60
61@SpringBootApplication
62@EnableSwagger2
63public class ECommerceApplication {
64
65    public static void main(String[] args) {
66        SpringApplication.run(ECommerceApplication.class, args);
67    }
68
69}
70

Lastly, this is what I declared in the application.properties file:

1<dependency>
2    <groupId>io.springfox</groupId>
3    <artifactId>springfox-swagger2</artifactId>
4    <version>2.9.2</version>
5</dependency>
6
7<dependency>
8    <groupId>io.springfox</groupId>
9    <artifactId>springfox-swagger-ui</artifactId>
10    <version>2.9.2</version>
11</dependency>
12        <dependency>
13    <groupId>org.springframework.boot</groupId>
14    <artifactId>spring-boot-starter-data-mongodb</artifactId>
15</dependency>
16<dependency>
17    <groupId>org.springframework.boot</groupId>
18    <artifactId>spring-boot-starter-web</artifactId>
19</dependency>
20@RestController
21@RequestMapping("/api")
22@CrossOrigin
23public class UserController {
24    @Autowired
25    private UserRepository userRepository;
26
27    @GetMapping("/")
28    public List<User> GetUsers() {
29        return userRepository.findAll();
30    }
31    @GetMapping("/{id}")
32    public User GetUser(@PathVariable String id) {
33        return userRepository.findById(id).orElse(null);
34    }
35    @PostMapping("/")
36    public User postMethodName(@RequestBody User user) {
37        return userRepository.save(user);
38    }
39    @PutMapping("/")
40    public User PutMapping(@RequestBody User newUser) {
41        User oldUser = userRepository.findById(newUser.getId()).orElse(null);
42        oldUser.setName(newUser.getName());
43        oldUser.setEmail(newUser.getEmail());
44        oldUser.setPassword(newUser.getPassword());
45        userRepository.save(oldUser);
46        return oldUser;
47    }
48    @DeleteMapping("/{id}")
49    public String DeleteUser(@PathVariable String id) {
50        userRepository.deleteById(id);
51        return id;
52    }
53}
54package com.omazon.ecommerce;
55
56import org.springframework.boot.SpringApplication;
57import org.springframework.boot.autoconfigure.SpringBootApplication;
58
59import springfox.documentation.swagger2.annotations.EnableSwagger2;
60
61@SpringBootApplication
62@EnableSwagger2
63public class ECommerceApplication {
64
65    public static void main(String[] args) {
66        SpringApplication.run(ECommerceApplication.class, args);
67    }
68
69}
70spring.data.mongodb.uri=mongodb://localhost:27017/e-commerce
71

This is the picture of the error I got:

ANSWER

Answered 2022-Jan-05 at 20:10

Swagger2's usage seems to require (or at least often includes) the concept of a Docket api via an instantiation such as new Docket() or new Docket(DocumentationType.SWAGGER_2). I don't see that in your code snippets, so wonder if that may be one issue.

Per the swagger docs, Docket is Springfox’s primary api configuration mechanism.

Specifically, this section regarding configuration may be helpful. Note the Docket instantiation:

1<dependency>
2    <groupId>io.springfox</groupId>
3    <artifactId>springfox-swagger2</artifactId>
4    <version>2.9.2</version>
5</dependency>
6
7<dependency>
8    <groupId>io.springfox</groupId>
9    <artifactId>springfox-swagger-ui</artifactId>
10    <version>2.9.2</version>
11</dependency>
12        <dependency>
13    <groupId>org.springframework.boot</groupId>
14    <artifactId>spring-boot-starter-data-mongodb</artifactId>
15</dependency>
16<dependency>
17    <groupId>org.springframework.boot</groupId>
18    <artifactId>spring-boot-starter-web</artifactId>
19</dependency>
20@RestController
21@RequestMapping("/api")
22@CrossOrigin
23public class UserController {
24    @Autowired
25    private UserRepository userRepository;
26
27    @GetMapping("/")
28    public List<User> GetUsers() {
29        return userRepository.findAll();
30    }
31    @GetMapping("/{id}")
32    public User GetUser(@PathVariable String id) {
33        return userRepository.findById(id).orElse(null);
34    }
35    @PostMapping("/")
36    public User postMethodName(@RequestBody User user) {
37        return userRepository.save(user);
38    }
39    @PutMapping("/")
40    public User PutMapping(@RequestBody User newUser) {
41        User oldUser = userRepository.findById(newUser.getId()).orElse(null);
42        oldUser.setName(newUser.getName());
43        oldUser.setEmail(newUser.getEmail());
44        oldUser.setPassword(newUser.getPassword());
45        userRepository.save(oldUser);
46        return oldUser;
47    }
48    @DeleteMapping("/{id}")
49    public String DeleteUser(@PathVariable String id) {
50        userRepository.deleteById(id);
51        return id;
52    }
53}
54package com.omazon.ecommerce;
55
56import org.springframework.boot.SpringApplication;
57import org.springframework.boot.autoconfigure.SpringBootApplication;
58
59import springfox.documentation.swagger2.annotations.EnableSwagger2;
60
61@SpringBootApplication
62@EnableSwagger2
63public class ECommerceApplication {
64
65    public static void main(String[] args) {
66        SpringApplication.run(ECommerceApplication.class, args);
67    }
68
69}
70spring.data.mongodb.uri=mongodb://localhost:27017/e-commerce
71...
72@Bean //Don't forget the @Bean annotation
73public Docket customImplementation(){
74   return new Docket()
75         .apiInfo(apiInfo());
76         //... more options available
77...
78

There's also a more complete example in those same docs here.

For reference, there's another usage example in this tutorial.

Source https://stackoverflow.com/questions/70596326

QUESTION

Can Django select_for_update be used to acquire a read lock?

Asked 2021-Dec-08 at 04:47

I'm working on a project similar to ecommerce in which I have models that represent a product with a certain amount in the storage, and users can buy some quantity of the product as long as it doesn't exceed the stored amount. I want to avoid a race condition taking place when the server receives multiple requests to buy the same product.

1class Product(models.Model):
2   amount_in_storage = models.PositiveIntegerField() # for design reasons, this amount is unchangeable, it must be only evaluated once during initialization like constants in C++
3
4   @property
5   def amount_available_for_purchase(self):
6       return self.amount_in_storage - Purchase.objects.filter(product=self.id).aggregate(models.Sum('amount'))["sum__amount"]
7
1class Product(models.Model):
2   amount_in_storage = models.PositiveIntegerField() # for design reasons, this amount is unchangeable, it must be only evaluated once during initialization like constants in C++
3
4   @property
5   def amount_available_for_purchase(self):
6       return self.amount_in_storage - Purchase.objects.filter(product=self.id).aggregate(models.Sum('amount'))["sum__amount"]
7class Purchase(models.Model):
8   product = models.ForeignKey(Product, ...)
9   amount = models.PositiveIntegerField()
10   payment_method = ...
11
12

Let's assume that this is the block of code that's responsible for creating a purchase.

1class Product(models.Model):
2   amount_in_storage = models.PositiveIntegerField() # for design reasons, this amount is unchangeable, it must be only evaluated once during initialization like constants in C++
3
4   @property
5   def amount_available_for_purchase(self):
6       return self.amount_in_storage - Purchase.objects.filter(product=self.id).aggregate(models.Sum('amount'))["sum__amount"]
7class Purchase(models.Model):
8   product = models.ForeignKey(Product, ...)
9   amount = models.PositiveIntegerField()
10   payment_method = ...
11
12@atomic_transaction
13def func(product_id, amount_to_purchase):
14   product = Product.objects.get(...)
15   if product.amount_available_for_purchase > amount_to_purchase:
16     # do payment related stuff
17     Purchase.objects.create(product=product, amount=amount_to_purchase)
18     # do more stuff
19

I would like to restrict concurrent access to this block of code, Ideally I would like to obtain a read lock access at the if condition, so that if multiple threads try to see if the amount available is greater than the amount to purchase, one of the threads will have to wait until the transaction is done, and then the read request will be evaluated, so I thought leveraging Django's select_for_update and a version field like so:

1class Product(models.Model):
2   amount_in_storage = models.PositiveIntegerField() # for design reasons, this amount is unchangeable, it must be only evaluated once during initialization like constants in C++
3
4   @property
5   def amount_available_for_purchase(self):
6       return self.amount_in_storage - Purchase.objects.filter(product=self.id).aggregate(models.Sum('amount'))["sum__amount"]
7class Purchase(models.Model):
8   product = models.ForeignKey(Product, ...)
9   amount = models.PositiveIntegerField()
10   payment_method = ...
11
12@atomic_transaction
13def func(product_id, amount_to_purchase):
14   product = Product.objects.get(...)
15   if product.amount_available_for_purchase > amount_to_purchase:
16     # do payment related stuff
17     Purchase.objects.create(product=product, amount=amount_to_purchase)
18     # do more stuff
19class Product(models.Model):
20   amount_in_storage = models.PositiveIntegerField()
21   version = models.PositiveIntegerField() # we use this field just to write to it, no reading will take place
22
23   @property
24   def amount_available_for_purchase(self):
25       return self.amount_in_storage - Purchase.objects.filter(product=self.id).aggregate(models.Sum('amount'))["sum__amount"]
26

And I use this field to obtain a lock like so:

1class Product(models.Model):
2   amount_in_storage = models.PositiveIntegerField() # for design reasons, this amount is unchangeable, it must be only evaluated once during initialization like constants in C++
3
4   @property
5   def amount_available_for_purchase(self):
6       return self.amount_in_storage - Purchase.objects.filter(product=self.id).aggregate(models.Sum('amount'))["sum__amount"]
7class Purchase(models.Model):
8   product = models.ForeignKey(Product, ...)
9   amount = models.PositiveIntegerField()
10   payment_method = ...
11
12@atomic_transaction
13def func(product_id, amount_to_purchase):
14   product = Product.objects.get(...)
15   if product.amount_available_for_purchase > amount_to_purchase:
16     # do payment related stuff
17     Purchase.objects.create(product=product, amount=amount_to_purchase)
18     # do more stuff
19class Product(models.Model):
20   amount_in_storage = models.PositiveIntegerField()
21   version = models.PositiveIntegerField() # we use this field just to write to it, no reading will take place
22
23   @property
24   def amount_available_for_purchase(self):
25       return self.amount_in_storage - Purchase.objects.filter(product=self.id).aggregate(models.Sum('amount'))["sum__amount"]
26
27@atomic_transaction
28def func(product_id, amount_to_purchase):
29   product = Product.objects.select_for_update.get(...)
30
31   # acquiring a lock
32   product.version += 1 
33   product.save()
34
35   if product.amount_available_for_purchase > amount_to_purchase:
36     # do payment related stuff
37     Purchase.objects.create(product=product, amount=amount_to_purchase)
38     # do more stuff
39

Using select_for_update if multiple threads reach the version modification line, only the first will evaluate, and the rest will have to wait until the whole transaction is completed, hence acquiring a read lock for the line at the if condition. In other words, only 1 thread at a time will have access to this block of code.

My questions are:

  1. Is my approach doing what I think it's doing?
  2. Is this a clean approach? if not, how can this be achieved without complicating the codebase and going through a major refactor?

ANSWER

Answered 2021-Dec-08 at 04:47
  1. Yes, your approach is pretty much right and it will acquire the lock for the first query and the rest will have to wait until the transaction is complete.

  2. If you are not using the version field for anything other than acquiring the lock, you can forcefully acquire a lock by forcefully evaluating the QuerySet using a list(). See the code below.

1class Product(models.Model):
2   amount_in_storage = models.PositiveIntegerField() # for design reasons, this amount is unchangeable, it must be only evaluated once during initialization like constants in C++
3
4   @property
5   def amount_available_for_purchase(self):
6       return self.amount_in_storage - Purchase.objects.filter(product=self.id).aggregate(models.Sum('amount'))["sum__amount"]
7class Purchase(models.Model):
8   product = models.ForeignKey(Product, ...)
9   amount = models.PositiveIntegerField()
10   payment_method = ...
11
12@atomic_transaction
13def func(product_id, amount_to_purchase):
14   product = Product.objects.get(...)
15   if product.amount_available_for_purchase > amount_to_purchase:
16     # do payment related stuff
17     Purchase.objects.create(product=product, amount=amount_to_purchase)
18     # do more stuff
19class Product(models.Model):
20   amount_in_storage = models.PositiveIntegerField()
21   version = models.PositiveIntegerField() # we use this field just to write to it, no reading will take place
22
23   @property
24   def amount_available_for_purchase(self):
25       return self.amount_in_storage - Purchase.objects.filter(product=self.id).aggregate(models.Sum('amount'))["sum__amount"]
26
27@atomic_transaction
28def func(product_id, amount_to_purchase):
29   product = Product.objects.select_for_update.get(...)
30
31   # acquiring a lock
32   product.version += 1 
33   product.save()
34
35   if product.amount_available_for_purchase > amount_to_purchase:
36     # do payment related stuff
37     Purchase.objects.create(product=product, amount=amount_to_purchase)
38     # do more stuff
39@atomic_transaction
40def func(product_id, amount_to_purchase):
41    # Forcefully acquiring a lock
42    product = list(Product.objects.select_for_update.filter(...))[0]
43
44    if product.amount_available_for_purchase > amount_to_purchase:
45      # do payment related stuff
46      Purchase.objects.create(product=product, amount=amount_to_purchase)
47      # do more stuff
48

Here you are acquiring the lock forcefully by evaluating the QuerySet like mentioned here in the docs.

Source https://stackoverflow.com/questions/69173209

QUESTION

Google Tag Manager / Enhanced E-commerce - Purchase tag dataLayer push working only on Tag Assistance

Asked 2021-Dec-07 at 07:30

I'm trying to add Enhance Ecommerce but something isn't okay. When I make an order through Google Tag Assistance everything is working and the transaction is showed on the Google Analytics but when I make an order normally like customer nothing is showed.

This is what I've added to thank-you page on the shop

1<script type="text/javascript">
2
3dataLayer.push({ ecommerce: null });
4dataLayer.push({
5    'event': 'transaction',
6    'ecommerce': {        
7        'purchase': {
8            'actionField': {
9                'id': '<?php echo $order->get_order_number() ?>',
10                'revenue': '<?php echo number_format($order->get_subtotal(), 2, ".", ""); ?>', 
11                'number_of_products': '<?php echo $order->get_item_count(); ?>'
12            },
13            'products': [
14                
15                <?php foreach ($order->get_items() as $key => $item): ?>
16                {
17                    'name': '<?php echo $item['name']; ?>',
18                    'id': '<?php echo $item['product_id']; ?>',
19                    'price': '<?php echo number_format($item->get_total(), 2, ".", ""); ?>',
20                    'quantity': '<?php echo $item['qty']; ?>'
21                },
22                <?php endforeach; 
23                ?>
24            ]
25        }
26    }
27});
28
29</script> 
30

And this is my setup in Google Tag Manager

tag enter image description here

The trigger enter image description here

Few variables - order_id enter image description here

Product name enter image description here

Tried google, tried tutorials and still nothing helped.

When I run from Tag Assistant everything is go to analytic. When doesn't go through Tag Assistant nothing is showed.

Any ideas?

UPDATE: GTM Workspace preview

enter image description here

ANSWER

Answered 2021-Dec-07 at 07:26

In order to enter preview, you have to first open GTM. In GTM, you have workspaces. Or at least, the default one. open GTM, go to the overview tab of the workspace that you're previewing (since you don't know what worspaces are, you probably use the default one) and make sure there are no Workspace Changes in it. Here is a screenshot of a workspace WITH changes:

enter image description here

And here is another workspace with NO changes:

enter image description here

If you have changes in your workspace, try publishing them and see if your tags start firing in prod.

Source https://stackoverflow.com/questions/70244649

Community Discussions contain sources that include Stack Exchange Network

Tutorials and Learning Resources in Ecommerce

Share this Page

share link

Get latest updates on Ecommerce