Compare commits

..

No commits in common. "more" and "master" have entirely different histories.
more ... master

295 changed files with 6243 additions and 15243 deletions

16
.browserslistrc Normal file
View File

@ -0,0 +1,16 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# For the full list of supported browsers by the Angular framework, please see:
# https://angular.io/guide/browser-support
# You can see what browsers were selected by your queries by running:
# npx browserslist
last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major versions
last 2 iOS major versions
Firefox ESR

58
.gitignore vendored
View File

@ -1,42 +1,42 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# Compiled output
angular/dist
angular/tmp
angular/out-tsc
angular/bazel-out
/dist
/tmp
/out-tsc
/bazel-out
# Node
angular/node_modules
angular/npm-debug.log
angular/yarn-error.log
/node_modules
npm-debug.log
yarn-error.log
# IDEs and editors
angular/.idea/
angular/.project
angular/.classpath
angular/.c9/
angular/*.launch
angular/.settings/
angular/*.sublime-workspace
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# Visual Studio Code
angular/.vscode/*
angular/!.vscode/settings.json
angular/!.vscode/tasks.json
angular/!.vscode/launch.json
angular/!.vscode/extensions.json
angular/.history/*
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# Miscellaneous
angular/.angular/cache
angular/.sass-cache/
angular/connect.lock
angular/coverage
angular/libpeerconnection.log
angular/testem.log
angular/typings
/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings
# System files
angular/.DS_Store
angular/Thumbs.db
.DS_Store
Thumbs.db

4
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
"recommendations": ["angular.ng-template"]
}

20
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,20 @@
{
// 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 Normal file
View File

@ -0,0 +1,42 @@
{
// 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"
}
}
}
}
]
}

30
Jenkinsfile vendored
View File

@ -1,30 +0,0 @@
env.HL_BUILD_MODE = "jenkins"
node('Palladium'){
stage('get new version to repo') {
checkout scm
if (lastCommitIsBumpCommit()) {
currentBuild.result = 'ABORTED'
error('Последний коммит - результат сборки jenkins')
}
//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
}
}

View File

@ -1,4 +1,4 @@
# CoffeeLikeMore
# FashionLogica
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 14.0.6.

122
angular.json Normal file
View File

@ -0,0 +1,122 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"fashion-logica": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "/var/www/lk/fashion-logica",
"baseHref": "/fashion-logica/",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets",
"src/manifest.webmanifest",
"src/firebase-messaging-sw.js"
],
"styles": [
"node_modules/primeng/resources/themes/bootstrap4-light-blue/theme.css",
"node_modules/primeicons/primeicons.css",
"node_modules/primeng/resources/primeng.min.css",
"node_modules/ngx-sharebuttons/themes/modern.scss",
"node_modules/ngx-sharebuttons/themes/material.scss",
"src/styles.scss"
],
"scripts": [],
"serviceWorker": true,
"ngswConfigPath": "ngsw-config.json"
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "4mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "fashion-logica:build:production"
},
"development": {
"browserTarget": "fashion-logica:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "fashion-logica:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/firebase-messaging-sw.js",
"src/assets",
"src/manifest.webmanifest"
],
"styles": [
"src/styles.scss"
],
"scripts": []
}
}
}
}
},
"cli": {
"analytics": false
}
}

View File

@ -1,131 +0,0 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"coffee-like-more": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
},
"i18n": {
"sourceLocale": "ru-RU"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "/var/www/html/lk.crm4retail.ru/more",
"baseHref": "/",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets",
"src/manifest.webmanifest",
"src/firebase-messaging-sw.js",
"src/sw-master.js",
"src/sw-custom.js"
],
"styles": [
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"node_modules/primeng/resources/themes/bootstrap4-light-blue/theme.css",
"node_modules/primeicons/primeicons.css",
"node_modules/primeng/resources/primeng.min.css",
"node_modules/ngx-sharebuttons/themes/modern.scss",
"node_modules/ngx-sharebuttons/themes/material.scss",
"src/styles.scss"
],
"scripts": [],
"serviceWorker": true,
"ngswConfigPath": "ngsw-config.json"
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "4mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "coffee-like-more:build:production"
},
"development": {
"browserTarget": "coffee-like-more:build:development",
"proxyConfig": "proxy.confi.json"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "coffee-like-more:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/firebase-messaging-sw.js",
"src/assets",
"src/manifest.webmanifest"
],
"styles": [
"./node_modules/@angular/material/prebuilt-themes/purple-green.css",
"src/styles.scss"
],
"scripts": []
}
}
}
}
},
"cli": {
"analytics": false
}
}

View File

@ -1,63 +0,0 @@
{
"name": "coffee-like-more",
"version": "0.0.2",
"scripts": {
"ng": "ng",
"start": "ng serve --host 192.168.0.14",
"build": "ng build --aot --configuration production --output-hashing none",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "^15.2.9",
"@angular/cdk": "^15.2.9",
"@angular/common": "^15.2.9",
"@angular/compiler": "^15.2.9",
"@angular/core": "^15.2.9",
"@angular/fire": "^7.5.0",
"@angular/forms": "^15.2.9",
"@angular/material": "^15.2.9",
"@angular/material-moment-adapter": "^15.2.9",
"@angular/platform-browser": "^15.2.9",
"@angular/platform-browser-dynamic": "^15.2.9",
"@angular/router": "^15.2.9",
"@angular/service-worker": "^15.2.9",
"@fortawesome/angular-fontawesome": "^0.12.1",
"@fortawesome/fontawesome-svg-core": "^6.2.0",
"@fortawesome/free-brands-svg-icons": "^6.2.0",
"@fortawesome/free-solid-svg-icons": "^6.2.0",
"@types/uuid": "^8.3.4",
"@types/web": "^0.0.99",
"angular-moment-timezone": "^1.7.1",
"angular2-text-mask": "^9.0.0",
"barcode-2-svg": "^0.3.3",
"firebase": "^9.9.3",
"google-libphonenumber": "^3.2.30",
"jsbarcode": "^3.11.5",
"libphonenumber-js": "^1.10.28",
"ng-qrcode": "^8.0.1",
"ngx-mat-intl-tel-input": "^5.0.0",
"ngx-sharebuttons": "^11.0.0",
"primeicons": "^5.0.0",
"primeng": "^15.4.1",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
"uuid": "^8.3.2",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "^15.2.8",
"@angular/cli": "~15.2.8",
"@angular/compiler-cli": "^15.2.9",
"@types/google-libphonenumber": "^7.4.23",
"@types/jasmine": "~4.0.0",
"jasmine-core": "~4.1.0",
"karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"typescript": "4.8"
}
}

View File

@ -1,38 +0,0 @@
{
"/api": {
"target": "https://apple-push-notifications.it-retail.tech/apns/api",
"secure": false,
"pathRewrite": {
"^/api": ""
},
"changeOrigin": true,
"logLevel": "debug"
},
"/icard-proxy": {
"target": "https://sakura.lk.crm4retail.ru/api/icard-proxy",
"secure": false,
"pathRewrite": {
"^/icard-proxy": ""
},
"changeOrigin": true,
"logLevel": "debug"
},
"/static": {
"target": "https://sakura.lk.crm4retail.ru/static",
"secure": false,
"pathRewrite": {
"^/static": ""
},
"changeOrigin": true,
"logLevel": "debug"
},
"/it-retail": {
"target": "https://sakura.lk.crm4retail.ru/it-retail",
"secure": false,
"pathRewrite": {
"^/it-retail": ""
},
"changeOrigin": true,
"logLevel": "debug"
}
}

View File

@ -1,20 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { MainComponent } from './pages/main/main.component';
import { AuthGuard } from './guards/auth-guard.guard';
const routes: Routes = [
{
path: '',
loadChildren: () => null as any,
// component: GuestCardComponent,
// canActivate: [AuthGuard]
},
// { path: '**', component: NotFoundComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

View File

@ -1,2 +0,0 @@
<router-outlet></router-outlet>
<p-toast position="top-center"></p-toast>

View File

@ -1,64 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { RouteConfigLoadStart, Router } from '@angular/router';
import { AuthService } from './services/auth.service';
import { CookiesService } from './services/cookies.service';
import { JsonrpcService, RpcService } from './services/jsonrpc.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
title = 'Coffee Like More';
constructor(
private router: Router,
private cookiesService: CookiesService,
private jsonRpcService: JsonrpcService,
private authService: AuthService,
) {
this.router.events.subscribe((x) => {
if (x instanceof RouteConfigLoadStart && x.route.path === '') {
x.route.loadChildren = () => {
switch (this.cookiesService.getItem('presentation-option')) {
case 'first':
return import(
'./presentation-options/first-option/first-option.module'
).then((mod) => mod.FirstOptionModule);
default:
return import(
'./presentation-options/default-option/default-option.module'
).then((mod) => mod.DefaultOptionModule);
}
};
}
});
}
getAdditionalInfo() {
return this.jsonRpcService.rpc(
{
method: 'getAdditionalInfo',
params: [],
},
RpcService.authService,
true
);
}
ngOnInit(): void {
if (this.authService.authorized) {
this.authService.getUserInfo();
}
this.getAdditionalInfo().subscribe({
next: (value) => {
this.cookiesService.setCookie('presentation-option', value?.data?.interface_id || 'default')
},
error: (err) => {
console.error(err);
}
})
}
}

View File

@ -1,93 +0,0 @@
import { OrderStatus, Page, PageCode, lvlPeriod } 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.BonusProgram,
name: 'Ваша карта лояльности',
description: '',
resName: 'bonus-program',
onSideBar: true,
},
{
code: PageCode.Orders,
name: 'Ваши чеки',
description: '',
resName: 'orders',
onSideBar: true,
},
{
code: PageCode.UserData,
name: 'Заполнить анкету',
description: '',
resName: 'user-data',
onSideBar: true
},
{
code: PageCode.RefSystem,
name: 'Пригласить друга',
description: '',
resName: 'ref-system',
onSideBar: true,
}
];
export const orderStatuses: OrderStatus = {
'Cancelled': 'Отменен',
'InProcessing': 'В обработке',
'Unconfirmed': 'Принят',
'WaitCooking': 'Принят',
'ReadyForCooking': 'Принят',
'CookingStarted': 'Готовится',
'CookingCompleted': 'Приготовлен',
'Waiting': 'В пути',
'OnWay': 'В пути',
'Delivered': 'Выполнен',
'Closed': 'Выполнен',
};
export const lvlPeriods: lvlPeriod[] = [
{
percent: 3,
start: 0,
end: 1600,
color: '#f2c94c'
},
{
percent: 6,
start: 1601,
end: 3600,
color: '#f2994a'
},
{
percent: 10,
start: 3601,
end: 8600,
color: '#6fcf97'
},
{
percent: 15,
start: 8601,
color: '#6fcf97'
},
]

View File

@ -1,7 +0,0 @@
<div class="tab">
<input [id]="'tab-' + guid" type="checkbox" name="tabs" />
<label [for]="'tab-' + guid">{{ header }}</label>
<div class="tab-content">
<ng-content></ng-content>
</div>
</div>

View File

@ -1,85 +0,0 @@
:host {
width: 100%;
}
.tab {
position: relative;
margin-bottom: 1px;
width: 100%;
color: var(--text-color);
overflow: hidden;
border-bottom: solid 1px #bdbdbd;
}
.tab input {
position: absolute;
opacity: 0;
z-index: -1;
}
.tab label {
display: block;
padding: 20px 26px;
position: relative;
background: #ffffff00;
font-weight: 400;
font-size: 12px;
line-height: 14px;
letter-spacing: -0.5px;
cursor: pointer;
}
// .tab label:before {
// display: block;
// content: " ";
// padding-top: 5px;
// }
.tab-content {
max-height: 0;
overflow: hidden;
background: #292929;
-webkit-transition: all 0.35s;
-o-transition: all 0.35s;
transition: all 0.35s;
border-top: solid 1px #bdbdbd;
font-style: normal;
font-weight: 400;
font-size: 12px;
p {
margin: 0;
}
}
.tab-content p {
margin: 1em;
}
/* :checked */
.tab input:checked ~ .tab-content {
padding: 16px 26px;
max-height: 100vh;
}
/* Icon */
.tab label::after {
position: absolute;
right: 0;
top: 0;
line-height: 3;
text-align: center;
-webkit-transition: all 0.35s;
-o-transition: all 0.35s;
transition: all 0.35s;
height: 100%;
margin-right: 12px;
display: flex;
align-items: center;
}
.tab input[type="checkbox"] + label::after {
content: "+";
}
.tab input[type="radio"] + label::after {
content: "\25BC";
}
.tab input[type="checkbox"]:checked + label::after {
transform: rotate(315deg);
}
.tab input[type="radio"]:checked + label::after {
transform: rotateX(180deg);
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AccordionComponent } from './accordion.component';
describe('AccordionComponent', () => {
let component: AccordionComponent;
let fixture: ComponentFixture<AccordionComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ AccordionComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(AccordionComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,23 +0,0 @@
import { Component, Input, OnInit } from '@angular/core';
import { v4 as uuidv4 } from 'uuid';
export interface IAccordionData {
header: string;
body: string;
}
@Component({
selector: 'app-accordion[header]',
templateUrl: './accordion.component.html',
styleUrls: ['./accordion.component.scss']
})
export class AccordionComponent implements OnInit {
@Input() header!: string
public guid: string = uuidv4()
constructor() { }
ngOnInit(): void {
}
}

View File

@ -1,7 +0,0 @@
<span class="example-pizza-party" matSnackBarLabel>
Вы действительно хотите выйти?
</span>
<div class="buttons-container">
<button mat-button (click)="rejection()" style="background: red;">Нет</button>
<button mat-button (click)="logout()">Да</button>
</div>

View File

@ -1,22 +0,0 @@
:host {
display: flex;
flex-direction: column;
align-items: center;
.buttons-container {
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
}
}
button {
padding: 10px 62px;
margin-top: 8px;
background-color: var(--button-color);
color: var(--button-text-color);
border-radius: 3px;
border: none;
width: calc(50% - 12px);
}

View File

@ -1,21 +0,0 @@
import { Component } from '@angular/core';
import { MatBottomSheetRef } from '@angular/material/bottom-sheet';
@Component({
selector: 'app-exit',
templateUrl: './exit.component.html',
styleUrls: ['./exit.component.scss'],
})
export class ExitComponent {
constructor(
private _bottomSheetRef: MatBottomSheetRef<ExitComponent>
) {}
rejection() {
this._bottomSheetRef.dismiss(false)
}
logout() {
this._bottomSheetRef.dismiss(true)
}
}

View File

@ -1,24 +0,0 @@
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)
}
}

