Reshav-Paul / grodudes_app

A grocery app made with flutter and wordpress/woocommerce backend
MIT License
13 stars 6 forks source link

I have a question about of Woocommerce Flutter App #1

Open trytosee opened 3 years ago

trytosee commented 3 years ago

Hello my brother,

I hope you and your family are good and healthy. I have a easy question. When i clicked on categories just 10 products come. I want to see more products. I tried to change from code but i couldnt. In first page which is Home page the code is working for all products but inside of categories just 10 products show. what should i do ? Where should i change ?

Best Regards, Mustafa Zor

Future fetchNextProductsPage() async { if (allProductPagesFetched) return; List fetchedProducts = []; fetchedProducts = await wooCommerceAPI .getAsync('products?per_page=$productsPerPage&page=$nextProductPage') .timeout(Duration(seconds: 60)); if (fetchedProducts == null) return; if (fetchedProducts.length > 0) nextProductPage++; if (fetchedProducts.length < productsPerPage) allProductPagesFetched = true; fetchedProducts.forEach((item) => _addProduct(Product(item))); notifyListeners(); }

Reshav-Paul commented 3 years ago

Hi Mustafa,

If I understand your description correctly it is happening because in the function fetchCategoryDetails() of the products state manager I have not specified a per_page query in the url and so woocommerce is sending a default list of 10 items. This is a valid issue which I did not notice while working on a deeply nested category hierarchy and so each sub category had less than 10 items.

The quickest way to solve this issue which is more of a hack than an actual solution would be to change the url in fetchCategoryDetails() by adding a per_page query into it and making it a high value, like so,

List<dynamic> data = await wooCommerceAPI
    .getAsync('products/categories?parent=${category.data['id']}&per_page=100')
    .catchError((err) => print(err));

A proper solution would require creating a stateful widget to make a dynamic loading listview that loads more products when the user reaches the end of the list as is done in AllProductsPage.dart (which however uses the provider state) or more appropriately as is done using local state in Orders.dart.

I am not working on this project anymore, so if you or anyone else would make a pull request using any of the above two methods or anything of your own that fixes this I will review and merge it.

Thanks and Regards.

trytosee commented 3 years ago

Thanks bro. I add code what you said But i still get 10 products just. I really want to get more than 10 products . Please i want to go on on this project but I'm stuck. what should i add more. For example on homepage when i clicked "Products" tab all of the products are coming. Like that i want to see also when i clicked on categories i want to see all products in side of categorie.

Future fetchCategoryDetails(Category category) async {
    //fetch sub categories
    List<dynamic> data = await wooCommerceAPI
        .getAsync('products/categories?parent=${category.data['id']}&per_page=100')
        .catchError((err) => print(err));
    List<Category> categories = [];
    data.forEach((item) => categories.add(Category(item)));
    if (categories.length > 0) return {'categories': categories};
    if (allProductPagesFetched) return;
    // fetch products if there are no sub categories
    List<dynamic> productData = await wooCommerceAPI
        .getAsync('products?category=${category.data['id']}')
        .catchError((err) => print(err));
    List<Product> fetchedProducts = [];
    productData.forEach((product) {
      _addProduct(Product(product));
      fetchedProducts.add(this.products[product['id']]);
    });
    return {
      'categories': categories,
      'products': fetchedProducts
    };
  }
trytosee commented 3 years ago

Now i got 100 products . But after the other 100 products not coming. Please help me.

Future fetchCategoryDetails(Category category) async {
    //fetch sub categories
    List<dynamic> data = await wooCommerceAPI
        .getAsync('products/categories?parent=${category.data['id']}&per_page=100')
        .catchError((err) => print(err));
    List<Category> categories = [];
    data.forEach((item) => categories.add(Category(item)));
    if (categories.length > 0) return {'categories': categories};
    if (allProductPagesFetched) return;
    // fetch products if there are no sub categories
    List<dynamic> productData = await wooCommerceAPI
        .getAsync('products?category=${category.data['id']}&per_page=100 ')
        .catchError((err) => print(err));
    List<Product> fetchedProducts = [];
    productData.forEach((product) {
      _addProduct(Product(product));
      fetchedProducts.add(this.products[product['id']]);
    });
    return {
      'categories': categories,
      'products': fetchedProducts
    };
  }
Reshav-Paul commented 3 years ago

Yes the query was added to category request and it also has to be added to the product request. I am attaching the code below. Also remove the line if (allProductPagesFetched) return; because that is for the products page only.

