dev #14384 Правка ошибок отображения WPA КофеЛайк: add auth service to store information about user and fix getUserInfo

This commit is contained in:
nikolay 2023-06-23 09:32:20 +04:00
parent e20cd30a54
commit 4e0a41b644
14 changed files with 430 additions and 388 deletions

View File

@ -1 +1,2 @@
<router-outlet></router-outlet>
<p-toast position="top-center"></p-toast>

View File

@ -1,8 +1,8 @@
import { Component, OnInit } from '@angular/core';
import { RouteConfigLoadStart, Router } from '@angular/router';
import { AuthService } from './services/auth.service';
import { CookiesService } from './services/cookies.service';
import { JsonrpcService, RpcService } from './services/jsonrpc.service';
import { lastValueFrom } from 'rxjs';
@Component({
selector: 'app-root',
@ -15,7 +15,8 @@ export class AppComponent implements OnInit {
constructor(
private router: Router,
private cookiesService: CookiesService,
private jsonRpcService: JsonrpcService
private jsonRpcService: JsonrpcService,
private authService: AuthService,
) {
this.router.events.subscribe((x) => {
if (x instanceof RouteConfigLoadStart && x.route.path === '') {
@ -48,6 +49,9 @@ export class AppComponent implements OnInit {
}
ngOnInit(): void {
if (this.authService.authorized) {
this.authService.getUserInfo();
}
this.getAdditionalInfo().subscribe({
next: (value) => {
this.cookiesService.setCookie('presentation-option', value?.data?.interface_id || 'default')

View File

@ -1,93 +1,93 @@
import {OrderStatus, Page, PageCode, lvlPeriod} from "./interface/data";
import { OrderStatus, Page, PageCode, lvlPeriod } from "./interface/data";
export const PageList: Page[] = [
{
code: PageCode.Auth,
name: 'Вход',
resName: 'auth',
onSideBar: false,
},
{
code: PageCode.Orders,
name: 'Заказы',
resName: 'orders',
onSideBar: true,
},
{
code: PageCode.Auth,
name: 'Вход',
resName: 'auth',
onSideBar: false,
},
{
code: PageCode.Orders,
name: 'Заказы',
resName: 'orders',
onSideBar: true,
},
];
export const PageListWithBonus: Page[] = [
{
code: PageCode.Auth,
name: 'Вход',
resName: 'auth',
onSideBar: false,
},
{
code: PageCode.BonusProgram,
name: 'Ваша карта лояльности',
description: '',
resName: 'bonus-program',
onSideBar: true,
},
{
code: PageCode.Orders,
name: 'Ваши чеки',
description: '',
resName: 'orders',
onSideBar: true,
},
{
code: PageCode.UserData,
name: 'Заполнить анкету',
description: '',
resName: 'user-data',
onSideBar: true
},
{
code: PageCode.RefSystem,
name: 'Пригласить друга',
description: '',
resName: 'ref-system',
onSideBar: true,
}
{
code: PageCode.Auth,
name: 'Вход',
resName: 'auth',
onSideBar: false,
},
{
code: PageCode.BonusProgram,
name: 'Ваша карта лояльности',
description: '',
resName: 'bonus-program',
onSideBar: true,
},
{
code: PageCode.Orders,
name: 'Ваши чеки',
description: '',
resName: 'orders',
onSideBar: true,
},
{
code: PageCode.UserData,
name: 'Заполнить анкету',
description: '',
resName: 'user-data',
onSideBar: true
},
{
code: PageCode.RefSystem,
name: 'Пригласить друга',
description: '',
resName: 'ref-system',
onSideBar: true,
}
];
export const orderStatuses: OrderStatus = {
'Cancelled': 'Отменен',
'InProcessing': 'В обработке',
'Unconfirmed': 'Принят',
'WaitCooking': 'Принят',
'ReadyForCooking': 'Принят',
'CookingStarted': 'Готовится',
'CookingCompleted': 'Приготовлен',
'Waiting': 'В пути',
'OnWay': 'В пути',
'Delivered': 'Выполнен',
'Closed': 'Выполнен',
'Cancelled': 'Отменен',
'InProcessing': 'В обработке',
'Unconfirmed': 'Принят',
'WaitCooking': 'Принят',
'ReadyForCooking': 'Принят',
'CookingStarted': 'Готовится',
'CookingCompleted': 'Приготовлен',
'Waiting': 'В пути',
'OnWay': 'В пути',
'Delivered': 'Выполнен',
'Closed': 'Выполнен',
};
export const lvlPeriods: lvlPeriod[] = [
{
percent: 3,
start: 0,
end: 1600,
color: '#f2c94c'
},
{
percent: 6,
start: 1601,
end: 3600,
color: '#f2994a'
},
{
percent: 10,
start: 3601,
end: 8600,
color: '#6fcf97'
},
{
percent: 15,
start: 8601,
color: '#6fcf97'
},
]
{
percent: 3,
start: 0,
end: 1600,
color: '#f2c94c'
},
{
percent: 6,
start: 1601,
end: 3600,
color: '#f2994a'
},
{
percent: 10,
start: 3601,
end: 8600,
color: '#6fcf97'
},
{
percent: 15,
start: 8601,
color: '#6fcf97'
},
]

View File

@ -6,7 +6,7 @@ export enum PageCode {
UserData,
}
export interface Moment extends moment.Moment {}
export interface Moment extends moment.Moment { }
export interface Page {
code: PageCode;
@ -74,10 +74,10 @@ export interface OrderStatus {
}
export interface lvlPeriod {
percent: number;
start: number;
end?: number;
color: string;
percent: number;
start: number;
end?: number;
color: string;
}
export interface DeliveryType {
@ -179,3 +179,32 @@ export interface UserData {
city: string;
phone: string | null;
}
export interface UserInfoCategory {
id: string;
isActive: boolean;
isDefaultForNewGuests: boolean;
name: string;
}
export interface UserInfoWallet {
id: string;
name: string;
programType: string;
type: string;
}
export interface UserInfoWalletBalance {
balance: number;
wallet: UserInfoWallet;
}
export interface UserInfo {
OrdersSum: number;
categories: UserInfoCategory[];
customer_level: number;
id: string;
name: string | null;
phone: string;
walletBalances: UserInfoWalletBalance[];
}

View File

@ -1,6 +1,5 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { IndexComponent } from './components/index/index.component';
import { GuestCardComponent } from './pages/guest-card/guest-card.component';
import { AuthGuard } from 'src/app/guards/auth-guard.guard';
import { LoginComponent } from './pages/login/login.component';

View File

@ -1,63 +1,55 @@
<app-navbar title="Карта гостя" [backEvent]="showBack ? logout : undefined"></app-navbar>
<p-toast position="top-center"></p-toast>
<ng-container *ngIf="!this.loyaltyProgram.purchaseData.$loading && customerInfo">
<ng-container *ngIf="!authService.loading && authService.userInfo">
<div class="guest-card">
<div class="top-info">
<div class="top-info__level">
<p id="level">Уровень {{ loyaltyProgram.currentLvl }}</p>
<p id="level-percent">Кэшбек {{ loyaltyProgram.currentLvlPeriod.percent }}%</p>
<p id="level">Уровень {{ authService.userInfo.customer_level }}</p>
<p id="level-percent">Кэшбек {{ authService.currentLvlPeriod.percent }}%</p>
</div>
<p class="top-info__bonus">
{{ Math.floor(loyaltyProgram.getBalanceAmount(customerInfo?.walletBalances)) }}
{{ Math.floor(authService.getBalanceAmount(authService.userInfo.walletBalances)) }}
бонусов
</p>
</div>
<div class="guest-card__qr" (click)="qrCodeClick()">
<ng-container *ngIf="customerInfo">
<qr-code
[value]="customerInfo?.phone?.substr(1) || 'Данные не найдены'"
[margin]="0"
[size]="qrCodeSize"
errorCorrectionLevel="H"
></qr-code>
</ng-container>
<ng-container *ngIf="!customerInfo">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 85 }"
></ng-container>
</ng-container>
<div class="guest-card__qr" (click)="qrCodeClick()">
<qr-code
[value]="authService.userInfo?.phone?.substr(1) || 'Данные не найдены'"
[margin]="0"
[size]="qrCodeSize"
errorCorrectionLevel="H"
></qr-code>
</div>
<div class="guest-card__user-description">
<p>
<ng-container *ngIf="loyaltyProgram.currentLvlPeriod.end">
<ng-container *ngIf="authService.currentLvlPeriod.end">
Осталось купить на сумму
<span class="price">{{
loyaltyProgram.currentLvlPeriod.end -
(customerInfo.OrdersSum) +
authService.currentLvlPeriod.end -
(authService.userInfo.OrdersSum) +
1
}}</span>
рублей, тогда кэшбек будет
<span class="percent"
>{{ loyaltyProgram.getNextLevel().percent }}%</span
>{{ authService.getNextLevel().percent }}%</span
>
с
{{
loyaltyProgram.purchaseData.currentPeriod[1]
authService.purchaseData.currentPeriod[1]
.locale("ru")
.format("D MMMM")
}}
</ng-container>
<ng-container *ngIf="!loyaltyProgram.currentLvlPeriod.end">
<ng-container *ngIf="!authService.currentLvlPeriod.end">
У Вас последний уровень бонусной программы. Процент начисляемых
бонусов:
{{ loyaltyProgram.currentLvlPeriod.percent }}%
{{ authService.currentLvlPeriod.percent }}%
</ng-container>
</p>
</div>
<span id="bonuses-condition"></span>
<app-last-order
[lastOrder]="loyaltyProgram.purchaseData.lastPurchase"
[loading]="loyaltyProgram.purchaseData.$loading"
[lastOrder]="authService.purchaseData.lastPurchase"
[loading]="authService.loading"
></app-last-order>
<a class="guest-card__loyalty-program" routerLink="loyality-program"
>Подробнее о правилах <br />
@ -66,12 +58,12 @@
</div>
<app-footer></app-footer>
</ng-container>
<ng-container *ngIf="!customerInfo && !loyaltyProgram.purchaseData.$loading">
<ng-container *ngIf="!authService.loading && !authService.userInfo">
<div class="not-found">
<p>Данные недоступны, попробуйте позже</p>
</div>
</ng-container>
<ng-container *ngIf="loyaltyProgram.purchaseData.$loading">
<ng-container *ngIf="authService.loading">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 85 }"
></ng-container>

View File

@ -6,10 +6,10 @@ import { ExitComponent } from 'src/app/components/exit/exit.component';
import { CookiesService } from 'src/app/services/cookies.service';
import { WpJsonService } from 'src/app/services/wp-json.service';
import { environment } from 'src/environments/environment';
import { LoyaltyProgramService } from 'src/app/services/loyalty-program.service';
import { MessageService } from 'primeng/api';
import { MessagingService } from 'src/app/services/messaging.service';
import { DeviceType, getTypeDevice } from 'src/app/utils';
import { AuthService } from 'src/app/services/auth.service';
@Component({
selector: 'app-guest-card',
@ -19,7 +19,6 @@ import { DeviceType, getTypeDevice } from 'src/app/utils';
export class GuestCardComponent implements OnInit {
public qrCodeSize: number = 85;
private isQrCodeClicked: boolean = false;
public customerInfo!: any;
public Math: Math = Math;
public showBack: boolean = false;
@ -27,39 +26,16 @@ export class GuestCardComponent implements OnInit {
private _bottomSheet: MatBottomSheet,
public cookiesService: CookiesService,
private router: Router,
private wpJsonService: WpJsonService,
public loyaltyProgram: LoyaltyProgramService,
private wpJsonService: WpJsonService,
private messagingService: MessagingService,
private messageService: MessageService,
public authService: AuthService,
) { }
ngOnInit(): void {
this.showBack = getTypeDevice() === DeviceType.android;
const token = this.cookiesService.getItem('token');
this.requestPermission();
this.loyaltyProgram.purchaseData.$loading = true;
this.wpJsonService
.getCustomerInfo(
environment.systemId,
token || '',
environment.icardProxy
)
.subscribe({
next: (value) => {
this.customerInfo = value.customer_info;
this.cookiesService.setCookie('phone-number', this.customerInfo?.phone?.substr(2))
this.loyaltyProgram.setCurrentLvl(this.customerInfo.OrdersSum);
this.loyaltyProgram.getLastPurchase(
environment.systemId,
token || '',
this.customerInfo.id
);
},
});
}
requestPermission() {

View File

@ -41,7 +41,7 @@
Используя приложение, вы принимаете <a href="https://docs.google.com/document/d/1tOZyI9DKerQpMY_N-hMExMB15j2F98E3VDqwIVMkk4I">условия</a>
и соглашаетесь на получение рекламно-информационных сообщений
</p>
<button [disabled]="phoneForm.invalid">Принять участие</button>
<button [disabled]="phoneForm.invalid && phoneForm.touched">Принять участие</button>
</form>
<ng-template #smsCode>

View File

@ -1,25 +1,20 @@
import {
AfterViewInit,
Component,
ElementRef,
EventEmitter,
HostListener,
OnInit,
ViewChild,
} from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router';
import { MessageService } from 'primeng/api';
import { CookiesService } from 'src/app/services/cookies.service';
import { JsonrpcService, RpcService } from 'src/app/services/jsonrpc.service';
import { AuthService } from 'src/app/services/auth.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss'],
})
export class LoginComponent implements OnInit, AfterViewInit {
export class LoginComponent implements OnInit {
public isShowNumber: boolean = true;
public phoneForm = new FormGroup({
name: new FormControl('', []),
@ -35,19 +30,12 @@ export class LoginComponent implements OnInit, AfterViewInit {
timeLeft: number = 0;
constructor(
private cookiesService: CookiesService,
private authService: AuthService,
private router: Router,
private jsonrpc: JsonrpcService,
private messageService: MessageService,
private _snackBar: MatSnackBar,
private jsonRpcService: JsonrpcService
) { }
ngOnInit(): void { }
ngAfterViewInit() {
}
@ViewChild('field', { static: false }) field!: ElementRef;
@ViewChild('field1', { static: false }) field1!: ElementRef;
@ViewChild('field2', { static: false }) field2!: ElementRef;
@ -112,47 +100,14 @@ export class LoginComponent implements OnInit, AfterViewInit {
}
submitNumber() {
const data = this.phoneForm.value;
this.isShowNumber = false;
if (this.timeLeft) {
this.messageService.add({
severity: 'custom',
summary: `Отправить повторно можно через ${this.timeLeft}с`,
});
if (this.phoneForm.invalid) {
this.phoneForm.markAsTouched();
return;
}
this.jsonrpc
.rpc(
{
method: 'sendVerifyByPhone',
params: [data.phone],
},
RpcService.authService,
false
)
.subscribe({
next: (result) => {
if (result.code !== 0) {
this._snackBar.open('Произошла ошибка! Попробуйте позже', '', {
duration: 3000,
});
}
if (result.code === 0) {
this.timeLeft = 60;
const interval = setInterval(() => {
if (this.timeLeft > 0) {
this.timeLeft--;
} else {
clearInterval(interval);
}
}, 1000);
}
this.isShowNumber = false;
},
error: (error) => {
console.error('Error: ', error);
},
});
const data = this.phoneForm.value;
this.authService.sendVerifyByPhone(data.phone!);
this.isShowNumber = false;
setTimeout(() => {
this.field.nativeElement.focus();
}, 0);
@ -160,56 +115,10 @@ export class LoginComponent implements OnInit, AfterViewInit {
submitCode() {
const data = this.codeForm.value;
this.jsonrpc
.rpc(
{
method: 'getTokenByPhone',
params: [this.phoneForm.value.phone, Object.values(data).join('')],
},
RpcService.authService,
false
)
.subscribe({
next: (result) => {
if (result.code === 0) {
this.cookiesService.setCookie('token', result?.data?.token);
this.jsonRpcService.rpc(
{
method: 'updateAdditionalInfo',
params: [
{
first_name: this.phoneForm.value.name,
birth_day: '01.01.1999'
},
],
},
RpcService.authService,
true
).subscribe({
next: (value) => {
this.router.navigate(['/'], {
queryParams: {
token: result?.data?.token,
},
});
},
error: (err) => {
console.error(err);
const phoneData = this.phoneForm.value;
}
})
// this.phoneConfirmed.emit(null);
} else if (result.code === 230) {
this._snackBar.open('Неверный код!', '', {
duration: 3000,
});
// this.errorConfirmCode = true;
}
},
error: (error) => {
console.error(error);
},
});
this.authService.submitCode(
Object.values(data).join(''), phoneData.phone!, phoneData.name!);
}
backToPhoneForm = () => {

View File

@ -1,15 +1,15 @@
<app-navbar title="Программа лояльности" [backEvent]="goBack"></app-navbar>
<ng-container *ngIf="loyaltyProgram.currentLvlPeriod">
<ng-container *ngIf="authService.currentLvlPeriod">
<div class="loyality-program">
<app-accordion header="Условия начисления бонусов">
<p>
Ваш текущий уровень {{ loyaltyProgram.currentLvl }},
поэтому вам начисляется {{ loyaltyProgram.currentLvlPeriod.percent }}% от суммы покупки.
Ваш текущий уровень {{ authService.userInfo?.customer_level }},
поэтому вам начисляется {{ authService.currentLvlPeriod.percent }}% от суммы покупки.
</p>
<p>
Смена уровня произойдет в начале следующего квартала,
{{ loyaltyProgram.purchaseData.currentPeriod[1]
{{ authService.purchaseData.currentPeriod[1]
.locale("ru")
.format("DD.MM.YY") }}.
</p>

View File

@ -1,18 +1,18 @@
import { Component, OnInit } from '@angular/core';
import { Component } from '@angular/core';
import { Location } from '@angular/common';
import { lvlPeriod } from 'src/app/interface/data';
import { lvlPeriods } from 'src/app/app.constants';
import { LoyaltyProgramService } from 'src/app/services/loyalty-program.service';
import { AuthService } from 'src/app/services/auth.service';
@Component({
selector: 'loyality-program',
templateUrl: './loyality-program.component.html',
styleUrls: ['./loyality-program.component.scss'],
})
export class LoyalityProgramComponent implements OnInit {
export class LoyalityProgramComponent {
constructor(
private _location: Location,
public loyaltyProgram: LoyaltyProgramService,
public authService: AuthService,
) { }
public lvlPeriods: lvlPeriod[] = lvlPeriods;
@ -20,10 +20,4 @@ export class LoyalityProgramComponent implements OnInit {
goBack = () => {
this._location.back();
}
ngOnInit(): void {
if (this.loyaltyProgram.currentLvlPeriod == null) {
this._location.back();
}
}
}

View File

@ -0,0 +1,258 @@
import { Injectable } from '@angular/core';
import { CookiesService } from './cookies.service';
import { WpJsonService } from './wp-json.service';
import { environment } from 'src/environments/environment';
import { JsonrpcService, RpcService } from './jsonrpc.service';
import { MessageService } from 'primeng/api';
import { UserInfo, Purchase, lvlPeriod, UserInfoWalletBalance } from '../interface/data';
import { lvlPeriods } from 'src/app/app.constants';
import moment, { Moment } from 'moment-timezone';
import { Router } from '@angular/router';
export interface IPurchaseData {
currentPeriod: Moment[];
lastPeriod: Moment[];
currentAmount?: number;
lastPurchase?: Purchase;
}
@Injectable({
providedIn: 'root',
})
export class AuthService {
public purchaseData: IPurchaseData = {
currentPeriod: [],
lastPeriod: [],
lastPurchase: undefined,
};
userInfo?: UserInfo;
loading: boolean = false;
error: any;
timeLeft: number = 0;
get currentLvlPeriod(): lvlPeriod {
return lvlPeriods[this.userInfo ? this.userInfo.customer_level - 1 : 0];
}
constructor(
private cookiesService: CookiesService,
private wpJsonService: WpJsonService,
private jsonrpc: JsonrpcService,
private messageService: MessageService,
private router: Router,
) {
this.getCurrentQuarterOfYear();
}
get token(): string | undefined {
return this.cookiesService.getItem('token');
}
get authorized(): boolean {
return !!this.token;
}
getUserInfo() {
const token = this.cookiesService.getItem('token');
if (!token) {
return;
}
this.loading = true;
this.wpJsonService
.getCustomerInfo(
environment.systemId,
token,
environment.icardProxy,
)
.subscribe({
next: (value) => {
if (value && value.customer_info && value.customer_info.errorCode === 'Customer_CustomerNotFound') {
this.wpJsonService.newCustomer(
environment.systemId,
token,
environment.icardProxy,
)
.subscribe({
next: () => {
this.getUserInfo();
}
})
} else if (value && value.error && value.error.code > 1) {
this.messageService.add({
severity: 'error',
summary: 'Произошла ошибка! Попробуйте позже',
});
} else if (value && value.customer_info) {
this.userInfo = value.customer_info;
this.cookiesService.setCookie('phone-number', this.userInfo!.phone?.slice(2));
}
},
error: (e) => {
this.error = e;
},
complete: () => {
this.loading = false;
},
});
}
sendVerifyByPhone(phone: string) {
if (this.timeLeft) {
this.messageService.add({
severity: 'custom',
summary: `Отправить повторно можно через ${this.timeLeft}с`,
});
return;
}
this.loading = true;
this.jsonrpc
.rpc(
{
method: 'sendVerifyByPhone',
params: [phone],
},
RpcService.authService,
false
)
.subscribe({
next: (result) => {
if (result.code !== 0) {
this.messageService.add({
severity: 'error',
summary: 'Произошла ошибка! Попробуйте позже',
});
}
if (result.code === 0) {
this.timeLeft = 60;
const interval = setInterval(() => {
if (this.timeLeft > 0) {
this.timeLeft--;
} else {
clearInterval(interval);
}
}, 1000);
}
},
error: (error) => {
console.error('Error: ', error);
},
complete: () => {
this.loading = false;
},
});
}
submitCode(code: string, phone: string, name: string) {
this.loading = true;
this.jsonrpc
.rpc(
{
method: 'getTokenByPhone',
params: [phone, code],
},
RpcService.authService,
false
)
.subscribe({
next: (result) => {
if (result.code === 0) {
this.cookiesService.setCookie('token', result?.data?.token);
this.jsonrpc.rpc(
{
method: 'updateAdditionalInfo',
params: [
{
first_name: name,
birth_day: '01.01.1999'
},
],
},
RpcService.authService,
true
).subscribe({
next: (value) => {
this.router.navigate(['/']);
this.getUserInfo();
},
error: (err) => {
console.error(err);
},
complete: () => {
this.loading = false;
}
})
} else if (result.code === 230) {
this.messageService.add({
severity: 'error',
summary: 'Неверный код!',
});
}
},
error: (error) => {
console.error(error);
},
});
}
getCurrentQuarterOfYear() {
const quarters = [
[
moment().subtract(1, 'years').endOf('year').subtract(3, 'months'),
moment().startOf('year').add(10, 'days'),
],
[
moment().startOf('year').add(10, 'days'),
moment().startOf('year').add(3, 'months'),
],
[
moment().startOf('year').add(3, 'months'),
moment().startOf('year').add(6, 'months'),
],
[
moment().startOf('year').add(6, 'months'),
moment().startOf('year').add(9, 'months'),
],
[
moment().startOf('year').add(9, 'months'),
moment().startOf('year').add(12, 'months'),
],
];
for (let i = 0; i < 4; i++) {
if (moment().isBetween(quarters[i][0], quarters[i][1])) {
this.purchaseData.lastPeriod = quarters[i - 1];
this.purchaseData.currentPeriod = quarters[i];
}
}
}
getNextLevel(): lvlPeriod {
if (this.userInfo?.customer_level === lvlPeriods.length) {
return lvlPeriods[lvlPeriods.length - 1];
}
return this.userInfo && lvlPeriods[this.userInfo?.customer_level] || lvlPeriods[0];
}
getLastPurchase(userInfo: UserInfo) {
this.wpJsonService.getLastPurchase(environment.systemId, this.token!).subscribe({
next: (res) => {
this.purchaseData.lastPurchase = res[userInfo.id][0];
},
});
}
getBalanceAmount(loyaltyPrograms: UserInfoWalletBalance[]) {
return (loyaltyPrograms || []).reduce((accumulator, currentValue) => {
if (currentValue.wallet.name !== 'Федеральная программа лояльности') {
return accumulator
}
return accumulator + currentValue.balance;
}, 0);
}
}

View File

@ -1,107 +0,0 @@
import { Injectable } from '@angular/core';
import moment from 'moment';
import { Moment, Purchase, lvlPeriod } from '../interface/data';
import { lvlPeriods } from '../app.constants';
import { WpJsonService } from './wp-json.service';
import { Observable } from 'rxjs';
export interface IPurchaseData {
currentPeriod: Moment[];
lastPeriod: Moment[];
currentAmount?: number;
$loading: boolean;
lastPurchase?: Purchase;
}
@Injectable({
providedIn: 'root',
})
export class LoyaltyProgramService {
public purchaseData: IPurchaseData = {
currentPeriod: [],
lastPeriod: [],
$loading: false,
lastPurchase: undefined,
};
public currentLvl: number = 1;
public currentLvlPeriod!: lvlPeriod;
public lvlPeriods: lvlPeriod[] = lvlPeriods;
constructor(
private wpJsonService: WpJsonService,
) {
this.getCurrentQuarterOfYear();
}
getCurrentQuarterOfYear() {
const quarters = [
[
moment().subtract(1, 'years').endOf('year').subtract(3, 'months'),
moment().startOf('year').add(10, 'days'),
],
[
moment().startOf('year').add(10, 'days'),
moment().startOf('year').add(3, 'months'),
],
[
moment().startOf('year').add(3, 'months'),
moment().startOf('year').add(6, 'months'),
],
[
moment().startOf('year').add(6, 'months'),
moment().startOf('year').add(9, 'months'),
],
[
moment().startOf('year').add(9, 'months'),
moment().startOf('year').add(12, 'months'),
],
];
for (let i = 0; i < 4; i++) {
if (moment().isBetween(quarters[i][0], quarters[i][1])) {
this.purchaseData.lastPeriod = quarters[i - 1];
this.purchaseData.currentPeriod = quarters[i];
}
}
}
getBalanceAmount(loyaltyPrograms: any[]) {
return (loyaltyPrograms || []).reduce((accumulator, currentValue) => {
if (currentValue.wallet.name !== 'Федеральная программа лояльности') {
return accumulator
}
return accumulator + currentValue.balance;
}, 0);
}
setCurrentLvl(currentAmount: number) {
const index = this.lvlPeriods.findIndex(
(item) =>
item.start <= currentAmount && currentAmount <= (item.end || Infinity)
)!;
if (index != -1) {
this.currentLvlPeriod = this.lvlPeriods[index];
this.currentLvl = index + 1;
}
}
getNextLevel(): lvlPeriod {
if(this.currentLvl == this.lvlPeriods.length) {
return lvlPeriods[this.currentLvl - 1];
}
return lvlPeriods[this.currentLvl];
}
getLastPurchase(systemId: string, token: string, customerId: string) {
this.purchaseData.$loading = true;
this.wpJsonService.getLastPurchase(systemId, token).subscribe({
next: (res) => {
this.purchaseData.lastPurchase = res[customerId][0];
},
complete: () => {
this.purchaseData.$loading = false;
}
});
}
}

View File

@ -4,8 +4,7 @@ import { HttpClient, HttpHeaders } from "@angular/common/http";
import { CookiesService } from "./cookies.service";
import { Observable, of, switchMap } from "rxjs";
import { JsonRpcBody } from "./jsonrpc.service";
import { DeliveryType, AcceptedOrder, Product, Purchase } from "../interface/data";
import { ActivatedRoute } from "@angular/router";
import { DeliveryType, AcceptedOrder, Product } from "../interface/data";
export enum Method {
@ -22,7 +21,6 @@ export class WpJsonService {
constructor(
private http: HttpClient,
private cookiesService: CookiesService,
private route: ActivatedRoute,
) { }
getDeliveryTypes(): Observable<DeliveryType[]> {
@ -42,18 +40,7 @@ export class WpJsonService {
}
getCustomerInfo(systemId: string, token: string, url: string): Observable<any> {
return this._request(`customer_info/${systemId}/${token}/`, 'GET', null, false, url).pipe(
switchMap((response) => {
// TODO: typescript compile optional chaining ('response?.customer_info?.errorCode') without check ('response.customer_info.errorCode')
if (response && response.customer_info && response.customer_info.errorCode !== 'Customer_CustomerNotFound') {
return of(response)
} else {
return this.newCustomer(systemId, token, url).pipe(
switchMap(() => this.getCustomerInfo(systemId, token, url))
)
}
})
)
return this._request(`customer_info/${systemId}/${token}/`, 'GET', null, false, url);
}
getLastPurchase(systemId: string, token: string): Observable<any> {