View File

@ -1,4 +0,0 @@
<img src="/assets/logo.svg" alt="Логотип">
<h3>Горячая линия</h3>
<a class="phone-number" href="tel:88003334130">8 (800) 333-41-30</a>
<app-social-media-buttons></app-social-media-buttons>

View File

@ -1,28 +0,0 @@
:host {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
padding-bottom: 100px;
h3 {
margin: 0;
font-family: Montserrat;
font-style: normal;
font-weight: 400;
font-size: 15px;
line-height: 20px;
text-align: center;
letter-spacing: -0.24px;
color: #6a737c;
}
.phone-number {
font-style: normal;
font-weight: 700;
font-size: 17px;
line-height: 22px;
text-align: center;
letter-spacing: -0.408px;
color: #d9d9d9;
text-decoration: none;
}
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FooterComponent } from './footer.component';
describe('FooterComponent', () => {
let component: FooterComponent;
let fixture: ComponentFixture<FooterComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ FooterComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(FooterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,15 +0,0 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-footer',
templateUrl: './footer.component.html',
styleUrls: ['./footer.component.scss']
})
export class FooterComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@ -1,25 +0,0 @@
<h2>Пригласи друзей!</h2>
<div class="container">
<p>
Пригласи друзей зарегистрироваться в приложении по твоему уникальному коду и
получи бонусы, когда они совершат первую покупку.
</p>
<button class="share" (click)="share()" [disabled]="loading">
<ng-container *ngIf="loading">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 24 }"
></ng-container>
</ng-container>
<mat-icon
*ngIf="!loading"
aria-hidden="false"
aria-label="Share"
fontIcon="share"
style="color: #fff"
></mat-icon>
</button>
</div>
<ng-template #spinner let-diameter>
<mat-spinner [strokeWidth]="3" [diameter]="diameter"></mat-spinner>
</ng-template>

View File

