@@ -66,7 +61,6 @@
type="tel"
placeholder="•"
#field1
- [appFocusNextInput]="inputFocusEmitter"
formControlName="code1"
maxlength="1"
/>
@@ -77,7 +71,6 @@
type="tel"
placeholder="•"
#field2
- [appFocusNextInput]="inputFocusEmitter"
formControlName="code2"
maxlength="1"
/>
@@ -88,7 +81,6 @@
type="tel"
placeholder="•"
#field3
- [appFocusNextInput]="inputFocusEmitter"
formControlName="code3"
maxlength="1"
/>
@@ -97,10 +89,10 @@
Не пришло SMS?
-
- Отправим повторно через {{timeLeft}}с
+
+ Отправим повторно через {{authService.timeLeft}}с
-
+
Отправить повторно
diff --git a/angular/src/app/presentation-options/default-option/pages/login/login.component.scss b/angular/src/app/presentation-options/default-option/pages/login/login.component.scss
index 004d3a6..a109a94 100644
--- a/angular/src/app/presentation-options/default-option/pages/login/login.component.scss
+++ b/angular/src/app/presentation-options/default-option/pages/login/login.component.scss
@@ -1,10 +1,11 @@
:host {
- padding-top: 48px;
display: flex;
flex-direction: column;
align-items: center;
max-width: 600px;
margin: 0 auto 52px;
+ padding-left: 20px;
+ padding-right: 20px;
h1 {
margin-top: 20px;
@@ -46,15 +47,16 @@
.offer {
margin-top: 10px;
- padding: 0 16px;
- font-family: "Gowun Dodum";
+ padding: 0 16px;
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 17px;
text-align: center;
- span {
- color: var(--button-color);
+
+ a {
+ text-decoration: none;
+ color: var(--button-color);
}
}
diff --git a/angular/src/app/presentation-options/default-option/pages/login/login.component.ts b/angular/src/app/presentation-options/default-option/pages/login/login.component.ts
index e848f34..22915b7 100644
--- a/angular/src/app/presentation-options/default-option/pages/login/login.component.ts
+++ b/angular/src/app/presentation-options/default-option/pages/login/login.component.ts
@@ -1,26 +1,24 @@
import {
- AfterViewInit,
Component,
- EventEmitter,
+ ElementRef,
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 { AuthService } from 'src/app/services/auth.service';
import { MessageService } from 'primeng/api';
-import { CookiesService } from 'src/app/services/cookies.service';
-import { JsonrpcService, RpcService } from 'src/app/services/jsonrpc.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('', []),
+ name: new FormControl('', [Validators.required]),
phone: new FormControl('', [Validators.required]),
});
public codeForm = new FormGroup({
@@ -29,41 +27,35 @@ export class LoginComponent implements OnInit, AfterViewInit {
code2: new FormControl('', [Validators.required]),
code3: new FormControl('', [Validators.required]),
});
- private inputIds = ['field', 'field1', 'field2', 'field3'];
- timeLeft: number = 0;
+ private inputIds = ['field', 'field1', 'field2', 'field3'];
constructor(
- private cookiesService: CookiesService,
+ public authService: AuthService,
private router: Router,
- private jsonrpc: JsonrpcService,
- private messageService: MessageService,
- private _snackBar: MatSnackBar,
- private jsonRpcService: JsonrpcService
- ) {}
+ private messageService: MessageService,
+ ) { }
- ngOnInit(): void {}
+ ngOnInit(): void { }
- ngAfterViewInit() {
- setTimeout(() => {
- this.inputFocusEmitter.emit(`#${this.inputIds[0]}`);
- }, 1000);
- }
+ @ViewChild('field', { static: false }) field!: ElementRef;
+ @ViewChild('field1', { static: false }) field1!: ElementRef;
+ @ViewChild('field2', { static: false }) field2!: ElementRef;
+ @ViewChild('field3', { static: false }) field3!: ElementRef;
- public inputFocusEmitter = new EventEmitter
();
-
- @HostListener('window:keyup', ['$event'])
+ @HostListener('window:input', ['$event'])
HandlKeyEvents(event: any) {
if (!event.target.classList.contains('field')) return;
- const key = event.key.toLocaleLowerCase();
+ const key = event.data
let elementId = '';
switch (key) {
- case 'backspace':
+ case null:
elementId = event.target.id;
event.target.value = '';
const prevInputIndex = this.inputIds.indexOf(elementId) - 1;
if (prevInputIndex >= 0) {
- this.inputFocusEmitter.emit(`#${this.inputIds[prevInputIndex]}`);
+ // this.inputFocusEmitter.emit(`#${this.inputIds[prevInputIndex]}`);
+ this.focusFieldByIndex(prevInputIndex);
}
break;
@@ -71,118 +63,72 @@ export class LoginComponent implements OnInit, AfterViewInit {
elementId = event.target.id;
const index = this.inputIds.indexOf(elementId);
const nextInputIndex = index + 1;
- if (event.target.value.length > 1) {
- event.target.value = event.target.value.slice(-1);
- }
+ event.target.value = key;
+
if (nextInputIndex > 0 && nextInputIndex <= this.inputIds.length) {
- this.inputFocusEmitter.emit(`#${this.inputIds[nextInputIndex]}`);
+ // this.inputFocusEmitter.emit(`#${this.inputIds[nextInputIndex]}`);
+ this.focusFieldByIndex(nextInputIndex);
}
+ if (nextInputIndex == this.inputIds.length) {
+ this.field3!.nativeElement.blur();
+ }
+
break;
}
}
+ focusFieldByIndex(i: number) {
+ setTimeout(() => {
+ switch (i) {
+ case 0:
+ this.field.nativeElement.focus();
+ this.field.nativeElement.click();
+ break;
+ case 1:
+ this.field1.nativeElement.focus();
+ this.field1.nativeElement.click();
+ break;
+ case 2:
+ this.field2.nativeElement.focus();
+ this.field2.nativeElement.click();
+ break;
+ case 3:
+ this.field3.nativeElement.focus();
+ this.field3.nativeElement.click();
+ break;
+ }
+ }, 0);
+ }
+
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();
+
+ this.messageService.clear();
+ this.messageService.add({
+ severity: 'error',
+ summary: 'Введите имя и телефон',
});
+
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.inputFocusEmitter.emit(`#${this.inputIds[0]}`);
+ this.field.nativeElement.focus();
}, 0);
}
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);
-
- }
- })
- // this.phoneConfirmed.emit(null);
- } else if (result.code === 230) {
- this._snackBar.open('Неверный код!', '', {
- duration: 3000,
- });
- // this.errorConfirmCode = true;
- }
- },
- error: (error) => {
- console.error(error);
- },
- });
+ const phoneData = this.phoneForm.value;
+
+ this.authService.submitCode(
+ Object.values(data).join(''), phoneData.phone!, phoneData.name!);
}
- backToPhoneForm() {
+ backToPhoneForm = () => {
this.codeForm.setValue({
code: '',
code1: '',
diff --git a/angular/src/app/presentation-options/default-option/pages/loyality-program/loyality-program.component.html b/angular/src/app/presentation-options/default-option/pages/loyality-program/loyality-program.component.html
index 4c7ba49..9850f25 100644
--- a/angular/src/app/presentation-options/default-option/pages/loyality-program/loyality-program.component.html
+++ b/angular/src/app/presentation-options/default-option/pages/loyality-program/loyality-program.component.html
@@ -1,105 +1,105 @@
-
+
-
-
-
-
- Ваш текущий уровень {{ loyaltyProgram.currentLvl }},
- поэтому вам начисляется {{ loyaltyProgram.currentLvlPeriod.percent }}% от суммы покупки.
-
-
- Смена уровня произойдет в начале следующего квартала,
- {{ loyaltyProgram.purchaseData.currentPeriod[1]
- .locale("ru")
- .format("DD.MM.YY") }}.
-
-
-
-
- Начисление Бонусных баллов происходит по дифференцированной шкале в
- зависимости от уровня:
-
+
+
+
+
+ Ваш текущий уровень {{ authService.userInfo?.current_level_and_cashback?.current_level ?? '--' }},
+ поэтому вам начисляется {{ authService.currentLvlPeriod.percent }}% от суммы покупки.
+
+
+ Смена уровня произойдет в начале следующего квартала,
+ {{ authService.currentPeriod[1]
+ .locale("ru")
+ .format("DD.MM.YY") }}.
+
+
+
+
+ Начисление Бонусных баллов происходит по дифференцированной шкале в
+ зависимости от уровня:
+
+
+
+
+
+ Уровень {{ index + 1 }}
+
+ Сумма покупок за прошлый квартал {{ item.start }}-{{ item.end }}
+ руб.
+
+ Начисляемый бонус {{ item.percent }}% от суммы покупки
+
+
+
+
+
+ Уровень {{ index + 1 }}
+ Сумма покупок за прошлый квартал — от {{ item.start }} руб.
+ Начисляемый бонус, в % от суммы покупки - {{ item.percent }}%
+
+
+
+
+
+
+
+ Участник может использовать Бонусы для «оплаты» до 100% стоимости любой
+ покупки.
+
+
+ Списание Бонусов происходит из расчета 1:1 (один Бонус дает скидку 1
+ российский рубль / 1 тенге / 1 белорусский рубль. Скидка, предоставляемая
+ Участнику при списании Бонусов, уменьшает цену товаров в заказе в
+ соответствии с условиями ПЛ.
+
+
+ Для списания Бонусов Участник должен попросить об этом в кофе-баре сети
+ «COFFEE LIKE» кассира до момента пробития фискального чека, после чего им
+ будет проверена возможность списания Бонусов.
+
+
+ Для всех Участников возможно списание без использования мобильного
+ приложения.
+
+ Полученные Бонусы не подлежат обмену на денежные средства.
+
+
+
+ Начисленные на счет бонусы сгорают по прошествии 90 дней с момента
+ совершения последней покупки с начислением или списанием бонусов.
+
-
-
- Уровень {{ index + 1 }}
-
- Сумма покупок за прошлый квартал {{ item.start }}-{{ item.end }}
- руб.
-
- Начисляемый бонус {{ item.percent }}% от суммы покупки
+ Возврат покупки, за которую бонусы были начислены:
+
+ В случае, если бонусов на счету достаточно для списания, бонусы
+ списываются в полном ранее начисленном за возвращаемый товар объеме.
+
+
+ В случае, если бонусов на счету недостаточно, формируется минусовой
+ баланс.
+
-
-
-
+
- Уровень {{ index + 1 }}
- Сумма покупок за прошлый квартал — от {{ item.start }} руб.
- Начисляемый бонус, в % от суммы покупки - {{ item.percent }}%
+ Возврат покупки, которая была оплачена бонусами:
+
+ В случае предъявления Участником кассового или товарного чека, сумма
+ бонусов, списанная для оплаты возвращаемого товара, зачисляется на счет
+ участника.
+
+
+ В случае возврата товара с применением оплаты бонусами, клиенту
+ возвращается денежная сумма в размере, внесенном Участником в оплату
+ товара при покупке, за вычетом суммы, оплаченной бонусами.
+
-
-
-
+
-
-
- Участник может использовать Бонусы для «оплаты» до 100% стоимости любой
- покупки.
-
-
- Списание Бонусов происходит из расчета 1:1 (один Бонус дает скидку 1
- российский рубль / 1 тенге / 1 белорусский рубль. Скидка, предоставляемая
- Участнику при списании Бонусов, уменьшает цену товаров в заказе в
- соответствии с условиями ПЛ.
-
-
- Для списания Бонусов Участник должен попросить об этом в кофе-баре сети
- «COFFEE LIKE» кассира до момента пробития фискального чека, после чего им
- будет проверена возможность списания Бонусов.
-
-
- Для всех Участников возможно списание без использования мобильного
- приложения.
-
- Полученные Бонусы не подлежат обмену на денежные средства.
-
-
-
- Начисленные на счет бонусы сгорают по прошествии 90 дней с момента
- совершения последней покупки с начислением или списанием бонусов.
-
+
-
- Возврат покупки, за которую бонусы были начислены:
-
- В случае, если бонусов на счету достаточно для списания, бонусы
- списываются в полном ранее начисленном за возвращаемый товар объеме.
-
-
- В случае, если бонусов на счету недостаточно, формируется минусовой
- баланс.
-
-
-
-
- Возврат покупки, которая была оплачена бонусами:
-
- В случае предъявления Участником кассового или товарного чека, сумма
- бонусов, списанная для оплаты возвращаемого товара, зачисляется на счет
- участника.
-
-
- В случае возврата товара с применением оплаты бонусами, клиенту
- возвращается денежная сумма в размере, внесенном Участником в оплату
- товара при покупке, за вычетом суммы, оплаченной бонусами.
-
-
-
-
-
-
-
+
diff --git a/angular/src/app/presentation-options/default-option/pages/loyality-program/loyality-program.component.scss b/angular/src/app/presentation-options/default-option/pages/loyality-program/loyality-program.component.scss
index d5a5c6d..531bfda 100644
--- a/angular/src/app/presentation-options/default-option/pages/loyality-program/loyality-program.component.scss
+++ b/angular/src/app/presentation-options/default-option/pages/loyality-program/loyality-program.component.scss
@@ -1,3 +1,4 @@
.loyality-program {
-
+ max-width: 600px;
+ margin: 0 auto;
}
diff --git a/angular/src/app/presentation-options/default-option/pages/loyality-program/loyality-program.component.ts b/angular/src/app/presentation-options/default-option/pages/loyality-program/loyality-program.component.ts
index be71ac8..516feba 100644
--- a/angular/src/app/presentation-options/default-option/pages/loyality-program/loyality-program.component.ts
+++ b/angular/src/app/presentation-options/default-option/pages/loyality-program/loyality-program.component.ts
@@ -1,29 +1,23 @@
-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 {
- constructor(
- private _location: Location,
- public loyaltyProgram: LoyaltyProgramService,
- ) {}
-
- public lvlPeriods: lvlPeriod[] = lvlPeriods;
-
- goBack() {
- this._location.back();
- }
+export class LoyalityProgramComponent {
+ constructor(
+ private _location: Location,
+ public authService: AuthService,
+ ) { }
- ngOnInit(): void {
- if(this.loyaltyProgram.currentLvlPeriod == null) {
- this._location.back();
- }
- }
+ public lvlPeriods: lvlPeriod[] = lvlPeriods;
+
+ goBack = () => {
+ this._location.back();
+ }
}
diff --git a/angular/src/app/presentation-options/first-option/first-option.module.ts b/angular/src/app/presentation-options/first-option/first-option.module.ts
index 290573b..dd3d022 100644
--- a/angular/src/app/presentation-options/first-option/first-option.module.ts
+++ b/angular/src/app/presentation-options/first-option/first-option.module.ts
@@ -9,14 +9,14 @@ import { MatIconModule } from '@angular/material/icon';
import { GuestCardComponent } from './pages/guest-card/guest-card.component';
import { QrCodeModule } from 'ng-qrcode';
import { AccordionComponent } from './components/accordion/accordion.component';
-import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
+import { MatLegacyProgressSpinnerModule as MatProgressSpinnerModule } from '@angular/material/legacy-progress-spinner';
import { LastOrderComponent } from './components/last-order/last-order.component';
import { InviteFriendsComponent } from './components/invite-friends/invite-friends.component';
import { LoginComponent } from './pages/login/login.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatLegacyFormFieldModule as MatFormFieldModule } from '@angular/material/legacy-form-field';
import { NgxMatIntlTelInputComponent } from 'ngx-mat-intl-tel-input';
-import { MatInputModule } from '@angular/material/input';
+import { MatLegacyInputModule as MatInputModule } from '@angular/material/legacy-input';
import { DirectivesModule } from 'src/app/directives/directives.module';
diff --git a/angular/src/app/presentation-options/first-option/pages/login/login.component.ts b/angular/src/app/presentation-options/first-option/pages/login/login.component.ts
index 0a60904..de6d19e 100644
--- a/angular/src/app/presentation-options/first-option/pages/login/login.component.ts
+++ b/angular/src/app/presentation-options/first-option/pages/login/login.component.ts
@@ -6,7 +6,7 @@ import {
OnInit
} from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
-import { MatSnackBar } from '@angular/material/snack-bar';
+import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar';
import { Router } from '@angular/router';
import { MessageService } from 'primeng/api';
import { CookiesService } from 'src/app/services/cookies.service';
diff --git a/angular/src/app/services/apple-wallet.service.ts b/angular/src/app/services/apple-wallet.service.ts
index e184003..f03d937 100644
--- a/angular/src/app/services/apple-wallet.service.ts
+++ b/angular/src/app/services/apple-wallet.service.ts
@@ -1,15 +1,22 @@
+import { lastValueFrom } from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http';
-import { Injectable } from '@angular/core';
+import { Injectable, Inject } from '@angular/core';
import { environment } from 'src/environments/environment';
+import { CookiesService } from './cookies.service';
+import { RpcService, JsonrpcService } from 'src/app/services/jsonrpc.service';
+import { DOCUMENT } from '@angular/common';
@Injectable({
providedIn: 'root',
})
export class AppleWalletService {
- private url: string = environment.appleWalletEndpoint;
+ private url: string = environment.appleWalletEndpoint;
constructor(
private http: HttpClient,
- ) {}
+ private cookiesService: CookiesService,
+ private jsonrpc: JsonrpcService,
+ @Inject(DOCUMENT) private document: Document,
+ ) { }
generateCard(token: string, user_id: string) {
let headers = new HttpHeaders();
@@ -20,7 +27,7 @@ export class AppleWalletService {
return this.http.get(`${this.url}/client/${environment.clientName}/passUrl/${user_id}/token/${token}`, options)
}
- reloadCard(user_id:string) {
+ reloadCard(user_id: string) {
let headers = new HttpHeaders();
headers = headers.set('Authorization', environment.appleWalletSecret);
const options = {
@@ -32,4 +39,37 @@ export class AppleWalletService {
}
return this.http.post(`${this.url}/sendNotification/${user_id}`, body, options)
}
+
+
+ async addCardToWallet() {
+ const token = this.cookiesService.getItem('token');
+ try {
+ const accountData = (
+ await lastValueFrom(
+ this.jsonrpc.rpc(
+ {
+ method: 'getTokenData',
+ params: [],
+ },
+ RpcService.authService,
+ true
+ )
+ )
+ ).data;
+
+ if (token && accountData.user_id) {
+ this.generateCard(token, accountData.user_id).subscribe({
+ next: (res: any) => {
+ this.document.location.href = res.url;
+ },
+ error: (err) => {
+ console.log('Error: ', err);
+ },
+ });
+ }
+ } catch (e) {
+ console.log(e);
+ }
+
+ }
}
diff --git a/angular/src/app/services/auth.service.ts b/angular/src/app/services/auth.service.ts
new file mode 100644
index 0000000..71e2c28
--- /dev/null
+++ b/angular/src/app/services/auth.service.ts
@@ -0,0 +1,243 @@
+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, lvlPeriod, UserInfoWalletBalance, Moment } from '../interface/data';
+import { lvlPeriods } from 'src/app/app.constants';
+import moment from 'moment-timezone';
+import { Router } from '@angular/router';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class AuthService {
+ lastPeriod: Moment[] = [];
+ currentPeriod: Moment[] = [];
+ userInfo?: UserInfo;
+ loading: boolean = false;
+ error: any;
+ timeLeft: number = 0;
+
+ get currentLvlPeriod(): lvlPeriod {
+ return lvlPeriods[
+ this.userInfo?.current_level_and_cashback ? this.userInfo?.current_level_and_cashback.current_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.error && value.error.code === 11) {
+ this.wpJsonService.newCustomer(
+ environment.systemId,
+ token,
+ environment.icardProxy,
+ )
+ .subscribe({
+ next: () => {
+ this.getUserInfo();
+ }
+ })
+ } else if (value && value.error && value.error.code > 1) {
+ this.messageService.clear();
+ 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;
+ }
+ });
+ }
+
+ logout() {
+ this.userInfo = undefined;
+ this.cookiesService.logout();
+ this.router.navigate(['/login']);
+ }
+
+ sendVerifyByPhone(phone: string) {
+ if (this.timeLeft) {
+ this.messageService.clear();
+ 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.clear();
+ 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: () => {
+ this.router.navigate(['/']);
+ this.getUserInfo();
+ },
+ error: (err) => {
+ console.error(err);
+ },
+ })
+ } else if (result.code === 230) {
+ this.messageService.clear();
+ this.messageService.add({
+ severity: 'error',
+ summary: 'Неверный код!',
+ });
+ }
+ },
+ error: (error) => {
+ console.error(error);
+ },
+ complete: () => {
+ this.loading = false;
+ }
+ });
+ }
+
+ 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.lastPeriod = quarters[i - 1];
+ this.currentPeriod = quarters[i];
+ }
+ }
+ }
+
+ getBalanceAmount(loyaltyPrograms: UserInfoWalletBalance[]) {
+ return (loyaltyPrograms || []).reduce((accumulator, currentValue) => {
+ if (currentValue.wallet.name !== 'Федеральная программа лояльности') {
+ return accumulator
+ }
+ return accumulator + currentValue.balance;
+ }, 0);
+ }
+}
diff --git a/angular/src/app/services/loyalty-program.service.ts b/angular/src/app/services/loyalty-program.service.ts
deleted file mode 100644
index f6646d7..0000000
--- a/angular/src/app/services/loyalty-program.service.ts
+++ /dev/null
@@ -1,173 +0,0 @@
-import { Injectable } from '@angular/core';
-import moment from 'moment';
-import { Moment, Purchase, lvlPeriod } from '../interface/data';
-import { lvlPeriods } from '../app.constants';
-
-export interface IPurchaseData {
- currentPeriod: Moment[];
- lastPeriod: Moment[];
- lastPurchases: Purchase[];
- currentPurchases: Purchase[];
- lastAmount?: number;
- currentAmount?: number;
- $loading: boolean;
-}
-
-@Injectable({
- providedIn: 'root',
-})
-export class LoyaltyProgramService {
- public purchaseData: IPurchaseData = {
- currentPeriod: [],
- lastPeriod: [],
- lastPurchases: [],
- currentPurchases: [],
- $loading: false,
- get currentAmount(): number {
- const amount = this.currentPurchases.reduce(
- (accumulator, currentValue) => {
- if (
- ['CancelPayFromWallet', 'CancelRefillWalletFromOrder'].includes(
- currentValue.transactionType || ''
- )
- ) {
- return accumulator - currentValue.orderSum!;
- } else if (
- ['PayFromWallet', 'RefillWalletFromOrder'].includes(
- currentValue.transactionType || ''
- )
- ) {
- return accumulator + currentValue.orderSum!;
- }
- return accumulator;
- },
- 0
- );
-
- return amount * 1;
- },
- get lastAmount(): number {
- const amount = this.lastPurchases.reduce((accumulator, currentValue) => {
- if (
- ['CancelPayFromWallet', 'CancelRefillWalletFromOrder'].includes(
- currentValue.transactionType || ''
- )
- ) {
- return accumulator - currentValue.orderSum!;
- } else if (
- ['PayFromWallet', 'RefillWalletFromOrder'].includes(
- currentValue.transactionType || ''
- )
- ) {
- return accumulator + currentValue.orderSum!;
- }
- return accumulator;
- }, 0);
- return amount * 1;
- },
- };
-
- public currentLvl: number = 1;
- public currentLvlPeriod!: lvlPeriod;
- public lvlPeriods: lvlPeriod[] = lvlPeriods;
-
- constructor() {
- 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);
- }
-
- setLastPurchases(purchases: Purchase[]) {
- this.purchaseData.lastPurchases = (purchases || []).filter((value: Purchase) => {
- return moment(value.transactionCreateDate).isBetween(
- this.purchaseData.lastPeriod[0],
- this.purchaseData.lastPeriod[1]
- );
- });
- }
-
- setCurrentPurchases(purchases: Purchase[]) {
- this.purchaseData.currentPurchases = (purchases || []).filter((value: Purchase) => {
- return moment(value.transactionCreateDate).isBetween(
- this.purchaseData.currentPeriod[0],
- this.purchaseData.currentPeriod[1]
- );
- });
- }
-
- filterPurchases(purchases: Purchase[]) {
- return (purchases || []).filter((purchase: Purchase) =>
- [
- 'PayFromWallet',
- 'RefillWalletFromOrder',
- 'CancelPayFromWallet',
- 'CancelRefillWalletFromOrder',
- ].includes(purchase.transactionType || '')
- );
- }
-
- getLastPurchase(purchases: Purchase[]) {
- return purchases.filter((purchase: Purchase) =>
- ['PayFromWallet', 'RefillWalletFromOrder'].includes(
- purchase.transactionType || ''
- )
- )[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];
- }
-}
diff --git a/angular/src/app/services/messaging.service.ts b/angular/src/app/services/messaging.service.ts
index 59bc0ed..d05ea0d 100644
--- a/angular/src/app/services/messaging.service.ts
+++ b/angular/src/app/services/messaging.service.ts
@@ -26,15 +26,15 @@ export class MessagingService {
method: 'getAdditionalInfo',
params: []
}, RpcService.authService, true)
- )).data
- let tokens: string[] = []
- if (typeof additionalInfo['fmc-token'] === 'string') {
- tokens.push(additionalInfo['fmc-token'], token)
- } else if (typeof additionalInfo['fmc-token'] === 'object') {
- tokens = [...additionalInfo['fmc-token'], token]
- } else {
- tokens = [token]
- }
+ )).data
+ let tokens: string[] = []
+ if (typeof additionalInfo['fmc-token'] === 'string') {
+ tokens.push(additionalInfo['fmc-token'], token)
+ } else if (typeof additionalInfo['fmc-token'] === 'object') {
+ tokens = [...additionalInfo['fmc-token'], token]
+ } else {
+ tokens = [token]
+ }
this.jsonRpcService
.rpc(
{
@@ -50,6 +50,7 @@ export class MessagingService {
)
.subscribe({
next: () => {
+ this.messageService.clear();
this.messageService.add({
severity: 'custom',
summary: 'Спасибо за подписку!',
@@ -57,6 +58,7 @@ export class MessagingService {
},
error: (err) => {
console.error('Error: ', err);
+ this.messageService.clear();
this.messageService.add({
severity: 'error',
summary: 'Произошла ошибка, попробуйте позже',
@@ -65,11 +67,20 @@ export class MessagingService {
});
}
+ checkRequestPermission() {
+ return Notification.permission !== 'granted' ? false : true;
+ }
+
requestPermission() {
+ if (this.checkRequestPermission()) {
+ return;
+ }
+
try {
this.angularFireMessaging.requestToken.subscribe({
next: (token) => {
this.updateToken(token);
+ this.receiveMessage();
},
error: (e) => console.error(e),
});
diff --git a/angular/src/app/services/wp-json.service.ts b/angular/src/app/services/wp-json.service.ts
index c45d237..c05b001 100644
--- a/angular/src/app/services/wp-json.service.ts
+++ b/angular/src/app/services/wp-json.service.ts
@@ -1,12 +1,10 @@
import { Injectable } from '@angular/core';
-import {environment} from "../../environments/environment";
-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} from "../interface/data";
-import {ActivatedRoute} from "@angular/router";
-import {Order} from "../models/order";
+import { environment } from "../../environments/environment";
+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 } from "../interface/data";
export enum Method {
@@ -23,38 +21,30 @@ export class WpJsonService {
constructor(
private http: HttpClient,
private cookiesService: CookiesService,
- private route: ActivatedRoute,
) { }
- getDeliveryTypes(): Observable{
+ getDeliveryTypes(): Observable {
return this._request('orders/delivery-types', 'GET');
}
- createOrder(order: any){
+ createOrder(order: any) {
return this._request('orders', 'POST', order);
}
- getOrders(): Observable{
+ getOrders(): Observable {
return this._request('orders', 'GET', null, true);
}
- getProductById(id: number): Observable{
+ getProductById(id: number): Observable {
return this._request(`products/${id}`, 'GET');
}
getCustomerInfo(systemId: string, token: string, url: string): Observable {
- 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 {
+ return this._request(`last_trans/${systemId}/${token}/`, 'GET', null, false, environment.icardProxy);
}
newCustomer(systemId: string, token: string, url: string): Observable {
@@ -83,7 +73,7 @@ export class WpJsonService {
headers = headers.set('Content-Type', 'application/json');
let urlToken = '';
if (token && token !== 'undefined' && auth) {
- urlToken = '?token=' + token;
+ urlToken = '?token=' + token;
}
this.body = body;
const options = {
@@ -96,6 +86,6 @@ export class WpJsonService {
url = baseUrl
}
return this.http
- .request( method, url + path + urlToken, options);
+ .request(method, url + path + urlToken, options);
}
}
diff --git a/angular/src/app/utils.ts b/angular/src/app/utils.ts
new file mode 100644
index 0000000..84080be
--- /dev/null
+++ b/angular/src/app/utils.ts
@@ -0,0 +1,24 @@
+import { environment } from "src/environments/environment.prod";
+
+export enum DeviceType {
+ ios,
+ android,
+}
+
+export function getTypeDevice(): DeviceType {
+ const userAgent = window.navigator.userAgent.toLowerCase();
+ const ios = /iphone|ipod|ipad/.test(userAgent);
+ return ios ? DeviceType.ios : DeviceType.android;
+}
+
+export async function pwaInstalled(): Promise {
+ if ("getInstalledRelatedApps" in navigator) {
+ const apps = await (window.navigator as any).getInstalledRelatedApps();
+ for (const app of apps) {
+ if (app.url == environment.manifestUrl) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/angular/src/assets/970х250_3.png b/angular/src/assets/970х250_3.png
new file mode 100644
index 0000000..f523104
Binary files /dev/null and b/angular/src/assets/970х250_3.png differ
diff --git a/angular/src/assets/apple_wallet.svg b/angular/src/assets/apple_wallet.svg
new file mode 100644
index 0000000..fc72fdf
--- /dev/null
+++ b/angular/src/assets/apple_wallet.svg
@@ -0,0 +1,232 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/angular/src/environments/environment.prod.ts b/angular/src/environments/environment.prod.ts
index a99cf24..c0de26c 100644
--- a/angular/src/environments/environment.prod.ts
+++ b/angular/src/environments/environment.prod.ts
@@ -8,19 +8,18 @@ export const environment = {
hasBonusProgram: true,
systemId: 'tsQ2cu59Xz9qgGTm3z',
defaultUrl: 'https://club.coffee-like.com',
+ manifestUrl: 'https://club.coffee-like.com/manifest.webmanifest',
firebase: {
- apiKey: "AIzaSyCnKvln5itnrBj62POCPHxshAN_Vmd0zds",
- authDomain: "fashionlogicanotification.firebaseapp.com",
- projectId: "fashionlogicanotification",
- storageBucket: "fashionlogicanotification.appspot.com",
- messagingSenderId: "99855572145",
-
- appId: "1:99855572145:web:7548c189d61b3bcc92d690",
- measurementId: "G-RQF97ZK7R1"
+ apiKey: "AIzaSyDTb_xuMz2vDx8xGs34AJiltraKVlwmrtY",
+ authDomain: "coffee-like-77bfe.firebaseapp.com",
+ projectId: "coffee-like-77bfe",
+ storageBucket: "coffee-like-77bfe.appspot.com",
+ messagingSenderId: "1094726277369",
+ appId: "1:1094726277369:web:8af560662da7700e7a2a28"
},
version: packageJson.version,
- appleWalletEndpoint: 'https://apple-push-notifications.it-retail.tech/apns/api',
+ appleWalletEndpoint: 'https://apple-wallet-iiko.it-retail.tech/apns/api',
icardProxy: 'https://club.coffee-like.com/api/icard-proxy/',
appleWalletSecret: 'Token F5mbzEERAznGKVbB6l',
- clientName: 'coffeeLike'
+ clientName: 'coffeelike'
}
diff --git a/angular/src/environments/environment.ts b/angular/src/environments/environment.ts
index 060fb78..09db583 100644
--- a/angular/src/environments/environment.ts
+++ b/angular/src/environments/environment.ts
@@ -8,18 +8,18 @@ export const environment = {
hasBonusProgram: true,
systemId: 'tsQ2cu59Xz9qgGTm3z',
defaultUrl: 'http://192.168.0.179:4200',
+ manifestUrl: 'https://club.coffee-like.com/manifest.webmanifest',
firebase: {
- apiKey: 'AIzaSyCnKvln5itnrBj62POCPHxshAN_Vmd0zds',
- authDomain: 'fashionlogicanotification.firebaseapp.com',
- projectId: 'fashionlogicanotification',
- storageBucket: 'fashionlogicanotification.appspot.com',
- messagingSenderId: '99855572145',
- appId: '1:99855572145:web:7548c189d61b3bcc92d690',
- measurementId: 'G-RQF97ZK7R1',
+ apiKey: "AIzaSyDTb_xuMz2vDx8xGs34AJiltraKVlwmrtY",
+ authDomain: "coffee-like-77bfe.firebaseapp.com",
+ projectId: "coffee-like-77bfe",
+ storageBucket: "coffee-like-77bfe.appspot.com",
+ messagingSenderId: "1094726277369",
+ appId: "1:1094726277369:web:8af560662da7700e7a2a28"
},
version: packageJson.version,
- appleWalletEndpoint: 'http://192.168.0.179:4200/apns/api',
- icardProxy: 'http://192.168.0.14:4200/icard-proxy/',
+ appleWalletEndpoint: 'https://apple-wallet-iiko.it-retail.tech/apns/api',
+ icardProxy: 'https://club.coffee-like.com/api/icard-proxy/',
appleWalletSecret: 'Token F5mbzEERAznGKVbB6l',
- clientName: 'coffeeLike'
+ clientName: 'coffeelike'
};
diff --git a/angular/src/firebase-messaging-sw.js b/angular/src/firebase-messaging-sw.js
index 3468516..d889cf9 100644
--- a/angular/src/firebase-messaging-sw.js
+++ b/angular/src/firebase-messaging-sw.js
@@ -2,13 +2,12 @@ importScripts('https://www.gstatic.com/firebasejs/3.6.9/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.6.9/firebase-messaging.js');
firebase.initializeApp({
- apiKey: "AIzaSyCnKvln5itnrBj62POCPHxshAN_Vmd0zds",
- authDomain: "fashionlogicanotification.firebaseapp.com",
- projectId: "fashionlogicanotification",
- storageBucket: "fashionlogicanotification.appspot.com",
- messagingSenderId: "99855572145",
- appId: "1:99855572145:web:7548c189d61b3bcc92d690",
- measurementId: "G-RQF97ZK7R1"
+ apiKey: "AIzaSyDTb_xuMz2vDx8xGs34AJiltraKVlwmrtY",
+ authDomain: "coffee-like-77bfe.firebaseapp.com",
+ projectId: "coffee-like-77bfe",
+ storageBucket: "coffee-like-77bfe.appspot.com",
+ messagingSenderId: "1094726277369",
+ appId: "1:1094726277369:web:8af560662da7700e7a2a28"
});
-const messaging = firebase.messaging();
\ No newline at end of file
+const messaging = firebase.messaging();
diff --git a/angular/src/manifest.webmanifest b/angular/src/manifest.webmanifest
index 38273a6..f3ddee2 100644
--- a/angular/src/manifest.webmanifest
+++ b/angular/src/manifest.webmanifest
@@ -50,5 +50,9 @@
"purpose": "maskable any"
}
],
- "gcm_sender_id": "99855572145"
+ "gcm_sender_id": "99855572145",
+ "related_applications": [{
+ "platform": "webapp",
+ "url": "https://club.coffee-like.com/manifest.webmanifest"
+ }]
}
diff --git a/angular/src/styles.scss b/angular/src/styles.scss
index a5e5ead..f284643 100644
--- a/angular/src/styles.scss
+++ b/angular/src/styles.scss
@@ -1,5 +1,89 @@
+@use '@angular/material' as mat;
+
+@include mat.core();
+
+$primary: (
+ 50 : #f0e4ec,
+ 100 : #d9bcd0,
+ 200 : #bf90b0,
+ 300 : #a56390,
+ 400 : #924179,
+ 500 : #7f2061,
+ 600 : #771c59,
+ 700 : #6c184f,
+ 800 : #621345,
+ 900 : #4f0b33,
+ A100 : #ff85c7,
+ A200 : #ff52b0,
+ A400 : #ff1f99,
+ A700 : #ff068d,
+ contrast: (
+ 50 : #000000,
+ 100 : #000000,
+ 200 : #000000,
+ 300 : #ffffff,
+ 400 : #ffffff,
+ 500 : #ffffff,
+ 600 : #ffffff,
+ 700 : #ffffff,
+ 800 : #ffffff,
+ 900 : #ffffff,
+ A100 : #000000,
+ A200 : #000000,
+ A400 : #ffffff,
+ A700 : #ffffff,
+ )
+);
+
+$accent: (
+ 50 : #ffffff,
+ 100 : #ffffff,
+ 200 : #ffffff,
+ 300 : #ffffff,
+ 400 : #ffffff,
+ 500 : #ffffff,
+ 600 : #ffffff,
+ 700 : #ffffff,
+ 800 : #ffffff,
+ 900 : #ffffff,
+ A100 : #ffffff,
+ A200 : #ffffff,
+ A400 : #ffffff,
+ A700 : #ffffff,
+ contrast: (
+ 50 : #000000,
+ 100 : #000000,
+ 200 : #000000,
+ 300 : #000000,
+ 400 : #000000,
+ 500 : #000000,
+ 600 : #000000,
+ 700 : #000000,
+ 800 : #000000,
+ 900 : #000000,
+ A100 : #000000,
+ A200 : #000000,
+ A400 : #000000,
+ A700 : #000000,
+ )
+);
+
+$primary-palette: mat.define-palette($primary);
+$accent-palette: mat.define-palette($accent);
+
+$theme: mat.define-light-theme((
+ color: (
+ primary: $primary-palette,
+ accent: $accent-palette,
+ ),
+ typography: mat.define-typography-config(),
+ density: 0,
+));
+
+@include mat.all-component-themes($theme);
+
// Сброс стилей
-html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:middle}
+html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;}
article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}
html{height:100%;}
body{line-height:1}
@@ -27,7 +111,7 @@ body {
}
:root {
- --main-color: #00b26b;
+ --main-color: #7F2061;
--main-border-radius: 35px;
--background-color: #ffffff;
@@ -39,6 +123,32 @@ body {
--button-text-color: #ffffff;
--button-text-color_disabled: #cccccc;
+
+ --main-color_hover: rgba(127, 32, 97, 0.3);
+}
+
+.mdc-button__label {
+ color: var(--button-text-color) !important;
+}
+
+.mat-mdc-outlined-button:not(:disabled) {
+ border-color: var(--button-text-color) !important;
+}
+
+.mat-h1,
+.mat-headline-5,
+.mat-typography .mat-h1,
+.mat-typography .mat-headline-5,
+.mat-typography h1 {
+ font-family: Montserrat;
+}
+
+.mat-h2,
+.mat-headline-6,
+.mat-typography .mat-h2,
+.mat-typography .mat-headline-6,
+.mat-typography h2 {
+ font-family: Montserrat, sans-serif;
}
hr {
@@ -46,64 +156,6 @@ hr {
border-top: 1px solid #BDBDBD;
}
-.mat-bottom-sheet-container {
- box-shadow: 0px 8px 10px -5px rgba(255, 255, 255, 0.2), 0px 16px 24px 2px rgba(255, 255, 255, 0.14), 0px 6px 30px 5px rgba(255, 255, 255, 0.12);
- background: var(--background-color);
- color: var(--text-color);
-}
-
-
-.mat-form-field-appearance-outline .mat-form-field-outline {
- color: var(--button-color_disabled) !important;
-}
-
-.mat-form-field-appearance-outline .mat-form-field-outline {
- color: var(--button-color) !important;
-}
-
-.mat-form-field-wrapper {
- padding: 0;
-}
-
-.mat-progress-spinner circle, .mat-spinner circle {
- stroke: var(--button-color);
-}
-
-.mat-form-field-outline-start, .mat-form-field-outline-end {
- border-radius: 0 !important;
-}
-.mat-form-field-outline-start {
- border-left: none !important;
-}
-.mat-form-field-outline-end {
- border-right: none !important;
-}
-
-.mat-focused .mat-form-field-outline > div {
- border-color: var(--button-color);
-}
-
-.mat-form-field-label {
- color: var(--text-color_1) !important;
-}
-
-.mat-focused .mat-form-field-label {
- color: var(--text-color) !important;
-}
-
-.mat-form-field-invalid .mat-form-field-outline > div {
- border-color: red;
-}
-
-.country-list-button {
- color: var(--text-color) !important;
-}
-
-.mat-menu-panel {
- background: var(--background-color);
- border-radius: 0;
-}
-
.country-selector {
opacity: 1 !important;
display: none !important;
@@ -117,7 +169,6 @@ hr {
color: var(--text-color);
}
-
qr-code canvas {
transition: all 0.3s ease 0s;
}
@@ -175,5 +226,21 @@ input::-webkit-date-and-time-value {
text-align: left;
}
+
+.p-toast-message-custom {
+ background-color: var(--background-color);
+ border: solid var(--main-color);
+ border-width: 0 0 0 6px;
+ color: var(--text-color);
+
+ .p-toast-icon-close {
+ color: var(--main-color);
+ }
+}
+
+.p-toast.p-component.p-toast-top-center {
+ max-width: 96vw;
+}
+
html, body { height: 100%; }
body { margin: 0; }
diff --git a/angular/src/test.ts b/angular/src/test.ts
index c04c876..51bb020 100644
--- a/angular/src/test.ts
+++ b/angular/src/test.ts
@@ -7,20 +7,8 @@ import {
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
-declare const require: {
- context(path: string, deep?: boolean, filter?: RegExp): {
- (id: string): T;
- keys(): string[];
- };
-};
-
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
);
-
-// Then we find all the tests.
-const context = require.context('./', true, /\.spec\.ts$/);
-// And load the modules.
-context.keys().forEach(context);
diff --git a/angular/tsconfig.json b/angular/tsconfig.json
index 5b6384b..169aa7f 100644
--- a/angular/tsconfig.json
+++ b/angular/tsconfig.json
@@ -16,7 +16,7 @@
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
- "target": "es2020",
+ "target": "ES2022",
"module": "es2020",
"lib": [
"es2020",
@@ -24,6 +24,7 @@
],
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
+ "useDefineForClassFields": false
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,