import { Injectable } from '@angular/core'; import { ApiProvider } from '../../services/api/api.provider'; import { Subject } from 'rxjs/Subject'; import { Cart, CartItem } from './cart'; import { Product } from '../product/product'; import 'rxjs/add/operator/map'; import * as _ from 'lodash'; // Generated class for the ProductsService provider. // See https://angular.io/docs/ts/latest/guide/dependency-injection.html // for more info on providers and Angular 2 DI. @Injectable() export class CartsProvider { carts: Cart[]; currentCart: Cart; // "broadcasting" currentCart cartObservable: Subject; cartsObservable: Subject; constructor( public apiProvider: ApiProvider) { this.carts = []; this.currentCart = Cart.fromJson(this.emptyCart()); this.cartObservable = > new Subject(); this.cartsObservable = > new Subject(); } // cartState(result: Cart) { this.currentCart = result; this.cartObservable.next(this.currentCart); // TODO REMOVE need to check if a cart actually exists this.cartsObservable.next(this.carts); } emptyCart(tenantId?: any, storeId?: any) { let empty: any[]; empty = []; return { '__v': '', 'userId': '', 'storeId': storeId, 'tenantId': tenantId, 'id': '', 'created': '', 'status': '', 'items': empty, 'numItems': 0, 'total': 0 }; } // TODO storeiD? tenatid? create(tenantId: string, storeId: string, userId: string) { let payload: any = {}; // TODO REMOVE for demo only payload.storeId = storeId; payload.tenantId = tenantId; let promise = new Promise( (resolve, reject) => { this.apiProvider.api('POST', '/v1/cart', payload) // new ApiProvider(http).api('POST', '/v1/cart/', payload) .then((response: any) => { if (response.id) { // this.carts[response._id] = response; // this.cartState(response); this.update(tenantId, storeId, userId, response.id).then( (cart: Cart) => resolve(cart)); // DO NOT DELETE, we are utilizing update to override the default userId on create // will need them in the future // const cart = Cart.fromJson(response); // this.carts.push(cart); // this.cartState(cart); // console.log('resolving'); // resolve(cart); } else { reject('No id in cart create response!'); } }, (err) => { // @todo: We should check for errors ?!? reject(err); }); }); return promise; } retrieve(cartId: string) { let payload = {}; let promise = new Promise((resolve, reject) => { // let cart_temp = this.carts.filter((item: Cart) => { return cartId === item.id; }); // if (cart_temp.length >0 ) resolve(cart_temp[0]); // else { this.apiProvider.api('GET', '/v1/cart/' + cartId, payload) .then((response: any) => { if (response.id) { const cart = Cart.fromJson(response); const position = this.carts.findIndex((item) => { return item.id === cart.id; }); this.carts.splice(position, 1, cart); this.cartState(cart); resolve(cart); } else { reject(); } }, (err) => { // catch error // @todo: We should check for errors ?!? reject(err); }); // } }); return promise; } // TODO add code retrieveAllCarts(tenantId?: string, storeId?: string) { let payload: any = {}; if(tenantId) payload.tenantId = tenantId; if(storeId) payload.storeId = storeId; let promise = new Promise((resolve, reject) => { if(this.carts.length === 0){ this.apiProvider.api('GET', '/v1/carts', payload) .then((response: any) => { if (response) { // let cartsN: Cart[] = []; // response.forEach((item: any) => { // cartsN.push(Cart.fromJson(item)); // }); this.carts = this.deserializeCarts(response); this.cartsObservable.next(this.carts); console.log('resolving'); resolve(this.carts); // ?? } else { reject(); } }, (err) => { // catch error // @todo: We should check for errors ?!? reject(err); }); } else resolve(this.carts); }); return promise; } // return from Cart Holder (carts) retrieveByUser(tenantId: string, userId: string ) { let promise = new Promise((resolve) => { resolve (this.carts.filter((cart) => { return (cart.tenantId === tenantId) && (cart.userId === userId); })); }); return promise; } retrieveByUserAndStore(tenantId: string, storeId: string, userId: string) { let promise = new Promise((resolve) => { resolve ( this.carts.filter((cart) => {return (cart.tenantId === tenantId) && (cart.userId === userId) && (cart.storeId === storeId); }) ); }); return promise; } // { // let promise = new Promise((resolve, reject) => { // this.retrieveAllCarts().then((data: Cart[]) => { // resolve (data.filter((cart) => { return (cart.storeId === storeId) && (cart.userId === userId) && (cart.tenantId === tenantId); })); // }, (err) => { // catch error // // @todo: We should check for errors ?!? // reject(err); // }); // }); // return promise; // } addItem(cartId: string, product: CartItem) { let payload = product.toJson(); let promise = new Promise((resolve, reject) => { this.apiProvider.api('POST', '/v1/cart/' + cartId, payload) .then((response: any) => { if (response.id) { const cart = Cart.fromJson(response); const position = this.carts.findIndex((item) => { return item.id === cart.id; }); this.carts.splice(position, 1, cart); this.cartState(cart); resolve(cart); } else { reject(); } }, (err) => { // catch error // @todo: We should check for errors ?!? reject(err); }); }); return promise; } // TODO add code //404! update(tenantId: string, storeId: string, userId: string, cartId: string, tableId?: string) { let payload: any = { 'tenantId': tenantId, 'storeId': storeId, 'userId': userId }; if(tableId) payload.tableId = tableId; let promise = new Promise((resolve, reject) => { this.apiProvider.api('PUT', '/v1/cart/' + cartId, payload) .then((response: any) => { // if (response._id) { if (response.id) { // this.carts[response._id] = response; // this.cartState(response); const cart = Cart.fromJson(response); const position = this.carts.findIndex((item) => { return item.id === cart.id; }); if (position > -1) { this.carts.splice(position, 1, cart); } else { this.carts.push(cart); } this.cartState(cart); console.log('deleting'); resolve(cart); } else { reject(); } }, (err) => { // catch error // @todo: We should check for errors ?!? reject(err); }); }); return promise; } // TODO test delete(cartId: string) { let payload = {}; let promise = new Promise((resolve, reject) => { this.apiProvider.api('DELETE', '/v1/cart/' + cartId, payload) .then((response: any) => { // if (response._id) { if (response.id) { // this.carts[response._id] = response; // this.cartState(response); const cart = Cart.fromJson(response); const position = this.carts.findIndex((item) => { return item.id === cart.id; }); this.carts.splice(position, 1); this.cartsObservable.next(this.carts); console.log('deleting'); resolve(this.carts); } else { reject(); } }, (err) => { // catch error // @todo: We should check for errors ?!? reject(err); }); }); return promise; } // TODO add code open:closed changeStatus(cartId: string) { // http://{{url}}/v1/cart/57b2dc1aca661db6009fdf12/status/open // PATCH // need to retreive status of cart? let payload = {}; let promise = new Promise((resolve, reject) => { this.retrieve(cartId).then( (result: any) => { if (result.id) { let newStatus: string = (this.currentCart.status === 'open' ? 'closed' : 'open'); // this.apiProvider.api('PATCH','v1/cart/'+cartId+'/status/'+newStatus, payload); this.apiProvider.api('PATCH', `/v1/cart/${cartId}/status/${newStatus}`, payload).then((response: any) => { if (response.id) { // this.carts[response._id] = response; // this.cartState(response); const cart = Cart.fromJson(response); const position = this.carts.findIndex((item) => { return item.id === cart.id; }); this.carts.splice(position, 1, cart); this.cartState(cart); console.log('resoving'); resolve(cart); // ?? } else { reject(); } }, (err) => { // catch error // @todo: We should check for errors ?!? reject(err); }); // then } else { // TODO add error reject(); } }, (err) => { // catch error // @todo: We should check for errors ?!? reject(err); }); }); return promise; } // // TODO add code paid(cartId: string) { // http://{{url}}/v1/cart/57ad9b365179a63b00b717dc/paid // POST let payload: any = {}; // payload.storeId = 'typicode'; let promise = new Promise( (resolve, reject) => { this.apiProvider.api('POST', `/v1/cart/${cartId}/paid`, payload) .then((response: any) => { // getting 800 error will handle errors when handler is ready if (response.id) { // this.carts[response._id] = response; // this.cartState(response); // console.log('resolving'); // resolve(response); const cart = Cart.fromJson(response); const position = this.carts.findIndex((item) => { return item.id === cart.id; }); this.carts.splice(position, 1, cart); this.cartState(cart); console.log('resolving'); resolve(cart); } else { reject('Error cart#1'); } }, (err) => { // @todo: We should check for errors ?!? reject(err); }); }); return promise; } // todo need attention retrieveItem(cartId: string, productId: string) { // http://{{url}}/v1/cart/57ad9b365179a63b00b717dc/ksjldhflkdsjfhlds // GET let payload: any = {}; let promise = new Promise( (resolve, reject) => { this.apiProvider.api('GET', `/v1/cart/${cartId}/${productId}`, payload) .then((response: any) => { // getting 800 error will handle errors when handler is ready if (response.productId) { // turn into Product resolve(Product.inCartFromJson(response)); } else { reject('Error retrieving carts'); } }, (err) => { // @todo: We should check for errors ?!? reject(err); }); }); return promise; } // cartItem and draw the id? updateCartItem(cartId: string, productId: string, updatedProduct: CartItem) { // http://{{url}}/v1/cart/57ad9b365179a63b00b717dc/ksjldhflkdsjfhlds // PUT let payload: any = updatedProduct.toJson(); let promise = new Promise( (resolve, reject) => { this.apiProvider.api('PUT', `/v1/cart/${cartId}/${productId}`, payload) .then((response: any) => { // getting 800 error will handle errors when handler is ready if (response.id) { // this.carts[response._id] = response; // this.cartState(response); // console.log('resolving'); // resolve(response); const cart = Cart.fromJson(response); const position = this.carts.findIndex((item) => { return item.id === cart.id; }); this.carts.splice(position, 1, cart); this.cartState(cart); console.log('updating'); resolve(cart); } else { reject('Error in updating Cart Item'); } }, (err) => { // @todo: We should check for errors ?!? reject(err); }); }); return promise; } // probably no login on backend deleteItem(cartId: string, productId: string) { // http://{{url}}/v1/cart/57ad9b365179a63b00b717dc/ksjldhflkdsjfhlds // DELETE console.log(`deleting from cart ${cartId} the following Item ${productId}`); let payload: any = {}; let promise = new Promise((resolve, reject) => { this.apiProvider.api('DELETE', `/v1/cart/${cartId}/${productId}`, payload) .then((response: any) => { if (response.id) { // this.carts[response._id] = response; // this.cartState(response); // resolve(response); const cart = Cart.fromJson(response); const position = this.carts.findIndex((item) => { return item.id === cart.id; }); this.carts.splice(position, 1, cart); this.cartState(cart); console.log('deleting item'); resolve(cart); // ?? } else { reject(); } }, (err) => { // catch error // @todo: We should check for errors ?!? reject(err); }); }); return promise; } deleteAllItems(cartId: string){ console.log(`deleting all items from cart ${cartId} `); let payload: any = {}; let promise = new Promise((resolve, reject) => { this.apiProvider.api('DELETE', `/v1/cart/${cartId}/flush`, payload) .then((response: any) => { if (response.id) { // this.carts[response._id] = response; // this.cartState(response); // resolve(response); const cart = Cart.fromJson(response); const position = this.carts.findIndex((item) => { return item.id === cart.id; }); this.carts.splice(position, 1, cart); this.cartState(cart); console.log('deleting item'); resolve(cart); // ?? } else { reject(); } }, (err) => { // catch error // @todo: We should check for errors ?!? reject(err); }); }); return promise; } // TODO : GIWRGO EINAI DIKH SOU DOULEIA // getDetails (cartId: string) { // let cart: Cart; // if (!this.carts[cartId]) { // we don't have an active cart stored // // So, let's create a new one and store it in our cache // cart = this.emptyCart(); // this.carts[cartId] = cart; // }else { // cart = this.carts[cartId]; // } // // @todo: we should ask the APIs to recalculate... // // cart.total = 0; // // angular.forEach(cart.items, function (value, key) { // // cart.total += value.price * value.quantity; // // }); // return cart; // } // setCurrentCart (id: string) { // let cart: Cart = this.getDetails(id); // this.currentCart = Cart.fromJson(this.emptyCart()); // for (let item in cart) { // if (cart.hasOwnProperty(item)) { // // this.currentCart[item] = cart[item]; // const position = this.currentCart.getCartItems().findIndex((item) => { return item.getProduct().id === cart.id; }); // this.carts.splice(position, 1, cart); // } // } // this.cartObservable.next(this.currentCart); // console.log(this.carts); // } // Deserializers rename to & from // TODO FIX // deserializeCart(incoming: any) { // let items: CartItem[]; // items = []; // for (let item of incoming.items) { // // let tempCartItem = // let tempCartItem = new CartItem( // Product.inCartFromJson(item) // , item.quantity); // items.push(tempCartItem); // } // return new Cart(undefined, undefined, undefined, items, undefined, incoming._id); // } deserializeCarts(incoming: any) { let carts: Cart[] = _.map((_.values(incoming)), Cart.fromJson); return carts; } }