Compare commits
61 Commits
master
...
fashion-lo
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a9f9fc872 | |||
| 7bb05324a9 | |||
| 5e3b211778 | |||
| e75999a3c1 | |||
| f8f500f612 | |||
| 72808c3c7c | |||
| efb8095e2f | |||
| 699db43b39 | |||
| 5152d9ad30 | |||
| da340475e0 | |||
| ef8ac5d24d | |||
| fa5d29e517 | |||
| 1a5fa44abc | |||
|
|
bedda578c8 | ||
|
|
44cf8d5074 | ||
|
|
ecdd4f103e | ||
| c0387d967d | |||
| b33ed15666 | |||
| c7ade7515c | |||
| e4bb1d8947 | |||
| c71e2d4c48 | |||
| 88b0d92300 | |||
| e570e82f90 | |||
| 85174c1fab | |||
| 7a895c76a6 | |||
| dbf01e4fc5 | |||
| 227392d7f6 | |||
| f8f2fe4673 | |||
| 4d16fa4184 | |||
| 5e69d6e5c5 | |||
|
|
a0de9cbb61 | ||
|
|
192a7a5d2f | ||
| dfd596cd56 | |||
| b92b1e73ce | |||
| 8ca151574a | |||
|
|
9f4447fa79 | ||
| 197c84f29c | |||
|
|
29d274e05b | ||
|
|
e558fcabc0 | ||
| 1ee13ab73d | |||
| 4414480d6e | |||
| 2ca121cbac | |||
| 25a5db7337 | |||
|
|
134ee3f59d | ||
|
|
914b1ec5ed | ||
|
|
86eaca953e | ||
|
|
a22479dffd | ||
|
|
bb455b2c45 | ||
|
|
9b64746c2e | ||
|
|
34080a0ee0 | ||
|
|
ff0f8d6fad | ||
|
|
988a05e94d | ||
|
|
5b9be577e7 | ||
|
|
615f708600 | ||
|
|
ba71eee97f | ||
|
|
06e0b8efe1 | ||
|
|
7a490e4599 | ||
|
|
8b6af5fa21 | ||
| 55486de524 | |||
|
|
836af4e1ae | ||
|
|
9352d06e73 |
58
.gitignore
vendored
@ -1,42 +1,42 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# Compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
/bazel-out
|
||||
angular/dist
|
||||
angular/tmp
|
||||
angular/out-tsc
|
||||
angular/bazel-out
|
||||
|
||||
# Node
|
||||
/node_modules
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
angular/node_modules
|
||||
angular/npm-debug.log
|
||||
angular/yarn-error.log
|
||||
|
||||
# IDEs and editors
|
||||
.idea/
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
angular/.idea/
|
||||
angular/.project
|
||||
angular/.classpath
|
||||
angular/.c9/
|
||||
angular/*.launch
|
||||
angular/.settings/
|
||||
angular/*.sublime-workspace
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
angular/.vscode/*
|
||||
angular/!.vscode/settings.json
|
||||
angular/!.vscode/tasks.json
|
||||
angular/!.vscode/launch.json
|
||||
angular/!.vscode/extensions.json
|
||||
angular/.history/*
|
||||
|
||||
# Miscellaneous
|
||||
/.angular/cache
|
||||
.sass-cache/
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
testem.log
|
||||
/typings
|
||||
angular/.angular/cache
|
||||
angular/.sass-cache/
|
||||
angular/connect.lock
|
||||
angular/coverage
|
||||
angular/libpeerconnection.log
|
||||
angular/testem.log
|
||||
angular/typings
|
||||
|
||||
# System files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
angular/.DS_Store
|
||||
angular/Thumbs.db
|
||||
|
||||
4
.vscode/extensions.json
vendored
@ -1,4 +0,0 @@
|
||||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
|
||||
"recommendations": ["angular.ng-template"]
|
||||
}
|
||||
20
.vscode/launch.json
vendored
@ -1,20 +0,0 @@
|
||||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "ng serve",
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "npm: start",
|
||||
"url": "http://localhost:4200/"
|
||||
},
|
||||
{
|
||||
"name": "ng test",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "npm: test",
|
||||
"url": "http://localhost:9876/debug.html"
|
||||
}
|
||||
]
|
||||
}
|
||||
42
.vscode/tasks.json
vendored
@ -1,42 +0,0 @@
|
||||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "start",
|
||||
"isBackground": true,
|
||||
"problemMatcher": {
|
||||
"owner": "typescript",
|
||||
"pattern": "$tsc",
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": {
|
||||
"regexp": "(.*?)"
|
||||
},
|
||||
"endsPattern": {
|
||||
"regexp": "bundle generation complete"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"isBackground": true,
|
||||
"problemMatcher": {
|
||||
"owner": "typescript",
|
||||
"pattern": "$tsc",
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": {
|
||||
"regexp": "(.*?)"
|
||||
},
|
||||
"endsPattern": {
|
||||
"regexp": "bundle generation complete"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
33
Jenkinsfile
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
env.HL_BUILD_MODE = "jenkins"
|
||||
|
||||
node('Lithium'){
|
||||
|
||||
stage('get new version to repo') {
|
||||
checkout scm
|
||||
if (lastCommitIsBumpCommit()) {
|
||||
currentBuild.result = 'ABORTED'
|
||||
error('Последний коммит - результат сборки jenkins')
|
||||
}
|
||||
sh "git checkout ${env.BRANCH_NAME}"
|
||||
sh "git checkout -- ."
|
||||
|
||||
sh "git pull"
|
||||
//sh "git submodule update --init --recursive"
|
||||
//sh "git submodule update --remote --merge"
|
||||
}
|
||||
stage("build and publish"){
|
||||
dir('angular'){
|
||||
sh label: '', script: 'npm i'
|
||||
sh label: '', script: 'npm run build'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean lastCommitIsBumpCommit() {
|
||||
lastCommit = sh([script: 'git log -1', returnStdout: true])
|
||||
if (lastCommit.contains("Author: jenkins")) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
{
|
||||
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
@ -10,6 +11,7 @@
|
||||
"style": "scss"
|
||||
}
|
||||
},
|
||||
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
@ -17,8 +19,8 @@
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "/var/www/lk/fashion-logica",
|
||||
"baseHref": "/fashion-logica/",
|
||||
"outputPath": "/var/www/html/lk.crm4retail.ru/fashion-logica",
|
||||
"baseHref": "/",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
@ -28,7 +30,9 @@
|
||||
"src/favicon.ico",
|
||||
"src/assets",
|
||||
"src/manifest.webmanifest",
|
||||
"src/firebase-messaging-sw.js"
|
||||
"src/firebase-messaging-sw.js",
|
||||
"src/sw-master.js",
|
||||
"src/sw-custom.js"
|
||||
],
|
||||
"styles": [
|
||||
"node_modules/primeng/resources/themes/bootstrap4-light-blue/theme.css",
|
||||
4
package-lock.json → angular/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "fashion-logica",
|
||||
"version": "0.0.0",
|
||||
"version": "0.0.2",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "fashion-logica",
|
||||
"version": "0.0.0",
|
||||
"version": "0.0.2",
|
||||
"dependencies": {
|
||||
"@angular/animations": "^14.0.0",
|
||||
"@angular/cdk": "^14.2.1",
|
||||
@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "fashion-logica",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.4",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve --host 192.168.0.179",
|
||||
"start": "ng serve --host 192.168.0.14",
|
||||
"build": "ng build",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"test": "ng test"
|
||||
@ -6,5 +6,5 @@ import { Component } from '@angular/core';
|
||||
styleUrls: ['./app.component.scss']
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'fashion-logica';
|
||||
title = 'Fashionlogica';
|
||||
}
|
||||
@ -49,7 +49,7 @@ export const PageListWithBonus: Page[] = [
|
||||
description: '',
|
||||
resName: 'ref-system',
|
||||
onSideBar: true,
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
export const orderStatuses: OrderStatus = {
|
||||
@ -32,6 +32,8 @@ import { QRCodeModule } from 'angularx-qrcode';
|
||||
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';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -47,7 +49,9 @@ import { MessagingService } from './services/messaging.service';
|
||||
OrderInfoComponent,
|
||||
FooterButtonsComponent,
|
||||
UserDataComponent,
|
||||
RefSystemComponent
|
||||
RefSystemComponent,
|
||||
NotFoundComponent,
|
||||
DownloadAppDirective
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
@ -56,7 +60,8 @@ import { MessagingService } from './services/messaging.service';
|
||||
{
|
||||
path: '**',
|
||||
component: MainComponent
|
||||
}
|
||||
},
|
||||
// { path: '**', component: NotFoundComponent }
|
||||
]),
|
||||
InputMaskModule,
|
||||
ProgressSpinnerModule,
|
||||
@ -64,7 +69,7 @@ import { MessagingService } from './services/messaging.service';
|
||||
HttpClientModule,
|
||||
BrowserAnimationsModule,
|
||||
BrowserModule,
|
||||
ServiceWorkerModule.register('ngsw-worker.js', {
|
||||
ServiceWorkerModule.register('/sw-master.js', {
|
||||
enabled: environment.production,
|
||||
// Register the ServiceWorker as soon as the application is stable
|
||||
// or after 30 seconds (whichever comes first).
|
||||
@ -1,12 +1,11 @@
|
||||
<div class="footer-buttons-container">
|
||||
<!-- *ngIf="deferredPrompt && token?.length" -->
|
||||
<button
|
||||
<!-- <button
|
||||
*ngIf="((deviceType == 'android' && deferredPrompt) || deviceType == 'ios') && token?.length"
|
||||
class="footer-buttons-container__button download"
|
||||
(click)="downloadPWA()"
|
||||
>
|
||||
<img src="./assets/download.svg" alt="download" />
|
||||
</button>
|
||||
</button> -->
|
||||
<button
|
||||
*ngIf="!isPermissionNotifications && token?.length"
|
||||
class="footer-buttons-container__button"
|
||||
@ -0,0 +1,24 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { MessageService } from 'primeng/api';
|
||||
|
||||
@Component({
|
||||
selector: 'app-footer-buttons',
|
||||
templateUrl: './footer-buttons.component.html',
|
||||
styleUrls: ['./footer-buttons.component.scss']
|
||||
})
|
||||
export class FooterButtonsComponent implements OnInit {
|
||||
@Input() token!: string;
|
||||
@Input() isPermissionNotifications!: boolean;
|
||||
@Output() requestingPermission = new EventEmitter<null>();
|
||||
public deviceType: 'ios' | 'android' | null = null;
|
||||
|
||||
constructor(
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
requestPermission() {
|
||||
this.requestingPermission.emit(null)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
import { DownloadAppDirective } from './download-app.directive';
|
||||
|
||||
describe('DownloadAppDirective', () => {
|
||||
it('should create an instance', () => {
|
||||
const directive = new DownloadAppDirective();
|
||||
expect(directive).toBeTruthy();
|
||||
});
|
||||
});
|
||||
85
angular/src/app/directives/download-app.directive.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import {
|
||||
Directive,
|
||||
ElementRef,
|
||||
HostListener,
|
||||
OnInit,
|
||||
Renderer2,
|
||||
} from '@angular/core';
|
||||
import { MessageService } from 'primeng/api';
|
||||
|
||||
@Directive({
|
||||
selector: '[appDownloadApp]',
|
||||
})
|
||||
export class DownloadAppDirective implements OnInit {
|
||||
public deviceType: 'ios' | 'android' | null = null;
|
||||
public deferredPrompt: any;
|
||||
|
||||
constructor(
|
||||
private messageService: MessageService,
|
||||
public renderer: Renderer2,
|
||||
private el: ElementRef
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getTypeDevice();
|
||||
if (this.deviceType === 'ios') {
|
||||
this.el.nativeElement.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('window:beforeinstallprompt', ['$event'])
|
||||
onBeforeInstallPrompt(e: any) {
|
||||
e.preventDefault();
|
||||
this.deferredPrompt = e;
|
||||
if (this.deferredPrompt) {
|
||||
this.el.nativeElement.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('window:appinstalled', ['$event'])
|
||||
onAppInstalled(e: any) {
|
||||
// Prevent Chrome 67 and earlier from automatically showing the prompt
|
||||
e.preventDefault();
|
||||
// Stash the event so it can be triggered later.
|
||||
this.deferredPrompt = e;
|
||||
this.el.nativeElement.style.display = 'none';
|
||||
}
|
||||
|
||||
getTypeDevice() {
|
||||
const userAgent = window.navigator.userAgent.toLowerCase();
|
||||
const ios = /iphone|ipod|ipad/.test(userAgent);
|
||||
this.deviceType = ios ? 'ios' : 'android';
|
||||
}
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
downloadApp(event: MouseEvent) {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
if (this.deviceType === 'ios') {
|
||||
this.messageService.add({
|
||||
severity: 'custom',
|
||||
summary: `Для установки нажмите на кнопку поделиться в Вашем браузере и выберите пункт 'На экран «Домой»'`,
|
||||
life: 5000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!this.deferredPrompt) {
|
||||
this.messageService.add({
|
||||
severity: 'error',
|
||||
summary: 'Не поддерживается в Вашем браузере!',
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.deferredPrompt.prompt();
|
||||
this.deferredPrompt.userChoice.then((res: any) => {
|
||||
if (res.outcome === 'accepted') {
|
||||
this.messageService.add({
|
||||
severity: 'custom',
|
||||
summary: 'Спасибо за установку!',
|
||||
});
|
||||
}
|
||||
this.deferredPrompt = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,9 @@
|
||||
<div class="woocommerce">
|
||||
<div
|
||||
[ngClass]="{
|
||||
woocommerce: true,
|
||||
'auth-page': currentPage.code === PageCode.Auth
|
||||
}"
|
||||
>
|
||||
<div
|
||||
*ngIf="currentPage.code !== PageCode.Auth"
|
||||
class="top-left-attribute"
|
||||
@ -40,6 +45,7 @@
|
||||
>
|
||||
<div class="container">
|
||||
<img
|
||||
style="width: 36px"
|
||||
src="{{ './assets/menu-icons/' + page.resName + '.png' }}"
|
||||
alt="Иконка меню"
|
||||
/>
|
||||
@ -50,6 +56,22 @@
|
||||
</div>
|
||||
</li>
|
||||
</ng-container>
|
||||
<li
|
||||
class="woocommerce-MyAccount-navigation-link download-app"
|
||||
appDownloadApp
|
||||
>
|
||||
<div class="container">
|
||||
<img
|
||||
style="width: 36px"
|
||||
src="./assets/menu-icons/download-app.png"
|
||||
alt="Иконка меню"
|
||||
/>
|
||||
<div class="menu-item-info">
|
||||
<a href="#">Установить приложение</a>
|
||||
<!-- <p>{{ page.description }}</p> -->
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="woocommerce-MyAccount-navigation-link"
|
||||
(click)="logout($event)"
|
||||
@ -66,8 +88,7 @@
|
||||
<span
|
||||
class="version"
|
||||
[ngClass]="{
|
||||
version: true,
|
||||
bottom: currentPage.code === PageCode.Auth
|
||||
version: true
|
||||
}"
|
||||
>
|
||||
v{{ version }}
|
||||
@ -2,11 +2,19 @@
|
||||
.woocommerce {
|
||||
min-height: calc(100vh - 39px);
|
||||
padding: 20px 18px;
|
||||
|
||||
&.auth-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
nav {
|
||||
margin-bottom: 24px;
|
||||
margin-top: 26px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
ul {
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
@ -14,6 +22,7 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
|
||||
li {
|
||||
padding: 12px;
|
||||
width: 100%;
|
||||
@ -25,20 +34,29 @@
|
||||
box-shadow: 0px 0px 5px rgb(0 0 0 / 15%);
|
||||
color: #000;
|
||||
border-radius: 15px;
|
||||
|
||||
&.is-active {
|
||||
border: solid #09467f 1px;
|
||||
// display: none;
|
||||
}
|
||||
|
||||
&.first {
|
||||
// border-radius: 7px 0 0 7px;
|
||||
}
|
||||
|
||||
&.download-app {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
|
||||
.menu-item-info {
|
||||
margin-left: 16px;
|
||||
& > a {
|
||||
|
||||
&>a {
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-size: 18px;
|
||||
@ -48,7 +66,8 @@
|
||||
display: block;
|
||||
text-align-last: left;
|
||||
}
|
||||
& > p {
|
||||
|
||||
&>p {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
@ -58,11 +77,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li:nth-child(odd) {
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.top-left-attribute {
|
||||
width: 10px;
|
||||
height: 5px;
|
||||
@ -71,12 +92,9 @@
|
||||
position: absolute;
|
||||
top: 69px;
|
||||
}
|
||||
|
||||
.version {
|
||||
opacity: 0.5;
|
||||
&.bottom {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,7 @@ import { ExitComponent } from '../../components/exit/exit.component';
|
||||
import { DialogService, DynamicDialogRef } from 'primeng/dynamicdialog';
|
||||
import { JsonrpcService, RpcService } from 'src/app/services/jsonrpc.service';
|
||||
import { MessageService } from 'primeng/api';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-account',
|
||||
@ -70,10 +71,24 @@ export class AccountComponent implements OnInit {
|
||||
this.currentPage = this.pageList[1];
|
||||
}
|
||||
|
||||
refSystem() {
|
||||
async refSystem() {
|
||||
const additionalInfo = (await lastValueFrom(
|
||||
this.jsonRpcService.rpc({
|
||||
method: 'getAdditionalInfo',
|
||||
params: []
|
||||
}, RpcService.authService, true)
|
||||
)).data
|
||||
this.route.queryParams.subscribe((params) => {
|
||||
if (params['refCardNumber']) {
|
||||
this.refSystemId = params['refCardNumber'];
|
||||
if (params['refUserId']) {
|
||||
if (additionalInfo.refSystem?.code.length) {
|
||||
this.messageService.add({
|
||||
severity: 'custom',
|
||||
summary:
|
||||
'Вы уже зарегестрированы в реферальной программе!',
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.refSystemId = params['refUserId'];
|
||||
this.jsonRpcService
|
||||
.rpc(
|
||||
{
|
||||
@ -93,7 +108,7 @@ export class AccountComponent implements OnInit {
|
||||
next: () => {
|
||||
this.router.navigate([], {
|
||||
queryParams: {
|
||||
refCardNumber: null,
|
||||
refUserId: null,
|
||||
},
|
||||
queryParamsHandling: 'merge',
|
||||
});
|
||||
@ -117,6 +132,10 @@ export class AccountComponent implements OnInit {
|
||||
|
||||
changePage(event: MouseEvent, page: Page): void {
|
||||
event.preventDefault();
|
||||
if (page.resName === 'download-app') {
|
||||
|
||||
return
|
||||
}
|
||||
this.currentPage = page;
|
||||
// let params = new HttpParams();
|
||||
// params = params.append('activePage', this.currentPage.code);
|
||||
@ -40,7 +40,7 @@
|
||||
></p-progressSpinner>
|
||||
</button>
|
||||
</p>
|
||||
<div class="decoration-pattern" style="background: url('./assets/card-decorative-pattern.png') no-repeat;"></div>
|
||||
<div class="decoration-pattern"></div>
|
||||
</form>
|
||||
</ng-container>
|
||||
<ng-template #confirmPhoneField>
|
||||
@ -54,8 +54,7 @@
|
||||
class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide"
|
||||
>
|
||||
<label for="code">
|
||||
Введите 4 последних цифры позвонившего вам номера телефона. На звонок
|
||||
отвечать не нужно.
|
||||
Введите 4 цифры из смс, которое пришло на Ваш номер телефона
|
||||
</label>
|
||||
<input
|
||||
pInputText
|
||||
@ -94,6 +93,6 @@
|
||||
<p style="color: red; margin: 0" *ngIf="errorConfirmCode">
|
||||
Пароль введен неверно
|
||||
</p>
|
||||
<div class="decoration-pattern" style="background: url('./assets/card-decorative-pattern.png') no-repeat;"></div>
|
||||
<div class="decoration-pattern"></div>
|
||||
</form>
|
||||
</ng-template>
|
||||
@ -102,5 +102,8 @@
|
||||
.decoration-pattern {
|
||||
width: calc(100% - 24px);
|
||||
height: 34px;
|
||||
background-image: url('../../../../assets/card-decorative-pattern.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
}
|
||||
@ -11,22 +11,19 @@
|
||||
<!-- <div class="imgs-row"></div>
|
||||
<div class="imgs-row" style="background-position-x: -22px;"></div>
|
||||
<div class="imgs-row"></div> -->
|
||||
<img src="./assets/card-decorative-pattern.svg" alt="" />
|
||||
<img src="./assets/card-decorative-pattern.png" alt="" />
|
||||
</div>
|
||||
<div class="card-container__content">
|
||||
<div class="info">
|
||||
<div *ngIf="accountData" class="row">
|
||||
<span class="key">Имя</span>
|
||||
<span class="value" *ngIf="userName.length">{{
|
||||
userName
|
||||
<span class="value">{{
|
||||
userName && userName.length ? userName : 'Не задано'
|
||||
}}</span>
|
||||
<span class="value" *ngIf="!userName.length"
|
||||
>Не задано</span
|
||||
>
|
||||
</div>
|
||||
<div *ngIf="accountData" class="row">
|
||||
<span class="key">Баланс карты</span>
|
||||
<span class="value">{{ accountData.Bonuses }}</span>
|
||||
<span class="value">{{ bonuses }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-container__barcode-container">
|
||||
@ -47,4 +44,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button *ngIf="deviceType == 'ios'" class="add-to-wallet" (click)="addCardToWallet($event)">Добавить в Apple Wallet</button>
|
||||
</div>
|
||||
@ -3,14 +3,14 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&>h2 {
|
||||
& > h2 {
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
&>p {
|
||||
& > p {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 15px;
|
||||
@ -154,12 +154,12 @@
|
||||
}
|
||||
|
||||
&.active_back {
|
||||
>.card-content__front {
|
||||
> .card-content__front {
|
||||
transform: rotateY(180deg);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
>.card-content__back {
|
||||
> .card-content__back {
|
||||
opacity: 1;
|
||||
transform: rotateY(0deg);
|
||||
}
|
||||
@ -196,5 +196,16 @@
|
||||
font-size: 12px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.add-to-wallet {
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
background: #09467f;
|
||||
border-color: #09467f;
|
||||
color: #fff;
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
margin: 12px auto 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,192 @@
|
||||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import {
|
||||
orderStatuses,
|
||||
PageList,
|
||||
PageListWithBonus,
|
||||
} from 'src/app/app.constants';
|
||||
import {
|
||||
BonusProgramAccount,
|
||||
Page,
|
||||
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';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { AppleWalletService } from 'src/app/services/apple-wallet.service';
|
||||
import { CookiesService } from 'src/app/services/cookies.service';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
import { MessageService } from 'primeng/api';
|
||||
|
||||
@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;
|
||||
readonly orderStatuses = orderStatuses;
|
||||
readonly moment = moment;
|
||||
readonly pageList = environment.hasBonusProgram
|
||||
? PageListWithBonus
|
||||
: PageList;
|
||||
public currentPage: Page = this.pageList[1];
|
||||
public userName: string = '';
|
||||
public deviceType: 'ios' | 'android' | null = null;
|
||||
public bonuses: number = 0
|
||||
|
||||
constructor(
|
||||
private jsonrpc: JsonrpcService,
|
||||
private appleWallet: AppleWalletService,
|
||||
private cookiesService: CookiesService,
|
||||
@Inject(DOCUMENT) private document: Document,
|
||||
private http: HttpClient,
|
||||
private messageService: MessageService,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getAccountData();
|
||||
this.getTypeDevice();
|
||||
}
|
||||
|
||||
getTypeDevice() {
|
||||
const userAgent = window.navigator.userAgent.toLowerCase();
|
||||
const ios = /iphone|ipod|ipad/.test(userAgent);
|
||||
this.deviceType = ios ? 'ios' : 'android';
|
||||
}
|
||||
|
||||
async getAccountData(): Promise<void> {
|
||||
this.loadingBonuses = true;
|
||||
|
||||
this.jsonrpc
|
||||
.rpc(
|
||||
{
|
||||
method: 'getAdditionalInfo',
|
||||
params: [],
|
||||
},
|
||||
RpcService.authService,
|
||||
true
|
||||
)
|
||||
.subscribe({
|
||||
next: (res) => {
|
||||
this.userName = res?.data?.first_name;
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error: ', err);
|
||||
},
|
||||
});
|
||||
|
||||
const getAccount = await lastValueFrom(
|
||||
this.jsonrpc.rpc(
|
||||
{
|
||||
method: 'GetAccounts',
|
||||
params: [],
|
||||
},
|
||||
RpcService.bonusService
|
||||
)
|
||||
);
|
||||
|
||||
this.accountData = getAccount && getAccount['Cards'][0];
|
||||
this.bonuses = this.accountData.BonusProgramAccounts?.reduce((previous, {Bonuses}) => {
|
||||
return previous + Bonuses
|
||||
}, 0) || this.accountData.Bonuses
|
||||
this.loadingBonuses = false;
|
||||
if (this.accountData) {
|
||||
barcode('#barcode')
|
||||
.options({ font: 'OCR-B' }) // Will affect all barcodes
|
||||
.EAN13(`${this.accountData.CardNumber}`.padStart(12, '0'), {
|
||||
fontSize: 18,
|
||||
textMargin: 0,
|
||||
})
|
||||
.render();
|
||||
}
|
||||
const getTransactions = (
|
||||
await lastValueFrom(
|
||||
this.jsonrpc.rpc(
|
||||
{
|
||||
method: 'GetAccountTransactions',
|
||||
params: [],
|
||||
},
|
||||
RpcService.bonusService
|
||||
)
|
||||
)
|
||||
)
|
||||
if (!getTransactions) {
|
||||
this.messageService.add({severity:'error', summary:'Произошла ошибка, попробуйте позже'});
|
||||
return
|
||||
}
|
||||
const transactions: Transaction[] = getTransactions && getTransactions['Transactions'];
|
||||
|
||||
const getPurchases = (
|
||||
await lastValueFrom(
|
||||
this.jsonrpc.rpc(
|
||||
{
|
||||
method: 'GetAccountPurchase',
|
||||
params: [],
|
||||
},
|
||||
RpcService.bonusService
|
||||
)
|
||||
)
|
||||
)
|
||||
if (!getPurchases) {
|
||||
this.messageService.add({severity:'error', summary:'Произошла ошибка, попробуйте позже'});
|
||||
return
|
||||
}
|
||||
const purchases: Purchase[] = getPurchases && getPurchases['Purchases'];
|
||||
|
||||
this.purchases = purchases && purchases.map<Purchase>((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 && transactions.forEach((transaction) => {
|
||||
if (!transaction.HasPurchase) {
|
||||
this.purchases.push({
|
||||
ID: transaction.ID,
|
||||
PurchaseDate: transaction.Date,
|
||||
Transactions: [transaction],
|
||||
IsSingleTransaction: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
this.purchases = this.purchases && this.purchases.sort((a, b) => {
|
||||
return moment(a.PurchaseDate).date() - moment(b.PurchaseDate).date();
|
||||
});
|
||||
}
|
||||
|
||||
async addCardToWallet(e: any) {
|
||||
e.preventDefault();
|
||||
const token = this.cookiesService.getItem('token');
|
||||
const accountData = (
|
||||
await lastValueFrom(
|
||||
this.jsonrpc.rpc(
|
||||
{
|
||||
method: 'getTokenData',
|
||||
params: [],
|
||||
},
|
||||
RpcService.authService,
|
||||
true
|
||||
)
|
||||
)
|
||||
).data;
|
||||
if (token && accountData.user_id) {
|
||||
this.appleWallet.generateCard(token, accountData.user_id).subscribe({
|
||||
next: (res: any) => {
|
||||
this.document.location.href = res.url;
|
||||
},
|
||||
error: (err) => {
|
||||
console.log('Error: ', err);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -67,7 +67,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<p
|
||||
*ngIf="purchases.length !== purchasesShortArray.length"
|
||||
*ngIf="purchases?.length !== purchasesShortArray?.length"
|
||||
class="show-more-orders"
|
||||
(click)="getMoreOrders()"
|
||||
>
|
||||
@ -75,12 +75,13 @@
|
||||
</p>
|
||||
<p-progressSpinner
|
||||
*ngIf="ordersLoadingStatus"
|
||||
[style]="{ width: '100%' }"
|
||||
[style]="{ display: 'block' }"
|
||||
strokeWidth="2"
|
||||
styleClass="angular-spinner"
|
||||
></p-progressSpinner>
|
||||
<p
|
||||
*ngIf="purchases.length === 0 && !ordersLoadingStatus"
|
||||
*ngIf="purchases?.length === 0 && !ordersLoadingStatus"
|
||||
class="no-orders"
|
||||
style="width: 100%; text-align: center"
|
||||
>
|
||||
Нет заказов
|
||||
76
angular/src/app/pages/account/orders/orders.component.scss
Normal file
@ -0,0 +1,76 @@
|
||||
.show-more-orders {
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
color: #09467f;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.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%;
|
||||
max-width: 400px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
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;
|
||||
&:nth-child(even) {
|
||||
background: #ebebeb;
|
||||
}
|
||||
}
|
||||
// &__cell-order-actions::before {
|
||||
// display: none;
|
||||
// }
|
||||
&__cell-order-actions {
|
||||
&.red-color {
|
||||
color: #ed0000;
|
||||
}
|
||||
&.green-color {
|
||||
color: #00a700;
|
||||
}
|
||||
}
|
||||
&__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-orders {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
@ -5,11 +5,12 @@ import { Purchase } from 'src/app/interface/data';
|
||||
import * as moment from 'moment-timezone';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { JsonrpcService, RpcService } from 'src/app/services/jsonrpc.service';
|
||||
import { MessageService } from 'primeng/api';
|
||||
|
||||
@Component({
|
||||
selector: 'app-orders',
|
||||
templateUrl: './orders.component.html',
|
||||
styleUrls: ['./orders.component.scss']
|
||||
styleUrls: ['./orders.component.scss'],
|
||||
})
|
||||
export class OrdersComponent implements OnInit {
|
||||
@Input() handleHttpError!: (error: HttpErrorResponse) => void;
|
||||
@ -23,24 +24,31 @@ export class OrdersComponent implements OnInit {
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private jsonrpc: JsonrpcService,
|
||||
) { }
|
||||
private messageService: MessageService,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getOrders()
|
||||
this.getOrders();
|
||||
}
|
||||
|
||||
async getOrders(){
|
||||
const purchases: Purchase[] = (await lastValueFrom(
|
||||
async getOrders() {
|
||||
const getPurchases = await lastValueFrom(
|
||||
this.jsonrpc.rpc(
|
||||
{
|
||||
method: 'GetAccountPurchase',
|
||||
params: []
|
||||
params: [],
|
||||
},
|
||||
RpcService.bonusService
|
||||
)))['Purchases'];
|
||||
)
|
||||
);
|
||||
if (!getPurchases) {
|
||||
this.messageService.add({severity:'error', summary:'Произошла ошибка, попробуйте позже'});
|
||||
return
|
||||
}
|
||||
const purchases: Purchase[] = getPurchases && getPurchases['Purchases'];
|
||||
|
||||
this.purchases = purchases.map<Purchase>((purchase) => {
|
||||
const id = purchase.ID.slice(0,36).toLowerCase();
|
||||
this.purchases = purchases && purchases.map<Purchase>((purchase) => {
|
||||
const id = purchase.ID.slice(0, 36).toLowerCase();
|
||||
// purchase.Transactions = transactions.filter((transaction) => {
|
||||
// const same = transaction.Purchase === id;
|
||||
// transaction.HasPurchase = same;
|
||||
@ -48,7 +56,7 @@ export class OrdersComponent implements OnInit {
|
||||
// });
|
||||
return purchase;
|
||||
});
|
||||
this.purchasesShortArray = this.purchases.slice(0, this.lastViewOrder)
|
||||
this.purchasesShortArray = this.purchases && this.purchases.slice(0, this.lastViewOrder);
|
||||
this.ordersLoadingStatus = false;
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
img {
|
||||
height: 26px;
|
||||
}
|
||||
@ -25,6 +26,7 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,7 @@ import { environment } from 'src/environments/environment';
|
||||
styleUrls: ['./ref-system.component.scss']
|
||||
})
|
||||
export class RefSystemComponent implements OnInit {
|
||||
public refUrl: string = `${environment.defaultUrl}/?refCardNumber=`
|
||||
public refUrl: string = `${environment.defaultUrl}/?refUserId=`
|
||||
public loading: boolean = true;
|
||||
|
||||
constructor(
|
||||
@ -21,13 +21,18 @@ export class RefSystemComponent implements OnInit {
|
||||
|
||||
async ngOnInit() {
|
||||
const accountData = (await lastValueFrom(
|
||||
this.jsonrpc.rpc({
|
||||
method: 'GetAccounts',
|
||||
params: []
|
||||
},
|
||||
RpcService.bonusService
|
||||
)))['Cards'][0]
|
||||
this.refUrl += accountData.CardNumber
|
||||
this.jsonrpc
|
||||
.rpc(
|
||||
{
|
||||
method: 'getTokenData',
|
||||
params: [],
|
||||
},
|
||||
RpcService.authService,
|
||||
true
|
||||
)
|
||||
)).data
|
||||
|
||||
this.refUrl += accountData.user_id
|
||||
this.loading = false
|
||||
}
|
||||
|
||||
@ -35,30 +40,30 @@ export class RefSystemComponent implements OnInit {
|
||||
if (navigator.share) {
|
||||
navigator.share({
|
||||
title: document.title,
|
||||
text: "Fashion Logica",
|
||||
text: "Fashionlogica",
|
||||
url: this.refUrl
|
||||
})
|
||||
.then(() => console.log('Successful share'))
|
||||
.catch((error) => {
|
||||
console.log('Error sharing:', error)
|
||||
});
|
||||
.then(() => console.log('Successful share'))
|
||||
.catch((error) => {
|
||||
console.log('Error sharing:', error)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
copyUrl() {
|
||||
navigator.clipboard.writeText(this.refUrl)
|
||||
.then(() => {
|
||||
this.messageService.add({
|
||||
severity: 'custom',
|
||||
summary: 'Ссылка скопирована!',
|
||||
.then(() => {
|
||||
this.messageService.add({
|
||||
severity: 'custom',
|
||||
summary: 'Ссылка скопирована!',
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
this.messageService.add({
|
||||
severity: 'error',
|
||||
summary: 'Произошла ошибка!',
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
this.messageService.add({
|
||||
severity: 'error',
|
||||
summary: 'Произошла ошибка!',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -75,12 +75,12 @@
|
||||
<div class="decoration-pattern">
|
||||
<img
|
||||
style="height: 34px"
|
||||
src="./assets/card-decorative-pattern.svg"
|
||||
src="./assets/card-decorative-pattern.png"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
style="height: 16px; margin-left: 2px"
|
||||
src="./assets/card-decorative-pattern.svg"
|
||||
src="./assets/card-decorative-pattern.png"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
@ -1,7 +1,9 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { MessageService } from 'primeng/api';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { UserDataForm } from 'src/app/interface/data';
|
||||
import { AppleWalletService } from 'src/app/services/apple-wallet.service';
|
||||
import { JsonrpcService, RpcService } from 'src/app/services/jsonrpc.service';
|
||||
|
||||
@Component({
|
||||
@ -21,6 +23,8 @@ export class UserDataComponent implements OnInit {
|
||||
constructor(
|
||||
private jsonRpcService: JsonrpcService,
|
||||
private messageService: MessageService,
|
||||
private appleWallet: AppleWalletService,
|
||||
private jsonrpc: JsonrpcService,
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
@ -30,6 +34,14 @@ export class UserDataComponent implements OnInit {
|
||||
params: []
|
||||
}, RpcService.authService, true).subscribe({
|
||||
next: (res) => {
|
||||
if (res.code === 45) {
|
||||
this.messageService.add({severity:'warn', summary:'Данные не найдены, заполните их на этой странице'});
|
||||
return
|
||||
}
|
||||
if (!res.data) {
|
||||
this.messageService.add({severity:'error', summary:'Произошла ошибка, попробуйте позже'});
|
||||
return
|
||||
}
|
||||
const { first_name, birthdate, gender } = res.data
|
||||
this.userData = { first_name, birthdate, gender }
|
||||
this.createUserDataForm({...this.userData})
|
||||
@ -59,8 +71,29 @@ export class UserDataComponent implements OnInit {
|
||||
method: 'updateAdditionalInfo',
|
||||
params: [this.userData]
|
||||
}, RpcService.authService, true).subscribe({
|
||||
next: () => {
|
||||
next: async () => {
|
||||
this.messageService.add({severity:'custom', summary:'Данные успешно обновлены!'});
|
||||
const accountData = (await lastValueFrom(
|
||||
this.jsonrpc
|
||||
.rpc(
|
||||
{
|
||||
method: 'getTokenData',
|
||||
params: [],
|
||||
},
|
||||
RpcService.authService,
|
||||
true
|
||||
)
|
||||
)).data
|
||||
if (accountData.user_id) {
|
||||
this.appleWallet.reloadCard(accountData.user_id).subscribe({
|
||||
next: (value) => {
|
||||
console.log(value);
|
||||
},
|
||||
error: (err) => {
|
||||
console.error(err);
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error: ', err)
|
||||
@ -1,7 +1,7 @@
|
||||
<div class="main-container">
|
||||
<app-navbar></app-navbar>
|
||||
<p-toast position="top-center"></p-toast>
|
||||
<app-footer-buttons [token]="token" [deferredPrompt]="deferredPrompt"
|
||||
[isPermissionNotifications]="isPermissionNotifications" (downloadingPWA)="downloadPWA()"
|
||||
<app-footer-buttons [token]="token"
|
||||
[isPermissionNotifications]="isPermissionNotifications"
|
||||
(requestingPermission)="requestPermission()"></app-footer-buttons>
|
||||
</div>
|
||||
@ -24,7 +24,6 @@ export class MainComponent implements OnInit {
|
||||
private cardComponent!: ComponentRef<CardComponent>;
|
||||
private accountComponent!: ComponentRef<AccountComponent>;
|
||||
public messagingToken!: string | null;
|
||||
public deferredPrompt: any;
|
||||
public isPermissionNotifications: boolean = false;
|
||||
public token = '';
|
||||
public message: any;
|
||||
@ -32,20 +31,12 @@ export class MainComponent implements OnInit {
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private viewContainerRef: ViewContainerRef,
|
||||
private afMessaging: AngularFireMessaging,
|
||||
public el: ElementRef,
|
||||
public renderer: Renderer2,
|
||||
private messageService: MessageService,
|
||||
private messagingService: MessagingService,
|
||||
private messageService: MessageService,
|
||||
private cookiesService: CookiesService,
|
||||
) {
|
||||
renderer.listen('window', 'appinstalled', (evt) => {
|
||||
console.log('INSTALLED!!!');
|
||||
});
|
||||
renderer.listen('window', 'beforeinstallprompt', (e) => {
|
||||
e.preventDefault();
|
||||
this.deferredPrompt = e;
|
||||
});
|
||||
route.queryParams.subscribe((params) => {
|
||||
if (params['token']) {
|
||||
this.token = params['token']
|
||||
@ -61,35 +52,20 @@ export class MainComponent implements OnInit {
|
||||
// this.checkRequestPermission()
|
||||
}
|
||||
|
||||
downloadPWA() {
|
||||
if (!this.deferredPrompt) {
|
||||
this.messageService.add({
|
||||
severity: 'error',
|
||||
summary: 'Не поддерживается в Вашем браузере!',
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.deferredPrompt.prompt();
|
||||
this.deferredPrompt.userChoice.then((res: any) => {
|
||||
if (res.outcome === 'accepted') {
|
||||
this.messageService.add({
|
||||
severity: 'custom',
|
||||
summary: 'Спасибо за установку!',
|
||||
});
|
||||
console.log('User Accepted!!!');
|
||||
}
|
||||
this.deferredPrompt = null;
|
||||
});
|
||||
}
|
||||
|
||||
checkRequestPermission() {
|
||||
this.isPermissionNotifications =
|
||||
Notification.permission !== 'granted' ? false : true;
|
||||
}
|
||||
|
||||
requestPermission() {
|
||||
if ('safari' in window) {
|
||||
console.log('safari');
|
||||
const userAgent = window.navigator.userAgent.toLowerCase();
|
||||
const ios = /iphone|ipod|ipad/.test(userAgent);
|
||||
if (ios) {
|
||||
this.messageService.add({
|
||||
severity: 'custom',
|
||||
summary: `Чтобы получать уведомления, добавьте карту в Apple Wallet`,
|
||||
life: 5000,
|
||||
});
|
||||
|
||||
// var permissionData = window.safari.pushNotification.permission('web.com.example.domain');
|
||||
// $scope.checkRemotePermission(permissionData);
|
||||
@ -100,20 +76,6 @@ export class MainComponent implements OnInit {
|
||||
this.message = this.messagingService.currentMessage;
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
8
angular/src/app/pages/not-found/not-found.component.html
Normal file
@ -0,0 +1,8 @@
|
||||
<div class="not-found-page">
|
||||
<app-navbar></app-navbar>
|
||||
<div class="not-found-page__container">
|
||||
<h1>404</h1>
|
||||
<p>Упс, что-то пошло не так!</p>
|
||||
<button (click)="routeHome()">Вернуться на главную</button>
|
||||
</div>
|
||||
</div>
|
||||
28
angular/src/app/pages/not-found/not-found.component.scss
Normal file
@ -0,0 +1,28 @@
|
||||
:host {
|
||||
.not-found-page {
|
||||
&__container {
|
||||
text-align: center;
|
||||
margin-top: 32px;
|
||||
h1 {
|
||||
font-size: 108px;
|
||||
font-weight: 600;
|
||||
color: #09467f;
|
||||
}
|
||||
p {
|
||||
margin: 16px 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
button {
|
||||
background-color: #09467f;
|
||||
color: #fff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 12px;
|
||||
margin: 0 auto;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
angular/src/app/pages/not-found/not-found.component.spec.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NotFoundComponent } from './not-found.component';
|
||||
|
||||
describe('NotFoundComponent', () => {
|
||||
let component: NotFoundComponent;
|
||||
let fixture: ComponentFixture<NotFoundComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ NotFoundComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(NotFoundComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
20
angular/src/app/pages/not-found/not-found.component.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-not-found',
|
||||
templateUrl: './not-found.component.html',
|
||||
styleUrls: ['./not-found.component.scss']
|
||||
})
|
||||
export class NotFoundComponent implements OnInit {
|
||||
|
||||
constructor(private router: Router) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
routeHome() {
|
||||
this.router.navigate(['/']);
|
||||
}
|
||||
|
||||
}
|
||||
35
angular/src/app/services/apple-wallet.service.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AppleWalletService {
|
||||
private url: string = environment.appleWalletEndpoint;
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
) {}
|
||||
|
||||
generateCard(token: string, user_id: string) {
|
||||
let headers = new HttpHeaders();
|
||||
headers = headers.set('Authorization', environment.appleWalletSecret);
|
||||
const options = {
|
||||
headers: headers,
|
||||
};
|
||||
return this.http.get(`${this.url}/client/${environment.clientName}/passUrl/${user_id}/token/${token}`, options)
|
||||
}
|
||||
|
||||
reloadCard(user_id:string) {
|
||||
let headers = new HttpHeaders();
|
||||
headers = headers.set('Authorization', environment.appleWalletSecret);
|
||||
const options = {
|
||||
headers: headers,
|
||||
};
|
||||
const body = {
|
||||
text: '',
|
||||
isUpdateCard: true
|
||||
}
|
||||
return this.http.post(`${this.url}/sendNotification/${user_id}`, body, options)
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AngularFireMessaging } from '@angular/fire/compat/messaging';
|
||||
import { MessageService } from 'primeng/api';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { BehaviorSubject, lastValueFrom } from 'rxjs';
|
||||
import { JsonrpcService, RpcService } from './jsonrpc.service';
|
||||
|
||||
@Injectable()
|
||||
@ -19,15 +19,29 @@ export class MessagingService {
|
||||
});
|
||||
}
|
||||
|
||||
updateToken(token: string | null) {
|
||||
async updateToken(token: string | null) {
|
||||
if (!token) return;
|
||||
const additionalInfo = (await lastValueFrom(
|
||||
this.jsonRpcService.rpc({
|
||||
method: 'getAdditionalInfo',
|
||||
params: []
|
||||
}, RpcService.authService, true)
|
||||
)).data
|
||||
let tokens: string[] = []
|
||||
if (typeof additionalInfo['fmc-token'] === 'string') {
|
||||
tokens.push(additionalInfo['fmc-token'], token)
|
||||
} else if (typeof additionalInfo['fmc-token'] === 'object') {
|
||||
tokens = [...additionalInfo['fmc-token'], token]
|
||||
} else {
|
||||
tokens = [token]
|
||||
}
|
||||
this.jsonRpcService
|
||||
.rpc(
|
||||
{
|
||||
method: 'updateAdditionalInfo',
|
||||
params: [
|
||||
{
|
||||
'fmc-token': token,
|
||||
'fmc-token': tokens,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -70,6 +84,11 @@ export class MessagingService {
|
||||
receiveMessage() {
|
||||
this.angularFireMessaging.messages.subscribe((payload: any) => {
|
||||
console.log('new message received. ', payload);
|
||||
const NotificationOptions = {
|
||||
body: payload.notification.body,
|
||||
data: payload.data,
|
||||
icon: payload.notification.icon
|
||||
}
|
||||
this.currentMessage.next(payload);
|
||||
});
|
||||
}
|
||||
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
BIN
angular/src/assets/card-decorative-pattern.png
Normal file
|
After Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 568 B After Width: | Height: | Size: 568 B |
BIN
angular/src/assets/icons/apple-icon-180x180.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
angular/src/assets/icons/icon-128x128.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
angular/src/assets/icons/icon-144x144.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
angular/src/assets/icons/icon-152x152.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
angular/src/assets/icons/icon-192x192.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
angular/src/assets/icons/icon-384x384.png
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
angular/src/assets/icons/icon-512x512.png
Normal file
|
After Width: | Height: | Size: 203 KiB |
BIN
angular/src/assets/icons/icon-72x72.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
angular/src/assets/icons/icon-96x96.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 992 B After Width: | Height: | Size: 992 B |
BIN
angular/src/assets/menu-icons/download-app.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 861 B After Width: | Height: | Size: 861 B |
|
Before Width: | Height: | Size: 992 B After Width: | Height: | Size: 992 B |