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> <router-outlet></router-outlet>
<p-toast position="top-center"></p-toast>

View File

@ -1,8 +1,8 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { RouteConfigLoadStart, Router } from '@angular/router'; import { RouteConfigLoadStart, Router } from '@angular/router';
import { AuthService } from './services/auth.service';
import { CookiesService } from './services/cookies.service'; import { CookiesService } from './services/cookies.service';
import { JsonrpcService, RpcService } from './services/jsonrpc.service'; import { JsonrpcService, RpcService } from './services/jsonrpc.service';
import { lastValueFrom } from 'rxjs';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
@ -15,7 +15,8 @@ export class AppComponent implements OnInit {
constructor( constructor(
private router: Router, private router: Router,
private cookiesService: CookiesService, private cookiesService: CookiesService,
private jsonRpcService: JsonrpcService private jsonRpcService: JsonrpcService,
private authService: AuthService,
) { ) {
this.router.events.subscribe((x) => { this.router.events.subscribe((x) => {
if (x instanceof RouteConfigLoadStart && x.route.path === '') { if (x instanceof RouteConfigLoadStart && x.route.path === '') {
@ -48,6 +49,9 @@ export class AppComponent implements OnInit {
} }
ngOnInit(): void { ngOnInit(): void {
if (this.authService.authorized) {
this.authService.getUserInfo();
}
this.getAdditionalInfo().subscribe({ this.getAdditionalInfo().subscribe({
next: (value) => { next: (value) => {
this.cookiesService.setCookie('presentation-option', value?.data?.interface_id || 'default') 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[] = [ export const PageList: Page[] = [
{ {
code: PageCode.Auth, code: PageCode.Auth,
name: 'Вход', name: 'Вход',
resName: 'auth', resName: 'auth',
onSideBar: false, onSideBar: false,
}, },
{ {
code: PageCode.Orders, code: PageCode.Orders,
name: 'Заказы', name: 'Заказы',
resName: 'orders', resName: 'orders',
onSideBar: true, onSideBar: true,
}, },
]; ];
export const PageListWithBonus: Page[] = [ export const PageListWithBonus: Page[] = [
{ {
code: PageCode.Auth, code: PageCode.Auth,
name: 'Вход', name: 'Вход',
resName: 'auth', resName: 'auth',
onSideBar: false, onSideBar: false,
}, },
{ {
code: PageCode.BonusProgram, code: PageCode.BonusProgram,
name: 'Ваша карта лояльности', name: 'Ваша карта лояльности',
description: '', description: '',
resName: 'bonus-program', resName: 'bonus-program',
onSideBar: true, onSideBar: true,
}, },
{ {
code: PageCode.Orders, code: PageCode.Orders,
name: 'Ваши чеки', name: 'Ваши чеки',
description: '', description: '',
resName: 'orders', resName: 'orders',
onSideBar: true, onSideBar: true,
}, },
{ {
code: PageCode.UserData, code: PageCode.UserData,
name: 'Заполнить анкету', name: 'Заполнить анкету',
description: '', description: '',
resName: 'user-data', resName: 'user-data',
onSideBar: true onSideBar: true
}, },
{ {
code: PageCode.RefSystem, code: PageCode.RefSystem,
name: 'Пригласить друга', name: 'Пригласить друга',
description: '', description: '',
resName: 'ref-system', resName: 'ref-system',
onSideBar: true, onSideBar: true,
} }
]; ];
export const orderStatuses: OrderStatus = { export const orderStatuses: OrderStatus = {
'Cancelled': 'Отменен', 'Cancelled': 'Отменен',
'InProcessing': 'В обработке', 'InProcessing': 'В обработке',
'Unconfirmed': 'Принят', 'Unconfirmed': 'Принят',
'WaitCooking': 'Принят', 'WaitCooking': 'Принят',
'ReadyForCooking': 'Принят', 'ReadyForCooking': 'Принят',
'CookingStarted': 'Готовится', 'CookingStarted': 'Готовится',
'CookingCompleted': 'Приготовлен', 'CookingCompleted': 'Приготовлен',
'Waiting': 'В пути', 'Waiting': 'В пути',
'OnWay': 'В пути', 'OnWay': 'В пути',
'Delivered': 'Выполнен', 'Delivered': 'Выполнен',
'Closed': 'Выполнен', 'Closed': 'Выполнен',
}; };
export const lvlPeriods: lvlPeriod[] = [ export const lvlPeriods: lvlPeriod[] = [
{ {
percent: 3, percent: 3,
start: 0, start: 0,
end: 1600, end: 1600,
color: '#f2c94c' color: '#f2c94c'
}, },
{ {
percent: 6, percent: 6,
start: 1601, start: 1601,
end: 3600, end: 3600,
color: '#f2994a' color: '#f2994a'
}, },
{ {
percent: 10, percent: 10,
start: 3601, start: 3601,
end: 8600, end: 8600,
color: '#6fcf97' color: '#6fcf97'
}, },
{ {
percent: 15, percent: 15,
start: 8601, start: 8601,
color: '#6fcf97' color: '#6fcf97'
}, },
] ]

View File

@ -6,7 +6,7 @@ export enum PageCode {
UserData, UserData,
} }
export interface Moment extends moment.Moment {} export interface Moment extends moment.Moment { }
export interface Page { export interface Page {
code: PageCode; code: PageCode;
@ -74,10 +74,10 @@ export interface OrderStatus {
} }
export interface lvlPeriod { export interface lvlPeriod {
percent: number; percent: number;
start: number; start: number;
end?: number; end?: number;
color: string; color: string;
} }
export interface DeliveryType { export interface DeliveryType {
@ -179,3 +179,32 @@ export interface UserData {
city: string; city: string;
phone: string | null; 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 { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { IndexComponent } from './components/index/index.component';
import { GuestCardComponent } from './pages/guest-card/guest-card.component'; import { GuestCardComponent } from './pages/guest-card/guest-card.component';
import { AuthGuard } from 'src/app/guards/auth-guard.guard'; import { AuthGuard } from 'src/app/guards/auth-guard.guard';
import { LoginComponent } from './pages/login/login.component'; import { LoginComponent } from './pages/login/login.component';

View File

@ -1,63 +1,55 @@
<app-navbar title="Карта гостя" [backEvent]="showBack ? logout : undefined"></app-navbar> <app-navbar title="Карта гостя" [backEvent]="showBack ? logout : undefined"></app-navbar>
<p-toast position="top-center"></p-toast> <ng-container *ngIf="!authService.loading && authService.userInfo">
<ng-container *ngIf="!this.loyaltyProgram.purchaseData.$loading && customerInfo">
<div class="guest-card"> <div class="guest-card">
<div class="top-info"> <div class="top-info">
<div class="top-info__level"> <div class="top-info__level">
<p id="level">Уровень {{ loyaltyProgram.currentLvl }}</p> <p id="level">Уровень {{ authService.userInfo.customer_level }}</p>
<p id="level-percent">Кэшбек {{ loyaltyProgram.currentLvlPeriod.percent }}%</p> <p id="level-percent">Кэшбек {{ authService.currentLvlPeriod.percent }}%</p>
</div> </div>
<p class="top-info__bonus"> <p class="top-info__bonus">
{{ Math.floor(loyaltyProgram.getBalanceAmount(customerInfo?.walletBalances)) }} {{ Math.floor(authService.getBalanceAmount(authService.userInfo.walletBalances)) }}
бонусов бонусов
</p> </p>
</div> </div>
<div class="guest-card__qr" (click)="qrCodeClick()"> <div class="guest-card__qr" (click)="qrCodeClick()">
<ng-container *ngIf="customerInfo"> <qr-code
<qr-code [value]="authService.userInfo?.phone?.substr(1) || 'Данные не найдены'"
[value]="customerInfo?.phone?.substr(1) || 'Данные не найдены'" [margin]="0"
[margin]="0" [size]="qrCodeSize"
[size]="qrCodeSize" errorCorrectionLevel="H"
errorCorrectionLevel="H"
></qr-code> ></qr-code>
</ng-container>
<ng-container *ngIf="!customerInfo">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 85 }"
></ng-container>
</ng-container>
</div> </div>
<div class="guest-card__user-description"> <div class="guest-card__user-description">
<p> <p>
<ng-container *ngIf="loyaltyProgram.currentLvlPeriod.end"> <ng-container *ngIf="authService.currentLvlPeriod.end">
Осталось купить на сумму Осталось купить на сумму
<span class="price">{{ <span class="price">{{
loyaltyProgram.currentLvlPeriod.end - authService.currentLvlPeriod.end -
(customerInfo.OrdersSum) + (authService.userInfo.OrdersSum) +
1 1
}}</span> }}</span>
рублей, тогда кэшбек будет рублей, тогда кэшбек будет
<span class="percent" <span class="percent"
>{{ loyaltyProgram.getNextLevel().percent }}%</span >{{ authService.getNextLevel().percent }}%</span
> >
с с
{{ {{
loyaltyProgram.purchaseData.currentPeriod[1] authService.purchaseData.currentPeriod[1]
.locale("ru") .locale("ru")
.format("D MMMM") .format("D MMMM")
}} }}
</ng-container> </ng-container>
<ng-container *ngIf="!loyaltyProgram.currentLvlPeriod.end"> <ng-container *ngIf="!authService.currentLvlPeriod.end">
У Вас последний уровень бонусной программы. Процент начисляемых У Вас последний уровень бонусной программы. Процент начисляемых
бонусов: бонусов:
{{ loyaltyProgram.currentLvlPeriod.percent }}% {{ authService.currentLvlPeriod.percent }}%
</ng-container> </ng-container>
</p> </p>
</div> </div>
<span id="bonuses-condition"></span> <span id="bonuses-condition"></span>
<app-last-order <app-last-order
[lastOrder]="loyaltyProgram.purchaseData.lastPurchase" [lastOrder]="authService.purchaseData.lastPurchase"
[loading]="loyaltyProgram.purchaseData.$loading" [loading]="authService.loading"
></app-last-order> ></app-last-order>
<a class="guest-card__loyalty-program" routerLink="loyality-program" <a class="guest-card__loyalty-program" routerLink="loyality-program"
>Подробнее о правилах <br /> >Подробнее о правилах <br />
@ -66,12 +58,12 @@
</div> </div>
<app-footer></app-footer> <app-footer></app-footer>
</ng-container> </ng-container>
<ng-container *ngIf="!customerInfo && !loyaltyProgram.purchaseData.$loading"> <ng-container *ngIf="!authService.loading && !authService.userInfo">
<div class="not-found"> <div class="not-found">
<p>Данные недоступны, попробуйте позже</p> <p>Данные недоступны, попробуйте позже</p>
</div> </div>
</ng-container> </ng-container>
<ng-container *ngIf="loyaltyProgram.purchaseData.$loading"> <ng-container *ngIf="authService.loading">
<ng-container <ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 85 }" *ngTemplateOutlet="spinner; context: { $implicit: 85 }"
></ng-container> ></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 { CookiesService } from 'src/app/services/cookies.service';
import { WpJsonService } from 'src/app/services/wp-json.service'; import { WpJsonService } from 'src/app/services/wp-json.service';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { LoyaltyProgramService } from 'src/app/services/loyalty-program.service';
import { MessageService } from 'primeng/api'; import { MessageService } from 'primeng/api';
import { MessagingService } from 'src/app/services/messaging.service'; import { MessagingService } from 'src/app/services/messaging.service';
import { DeviceType, getTypeDevice } from 'src/app/utils'; import { DeviceType, getTypeDevice } from 'src/app/utils';
import { AuthService } from 'src/app/services/auth.service';
@Component({ @Component({
selector: 'app-guest-card', selector: 'app-guest-card',
@ -19,7 +19,6 @@ import { DeviceType, getTypeDevice } from 'src/app/utils';
export class GuestCardComponent implements OnInit { export class GuestCardComponent implements OnInit {
public qrCodeSize: number = 85; public qrCodeSize: number = 85;
private isQrCodeClicked: boolean = false; private isQrCodeClicked: boolean = false;
public customerInfo!: any;
public Math: Math = Math; public Math: Math = Math;
public showBack: boolean = false; public showBack: boolean = false;
@ -28,38 +27,15 @@ export class GuestCardComponent implements OnInit {
public cookiesService: CookiesService, public cookiesService: CookiesService,
private router: Router, private router: Router,
private wpJsonService: WpJsonService, private wpJsonService: WpJsonService,
public loyaltyProgram: LoyaltyProgramService,
private messagingService: MessagingService, private messagingService: MessagingService,
private messageService: MessageService, private messageService: MessageService,
public authService: AuthService,
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.showBack = getTypeDevice() === DeviceType.android; this.showBack = getTypeDevice() === DeviceType.android;
const token = this.cookiesService.getItem('token');
this.requestPermission(); 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() { requestPermission() {

View File

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

View File

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

View File

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

View File

@ -1,18 +1,18 @@
import { Component, OnInit } from '@angular/core'; import { Component } from '@angular/core';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { lvlPeriod } from 'src/app/interface/data'; import { lvlPeriod } from 'src/app/interface/data';
import { lvlPeriods } from 'src/app/app.constants'; 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({ @Component({
selector: 'loyality-program', selector: 'loyality-program',
templateUrl: './loyality-program.component.html', templateUrl: './loyality-program.component.html',
styleUrls: ['./loyality-program.component.scss'], styleUrls: ['./loyality-program.component.scss'],
}) })
export class LoyalityProgramComponent implements OnInit { export class LoyalityProgramComponent {
constructor( constructor(
private _location: Location, private _location: Location,
public loyaltyProgram: LoyaltyProgramService, public authService: AuthService,
) { } ) { }
public lvlPeriods: lvlPeriod[] = lvlPeriods; public lvlPeriods: lvlPeriod[] = lvlPeriods;
@ -20,10 +20,4 @@ export class LoyalityProgramComponent implements OnInit {
goBack = () => { goBack = () => {
this._location.back(); 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 { CookiesService } from "./cookies.service";
import { Observable, of, switchMap } from "rxjs"; import { Observable, of, switchMap } from "rxjs";
import { JsonRpcBody } from "./jsonrpc.service"; import { JsonRpcBody } from "./jsonrpc.service";
import { DeliveryType, AcceptedOrder, Product, Purchase } from "../interface/data"; import { DeliveryType, AcceptedOrder, Product } from "../interface/data";
import { ActivatedRoute } from "@angular/router";
export enum Method { export enum Method {
@ -22,7 +21,6 @@ export class WpJsonService {
constructor( constructor(
private http: HttpClient, private http: HttpClient,
private cookiesService: CookiesService, private cookiesService: CookiesService,
private route: ActivatedRoute,
) { } ) { }
getDeliveryTypes(): Observable<DeliveryType[]> { getDeliveryTypes(): Observable<DeliveryType[]> {
@ -42,18 +40,7 @@ export class WpJsonService {
} }
getCustomerInfo(systemId: string, token: string, url: string): Observable<any> { getCustomerInfo(systemId: string, token: string, url: string): Observable<any> {
return this._request(`customer_info/${systemId}/${token}/`, 'GET', null, false, url).pipe( return this._request(`customer_info/${systemId}/${token}/`, 'GET', null, false, url);
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))
)
}
})
)
} }
getLastPurchase(systemId: string, token: string): Observable<any> { getLastPurchase(systemId: string, token: string): Observable<any> {