Merge branch 'tasty-coffee' of https://git.hlcompany.ru/git/usersite into tasty-coffee

# Conflicts:
#	angular/angular.json
#	angular/src/app/app.component.ts
#	angular/src/app/interface/data.ts
#	angular/src/app/presentation-options/default-option/components/navbar/navbar.component.html
#	angular/src/app/presentation-options/default-option/components/navbar/navbar.component.scss
#	angular/src/app/presentation-options/default-option/components/navbar/navbar.component.ts
#	angular/src/app/presentation-options/default-option/default-option.module.ts
#	angular/src/app/presentation-options/default-option/pages/guest-card/guest-card.component.html
#	angular/src/app/presentation-options/default-option/pages/guest-card/guest-card.component.scss
#	angular/src/app/presentation-options/default-option/pages/guest-card/guest-card.component.ts
#	angular/src/app/presentation-options/default-option/pages/login/login.component.html
#	angular/src/app/presentation-options/default-option/pages/login/login.component.scss
#	angular/src/app/services/auth.service.ts
#	angular/src/environments/environment.prod.ts
#	angular/src/environments/environment.ts
#	angular/src/manifest.webmanifest
#	angular/src/styles.scss
This commit is contained in:
gofnnp 2023-09-12 14:42:41 +04:00
commit 188f93e2b3
16 changed files with 218 additions and 207 deletions

View File

@ -118,4 +118,4 @@ import { DirectivesModule } from './directives/directives.module';
],
bootstrap: [AppComponent],
})
export class AppModule { }
export class AppModule {}

View File

@ -7,57 +7,27 @@ import {
} from '@angular/core';
import { MessageService } from 'primeng/api';
import { getTypeDevice, pwaInstalled } from 'src/app/utils';
import { AppComponent } from '../app.component';
@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,
) { }
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()) {
if (AppComponent.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) {
if (!AppComponent.pwaPrompt) {
this.messageService.clear();
this.messageService.add({
severity: 'error',
@ -65,8 +35,8 @@ export class DownloadAppDirective implements OnInit {
});
return;
}
this.deferredPrompt.prompt();
this.deferredPrompt.userChoice.then((res: any) => {
AppComponent.pwaPrompt.prompt();
AppComponent.pwaPrompt.userChoice.then((res: any) => {
if (res.outcome === 'accepted') {
this.messageService.clear();
this.messageService.add({
@ -74,8 +44,7 @@ export class DownloadAppDirective implements OnInit {
summary: 'Спасибо за установку!',
});
}
this.deferredPrompt = null;
AppComponent.pwaPrompt = null;
});
}
}

View File

@ -75,6 +75,7 @@
font-size: 16px;
line-height: 19px;
letter-spacing: -0.5px;
color: var(--text-color);
}
.price,

View File

@ -0,0 +1,13 @@
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Pipe({
name: 'safeHtml',
})
export class SafeHtmlPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) {}
transform(html: string) {
return this.sanitizer.bypassSecurityTrustHtml(html);
}
}

View File

@ -14,7 +14,7 @@
line-height: 20px;
text-align: center;
letter-spacing: -0.24px;
color: #6a737c;
color: var(--text-color_1);
}
.phone-number {
font-style: normal;
@ -23,7 +23,7 @@
line-height: 22px;
text-align: center;
letter-spacing: -0.408px;
color: #d9d9d9;
color: var(--text-color);
text-decoration: none;
}
}

View File

@ -1,23 +1,19 @@
<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>
<ng-container *ngIf="lastOrder">
<h2>Ваш предыдущий заказ</h2>
<p class="flex"><span>Дата: </span>
<span class="info" *ngIf="!loading">{{lastOrder!.last_purchase_date}}</span>
</p>
<p class="flex"><span>На сумму: </span>
<span class="info" *ngIf="!loading">{{lastOrder?.last_purchase_sum}}₽</span>
</p>
</ng-container>
<ng-container *ngIf="!lastOrder">
<p class="flex">
<span>Покупок за последние пол года не было</span>
</p>
</ng-container>
</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>

View File

@ -1,51 +1,53 @@
:host {
padding: 24px 16px 0px;
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);
& > .info-order {
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 16px;
h2 {
font-style: normal;
font-weight: 700;
font-size: 15px;
line-height: 20px;
letter-spacing: -0.24px;
}
span {
color: var(--text-color_1);
}
.flex {
display: flex;
align-items: center;
flex-direction: row;
gap: 8px;
}
.info {
font-size: 14px;
}
}
.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);
}
}
.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);
}
.info {
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 16px;
color: var(--text-color_1);
}
}

View File

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

View File

