Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 'use strict';
- import { observable } from 'mobx';
- import axios from 'axios';
- import * as _ from 'lodash';
- import { formatRoute } from 'react-router-named-routes';
- import { reloadTop } from '../navigation';
- import { API } from '../routes';
- import * as C from '../_constants';
- import Utils from '../../../_utils';
- import Shop from './_shop';
- import Usage from './_usage';
- import Discount from './_discount';
- const PRODUCT_VARIANTS_LIFETIME = 180;
- export default class Storage {
- /**
- * @type {{id: number, variants: {id:number,title:string,price:string}[], loaded_at: Date}[]}
- * @private
- */
- @observable _productVariants = [];
- /**
- * @type {Discount[]}
- * @private
- */
- @observable _discounts = [];
- /**
- * @type {number[]}
- * @private
- */
- #_requested_products = [];
- /**
- * @type {Shop}
- */
- #shop;
- /**
- * @type {Usage}
- */
- #usage;
- /**
- * @type {number}
- */
- #updateDiscountsTimeout = 0;
- /**
- * @param {{}} shopData
- * @param {{}[]} plansData
- * @param {{}} initialData
- */
- constructor (shopData, plansData, initialData) {
- this.#shop = new Shop(shopData);
- this.#usage = new Usage(plansData, this.#shop);
- this._discounts = initialData.discounts.map(d => new Discount(d, this.shop.timezone));
- this.#loadDiscounts(true);
- }
- /**
- * @return {Shop}
- */
- get shop () {
- return this.#shop;
- }
- /**
- * @return {Usage}
- */
- get usage () {
- return this.#usage;
- }
- /**
- * @return {Discount[]}
- */
- discountsList (status = C.DISCOUNT_STATUS_ANY, search = '') {
- return this._discounts
- .filter(d => status === C.DISCOUNT_STATUS_ANY || d.status === status)
- .filter(d => search === '' || d.name.toLowerCase().indexOf(search.toLowerCase()) !== -1);
- }
- /**
- * @param {number} discountId
- * @param {boolean} enable
- * @param {function} callback
- */
- discountEnable (discountId, enable, callback) {
- let discount = this._discounts.find(d => d.id === discountId);
- if (!discount) {
- return;
- }
- axios.post(formatRoute(API.DISCOUNT_ENABLE, {id: discountId}), {enable})
- .then(response => {
- discount.fillWithData(response.data);
- callback();
- })
- .catch(error => this.constructor.error(error));
- }
- /**
- * @param {number} discountId
- */
- discountDelete (discountId) {
- axios.post(formatRoute(API.DISCOUNT_DELETE, {id: discountId}))
- .then(response => {
- this._discounts = this._discounts.filter(d => d.id !== discountId);
- })
- .catch(error => this.constructor.error(error));
- }
- /**
- * @param {number} discountId
- * @param {{
- * name: string,
- * value_type:string,
- * value: number,
- * override_cents:boolean,
- * override_cents_to: number,
- * override_to_nearest:boolean,
- * applies_to:string,
- * collections: {id:number, title:string, image:string|null}[],
- * products: {id:number, title:string, image:.string|null, hasOnlyDefaultVariant:boolean, variants:number[], selected_itself:boolean}[]
- * date_start:Date,
- * date_stop: Date|null,
- * }} data
- * @param {function} callback
- * @param {boolean} reactivation
- */
- discountSave (discountId, data, callback, reactivation = false) {
- data = this.constructor.prepareDiscountDataToSave(data, this.shop.timezone);
- data.reactivation = reactivation;
- let url = discountId ? formatRoute(API.DISCOUNT_EDIT, {id: discountId}) : API.DISCOUNT_ADD;
- axios.post(url, data)
- .then(response => {
- let discountNew = new Discount(response.data, this.shop.timezone);
- if (discountId) {
- let index = this._discounts.findIndex(d => d.id === discountId);
- if (index !== -1) {
- this._discounts.splice(index, 1, discountNew);
- } else {
- this._discounts.push(discountNew);
- }
- } else {
- this._discounts.push(discountNew);
- }
- this.shop.progress = 2; // Get-started-task "Create a test rule" - done
- callback(discountNew.id);
- })
- .catch(error => this.constructor.error(error));
- }
- /**
- * @param {{
- * applies_to:string,
- * collections: {id:number, title:string, image:string|null}[],
- * products: {id:number, title:string, image:.string|null, hasOnlyDefaultVariant:boolean, variants:number[], selected_itself:boolean}[],
- * date_start:Date,
- * date_stop: Date|null
- * }} data
- * @param {string} shopTimezone
- * @return {*}
- */
- static prepareDiscountDataToSave (data, shopTimezone) {
- data = _.cloneDeep(data);
- data.date_start = Utils.datetimeToString(Utils.datetimeFromShopToServerTimezone(
- data.date_start,
- shopTimezone
- ));
- if (data.date_stop) {
- data.date_stop = Utils.datetimeToString(Utils.datetimeFromShopToServerTimezone(
- data.date_stop,
- shopTimezone
- ));
- } else if (typeof (data.date_stop) !== 'undefined') {
- delete (data.date_stop);
- }
- data.products = data.products.map(p => ({
- id: p.id,
- selected_itself: p.selected_itself,
- variants: p.variants.map(v => parseInt(v))
- }));
- data.collections = data.collections.map(c => parseInt(c.id));
- return data;
- }
- /**
- * @param {number} discountId
- * @param {function} callback
- */
- discountLoadDetails (discountId, callback) {
- axios.get(formatRoute(API.DISCOUNT_PRODUCTS_AND_COLLECTIONS, {id: discountId}))
- .then(response => {
- let discount = this._discounts.find(d => d.id === discountId);
- if (!discount) {
- callback({});
- }
- discount.collections = response.data.collections;
- discount.products = response.data.products;
- callback(discount);
- })
- .catch(error => this.constructor.error(error));
- }
- /**
- * @param {number[]} productIds
- * @param {function} callback
- */
- loadProductVariants (productIds, callback = () => null) {
- // Exclude already loaded (except expired ones) and already requested products
- let now = new Date();
- let excludeIds = [];
- this._productVariants.forEach(product => {
- let expired = now - product.loaded_at > PRODUCT_VARIANTS_LIFETIME * 1000;
- if (!expired) {
- excludeIds.push(product.id);
- }
- });
- productIds = productIds.filter(pid => !excludeIds.includes(pid));
- productIds = productIds.filter(pid => !this.#_requested_products.includes(pid));
- if (!productIds.length) {
- callback();
- return;
- }
- // Remember requested products
- this.#_requested_products = this.#_requested_products.concat(productIds);
- // Do request
- axios.post(API.GET_PRODUCT_VARIANTS, {products: productIds})
- .then(response => {
- // Apply response
- response.data.forEach(item => {
- let newProduct = {
- id: item.id,
- variants: item.variants,
- loaded_at: new Date()
- };
- let k = this._productVariants.findIndex(p => p.id === item.id);
- if (k !== -1) {
- this._productVariants.splice(k, 1, newProduct);
- } else {
- this._productVariants.push(newProduct);
- }
- });
- callback();
- // Clear requested products
- setTimeout(
- () => this.#_requested_products = this.#_requested_products.filter(pid => !productIds.includes(pid)),
- 1000
- );
- })
- .catch(error => this.constructor.error(error));
- }
- /**
- * @param {number} productId
- * @return {{id:number,title:string,price:string}[]|null}
- */
- getProductVariants (productId) {
- let product = this._productVariants.find(p => p.id === productId);
- return product ? product.variants : null;
- }
- /**
- * @param {boolean} delayed
- */
- #loadDiscounts (delayed = false) {
- if (!delayed) {
- axios.get(API.DISCOUNTS)
- .then(response => {
- this._discounts = response.data.map(d => {
- return new Discount(d, this.shop.timezone);
- });
- })
- .catch(error => this.constructor.error(error));
- }
- if (this.#updateDiscountsTimeout) {
- clearTimeout(this.#updateDiscountsTimeout);
- }
- this.#updateDiscountsTimeout = setTimeout(
- () => this.#loadDiscounts(),
- 5000
- );
- }
- /**
- * @type {boolean}
- */
- static #reloading = false;
- /**
- * @param {Error} error
- */
- static error (error) {
- if (error.response && error.response.status && error.response.status === 401) {
- if (!this.#reloading) {
- this.#reloading = true;
- console.warn('Session lost, reloading...');
- reloadTop();
- }
- return;
- }
- console.error(error.message);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement