Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Dificuldades em criar um storage para itens de um carrinho

Estou desenvolvendo um simples app para listagem de pizzas. Quando seleciono uma pizza dessa lista, tenho os detalhes da mesma (Sabor, Ingredientes, tamanhos e seus respectivos preços). Utilizando um toggle posso escolher o tamanho da pizza. Na próxima página tenho a opção de escolher uma bebida (Nome, tipo: lata, litro, 2 litros). Todos esses dados eu consumo de uma API, o problema é como posso adicionar esses item a um carrinho, por exemplo? Abaixo alguns códigos:

CartServiceProvider

import { Injectable } from '@angular/core';
import { Storage } from '@ionic/storage';

@Injectable()
export class CartServiceProvider {

  cartItems: any[];

  constructor(private storage: Storage) {
    this.storage.get('cart').then((value) => {
      if(value == null) {
        this.cartItems = [];
      } else {
        this.cartItems = value;
      }
    });
  }

  getCart(): Promise<any> {
    return this.storage.get('cart');
  }

  addToCart(item: any): Promise<any> {
    this.cartItems.push(item);
    return this.storage.set('cart', this.cartItems);
  }

  clearCart(): Promise<any> {
    this.cartItems = [];
    return this.storage.remove('cart');
  }

}

PizzaPage.ts

import { Cart } from './../../models/cart';
import { DrinkPage } from './../drink/drink';
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { Pizza } from '../../models/pizza';
import { CartServiceProvider } from '../../providers/cart-service/cart-service';

@IonicPage()
@Component({
  selector: 'page-pizza',
  templateUrl: 'pizza.html',
})
export class PizzaPage {

  public pizza : Pizza;
  public sizes : any[] = [];
  public totalPrice: number = 0.00;
  itemsInCart: Object[] = [];
  //cart = new Array<Cart>();
  //cart : Array<Cart> = [];
  cart : Pizza;

  constructor(public navCtrl: NavController,
              public navParams: NavParams,
              private cartService: CartServiceProvider) {
                this.pizza = this.navParams.get('pizza');
  }

  ionViewDidLoad() {
    this.pizza.sizes.forEach(element => {
      this.sizes.push(element);
    });
  }

  nextPage() {
    this.navCtrl.push(DrinkPage, {
      totalPrice: this.totalPrice
    });
  }

  updateTotalPrice(active: Boolean, pizzaPrice) {
    active ?
    this.totalPrice += pizzaPrice :
    this.totalPrice -= pizzaPrice;
  }

  getTotalPrice() {
    return this.totalPrice;
  }

  addToCart(active: Boolean, id, pizza, size, price) {
    if(active == true) {
      this.cart._id = id;
      this.cart.name = pizza;
      this.cart.sizes = size;
      console.log('aqui');
    }

    this.cartService.addToCart(this.cart);
    console.log(this.cart);
  }

}

PizzaPage.html

<ion-header>

  <ion-navbar>
    <ion-title>Escolha sua Pizza</ion-title>
  </ion-navbar>

</ion-header>


<ion-content padding>
  <ion-card >
    <img src={{pizza.image}}/>
    <ion-card-content>
      <ion-card-title>
        {{pizza.name}}
      </ion-card-title>
      <p>
        {{pizza.ingredients}}
      </p>
    </ion-card-content>
      <ion-item *ngFor="let item of sizes">
        <ion-label>
          <h2> {{ item.size }}</h2>
          <h4>R$ {{ item.price }}</h4>
        </ion-label>
        <ion-toggle #toggle color="secondary"
          (ionChange)="updateTotalPrice(toggle.checked, item.price)" (click)="addToCart(toggle.checked, pizza._id, pizza.name, item.size, item.price)">
        </ion-toggle>        
      </ion-item>
  </ion-card>

  <ion-item-divider color="light">
      <span item-right>Preço Total: R$ {{ totalPrice }}</span>
    </ion-item-divider>

    <ion-fab top right edge>
      <button ion-fab mini (click)=nextPage()>
          <ion-icon name="arrow-dropright"></ion-icon>
      </button>
    </ion-fab>
</ion-content>

Alguma orientação? Lembrando que ainda possuo a página de Bebidas onde devo fazer basicamente a mesma coisa da Pizza (escolher a pizza, o tamanho e adicionar ao carrinho).

3 respostas

Boa tarde, Wesley! Como vai?

A sua pergunta durante o seu post foi:

como posso adicionar esses item a um carrinho, por exemplo?

No entanto, vc já faz isso! Como na linha a seguir:

// PizzaPage.ts

this.cartService.addToCart(this.cart);

Então não ficou claro para mim qual é a sua dúvida ou o problema que vc está enfrentando. Afinal de contas, vc já tem um serviço representando o seu carrinho, o CartServiceProvider, então sempre que quiser adicionar algo no carrinho basta injetar esse serviço e usar ele.

Pegou a ideia?

Se vc ainda tiver alguma dúvida, é só falar que eu te ajudo!

DICA: Quando estiver trabalhando com Angular/Ionic dê preferência por trabalhar com Observable do RxJS do que trabalhar com Promise pois o RxJS é a solução padrão desses frameworks para tratamento de processamento assíncrono!

Grande abraço, meu aluno!

Boa, Gabriel Leite. Obrigado pela dica do Observable. Sim, nessa linha:

this.cartService.addToCart(this.cart);

a ideia é que realmente faça a inclusão do item ao carrinho. No entanto, não consigo de fato inserir este item. Eu tenho dois modelos de dados que é um para Pizza e Bebida. Nesta linha tento fazer o seguinte:

addToCart(active: Boolean, pizza, size, price) {
    if(active == true) {
      this.cart.productName = pizza;
      this.cart.productSize = size;
    }
    this.cartService.addToCart(this.cart);

Só que recebo: Cannot set property 'productName' of undefined. Lembrando que meu objeto cart está definido como: cart : Cart; Logo meu modelo Cart:

export class Cart {
  cartId: Number;
  productName: String[];
  quantity: Number;
  productSize: String[];
  totalPrice: Number;
}
solução!

Boa noite, Wesley! Como vai?

Cannot set property 'productName' of undefined.

Vc está recebendo essa mensagem de erro pq o atributo cart não foi inicializado em nenhum momento na sua classe, portanto ele está com o valor de undefined e ao tentar fazer this.cart.productName = pizza vc acaba tendo esse erro! Inicialize o atributo e esse problema será resolvido.

DICA: Quando os seus modelos consistirem apenas de atributos como é o caso do Cart sem ter nenhum método de comportamento, a boa prática é representar esses modelos como interfaces e não classes, assim como foi visto durante o curso!

Grande abraço, meu aluno!