@ -4,7 +4,7 @@
align-items: center;
padding: 10px;
cursor: pointer;
transition: background-color 0.1s;
transition: background-color 0.1s;
&:hover {
background-color: var(--main-color_hover);

View File

@ -7,7 +7,7 @@
width: 48px;
height: 48px;
border-radius: 100%;
background: var(--button-color);
background: var(--main-color_2);
display: flex;
align-items: center;
justify-content: center;

View File

@ -1,105 +1,105 @@
<app-navbar title="Программа лояльности" [backEvent]="goBack"></app-navbar>
<ng-container *ngIf="authService.currentLvlPeriod">
<div class="loyality-program">
<app-accordion header="Условия начисления бонусов">
<p>
Ваш текущий уровень {{ authService.userInfo?.customer_level }},
поэтому вам начисляется {{ authService.currentLvlPeriod.percent }}% от суммы покупки.
</p>
<p>
Смена уровня произойдет в начале следующего квартала,
{{ authService.purchaseData.currentPeriod[1]
.locale("ru")
.format("DD.MM.YY") }}.
</p>
</app-accordion>
<app-accordion header="Уровни бонусной программы">
<p>
Начисление Бонусных баллов происходит по дифференцированной шкале в
зависимости от уровня:
</p>
<div class="loyality-program">
<app-accordion header="Условия начисления бонусов">
<p>
Ваш текущий уровень {{ authService.userInfo?.current_level_and_cashback?.current_level ?? '--' }},
поэтому вам начисляется {{ authService.currentLvlPeriod.percent }}% от суммы покупки.
</p>
<p>
Смена уровня произойдет в начале следующего квартала,
{{ authService.currentPeriod[1]
.locale("ru")
.format("DD.MM.YY") }}.
</p>
</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>
<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>
<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>
Возврат покупки, за которую бонусы были начислены:
<li>
В случае, если бонусов на счету достаточно для списания, бонусы
списываются в полном ранее начисленном за возвращаемый товар объеме.
</li>
<li>
В случае, если бонусов на счету недостаточно, формируется минусовой
баланс.
</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>
Возврат покупки, которая была оплачена бонусами:
<li>
В случае предъявления Участником кассового или товарного чека, сумма
бонусов, списанная для оплаты возвращаемого товара, зачисляется на счет
участника.
</li>
<li>
В случае возврата товара с применением оплаты бонусами, клиенту
возвращается денежная сумма в размере, внесенном Участником в оплату
товара при покупке, за вычетом суммы, оплаченной бонусами.
</li>
</ul>
</ng-container>
</ng-container>
</app-accordion>
</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>
</div>
<ul>
Возврат покупки, за которую бонусы были начислены:
<li>
В случае, если бонусов на счету достаточно для списания, бонусы
списываются в полном ранее начисленном за возвращаемый товар объеме.
</li>
<li>
В случае, если бонусов на счету недостаточно, формируется минусовой
баланс.
</li>
</ul>
<ul>
Возврат покупки, которая была оплачена бонусами:
<li>
В случае предъявления Участником кассового или товарного чека, сумма
бонусов, списанная для оплаты возвращаемого товара, зачисляется на счет
участника.
</li>
<li>
В случае возврата товара с применением оплаты бонусами, клиенту
возвращается денежная сумма в размере, внесенном Участником в оплату
товара при покупке, за вычетом суммы, оплаченной бонусами.
</li>
</ul>
</app-accordion>
</div>
<app-footer></app-footer>
<app-footer></app-footer>
</ng-container>

View File

@ -1,3 +1,4 @@
.loyality-program {
max-width: 600px;
margin: 0 auto;
}

View File

@ -1,4 +1,4 @@
import { environment } from "src/environments/environment.prod";
import { environment } from 'src/environments/environment.prod';
export enum DeviceType {
ios,
@ -12,7 +12,9 @@ export function getTypeDevice(): DeviceType {
}
export async function pwaInstalled(): Promise<boolean> {
if ("getInstalledRelatedApps" in navigator) {
if (window.matchMedia('(display-mode: standalone)').matches) return true;
if ('getInstalledRelatedApps' in navigator) {
const apps = await (window.navigator as any).getInstalledRelatedApps();
for (const app of apps) {
if (app.url == environment.manifestUrl) {
@ -22,3 +24,9 @@ export async function pwaInstalled(): Promise<boolean> {
}
return false;
}
export function format(s: string, ...args: string[]) {
return s.replace(/{(\d+)}/g, function (match, number) {
return typeof args[number] != 'undefined' ? args[number] : match;
});
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 291 KiB

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Creator: CorelDRAW -->
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="35.6446mm" height="51.1881mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
viewBox="0 0 4756.71 6830.97"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
<defs>
<style type="text/css">
<![CDATA[
.fil0 {fill:#005C50;fill-rule:nonzero}
]]>
</style>
</defs>
<g id="Слой_x0020_1">
<metadata id="CorelCorpID_0Corel-Layer"/>
<path class="fil0" d="M3624.79 6537.21l-2493 0 -593.79 -5550.88 3680.77 0 -593.98 5550.88zm961.94 -6281.71l-202.72 0 -78.95 -255.5 -3853.44 0 -78.85 255.5 -202.76 0 -170 550.53 241.74 0 644.49 6024.94 2984.16 0 644.68 -6024.94 241.65 0 -169.99 -550.53z"/>
<polygon class="fil0" points="1026.49,2860.81 3728.55,2860.81 3874.58,1495.52 880.44,1495.52 "/>
<polygon class="fil0" points="1202.08,4502.38 3552.85,4502.38 3699.07,3135.98 1055.9,3135.98 "/>
<polygon class="fil0" points="1377.49,6144.24 3379.23,6144.24 3523.42,4777.69 1231.56,4777.69 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB