diff --git a/angular/angular.json b/angular/angular.json
index 76e1e77..e10ef21 100644
--- a/angular/angular.json
+++ b/angular/angular.json
@@ -87,7 +87,8 @@
"browserTarget": "coffee-like:build:production"
},
"development": {
- "browserTarget": "coffee-like:build:development"
+ "browserTarget": "coffee-like:build:development",
+ "proxyConfig": "proxy.confi.json"
}
},
"defaultConfiguration": "development"
diff --git a/angular/package-lock.json b/angular/package-lock.json
index 4b1a00f..275ecff 100644
--- a/angular/package-lock.json
+++ b/angular/package-lock.json
@@ -30,7 +30,9 @@
"firebase": "^9.9.3",
"google-libphonenumber": "^3.2.30",
"jsbarcode": "^3.11.5",
+ "libphonenumber-js": "^1.10.28",
"ng-qrcode": "^7.0.0",
+ "ngx-mat-intl-tel-input": "^5.0.0",
"ngx-sharebuttons": "^11.0.0",
"primeicons": "^5.0.0",
"primeng": "^14.0.1",
@@ -8862,6 +8864,11 @@
"node": ">=0.10.0"
}
},
+ "node_modules/libphonenumber-js": {
+ "version": "1.10.28",
+ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.28.tgz",
+ "integrity": "sha512-1eAgjLrZA0+2Wgw4hs+4Q/kEBycxQo8ZLYnmOvZ3AlM8ImAVAJgDPlZtISLEzD1vunc2q8s2Pn7XwB7I8U3Kzw=="
+ },
"node_modules/license-webpack-plugin": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz",
@@ -9636,6 +9643,22 @@
"@angular/core": ">=14 <15"
}
},
+ "node_modules/ngx-mat-intl-tel-input": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ngx-mat-intl-tel-input/-/ngx-mat-intl-tel-input-5.0.0.tgz",
+ "integrity": "sha512-3XwA0zzcxBF/p+BQqBuGxPa7Mi+upehbrR6WvgwWcd+T9NcjImNEAf/Pd8R37OarN3fLrxFq/8g6B2zqYZtBCg==",
+ "dependencies": {
+ "tslib": "^2.x"
+ },
+ "peerDependencies": {
+ "@angular/common": ">=14.x",
+ "@angular/core": ">=14.x",
+ "@angular/forms": ">=14.x",
+ "@angular/platform-browser": ">=14.x",
+ "@angular/platform-browser-dynamic": ">=14.x",
+ "libphonenumber-js": "^1.10.11"
+ }
+ },
"node_modules/ngx-sharebuttons": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/ngx-sharebuttons/-/ngx-sharebuttons-11.0.0.tgz",
@@ -20274,6 +20297,11 @@
"klona": "^2.0.4"
}
},
+ "libphonenumber-js": {
+ "version": "1.10.28",
+ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.28.tgz",
+ "integrity": "sha512-1eAgjLrZA0+2Wgw4hs+4Q/kEBycxQo8ZLYnmOvZ3AlM8ImAVAJgDPlZtISLEzD1vunc2q8s2Pn7XwB7I8U3Kzw=="
+ },
"license-webpack-plugin": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz",
@@ -20862,6 +20890,14 @@
"tslib": "^2.4.0"
}
},
+ "ngx-mat-intl-tel-input": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ngx-mat-intl-tel-input/-/ngx-mat-intl-tel-input-5.0.0.tgz",
+ "integrity": "sha512-3XwA0zzcxBF/p+BQqBuGxPa7Mi+upehbrR6WvgwWcd+T9NcjImNEAf/Pd8R37OarN3fLrxFq/8g6B2zqYZtBCg==",
+ "requires": {
+ "tslib": "^2.x"
+ }
+ },
"ngx-sharebuttons": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/ngx-sharebuttons/-/ngx-sharebuttons-11.0.0.tgz",
diff --git a/angular/package.json b/angular/package.json
index d3d91df..abd0f1d 100644
--- a/angular/package.json
+++ b/angular/package.json
@@ -32,7 +32,9 @@
"firebase": "^9.9.3",
"google-libphonenumber": "^3.2.30",
"jsbarcode": "^3.11.5",
+ "libphonenumber-js": "^1.10.28",
"ng-qrcode": "^7.0.0",
+ "ngx-mat-intl-tel-input": "^5.0.0",
"ngx-sharebuttons": "^11.0.0",
"primeicons": "^5.0.0",
"primeng": "^14.0.1",
diff --git a/angular/proxy.confi.json b/angular/proxy.confi.json
new file mode 100644
index 0000000..d5a8fdc
--- /dev/null
+++ b/angular/proxy.confi.json
@@ -0,0 +1,38 @@
+{
+ "/api": {
+ "target": "https://apple-push-notifications.it-retail.tech/apns/api",
+ "secure": false,
+ "pathRewrite": {
+ "^/api": ""
+ },
+ "changeOrigin": true,
+ "logLevel": "debug"
+ },
+ "/icard-proxy": {
+ "target": "https://sakura.lk.crm4retail.ru/api/icard-proxy",
+ "secure": false,
+ "pathRewrite": {
+ "^/icard-proxy": ""
+ },
+ "changeOrigin": true,
+ "logLevel": "debug"
+ },
+ "/static": {
+ "target": "https://sakura.lk.crm4retail.ru/static",
+ "secure": false,
+ "pathRewrite": {
+ "^/static": ""
+ },
+ "changeOrigin": true,
+ "logLevel": "debug"
+ },
+ "/it-retail": {
+ "target": "https://sakura.lk.crm4retail.ru/it-retail",
+ "secure": false,
+ "pathRewrite": {
+ "^/it-retail": ""
+ },
+ "changeOrigin": true,
+ "logLevel": "debug"
+ }
+}
\ No newline at end of file
diff --git a/angular/src/app/app.module.ts b/angular/src/app/app.module.ts
index c48e111..be101cf 100644
--- a/angular/src/app/app.module.ts
+++ b/angular/src/app/app.module.ts
@@ -7,9 +7,9 @@ import { AppComponent } from './app.component';
import { MainComponent } from './pages/main/main.component';
import { NavbarComponent } from './components/navbar/navbar.component';
import { CardComponent } from './components/card/card.component';
-import {InputMaskModule} from "primeng/inputmask";
+import { InputMaskModule } from 'primeng/inputmask';
import { AuthComponent } from './pages/account/auth/auth.component';
-import {ProgressSpinnerModule} from "primeng/progressspinner";
+import { ProgressSpinnerModule } from 'primeng/progressspinner';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AccountComponent } from './pages/account/account.component';
import { ExitComponent } from './components/exit/exit.component';
@@ -23,17 +23,17 @@ import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFireMessagingModule } from '@angular/fire/compat/messaging';
-import {ToastModule} from 'primeng/toast';
+import { ToastModule } from 'primeng/toast';
import { MessageService } from 'primeng/api';
import { FooterButtonsComponent } from './components/footer-buttons/footer-buttons.component';
import { UserDataComponent } from './pages/account/user-data/user-data.component';
import { RefSystemComponent } from './pages/account/ref-system/ref-system.component';
-import { ShareButtonsModule } from 'ngx-sharebuttons/buttons';
+import { ShareButtonsModule } from 'ngx-sharebuttons/buttons';
import { ShareIconsModule } from 'ngx-sharebuttons/icons';
import { MessagingService } from './services/messaging.service';
import { NotFoundComponent } from './pages/not-found/not-found.component';
import { DownloadAppDirective } from './directives/download-app.directive';
-import {MatIconModule} from '@angular/material/icon';
+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';
@@ -42,6 +42,16 @@ import { InviteFriendsComponent } from './components/invite-friends/invite-frien
import { FooterComponent } from './components/footer/footer.component';
import { SocialMediaButtonsComponent } from './components/social-media-buttons/social-media-buttons.component';
import { LoginComponent } from './pages/login/login.component';
+import { NgxMatIntlTelInputComponent } from 'ngx-mat-intl-tel-input';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { FocusNextInputDirective } from './directives/focus-next-input.directive';
+import { MatSnackBarModule } from '@angular/material/snack-bar';
+import {
+ MAT_BOTTOM_SHEET_DATA,
+ MatBottomSheetModule,
+ MatBottomSheetRef,
+} from '@angular/material/bottom-sheet';
@NgModule({
declarations: [
@@ -66,7 +76,8 @@ import { LoginComponent } from './pages/login/login.component';
InviteFriendsComponent,
FooterComponent,
SocialMediaButtonsComponent,
- LoginComponent
+ LoginComponent,
+ FocusNextInputDirective,
],
imports: [
BrowserModule,
@@ -81,20 +92,31 @@ import { LoginComponent } from './pages/login/login.component';
enabled: environment.production,
// Register the ServiceWorker as soon as the application is stable
// or after 30 seconds (whichever comes first).
- registrationStrategy: 'registerWhenStable:30000'
+ registrationStrategy: 'registerWhenStable:30000',
}),
AngularFireModule.initializeApp(environment.firebase),
AngularFireMessagingModule,
ToastModule,
ReactiveFormsModule,
ShareButtonsModule.withConfig({
- debug: true
+ debug: true,
}),
ShareIconsModule,
MatIconModule,
- QrCodeModule
+ QrCodeModule,
+ NgxMatIntlTelInputComponent,
+ MatFormFieldModule,
+ MatInputModule,
+ MatSnackBarModule,
+ MatBottomSheetModule,
],
- providers: [DialogService, MessageService, MessagingService ],
- bootstrap: [AppComponent]
+ providers: [
+ DialogService,
+ MessageService,
+ MessagingService,
+ { provide: MatBottomSheetRef, useValue: {} },
+ { provide: MAT_BOTTOM_SHEET_DATA, useValue: {} },
+ ],
+ bootstrap: [AppComponent],
})
-export class AppModule { }
+export class AppModule {}
diff --git a/angular/src/app/components/exit/exit.component.html b/angular/src/app/components/exit/exit.component.html
index d28addb..cf977a7 100644
--- a/angular/src/app/components/exit/exit.component.html
+++ b/angular/src/app/components/exit/exit.component.html
@@ -1,13 +1,7 @@
-
-
Вы действительно хотите выйти?
-
- Да
-
-
- Нет
-
+
+ Вы действительно хотите выйти?
+
+
+ Нет
+ Да
diff --git a/angular/src/app/components/exit/exit.component.scss b/angular/src/app/components/exit/exit.component.scss
index 97f229d..c288335 100644
--- a/angular/src/app/components/exit/exit.component.scss
+++ b/angular/src/app/components/exit/exit.component.scss
@@ -1,9 +1,22 @@
+:host {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ .buttons-container {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ }
+}
+
button {
- margin-right: 1rem;
- padding: 4px 21px;
+ padding: 10px 62px;
margin-top: 8px;
background-color: var(--main-color);
color: #fff;
border-radius: 3px;
border: none;
+ width: calc(50% - 12px);
}
\ No newline at end of file
diff --git a/angular/src/app/components/exit/exit.component.ts b/angular/src/app/components/exit/exit.component.ts
index 1ad8e0b..70c4b59 100644
--- a/angular/src/app/components/exit/exit.component.ts
+++ b/angular/src/app/components/exit/exit.component.ts
@@ -1,19 +1,21 @@
-import { Component, OnInit } from '@angular/core';
-import { DynamicDialogRef } from 'primeng/dynamicdialog';
+import { Component } from '@angular/core';
+import { MatBottomSheetRef } from '@angular/material/bottom-sheet';
@Component({
selector: 'app-exit',
templateUrl: './exit.component.html',
- styleUrls: ['./exit.component.scss']
+ styleUrls: ['./exit.component.scss'],
})
export class ExitComponent {
-
constructor(
- public dialogRef: DynamicDialogRef
- ) { }
+ private _bottomSheetRef: MatBottomSheetRef
+ ) {}
- onClick(val: boolean): void {
- this.dialogRef.close(val);
+ rejection() {
+ this._bottomSheetRef.dismiss(false)
}
+ logout() {
+ this._bottomSheetRef.dismiss(true)
+ }
}
diff --git a/angular/src/app/components/navbar/navbar.component.html b/angular/src/app/components/navbar/navbar.component.html
index af71b4c..6717b43 100644
--- a/angular/src/app/components/navbar/navbar.component.html
+++ b/angular/src/app/components/navbar/navbar.component.html
@@ -1,5 +1,5 @@
diff --git a/angular/src/app/components/navbar/navbar.component.scss b/angular/src/app/components/navbar/navbar.component.scss
index 3e52122..dcd7a52 100644
--- a/angular/src/app/components/navbar/navbar.component.scss
+++ b/angular/src/app/components/navbar/navbar.component.scss
@@ -1,3 +1,7 @@
+:host {
+ width: 100%;
+}
+
.container {
box-sizing: border-box;
padding: 12px 16px;
diff --git a/angular/src/app/components/navbar/navbar.component.ts b/angular/src/app/components/navbar/navbar.component.ts
index c58fad0..f0300d0 100644
--- a/angular/src/app/components/navbar/navbar.component.ts
+++ b/angular/src/app/components/navbar/navbar.component.ts
@@ -1,4 +1,4 @@
-import { Component, Input, OnInit } from '@angular/core';
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'app-navbar[title]',
@@ -7,10 +7,15 @@ import { Component, Input, OnInit } from '@angular/core';
})
export class NavbarComponent implements OnInit {
@Input() title: string = 'Название не задано'
+ @Output() backEvent = new EventEmitter();
constructor() { }
ngOnInit(): void {
}
+ back() {
+ this.backEvent.emit(null)
+ }
+
}
diff --git a/angular/src/app/directives/focus-next-input.directive.spec.ts b/angular/src/app/directives/focus-next-input.directive.spec.ts
new file mode 100644
index 0000000..1253457
--- /dev/null
+++ b/angular/src/app/directives/focus-next-input.directive.spec.ts
@@ -0,0 +1,8 @@
+import { FocusNextInputDirective } from './focus-next-input.directive';
+
+describe('FocusNextInputDirective', () => {
+ it('should create an instance', () => {
+ const directive = new FocusNextInputDirective();
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/angular/src/app/directives/focus-next-input.directive.ts b/angular/src/app/directives/focus-next-input.directive.ts
new file mode 100644
index 0000000..3371901
--- /dev/null
+++ b/angular/src/app/directives/focus-next-input.directive.ts
@@ -0,0 +1,23 @@
+import { Directive, EventEmitter, Input, Renderer2 } from '@angular/core';
+
+@Directive({
+ selector: '[appFocusNextInput]'
+})
+export class FocusNextInputDirective {
+ @Input('appFocusNextInput') eventEmitter!: EventEmitter;
+
+ constructor(private renderer: Renderer2) { }
+
+ ngOnInit() {
+ this.eventEmitter.subscribe(elementId => {
+ try {
+ this.renderer.selectRootElement(elementId).focus();
+ this.renderer.selectRootElement(elementId).click();
+ } catch (ex) {
+ (document.activeElement as HTMLElement).blur();
+ // If the element doesn't exist or if the element disappears when this called then no need to do anything
+ }
+ });
+ }
+
+}
diff --git a/angular/src/app/pages/guest-card/guest-card.component.html b/angular/src/app/pages/guest-card/guest-card.component.html
index abf93cf..41df275 100644
--- a/angular/src/app/pages/guest-card/guest-card.component.html
+++ b/angular/src/app/pages/guest-card/guest-card.component.html
@@ -1,134 +1,153 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ За период с 11.01.2023 по 31.03.2023 вам начислено
+ 360 бонусов
+
+
+
+ Расчет начисления бонусов - 10% от суммы покупок за период с
+ 11.01.2023г. по 31.03.2023 г.
+
+
+ За период с 11.01.2023г. по 31.03.2023 г. сумма ваших покупок составила
+ 3700 руб.
+
+ Начисляемый бонус 10% от суммы покупок
+
+
+
+ Участник может использовать Бонусы для «оплаты» до 100% стоимости любой
+ покупки.
+
+
+ Списание Бонусов происходит из расчета 1:1 (один Бонус дает скидку 1
+ российский рубль / 1 тенге / 1 белорусский рубль. Скидка,
+ предоставляемая Участнику при списании Бонусов, уменьшает цену товаров в
+ заказе в соответствии с условиями ПЛ.
+
+
+ Для списания Бонусов Участник должен попросить об этом в кофе-баре сети
+ «COFFEE LIKE» кассира до момента пробития фискального чека, после чего
+ им будет проверена возможность списания Бонусов.
+
+
+ Для всех Участников возможно списание без использования мобильного
+ приложения.
+
+ Полученные Бонусы не подлежат обмену на денежные средства.
+
+
+
+ Начисленные на счет бонусы сгорают по прошествии 90 дней с момента
+ совершения последней покупки с начислением или списанием бонусов.
+
+
+
+ Возврат покупки, за которую бонусы были начислены:
+
+ В случае, если бонусов на счету достаточно для списания, бонусы
+ списываются в полном ранее начисленном за возвращаемый товар объеме.
+
+
+ В случае, если бонусов на счету недостаточно, формируется минусовой
+ баланс.
+
+
+
+
+ Возврат покупки, которая была оплачена бонусами:
+
+ В случае предъявления Участником кассового или товарного чека, сумма
+ бонусов, списанная для оплаты возвращаемого товара, зачисляется на
+ счет участника.
+
+
+ В случае возврата товара с применением оплаты бонусами, клиенту
+ возвращается денежная сумма в размере, внесенном Участником в оплату
+ товара при покупке, за вычетом суммы, оплаченной бонусами.
+
+
+
+
+
+ Сумма ваших покупок за период с 01.04.2023г. - 1200 руб.
+
+
+
+ Начисление Бонусных баллов происходит по дифференцированной шкале в
+ зависимости от уровня:
+
+
+
+ Уровень 1
+ Сумма покупок за предыдущий период 0-1600 руб.
+ Начисляемый бонус 3% от суммы покупки
+
+
+
+ Уровень 2
+ Сумма покупок за предыдущий период 1601-3600 руб.
+ Начисляемый бонус 6% от суммы покупки
+
+
+
+ Уровень 3
+ Сумма покупок за предыдущий период 3601-8600 руб.
+ Начисляемый бонус 10% от суммы покупки
+
+
+
+ Уровень 4
+ Сумма покупок за предыдущий период — от 8601 руб.
+ Начисляемый бонус, в % от суммы покупки - 15%
+
+
+
+
+
+ До следующего уровня за период с 01.04.2023 по 30.06.2023г осталось
+ совершить покупки на 401 рублей
+
+
+
+
Узнать условия начисления бонусов
+
+
+
+
+
+
+
+
+
+
Подробнее о правилах
+ Программы лояльности
-
- За период с 11.01.2023 по 31.03.2023 вам начислено 360 бонусов
-
-
-
- Расчет начисления бонусов - 10% от суммы покупок за период с 11.01.2023г.
- по 31.03.2023 г.
-
-
- За период с 11.01.2023г. по 31.03.2023 г. сумма ваших покупок составила
- 3700 руб.
-
- Начисляемый бонус 10% от суммы покупок
-
-
-
- Участник может использовать Бонусы для «оплаты» до 100% стоимости любой
- покупки.
-
-
- Списание Бонусов происходит из расчета 1:1 (один Бонус дает скидку 1
- российский рубль / 1 тенге / 1 белорусский рубль. Скидка, предоставляемая
- Участнику при списании Бонусов, уменьшает цену товаров в заказе в
- соответствии с условиями ПЛ.
-
-
- Для списания Бонусов Участник должен попросить об этом в кофе-баре сети
- «COFFEE LIKE» кассира до момента пробития фискального чека, после чего им
- будет проверена возможность списания Бонусов.
-
-
- Для всех Участников возможно списание без использования мобильного
- приложения.
-
- Полученные Бонусы не подлежат обмену на денежные средства.
-
-
-
- Начисленные на счет бонусы сгорают по прошествии 90 дней с момента
- совершения последней покупки с начислением или списанием бонусов.
-
-
-
- Возврат покупки, за которую бонусы были начислены:
-
- В случае, если бонусов на счету достаточно для списания, бонусы
- списываются в полном ранее начисленном за возвращаемый товар объеме.
-
-
- В случае, если бонусов на счету недостаточно, формируется минусовой
- баланс.
-
-
-
-
- Возврат покупки, которая была оплачена бонусами:
-
- В случае предъявления Участником кассового или товарного чека, сумма
- бонусов, списанная для оплаты возвращаемого товара, зачисляется на счет
- участника.
-
-
- В случае возврата товара с применением оплаты бонусами, клиенту
- возвращается денежная сумма в размере, внесенном Участником в оплату
- товара при покупке, за вычетом суммы, оплаченной бонусами.
-
-
-
-
-
- Сумма ваших покупок за период с 01.04.2023г. - 1200 руб.
-
-
-
- Начисление Бонусных баллов происходит по дифференцированной шкале в
- зависимости от уровня:
-
-
-
- Уровень 1
- Сумма покупок за предыдущий период 0-1600 руб.
- Начисляемый бонус 3% от суммы покупки
-
-
-
- Уровень 2
- Сумма покупок за предыдущий период 1601-3600 руб.
- Начисляемый бонус 6% от суммы покупки
-
-
-
- Уровень 3
- Сумма покупок за предыдущий период 3601-8600 руб.
- Начисляемый бонус 10% от суммы покупки
-
-
-
- Уровень 4
- Сумма покупок за предыдущий период — от 8601 руб.
- Начисляемый бонус, в % от суммы покупки - 15%
-
-
-
-
-
- До следующего уровня за период с 01.04.2023 по 30.06.2023г осталось
- совершить покупки на 401 рублей
-
-
-
-
Узнать условия начисления бонусов
-
-
-
-
-
-
-
-
-
- Подробнее о правилах Программы лояльности
-
+
diff --git a/angular/src/app/pages/guest-card/guest-card.component.ts b/angular/src/app/pages/guest-card/guest-card.component.ts
index 1ea6044..5c39173 100644
--- a/angular/src/app/pages/guest-card/guest-card.component.ts
+++ b/angular/src/app/pages/guest-card/guest-card.component.ts
@@ -1,5 +1,16 @@
import { Component, OnInit } from '@angular/core';
-import { IAccordionData } from 'src/app/components/accordion/accordion.component';
+import { MatBottomSheet } from '@angular/material/bottom-sheet';
+import { Router } from '@angular/router';
+import { Observable } from 'rxjs';
+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 moment from 'moment';
+
+interface Moment extends moment.Moment {
+
+}
@Component({
selector: 'app-guest-card',
@@ -9,15 +20,49 @@ import { IAccordionData } from 'src/app/components/accordion/accordion.component
export class GuestCardComponent implements OnInit {
public qrCodeSize: number = 85;
private isQrCodeClicked: boolean = false;
+ public customerInfo!: Observable
;
+ public purchases!: Observable;
public discountLevel: number = 4.2;
- constructor() {}
+ constructor(
+ private _bottomSheet: MatBottomSheet,
+ private cookiesService: CookiesService,
+ private router: Router,
+ private wpJsonService: WpJsonService
+ ) {}
- ngOnInit(): void {}
+ ngOnInit(): void {
+ const token = this.cookiesService.getItem('token')
+ this.customerInfo = this.wpJsonService.getCustomerInfo(environment.systemId, token || '', environment.icardProxy)
+ this.purchases = this.getPurchases()
+ // this.purchases.subscribe((value) => console.log(value));
+ }
qrCodeClick() {
this.isQrCodeClicked = !this.isQrCodeClicked;
this.qrCodeSize = this.isQrCodeClicked ? 180 : 85;
}
+
+ deleteToken(): void {
+ this.cookiesService.deleteCookie('token');
+ }
+
+ logout() {
+ const bottomSheet = this._bottomSheet.open(ExitComponent)
+ bottomSheet.afterDismissed().subscribe({
+ next: (val) => {
+ if (val) {
+ this.deleteToken();
+ this.router.navigate(['/login']);
+ }
+ }
+ })
+ }
+
+ getPurchases(start: Date | Moment = moment().startOf('month'), end: Date | Moment = moment()): Observable {
+ const token = this.cookiesService.getItem('token')
+ const delta = moment(end).diff(moment(start), 'days')
+ return this.wpJsonService.getTransactionsInfo(environment.systemId, token ?? '', environment.icardProxy)
+ }
}
diff --git a/angular/src/app/pages/login/login.component.html b/angular/src/app/pages/login/login.component.html
index 7f6f7f2..d05ebb6 100644
--- a/angular/src/app/pages/login/login.component.html
+++ b/angular/src/app/pages/login/login.component.html
@@ -1,26 +1,99 @@
+
Участвуй в программе лояльности COFFEE LIKE
Начни получать бонусы прямо сейчас
-
Введите код из SMS
-
- Не пришло SMS? Отправим повторно через секунд
+ Не пришло SMS? Отправим повторно через секунд
diff --git a/angular/src/app/pages/login/login.component.scss b/angular/src/app/pages/login/login.component.scss
index 2f200ea..431a4f6 100644
--- a/angular/src/app/pages/login/login.component.scss
+++ b/angular/src/app/pages/login/login.component.scss
@@ -7,6 +7,7 @@
margin: 0 auto 52px;
h1 {
+ margin-top: 20px;
width: 302px;
font-style: normal;
font-weight: 700;
@@ -106,24 +107,92 @@
font-weight: 700;
font-size: 17px;
line-height: 22px;
+ &:disabled {
+ background-color: #344a3a;
+ }
}
}
.code-form {
width: 100%;
- input {
- width: 100%;
- padding: 24px 16px 8px;
- background-color: #252323;
- margin-bottom: 16px;
- border: none;
- border-top: solid #6a737c 1px;
- border-bottom: solid #6a737c 1px;
- color: #6a737c;
- font-style: normal;
- font-weight: 400;
- font-size: 22px;
- line-height: 28px;
+ // input {
+ // width: 100%;
+ // padding: 24px 16px 8px;
+ // background-color: #252323;
+ // margin-bottom: 16px;
+ // border: none;
+ // border-top: solid #6a737c 1px;
+ // border-bottom: solid #6a737c 1px;
+ // color: #6a737c;
+ // font-style: normal;
+ // font-weight: 400;
+ // font-size: 22px;
+ // line-height: 28px;
+ // }
+ .inputs-container {
+ width: 102px;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ margin-bottom: 40px;
+
+ // code
+ .box {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 42px;
+ width: 42px;
+ border-radius: 6px;
+ // box-shadow: 0 0 6px 1px hsla(240, 54%, 61%, 0.2);
+ overflow: hidden;
+ will-change: transform;
+ }
+ .box:focus-within {
+ box-shadow: 0 0 6px 1px rgba($color: #28af49, $alpha: 0.2),
+ 0 0 0 2px rgba($color: #28af49, $alpha: 0.6);
+ }
+ .box::before,
+ .box::after {
+ content: "";
+ position: absolute;
+ height: 100%;
+ width: 100%;
+ top: 0;
+ left: 0;
+ border-radius: 6px;
+ overflow: hidden;
+ }
+ .box::before {
+ // background: hsl(240, 54%, 97%);
+ z-index: 1;
+ transition: background-color 450ms cubic-bezier(0.25, 0.01, 0.25, 1);
+ }
+ .box::after {
+ transform: translateY(100%);
+ background-color: hsl(145, 0%, 42%);
+ opacity: 0;
+ z-index: 10;
+ transition: transform 450ms cubic-bezier(0.25, 0.01, 0.25, 1),
+ opacity 450ms cubic-bezier(0.25, 0.01, 0.25, 1),
+ background-color 450ms cubic-bezier(0.25, 0.01, 0.25, 1);
+ }
+
+ .field {
+ position: relative;
+ border: 0;
+ outline: 0;
+ font-size: 25.21px;
+ line-height: 42px;
+ color: #fff;
+ background-color: transparent;
+ text-align: center;
+ z-index: 100;
+ }
+ .field::placeholder {
+ color: #fff;
+ }
}
}
@@ -133,5 +202,10 @@
font-size: 12px;
line-height: 16px;
text-align: center;
+ margin-top: 23px;
}
}
+
+mat-form-field {
+ width: 100%;
+}
diff --git a/angular/src/app/pages/login/login.component.ts b/angular/src/app/pages/login/login.component.ts
index a1ff1fc..0e31c2a 100644
--- a/angular/src/app/pages/login/login.component.ts
+++ b/angular/src/app/pages/login/login.component.ts
@@ -1,25 +1,158 @@
-import { Component, OnInit } from '@angular/core';
+import {
+ AfterViewInit,
+ Component,
+ EventEmitter,
+ HostListener,
+ OnInit
+} from '@angular/core';
+import { FormControl, FormGroup, Validators } from '@angular/forms';
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';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss'],
})
-export class LoginComponent implements OnInit {
- isShowNumber: boolean = true;
+export class LoginComponent implements OnInit, AfterViewInit {
+ public isShowNumber: boolean = true;
+ public phoneForm = new FormGroup({
+ name: new FormControl('', [Validators.required]),
+ phone: new FormControl('', [Validators.required]),
+ });
+ public codeForm = new FormGroup({
+ code: new FormControl('', [Validators.required]),
+ code1: new FormControl('', [Validators.required]),
+ code2: new FormControl('', [Validators.required]),
+ code3: new FormControl('', [Validators.required]),
+ });
+ private inputIds = ['field', 'field1', 'field2', 'field3'];
- constructor(private cookiesService: CookiesService, private router: Router) {}
+ constructor(
+ private cookiesService: CookiesService,
+ private router: Router,
+ private jsonrpc: JsonrpcService,
+ private messageService: MessageService
+ ) {}
ngOnInit(): void {}
+ ngAfterViewInit() {
+ setTimeout(() => {
+ this.inputFocusEmitter.emit(`#${this.inputIds[0]}`);
+ }, 1000)
+ }
+
+ public inputFocusEmitter = new EventEmitter();
+
+ @HostListener('window:keyup', ['$event'])
+ HandlKeyEvents(event: any) {
+ if (!event.target.classList.contains('field')) return;
+ const key = event.key.toLocaleLowerCase();
+ let elementId = '';
+
+ switch (key) {
+ case 'backspace':
+ elementId = event.target.id;
+ event.target.value = '';
+ const prevInputIndex = this.inputIds.indexOf(elementId) - 1;
+ if (prevInputIndex >= 0) {
+ this.inputFocusEmitter.emit(`#${this.inputIds[prevInputIndex]}`);
+ }
+ break;
+
+ default:
+ 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);
+
+ }
+ if (nextInputIndex > 0 && nextInputIndex <= this.inputIds.length) {
+ this.inputFocusEmitter.emit(`#${this.inputIds[nextInputIndex]}`);
+ }
+ break;
+ }
+ }
+
submitNumber() {
+ const data = this.phoneForm.value;
+ console.log(data);
this.isShowNumber = false;
+ this.jsonrpc.rpc({
+ method: 'sendVerifyByPhone',
+ params: [data.phone]
+ }, RpcService.authService, false).subscribe({
+ next: (result) => {
+ if (result.code === -1) {
+ this.messageService.add({
+ severity: 'error',
+ summary: 'Произошла ошибка, попробуйте позже!',
+ });
+ }
+ // if (result.code === 0) {
+ // this.isCodeConfirm = true;
+ // this.timeLeft = 60;
+ // const interval = setInterval(() => {
+ // if(this.timeLeft > 0) {
+ // this.timeLeft--;
+ // } else {
+ // clearInterval(interval);
+ // }
+ // },1000)
+ // }
+ // this.loading = false;
+ this.isShowNumber = false;
+ },
+ error: (error) => {
+ console.error('Error: ', error);
+
+ }
+ }
+ );
+ setTimeout(() => {
+ this.inputFocusEmitter.emit(`#${this.inputIds[0]}`);
+ }, 0)
}
submitCode() {
- this.cookiesService.setCookie('token', 'test')
- this.router.navigate(['/'])
+ 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.router.navigate(['/'], {
+ queryParams: {
+ token: result?.data?.token
+ },
+ });
+ // this.phoneConfirmed.emit(null);
+ } else {
+ // this.errorConfirmCode = true;
+
+ }
+ },
+ error: (error) => {
+ console.error(error);
+
+ }
+ }
+ );
+ }
+
+ backToPhoneForm() {
+ this.codeForm.setValue({
+ code: '',
+ code1: '',
+ code2: '',
+ code3: ''
+ })
+ this.isShowNumber = true
}
}
diff --git a/angular/src/app/services/wp-json.service.ts b/angular/src/app/services/wp-json.service.ts
index 9071beb..4e91efe 100644
--- a/angular/src/app/services/wp-json.service.ts
+++ b/angular/src/app/services/wp-json.service.ts
@@ -42,7 +42,27 @@ export class WpJsonService {
return this._request(`products/${id}`, 'GET');
}
- _request(path: string, method: string, body?: any, auth = false): Observable {
+ getCustomerInfo(systemId: string, token: string, url: string): Observable {
+ return this._request(`customer_info/${systemId}/${token}/`, 'GET', null, false, url)
+ }
+
+ getTransactions(systemId: string, token: string, url: string, delta?: number): Observable {
+ return this._request(`trans/${systemId}/${token}/${delta || ''}`, 'GET', null, false, url)
+ }
+
+ getTransactionsInfo(systemId: string, token: string, url: string, delta?: number): Observable {
+ return this._request(`purchase/${systemId}/${token}/${delta || ''}`, 'GET', null, false, url)
+ }
+
+ // getSiteConfig(): Observable {
+ // return this._request(`/assets/site-config.json`, 'GET', null, false)
+ // }
+
+ // getSiteConfigFromIiko(): Observable {
+ // return this._request(`/static/settings.json`, 'GET', null, false)
+ // }
+
+ _request(path: string, method: string, body?: any, auth = false, baseUrl?: string): Observable {
const token = decodeURI(this.cookiesService.getItem('token') ?? '');
let headers = new HttpHeaders();
headers = headers.set('Content-Type', 'application/json');
@@ -56,8 +76,10 @@ export class WpJsonService {
body: this.body,
};
- const url = environment.production ? window.location.origin + '/wp-json/woofood/v1/' : this.api
-
+ let url = environment.production ? window.location.origin + '/' : this.api
+ if (baseUrl) {
+ url = baseUrl
+ }
return this.http
.request( method, url + path + urlToken, options);
}
diff --git a/angular/src/environments/environment.prod.ts b/angular/src/environments/environment.prod.ts
index ca311d1..86f5ab5 100644
--- a/angular/src/environments/environment.prod.ts
+++ b/angular/src/environments/environment.prod.ts
@@ -6,7 +6,7 @@ export const environment = {
appBonusEndpoint: 'https://customerapi2.mi.crm4retail.ru/json.rpc/',
appWPEndpoint: 'http://213.239.210.240:4500/wp-json/woofood/v1/',
hasBonusProgram: true,
- systemId: 'g6zyv8tj53w28ov7cl',
+ systemId: 'tsQ2cu59Xz9qgGTm3z',
defaultUrl: 'https://coffee-like.lk.crm4retail.ru',
firebase: {
apiKey: "AIzaSyCnKvln5itnrBj62POCPHxshAN_Vmd0zds",
@@ -19,6 +19,7 @@ export const environment = {
},
version: packageJson.version,
appleWalletEndpoint: 'https://apple-push-notifications.it-retail.tech/apns/api',
+ icardProxy: 'https://coffee-like.lk.crm4retail.ru/api/icard-proxy/',
appleWalletSecret: 'Token F5mbzEERAznGKVbB6l',
clientName: 'coffeeLike'
}
diff --git a/angular/src/environments/environment.ts b/angular/src/environments/environment.ts
index 6059fbc..060fb78 100644
--- a/angular/src/environments/environment.ts
+++ b/angular/src/environments/environment.ts
@@ -6,7 +6,7 @@ export const environment = {
appBonusEndpoint: 'https://customerapi2.mi.crm4retail.ru/json.rpc/',
appWPEndpoint: 'http://192.168.0.179:4200/wp-json/woofood/v1/',
hasBonusProgram: true,
- systemId: 'g6zyv8tj53w28ov7cl',
+ systemId: 'tsQ2cu59Xz9qgGTm3z',
defaultUrl: 'http://192.168.0.179:4200',
firebase: {
apiKey: 'AIzaSyCnKvln5itnrBj62POCPHxshAN_Vmd0zds',
@@ -19,6 +19,7 @@ export const environment = {
},
version: packageJson.version,
appleWalletEndpoint: 'http://192.168.0.179:4200/apns/api',
+ icardProxy: 'http://192.168.0.14:4200/icard-proxy/',
appleWalletSecret: 'Token F5mbzEERAznGKVbB6l',
clientName: 'coffeeLike'
};
diff --git a/angular/src/styles.scss b/angular/src/styles.scss
index d7d2e69..9a2ffb2 100644
--- a/angular/src/styles.scss
+++ b/angular/src/styles.scss
@@ -30,6 +30,55 @@ hr {
border-top: 1px solid#BDBDBD;
}
+.mat-form-field-wrapper {
+ padding: 0;
+}
+
+.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: #28af49;
+}
+
+.mat-focused .mat-form-field-label {
+ color: #fff !important;
+}
+
+.mat-form-field-invalid .mat-form-field-outline > div {
+ border-color: red;
+}
+
+.country-list-button {
+ color: #fff !important;
+}
+
+.mat-menu-panel {
+ background: #231f20;
+ border-radius: 0;
+}
+
+.country-selector {
+ opacity: 1 !important;
+ display: none !important;
+}
+
+.ngx-floating .country-selector {
+ display: block !important;
+}
+
+.country-selector-code {
+ color: #fff;
+}
+
+
qr-code canvas {
transition: all 0.3s ease 0s;
}