@ -1,34 +0,0 @@
:host {
padding: 16px;
h2 {
font-family: Montserrat;
font-style: normal;
font-weight: 700;
font-size: 17px;
line-height: 22px;
letter-spacing: -0.408px;
}
& .container {
width: 100%;
display: flex;
flex-direction: row;
gap: 16px;
p {
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 16px;
color: var(--text-color);
}
.share {
width: 72px;
height: 48px;
background: var(--button-color);
padding: 8px 26px;
border: none;
}
}
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { InviteFriendsComponent } from './invite-friends.component';
describe('InviteFriendsComponent', () => {
let component: InviteFriendsComponent;
let fixture: ComponentFixture<InviteFriendsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ InviteFriendsComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(InviteFriendsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,54 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { MessageService } from 'primeng/api';
import { lastValueFrom } from 'rxjs';
import { JsonrpcService, RpcService } from 'src/app/services/jsonrpc.service';
import { environment } from 'src/environments/environment';
@Component({
selector: 'app-invite-friends',
templateUrl: './invite-friends.component.html',
styleUrls: ['./invite-friends.component.scss']
})
export class InviteFriendsComponent implements OnInit {
public refUrl: string = `${environment.defaultUrl}/?refUserId=`
public loading: boolean = true;
private shareData: ShareData = {
title: ''
}
constructor(
private jsonrpc: JsonrpcService,
private messageService: MessageService
) { }
async ngOnInit() {
const accountData = (await lastValueFrom(
this.jsonrpc
.rpc(
{
method: 'getTokenData',
params: [],
},
RpcService.authService,
true
)
)).data
this.refUrl += accountData.user_id
this.loading = false
}
share() {
if (navigator.share) {
navigator.share({
title: document.title,
text: "Coffee Like More",
url: this.refUrl
})
.then(() => console.log('Successful share'))
.catch((error) => {
console.log('Error sharing:', error)
});
}
}
}

View File

@ -1,31 +0,0 @@
<h2>Ваш предыдущий заказ</h2>
<div class="info-order">
<p class="flex"><span>Дата: </span>
<span *ngIf="!loading">{{(lastOrder?.transactionCreateDate | date:'dd.MM.yyyyг.') || 'Данные не найдены'}}</span>
<ng-container *ngIf="loading">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 24 }"
></ng-container>
</ng-container>
</p>
<p class="flex"><span>На сумму: </span>
<span *ngIf="!loading">{{lastOrder?.orderSum ? lastOrder?.orderSum + ' ₽' : 'Данные не найдены'}}</span>
<ng-container *ngIf="loading">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 24 }"
></ng-container>
</ng-container>
</p>
</div>
<a href="https://yandex.ru/profile/151770398186" target="_blank">
<button class="evaluate-order">Оценить заказ</button>
</a>
<p class="info">
Списание бонусов возможно на любые категории. Бонусами можно оплатить 100%
суммы покупки. Бонусы начисляются только на напитки с учётом добавок.
Неиспользованные бонусы сгорают в течение 90 дней.
</p>
<ng-template #spinner let-diameter>
<mat-spinner [strokeWidth]="3" [diameter]="diameter"></mat-spinner>
</ng-template>

View File

@ -1,52 +0,0 @@
:host {
padding: 24px 16px 0px;
& > h2 {
font-family: Montserrat;
font-style: normal;
font-weight: 700;
font-size: 15px;
line-height: 20px;
letter-spacing: -0.24px;
}
& > .info-order {
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 16px;
span {
color: #828282;
}
.flex {
display: flex;
align-items: center;
flex-direction: row;
gap: 8px;
}
}
.evaluate-order {
margin: 24px 0;
width: 100%;
padding: 12px;
text-align: center;
border: 2px solid #28af49;
border-radius: 6px;
font-style: normal;
font-weight: 700;
font-size: 17px;
line-height: 22px;
letter-spacing: -0.408px;
background-color: transparent;
color: #28af49;
}
.info {
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 16px;
color: rgba(255, 255, 255, 0.5);
}
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LastOrderComponent } from './last-order.component';
describe('LastOrderComponent', () => {
let component: LastOrderComponent;
let fixture: ComponentFixture<LastOrderComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ LastOrderComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(LastOrderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,18 +0,0 @@
import { Component, Input, OnInit } from '@angular/core';
import { Purchase } from 'src/app/interface/data';
@Component({
selector: 'app-last-order[lastOrder]',
templateUrl: './last-order.component.html',
styleUrls: ['./last-order.component.scss']
})
export class LastOrderComponent implements OnInit {
@Input() lastOrder!: Purchase;
@Input() loading!: boolean;
constructor() { }
ngOnInit(): void {
}
}

View File

@ -1,5 +0,0 @@
<div class="container">
<mat-icon style="cursor: pointer;" aria-hidden="false" aria-label="Назад" fontIcon="arrow_back_ios" class="back-arrow" (click)="back()"></mat-icon>
<h1 class="title">{{title}}</h1>
<div class="plug"></div>
</div>

View File

@ -1,33 +0,0 @@
:host {
width: 100%;
}
.container {
box-sizing: border-box;
padding: 12px 16px;
width: 100%;
background: #231f20;
box-shadow: 0px 8px 16px rgba(17, 17, 17, 0.5);
color: var(--text-color);
display: flex;
align-items: center;
justify-content: space-between;
.back-arrow {
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
}
.plug {
height: 24px;
width: 24px;
visibility: hidden;
}
.title {
font-family: "Montserrat", sans-serif;
font-weight: 700;
font-size: 17px;
line-height: 22px;
margin: 0;
}
}

View File

@ -1,21 +0,0 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'app-navbar[title]',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit {
@Input() title: string = 'Название не задано'
@Output() backEvent = new EventEmitter<null>();
constructor() { }
ngOnInit(): void {
}
back() {
this.backEvent.emit(null)
}
}

View File

@ -1,3 +0,0 @@
<a *ngFor="let link of links" [href]="link.url" target="_blank">
<img [src]="link.imgUrl" [alt]="link.label" />
</a>

View File

@ -1,15 +0,0 @@
:host {
display: flex;
flex-direction: row;
gap: 16px;
justify-content: space-between;
a {
width: 48px;
height: 48px;
border-radius: 100%;
background: #333333;
display: flex;
align-items: center;
justify-content: center;
}
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SocialMediaButtonsComponent } from './social-media-buttons.component';
describe('SocialMediaButtonsComponent', () => {
let component: SocialMediaButtonsComponent;
let fixture: ComponentFixture<SocialMediaButtonsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ SocialMediaButtonsComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(SocialMediaButtonsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,38 +0,0 @@
import { Component, OnInit } from '@angular/core';
export interface ISocialMediaLink {
url: string;
imgUrl: string;
label: string;
}
@Component({
selector: 'app-social-media-buttons',
templateUrl: './social-media-buttons.component.html',
styleUrls: ['./social-media-buttons.component.scss']
})
export class SocialMediaButtonsComponent implements OnInit {
public links: ISocialMediaLink[] = [
{
label: 'Инстаграм',
url: 'https://www.instagram.com/',
imgUrl: '/assets/social-media-icons/instagram.svg'
},
{
label: 'ВК',
url: 'https://vk.com/coffeelike_com',
imgUrl: '/assets/social-media-icons/vk.svg'
},
{
label: 'Youtube',
url: 'https://www.youtube.com/c/coffeelikeru',
imgUrl: '/assets/social-media-icons/youtube.svg'
}
]
constructor() { }
ngOnInit(): void {
}
}

View File

@ -1,13 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FocusNextInputDirective } from './focus-next-input.directive';
import { DownloadAppDirective } from './download-app.directive';
@NgModule({
imports: [
CommonModule
],
declarations: [FocusNextInputDirective, DownloadAppDirective],
exports: [FocusNextInputDirective, DownloadAppDirective]
})
export class DirectivesModule { }

View File

@ -1,81 +0,0 @@
import {
Directive,
ElementRef,
HostListener,
OnInit,
Renderer2,
} from '@angular/core';
import { MessageService } from 'primeng/api';
import { getTypeDevice, pwaInstalled } from 'src/app/utils';
@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 {
getTypeDevice();
if (this.deviceType === 'ios') {
this.el.nativeElement.style.display = 'block';
}
this.checkInstalled();
}
async checkInstalled(): Promise<void> {
if (window.matchMedia('(display-mode: standalone)').matches
|| await pwaInstalled()) {
this.el.nativeElement.style.display = 'none';
}
}
@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';
}
@HostListener('click', ['$event'])
async downloadApp(event: MouseEvent) {
if (!this.deferredPrompt) {
this.messageService.clear();
this.messageService.add({
severity: 'error',
summary: 'Не поддерживается в Вашем браузере!',
});
return;
}
this.deferredPrompt.prompt();
this.deferredPrompt.userChoice.then((res: any) => {
if (res.outcome === 'accepted') {
this.messageService.clear();
this.messageService.add({
severity: 'success',
summary: 'Спасибо за установку!',
});
}
this.deferredPrompt = null;
});
}
}

View File

@ -1,29 +0,0 @@
import { Directive, EventEmitter, Input, Renderer2 } from '@angular/core';
@Directive({
selector: '[appFocusNextInput]'
})
export class FocusNextInputDirective {
@Input('appFocusNextInput') eventEmitter!: EventEmitter<string>;
constructor(private renderer: Renderer2) { }
ngOnInit() {
// TODO:
// 1: don't need to listen all events
// 2: not working in safari
this.eventEmitter.subscribe(elementId => {
try {
const element = this.renderer.selectRootElement(elementId)
setTimeout(() => {
element.focus();
element.click();
}, 0);
} catch (ex) {
(document.activeElement as HTMLElement).blur();
// If the element doesn't exist or if the element disappears when this called then no need to do anything
}
});
}
}

View File

@ -1,16 +0,0 @@
import { TestBed } from '@angular/core/testing';
import { AuthGuard } from './auth-guard.guard';
describe('AuthGuardGuard', () => {
let guard: AuthGuard;
beforeEach(() => {
TestBed.configureTestingModule({});
guard = TestBed.inject(AuthGuard);
});
it('should be created', () => {
expect(guard).toBeTruthy();
});
});

View File

@ -1,47 +0,0 @@
import { Injectable } from '@angular/core';
import {
ActivatedRouteSnapshot,
CanActivate,
CanActivateChild,
Router,
RouterStateSnapshot,
UrlTree,
} from '@angular/router';
import { Observable, of } from 'rxjs';
import { CookiesService } from '../services/cookies.service';
@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanActivate, CanActivateChild {
constructor(private cookiesService: CookiesService, private router: Router) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
):
| Observable<boolean | UrlTree>
| Promise<boolean | UrlTree>
| boolean
| UrlTree
{
if (this.cookiesService.getItem('token')) {
return of(true);
} else {
this.router.navigate(['/login']);
return of(false);
}
}
canActivateChild(
childRoute: ActivatedRouteSnapshot,
state: RouterStateSnapshot
):
| boolean
| UrlTree
| Observable<boolean | UrlTree>
| Promise<boolean | UrlTree>
{
return this.canActivate(childRoute, state);
}
}

View File

@ -1,222 +0,0 @@
export enum PageCode {
Auth,
Orders,
BonusProgram,
RefSystem,
UserData,
}
export interface Moment extends moment.Moment { }
export interface Page {
code: PageCode;
component?: any;
name: string;
description?: string;
getMethod?: string;
resName?: string;
onSideBar: boolean;
}
export interface UserDataForm {
first_name: string;
birthdate: string;
gender: string;
}
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;
transactionCreateDate?: string;
transactionType?: 'CancelPayFromWallet' | 'PayFromWallet' | 'RefillWallet';
transactionSum: number;
orderSum?: number;
}
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 lvlPeriod {
percent: number;
start: number;
end?: number;
color: 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;
}
export interface UserInfoCategory {
id: string;
isActive: boolean;
isDefaultForNewGuests: boolean;
name: string;
}
export interface UserInfoWallet {
id: string;
name: string;
programType: string;
type: string;
}
export interface UserInfoWalletBalance {
balance: number;
wallet: UserInfoWallet;
}
export interface UserInfo {
OrdersSum: number;
categories: UserInfoCategory[];
customer_level: number;
birthday: string;
id: string;
name: string | null;
phone: string;
walletBalances: UserInfoWalletBalance[] | { error: ResponseError };
}
export interface ResponseError {
code: number;
msg: string;
}
export interface UpdateNewCustomerRequest {
name: string;
sex: string;
birthday: string;
}

View File

@ -1,193 +0,0 @@
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,
transactionSum: 0
});
}
});
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);
},
});
}
}
}

View File

@ -1,76 +0,0 @@
.show-more-orders {
text-align: center;
cursor: pointer;
color: var(--main-color);
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;
}

View File

