Commit b69474aa authored by Tsvetelina Yordanova's avatar Tsvetelina Yordanova
Browse files

feat: #60 create promotion

parent 33d280d4
Loading
Loading
Loading
Loading
+32 −31
Original line number Diff line number Diff line
@@ -31,6 +31,28 @@
				</ion-item>
			</ion-col>
		</ion-row>
		<ion-row>
			<ion-col>
				<ion-item>
					<ion-label>Select Product</ion-label>
					<ion-select
						placeholder="Select One"
						formControlName="product"
					>
						<ion-select-option
							[value]="product.id"
							*ngFor="let product of displayProducts"
							><ion-img
								*ngIf="product.image"
								[src]="product.image"
								alt="Product image"
							></ion-img>
							{{ product.title }}</ion-select-option
						>
					</ion-select>
				</ion-item>
			</ion-col>
		</ion-row>
		<ion-row>
			<ion-col text-center>
				<ion-item>
@@ -46,6 +68,16 @@
				</ion-item>
			</ion-col>
		</ion-row>
		<ion-row>
			<ion-col text-center>
				<ion-item>
					<ion-label position="floating">{{
						'CARRIERS_VIEW.PROMOTIONS.DESCRIPTION' | translate
					}}</ion-label>
					<ion-textarea formControlName="description"> </ion-textarea>
				</ion-item>
			</ion-col>
		</ion-row>
		<ion-row>
			<ion-col text-center>
				<ion-item>
@@ -74,36 +106,5 @@
				</ion-item>
			</ion-col>
		</ion-row>

		<ion-row>
			<ion-col>
				<ion-item>
					<ion-label class="labels" position="floating">{{
						'CARRIERS_VIEW.PROMOTIONS.PURCHASES_COUNT' | translate
					}}</ion-label>
					<ion-input
						type="number"
						formControlName="purchasesCount"
						[placeholder]="
							'CARRIERS_VIEW.PROMOTIONS.PURCHASES_COUNT'
								| translate
						"
					></ion-input>
				</ion-item>
			</ion-col>
		</ion-row>
		<ion-row>
			<ion-col text-center>
				<ion-item>
					<ion-label class="labels" position="floating">{{
						'CARRIERS_VIEW.PROMOTIONS.IS_ACTIVE' | translate
					}}</ion-label>
					<ion-checkbox
						formControlName="active"
						color="primary"
					></ion-checkbox>
				</ion-item>
			</ion-col>
		</ion-row>
	</ion-grid>
</form>
+142 −99
Original line number Diff line number Diff line
import { Component, OnDestroy, OnInit, Input } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import {
	Component,
	OnDestroy,
	OnInit,
	Input,
	Output,
	EventEmitter,
} from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { IPromotion } from '@modules/server.common/interfaces/IPromotion';
	IPromotion,
	IPromotionCreateObject,
} from '@modules/server.common/interfaces/IPromotion';
import { Subject } from 'rxjs';
import { ILocaleMember } from '@modules/server.common/interfaces/ILocale';
import { takeUntil } from 'rxjs/operators';
import { result } from 'lodash';
import { WarehouseProductsRouter } from '@modules/client.common.angular2/routers/warehouse-products-router.service';
import IProduct from '@modules/server.common/interfaces/IProduct';
import { ProductLocalesService } from '@modules/client.common.angular2/locale/product-locales.service';

@Component({
	selector: 'basic-info-form',
@@ -19,18 +17,20 @@ import { result } from 'lodash';
	templateUrl: 'basic-info-form.component.html',
})
export class BasicInfoFormComponent implements OnInit, OnDestroy {
	languageCode: string;

	@Input()
	readonly form: FormGroup;

	@Input()
	promotionData: IPromotion;

	@Output()
	onCompleteEvent = new EventEmitter();
	availableProducts: Partial<IProduct>[] = [];
	displayProducts: { id: string; title: string; image: string }[];

	private languageCode: string;

	private promotion: Partial<IPromotion>;

	private _promotion: IPromotion | any;
	private translateProperties = ['title', 'description'];

