diff --git a/src/app/app.component.scss b/src/app/app.component.scss index d990e4dd..e8f85a9d 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -3,13 +3,15 @@ min-height: 100vh; display: block; .main-body { - margin-top: 50px; + @media screen and (min-width: 768px) { + margin-top: 50px; + } } } .issearchopen :host /deep/ .main-body { - @media screen and(min-width: 320px) and(max-width: 768px) { - margin-top: 48px; + @media screen and (min-width: 320px) and(max-width: 768px) { + margin-top: 45px; } } diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 8637ec8d..315f6982 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -3,10 +3,9 @@ import { LayoutState } from './layout/reducers/layout.state'; import { getlayoutStateJS } from './layout/reducers/layout.selector'; import { environment } from './../environments/environment'; import { filter } from 'rxjs/operators'; -import { getAuthStatus } from './auth/reducers/selectors'; import { AppState } from './interfaces'; import { Store } from '@ngrx/store'; -import { Subscription, Observable } from 'rxjs'; +import { Observable } from 'rxjs'; import { CheckoutService } from './core/services/checkout.service'; import { Component, OnInit, OnDestroy, Inject, PLATFORM_ID } from '@angular/core'; import { Router, NavigationEnd } from '@angular/router'; @@ -19,7 +18,6 @@ import { isPlatformBrowser } from '../../node_modules/@angular/common'; styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit, OnDestroy { - orderSub$: Subscription; currentUrl: string; currentStep: string; checkoutUrls = ['/checkout/cart', '/checkout/address', '/checkout/payment']; @@ -28,7 +26,6 @@ export class AppComponent implements OnInit, OnDestroy { constructor( private router: Router, - private checkoutService: CheckoutService, private store: Store, private metaTitle: Title, private meta: Meta, @@ -54,10 +51,6 @@ export class AppComponent implements OnInit, OnDestroy { } ngOnInit() { - this.store.select(getAuthStatus).subscribe(() => { - this.orderSub$ = this.checkoutService.fetchCurrentOrder().subscribe(); - }); - this.layoutState$ = this.store.select(getlayoutStateJS); this.addFaviconIcon(); @@ -86,7 +79,6 @@ export class AppComponent implements OnInit, OnDestroy { } ngOnDestroy() { - this.orderSub$.unsubscribe(); } private addMetaInfo() { diff --git a/src/app/auth/components/login/login.component.ts b/src/app/auth/components/login/login.component.ts index 88a418ed..ca017502 100644 --- a/src/app/auth/components/login/login.component.ts +++ b/src/app/auth/components/login/login.component.ts @@ -45,13 +45,18 @@ export class LoginComponent implements OnInit, OnDestroy { if (this.signInForm.valid) { this.loginSubs = this.authService - .login(values).pipe( - tap(_ => _, (user) => { - const errors = user.error.error || 'Something went wrong'; - keys.forEach(val => { - this.pushErrorFor(val, errors); - }); - })).subscribe(); + .login(values) + .pipe( + tap( + _ => _, + (user) => { + const errors = user.error.error || 'Something went wrong'; + keys.forEach(val => { + this.pushErrorFor(val, errors); + }); + } + ) + ).subscribe(); } else { keys.forEach(val => { const ctrl = this.signInForm.controls[val]; diff --git a/src/app/auth/components/sign-up/sign-up.component.html b/src/app/auth/components/sign-up/sign-up.component.html index 35df9205..085f5381 100644 --- a/src/app/auth/components/sign-up/sign-up.component.html +++ b/src/app/auth/components/sign-up/sign-up.component.html @@ -27,7 +27,7 @@

Signup to {{title}}

autocomplete="off">
! -

{{signUpForm.get('email').errors['msg'] || 'Please enter a valid email id'}}

+

{{signUpForm.get('email').errors.msg || 'Please enter a valid email id'}}

@@ -36,7 +36,7 @@

Signup to {{title}}

placeholder="Choose Password" autocomplete="off">
! -

{{signUpForm.get('password').errors['msg'] || 'Password must be at least 6 characters'}}

+

{{signUpForm.get('password').errors.msg || 'Password must be at least 6 characters'}}

@@ -53,7 +53,7 @@

Signup to {{title}}

! -

{{signUpForm.get('mobile').errors['msg'] || 'Please enter a valid mobile number (10 digits)'}}

+

{{signUpForm.get('mobile').errors.msg || 'Please enter a valid mobile number (10 digits)'}}

@@ -68,7 +68,7 @@

Signup to {{title}}

! -

{{signUpForm.get('gender').errors['msg'] || 'Please select your gender'}}

+

{{signUpForm.get('gender').errors.msg || 'Please select your gender'}}

diff --git a/src/app/auth/components/sign-up/sign-up.component.ts b/src/app/auth/components/sign-up/sign-up.component.ts index 0a599852..8016c445 100644 --- a/src/app/auth/components/sign-up/sign-up.component.ts +++ b/src/app/auth/components/sign-up/sign-up.component.ts @@ -37,6 +37,7 @@ export class SignUpComponent implements OnInit, OnDestroy { } onSubmit() { + debugger const values = this.signUpForm.value; const keys = Object.keys(values); this.formSubmit = true; @@ -106,9 +107,9 @@ export class SignUpComponent implements OnInit, OnDestroy { const password = group.controls[passwordKey]; const confirmPassword = group.controls[confirmPasswordKey]; - return { - mismatchedPasswords: password.value !== confirmPassword.value - }; + if (password.value !== confirmPassword.value) { + return { mismatchedPasswords: true } + } } } diff --git a/src/app/auth/components/update-password/update-password.component.ts b/src/app/auth/components/update-password/update-password.component.ts index 9174989b..d4c14f11 100644 --- a/src/app/auth/components/update-password/update-password.component.ts +++ b/src/app/auth/components/update-password/update-password.component.ts @@ -88,9 +88,9 @@ export class UpdatePasswordComponent implements OnInit { const password = group.controls[passwordKey]; const confirmPassword = group.controls[confirmPasswordKey]; - return { - mismatchedPasswords: password.value !== confirmPassword.value - }; + if (password.value !== confirmPassword.value) { + return { mismatchedPasswords: true } + } } } diff --git a/src/app/auth/effects/auth.effects.ts b/src/app/auth/effects/auth.effects.ts index 7e24f776..8c6c7209 100644 --- a/src/app/auth/effects/auth.effects.ts +++ b/src/app/auth/effects/auth.effects.ts @@ -1,37 +1,56 @@ +import { CheckoutActions } from './../../checkout/actions/checkout.actions'; import { Injectable } from '@angular/core'; -import { filter, switchMap, map } from 'rxjs/operators'; -import { Observable } from 'rxjs'; +import { switchMap, map } from 'rxjs/operators'; +import { Observable} from 'rxjs'; import { Actions, Effect } from '@ngrx/effects'; import { Action } from '@ngrx/store'; import { User } from './../../core/models/user'; import { AuthService } from '../../core/services/auth.service'; import { AuthActions } from '../actions/auth.actions'; +import { CheckoutService } from '../../core/services/checkout.service'; +import { Order } from '../../core/models/order'; @Injectable() export class AuthenticationEffects { - constructor( - private actions$: Actions, - private authService: AuthService, - private authActions: AuthActions - ) {} - // tslint:disable-next-line:member-ordering @Effect() Authorized$: Observable = this.actions$ .ofType(AuthActions.AUTHORIZE) .pipe( - switchMap(() => this.authService.authorized()), - filter(data => data.status !== 'unauthorized'), - map(() => this.authActions.loginSuccess()) + switchMap(() => { + return this.authService.authorized(); + }), + switchMap((data) => this.checkoutService.fetchCurrentOrder().pipe(map(() => data))), + map(data => { + if (data.status === 'unauthorized') { + return this.authActions.noOp(); + } else { + return this.authActions.loginSuccess(); + } + }) + ); + + @Effect() + AfterLoginSuccess$: Observable = this.actions$ + .ofType(AuthActions.LOGIN_SUCCESS) + .pipe( + switchMap(() => this.checkoutService.fetchCurrentOrder()), + map(_ => this.authActions.noOp()) + ); + + @Effect() + AfterLogoutSuccess$: Observable = this.actions$ + .ofType(AuthActions.LOGOUT_SUCCESS) + .pipe( + map(_ => this.checkoutActions.orderCompleteSuccess()) ); - // tslint:disable-next-line:member-ordering @Effect() OAuthLogin: Observable = this.actions$ .ofType(AuthActions.O_AUTH_LOGIN) .pipe( - switchMap(action => { + switchMap(action => { return this.authService.socialLogin(action.payload); }), map(data => { @@ -42,4 +61,12 @@ export class AuthenticationEffects { } }) ); + + constructor( + private actions$: Actions, + private checkoutActions: CheckoutActions, + private authService: AuthService, + private authActions: AuthActions, + private checkoutService: CheckoutService + ) { } } diff --git a/src/app/checkout/address/add-address/add-address.component.html b/src/app/checkout/address/add-address/add-address.component.html index 647a1b58..e4532d12 100644 --- a/src/app/checkout/address/add-address/add-address.component.html +++ b/src/app/checkout/address/add-address/add-address.component.html @@ -10,8 +10,6 @@
- -
- \ No newline at end of file + diff --git a/src/app/checkout/address/delivery-options/delivery-options.component.ts b/src/app/checkout/address/delivery-options/delivery-options.component.ts index 41f80f51..455ecf1a 100644 --- a/src/app/checkout/address/delivery-options/delivery-options.component.ts +++ b/src/app/checkout/address/delivery-options/delivery-options.component.ts @@ -33,7 +33,7 @@ export class DeliveryOptionsComponent implements OnInit, OnDestroy { ngOnInit() { this.orderSub$ = this.checkoutService.fetchCurrentOrder().subscribe(); } - + ngOnDestroy() { this.orderSub$.unsubscribe(); } diff --git a/src/app/checkout/address/services/address.service.ts b/src/app/checkout/address/services/address.service.ts index abb7b92a..fbf79cb7 100644 --- a/src/app/checkout/address/services/address.service.ts +++ b/src/app/checkout/address/services/address.service.ts @@ -1,3 +1,4 @@ +import { CheckoutService } from './../../../core/services/checkout.service'; import { ToastrService } from 'ngx-toastr'; import { map, tap } from 'rxjs/operators'; import { HttpClient } from '@angular/common/http'; @@ -11,7 +12,8 @@ export class AddressService { constructor( private fb: FormBuilder, private http: HttpClient, - private toastrService: ToastrService + private toastrService: ToastrService, + private checkoutService: CheckoutService ) { } initAddressForm() { @@ -70,6 +72,7 @@ export class AddressService { + `&address[zipcode]=${updatedAddress.zipcode}` + `&address[state_id]=${updatedAddress.state_id}` + `&address[country_id]=${updatedAddress.country_id}` + + `&order_token=${this.checkoutService.getOrderToken()}` return this.http.put(url, {}) .pipe( tap( diff --git a/src/app/checkout/cart/components/line-item-list/line-item/line-item.component.ts b/src/app/checkout/cart/components/line-item-list/line-item/line-item.component.ts index bf21fdae..bf5dcfeb 100644 --- a/src/app/checkout/cart/components/line-item-list/line-item/line-item.component.ts +++ b/src/app/checkout/cart/components/line-item-list/line-item/line-item.component.ts @@ -5,6 +5,7 @@ import { CheckoutService } from './../../../../../core/services/checkout.service import { CheckoutActions } from './../../../../actions/checkout.actions'; import { AppState } from './../../../../../interfaces'; import { LineItem } from './../../../../../core/models/line_item'; +import { ToastrService } from 'ngx-toastr'; @Component({ selector: 'app-line-item', @@ -24,6 +25,7 @@ export class LineItemComponent implements OnInit { private store: Store, private checkoutService: CheckoutService, private checkoutActions: CheckoutActions, + private toastyService: ToastrService ) { } ngOnInit() { @@ -55,7 +57,14 @@ export class LineItemComponent implements OnInit { } addQuantity() { - this.quantityCount += 1; - this.store.dispatch(this.checkoutActions.addToCart(this.lineItem.variant_id, 1)); + const productInHands = this.lineItem.variant.total_on_hand; + const backOrderable = this.lineItem.variant.is_backorderable; + + if (productInHands >= (this.quantityCount + 1) || backOrderable === true) { + this.quantityCount += 1; + this.store.dispatch(this.checkoutActions.addToCart(this.lineItem.variant_id, 1)); + } else { + this.toastyService.error('Sorry! You can not add more quantity for this product.') + } } } diff --git a/src/app/checkout/order-failed/order-failed.component.ts b/src/app/checkout/order-failed/order-failed.component.ts index 5cdbc136..b872901d 100644 --- a/src/app/checkout/order-failed/order-failed.component.ts +++ b/src/app/checkout/order-failed/order-failed.component.ts @@ -3,7 +3,7 @@ import { AppState } from './../../interfaces'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs/Observable'; import { LayoutState } from './../../layout/reducers/layout.state'; -import { tap } from 'rxjs/operators'; +import { tap, switchMap } from 'rxjs/operators'; import { LineItem } from './../../core/models/line_item'; import { Order } from './../../core/models/order'; import { UserService } from './../../user/services/user.service'; @@ -11,7 +11,7 @@ import { ActivatedRoute, Router, Params } from '@angular/router'; import { Component, OnInit, PLATFORM_ID, Inject, OnDestroy } from '@angular/core'; import { CheckoutService } from '../../core/services/checkout.service'; import { isPlatformBrowser } from '../../../../node_modules/@angular/common'; -import { Subscription } from 'rxjs'; +import { Subscription, of } from 'rxjs'; @Component({ selector: 'app-order-failed', @@ -40,18 +40,19 @@ export class OrderFailedComponent implements OnInit, OnDestroy { this.subscriptionList$.push( this.activatedRouter.queryParams .pipe( - tap(({ orderReferance }) => { - this.subscriptionList$.push( - this.userService + switchMap(params => { + const { reason, orderReferance } = params; + this.errorReason = reason; + if (!orderReferance) { + this.route.navigate(['/']) + return of(params); + } + return this.userService .getOrderDetail(orderReferance) - .subscribe(order => this.orderDetails = order) - ) + .pipe(tap(order => this.orderDetails = order)); }) ) - .subscribe(({ reason, orderReferance }) => { - this.errorReason = reason; - if (!orderReferance) { this.route.navigate(['/']) } - }) + .subscribe() ); } diff --git a/src/app/checkout/order-success/order-success.component.ts b/src/app/checkout/order-success/order-success.component.ts index 91997be2..e05c9b21 100644 --- a/src/app/checkout/order-success/order-success.component.ts +++ b/src/app/checkout/order-success/order-success.component.ts @@ -4,7 +4,7 @@ import { Order } from './../../core/models/order'; import { UserService } from './../../user/services/user.service'; import { ActivatedRoute, Router, Params } from '@angular/router'; import { Component, OnInit, PLATFORM_ID, Inject, OnDestroy } from '@angular/core'; -import { Subscription, Observable, interval } from 'rxjs'; +import { Subscription, Observable, interval, of } from 'rxjs'; import { Store } from '@ngrx/store'; import { AppState } from '../../interfaces'; import { getlayoutStateJS } from '../../layout/reducers/layout.selector'; @@ -36,23 +36,18 @@ export class OrderSuccessComponent implements OnInit, OnDestroy { this.subscriptionList$.push( this.activatedRouter.queryParams .pipe( - tap(({ orderReferance }) => { - interval(200) - .pipe( - switchMap(_ => this.userService.getOrderDetail(orderReferance)), - take(30), - skipWhile(order => order.shipment_state !== 'ready'), - map(order => this.orderDetails = order), - take(1) - ) + switchMap(params => { + const { orderReferance } = params; + if (!orderReferance) { + this.route.navigate(['/']); + return of(params); + } + return this.userService + .getOrderDetail(orderReferance) + .pipe(tap(order => this.orderDetails = order)); }) ) - .subscribe(params => { - this.queryParams = params - if (!this.queryParams.orderReferance) { - this.route.navigate(['/']) - } - }) + .subscribe() ); } diff --git a/src/app/checkout/payment/payment-modes-list/payment-modes-list.component.ts b/src/app/checkout/payment/payment-modes-list/payment-modes-list.component.ts index af85ba09..0ecbde5c 100644 --- a/src/app/checkout/payment/payment-modes-list/payment-modes-list.component.ts +++ b/src/app/checkout/payment/payment-modes-list/payment-modes-list.component.ts @@ -1,17 +1,18 @@ - +import { Component, OnInit, Input, PLATFORM_ID, Inject, OnDestroy } from '@angular/core'; import { tap } from 'rxjs/operators'; +import { ToastrService } from 'ngx-toastr'; +import { Subscription } from 'rxjs'; +import { Store } from '@ngrx/store'; +import { Router } from '@angular/router'; + import { getAuthStatus } from './../../../auth/reducers/selectors'; import { CheckoutActions } from './../../actions/checkout.actions'; import { AppState } from './../../../interfaces'; -import { Store } from '@ngrx/store'; -import { Router } from '@angular/router'; import { PaymentMode } from './../../../core/models/payment_mode'; import { PaymentService } from './../services/payment.service'; import { CheckoutService } from './../../../core/services/checkout.service'; -import { Component, OnInit, Input, PLATFORM_ID, Inject } from '@angular/core'; import { Address } from '../../../core/models/address'; import { environment } from '../../../../environments/environment'; -import { ToastrService } from 'ngx-toastr'; import { isPlatformBrowser } from '../../../../../node_modules/@angular/common'; @Component({ @@ -19,14 +20,14 @@ import { isPlatformBrowser } from '../../../../../node_modules/@angular/common'; templateUrl: './payment-modes-list.component.html', styleUrls: ['./payment-modes-list.component.scss'] }) -export class PaymentModesListComponent implements OnInit { +export class PaymentModesListComponent implements OnInit, OnDestroy { @Input() paymentAmount: number; @Input() orderNumber: string; @Input() address: Address; isShippeble: boolean; showDummyCardInfo = environment.config.showDummyCardInfo; - + subscriptionList$: Array = []; paymentModes: PaymentMode[]; selectedMode: PaymentMode = new PaymentMode; isAuthenticated: boolean; @@ -42,13 +43,14 @@ export class PaymentModesListComponent implements OnInit { private store: Store, private checkoutActions: CheckoutActions, private toastyService: ToastrService, - @Inject(PLATFORM_ID) private platformId: Object) { - this.store.select(getAuthStatus).subscribe((auth) => { - this.isAuthenticated = auth; - }); - } + @Inject(PLATFORM_ID) private platformId: Object) { } ngOnInit() { + this.subscriptionList$.push( + this.store.select(getAuthStatus).subscribe((auth) => { + this.isAuthenticated = auth; + }) + ); this.fetchAllPayments(); } @@ -57,56 +59,63 @@ export class PaymentModesListComponent implements OnInit { } private fetchAllPayments() { - this.checkoutService.availablePaymentMethods() - .subscribe((payment) => { - this.paymentModes = payment.payment_methods; - this.selectedMode = this.paymentService.getDefaultSelectedMode(this.paymentModes); - }); + this.subscriptionList$.push( + this.checkoutService.availablePaymentMethods() + .subscribe((payment) => { + this.paymentModes = payment.payment_methods; + this.selectedMode = this.paymentService.getDefaultSelectedMode(this.paymentModes); + }) + ); } makePaymentCod() { const paymentModeId = this.selectedMode.id; const shipping_pincode = (this.address.zipcode) - this.checkoutService.shipmentAvailability(+shipping_pincode) - .subscribe((res: any) => { - this.isShippeble = res.available - if (this.isShippeble && this.paymentAmount >= this.freeShippingAmount) { - this.checkoutService.createNewPayment(paymentModeId, this.paymentAmount).pipe( - tap(() => { - this.store.dispatch(this.checkoutActions.orderCompleteSuccess()); - this.redirectToNewPage(); - this.checkoutService.createEmptyOrder() - .subscribe(); - })) - .subscribe(); - } else { - if (this.paymentAmount < this.freeShippingAmount) { - // tslint:disable-next-line:max-line-length - this.toastyService.error(`${this.selectedMode.name} is not available for Order amount less than ${this.currency} ${this.freeShippingAmount}.`, 'Order Amount'); - } else if (!this.isShippeble) { - this.toastyService.error(`${this.selectedMode.name} is not available for pincode ${shipping_pincode}.`, 'Pincode'); + this.subscriptionList$.push( + this.checkoutService.shipmentAvailability(+shipping_pincode) + .subscribe((res: any) => { + this.isShippeble = res.available + if (this.isShippeble && this.paymentAmount >= this.freeShippingAmount) { + this.subscriptionList$.push( + this.checkoutService.createNewPayment(paymentModeId, this.paymentAmount).pipe( + tap(() => { + this.store.dispatch(this.checkoutActions.orderCompleteSuccess()); + this.redirectToNewPage(); + this.checkoutService.removeLocalOrder(); + })) + .subscribe() + ); + } else { + if (this.paymentAmount < this.freeShippingAmount) { + // tslint:disable-next-line:max-line-length + this.toastyService.error(`${this.selectedMode.name} is not available for Order amount less than ${this.currency} ${this.freeShippingAmount}.`, 'Order Amount'); + } else if (!this.isShippeble) { + this.toastyService.error(`${this.selectedMode.name} is not available for pincode ${shipping_pincode}.`, 'Pincode'); + } } - } - }); + }) + ); } makePaymentPayubiz() { - this.checkoutService.makePayment(this.paymentAmount, this.address, this.orderNumber) - .subscribe((response: any) => { - response = response - this.checkoutService.createNewPayment(this.selectedMode.id, this.paymentAmount).pipe( - tap(() => { - this.store.dispatch(this.checkoutActions.orderCompleteSuccess()); - this.checkoutService.createEmptyOrder() - .subscribe(); - }) - ) - .subscribe((res) => { - if (isPlatformBrowser(this.platformId)) { - window.open(response.url, '_self'); - } - }); - }) + this.subscriptionList$.push( + this.checkoutService.makePayment(this.paymentAmount, this.address, this.orderNumber) + .subscribe((response: any) => { + this.subscriptionList$.push( + this.checkoutService.createNewPayment(this.selectedMode.id, this.paymentAmount).pipe( + tap(() => { + this.store.dispatch(this.checkoutActions.orderCompleteSuccess()); + this.checkoutService.removeLocalOrder(); + }) + ) + .subscribe(_ => { + if (isPlatformBrowser(this.platformId)) { + window.open(response.url, '_self'); + } + }) + ); + }) + ); } private redirectToNewPage() { @@ -117,4 +126,8 @@ export class PaymentModesListComponent implements OnInit { this.router.navigate(['/']); } } + + ngOnDestroy() { + this.subscriptionList$.map(sub$ => sub$.unsubscribe()); + } } diff --git a/src/app/checkout/payment/payment.component.ts b/src/app/checkout/payment/payment.component.ts index c0ad4885..18c61dd0 100644 --- a/src/app/checkout/payment/payment.component.ts +++ b/src/app/checkout/payment/payment.component.ts @@ -1,5 +1,7 @@ import { Address } from './../../core/models/address'; -import { getTotalCartValue, getOrderNumber, getTotalCartItems, getShipAddress, getShipTotal, getItemTotal, getAdjustmentTotal } from './../reducers/selectors'; +import { + getTotalCartValue, getOrderNumber, getTotalCartItems, getShipAddress, getShipTotal, getItemTotal, getAdjustmentTotal +} from './../reducers/selectors'; import { AppState } from './../../interfaces'; import { Store } from '@ngrx/store'; import { Observable, Subscription } from 'rxjs'; diff --git a/src/app/checkout/reducers/selectors.ts b/src/app/checkout/reducers/selectors.ts index 53ce894f..e4d596b7 100644 --- a/src/app/checkout/reducers/selectors.ts +++ b/src/app/checkout/reducers/selectors.ts @@ -28,11 +28,11 @@ export function fetchTotalCartValue(state: CheckoutState) { } export function fetchShipAddress(state: CheckoutState) { - return state.shipAddress ? state.shipAddress.toJS() : state.shipAddress.toJS(); + return state.shipAddress ? state.shipAddress.toJS() : state.shipAddress; } export function fetchBillAddress(state: CheckoutState) { - return state.billAddress ? state.billAddress.toJS() : state.billAddress.toJS(); + return state.billAddress ? state.billAddress.toJS() : state.billAddress; } export function fetchOrderState(state: CheckoutState) { diff --git a/src/app/core/services/auth.service.ts b/src/app/core/services/auth.service.ts index 3fdb9122..09873abb 100644 --- a/src/app/core/services/auth.service.ts +++ b/src/app/core/services/auth.service.ts @@ -1,3 +1,4 @@ +import { CheckoutService } from './checkout.service'; import { of as observableOf, Observable, throwError, of } from 'rxjs'; import { catchError, map, tap } from 'rxjs/operators'; import { Router } from '@angular/router'; @@ -28,6 +29,7 @@ export class AuthService { private store: Store, private oAuthService: OauthService, private toastrService: ToastrService, + private checkoutService: CheckoutService, private router: Router, @Inject(PLATFORM_ID) private platformId: Object ) { } @@ -155,7 +157,7 @@ export class AuthService { map((res: Response) => { // Setting token after login if (isPlatformBrowser(this.platformId)) { - localStorage.removeItem('user'); + localStorage.clear(); } this.store.dispatch(this.actions.logoutSuccess()); return res; @@ -184,7 +186,8 @@ export class AuthService { client: user.client || [], uid: user.uid || [], 'Auth-Token': user.spree_api_key || [], - 'ng-api': 'true' + 'ng-api': 'true', + 'Guest-Order-Token': this.checkoutService.getOrderToken() || [] }); } diff --git a/src/app/core/services/checkout.service.ts b/src/app/core/services/checkout.service.ts index 198decb2..2e3de08e 100644 --- a/src/app/core/services/checkout.service.ts +++ b/src/app/core/services/checkout.service.ts @@ -1,6 +1,5 @@ -import { map, tap } from 'rxjs/operators'; -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { getOrderNumber } from './../../checkout/reducers/selectors'; +import { map, tap, switchMap } from 'rxjs/operators'; +import { HttpClient } from '@angular/common/http'; import { CheckoutActions } from './../../checkout/actions/checkout.actions'; import { Injectable, Inject, PLATFORM_ID } from '@angular/core'; import { LineItem } from './../models/line_item'; @@ -11,18 +10,18 @@ import { ToastrService } from 'ngx-toastr'; import * as CryptoJS from 'crypto-js'; import { environment } from '../../../environments/environment'; import { isPlatformBrowser } from '@angular/common'; -import { Observable } from 'rxjs'; +import { Observable, of } from 'rxjs'; @Injectable() export class CheckoutService { - private orderNumber: number; /** - * Creates an instance of CheckoutService. - * @param {HttpService} http + *Creates an instance of CheckoutService. + * @param {HttpClient} http * @param {CheckoutActions} actions * @param {Store} store - * + * @param {ToastrService} toastyService + * @param {*} platformId * @memberof CheckoutService */ constructor( @@ -31,8 +30,6 @@ export class CheckoutService { private store: Store, private toastyService: ToastrService, @Inject(PLATFORM_ID) private platformId: Object) { - this.store.select(getOrderNumber) - .subscribe(number => (this.orderNumber = number)); } /** @@ -43,42 +40,66 @@ export class CheckoutService { * * @memberof CheckoutService */ - createNewLineItem(variant_id: number, quantity: number) { + createNewLineItem(variant_id: number, quantity: number): Observable { + if (!this.getOrderToken()) { + const order_params = { order: { line_items: { 0: { variant_id: variant_id, quantity: quantity } } } }; + return this.createNewOrder(order_params).pipe(map(order => order.line_items[0])); + } + const params = { line_item: { variant_id: variant_id, quantity: quantity } - }, - url = `api/v1/orders/${this.orderNumber}/line_items?order_token=${this.getOrderToken()}`; - + }; + const url = `api/v1/orders/${this.orderNumber()}/line_items?order_token=${this.getOrderToken()}`; return this.http.post(url, params).pipe( tap( lineItem => { this.toastyService.success('Success!', 'Cart updated!'); return lineItem; }, + _ => { + localStorage.removeItem('order'); + this.createNewLineItem(variant_id, quantity).subscribe(); + } + ) + ); + } + + createNewOrder(orderParams): Observable { + const new_order_url = `api/v1/orders`; + return this.http.post(new_order_url, orderParams).pipe( + tap( + order => { + this.toastyService.success('Success!', 'Cart updated!'); + this.setOrderTokenInLocalStorage({ order_token: order.token, order_number: order.number }); + this.store.dispatch(this.actions.fetchCurrentOrderSuccess(order)); + }, _ => this.toastyService.error('Something went wrong!', 'Failed') ) ); } - /** - * - * - * @returns - * - * @memberof CheckoutService - */ fetchCurrentOrder() { return this.http.get('api/v1/orders/current').pipe( - map(order => { + switchMap(order => { if (order) { - const token = order.token; - this.setOrderTokenInLocalStorage({ order_token: token }); - return this.store.dispatch( - this.actions.fetchCurrentOrderSuccess(order) - ); + return of(order); } else { - this.createEmptyOrder().subscribe(); + if (this.getOrderToken()) { + const s_order = JSON.parse(localStorage.getItem('order')); + return this.getOrder(s_order.order_number); + } else { + return of(null); + } } + }), + map(order => { + if (!order) { + localStorage.removeItem('order'); + return; + } + const { token, number } = order; + this.setOrderTokenInLocalStorage({ order_token: token, order_number: number }); + return this.store.dispatch(this.actions.fetchCurrentOrderSuccess(order)); }) ); } @@ -91,35 +112,18 @@ export class CheckoutService { * @memberof CheckoutService */ getOrder(orderNumber: string) { - const url = `api/v1/orders/${orderNumber}.json`; + const url = `api/v1/orders/${orderNumber}?order_token=${this.getOrderToken()}`; return this.http.get(url); } - /** - * - * - * @returns - * - * @memberof CheckoutService - */ - createEmptyOrder() { - const headers = new HttpHeaders().set('Content-Type', 'text/plain'); + removeLocalOrder() { + if (isPlatformBrowser(this.platformId)) { + localStorage.removeItem('order'); + } + } - return this.http - .post('api/v1/orders.json', null, { headers: headers }) - .pipe( - map(order => { - this.setOrderTokenInLocalStorage({ order_token: order.token }); - return this.store.dispatch( - this.actions.fetchCurrentOrderSuccess(order) - ); - }), - tap( - _ => _, - _ => - this.toastyService.error('Unable to create empty order', 'ERROR!!') - ) - ); + createEmptyOrder() { + return this.http.post(`api/v1/orders`, { order: {} }); } /** @@ -131,7 +135,7 @@ export class CheckoutService { * @memberof CheckoutService */ deleteLineItem(lineItem: LineItem) { - const url = `api/v1/orders/${this.orderNumber}/line_items/${ + const url = `api/v1/orders/${this.orderNumber()}/line_items/${ lineItem.id }?order_token=${this.getOrderToken()}`; return this.http.delete(url).pipe(map(_ => lineItem)); @@ -146,7 +150,7 @@ export class CheckoutService { */ changeOrderState() { const url = `api/v1/checkouts/${ - this.orderNumber + this.orderNumber() }/next.json?order_token=${this.getOrderToken()}`; return this.http .put(url, {}) @@ -167,7 +171,7 @@ export class CheckoutService { */ updateOrder(params: any) { const url = `api/v1/checkouts/${ - this.orderNumber + this.orderNumber() }.json?order_token=${this.getOrderToken()}`; return this.http .put(url, params) @@ -187,7 +191,7 @@ export class CheckoutService { */ availablePaymentMethods() { const url = `api/v1/orders/${ - this.orderNumber + this.orderNumber() }/payments/new?order_token=${this.getOrderToken()}`; return this.http.get(url); } @@ -204,7 +208,7 @@ export class CheckoutService { return this.http .post( `api/v1/orders/${ - this.orderNumber + this.orderNumber() }/payments?order_token=${this.getOrderToken()}`, { payment: { @@ -263,15 +267,19 @@ export class CheckoutService { * * @memberof CheckoutService */ - private getOrderToken() { + getOrderToken() { + const order = isPlatformBrowser(this.platformId) ? JSON.parse(localStorage.getItem('order')) : {}; + return order ? order.order_token : null; + } + + orderNumber() { const order = isPlatformBrowser(this.platformId) ? JSON.parse(localStorage.getItem('order')) : {}; - const token = order.order_token; - return token; + return order ? order.order_number : null; } - shipmentAvailability(pincode: number): Observable<{available: boolean}> { + shipmentAvailability(pincode: number): Observable<{ available: boolean }> { return this.http - .post<{available: boolean}>(`address/shipment_availability`, { pincode: pincode }); + .post<{ available: boolean }>(`address/shipment_availability`, { pincode: pincode }); } /** * @@ -284,7 +292,7 @@ export class CheckoutService { private setOrderTokenInLocalStorage(token: any): void { const jsonData = JSON.stringify(token); if (isPlatformBrowser(this.platformId)) { - localStorage.setItem('order', jsonData) ; + localStorage.setItem('order', jsonData); } } } diff --git a/src/app/core/services/product.service.ts b/src/app/core/services/product.service.ts index 7b8f3671..1735dcfa 100644 --- a/src/app/core/services/product.service.ts +++ b/src/app/core/services/product.service.ts @@ -1,15 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { map } from 'rxjs/operators'; +import { Observable } from 'rxjs'; +import { Injectable } from '@angular/core'; + import { JsonApiParserService } from './json-api-parser.service'; import { CJsonApi } from './../models/jsonapi'; import { ToastrService } from 'ngx-toastr'; import { Taxonomy } from './../models/taxonomy'; -import { HttpClient } from '@angular/common/http'; -import { Injectable } from '@angular/core'; import { Product } from '../models/product'; -import { map } from 'rxjs/operators'; -import { Observable } from 'rxjs'; @Injectable() export class ProductService { + success: any; + error: any; + /** * Creates an instance of ProductService. * @param {HttpService} http @@ -21,10 +25,6 @@ export class ProductService { private toastrService: ToastrService, private apiParser: JsonApiParserService, ) { } - // tslint:disable-next-line:member-ordering - success: any; - // tslint:disable-next-line:member-ordering - error: any; /** * * @@ -49,22 +49,22 @@ export class ProductService { getProductReviews(products): Observable { return this.http.get(`products/${products}/reviews`); } + /** * * - * @returns {Array} - * + * @returns {Observable>} * @memberof ProductService */ - getTaxonomies(): any { + getTaxonomies(): Observable> { return this.http.get>(`api/v1/taxonomies?set=nested`); } /** * * - * @returns {Array} - * + * @param {number} pageNumber + * @returns {Observable>} * @memberof ProductService */ getProducts(pageNumber: number): Observable> { @@ -79,14 +79,34 @@ export class ProductService { ); } + /** + * + * + * @param {number} id + * @returns {Observable<{}>} + * @memberof ProductService + */ markAsFavorite(id: number): Observable<{}> { return this.http.post<{}>(`favorite_products`, { id: id }); } + /** + * + * + * @param {number} id + * @returns {Observable<{}>} + * @memberof ProductService + */ removeFromFavorite(id: number): Observable<{}> { return this.http.delete<{}>(`favorite_products/${id}`); } + /** + * + * + * @returns {Observable>} + * @memberof ProductService + */ getFavoriteProducts(): Observable> { return this.http .get<{ data: CJsonApi[] }>( @@ -99,6 +119,12 @@ export class ProductService { ); } + /** + * + * + * @returns {Observable>} + * @memberof ProductService + */ getUserFavoriteProducts(): Observable> { return this.http .get<{ data: CJsonApi[] }>( @@ -111,8 +137,14 @@ export class ProductService { ); } - // tslint:disable-next-line:max-line-length - getProductsByTaxon(id: string): Observable { + /** + * + * + * @param {string} id + * @returns {Observable<{pagination: Object, products: Array}>} + * @memberof ProductService + */ + getProductsByTaxon(id: string): Observable<{ pagination: Object, products: Array }> { return this.http .get<{ data: CJsonApi[]; pagination: Object }>( `api/v1/taxons/products?${id}&per_page=20&data_set=small` @@ -127,6 +159,13 @@ export class ProductService { ); } + /** + * + * + * @param {string} id + * @returns {Observable>} + * @memberof ProductService + */ getProductsByTaxonNP(id: string): Observable> { return this.http .get<{ data: CJsonApi[] }>( @@ -139,13 +178,27 @@ export class ProductService { ); } + /** + * + * + * @param {string} name + * @returns {Observable>} + * @memberof ProductService + */ getTaxonByName(name: string): Observable> { return this.http.get>( `api/v1/taxonomies?q[name_cont]=${name}&set=nested&per_page=2` ); } - getproductsByKeyword(keyword: string): Observable { + /** + * + * + * @param {string} keyword + * @returns {Observable<{pagination: Object, products: Array}>} + * @memberof ProductService + */ + getproductsByKeyword(keyword: string): Observable<{ pagination: Object, products: Array }> { return this.http .get<{ data: CJsonApi[]; pagination: Object }>( `api/v1/products?${keyword}&per_page=20&data_set=small` @@ -154,23 +207,34 @@ export class ProductService { map(resp => { return { pagination: resp.pagination, - products: this.apiParser.parseArrayofObject(resp.data) as Array< - Product - > + products: this.apiParser.parseArrayofObject(resp.data) as Array }; }) ); } - getChildTaxons( - taxonomyId: string, - taxonId: string - ): Observable> { + /** + * + * + * @param {string} taxonomyId + * @param {string} taxonId + * @returns {Observable>} + * @memberof ProductService + */ + getChildTaxons(taxonomyId: string, taxonId: string): Observable> { return this.http.get>( `/api/v1/taxonomies/${taxonomyId}/taxons/${taxonId}` ); } + /** + * + * + * @param {*} productId + * @param {*} params + * @returns + * @memberof ProductService + */ submitReview(productId: any, params: any) { return this.http.post(`products/${productId}/reviews`, params).pipe( map( @@ -193,7 +257,14 @@ export class ProductService { ); } - getRelatedProducts(productId: any): Observable> { + /** + * + * + * @param {number} productId + * @returns {Observable>} + * @memberof ProductService + */ + getRelatedProducts(productId: number): Observable> { return this.http .get<{ data: CJsonApi[] }>(`api/products/${productId}/relations`) .pipe( diff --git a/src/app/core/services/variant-parser.service.ts b/src/app/core/services/variant-parser.service.ts index 725bf21f..8e8f6d3c 100644 --- a/src/app/core/services/variant-parser.service.ts +++ b/src/app/core/services/variant-parser.service.ts @@ -1,6 +1,4 @@ -import { Effect } from '@ngrx/effects'; import { OptionValue } from './../models/option_value'; -import { element } from 'protractor'; import { Variant } from './../models/variant'; import { OptionType } from './../models/option_type'; import { Injectable } from '@angular/core'; diff --git a/src/app/home/category-page/category-page.component.ts b/src/app/home/category-page/category-page.component.ts index 4e8d35c1..99a55873 100644 --- a/src/app/home/category-page/category-page.component.ts +++ b/src/app/home/category-page/category-page.component.ts @@ -1,3 +1,4 @@ +import { Taxon } from './../../core/models/taxon'; import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; import { environment } from '../../../environments/environment'; import { ActivatedRoute } from '@angular/router'; @@ -7,6 +8,7 @@ import { getTaxonomies } from '../../product/reducers/selectors'; import { Observable, forkJoin, of } from 'rxjs'; import { ProductService } from '../../core/services/product.service'; import { map, switchMap } from 'rxjs/operators'; +import { Product } from '../../core/models/product'; @Component({ selector: 'app-category-page', @@ -16,11 +18,9 @@ import { map, switchMap } from 'rxjs/operators'; }) export class CategoryPageComponent implements OnInit { banners = environment.config.category_banner; - category_banner: any; - categeory_number: any; - id: any - selectedTaxons$: Observable - productList$: Observable + categeory_number: number; + selectedTaxons$: Observable; + productList$: Observable>; selectedCategory: any; constructor(private route: ActivatedRoute, diff --git a/src/app/home/content/content-header/content-header.component.html b/src/app/home/content/content-header/content-header.component.html index d44b02ac..8e8275cb 100644 --- a/src/app/home/content/content-header/content-header.component.html +++ b/src/app/home/content/content-header/content-header.component.html @@ -1,4 +1,4 @@ -
+
@@ -25,7 +25,7 @@

Showing {{paginationInfo.count}} of {{paginationIn

-
+
@@ -50,7 +50,7 @@

Showing {{paginationInfo.count}} of {{paginationIn
  • - +
  • diff --git a/src/app/home/content/content-header/content-header.component.ts b/src/app/home/content/content-header/content-header.component.ts index df2e621d..8551d226 100644 --- a/src/app/home/content/content-header/content-header.component.ts +++ b/src/app/home/content/content-header/content-header.component.ts @@ -1,6 +1,7 @@ import { Router } from '@angular/router'; import { Component, OnInit, Output, EventEmitter, Input, ChangeDetectionStrategy, PLATFORM_ID, Inject } from '@angular/core'; -import { isPlatformBrowser } from '../../../../../node_modules/@angular/common'; +import { LayoutState } from '../../../layout/reducers/layout.state'; + @Component({ selector: 'app-content-header', templateUrl: './content-header.component.html', @@ -11,9 +12,9 @@ export class ContentHeaderComponent implements OnInit { @Output() toggleSize = new EventEmitter(); @Input() paginationInfo; @Input() fillterList; + @Input() layoutState: LayoutState; subselectedItem; childselectedItem; - screenWidth: any; options = [ { name: 'Newest', value: 1 }, @@ -34,14 +35,13 @@ export class ContentHeaderComponent implements OnInit { } selectedOption = 'Relevance'; - isMobile: any; selectedSize = 'COZY'; searchKeyword = ''; selectedEntry; isfilterModalShown; issortModalShown defaultselectedEntry = 'Relevance'; - constructor(private routernomal: Router, @Inject(PLATFORM_ID) private platformId: any) { } + constructor(private routernomal: Router) { } sortModalShow() { this.issortModalShown = true; } sortModalhide() { this.issortModalShown = false; } @@ -61,11 +61,6 @@ export class ContentHeaderComponent implements OnInit { } ngOnInit() { - if (isPlatformBrowser(this.platformId)) { - if (window.screen.width <= 768) { - this.screenWidth = window.screen.width; - } - } } toggleView(view) { diff --git a/src/app/home/content/content.ts b/src/app/home/content/content.ts index 65c6b2d9..8409bec7 100644 --- a/src/app/home/content/content.ts +++ b/src/app/home/content/content.ts @@ -5,20 +5,19 @@ import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core'; selector: 'app-content', template: `
    -
    `, - // styleUrls: ['./content-header.component.scss'] - // }) export class ContentComponent implements OnInit { @Input() productsList; @Input() paginationData; @Input() taxonIds; @Input() fillterList; + @Input() layoutState; toggleLayout = { size: 'COZY' }; constructor() { } diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html index 96df7503..16842fac 100644 --- a/src/app/home/home.component.html +++ b/src/app/home/home.component.html @@ -10,7 +10,7 @@

    Searched Results

    - +
    diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index 3c16718b..8ff5a13b 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -1,3 +1,4 @@ +import { getlayoutStateJS } from './../layout/reducers/layout.selector'; import { SearchActions } from './reducers/search.actions'; import { getSelectedTaxonIds, @@ -17,6 +18,7 @@ import { Component, OnInit, ViewChild, ChangeDetectionStrategy, PLATFORM_ID, Inj import { ModalDirective } from 'ngx-bootstrap/modal'; import { Product } from '../core/models/product'; import { isPlatformBrowser } from '../../../node_modules/@angular/common'; +import { LayoutState } from '../layout/reducers/layout.state'; @Component({ selector: 'app-home', @@ -38,6 +40,7 @@ export class HomeComponent implements OnInit, OnDestroy { isMobile; rootTaxonomyId: any; rootTaxonomyIdSubs$: Subscription; + layoutState$: Observable; @ViewChild('autoShownModal') autoShownModal: ModalDirective; isModalShown = false; @@ -57,6 +60,7 @@ export class HomeComponent implements OnInit, OnDestroy { this.pagination$ = this.store.select(getPaginationData); this.isFilterOn$ = this.store.select(searchFilterStatus); this.rootTaxonomyIdSubs$ = this.store.select(rootTaxonomyId).subscribe(id => this.rootTaxonomyId = id); + this.layoutState$ = this.store.select(getlayoutStateJS); } showModal(): void { diff --git a/src/app/landing/components/lp-banner/lp-banner.component.scss b/src/app/landing/components/lp-banner/lp-banner.component.scss index 50d0d003..eb26473b 100644 --- a/src/app/landing/components/lp-banner/lp-banner.component.scss +++ b/src/app/landing/components/lp-banner/lp-banner.component.scss @@ -8,7 +8,7 @@ } @media (max-width: 768px) { img { - height: 150px; + height: 170px; object-fit: cover; } } diff --git a/src/app/layout/header/header.component.scss b/src/app/layout/header/header.component.scss index f4d8fa07..ef7cb45f 100644 --- a/src/app/layout/header/header.component.scss +++ b/src/app/layout/header/header.component.scss @@ -2,24 +2,26 @@ .navbar { padding: 0px; padding-top: 1rem; - &#main{ - transition: all 500ms; - position: fixed; - width: 100%; - z-index: 100; - } - &:not(#main), - &.page-scroll-header { - box-shadow: 0 8px 6px -8px $gray-900; - z-index: 1; - } - &#sub-header { - transition: all 150ms; - width: 100%; - z-index: 1; - top: 50px; - &.hide-sub-header { - top: 0; + @media screen and (min-width: 768px) { + &#main { + transition: all 500ms; + position: fixed; + width: 100%; + z-index: 100; + } + &:not(#main), + &.page-scroll-header { + box-shadow: 0 8px 6px -8px $gray-900; + z-index: 1; + } + &#sub-header { + transition: all 150ms; + width: 100%; + z-index: 1; + top: 50px; + &.hide-sub-header { + top: 0; + } } } } diff --git a/src/app/user/services/user.service.ts b/src/app/user/services/user.service.ts index 08989b33..6d912b4e 100644 --- a/src/app/user/services/user.service.ts +++ b/src/app/user/services/user.service.ts @@ -73,7 +73,7 @@ export class UserService { } /** - * This function updates the address of the user. + * This function updates the address of the user. * * @param {Address} updatedAddress * @returns {Observable<{status: string}>}