@ -1,82 +0,0 @@
<app-navbar title="Карта гостя" (backEvent)="logout()"></app-navbar>
<div class="guest-card">
<div class="top-info">
<div class="top-info__level">
<p id="level">Уровень {{ currentLvl }}</p>
<p id="level-percent">Кэшбек {{ currentLvlPeriod.percent }}%</p>
</div>
<p class="top-info__bonus">{{ getBalanceAmount(customerInfo?.walletBalances) }} бонусов</p>
</div>
<div class="guest-card__qr" (click)="qrCodeClick()">
<ng-container *ngIf="customerInfo">
<qr-code
[value]="customerInfo?.phone.substr(2) || 'Данные не найдены'"
[margin]="0"
[size]="qrCodeSize"
errorCorrectionLevel="M"
></qr-code>
</ng-container>
<ng-container *ngIf="!customerInfo">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 85 }"
></ng-container>
</ng-container>
</div>
<div class="guest-card__user-description">
<p>
<ng-container *ngIf="currentLvlPeriod.end">
Осталось купить на сумму <span class="price">{{ currentLvlPeriod.end - (purchaseData.currentAmount || 0) + 1 }}</span>
рублей, тогда кэшбек будет <span class="percent">{{ getNextLevel().percent }}%</span> с
{{ purchaseData.currentPeriod[1].locale('ru').format('D MMMM')}}
</ng-container>
<ng-container *ngIf="!currentLvlPeriod.end">
У Вас последний уровень бонусной программы. Процент начисляемых бонусов:
{{currentLvlPeriod.percent}}%
</ng-container>
</p>
</div>
<span id="bonuses-condition"></span>
<!-- <div class="guest-card__level-info"> -->
<!-- <ng-container *ngIf="!purchaseData.$loading"> -->
<!-- <ng-container *ngIf="currentLvlPeriod.end"> -->
<!-- <\!-- <input -\-> -->
<!-- <\!-- type="range" -\-> -->
<!-- <\!-- [value]="purchaseData.currentAmount" -\-> -->
<!-- <\!-- [min]="currentLvlPeriod.start" -\-> -->
<!-- <\!-- [max]="currentLvlPeriod.end" -\-> -->
<!-- <\!-- [step]="0.01" -\-> -->
<!-- <\!-- disabled="true" -\-> -->
<!-- <\!-- [ngStyle]="{ -\-> -->
<!-- <\!-- 'background-size': ((purchaseData.currentAmount! - currentLvlPeriod.start) / (currentLvlPeriod.end - currentLvlPeriod.start + 1)) * 100 + '% 100%' -\-> -->
<!-- <\!-- }" -\-> -->
<!-- <\!-- /> -\-> -->
<!-- </ng-container> -->
<!-- <ng-container *ngIf="!currentLvlPeriod.end"> -->
<!-- <h2> -->
<!-- У Вас последний уровень бонусной программы. Процент начисляемых бонусов: {{currentLvlPeriod.percent}}% -->
<!-- </h2> -->
<!-- </ng-container> -->
<!-- </ng-container> -->
<!-- <ng-container *ngIf="purchaseData.$loading"> -->
<!-- <ng-container -->
<!-- *ngTemplateOutlet="spinner; context: { $implicit: 48 }" -->
<!-- ></ng-container> -->
<!-- </ng-container> -->
<!-- </div> -->
<app-last-order
[lastOrder]="lastPurchase"
[loading]="purchaseData.$loading"
></app-last-order>
<a class="guest-card__loyalty-program" routerLink="loyality-program"
>Подробнее о правилах <br />
Программы лояльности</a
>
</div>
<ng-template #spinner let-diameter>
<mat-spinner [strokeWidth]="3" [diameter]="diameter"></mat-spinner>
</ng-template>

View File