	get locale() {
		return this.form.get('locale');
@@ -40,62 +40,37 @@ export class BasicInfoFormComponent implements OnInit, OnDestroy {
		return this.form.get('title');
	}

	get activeFrom() {
		return this.form.get('activeFrom');
	get description() {
		return this.form.get('description');
	}

	get activeTo() {
		return this.form.get('activeTo');
	get warehouseId() {
		return localStorage.getItem('_warehouseId');
	}

	get product() {
		return this.form.get('product');
	}

	get active() {
		return this.form.get('active');
	}

	get purchasesCount() {
		return this.form.get('purchasesCount');
	get language() {
		return localStorage.getItem('_language');
	}

	private _ngDestroy$ = new Subject<void>();

	constructor(
		private readonly warehouseProductService: WarehouseProductsRouter,
		private readonly productLocalesService: ProductLocalesService
	) {}

	ngOnInit(): void {
		//tstodo get global locale from somewhere
		this._setDefaultLocaleValue();

		this._promotion = this.promotionData || this._initPromotion();
		this._initMerchantProducts();

		['title', 'description'].forEach((promotionTranslateProp) => {
			this.addLocaleMember(this._promotion[promotionTranslateProp]);
		});
		this.promotion = this.promotionData || this._initPromotion();

		this._loadData();
		this._initTranslationValues();

		this.locale.valueChanges
			.pipe(takeUntil(this._ngDestroy$))
			.subscribe((value) => {
				console.log(this._promotion);

				['title', 'description'].forEach((promotionTranslateProp) => {
					this.saveLocaleMember(
						promotionTranslateProp,
						this._promotion[promotionTranslateProp]
					);
				});

				['title', 'description'].forEach((promotionTranslateProp) => {
					this.addLocaleMember(
						this._promotion[promotionTranslateProp]
					);
				});

				this.languageCode = value;
		this._setValue();

				this.setValue();
			});
		this._subscribeToLanguageChanges();
	}

	ngOnDestroy() {
@@ -103,41 +78,33 @@ export class BasicInfoFormComponent implements OnInit, OnDestroy {
		this._ngDestroy$.complete();
	}

	saveLocaleMember(translateProp: string, member: ILocaleMember[]): void {
		debugger;

		const memberValue = this._getLocaleMember(member);
	getValue() {
		this._saveTranslationValues();

		if (memberValue) {
			this._promotion[translateProp].value = this[translateProp].value;
		}
	}
		let basicInfoValue = this.form.value;

	addLocaleMember(member: ILocaleMember[]): void {
		const memberValue = this._getLocaleMember(member);
		basicInfoValue.title = this.promotion.title;
		basicInfoValue.description = this.promotion.description;
		delete basicInfoValue.locale;

		if (!memberValue) {
			member.push({ locale: this.locale.value, value: '' });
		}
		return basicInfoValue as IPromotionCreateObject;
	}

	getValue() {
		return this.form.getRawValue();
	}
	private _setValue() {
		if (!this.promotion) return;

	setValue() {
		const promotionFormValue = {
			title: this._getLocaleMember(this._promotion.title)
				? this._getLocaleMember(this._promotion.title)['value']
				: '',
			description: this._getLocaleMember(this._promotion.description)
				? this._getLocaleMember(this._promotion.description)['value']
				: '',
			activeFrom: this._promotion.activeFrom || new Date(),
			activeTo: this._promotion.activeFrom || null,
			product: null,
			active: this._promotion.active || true,
			purchasesCount: this._promotion.purchasesCount || 0,
			title: this.productLocalesService.getTranslate(
				this.promotion.title,
				this.languageCode
			),
			description: this.productLocalesService.getTranslate(
				this.promotion.description,
				this.languageCode
			),
			activeFrom: this.promotion.activeFrom || new Date(),
			activeTo: this.promotion.activeTo || null,
			product: this.promotion.product || null,
		};

		this.form.patchValue(promotionFormValue);
@@ -147,11 +114,94 @@ export class BasicInfoFormComponent implements OnInit, OnDestroy {
		return formBuilder.group({
			locale: ['en-US'],
			title: [''],
			description: [''],
			activeFrom: [null],
			activeTo: [null],
			product: [null],
			active: [true],
			purchasesCount: [0, Validators.min(0)],
		});
	}

	private _saveLocaleMember(
		translateProp: string,
		member: ILocaleMember[]
	): void {
		const memberValue = this._getLocaleMember(member, this.languageCode);

		if (memberValue) {
			let updateProperty = this.promotion[translateProp].find(
				(localeValue) => {
					return localeValue['locale'] === this.languageCode;
				}
			);
			updateProperty.value = this[translateProp].value;
		}
	}

	private _addLocaleMember(member: ILocaleMember[]): void {
		const memberValue = this._getLocaleMember(member, this.locale.value);

		if (!memberValue) {
			member.push({ locale: this.locale.value, value: '' });
		}
	}

	private _initTranslationValues() {
		this.translateProperties.forEach((promotionTranslateProp) => {
			this._addLocaleMember(this.promotion[promotionTranslateProp]);
		});
	}

	private _saveTranslationValues() {
		this.translateProperties.forEach((promotionTranslateProp) => {
			this._saveLocaleMember(
				promotionTranslateProp,
				this.promotion[promotionTranslateProp]
			);
		});
	}

	private _initMerchantProducts() {
		this.warehouseProductService
			.getAvailable(this.warehouseId || null)
			.pipe(takeUntil(this._ngDestroy$))
			.subscribe((resData) => {
				if (!resData) return;

				this.availableProducts = resData.map((warehouseProduct) => {
					return {
						id: warehouseProduct.product['id'] || null,
						title: warehouseProduct.product['title'] || [],
						images: warehouseProduct.product['images'] || [],
					};
				});

				this._initFormDisplayProducts();
			});
	}

	private _initFormDisplayProducts() {
		if (!this.availableProducts) return;

		this.displayProducts = this.availableProducts.map((product) => {
			return {
				id: product['id'],
				image: this.productLocalesService.getTranslate(product.images),
				title: this.productLocalesService.getTranslate(product.title),
			};
		});
	}

	private _subscribeToLanguageChanges() {
		this.locale.valueChanges
			.pipe(takeUntil(this._ngDestroy$))
			.subscribe((value) => {
				this._saveTranslationValues();
				this._initTranslationValues();

				this.languageCode = value;

				this._initFormDisplayProducts();
				this._setValue();
			});
	}

@@ -162,29 +212,22 @@ export class BasicInfoFormComponent implements OnInit, OnDestroy {
			activeFrom: new Date(),
			activeTo: null,
			product: null,
			active: true,
			purchasesCount: 0,
		};
	}

	private _setDefaultLocaleValue() {
		this.languageCode = 'en-US';
	}

	private _loadData() {
		if (this._promotion) {
			this.setValue();
		}
		this.languageCode = this.language || 'en-US';
	}

	private _getLocaleMember(
		promotionMember: ILocaleMember[]
	): String | boolean {
		let resultLocale;
		promotionMember: ILocaleMember[],
		languageCode: string
	): ILocaleMember | boolean {
		let resultLocale: ILocaleMember;

		if (promotionMember) {
			resultLocale = promotionMember.find((t) => {
				return t.locale === this.languageCode;
				return t.locale === languageCode;
			});
		}

+23 −23
Original line number Diff line number Diff line
@@ -2,34 +2,29 @@
	<ion-row>
		<ion-col>
			<ion-item>
				<ion-label>Language</ion-label>
				<ion-select formControlName="locale" okText="Okay">
					<ion-select-option value="en-US">{{
						'ENGLISH' | translate
					}}</ion-select-option>
					<ion-select-option value="he-IL">{{
						'HEBREW' | translate
					}}</ion-select-option>
					<ion-select-option value="ru-RU">{{
						'RUSSIAN' | translate
					}}</ion-select-option>
					<ion-select-option value="bg-BG">{{
						'BULGARIAN' | translate
					}}</ion-select-option>
					<ion-select-option value="es-ES">{{
						'SPANISH' | translate
					}}</ion-select-option>
				</ion-select>
				<ion-label class="labels" position="floating">{{
					'CARRIERS_VIEW.PROMOTIONS.PURCHASES_COUNT' | translate
				}}</ion-label>
				<ion-input
					type="number"
					formControlName="purchasesCount"
					[placeholder]="
						'CARRIERS_VIEW.PROMOTIONS.PURCHASES_COUNT' | translate
					"
				></ion-input>
			</ion-item>
		</ion-col>
	</ion-row>
	<ion-row>
		<ion-col text-center>
			<ion-item>
				<ion-label position="floating">{{
					'CARRIERS_VIEW.PROMOTIONS.DESCRIPTION' | translate
			<ion-item class="">
				<ion-label class="labels" position="fixed">{{
					'CARRIERS_VIEW.PROMOTIONS.IS_ACTIVE' | translate
				}}</ion-label>
				<ion-textarea formControlName="description"> </ion-textarea>
				<ion-checkbox
					formControlName="active"
					color="primary"
				></ion-checkbox>
			</ion-item>
		</ion-col>
	</ion-row>
@@ -42,7 +37,12 @@
	<ion-row *ngIf="image">
		<ion-col text-center>
			<ion-thumbnail>
				<ion-img [src]="image.value" #imagePreview></ion-img>
				<ion-img
					*ngIf="image && image.value"
					[src]="image.value"
					#imagePreview
					[alt]="'Invalid image'"
				></ion-img>
			</ion-thumbnail>
		</ion-col>
	</ion-row>
+43 −7
Original line number Diff line number Diff line
import { Component, Input, ElementRef, ViewChild } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import { Component, Input, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import {
	IPromotion,
	IPromotionCreateObject,
} from '@modules/server.common/interfaces/IPromotion';

@Component({
	selector: 'details-info-form',
	styleUrls: ['./details-info-form.component.scss'],
	templateUrl: 'details-info-form.component.html',
})
export class DetailsInfoFormComponent {
export class DetailsInfoFormComponent implements OnInit {
	@Input()
	readonly form: FormGroup;

	@Input()
	promotionData: IPromotion;

	promotionDetails: Partial<IPromotion>;

	constructor() {}

	ngOnInit(): void {
		this.promotionDetails =
			this.promotionData || this._initPromotionDetails();

		this.setValue();
	}

	get image() {
		return this.form.get('image');
	}

	static buildForm(formBuilder: FormBuilder): FormGroup {
		return formBuilder.group({
			description: [''],
			image: [null],
			locale: ['en-US'],
			image: [''],
			active: [true],
			purchasesCount: [0, Validators.min(0)],
		});
	}

	getValue() {
		return this.form.getRawValue();
		return this.form.value as IPromotionCreateObject;
	}

	setValue() {
		if (!this.promotionDetails) return;

		const promotionFormValue = {
			image: this.promotionDetails.image || '',
			active: this.promotionDetails.active || true,
			purchasesCount: this.promotionDetails.purchasesCount || 0,
		};

		this.form.patchValue(promotionFormValue);
	}

	private _initPromotionDetails() {
		return {
			image: null,
			active: true,
			purchasesCount: 0,
		};
	}
}
+11 −24
Original line number Diff line number Diff line
import {
	OnInit,
	OnDestroy,
	Component,
	ViewChild,
@@ -21,7 +20,7 @@ import { Subject } from 'rxjs';
	templateUrl: 'promotion-mutation.html',
	styleUrls: ['./promotion-mutation.scss'],
})
export class PromotionMutation implements OnInit, OnDestroy {
export class PromotionMutation implements OnDestroy {
	@Input()
	promotion: IPromotion;

@@ -56,43 +55,31 @@ export class PromotionMutation implements OnInit, OnDestroy {
		private readonly promotionService: PromotionService
	) {}

	ngOnInit(): void {}

	ngOnDestroy(): void {
		this._ngDestroy$.next();
		this._ngDestroy$.unsubscribe();
	}

	savePromotion() {
		let updatePromotionData = this.basicInfoForm.getValue();
	}
	savePromotion() {}

	createPromotion() {
		// const promotionCreateInput = {
		// 	...this.basicInfoForm.getValue(),
		// 	...this.detailsInfoForm.getValue(),
		// };

		let promotionCreateInput = {
			title: [],
			description: [],
			active: true,
			activeFrom: null,
			activeTo: null,
			purchasesCount: 12,
			image: null,
			product: null,
		const promotionCreateInput = {
			...this.basicInfoForm.getValue(),
			...this.detailsInfoForm.getValue(),
		};

		// delete promotionCreateInput.product;
		if (!this.form.valid) {
			this.presentToast('Please fill in valid data.');
			return;
		}

		debugger;

		this.promotionService
			.create(promotionCreateInput)
			.pipe(first())
			.subscribe(
				(data) => {
					//tstodo
					console.log(data);
					this.presentToast('Successfully created promotion!');
				},
				(err) => {
Loading