Future fetchCategoryDetails(Category category) async {
    //fetch sub categories
    List<dynamic> data = await wooCommerceAPI
        .getAsync('products/categories?parent=${category.data['id']}&per_page=100')
        .catchError((err) => print(err));
    List<Category> categories = [];
    data.forEach((item) => categories.add(Category(item)));
    if (categories.length > 0) return {'categories': categories};

    // fetch products if there are no sub categories
    List<dynamic> productData = await wooCommerceAPI
        .getAsync('products?category=${category.data['id']}&per_page=100')
        .catchError((err) => print(err));
    List<Product> fetchedProducts = [];
    productData.forEach((product) {
      _addProduct(Product(product));
      fetchedProducts.add(this.products[product['id']]);
    });
    return {
      'categories': categories,
      'products': fetchedProducts,
    };
  }

I hope this works!

Reshav-Paul commented 3 years ago

Now i got 100 products . But after the other 100 products not coming. Please help me.

Future fetchCategoryDetails(Category category) async {
    //fetch sub categories
    List<dynamic> data = await wooCommerceAPI
        .getAsync('products/categories?parent=${category.data['id']}&per_page=100')
        .catchError((err) => print(err));
    List<Category> categories = [];
    data.forEach((item) => categories.add(Category(item)));
    if (categories.length > 0) return {'categories': categories};
    if (allProductPagesFetched) return;
    // fetch products if there are no sub categories
    List<dynamic> productData = await wooCommerceAPI
        .getAsync('products?category=${category.data['id']}&per_page=100 ')
        .catchError((err) => print(err));
    List<Product> fetchedProducts = [];
    productData.forEach((product) {
      _addProduct(Product(product));
      fetchedProducts.add(this.products[product['id']]);
    });
    return {
      'categories': categories,
      'products': fetchedProducts
    };
  }

Yes that is supposed to happen. As I said this is more a hack than a fix. An actual fix would require building a stateful dynamic listview as in Orders.dart or AllProductsPage.dart.

A better hacky solution would be to run a loop. Say you have 250 products. Make the first request for 100 products. If you get 100 products in the response start the loop. Inside the loop use a page variable and pass it to the url query string to get the next page starting from page 2 and keep adding the products to a list. When you get a page that has less than 100 products (page 3 if you have 250 products) you break out.

Still the ideal solution would be to make a stateful dynamic listview widget.

trytosee commented 3 years ago

For example : I have in a categorie 1000 products. Can you show me a loop for easiest way. where i have to write ? How should i change i really dont understand i m so sorry.

// fetch products if there are no sub categories
    List<dynamic> productData = await wooCommerceAPI
        .getAsync('products?category=${category.data['id']}&per_page=100 ')
        .catchError((err) => print(err));
    List<Product> fetchedProducts = [];
    productData.forEach((product) {
      _addProduct(Product(product));
      fetchedProducts.add(this.products[product['id']]);
    });
    return {
      'categories': categories,
      'products': fetchedProducts
    };
  }
Reshav-Paul commented 3 years ago

I have not tested it but you can do something like this. Modify it how you want.

Future fetchCategoryDetails(Category category) async {
    //fetch sub categories
    List<dynamic> data = await wooCommerceAPI
        .getAsync('products/categories?parent=${category.data['id']}&per_page=100')
        .catchError((err) => print(err));
    List<Category> categories = [];
    data.forEach((item) => categories.add(Category(item)));
    if (categories.length > 0) return {'categories': categories};

    // fetch products if there are no sub categories
    List<dynamic> productData = await wooCommerceAPI
        .getAsync('products?category=${category.data['id']}&per_page=100')
        .catchError((err) => print(err));
    List<Product> fetchedProducts = [];
    productData.forEach((product) {
      _addProduct(Product(product));
      fetchedProducts.add(this.products[product['id']]);
    });

    int page = 2;
    while (productData.length >= 100) {
        productData = await wooCommerceAPI
          .getAsync('products?category=${category.data['id']}&per_page=100&page=$page')
          .catchError((err) => print(err));

        productData.forEach((product) {
          _addProduct(Product(product));
          fetchedProducts.add(this.products[product['id']]);
       });
      page++;
    }
    return {
      'categories': categories,
      'products': fetchedProducts,
    };
  }

Test it out. There may be issues because I have not tested it. But I repeat this is not the most ideal solution. This has the potential to make more http requests than necessary and fetching more data than necessary in most situations. But this will be the quickest to implement.