@ -1,221 +0,0 @@
:host {
.guest-card {
display: flex;
flex-direction: column;
align-items: center;
max-width: 600px;
margin: 0 auto;
.top-info {
padding: 8px 0 0;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
background-color: #292929;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
border: 1px solid #000000;
border-top: 1px solid #888888;
&__level {
width: 100%;
display: flex;
align-items: center;
justify-content: space-around;
font-size: 16px;
}
& p {
color: var(--button-color);
}
p.top-info__bonus{
font-size: 20px;
}
}
&__qr {
margin: 10px;
padding: 10px;
width: fit-content;
background-image: linear-gradient(
#fff 33%,
transparent 0px,
transparent 67%,
#fff 0px
),
linear-gradient(
90deg,
#ffe 33%,
transparent 0px,
transparent 66%,
#fff 0px
),
linear-gradient(#fff 33%, transparent 0px, transparent 67%, #fff 0),
linear-gradient(90deg, #fff 33%, transparent 0, transparent 66%, #fff 0);
background-size: 1px 100%, 100% 1px, 1px 100%, 100% 1px;
background-position: 0 0, 0 0, 100% 100%, 100% 100%;
background-repeat: no-repeat, no-repeat, no-repeat, no-repeat;
cursor: pointer;
}
&__user-description {
background-color: #292929;
padding: 14px 24px;
p {
width: 60%;
text-align: center;
margin: 0 auto;
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 19px;
letter-spacing: -0.5px;
}
.price,
.percent {
font-weight: bold;
}
}
&__purchases-description {
margin: 0;
padding: 14px 24px;
width: 100%;
text-align: center;
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 19px;
letter-spacing: -0.5px;
grid-template-columns: calc(100% - 24px) 24px;
span {
color: #219653;
}
}
&__level-info {
padding-top: 36px;
padding-left: 36px;
padding-right: 36px;
display: flex;
flex-direction: column;
align-items: center;
h2 {
font-style: normal;
font-family: Montserrat;
font-weight: 700;
font-size: 17px;
line-height: 22px;
text-align: center;
letter-spacing: -0.408px;
}
input[type="range"] {
-webkit-appearance: none;
width: 100%;
height: 6px;
border-radius: 5px;
display: block;
position: relative;
background: #231f20;
box-shadow: 0px 0px 3px #f2c94c59;
background-image: linear-gradient(#f2c94c, #f2c94c);
background-size: 70% 100%;
background-repeat: no-repeat;
&::before,
&::after {
content: " ";
display: block;
width: 16px;
height: 16px;
border-radius: 100%;
position: absolute;
top: -5px;
}
&::before {
background-color: #f2c94c;
left: 0px;
}
&::after {
background-color: #f2c94c;
right: 0px;
}
&::-webkit-slider-thumb {
-webkit-appearance: none;
background: #f2c94c;
width: 16px;
height: 16px;
border-radius: 100%;
display: none;
}
&::-ms-thumb {
-webkit-appearance: none;
height: 20px;
width: 20px;
border-radius: 50%;
background: #f2c94c;
cursor: ew-resize;
box-shadow: 0 0 2px 0 #555;
transition: background 0.3s ease-in-out;
}
&::-moz-range-thumb {
-webkit-appearance: none;
height: 20px;
width: 20px;
border-radius: 50%;
background: #f2c94c;
cursor: ew-resize;
box-shadow: 0 0 2px 0 #555;
transition: background 0.3s ease-in-out;
}
}
}
&__download-app {
width: 100%;
position: relative;
margin-top: 32px;
display: flex;
justify-content: flex-end;
img {
width: 100%;
max-width: calc(100% - 16px);
}
}
&__loyalty-program {
text-align: center;
color: #7F2061;
font-style: normal;
font-weight: bold;
font-size: 12px;
line-height: 16px;
text-decoration: none;
margin: 17px 0 22px;
}
}
}
app-accordion {
ul {
li {
list-style-type: disc;
margin-left: 16px;
}
}
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { GuestCardComponent } from './guest-card.component';
describe('GuestCardComponent', () => {
let component: GuestCardComponent;
let fixture: ComponentFixture<GuestCardComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ GuestCardComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(GuestCardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,193 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { MatBottomSheet } from '@angular/material/bottom-sheet';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { ExitComponent } from 'src/app/components/exit/exit.component';
import { CookiesService } from 'src/app/services/cookies.service';
import { WpJsonService } from 'src/app/services/wp-json.service';
import { environment } from 'src/environments/environment';
import moment from 'moment';
import { Purchase, lvlPeriod } from 'src/app/interface/data';
import { lvlPeriods } from 'src/app/app.constants';
interface Moment extends moment.Moment {}
export interface IPurchaseData {
currentPeriod: Moment[];
lastPeriod: Moment[];
lastPurchases: Purchase[];
currentPurchases: Purchase[];
lastAmount?: number;
currentAmount?: number;
$loading: boolean;
}
@Component({
selector: 'app-guest-card',
templateUrl: './guest-card.component.html',
styleUrls: ['./guest-card.component.scss'],
})
export class GuestCardComponent implements OnInit {
public qrCodeSize: number = 85;
private isQrCodeClicked: boolean = false;
public customerInfo!: any;
public purchases!: Purchase[];
public lastPurchase!: Purchase;
public purchaseData: IPurchaseData = {
currentPeriod: [],
lastPeriod: [],
lastPurchases: [],
currentPurchases: [],
$loading: true,
get currentAmount():number {
const amount = this.currentPurchases.reduce((accumulator, currentValue) => {
if (currentValue.transactionType !== 'PayFromWallet') return accumulator;
return accumulator + currentValue.orderSum!;
}, 0);
return amount * 1
},
get lastAmount():number {
const amount = this.lastPurchases.reduce((accumulator, currentValue) => {
if (currentValue.transactionType !== 'PayFromWallet') return accumulator;
return accumulator + currentValue.orderSum!;
}, 0);
return amount * 1
}
};
public discountLevel: number = 4.2;
public lvlPeriods: lvlPeriod[] = lvlPeriods;
public currentLvlPeriod!: lvlPeriod;
public currentLvl: number = 1;
constructor(
private _bottomSheet: MatBottomSheet,
private cookiesService: CookiesService,
private router: Router,
private wpJsonService: WpJsonService
) {}
ngOnInit(): void {
const token = this.cookiesService.getItem('token');
this.getCurrentQuarterOfYear();
this.wpJsonService
.getCustomerInfo(
environment.systemId,
token || '',
environment.icardProxy
)
.subscribe({
next: (value) => {
this.customerInfo = value.customer_info;
this.getPurchases().subscribe((value) => {
this.purchases = value[this.customerInfo?.id].filter(
(purchase: Purchase) =>
[
'PayFromWallet',
'CancelPayFromWallet',
'RefillWallet',
'RefillWalletFromOrder'
].includes(purchase.transactionType || '')
);
this.lastPurchase = this.purchases.filter(
(purchase: Purchase) =>
[
'PayFromWallet',
'RefillWalletFromOrder'
].includes(purchase.transactionType || '')
)[0]
this.purchaseData.lastPurchases = this.purchases.filter((value: Purchase) => {
return moment(value.transactionCreateDate).isBetween(this.purchaseData.lastPeriod[0], this.purchaseData.lastPeriod[1])
})
this.purchaseData.currentPurchases = this.purchases.filter((value: Purchase) => {
return moment(value.transactionCreateDate).isBetween(this.purchaseData.currentPeriod[0], this.purchaseData.currentPeriod[1])
})
const currentAmount = this.purchaseData.currentAmount || 0
const index = this.lvlPeriods.findIndex((item) => item.start <= currentAmount && currentAmount <= (item.end || Infinity))!
if(index != -1) {
this.currentLvlPeriod = this.lvlPeriods[index];
this.currentLvl = index + 1;
this.purchaseData.$loading = false;
}
});
},
});
}
getNextLevel(): lvlPeriod {
if(this.currentLvl == this.lvlPeriods.length) {
return lvlPeriods[this.currentLvl - 1];
}
return lvlPeriods[this.currentLvl];
}
qrCodeClick() {
this.isQrCodeClicked = !this.isQrCodeClicked;
this.qrCodeSize = this.isQrCodeClicked ? 180 : 85;
}
deleteToken(): void {
this.cookiesService.logout();
}
logout() {
const bottomSheet = this._bottomSheet.open(ExitComponent);
bottomSheet.afterDismissed().subscribe({
next: (val) => {
if (val) {
this.deleteToken();
this.router.navigate(['/login']);
}
},
});
}
getPurchases(
start: Date | Moment = moment().subtract(1, 'months').startOf('month'),
end: Date | Moment = moment()
): Observable<any> {
const token = this.cookiesService.getItem('token');
const delta = moment(end).diff(moment(start), 'days');
return this.wpJsonService.getTransactions(
environment.systemId,
token ?? '',
environment.icardProxy
);
}
getCurrentQuarterOfYear() {
const quarters = [
[
moment().subtract(1, 'years').endOf('year').subtract(3, 'months'),
moment().subtract(1, 'years').endOf('year'),
],
[moment().startOf('year'), moment().startOf('year').add(3, 'months')],
[
moment().startOf('year').add(3, 'months'),
moment().startOf('year').add(6, 'months'),
],
[
moment().startOf('year').add(6, 'months'),
moment().startOf('year').add(9, 'months'),
],
[
moment().startOf('year').add(9, 'months'),
moment().startOf('year').add(12, 'months'),
],
];
for (let i = 0; i < 4; i++) {
if (moment().isBetween(quarters[i][0], quarters[i][1])) {
this.purchaseData.lastPeriod = quarters[i - 1];
this.purchaseData.currentPeriod = quarters[i];
}
}
}
getBalanceAmount(loyaltyPrograms: any[]) {
return loyaltyPrograms.reduce((accumulator, currentValue) => {
return accumulator + currentValue.balance;
}, 0);
}
}

View File

@ -1,107 +0,0 @@
<app-navbar
*ngIf="phoneForm.value.phone && !isShowNumber"
[title]="phoneForm.value.phone"
(backEvent)="backToPhoneForm()"
[ngStyle]="{
position: 'absolute',
top: 0
}"
></app-navbar>
<h1>Участвуй в программе лояльности COFFEE LIKE</h1>
<p class="description">Начни получать бонусы прямо сейчас</p>
<form
*ngIf="isShowNumber; else smsCode"
(ngSubmit)="submitNumber()"
[formGroup]="phoneForm"
>
<!-- <div class="input-container"> -->
<mat-form-field appearance="outline">
<mat-label>Ваше имя</mat-label>
<input formControlName="name" matInput type="text" />
</mat-form-field>
<!-- </div> -->
<div class="input-container">
<!-- <label for="number">Номер телефона</label>
<input id="number" type="text" placeholder="Введите номер" /> -->
<mat-form-field appearance="outline">
<mat-label>Номер телефона</mat-label>
<ngx-mat-intl-tel-input
formControlName="phone"
[enablePlaceholder]="true"
[enableSearch]="false"
[onlyCountries]="['ru', 'kg', 'by', 'kz', 'fi', 'de']"
[preferredCountries]="['ru']"
name="phone"
#phone
>
</ngx-mat-intl-tel-input>
</mat-form-field>
</div>
<p class="offer">
Используя приложение, вы принимаете условия в <span>соглашениях</span> и
соглашаетесь на получение рекламно-информационных сообщений
</p>
<button [disabled]="phoneForm.invalid">Принять участие</button>
</form>
<ng-template #smsCode>
<h2>Введите код из SMS</h2>
<form class="code-form" [formGroup]="codeForm" (ngSubmit)="submitCode()">
<div class="inputs-container">
<label class="box"
><input
class="field"
id="field"
type="tel"
placeholder="•"
#field
[appFocusNextInput]="inputFocusEmitter"
formControlName="code"
maxlength="1"
/></label>
<label class="box"
><input
class="field"
id="field1"
type="tel"
placeholder="•"
#field1
[appFocusNextInput]="inputFocusEmitter"
formControlName="code1"
maxlength="1"
/></label>
<label class="box"
><input
class="field"
id="field2"
type="tel"
placeholder="•"
#field2
[appFocusNextInput]="inputFocusEmitter"
formControlName="code2"
maxlength="1"
/></label>
<label class="box"
><input
class="field"
id="field3"
type="tel"
placeholder="•"
#field3
[appFocusNextInput]="inputFocusEmitter"
formControlName="code3"
maxlength="1"
/></label>
</div>
<button>Войти</button>
</form>
<p class="resend-code">
Не пришло SMS?<br />
<ng-container *ngIf="timeLeft">
Отправим повторно через {{timeLeft}}с
</ng-container>
<ng-container *ngIf="!timeLeft">
<span class="resend" (click)="submitNumber()">Отправить повторно</span>
</ng-container>
</p>
</ng-template>

View File

@ -1,214 +0,0 @@
:host {
padding-top: 48px;
display: flex;
flex-direction: column;
align-items: center;
max-width: 600px;
margin: 0 auto 52px;
h1 {
margin-top: 20px;
width: 302px;
font-style: normal;
font-weight: 700;
font-size: 17px;
line-height: 22px;
text-align: center;
letter-spacing: -0.408px;
}
h2 {
margin-top: 44px;
font-style: normal;
font-weight: 700;
font-size: 20px;
line-height: 24px;
text-align: center;
letter-spacing: 0.38px;
}
.description {
width: 180px;
font-style: normal;
font-weight: 400;
font-size: 15px;
line-height: 20px;
text-align: center;
letter-spacing: -0.24px;
margin-top: 16px;
}
form {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 35px;
.offer {
margin-top: 10px;
padding: 0 16px;
font-family: "Gowun Dodum";
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 17px;
text-align: center;
span {
color: #13a538;
}
}
.input-container {
position: relative;
width: 100%;
label {
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 16px;
color: #6a737c;
text-align: left;
position: absolute;
top: 10px;
left: 16px;
}
input {
width: 100%;
padding: 24px 16px 8px;
background-color: #252323;
margin-bottom: 16px;
border: none;
border-top: solid #6a737c 1px;
border-bottom: solid #6a737c 1px;
color: #6a737c;
font-style: normal;
font-weight: 400;
font-size: 22px;
line-height: 28px;
}
}
button {
height: 46px;
width: calc(100% - 32px);
padding: 10px 24px;
background: #28af49;
border-radius: 6px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
border: none;
letter-spacing: -0.408px;
color: #ffffff;
font-style: normal;
font-weight: 700;
font-size: 17px;
line-height: 22px;
&:disabled {
background-color: #344a3a;
}
}
}
.code-form {
width: 100%;
// input {
// width: 100%;
// padding: 24px 16px 8px;
// background-color: #252323;
// margin-bottom: 16px;
// border: none;
// border-top: solid #6a737c 1px;
// border-bottom: solid #6a737c 1px;
// color: #6a737c;
// font-style: normal;
// font-weight: 400;
// font-size: 22px;
// line-height: 28px;
// }
.inputs-container {
width: 102px;
display: flex;
flex-direction: row;
justify-content: space-between;
margin-bottom: 40px;
// code
.box {
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: 42px;
width: 42px;
border-radius: 6px;
// box-shadow: 0 0 6px 1px hsla(240, 54%, 61%, 0.2);
overflow: hidden;
will-change: transform;
}
.box:focus-within {
box-shadow: 0 0 6px 1px rgba($color: #28af49, $alpha: 0.2),
0 0 0 2px rgba($color: #28af49, $alpha: 0.6);
}
.box::before,
.box::after {
content: "";
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
border-radius: 6px;
overflow: hidden;
}
.box::before {
// background: hsl(240, 54%, 97%);
z-index: 1;
transition: background-color 450ms cubic-bezier(0.25, 0.01, 0.25, 1);
}
.box::after {
transform: translateY(100%);
background-color: hsl(145, 0%, 42%);
opacity: 0;
z-index: 10;
transition: transform 450ms cubic-bezier(0.25, 0.01, 0.25, 1),
opacity 450ms cubic-bezier(0.25, 0.01, 0.25, 1),
background-color 450ms cubic-bezier(0.25, 0.01, 0.25, 1);
}
.field {
position: relative;
border: 0;
outline: 0;
font-size: 25.21px;
line-height: 42px;
color: #fff;
background-color: transparent;
text-align: center;
z-index: 100;
}
.field::placeholder {
color: #fff;
}
}
}
.resend-code {
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 16px;
text-align: center;
margin-top: 23px;
.resend {
cursor: pointer;
}
}
}
mat-form-field {
width: 100%;
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginComponent } from './login.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ LoginComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,168 +0,0 @@
import {
AfterViewInit,
Component,
EventEmitter,
HostListener,
OnInit
} from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router';
import { MessageService } from 'primeng/api';
import { CookiesService } from 'src/app/services/cookies.service';
import { JsonrpcService, RpcService } from 'src/app/services/jsonrpc.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss'],
})
export class LoginComponent implements OnInit, AfterViewInit {
public isShowNumber: boolean = true;
public phoneForm = new FormGroup({
name: new FormControl('', []),
phone: new FormControl('', [Validators.required]),
});
public codeForm = new FormGroup({
code: new FormControl('', [Validators.required]),
code1: new FormControl('', [Validators.required]),
code2: new FormControl('', [Validators.required]),
code3: new FormControl('', [Validators.required]),
});
private inputIds = ['field', 'field1', 'field2', 'field3'];
timeLeft: number = 0;
constructor(
private cookiesService: CookiesService,
private router: Router,
private jsonrpc: JsonrpcService,
private messageService: MessageService,
private _snackBar: MatSnackBar
) { }
ngOnInit(): void { }
ngAfterViewInit() {
setTimeout(() => {
this.inputFocusEmitter.emit(`#${this.inputIds[0]}`);
}, 1000)
}
public inputFocusEmitter = new EventEmitter<string>();
@HostListener('window:keyup', ['$event'])
HandlKeyEvents(event: any) {
if (!event.target.classList.contains('field')) return;
const key = event.key.toLocaleLowerCase();
let elementId = '';
switch (key) {
case 'backspace':
elementId = event.target.id;
event.target.value = '';
const prevInputIndex = this.inputIds.indexOf(elementId) - 1;
if (prevInputIndex >= 0) {
this.inputFocusEmitter.emit(`#${this.inputIds[prevInputIndex]}`);
}
break;
default:
elementId = event.target.id;
const index = this.inputIds.indexOf(elementId);
const nextInputIndex = index + 1;
if (event.target.value.length > 1) {
event.target.value = event.target.value.slice(-1);
}
if (nextInputIndex > 0 && nextInputIndex <= this.inputIds.length) {
this.inputFocusEmitter.emit(`#${this.inputIds[nextInputIndex]}`);
}
break;
}
}
submitNumber() {
const data = this.phoneForm.value;
this.isShowNumber = false;
if (this.timeLeft) {
this.messageService.clear();
this.messageService.add({
severity: 'custom',
summary: `Отправить повторно можно через ${this.timeLeft}с`,
});
return;
}
this.jsonrpc.rpc({
method: 'sendVerifyByPhone',
params: [data.phone]
}, RpcService.authService, false).subscribe({
next: (result) => {
if (result.code !== 0) {
this._snackBar.open('Произошла ошибка! Попробуйте позже', '', {
duration: 3000
})
}
if (result.code === 0) {
this.timeLeft = 60;
const interval = setInterval(() => {
if (this.timeLeft > 0) {
this.timeLeft--;
} else {
clearInterval(interval);
}
}, 1000)
}
this.isShowNumber = false;
},
error: (error) => {
console.error('Error: ', error);
}
}
);
setTimeout(() => {
this.inputFocusEmitter.emit(`#${this.inputIds[0]}`);
}, 0)
}
submitCode() {
const data = this.codeForm.value;
this.jsonrpc.rpc({
method: 'getTokenByPhone',
params: [this.phoneForm.value.phone, Object.values(data).join('')]
}, RpcService.authService, false).subscribe({
next: (result) => {
if (result.code === 0) {
this.cookiesService.setCookie('token', result?.data?.token);
this.router.navigate(['/'], {
queryParams: {
token: result?.data?.token
},
});
// this.phoneConfirmed.emit(null);
} else if (result.code === 230) {
this._snackBar.open('Неверный код!', '', {
duration: 3000
})
// this.errorConfirmCode = true;
}
},
error: (error) => {
console.error(error);
}
}
);
}
backToPhoneForm() {
this.codeForm.setValue({
code: '',
code1: '',
code2: '',
code3: ''
})
this.isShowNumber = true
}
}

View File

@ -1,99 +0,0 @@
<app-navbar title="Программа лояльности" (backEvent)="goBack()"></app-navbar>
<div class="loyality-program">
<app-accordion header="Условия начисления бонусов">
<p>
Расчет начисления бонусов - 10% от суммы покупок за период с 11.01.2023г.
по 31.03.2023 г.
</p>
<p>
За период с 11.01.2023г. по 31.03.2023 г. сумма ваших покупок составила
3700 руб.
</p>
<p>Начисляемый бонус 10% от суммы покупок</p>
</app-accordion>
<app-accordion header="Условия «оплаты» покупки бонусами">
<p>
Участник может использовать Бонусы для «оплаты» до 100% стоимости любой
покупки.
</p>
<p>
Списание Бонусов происходит из расчета 1:1 (один Бонус дает скидку 1
российский рубль / 1 тенге / 1 белорусский рубль. Скидка, предоставляемая
Участнику при списании Бонусов, уменьшает цену товаров в заказе в
соответствии с условиями ПЛ.
</p>
<p>
Для списания Бонусов Участник должен попросить об этом в кофе-баре сети
«COFFEE LIKE» кассира до момента пробития фискального чека, после чего им
будет проверена возможность списания Бонусов.
</p>
<p>
Для всех Участников возможно списание без использования мобильного
приложения.
</p>
<p>Полученные Бонусы не подлежат обмену на денежные средства.</p>
</app-accordion>
<app-accordion header="Особые условия">
<p>
Начисленные на счет бонусы сгорают по прошествии 90 дней с момента
совершения последней покупки с начислением или списанием бонусов.
</p>
<ul>
Возврат покупки, за которую бонусы были начислены:
<li>
В случае, если бонусов на счету достаточно для списания, бонусы
списываются в полном ранее начисленном за возвращаемый товар объеме.
</li>
<li>
В случае, если бонусов на счету недостаточно, формируется минусовой
баланс.
</li>
</ul>
<ul>
Возврат покупки, которая была оплачена бонусами:
<li>
В случае предъявления Участником кассового или товарного чека, сумма
бонусов, списанная для оплаты возвращаемого товара, зачисляется на счет
участника.
</li>
<li>
В случае возврата товара с применением оплаты бонусами, клиенту
возвращается денежная сумма в размере, внесенном Участником в оплату
товара при покупке, за вычетом суммы, оплаченной бонусами.
</li>
</ul>
</app-accordion>
<app-accordion header="Узнать % начисляемых бонусов">
<p>
Начисление Бонусных баллов происходит по дифференцированной шкале в
зависимости от уровня:
</p>
<ng-container
*ngFor="let item of lvlPeriods; let index = index; let last = last"
>
<ng-container *ngIf="!last">
<ul>
<span [style]="{ color: item.color }">Уровень {{ index + 1 }}</span>
<li>
Сумма покупок за предыдущий период {{ item.start }}-{{ item.end }}
руб.
</li>
<li>Начисляемый бонус {{ item.percent }}% от суммы покупки</li>
</ul>
<br />
</ng-container>
<ng-container *ngIf="last">
<ul>
<span [style]="{ color: item.color }">Уровень {{ index + 1 }}</span>
<li>Сумма покупок за предыдущий период — от {{ item.start }} руб.</li>
<li>Начисляемый бонус, в % от суммы покупки - {{ item.percent }}%</li>
</ul>
</ng-container>
</ng-container>
</app-accordion>
</div>

View File

@ -1,3 +0,0 @@
.loyality-program {
margin-bottom: 20px;
}

View File

@ -1,21 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { lvlPeriod } from 'src/app/interface/data';
import { lvlPeriods } from 'src/app/app.constants';
@Component({
selector: 'loyality-program',
templateUrl: './loyality-program.component.html',
styleUrls: ['./loyality-program.component.scss'],
})
export class LoyalityProgramComponent implements OnInit {
constructor(private _location: Location) {}
public lvlPeriods: lvlPeriod[] = lvlPeriods;
goBack() {
this._location.back();
}
ngOnInit(): void {}
}

View File

@ -1,7 +0,0 @@
<div class="main-container">
<!-- <app-navbar></app-navbar> -->
<p-toast position="top-center"></p-toast>
<app-footer-buttons [token]="token"
[isPermissionNotifications]="isPermissionNotifications"
(requestingPermission)="requestPermission()"></app-footer-buttons>
</div>

View File

@ -1,8 +0,0 @@
<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>

View File

@ -1,28 +0,0 @@
:host {
.not-found-page {
&__container {
text-align: center;
margin-top: 32px;
h1 {
font-size: 108px;
font-weight: 600;
color: var(--main-color);
}
p {
margin: 16px 0;
font-size: 14px;
}
button {
background-color: var(--button-color);
color: var(--text-color);
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
padding: 12px;
margin: 0 auto;
border: 0;
}
}
}
}

View File

@ -1,23 +0,0 @@
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();
});
});

View File

@ -1,20 +0,0 @@
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(['/']);
}
}

