diff --git a/angular.json b/angular.json
index b05325a..2c03be9 100644
--- a/angular.json
+++ b/angular.json
@@ -25,12 +25,18 @@
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
- "src/assets"
+ "src/assets",
+ "src/manifest.webmanifest"
],
"styles": [
+ "node_modules/primeng/resources/themes/bootstrap4-light-blue/theme.css",
+ "node_modules/primeicons/primeicons.css",
+ "node_modules/primeng/resources/primeng.min.css",
"src/styles.scss"
],
- "scripts": []
+ "scripts": [],
+ "serviceWorker": true,
+ "ngswConfigPath": "ngsw-config.json"
},
"configurations": {
"production": {
@@ -38,7 +44,7 @@
{
"type": "initial",
"maximumWarning": "500kb",
- "maximumError": "1mb"
+ "maximumError": "2mb"
},
{
"type": "anyComponentStyle",
@@ -93,7 +99,9 @@
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
- "src/assets"
+ "src/firebase-messaging-sw.js",
+ "src/assets",
+ "src/manifest.webmanifest"
],
"styles": [
"src/styles.scss"
@@ -103,5 +111,8 @@
}
}
}
+ },
+ "cli": {
+ "analytics": false
}
}
diff --git a/ngsw-config.json b/ngsw-config.json
new file mode 100644
index 0000000..f8bf210
--- /dev/null
+++ b/ngsw-config.json
@@ -0,0 +1,30 @@
+{
+ "$schema": "./node_modules/@angular/service-worker/config/schema.json",
+ "index": "/index.html",
+ "assetGroups": [
+ {
+ "name": "app",
+ "installMode": "prefetch",
+ "resources": {
+ "files": [
+ "/favicon.ico",
+ "/index.html",
+ "/manifest.webmanifest",
+ "/*.css",
+ "/*.js"
+ ]
+ }
+ },
+ {
+ "name": "assets",
+ "installMode": "lazy",
+ "updateMode": "prefetch",
+ "resources": {
+ "files": [
+ "/assets/**",
+ "/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"
+ ]
+ }
+ }
+ ]
+}
diff --git a/package.json b/package.json
index 4ca2d7a..924fd7d 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"version": "0.0.0",
"scripts": {
"ng": "ng",
- "start": "ng serve",
+ "start": "ng serve --host 192.168.0.179",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
@@ -14,18 +14,30 @@
"@angular/common": "^14.0.0",
"@angular/compiler": "^14.0.0",
"@angular/core": "^14.0.0",
+ "@angular/fire": "^7.4.1",
"@angular/forms": "^14.0.0",
"@angular/platform-browser": "^14.0.0",
"@angular/platform-browser-dynamic": "^14.0.0",
"@angular/router": "^14.0.0",
+ "@angular/service-worker": "^14.0.0",
+ "@types/uuid": "^8.3.4",
+ "angular-moment-timezone": "^1.7.1",
+ "barcode-2-svg": "^0.3.3",
+ "firebase": "^9.9.3",
+ "google-libphonenumber": "^3.2.30",
+ "jsbarcode": "^3.11.5",
+ "primeicons": "^5.0.0",
+ "primeng": "^14.0.1",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
+ "uuid": "^8.3.2",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "^14.0.6",
"@angular/cli": "~14.0.6",
"@angular/compiler-cli": "^14.0.0",
+ "@types/google-libphonenumber": "^7.4.23",
"@types/jasmine": "~4.0.0",
"jasmine-core": "~4.1.0",
"karma": "~6.3.0",
diff --git a/src/app/app.component.html b/src/app/app.component.html
index e11ca59..0680b43 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,484 +1 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ title }} app is running!
-
-
-
-
-
-
-
Resources
-
Here are some links to help you get started:
-
-
-
-
-
Next Steps
-
What do you want to do next with your app?
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
ng generate component xyz
-
ng add @angular/material
-
ng add @angular/pwa
-
ng add _____
-
ng test
-
ng build
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/app/app.constants.ts b/src/app/app.constants.ts
new file mode 100644
index 0000000..797898e
--- /dev/null
+++ b/src/app/app.constants.ts
@@ -0,0 +1,51 @@
+import {OrderStatus, Page, PageCode} from "./interface/data";
+
+export const PageList: Page[] = [
+ {
+ code: PageCode.Auth,
+ name: 'Вход',
+ resName: 'auth',
+ onSideBar: false,
+ },
+ {
+ code: PageCode.Orders,
+ name: 'Заказы',
+ resName: 'orders',
+ onSideBar: true,
+ },
+];
+
+export const PageListWithBonus: Page[] = [
+ {
+ code: PageCode.Auth,
+ name: 'Вход',
+ resName: 'auth',
+ onSideBar: false,
+ },
+ {
+ code: PageCode.Orders,
+ name: 'Заказы',
+ resName: 'orders',
+ onSideBar: true,
+ },
+ {
+ code: PageCode.BonusProgram,
+ name: 'Бонусная карта',
+ resName: 'bonus-program',
+ onSideBar: true,
+ },
+];
+
+export const orderStatuses: OrderStatus = {
+ 'Cancelled': 'Отменен',
+ 'InProcessing': 'В обработке',
+ 'Unconfirmed': 'Принят',
+ 'WaitCooking': 'Принят',
+ 'ReadyForCooking': 'Принят',
+ 'CookingStarted': 'Готовится',
+ 'CookingCompleted': 'Приготовлен',
+ 'Waiting': 'В пути',
+ 'OnWay': 'В пути',
+ 'Delivered': 'Выполнен',
+ 'Closed': 'Выполнен',
+};
\ No newline at end of file
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index b1c6c96..91f0198 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,18 +1,72 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
+import { RouterModule } from '@angular/router';
import { AppRoutingModule } from './app-routing.module';
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 { AuthComponent } from './pages/account/auth/auth.component';
+import {ProgressSpinnerModule} from "primeng/progressspinner";
+import { FormsModule } from '@angular/forms';
+import { AccountComponent } from './pages/account/account.component';
+import { ExitComponent } from './components/exit/exit.component';
+import { HttpClientModule } from '@angular/common/http';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { DialogService } from 'primeng/dynamicdialog';
+import { BonusProgramComponent } from './pages/account/bonus-program/bonus-program.component';
+import { OrdersComponent } from './pages/account/orders/orders.component';
+import { OrderInfoComponent } from './components/order-info/order-info.component';
+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 { MessageService } from 'primeng/api';
+import { FooterButtonsComponent } from './components/footer-buttons/footer-buttons.component';
@NgModule({
declarations: [
- AppComponent
+ AppComponent,
+ NavbarComponent,
+ MainComponent,
+ CardComponent,
+ AuthComponent,
+ AccountComponent,
+ ExitComponent,
+ BonusProgramComponent,
+ OrdersComponent,
+ OrderInfoComponent,
+ FooterButtonsComponent,
],
imports: [
BrowserModule,
- AppRoutingModule
+ AppRoutingModule,
+ RouterModule.forRoot([
+ {
+ path: '**',
+ component: MainComponent
+ }
+ ]),
+ InputMaskModule,
+ ProgressSpinnerModule,
+ FormsModule,
+ HttpClientModule,
+ BrowserAnimationsModule,
+ BrowserModule,
+ ServiceWorkerModule.register('ngsw-worker.js', {
+ enabled: environment.production,
+ // Register the ServiceWorker as soon as the application is stable
+ // or after 30 seconds (whichever comes first).
+ registrationStrategy: 'registerWhenStable:30000'
+ }),
+ AngularFireModule.initializeApp(environment.firebase),
+ AngularFireMessagingModule,
+ ToastModule,
],
- providers: [],
+ providers: [DialogService, MessageService],
bootstrap: [AppComponent]
})
export class AppModule { }
diff --git a/src/app/components/card/card.component.html b/src/app/components/card/card.component.html
new file mode 100644
index 0000000..f2fda25
--- /dev/null
+++ b/src/app/components/card/card.component.html
@@ -0,0 +1 @@
+card works!
diff --git a/src/app/components/card/card.component.scss b/src/app/components/card/card.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/components/card/card.component.spec.ts b/src/app/components/card/card.component.spec.ts
new file mode 100644
index 0000000..85f973b
--- /dev/null
+++ b/src/app/components/card/card.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CardComponent } from './card.component';
+
+describe('CardComponent', () => {
+ let component: CardComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ CardComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(CardComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/card/card.component.ts b/src/app/components/card/card.component.ts
new file mode 100644
index 0000000..07a9ab0
--- /dev/null
+++ b/src/app/components/card/card.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-card',
+ templateUrl: './card.component.html',
+ styleUrls: ['./card.component.scss']
+})
+export class CardComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/src/app/components/exit/exit.component.html b/src/app/components/exit/exit.component.html
new file mode 100644
index 0000000..d28addb
--- /dev/null
+++ b/src/app/components/exit/exit.component.html
@@ -0,0 +1,13 @@
+
+
Вы действительно хотите выйти?
+
+
+
diff --git a/src/app/components/exit/exit.component.scss b/src/app/components/exit/exit.component.scss
new file mode 100644
index 0000000..0d10b09
--- /dev/null
+++ b/src/app/components/exit/exit.component.scss
@@ -0,0 +1,9 @@
+button {
+ margin-right: 1rem;
+ padding: 4px 21px;
+ margin-top: 8px;
+ background-color: #009688;
+ color: #fff;
+ border-radius: 3px;
+ border: none;
+}
\ No newline at end of file
diff --git a/src/app/components/exit/exit.component.spec.ts b/src/app/components/exit/exit.component.spec.ts
new file mode 100644
index 0000000..8f802be
--- /dev/null
+++ b/src/app/components/exit/exit.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ExitComponent } from './exit.component';
+
+describe('ExitComponent', () => {
+ let component: ExitComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ExitComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(ExitComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/exit/exit.component.ts b/src/app/components/exit/exit.component.ts
new file mode 100644
index 0000000..1ad8e0b
--- /dev/null
+++ b/src/app/components/exit/exit.component.ts
@@ -0,0 +1,19 @@
+import { Component, OnInit } from '@angular/core';
+import { DynamicDialogRef } from 'primeng/dynamicdialog';
+
+@Component({
+ selector: 'app-exit',
+ templateUrl: './exit.component.html',
+ styleUrls: ['./exit.component.scss']
+})
+export class ExitComponent {
+
+ constructor(
+ public dialogRef: DynamicDialogRef
+ ) { }
+
+ onClick(val: boolean): void {
+ this.dialogRef.close(val);
+ }
+
+}
diff --git a/src/app/components/footer-buttons/footer-buttons.component.html b/src/app/components/footer-buttons/footer-buttons.component.html
new file mode 100644
index 0000000..44725e8
--- /dev/null
+++ b/src/app/components/footer-buttons/footer-buttons.component.html
@@ -0,0 +1,4 @@
+
diff --git a/src/app/components/footer-buttons/footer-buttons.component.scss b/src/app/components/footer-buttons/footer-buttons.component.scss
new file mode 100644
index 0000000..09c90c8
--- /dev/null
+++ b/src/app/components/footer-buttons/footer-buttons.component.scss
@@ -0,0 +1,23 @@
+:host {
+ position: fixed;
+ bottom: 16px;
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ .footer-buttons-container {
+ max-width: 400px;
+ width: 90vw;
+ &__button {
+ width: 100%;
+ height: 34px;
+ background: #197664;
+ color: #fff;
+ border-radius: 5px;
+ font-weight: 600;
+ letter-spacing: 2px;
+ border: none;
+ margin-top: 8px;
+ cursor: pointer;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/components/footer-buttons/footer-buttons.component.spec.ts b/src/app/components/footer-buttons/footer-buttons.component.spec.ts
new file mode 100644
index 0000000..b8cca38
--- /dev/null
+++ b/src/app/components/footer-buttons/footer-buttons.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { FooterButtonsComponent } from './footer-buttons.component';
+
+describe('FooterButtonsComponent', () => {
+ let component: FooterButtonsComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ FooterButtonsComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(FooterButtonsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/footer-buttons/footer-buttons.component.ts b/src/app/components/footer-buttons/footer-buttons.component.ts
new file mode 100644
index 0000000..1841683
--- /dev/null
+++ b/src/app/components/footer-buttons/footer-buttons.component.ts
@@ -0,0 +1,29 @@
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+
+@Component({
+ selector: 'app-footer-buttons',
+ templateUrl: './footer-buttons.component.html',
+ styleUrls: ['./footer-buttons.component.scss']
+})
+export class FooterButtonsComponent implements OnInit {
+ @Input() deferredPrompt: any;
+ @Input() token!: string;
+ @Input() isPermissionNotifications!: boolean;
+ @Output() downloadingPWA = new EventEmitter();
+ @Output() requestingPermission = new EventEmitter();
+
+ constructor(
+
+ ) { }
+
+ ngOnInit(): void {
+ }
+
+ downloadPWA() {
+ this.downloadingPWA.emit(null)
+ }
+
+ requestPermission() {
+ this.requestingPermission.emit(null)
+ }
+}
diff --git a/src/app/components/navbar/navbar.component.html b/src/app/components/navbar/navbar.component.html
new file mode 100644
index 0000000..43cf6ae
--- /dev/null
+++ b/src/app/components/navbar/navbar.component.html
@@ -0,0 +1,23 @@
+
+
+
Card Project
+
+
diff --git a/src/app/components/navbar/navbar.component.scss b/src/app/components/navbar/navbar.component.scss
new file mode 100644
index 0000000..ae5900c
--- /dev/null
+++ b/src/app/components/navbar/navbar.component.scss
@@ -0,0 +1,18 @@
+.container {
+ display: flex;
+ box-sizing: border-box;
+ padding: 12px 16px;
+ width: 100%;
+ flex-direction: row;
+ align-items: center;
+ white-space: nowrap;
+ height: 64px;
+ background: #008376;
+ color: #fff;
+}
+
+.title {
+ font-weight: 400;
+ font-size: 20px;
+ margin-left: 12px;
+}
\ No newline at end of file
diff --git a/src/app/components/navbar/navbar.component.spec.ts b/src/app/components/navbar/navbar.component.spec.ts
new file mode 100644
index 0000000..505cc2f
--- /dev/null
+++ b/src/app/components/navbar/navbar.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { NavbarComponent } from './navbar.component';
+
+describe('NavbarComponent', () => {
+ let component: NavbarComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ NavbarComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(NavbarComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/navbar/navbar.component.ts b/src/app/components/navbar/navbar.component.ts
new file mode 100644
index 0000000..6a9bec8
--- /dev/null
+++ b/src/app/components/navbar/navbar.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-navbar',
+ templateUrl: './navbar.component.html',
+ styleUrls: ['./navbar.component.scss']
+})
+export class NavbarComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/src/app/components/order-info/order-info.component.html b/src/app/components/order-info/order-info.component.html
new file mode 100644
index 0000000..52fc453
--- /dev/null
+++ b/src/app/components/order-info/order-info.component.html
@@ -0,0 +1,1070 @@
+
+
+ Заказ № {{ order.id }} был оформлен
+ {{
+ moment(order["date_created"]).format("DD.MM.YYYY")
+ }}
+
+
+ Статус: {{ formatStatus(order.status) }}
+
+
+
Статус заказа:
+
{{ formatStatus(order.status) }}
+
+
+
+
1,
+ cancelled: order.status === 'Cancelled'
+ }"
+ id="0"
+ >
+
+
+
+
2
+ }"
+ id="1"
+ >
+
+
+
3
+ }"
+ id="2"
+ >
+
+
+
4
+ }"
+ id="3"
+ >
+
+
+
5
+ }"
+ id="4"
+ >
+
+
+
+
+
+
+
+ Информация о заказе
+
+
+
+
+ | Товар |
+ Итого |
+
+
+
+
+
+ |
+ {{ item.name }}
+ × {{ item.amount }}
+
+ |
+
+
+ {{
+ order.currency_symbol
+ }}{{ item.price }}
+ |
+
+
+
+
+ | Доставка: |
+
+ {{
+ order.currency_symbol
+ }}{{ order.shipping.total }} ({{ order.shipping.name }})
+ |
+
+
+ | Метод оплаты: |
+
+
+ Оплата картой |
+
+
+ Оплата наличными |
+
+
+
+
+ | Итого: |
+
+ {{
+ order.currency_symbol
+ }}{{ order.total }}
+ |
+
+
+
+
+
+
+ Адрес доставки
+
+ {{ order.address.city ? order.address.city + ", " : ""
+ }}{{ order.address.street }} {{ order.address.house }} кв.
+ {{ order.address.flat }}
+
+
+
diff --git a/src/app/components/order-info/order-info.component.scss b/src/app/components/order-info/order-info.component.scss
new file mode 100644
index 0000000..81a87c0
--- /dev/null
+++ b/src/app/components/order-info/order-info.component.scss
@@ -0,0 +1,98 @@
+.woocommerce-MyAccount-content {
+ max-width: 400px;
+ margin-left: calc(50vw - 200px);
+}
+.container-progressbar {
+ width: 80%;
+ transform: translate(0, 0);
+ margin: 18px 10% 90px;
+}
+.steps {
+ position: relative;
+ display: flex;
+ justify-content: space-between;
+ width: 100%;
+}
+.step {
+ width: 20px;
+ height: 20px;
+ background: #fff;
+ border: 2px solid #acaca6;
+ border-radius: 50%;
+ transition: background 1s;
+ position: relative;
+ .status-image {
+ width: 80px;
+ height: 80px;
+ position: absolute;
+ top: 25px;
+ left: -32px;
+ }
+}
+.step.selected {
+ border: 2px solid #f9b004;
+}
+.step.completed {
+ border: 2px solid #f9b004;
+ background: #f9b004;
+}
+.step.cancelled {
+ background: #d7120b;
+ border: 2px solid #d7120b;
+}
+.progress {
+ position: absolute;
+ width: 100%;
+ height: 50%;
+ border-bottom: 2px solid #acaca6;
+ z-index: -1;
+}
+.percent {
+ position: absolute;
+ width: 0;
+ top: 2px;
+ height: 100%;
+ border-bottom: 2px solid #f9b004;
+ z-index: 1;
+ transition: width 1s;
+}
+p {
+ margin: 16px 0;
+}
+.woocommerce-order-details {
+ &__title {
+ font-weight: 600;
+ font-size: 18px;
+ }
+}
+.woocommerce-table {
+ border: 2px solid #dee2e6;
+ border-radius: 0.25rem;
+ border-collapse: separate;
+ text-align: left;
+ margin-top: 8px;
+ th {
+ font-weight: 600;
+ }
+ th, td {
+ padding: 0.7rem 1.5rem;
+ border-bottom: 2px solid #dee2e6;
+ }
+}
+.woocommerce-column {
+ &__title {
+ margin-top: 16px;
+ font-weight: 600;
+ font-size: 18px;
+ }
+}
+address {
+ border: 1px solid #dee2e6;
+ border-bottom-width: 2px;
+ border-right-width: 2px;
+ text-align: left;
+ width: 100%;
+ border-radius: 5px;
+ padding: 10px 12px;
+ margin-top: 8px;
+}
diff --git a/src/app/components/order-info/order-info.component.spec.ts b/src/app/components/order-info/order-info.component.spec.ts
new file mode 100644
index 0000000..8708beb
--- /dev/null
+++ b/src/app/components/order-info/order-info.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { OrderInfoComponent } from './order-info.component';
+
+describe('OrderInfoComponent', () => {
+ let component: OrderInfoComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ OrderInfoComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(OrderInfoComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/order-info/order-info.component.ts b/src/app/components/order-info/order-info.component.ts
new file mode 100644
index 0000000..a7ab234
--- /dev/null
+++ b/src/app/components/order-info/order-info.component.ts
@@ -0,0 +1,43 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { orderStatuses } from 'src/app/app.constants';
+import { AcceptedOrder, OrderProduct } from 'src/app/interface/data';
+import * as moment from 'moment-timezone';
+
+@Component({
+ selector: 'app-order-info',
+ templateUrl: './order-info.component.html',
+ styleUrls: ['./order-info.component.scss']
+})
+export class OrderInfoComponent implements OnInit {
+ @Input() order!: AcceptedOrder;
+ @Input() loadingStatus: boolean = false;
+ percent: number = 0;
+ readonly moment = moment;
+
+ constructor() { }
+
+ ngOnInit(): void {
+ this.setPercent();
+ }
+
+ setPercent() {
+ const statusIndex = this.getStatusIndex(this.order.status);
+ if (statusIndex !== -1 && statusIndex !== 0) {
+ this.percent = (statusIndex - 1) * 20;
+ }
+ }
+
+ formatStatus(status: string): string|undefined{
+ const key = Object.keys(orderStatuses).find((el) => status === el) ?? '';
+ return orderStatuses[key];
+ }
+
+ getStatusIndex(status: string) {
+ return [...new Set(Object.values(orderStatuses))].findIndex((value) => value === this.formatStatus(status));
+ }
+
+ getItemModifiersName(item: OrderProduct): string[]{
+ return Object.keys(item.modifiers);
+ }
+
+}
diff --git a/src/app/interface/data.ts b/src/app/interface/data.ts
new file mode 100644
index 0000000..a06a673
--- /dev/null
+++ b/src/app/interface/data.ts
@@ -0,0 +1,161 @@
+
+
+export enum PageCode {
+ Auth,
+ Orders,
+ BonusProgram
+}
+
+export interface Page {
+ code: PageCode;
+ component?: any;
+ name: string;
+ getMethod?: string;
+ resName?: string;
+ onSideBar: boolean
+}
+
+export interface BonusProgramAccount {
+ BonusProgramName: string;
+ BonusProgramTypeID: string;
+ CardNumber: number;
+ Bonuses: number;
+ HoldedBonuses: number;
+ BonusProgramAccounts: BonusProgramAccount[];
+ DateBonusBurn: string;
+ _links: any[];
+ _embedded: any;
+}
+
+export interface Purchase {
+ PurchaseId?: string;
+ CustomerId?: string;
+ PurchaseDate: string;
+ PurchaseState?: number;
+ CardNumber?: number;
+ Address?: string
+ CheckSummary?: number
+ BonusSummary?: number
+ ID: string;
+ Transactions: Transaction[];
+ IsSingleTransaction?: boolean;
+}
+
+export interface Transaction {
+ User: string;
+ Purchase: string;
+ Date: string;
+ Value: number;
+ TransactionType: number;
+ UserBonusesSnapshot: number;
+ BonusPercent: number;
+ DateActiveBonus: string;
+ AccountBonus: string;
+ Bonus: string;
+ ID:string;
+ HasPurchase?:boolean;
+}
+
+export interface OrderStatus{
+ [key: string]: string;
+}
+
+export interface DeliveryType {
+ cost: number;
+ title: string;
+ id: number;
+}
+
+export interface AcceptedOrder {
+ id: number;
+ status: string;
+ currency_symbol: string;
+ total: number;
+ address: {
+ city: string;
+ street: string;
+ house: number;
+ flat: number;
+ };
+ payment_method: string;
+ shipping: {
+ name: string;
+ total: number;
+ };
+ date_created: string;
+ items: OrderProduct[]
+}
+
+export interface Product{
+ id: number;
+ name: string;
+ price: string;
+ image_url: string;
+ image_gallery: string[];
+ category_id: number;
+ description?: string;
+ stock_status: string;
+ currency_symbol: string;
+ modifier_data: Modifier[];
+ short_description?: string;
+ guid?: string;
+}
+
+export interface Modifier{
+ id: number;
+ name: string;
+ category_type: string;
+ minimum_options: number;
+ maximum_options: number;
+ global_categories: string;
+ required: number;
+ options: Option[];
+ allOptions?: Option[];
+}
+
+export interface Option{
+ id: number;
+ name: string;
+ price: string;
+ prechecked: string;
+ active?: boolean;
+}
+
+export interface OrderProduct{
+ id: number;
+ amount: number;
+ name: string;
+ price: number;
+ modifiers: {
+ [name: string]: OrderModifier[]
+ }
+}
+
+export interface OrderModifier{
+ name: string;
+ id: number;
+ price: number;
+}
+
+export interface DeliveryData {
+ paymentMethod: PaymentMethod;
+ deliveryDate: Date | null;
+ deliveryType: DeliveryType | null;
+ persons: number;
+ comment: string;
+}
+
+export interface PaymentMethod {
+ type: string;
+ label: string;
+}
+
+export interface UserData {
+ first_name: string | null;
+ last_name: string | null;
+ street: string | null;
+ house: string | null;
+ flat: string | null;
+ city: string;
+ phone: string | null;
+}
\ No newline at end of file
diff --git a/src/app/models/order-product.ts b/src/app/models/order-product.ts
new file mode 100644
index 0000000..a99913c
--- /dev/null
+++ b/src/app/models/order-product.ts
@@ -0,0 +1,62 @@
+import {Modifier, Product} from "../interface/data";
+export class OrderProduct implements Product{
+
+
+ constructor(product: Product,guid: string, amount: number = 1) {
+ this.category_id = product.category_id;
+ this.currency_symbol = product.currency_symbol;
+ this.description = product.description;
+ this.id = product.id;
+ this.image_gallery = product.image_gallery;
+ this.image_url = product.image_url;
+ this.modifier_data = product.modifier_data;
+ this.name = product.name;
+ this.price = product.price;
+ this.stock_status = product.stock_status;
+ this.amount = amount;
+ this.guid = guid;
+ this.short_description = product.short_description;
+ }
+
+
+ public amount: number;
+ public category_id: number;
+ public currency_symbol: string;
+ public description?: string;
+ public short_description?: string;
+ public id: number;
+ public image_gallery: string[];
+ public image_url: string;
+ public modifier_data: Modifier[];
+ public name: string;
+ public price: string;
+ public stock_status: string;
+ public guid: string;
+
+
+ get finalPrice(): number{
+ const modifiersPrice = this.modifier_data.reduce((previousValue, currentValue) => {
+ return previousValue + currentValue.options.reduce((previousOptionValue, currentOptionValue) => {
+ return previousOptionValue + Number(currentOptionValue.price);
+ }, 0);
+ }, 0);
+ return (Number(this.price) + modifiersPrice) * this.amount;
+ new Date()
+ }
+
+ toJson(){
+ return {
+ id: this.id,
+ amount: this.amount,
+ name: this.name,
+ modifiers: this.modifier_data?.map(modifier => {
+ return {
+ id: modifier.id,
+ options: modifier.options,
+ }
+ }),
+ }
+ }
+
+
+}
diff --git a/src/app/models/order.ts b/src/app/models/order.ts
new file mode 100644
index 0000000..5d14cad
--- /dev/null
+++ b/src/app/models/order.ts
@@ -0,0 +1,68 @@
+import {DeliveryData, UserData} from "../interface/data";
+import {OrderProduct} from "./order-product";
+import * as moment from 'moment';
+import { CookiesService } from "../services/cookies.service";
+
+export interface OrderInfo {
+ products: OrderProduct[];
+ userData?: UserData;
+ deliveryData?: DeliveryData;
+ phone: string;
+ token: string | undefined;
+}
+
+export class Order {
+
+ public products: OrderProduct[];
+ public userData?: UserData;
+ public deliveryData?: DeliveryData;
+ public phone: string;
+ public token: string | undefined;
+
+ constructor(
+ orderInfo: OrderInfo
+ ) {
+ this.products = orderInfo.products;
+ this.userData = orderInfo.userData;
+ this.deliveryData = orderInfo.deliveryData;
+ this.phone = orderInfo.phone;
+ this.token = orderInfo.token;
+ }
+
+ get price(): number {
+ return this.products.reduce((previousValue, currentValue) => previousValue + currentValue.finalPrice, 0);
+ }
+
+ toJson(): any {
+ const date = moment(this.deliveryData?.deliveryDate ?? Date.now());
+ return {
+ items: this.products.map(product => {
+ return product.toJson();
+ }),
+ user_data: {
+ phone: this.phone,
+ ...this.userData
+ },
+ payment_method: this.deliveryData?.paymentMethod.type,
+ delivery_time: date.format('HH:mm'),
+ delivery_date: date.format("YYYY-MM-DD"),
+ delivery_instance_id: this.deliveryData?.deliveryType?.id,
+ persons: 1,
+ payments: [
+ {
+ type: this.deliveryData?.paymentMethod.type,
+ summ: this.price,
+ },
+ {
+ type: "crm4retail",
+ summ: 0,
+ payload: {
+ id: "c07a10d8-ba7e-43b0-92aa-ae470060bc7d"
+ }
+ }
+ ],
+ comment: this.deliveryData?.comment,
+ token: this.token
+ }
+ }
+}
diff --git a/src/app/pages/account/account.component.html b/src/app/pages/account/account.component.html
new file mode 100644
index 0000000..70f45f0
--- /dev/null
+++ b/src/app/pages/account/account.component.html
@@ -0,0 +1,34 @@
+
+
\ No newline at end of file
diff --git a/src/app/pages/account/account.component.scss b/src/app/pages/account/account.component.scss
new file mode 100644
index 0000000..f035246
--- /dev/null
+++ b/src/app/pages/account/account.component.scss
@@ -0,0 +1,36 @@
+:host {
+ .woocommerce {
+ min-height: calc(100vh - 64px);
+ padding: 24px 12px;
+ nav {
+ margin-bottom: 24px;
+ display: flex;
+ justify-content: center;
+ ul {
+ max-width: 400px;
+ width: 100%;
+ background: #161616;
+ border-radius: 6px;
+ display: flex;
+ justify-content: space-between;
+ li {
+ padding: 12px;
+ width: 100%;
+ white-space: nowrap;
+ text-align: center;
+ cursor: pointer;
+ &.is-active {
+ background-color: #009688;
+ }
+ &.first {
+ border-radius: 7px 0 0 7px;
+ }
+ a {
+ text-decoration: none;
+ color: #fff;
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/pages/account/account.component.ts b/src/app/pages/account/account.component.ts
new file mode 100644
index 0000000..9251fb8
--- /dev/null
+++ b/src/app/pages/account/account.component.ts
@@ -0,0 +1,102 @@
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import {CookiesService} from "../../services/cookies.service";
+import {ActivatedRoute, Router} from "@angular/router";
+import {Page, PageCode} from "../../interface/data";
+import {environment} from "../../../environments/environment";
+import {PageList, PageListWithBonus} from "../../app.constants";
+import {HttpErrorResponse} from "@angular/common/http";
+import {ExitComponent} from "../../components/exit/exit.component";
+import { DialogService, DynamicDialogRef } from 'primeng/dynamicdialog';
+
+@Component({
+ selector: 'app-account',
+ templateUrl: './account.component.html',
+ styleUrls: ['./account.component.scss'],
+ providers:[DialogService],
+})
+export class AccountComponent implements OnInit {
+ @Output() setUserDataOrderPage = new EventEmitter();
+
+ constructor(
+ private cookiesService: CookiesService,
+ private router: Router,
+ private route: ActivatedRoute,
+ private dialogService: DialogService,
+ ) {}
+
+ public currentPage!: Page;
+ public handleHttpErrorFunc = this.handleHttpError.bind(this);
+ private ref!: DynamicDialogRef;
+
+ readonly PageCode = PageCode;
+ readonly pageList = environment.hasBonusProgram ? PageListWithBonus : PageList;
+
+ ngOnInit(): void {
+ this.currentPage = this.getToken() ? this.pageList[2] : this.pageList[0];
+ document.body.classList.add('woocommerce-account', 'woocommerce-page', 'woocommerce-orders');
+ }
+
+ phoneConfirmed(): void{
+ this.currentPage = this.pageList[2];
+ }
+
+ changePage(event: MouseEvent, page: Page): void{
+ event.preventDefault();
+ this.currentPage = page;
+ }
+
+ handleHttpError(error: HttpErrorResponse): void {
+ if (error.status === 500) {
+ this.logout();
+ }
+ }
+
+ setToken(token: string): void{
+ this.cookiesService.setCookie('token', token);
+ }
+
+ getToken(): string|void{
+ return this.cookiesService.getItem('token');
+ }
+
+ deleteToken(): void{
+ this.cookiesService.deleteCookie('token');
+ this.router.navigate([''], {
+ queryParams: {},
+ });
+ }
+
+ logout(event?: MouseEvent){
+ if(event){
+ event.preventDefault();
+ }
+ this.ref = this.dialogService.open(ExitComponent, {
+ width: 'auto',
+ style: {
+ 'max-width': '90vw',
+ 'max-height': '90vh',
+ },
+ contentStyle: {
+ 'max-height': '90vh',
+ height: 'auto',
+ 'max-width': '90vw',
+ overflow: 'auto',
+ 'border-radius': '4px',
+ },
+ baseZIndex: 10000,
+ autoZIndex: true,
+ dismissableMask: true,
+ closeOnEscape: true,
+ showHeader: false,
+ });
+ this.ref.onClose.subscribe(
+ result => {
+ if (result) {
+ this.currentPage = this.pageList[0];
+ this.deleteToken();
+ }
+ }
+ );
+ }
+
+}
diff --git a/src/app/pages/account/auth/auth.component.html b/src/app/pages/account/auth/auth.component.html
new file mode 100644
index 0000000..e662b84
--- /dev/null
+++ b/src/app/pages/account/auth/auth.component.html
@@ -0,0 +1,94 @@
+
+Вход
+
+
+
+
+
+
diff --git a/src/app/pages/account/auth/auth.component.scss b/src/app/pages/account/auth/auth.component.scss
new file mode 100644
index 0000000..e62e405
--- /dev/null
+++ b/src/app/pages/account/auth/auth.component.scss
@@ -0,0 +1,52 @@
+:host{
+ .woocommerce-form-login__submit{
+ width: 150px;
+ }
+
+ h2 {
+ color: #fff;
+ text-align: center;
+ font-size: 24px;
+ margin-bottom: 16px;
+ }
+
+ .woocommerce-form {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+
+ .form-row {
+ width: 80%;
+ margin-bottom: 16px;
+ max-width: 400px;
+ .button {
+ width: 100%;
+ height: 37px;
+ background: #197664;
+ color: #fff;
+ border-radius: 5px;
+ font-weight: 600;
+ letter-spacing: 2px;
+ border: none;
+ }
+ label {
+ display:inline-block;
+ margin-bottom: 8px;
+ color: #fff;
+ }
+ .input-text {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
+ font-size: 1rem;
+ color: #495057;
+ background: #ffffff;
+ padding: 0.5rem 0.75rem;
+ border: 1px solid #ced4da;
+ transition: background-color 0.15s, border-color 0.15s, box-shadow 0.15s;
+ -webkit-appearance: none;
+ appearance: none;
+ border-radius: 4px;
+ width: 100%;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/pages/account/auth/auth.component.spec.ts b/src/app/pages/account/auth/auth.component.spec.ts
new file mode 100644
index 0000000..ce78535
--- /dev/null
+++ b/src/app/pages/account/auth/auth.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AuthComponent } from './auth.component';
+
+describe('AuthComponent', () => {
+ let component: AuthComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ AuthComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(AuthComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/pages/account/auth/auth.component.ts b/src/app/pages/account/auth/auth.component.ts
new file mode 100644
index 0000000..242a121
--- /dev/null
+++ b/src/app/pages/account/auth/auth.component.ts
@@ -0,0 +1,76 @@
+import { HttpErrorResponse } from '@angular/common/http';
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { CookiesService } from 'src/app/services/cookies.service';
+import { FormatPhoneService } from 'src/app/services/format-phone.service';
+import { JsonrpcService, RpcService } from 'src/app/services/jsonrpc.service';
+
+@Component({
+ selector: 'app-auth',
+ templateUrl: './auth.component.html',
+ styleUrls: ['./auth.component.scss']
+})
+export class AuthComponent {
+
+ @Input() handleHttpError!: (error: HttpErrorResponse) => void;
+ @Output() phoneConfirmed = new EventEmitter();
+ public phone: string = '';
+ public isCodeConfirm = false;
+ public code: string = '';
+ public phoneToConfirm!: string;
+ public loading = false;
+ public errorConfirmCode: boolean = false;
+
+ constructor(
+ private phoneFormatter: FormatPhoneService,
+ private jsonrpc: JsonrpcService,
+ private cookiesService: CookiesService,
+ private router: Router,
+ private route: ActivatedRoute,
+ ) {
+ }
+
+ getCode(event: SubmitEvent): void {
+ event.preventDefault();
+ this.loading = true;
+ this.phoneToConfirm = '+7' + this.phone.replace(/\D/g, '');
+ this.jsonrpc.rpc({
+ method: 'sendVerifyByPhone',
+ params: [this.phoneToConfirm]
+ }, RpcService.authService, false).subscribe({
+ next: (result) => {
+ if (result.code === 0) {
+ this.isCodeConfirm = true;
+ }
+ this.loading = false;
+ },
+ error: this.handleHttpError
+ }
+ );
+ }
+
+ confirmCode(event: SubmitEvent): void {
+ event.preventDefault();
+ this.jsonrpc.rpc({
+ method: 'getTokenByPhone',
+ params: [this.phoneToConfirm, this.code]
+ }, RpcService.authService, false).subscribe({
+ next: (result) => {
+ if (result.code === 0) {
+ this.cookiesService.setCookie('token', result?.data?.token);
+ this.router.navigate(['/auth'], {
+ queryParams: {
+ token: result?.data?.token
+ },
+ });
+ this.phoneConfirmed.emit(null);
+ } else {
+ this.errorConfirmCode = true;
+ }
+ },
+ error: this.handleHttpError
+ }
+ );
+ }
+
+}
diff --git a/src/app/pages/account/bonus-program/bonus-program.component.html b/src/app/pages/account/bonus-program/bonus-program.component.html
new file mode 100644
index 0000000..8cfac02
--- /dev/null
+++ b/src/app/pages/account/bonus-program/bonus-program.component.html
@@ -0,0 +1,63 @@
+
+
*Нажмите на карту, чтобы перевернуть её
+
+
+
+
+
+
+
Card Project
+
+
+
+
+
+
+
+
diff --git a/src/app/pages/account/bonus-program/bonus-program.component.scss b/src/app/pages/account/bonus-program/bonus-program.component.scss
new file mode 100644
index 0000000..07fbdc0
--- /dev/null
+++ b/src/app/pages/account/bonus-program/bonus-program.component.scss
@@ -0,0 +1,87 @@
+:host {
+ .woocommerce-MyAccount-content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ .card-content {
+ position: relative;
+ height: 200px;
+ width: 100%;
+ max-width: 400px;
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+ &__front, &__back {
+ display: block;
+ transition-timing-function: cubic-bezier(.175, .885, .32, 1.275);
+ transition-duration: .7s;
+ transition-property: transform, opacity;
+ color: #fff;
+ width: 100%;
+ height: 100%;
+ background: #fdfdfd;
+ border-radius: 12px;
+ border: solid #a3a3a3 1px;
+ box-shadow: 0 0 3px 1px #fff;
+ padding: 12px;
+ background-size: cover;
+ }
+ &__front {
+ transform: rotateY(0deg);
+ background-image: url(../../../../assets/background.svg);
+ }
+ &__back {
+ position: absolute;
+ opacity: 0;
+ top: 0px;
+ left: 0px;
+ transform: rotateY(-180deg);
+ background: #000;
+ }
+ &.active_back {
+ > .card-content__front {
+ transform: rotateY(180deg);
+ opacity: 0;
+ }
+ > .card-content__back {
+ opacity: 1;
+ transform: rotateY(0deg);
+ }
+ }
+ &__logo {
+ height: 30px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ .title {
+ color: #03d1be;
+ font-weight: 600;
+ letter-spacing: 2px;
+ }
+ }
+ &__footer {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-end;
+ position: absolute;
+ bottom: 12px;
+ width: calc(100% - 24px);
+ .count {
+ font-size: 22px;
+ }
+ }
+ &__barcode-container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100%;
+ }
+ }
+ .explanation {
+ font-size: 12px;
+ margin-bottom: 8px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/pages/account/bonus-program/bonus-program.component.spec.ts b/src/app/pages/account/bonus-program/bonus-program.component.spec.ts
new file mode 100644
index 0000000..bd4121d
--- /dev/null
+++ b/src/app/pages/account/bonus-program/bonus-program.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { BonusProgramComponent } from './bonus-program.component';
+
+describe('BonusProgramComponent', () => {
+ let component: BonusProgramComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ BonusProgramComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(BonusProgramComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/pages/account/bonus-program/bonus-program.component.ts b/src/app/pages/account/bonus-program/bonus-program.component.ts
new file mode 100644
index 0000000..a699a22
--- /dev/null
+++ b/src/app/pages/account/bonus-program/bonus-program.component.ts
@@ -0,0 +1,93 @@
+import { Component, OnInit } from '@angular/core';
+import { lastValueFrom } from 'rxjs';
+import { orderStatuses } from 'src/app/app.constants';
+import { BonusProgramAccount, Purchase, Transaction } from 'src/app/interface/data';
+import { JsonrpcService, RpcService } from 'src/app/services/jsonrpc.service';
+import * as moment from 'moment-timezone';
+import * as barcode from 'jsbarcode';
+
+@Component({
+ selector: 'app-bonus-program',
+ templateUrl: './bonus-program.component.html',
+ styleUrls: ['./bonus-program.component.scss']
+})
+export class BonusProgramComponent implements OnInit {
+
+ public accountData!: BonusProgramAccount;
+ public purchases: Purchase[] = [];
+ public loadingBonuses: boolean = false;
+ public isCardBack: boolean = false;
+ readonly orderStatuses = orderStatuses;
+ readonly moment = moment;
+
+ constructor(
+ private jsonrpc: JsonrpcService,
+ ) { }
+
+ ngOnInit(): void {
+ this.getAccountData();
+ }
+
+ rotateCard() {
+ this.isCardBack = !this.isCardBack
+ }
+
+ async getAccountData(): Promise{
+ this.loadingBonuses = true;
+ this.accountData = (await lastValueFrom(
+ this.jsonrpc.rpc({
+ method: 'GetAccounts',
+ params: []
+ },
+ RpcService.bonusService
+ )))['Cards'][0];
+
+ barcode("#barcode")
+ .options({font: "OCR-B"}) // Will affect all barcodes
+ .EAN13(`${this.accountData.CardNumber}`.padStart(12, "0"), {fontSize: 18, textMargin: 0})
+ .render();
+ console.log(this.accountData)
+ this.loadingBonuses = false;
+ const transactions: Transaction[] = (await lastValueFrom(
+ this.jsonrpc.rpc(
+ {
+ method: 'GetAccountTransactions',
+ params: []
+ },
+ RpcService.bonusService
+ )))['Transactions'];
+
+ const purchases: Purchase[] = (await lastValueFrom(
+ this.jsonrpc.rpc(
+ {
+ method: 'GetAccountPurchase',
+ params: []
+ },
+ RpcService.bonusService
+ )))['Purchases'];
+
+ this.purchases = purchases.map((purchase) => {
+ const id = purchase.ID.slice(0,36).toLowerCase();
+ purchase.Transactions = transactions.filter((transaction) => {
+ const same = transaction.Purchase === id;
+ transaction.HasPurchase = same;
+ return same;
+ });
+ return purchase;
+ });
+ transactions.forEach((transaction) => {
+ if(!transaction.HasPurchase){
+ this.purchases.push({
+ ID: transaction.ID,
+ PurchaseDate: transaction.Date,
+ Transactions: [transaction],
+ IsSingleTransaction: true,
+ })
+ }
+ });
+ this.purchases = this.purchases.sort((a,b) => {
+ return moment(a.PurchaseDate).date() - moment(b.PurchaseDate).date();
+ });
+ }
+
+}
diff --git a/src/app/pages/account/orders/orders.component.html b/src/app/pages/account/orders/orders.component.html
new file mode 100644
index 0000000..b368675
--- /dev/null
+++ b/src/app/pages/account/orders/orders.component.html
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+ {{
+ order.id
+ }}
+ |
+
+
+ |
+
+ {{ formatStatus(order.status) }}
+ |
+
+ {{
+ order.currency_symbol
+ }}{{ order.total }}
+ |
+
+ Просмотр
+ |
+
+
+
+
+ Показать больше
+
+
+
+ Нет заказов
+
+
+
+
+
+
diff --git a/src/app/pages/account/orders/orders.component.scss b/src/app/pages/account/orders/orders.component.scss
new file mode 100644
index 0000000..0bbf8c4
--- /dev/null
+++ b/src/app/pages/account/orders/orders.component.scss
@@ -0,0 +1,56 @@
+.show-more-orders {
+ text-align: center;
+ cursor: pointer;
+ color: #009688;
+ margin-top: 8px;
+}
+.woocommerce-MyAccount-content {
+ max-width: 400px;
+ margin-left: calc(50vw - 200px);
+}
+.woocommerce-orders-table {
+ border: 2px solid #dee2e6;
+ border-bottom: 0;
+ border-radius: 0.25rem;
+ border-collapse: separate;
+ text-align: left;
+ margin-top: 8px;
+ width: 100%;
+ thead {
+ display: none;
+ }
+ .woocommerce-orders-table {
+ &__cell {
+ padding: 0.7rem 1.5rem;
+ border-bottom: 2px solid #dee2e6;
+ text-align: right!important;
+ display: block;
+ &::before {
+ content: attr(data-title) ": ";
+ font-weight: 700;
+ float: left;
+ }
+ }
+ &__row {
+ display: block;
+ }
+ &__cell-order-actions::before {
+ display: none;
+ }
+ &__cell-order-number a {
+ text-decoration: none;
+ color: #009688;
+ }
+ }
+
+ .woocommerce-button {
+ display: inline-block;
+ color: #ffffff;
+ background-color: #009688;
+ padding: 13px;
+ border-radius: 4px;
+ text-decoration: none;
+ width: 100%;
+ text-align: center;
+ }
+}
\ No newline at end of file
diff --git a/src/app/pages/account/orders/orders.component.spec.ts b/src/app/pages/account/orders/orders.component.spec.ts
new file mode 100644
index 0000000..1e3b4d3
--- /dev/null
+++ b/src/app/pages/account/orders/orders.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { OrdersComponent } from './orders.component';
+
+describe('OrdersComponent', () => {
+ let component: OrdersComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ OrdersComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(OrdersComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/pages/account/orders/orders.component.ts b/src/app/pages/account/orders/orders.component.ts
new file mode 100644
index 0000000..af77717
--- /dev/null
+++ b/src/app/pages/account/orders/orders.component.ts
@@ -0,0 +1,98 @@
+import { HttpErrorResponse } from '@angular/common/http';
+import { Component, Input, OnInit } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { AcceptedOrder } from 'src/app/interface/data';
+import { WpJsonService } from 'src/app/services/wp-json.service';
+import * as moment from 'moment-timezone';
+import { orderStatuses } from 'src/app/app.constants';
+
+@Component({
+ selector: 'app-orders',
+ templateUrl: './orders.component.html',
+ styleUrls: ['./orders.component.scss']
+})
+export class OrdersComponent implements OnInit {
+ @Input() handleHttpError!: (error: HttpErrorResponse) => void;
+
+ public orders: AcceptedOrder[] = [];
+ public ordersShortArray: AcceptedOrder[] = [];
+ public lastViewOrder: number = 4;
+ public selectedOrder: AcceptedOrder|null = null;
+ public selectedOrderId: number|null = null;
+ public ordersLoadingStatus: boolean = true;
+ readonly moment = moment;
+ private timer!: any;
+
+ constructor(
+ private wpJson: WpJsonService,
+ private route: ActivatedRoute,
+ private router: Router,
+ ) { }
+
+ ngOnInit(): void {
+ this.getOrders();
+ this.route.queryParams.subscribe({
+ next: (queryParams:any) => {
+ this.setSelectedOrder(queryParams.order);
+ }
+ });
+ // this.requestTimer(1);
+ }
+
+ requestTimer(interval: number) {
+ this.timer = setInterval(() => {
+ if (this.permissionToRequest()) this.getOrders()
+ }, interval * 60000);
+ }
+
+ permissionToRequest() {
+ for (let order of this.ordersShortArray) {
+ if (order.status !== 'Delivered' && order.status !== 'Closed' && order.status !== 'Cancelled' ) {
+ return true
+ }
+ }
+ return false
+ }
+
+ getOrders(): void{
+ this.wpJson.getOrders().subscribe({
+ next: (result) => {
+ this.orders = result;
+ this.ordersShortArray = this.orders.slice(0, this.lastViewOrder);
+ this.setSelectedOrder(this.selectedOrderId);
+ },
+ error: this.handleHttpError
+ }
+ );
+ this.ordersLoadingStatus = false;
+ }
+
+ setSelectedOrder(orderId?:number|null): void{
+ this.selectedOrderId = orderId ?? null;
+ this.selectedOrder = this.orders.find((el) => el.id == this.selectedOrderId) ?? null;
+ }
+
+ showOrderDetails(event: MouseEvent, orderId: number): void{
+ event.preventDefault();
+ this.router.navigate([], {
+ relativeTo: this.route,
+ queryParams: {
+ order: orderId
+ },
+ queryParamsHandling: 'merge',
+ })
+ }
+
+ formatStatus(status: string): string|undefined{
+ const key = Object.keys(orderStatuses).find((el) => status === el) ?? '';
+ if (key === '') {
+ return orderStatuses['InProcessing']
+ }
+ return orderStatuses[key];
+ }
+
+ getMoreOrders() {
+ this.lastViewOrder += 4;
+ this.ordersShortArray = this.orders.slice(0, this.lastViewOrder);
+ }
+}
diff --git a/src/app/pages/main/main.component.html b/src/app/pages/main/main.component.html
new file mode 100644
index 0000000..249274b
--- /dev/null
+++ b/src/app/pages/main/main.component.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/src/app/pages/main/main.component.scss b/src/app/pages/main/main.component.scss
new file mode 100644
index 0000000..f26cc43
--- /dev/null
+++ b/src/app/pages/main/main.component.scss
@@ -0,0 +1,6 @@
+.main-container {
+ width: 100vw;
+ min-height: 100vh;
+ background-image: url(../../../assets/background.svg);
+ background-position: center;
+}
\ No newline at end of file
diff --git a/src/app/pages/main/main.component.ts b/src/app/pages/main/main.component.ts
new file mode 100644
index 0000000..9bec152
--- /dev/null
+++ b/src/app/pages/main/main.component.ts
@@ -0,0 +1,130 @@
+import { Component, ComponentRef, ElementRef, EmbeddedViewRef, OnInit, Renderer2, ViewContainerRef } from "@angular/core";
+import { AngularFireMessaging } from "@angular/fire/compat/messaging";
+import { ActivatedRoute } from "@angular/router";
+import { CardComponent } from "src/app/components/card/card.component";
+import { AccountComponent } from "../account/account.component";
+import {MessageService} from 'primeng/api';
+
+
+@Component({
+ selector: 'app-main',
+ templateUrl: './main.component.html',
+ styleUrls: ['./main.component.scss']
+})
+export class MainComponent implements OnInit {
+ private cardComponent!: ComponentRef;
+ private accountComponent!: ComponentRef;
+ public messagingToken!: string | null;
+ public deferredPrompt: any;
+ public isPermissionNotifications: boolean = false;
+ public token = ''
+
+ constructor(
+ private route: ActivatedRoute,
+ private viewContainerRef: ViewContainerRef,
+ private afMessaging: AngularFireMessaging,
+ public el: ElementRef,
+ public renderer: Renderer2,
+ private messageService: MessageService
+ ) {
+ renderer.listen('window', 'appinstalled', (evt) => {
+ console.log('INSTALLED!!!')
+ })
+ renderer.listen('window', 'beforeinstallprompt', (e) => {
+ e.preventDefault()
+ this.deferredPrompt = e
+ })
+ route.queryParams.subscribe( (params) => {
+ console.log('####: ', params)
+ this.token = params['token']
+ });
+ }
+
+ ngOnInit(): void {
+ this.appendAccount();
+ this.checkRequestPermission()
+ }
+
+ downloadPWA() {
+ this.deferredPrompt.prompt();
+ this.deferredPrompt.userChoice.then((res: any) => {
+ if (res.outcome === 'accepted') {
+ this.messageService.add({severity:'success', summary:'Спасибо за установку!'});
+ console.log('User Accepted!!!')
+ }
+ this.deferredPrompt = null;
+ })
+ }
+
+ checkRequestPermission() {
+ this.isPermissionNotifications = Notification.permission !== 'granted' ? false : true
+ }
+
+ requestPermission() {
+ if (!('serviceWorker' in navigator)) {
+ this.messageService.add({severity:'error', summary:'Не поддерживается в Вашем браузере!'});
+ return;
+ }
+
+ if (!('PushManager' in window)) {
+ // Браузер не поддерживает push-уведомления.
+ this.messageService.add({severity:'error', summary:'Не поддерживается в Вашем браузере!'});
+ return;
+ }
+ this.afMessaging.requestPermission.subscribe({
+ next: () => {
+ console.log('Permission granted! Save to the server!')
+ },
+ error: e => console.error(e)
+ })
+
+ this.afMessaging.requestToken.subscribe({
+ next: (token) => {
+ this.messagingToken = token;
+ if (this.messagingToken) {
+ this.messageService.add({severity:'success', summary:'Спасибо за подписку!'});
+ this.isPermissionNotifications = true;
+ }
+ console.log(token)
+ },
+ error: e => console.error(e)
+ })
+
+ }
+ // test function
+ copyMessage(val: string | null){
+ const selBox = document.createElement('textarea');
+ selBox.style.position = 'fixed';
+ selBox.style.left = '0';
+ selBox.style.top = '0';
+ selBox.style.opacity = '0';
+ if (val) selBox.value = val;
+ document.body.appendChild(selBox);
+ selBox.focus();
+ selBox.select();
+ document.execCommand('copy');
+ document.body.removeChild(selBox);
+ }
+
+ appendCard(): void {
+ const route = this.route.snapshot.url[0]?.path;
+ const element = document.getElementsByClassName('main-container');
+ if (!route && element[0]) {
+ this.cardComponent = this.viewContainerRef.createComponent(CardComponent);
+ const domElem = (this.cardComponent.hostView as EmbeddedViewRef)
+ .rootNodes[0] as HTMLElement;
+ element[0].appendChild(domElem);
+ }
+ }
+
+ appendAccount(): void {
+ const route = this.route.snapshot.url[0]?.path;
+ const element = document.getElementsByClassName('main-container');
+ if (element[0]) {
+ this.accountComponent = this.viewContainerRef.createComponent(AccountComponent);
+ const domElem = (this.accountComponent.hostView as EmbeddedViewRef)
+ .rootNodes[0] as HTMLElement;
+ element[0].appendChild(domElem);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/services/cookies.service.ts b/src/app/services/cookies.service.ts
new file mode 100644
index 0000000..3cb3675
--- /dev/null
+++ b/src/app/services/cookies.service.ts
@@ -0,0 +1,45 @@
+import { Injectable } from '@angular/core';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class CookiesService {
+
+ constructor() {}
+
+ getItem(key: string): string|undefined {
+ const matches = document.cookie.match(new RegExp(
+ '(?:^|; )' + key.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + '=([^;]*)'
+ ));
+ return matches ? decodeURIComponent(matches[1]) : undefined;
+ }
+
+ setCookie(key: string, value: string, options: any = {}): void {
+ const now = new Date();
+ const time = now.getTime();
+ const expireTime = time + 1000*36000*4*365*3;
+ now.setTime(expireTime);
+
+ options = { path: '/', ...options, expires: now.toUTCString() };
+
+ if (options.expires instanceof Date) {
+ options.expires = options.expires.toUTCString();
+ }
+
+ let updatedCookie = encodeURIComponent(key) + '=' + encodeURIComponent(value);
+
+ for (const optionKey of Object.keys(options)) {
+ updatedCookie += '; ' + optionKey;
+ const optionValue = options[optionKey];
+ if (optionValue !== true) {
+ updatedCookie += '=' + optionValue;
+ }
+ }
+
+ document.cookie = updatedCookie;
+ }
+
+ deleteCookie(key: string): void {
+ this.setCookie(key, '', { 'max-age': -1 });
+ }
+}
diff --git a/src/app/services/format-phone.service.ts b/src/app/services/format-phone.service.ts
new file mode 100644
index 0000000..59ecc97
--- /dev/null
+++ b/src/app/services/format-phone.service.ts
@@ -0,0 +1,31 @@
+import { Injectable } from '@angular/core';
+import { AsYouTypeFormatter } from 'google-libphonenumber';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class FormatPhoneService {
+
+ constructor() { }
+ formatPhoneNumber(phoneNumber: string): string{
+ const formatter = new AsYouTypeFormatter('RU');
+ if (!phoneNumber || phoneNumber.length < 2){
+ return '+7';
+ }
+ else{
+ let formattedNumber = '';
+ phoneNumber = phoneNumber.replace(/[^\d]/g, '');
+ phoneNumber = '+' + phoneNumber;
+ for (let i = 0; i < phoneNumber.length; i++) {
+ if (i === phoneNumber.length - 1){
+ formattedNumber = formatter.inputDigit(phoneNumber.charAt(i)).trim();
+ }
+ else {
+ formatter.inputDigit(phoneNumber.charAt(i));
+ }
+ }
+ formatter.clear();
+ return formattedNumber;
+ }
+ }
+}
diff --git a/src/app/services/jsonrpc.service.ts b/src/app/services/jsonrpc.service.ts
new file mode 100644
index 0000000..2d2feff
--- /dev/null
+++ b/src/app/services/jsonrpc.service.ts
@@ -0,0 +1,71 @@
+import { Injectable } from '@angular/core';
+import { environment } from 'src/environments/environment';
+import {HttpClient, HttpErrorResponse, HttpHeaders} from '@angular/common/http';
+import { Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
+import { CookiesService } from './cookies.service';
+import { v4 as uuidv4 } from 'uuid';
+
+export enum RpcService{
+ authService,
+ bonusService
+}
+
+export interface JsonRpcBody {
+ id: string;
+ jsonrpc: string;
+ method: string;
+ params: any;
+}
+
+@Injectable({
+ providedIn: 'root'
+})
+
+export class JsonrpcService {
+
+ protected readonly api = environment.appAuthEndpoint;
+ private jsonrpc = '2.0';
+ private body!: JsonRpcBody;
+
+ constructor(
+ private http: HttpClient,
+ private cookiesService: CookiesService
+ ) { }
+
+ rpc(data: {method: string, params: any[]},service: RpcService, auth = false): Observable {
+ let headers = new HttpHeaders();
+ headers = headers.set('Content-Type', 'application/json-rpc');
+ const options = {
+ headers: headers,
+ };
+ const token = decodeURI(this.cookiesService.getItem('token') ?? '');
+ switch (service) {
+ case RpcService.authService:
+ this.body = {
+ id: uuidv4(),
+ jsonrpc: this.jsonrpc,
+ method: data.method,
+ params: auth ? [environment.systemId, token, ...data.params] : [environment.systemId, ...data.params],
+ };
+ return this.http
+ .post(environment.appAuthEndpoint, this.body, options)
+ .pipe(map((res: any) => res.result[0]));
+ case RpcService.bonusService:
+ this.body = {
+ id: uuidv4(),
+ jsonrpc: this.jsonrpc,
+ method: data.method,
+ params: [token, ...data.params],
+ };
+ return this.http
+ .post(environment.appBonusEndpoint, this.body, options)
+ .pipe(map((res: any) => res.result));
+ }
+
+ }
+
+ handleHttpError(error: HttpErrorResponse): void {
+ console.log(error.message);
+ }
+}
diff --git a/src/app/services/messaging.service.ts b/src/app/services/messaging.service.ts
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/services/wp-json.service.ts b/src/app/services/wp-json.service.ts
new file mode 100644
index 0000000..9071beb
--- /dev/null
+++ b/src/app/services/wp-json.service.ts
@@ -0,0 +1,64 @@
+import { Injectable } from '@angular/core';
+import {environment} from "../../environments/environment";
+import {HttpClient, HttpHeaders} from "@angular/common/http";
+import {CookiesService} from "./cookies.service";
+import {Observable} from "rxjs";
+import {JsonRpcBody} from "./jsonrpc.service";
+import {DeliveryType, AcceptedOrder, Product} from "../interface/data";
+import {ActivatedRoute} from "@angular/router";
+import {Order} from "../models/order";
+
+export enum Method {
+
+}
+
+@Injectable({
+ providedIn: 'root'
+})
+export class WpJsonService {
+
+ protected readonly api = environment.appWPEndpoint;
+ private body!: JsonRpcBody;
+
+ constructor(
+ private http: HttpClient,
+ private cookiesService: CookiesService,
+ private route: ActivatedRoute,
+ ) { }
+
+ getDeliveryTypes(): Observable{
+ return this._request('orders/delivery-types', 'GET');
+ }
+
+ createOrder(order: any){
+ return this._request('orders', 'POST', order);
+ }
+
+ getOrders(): Observable{
+ return this._request('orders', 'GET', null, true);
+ }
+
+ getProductById(id: number): Observable{
+ return this._request(`products/${id}`, 'GET');
+ }
+
+ _request(path: string, method: string, body?: any, auth = false): Observable {
+ const token = decodeURI(this.cookiesService.getItem('token') ?? '');
+ let headers = new HttpHeaders();
+ headers = headers.set('Content-Type', 'application/json');
+ let urlToken = '';
+ if (token && token !== 'undefined' && auth) {
+ urlToken = '?token=' + token;
+ }
+ this.body = body;
+ const options = {
+ headers: headers,
+ body: this.body,
+ };
+
+ const url = environment.production ? window.location.origin + '/wp-json/woofood/v1/' : this.api
+
+ return this.http
+ .request( method, url + path + urlToken, options);
+ }
+}
diff --git a/src/assets/background.svg b/src/assets/background.svg
new file mode 100644
index 0000000..c4aa630
--- /dev/null
+++ b/src/assets/background.svg
@@ -0,0 +1,601 @@
+
+
+
diff --git a/src/assets/icons/apple-icon-180x180.png b/src/assets/icons/apple-icon-180x180.png
new file mode 100644
index 0000000..504c88d
Binary files /dev/null and b/src/assets/icons/apple-icon-180x180.png differ
diff --git a/src/assets/icons/icon-128x128.png b/src/assets/icons/icon-128x128.png
new file mode 100644
index 0000000..9f9241f
Binary files /dev/null and b/src/assets/icons/icon-128x128.png differ
diff --git a/src/assets/icons/icon-144x144.png b/src/assets/icons/icon-144x144.png
new file mode 100644
index 0000000..4a5f8c1
Binary files /dev/null and b/src/assets/icons/icon-144x144.png differ
diff --git a/src/assets/icons/icon-152x152.png b/src/assets/icons/icon-152x152.png
new file mode 100644
index 0000000..34a1a8d
Binary files /dev/null and b/src/assets/icons/icon-152x152.png differ
diff --git a/src/assets/icons/icon-192x192.png b/src/assets/icons/icon-192x192.png
new file mode 100644
index 0000000..9172e5d
Binary files /dev/null and b/src/assets/icons/icon-192x192.png differ
diff --git a/src/assets/icons/icon-384x384.png b/src/assets/icons/icon-384x384.png
new file mode 100644
index 0000000..e54e8d3
Binary files /dev/null and b/src/assets/icons/icon-384x384.png differ
diff --git a/src/assets/icons/icon-512x512.png b/src/assets/icons/icon-512x512.png
new file mode 100644
index 0000000..51ee297
Binary files /dev/null and b/src/assets/icons/icon-512x512.png differ
diff --git a/src/assets/icons/icon-72x72.png b/src/assets/icons/icon-72x72.png
new file mode 100644
index 0000000..2814a3f
Binary files /dev/null and b/src/assets/icons/icon-72x72.png differ
diff --git a/src/assets/icons/icon-96x96.png b/src/assets/icons/icon-96x96.png
new file mode 100644
index 0000000..d271025
Binary files /dev/null and b/src/assets/icons/icon-96x96.png differ
diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts
index 3612073..1be8439 100644
--- a/src/environments/environment.prod.ts
+++ b/src/environments/environment.prod.ts
@@ -1,3 +1,16 @@
export const environment = {
- production: true
-};
+ production: true,
+ appAuthEndpoint: 'https://testauth.crm4retail.ru/tnt',
+ appBonusEndpoint: 'https://customerapi2.mi.crm4retail.ru/json.rpc/',
+ appWPEndpoint: 'http://213.239.210.240:4500/wp-json/woofood/v1/',
+ hasBonusProgram: true,
+ systemId: 'dfe16ca16a3598b812',
+ firebase: {
+ apiKey: "AIzaSyCujHg9GtN8Uxi-JcCN8zggvXlfNQRKc04",
+ authDomain: "push-notification-test2-56dac.firebaseapp.com",
+ projectId: "push-notification-test2-56dac",
+ storageBucket: "push-notification-test2-56dac.appspot.com",
+ messagingSenderId: "1004369687552",
+ appId: "1:1004369687552:web:a6cc20625e05520a37d4e5"
+ }
+}
diff --git a/src/environments/environment.ts b/src/environments/environment.ts
index f56ff47..5d85430 100644
--- a/src/environments/environment.ts
+++ b/src/environments/environment.ts
@@ -1,16 +1,16 @@
-// This file can be replaced during build by using the `fileReplacements` array.
-// `ng build` replaces `environment.ts` with `environment.prod.ts`.
-// The list of file replacements can be found in `angular.json`.
-
export const environment = {
- production: false
+ production: false,
+ appAuthEndpoint: 'https://testauth.crm4retail.ru/tnt',
+ appBonusEndpoint: 'https://customerapi2.mi.crm4retail.ru/json.rpc/',
+ appWPEndpoint: 'http://192.168.0.179:4200/wp-json/woofood/v1/',
+ hasBonusProgram: true,
+ systemId: 'dfe16ca16a3598b812',
+ firebase: {
+ apiKey: "AIzaSyCujHg9GtN8Uxi-JcCN8zggvXlfNQRKc04",
+ authDomain: "push-notification-test2-56dac.firebaseapp.com",
+ projectId: "push-notification-test2-56dac",
+ storageBucket: "push-notification-test2-56dac.appspot.com",
+ messagingSenderId: "1004369687552",
+ appId: "1:1004369687552:web:a6cc20625e05520a37d4e5"
+ }
};
-
-/*
- * For easier debugging in development mode, you can import the following file
- * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
- *
- * This import should be commented out in production mode because it will have a negative impact
- * on performance if an error is thrown.
- */
-// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
diff --git a/src/firebase-messaging-sw.js b/src/firebase-messaging-sw.js
new file mode 100644
index 0000000..9427ec6
--- /dev/null
+++ b/src/firebase-messaging-sw.js
@@ -0,0 +1,13 @@
+importScripts('https://www.gstatic.com/firebasejs/7.4.1/firebase-app.js');
+importScripts('https://www.gstatic.com/firebasejs/7.4.1/firebase-messaging.js');
+
+firebase.initializeApp({
+ apiKey: "AIzaSyCujHg9GtN8Uxi-JcCN8zggvXlfNQRKc04",
+ authDomain: "push-notification-test2-56dac.firebaseapp.com",
+ projectId: "push-notification-test2-56dac",
+ storageBucket: "push-notification-test2-56dac.appspot.com",
+ messagingSenderId: "1004369687552",
+ appId: "1:1004369687552:web:a6cc20625e05520a37d4e5"
+});
+
+const messaging = firebase.messaging();
\ No newline at end of file
diff --git a/src/index.html b/src/index.html
index 216b0c7..c9c941d 100644
--- a/src/index.html
+++ b/src/index.html
@@ -5,9 +5,16 @@
CardProject
+
+
+
+
+
+
-
+
+
diff --git a/src/manifest.webmanifest b/src/manifest.webmanifest
new file mode 100644
index 0000000..cc41419
--- /dev/null
+++ b/src/manifest.webmanifest
@@ -0,0 +1,60 @@
+{
+ "name": "card-project",
+ "short_name": "card-project",
+ "theme_color": "#1976d2",
+ "background_color": "#fafafa",
+ "display": "standalone",
+ "scope": "./",
+ "start_url": "./",
+ "icons": [
+ {
+ "src": "assets/icons/icon-72x72.png",
+ "sizes": "72x72",
+ "type": "image/png",
+ "purpose": "maskable any"
+ },
+ {
+ "src": "assets/icons/icon-96x96.png",
+ "sizes": "96x96",
+ "type": "image/png",
+ "purpose": "maskable any"
+ },
+ {
+ "src": "assets/icons/icon-128x128.png",
+ "sizes": "128x128",
+ "type": "image/png",
+ "purpose": "maskable any"
+ },
+ {
+ "src": "assets/icons/icon-144x144.png",
+ "sizes": "144x144",
+ "type": "image/png",
+ "purpose": "maskable any"
+ },
+ {
+ "src": "assets/icons/icon-152x152.png",
+ "sizes": "152x152",
+ "type": "image/png",
+ "purpose": "maskable any"
+ },
+ {
+ "src": "assets/icons/icon-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "maskable any"
+ },
+ {
+ "src": "assets/icons/icon-384x384.png",
+ "sizes": "384x384",
+ "type": "image/png",
+ "purpose": "maskable any"
+ },
+ {
+ "src": "assets/icons/icon-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "maskable any"
+ }
+ ],
+ "gcm_sender_id": "1004369687552"
+}
diff --git a/src/styles.scss b/src/styles.scss
index 90d4ee0..b8359ef 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -1 +1,27 @@
-/* You can add global styles to this file, and also import other style files */
+// Сброс стилей
+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}
+article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}
+html{height:100%;color:#fff;}
+body{line-height:1}
+ol,ul{list-style:none}
+blockquote,q{quotes:none}
+blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}
+table{border-collapse:collapse;border-spacing:0}
+
+* {
+ font-family: 'Raleway', sans-serif;
+}
+
+.p-inputtext {
+ width: 100%;
+}
+
+mark {
+ padding: 4px;
+ background: #009688;
+ color: #fff;
+}
+
+::-webkit-scrollbar {
+ width: 0;
+}
\ No newline at end of file