View File

@ -1,7 +0,0 @@
<div class="tab">
<input [id]="'tab-' + guid" type="checkbox" name="tabs" />
<label [for]="'tab-' + guid">{{ header }}</label>
<div class="tab-content">
<ng-content></ng-content>
</div>
</div>

View File

@ -1,83 +0,0 @@
:host {
width: 100%;
}
.tab {
position: relative;
margin-bottom: 1px;
width: 100%;
color: var(--text-color);
overflow: hidden;
border-bottom: solid 1px #bdbdbd;
}
.tab input {
position: absolute;
opacity: 0;
z-index: -1;
}
.tab label {
display: block;
padding: 20px 26px;
position: relative;
font-weight: 400;
font-size: 12px;
line-height: 14px;
letter-spacing: -0.5px;
cursor: pointer;
}
// .tab label:before {
// display: block;
// content: " ";
// padding-top: 5px;
// }
.tab-content {
max-height: 0;
overflow: hidden;
-webkit-transition: all 0.35s;
-o-transition: all 0.35s;
transition: all 0.35s;
border-top: solid 1px #bdbdbd;
font-style: normal;
font-weight: 400;
font-size: 12px;
p {
margin: 0;
}
}
.tab-content p {
margin: 1em;
}
/* :checked */
.tab input:checked ~ .tab-content {
padding: 16px 26px;
max-height: 100vh;
}
/* Icon */
.tab label::after {
position: absolute;
right: 0;
top: 0;
line-height: 3;
text-align: center;
-webkit-transition: all 0.35s;
-o-transition: all 0.35s;
transition: all 0.35s;
height: 100%;
margin-right: 12px;
display: flex;
align-items: center;
}
.tab input[type="checkbox"] + label::after {
content: "+";
}
.tab input[type="radio"] + label::after {
content: "\25BC";
}
.tab input[type="checkbox"]:checked + label::after {
transform: rotate(315deg);
}
.tab input[type="radio"]:checked + label::after {
transform: rotateX(180deg);
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AccordionComponent } from './accordion.component';
describe('AccordionComponent', () => {
let component: AccordionComponent;
let fixture: ComponentFixture<AccordionComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ AccordionComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(AccordionComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,23 +0,0 @@
import { Component, Input, OnInit } from '@angular/core';
import { v4 as uuidv4 } from 'uuid';
export interface IAccordionData {
header: string;
body: string;
}
@Component({
selector: 'app-accordion[header]',
templateUrl: './accordion.component.html',
styleUrls: ['./accordion.component.scss']
})
export class AccordionComponent implements OnInit {
@Input() header!: string
public guid: string = uuidv4()
constructor() { }
ngOnInit(): void {
}
}

View File

@ -1,29 +0,0 @@
:host {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
padding-bottom: 100px;
padding-top: 52px;
h3 {
margin: 0;
font-family: Montserrat;
font-style: normal;
font-weight: 400;
font-size: 15px;
line-height: 20px;
text-align: center;
letter-spacing: -0.24px;
color: #6a737c;
}
.phone-number {
font-style: normal;
font-weight: 700;
font-size: 17px;
line-height: 22px;
text-align: center;
letter-spacing: -0.408px;
color: #d9d9d9;
text-decoration: none;
}
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FooterComponent } from './footer.component';
describe('FooterComponent', () => {
let component: FooterComponent;
let fixture: ComponentFixture<FooterComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ FooterComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(FooterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,15 +0,0 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-footer',
templateUrl: './footer.component.html',
styleUrls: ['./footer.component.scss']
})
export class FooterComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { IndexComponent } from './index.component';
describe('IndexComponent', () => {
let component: IndexComponent;
let fixture: ComponentFixture<IndexComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ IndexComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(IndexComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,15 +0,0 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-index',
templateUrl: './index.component.html',
styleUrls: ['./index.component.scss']
})
export class IndexComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@ -1,25 +0,0 @@
<h2>Пригласи друзей!</h2>
<div class="container">
<p>
Пригласи друзей зарегистрироваться в приложении по твоему уникальному коду и
получи бонусы, когда они совершат первую покупку.
</p>
<button class="share" (click)="share()" [disabled]="loading">
<ng-container *ngIf="loading">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 24 }"
></ng-container>
</ng-container>
<mat-icon
*ngIf="!loading"
aria-hidden="false"
aria-label="Share"
fontIcon="share"
style="color: #fff"
></mat-icon>
</button>
</div>
<ng-template #spinner let-diameter>
<mat-spinner [strokeWidth]="3" [diameter]="diameter"></mat-spinner>
</ng-template>

View File

@ -1,34 +0,0 @@
:host {
padding: 16px;
h2 {
font-family: Montserrat;
font-style: normal;
font-weight: 700;
font-size: 17px;
line-height: 22px;
letter-spacing: -0.408px;
}
& .container {
width: 100%;
display: flex;
flex-direction: row;
gap: 16px;
p {
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 16px;
color: var(--text-color);
}
.share {
width: 72px;
height: 48px;
background: var(--button-color);
padding: 8px 26px;
border: none;
}
}
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { InviteFriendsComponent } from './invite-friends.component';
describe('InviteFriendsComponent', () => {
let component: InviteFriendsComponent;
let fixture: ComponentFixture<InviteFriendsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ InviteFriendsComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(InviteFriendsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,54 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { MessageService } from 'primeng/api';
import { lastValueFrom } from 'rxjs';
import { JsonrpcService, RpcService } from 'src/app/services/jsonrpc.service';
import { environment } from 'src/environments/environment';
@Component({
selector: 'app-invite-friends',
templateUrl: './invite-friends.component.html',
styleUrls: ['./invite-friends.component.scss']
})
export class InviteFriendsComponent implements OnInit {
public refUrl: string = `${environment.defaultUrl}/?refUserId=`
public loading: boolean = true;
private shareData: ShareData = {
title: ''
}
constructor(
private jsonrpc: JsonrpcService,
private messageService: MessageService
) { }
async ngOnInit() {
const accountData = (await lastValueFrom(
this.jsonrpc
.rpc(
{
method: 'getTokenData',
params: [],
},
RpcService.authService,
true
)
)).data
this.refUrl += accountData.user_id
this.loading = false
}
share() {
if (navigator.share) {
navigator.share({
title: document.title,
text: "Coffee Like More",
url: this.refUrl
})
.then(() => console.log('Successful share'))
.catch((error) => {
console.log('Error sharing:', error)
});
}
}
}

View File

@ -1,32 +0,0 @@
<h2>Ваш предыдущий заказ</h2>
<div class="info-order">
<p class="flex"><span>Дата: </span>
<span *ngIf="!loading">{{(lastOrder?.transactionCreateDate | date:'dd.MM.yyyyг.') || 'Данные не найдены'}}</span>
<ng-container *ngIf="loading">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 24 }"
></ng-container>
</ng-container>
</p>
<p class="flex"><span>На сумму: </span>
<span *ngIf="!loading">{{lastOrder?.orderSum ? lastOrder?.orderSum + ' ₽' : 'Данные не найдены'}}</span>
<ng-container *ngIf="loading">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 24 }"
></ng-container>
</ng-container>
</p>
</div>
<img src="./assets/970х250_3.png" alt="" width="100%" />
<a href="https://yandex.ru/profile/151770398186" target="_blank">
<button class="evaluate-order">Оценить заказ</button>
</a>
<p class="info">
Списание бонусов возможно на любые категории. Бонусами можно оплатить 100%
суммы покупки. Бонусы начисляются только на напитки с учётом добавок.
Неиспользованные бонусы сгорают в течение 90 дней.
</p>
<ng-template #spinner let-diameter>
<mat-spinner [strokeWidth]="3" [diameter]="diameter"></mat-spinner>
</ng-template>

View File

@ -1,51 +0,0 @@
:host {
padding: 24px 16px 0px;
& > h2 {
font-style: normal;
font-weight: 700;
font-size: 15px;
line-height: 20px;
letter-spacing: -0.24px;
}
& > .info-order {
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 16px;
span {
color: var(--text-color_1);
}
.flex {
display: flex;
align-items: center;
flex-direction: row;
gap: 8px;
}
}
.evaluate-order {
margin: 24px 0;
width: 100%;
padding: 12px;
text-align: center;
border: 2px solid var(--button-color);
border-radius: 6px;
font-style: normal;
font-weight: 700;
font-size: 17px;
line-height: 22px;
letter-spacing: -0.408px;
background-color: transparent;
color: var(--button-color);
}
.info {
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 16px;
color: var(--text-color_1);
}
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LastOrderComponent } from './last-order.component';
describe('LastOrderComponent', () => {
let component: LastOrderComponent;
let fixture: ComponentFixture<LastOrderComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ LastOrderComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(LastOrderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,18 +0,0 @@
import { Component, Input, OnInit } from '@angular/core';
import { Purchase } from 'src/app/interface/data';
@Component({
selector: 'app-last-order[lastOrder]',
templateUrl: './last-order.component.html',
styleUrls: ['./last-order.component.scss']
})
export class LastOrderComponent implements OnInit {
@Input() lastOrder?: Purchase;
@Input() loading!: boolean;
constructor() { }
ngOnInit(): void {
}
}

View File

@ -1,3 +0,0 @@
<li class="menu-item">
<ng-content></ng-content>
</li>

View File

@ -1,16 +0,0 @@
.menu-item {
display: flex;
gap: 10px;
align-items: center;
padding: 10px;
cursor: pointer;
transition: background-color 0.1s;
&:hover {
background-color: var(--main-color_hover);
}
.icon {
}
}

View File

@ -1,18 +0,0 @@
import { Component, Input, HostListener, } from "@angular/core";
@Component({
selector: 'menu-item',
templateUrl: './menu_item.component.html',
styleUrls: ['./menu_item.component.scss'],
})
export class MenuItemComponent {
@Input()
handler?: (e: any) => void;
@HostListener('click', ['$event'])
onClick(e: any) {
if (this.handler) {
this.handler(e);
}
}
}

View File

@ -1,33 +0,0 @@
<div class="container">
<div class="back">
<mat-icon *ngIf="backEvent" style="cursor: pointer;" aria-hidden="false" aria-label="Назад" fontIcon="arrow_back_ios" class="back-arrow" (click)="back()"></mat-icon>
</div>
<h1 class="title">{{title}}</h1>
<!-- <div class="plug"></div> -->
<div *ngIf="showDropdown" class="backdrop" (click)="closeMenu()"></div>
<div *ngIf="showMenu" class="menu">
<button mat-button (click)="toggleMenu()">
<span class="material-icons" style="color: var(--text-color)">
more_horiz
</span>
</button>
<div class="menu__dropdown" *ngIf="showDropdown">
<ul>
<menu-item [handler]="handler(addToWallet)">
<img src="./assets/apple_wallet.svg" class="icon" width="24" height="24" />
<span class="item_title">Добавить карточку в Wallet</span>
</menu-item>
<menu-item [handler]="handler(logout)">
<span class="material-icons" style="color: var(--main-color)">
logout
</span>
<span class="item_title">Выйти</span>
</menu-item>
</ul>
</div>
</div>
<div class="wrapper" *ngIf="!showMenu">
<button mat-stroked-button appDownloadApp>Установить</button>
</div>
</div>

View File

@ -1,78 +0,0 @@
:host {
width: 100%;
.notification {
img {
width: 28px;
height: 28px;
}
}
}
.container {
box-sizing: border-box;
padding: 12px 16px;
width: 100%;
background: var(--header-color);
color: var(--text-color);
display: grid;
justify-content: space-between;
grid-template-columns: auto auto auto;
justify-items: center;
align-items: center;
.back {
width: 40px;
}
.back-arrow {
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
}
.plug {
height: 24px;
width: 24px;
visibility: hidden;
}
.title {
font-weight: 700;
font-size: 17px;
line-height: 22px;
margin: 0;
}
.wrapper {
display: flex;
align-items: center;
gap: 10px;
min-width: 40px;
}
.menu {
position: relative;
.menu__dropdown {
overflow: hidden;
z-index: 110;
position: fixed;
background-color: white;
width: fit-content;
height: fit-content;
right: 20px;
border-radius: 6px;
box-shadow: 0px 2px 5px -3px black;
.item_title {
color: var(--background-color);
font-size: 14px;
font-style: normal;
}
}
}
.backdrop {
z-index: 100;
position: absolute;
width: 100vw;
left: 0;
top: 0;
height: 100vh;
}
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NavbarComponent } from './navbar.component';
describe('NavbarComponent', () => {
let component: NavbarComponent;
let fixture: ComponentFixture<NavbarComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ NavbarComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(NavbarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,82 +0,0 @@
import { Component, Input, OnInit } from '@angular/core';
import { MessagingService } from 'src/app/services/messaging.service';
import { getTypeDevice, DeviceType } from 'src/app/utils';
import { AppleWalletService } from 'src/app/services/apple-wallet.service';
import { CookiesService } from 'src/app/services/cookies.service';
import { MatBottomSheet } from '@angular/material/bottom-sheet';
import { ExitComponent } from 'src/app/components/exit/exit.component';
import { AuthService } from 'src/app/services/auth.service';
@Component({
selector: 'app-navbar[title]',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit {
@Input() title: string = 'Название не задано'
@Input() backEvent?: () => void;
showMenu: boolean = false;
showDropdown: boolean = false;
constructor(
public messagingService: MessagingService,
private appleWalletService: AppleWalletService,
private cookiesService: CookiesService,
private _bottomSheet: MatBottomSheet,
private authService: AuthService,
) { }
handler(cb: () => void): (e: any) => void {
return (e: any) => {
cb();
this.closeMenu();
}
}
ngOnInit(): void {
const deviceType = getTypeDevice();
this.showMenu = deviceType === DeviceType.ios;
}
toggleMenu() {
this.showDropdown = !this.showDropdown;
}
openMenu() {
this.showDropdown = true;
}
closeMenu = () => {
this.showDropdown = false;
}
back() {
if (this.backEvent) {
this.backEvent();
}
}
addToWallet = () => {
if (this.authService.userInfo) {
this.appleWalletService.addCardToWallet(this.authService.userInfo);
}
}
deleteToken = (): void => {
this.cookiesService.logout();
}
logout = () => {
const bottomSheet = this._bottomSheet.open(ExitComponent);
bottomSheet.afterDismissed().subscribe({
next: (val) => {
if (val) {
this.authService.logout();
}
},
});
}
}

View File

@ -1,3 +0,0 @@
<a *ngFor="let link of links" [href]="link.url" target="_blank">
<img [src]="link.imgUrl" [alt]="link.label" />
</a>

View File

@ -1,15 +0,0 @@
:host {
display: flex;
flex-direction: row;
gap: 16px;
justify-content: space-between;
a {
width: 48px;
height: 48px;
border-radius: 100%;
background: var(--button-color);
display: flex;
align-items: center;
justify-content: center;
}
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SocialMediaButtonsComponent } from './social-media-buttons.component';
describe('SocialMediaButtonsComponent', () => {
let component: SocialMediaButtonsComponent;
let fixture: ComponentFixture<SocialMediaButtonsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ SocialMediaButtonsComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(SocialMediaButtonsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,38 +0,0 @@
import { Component, OnInit } from '@angular/core';
export interface ISocialMediaLink {
url: string;
imgUrl: string;
label: string;
}
@Component({
selector: 'app-social-media-buttons',
templateUrl: './social-media-buttons.component.html',
styleUrls: ['./social-media-buttons.component.scss']
})
export class SocialMediaButtonsComponent implements OnInit {
public links: ISocialMediaLink[] = [
{
label: 'Инстаграм',
url: 'https://instagram.com/coffeelike_com?igshid=MzRlODBiNWFlZA==',
imgUrl: '/assets/social-media-icons/instagram.svg'
},
{
label: 'ВК',
url: 'https://vk.com/coffeelike_com',
imgUrl: '/assets/social-media-icons/vk.svg'
},
{
label: 'Youtube',
url: 'https://www.youtube.com/c/coffeelikeru',
imgUrl: '/assets/social-media-icons/youtube.svg'
}
]
constructor() { }
ngOnInit(): void {
}
}

View File

@ -1,33 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { GuestCardComponent } from './pages/guest-card/guest-card.component';
import { AuthGuard } from 'src/app/guards/auth-guard.guard';
import { LoginComponent } from './pages/login/login.component';
import { LoyalityProgramComponent } from './pages/loyality-program/loyality-program.component';
import { CreateUserComponent } from './pages/create_user/create_user.component';
const routes: Routes = [
{
path: '',
component: GuestCardComponent,
canActivate: [AuthGuard],
},
{
path: 'login',
component: LoginComponent
},
{
path: 'loyality-program',
component: LoyalityProgramComponent,
},
{
path: 'create_user',
component: CreateUserComponent,
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class DefaultOptionRoutingModule { }

View File

@ -1,63 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DefaultOptionRoutingModule } from './default-option-routing.module';
import { IndexComponent } from './components/index/index.component';
import { FooterComponent } from './components/footer/footer.component';
import { SocialMediaButtonsComponent } from './components/social-media-buttons/social-media-buttons.component';
import { NavbarComponent } from './components/navbar/navbar.component';
import { MenuItemComponent } from './components/navbar/menu_item.component';
import { MatIconModule } from '@angular/material/icon';
import { MatSelectModule } from '@angular/material/select';
import { GuestCardComponent } from './pages/guest-card/guest-card.component';
import { QrCodeModule } from 'ng-qrcode';
import { AccordionComponent } from './components/accordion/accordion.component';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { LastOrderComponent } from './components/last-order/last-order.component';
import { InviteFriendsComponent } from './components/invite-friends/invite-friends.component';
import { LoginComponent } from './pages/login/login.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { NgxMatIntlTelInputComponent } from 'ngx-mat-intl-tel-input';
import { MatInputModule } from '@angular/material/input';
import { DirectivesModule } from 'src/app/directives/directives.module';
import { LoyalityProgramComponent } from './pages/loyality-program/loyality-program.component';
import { MatButtonModule } from '@angular/material/button';
import { ToastModule } from 'primeng/toast';
import { CreateUserComponent } from './pages/create_user/create_user.component';
import { TextMaskModule } from 'angular2-text-mask';
@NgModule({
declarations: [
IndexComponent,
FooterComponent,
SocialMediaButtonsComponent,
NavbarComponent,
GuestCardComponent,
AccordionComponent,
LastOrderComponent,
InviteFriendsComponent,
LoginComponent,
LoyalityProgramComponent,
MenuItemComponent,
CreateUserComponent,
],
imports: [
TextMaskModule,
ToastModule,
CommonModule,
DefaultOptionRoutingModule,
MatIconModule,
QrCodeModule,
MatProgressSpinnerModule,
FormsModule,
MatFormFieldModule,
NgxMatIntlTelInputComponent,
ReactiveFormsModule,
MatInputModule,
DirectivesModule,
MatButtonModule,
MatSelectModule,
],
bootstrap: [IndexComponent],
})
export class DefaultOptionModule { }

View File

@ -1,43 +0,0 @@
<ng-container *ngIf="!authService.loading">
<form
(ngSubmit)="submit()"
[formGroup]="form"
>
<div class="container center">
<div class="form">
<h1>Регистрация</h1>
<mat-form-field appearance="outline">
<mat-label>Ваше имя</mat-label>
<input formControlName="name" matInput type="text" />
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Пол</mat-label>
<mat-select formControlName="sex">
<mat-option value="0">Не выбран</mat-option>
<mat-option value="1">Мужчина</mat-option>
<mat-option value="2">Женщина</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Дата рождения</mat-label>
<input (click)="focusHandler($event)" (blur)="blurHandler()" formControlName="date" matInput [textMask]="mask" type="text" inputmode="numeric">
</mat-form-field>
<button mat-raised-button color="primary">Зарегистрироваться</button>
</div>
</div>
</form>
</ng-container>
<ng-container *ngIf="authService.loading">
<div class="spinner-container">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 85 }"
></ng-container>
</div>
</ng-container>
<ng-template #spinner let-diameter>
<div class="center wrapper">
<mat-spinner [strokeWidth]="3" [diameter]="diameter"></mat-spinner>
</div>
</ng-template>

Some files were not shown because too many files have changed in this diff Show More