Переделал роутинг с кастомного на ангуляровский, правки по меню, доделал страницу 404
This commit is contained in:
gofnnp 2022-12-27 16:35:50 +04:00
parent 6dad05b628
commit 7fe1d8c22e
21 changed files with 1007 additions and 595 deletions

View File

@ -1 +1,4 @@
<router-outlet></router-outlet>
<app-navbar></app-navbar>
<div class="layout">
<router-outlet></router-outlet>
</div>

View File

@ -0,0 +1,5 @@
:host {
.layout {
padding: 0 16px 16px;
}
}

View File

@ -1,10 +1,23 @@
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { PrimeNGConfig } from 'primeng/api';
import * as ConfigActions from './state/config/config.actions'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
export class AppComponent implements OnInit {
title = 'Demo stand';
constructor(private primengConfig: PrimeNGConfig,
private store: Store) {}
ngOnInit() {
this.primengConfig.ripple = true;
this.store.dispatch(ConfigActions.getConfig());
}
}

View File

@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { RouterModule, Routes } from '@angular/router';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@ -53,6 +53,17 @@ import { ConfigEffects } from './state/config/config.effects';
import {PaginatorModule} from 'primeng/paginator';
import {InputTextModule} from 'primeng/inputtext';
import { ChangeQuantityComponent } from './components/change-quantity/change-quantity.component';
import { MenuComponent } from './components/menu/menu.component';
import { SidebarModule } from 'primeng/sidebar';
import {RippleModule} from 'primeng/ripple';
const routes: Routes = [
{ path: '', redirectTo: 'products', pathMatch: 'full' },
{ path: 'products', component: ProductsComponent },
// { path: 'cart', component: CartComponent },
{ path: 'account', component: AccountComponent },
{ path: '**', component: NotFoundComponent }
];
@NgModule({
declarations: [
@ -76,18 +87,13 @@ import { ChangeQuantityComponent } from './components/change-quantity/change-qua
CheckboxGroupComponent,
UserDataOrderComponent,
InfoComponent,
ChangeQuantityComponent
ChangeQuantityComponent,
MenuComponent
],
imports: [
BrowserModule,
AppRoutingModule,
RouterModule.forRoot([
{
path: '**',
component: MainComponent
},
// { path: '**', component: NotFoundComponent }
]),
RouterModule.forRoot(routes),
InputMaskModule,
ProgressSpinnerModule,
FormsModule,
@ -119,7 +125,9 @@ import { ChangeQuantityComponent } from './components/change-quantity/change-qua
StoreModule.forRoot({config: configReducer}),
EffectsModule.forRoot([ConfigEffects]),
PaginatorModule,
InputTextModule
InputTextModule,
SidebarModule,
RippleModule
],
providers: [DialogService, MessageService, MessagingService ],
bootstrap: [AppComponent]

View File

@ -0,0 +1,54 @@
<nav class="main-menu-container" isShow="false" #menu>
<ul>
<ng-container
*ngFor="
let page of mainPageList;
let index = index;
let last = last;
let first = first
"
>
<li
*ngIf="page.onSideBar && !last"
class="main-menu-container__item"
[ngClass]="{
cart: page.resName === 'cart'
}"
[attr.data-counter]="page.resName === 'cart' ? cartCount : null"
[routerLink]="page.resName"
routerLinkActive="active"
>
<mat-icon
[ngClass]="{
'mat-icon': true
}"
>
{{ page.icon }}
</mat-icon>
<a>
{{ page.name }}
</a>
</li>
</ng-container>
<li
*ngIf="mainPageList[mainPageList.length - 1].onSideBar"
class="main-menu-container__item"
[ngClass]="{
cart: true
}"
[attr.data-counter]="cartCount"
(click)="changeMainPage(mainPageList[mainPageList.length - 1])"
>
<mat-icon
[ngClass]="{
'mat-icon': true
}"
>
{{ mainPageList[mainPageList.length - 1].icon }}
</mat-icon>
<a>
{{ mainPageList[mainPageList.length - 1].name }}
</a>
</li>
</ul>
</nav>

View File

@ -0,0 +1,120 @@
:host {
.main-menu-container {
// position: fixed;
// width: 100%;
// bottom: 0;
// left: 0;
// margin: 0;
// z-index: 777;
// height: 57px;
// border-top: solid 1px #dfdfdf;
// background-color: #fff;
ul {
display: flex;
height: 100%;
font-size: 14px;
flex-wrap: nowrap;
flex-direction: row;
gap: 32px;
li {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 4px;
font-size: 14px;
font-weight: 600;
letter-spacing: 2px;
color: #b5b5b9;
transition: color 0.3s ease;
cursor: pointer;
&.active {
color: #252525;
a {
border-bottom: 2px solid #e16f38;
}
}
&:hover {
color: #252525;
a {
border-bottom: 2px solid #e16f38;
}
}
a {
border-bottom: 2px solid #e16f3800;
}
& .mat-icon {
display: none;
&.is-active {
color: #000;
}
}
&.is-active {
color: #000;
}
&.cart {
position: relative;
&::before {
content: attr(data-counter);
color: #fff;
position: absolute;
right: -18px;
top: -8px;
background: #d7120b;
border-radius: 50px;
min-width: 1.2rem;
line-height: 1.2rem;
font-size: 0.8rem;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
}
@media screen and (max-width: 600px) {
.main-menu-container {
position: fixed;
width: 100%;
bottom: 0;
left: 0;
margin: 0;
z-index: 777;
height: 57px;
border-top: solid 1px #dfdfdf;
background-color: #fff;
ul {
li {
&.cart {
&::before {
right: 34px;
top: 5px;
}
}
& .mat-icon {
display: block;
}
}
}
}
}
}

View File

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

View File

@ -0,0 +1,48 @@
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { PageListMain } from 'src/app/app.constants';
import { Page } from 'src/app/interface/data';
import { CartService } from 'src/app/services/cart.service';
@Component({
selector: 'app-menu',
templateUrl: './menu.component.html',
styleUrls: ['./menu.component.scss'],
})
export class MenuComponent implements OnInit {
@Output() toggleMenu = new EventEmitter();
readonly mainPageList = PageListMain;
public cartCount = 0;
constructor(
private router: Router,
private route: ActivatedRoute,
private cartService: CartService
) {}
ngOnInit(): void {
this.cartCount = this.cartService.cartCount;
this.cartService.cartCount$.subscribe({
next: (count) => {
this.cartCount = count;
document
.querySelectorAll('.cart')[0]
.setAttribute('data-counter', this.cartCount.toString());
},
});
}
changeMainPage(page: Page, event?: MouseEvent): void {
if (event) {
event.preventDefault();
}
if (page.resName === 'cart') {
this.toggleMenu.emit()
return
}
this.router.navigate([page.resName], {
// relativeTo: this.route,
// queryParamsHandling: 'merge',
});
}
}

View File

@ -1,4 +1,6 @@
<div class="container-navbar">
<img src="./assets/logo-black.png" alt="Логотип">
<span class="menu" (click)="showMenu()">Меню</span>
<!-- <span class="menu" (click)="showMenu()">Меню</span> -->
<app-menu (toggleMenu)="cart.toggleSideBar()"></app-menu>
<app-cart #cart></app-cart>
</div>

View File

@ -1,6 +1,6 @@
.container-navbar {
box-sizing: border-box;
padding: 0 32px;
padding: 0 54px;
width: 100%;
height: 54px;
// background: #09467f;
@ -11,7 +11,6 @@
img {
height: 26px;
margin-left: 4px;
}
.menu {

View File

@ -1,160 +1,159 @@
:host {
.woocommerce-shipping-fields__field-wrapper {
margin: 8px auto 0 auto;
max-width: 400px;
.woocommerce-shipping-fields__field-wrapper {
margin: 8px auto 0 auto;
max-width: 400px;
}
.order_form__title {
font-weight: 700;
font-size: 18px;
margin-bottom: 12px;
}
input {
width: 100%;
color: #000000;
border: 1px solid #000000;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica,
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", Segoe UI Symbol;
font-size: 1rem;
color: #495057;
background: #ffffff;
padding: 0.5rem 0.75rem;
border: 1px solid #ced4da;
transition: background-color 0.15s, border-color 0.15s, box-shadow 0.15s;
-webkit-appearance: none;
appearance: none;
border-radius: 4px;
&.ng-dirty.ng-invalid {
border-color: red;
}
.order_form__title {
font-weight: 700;
font-size: 18px;
margin-bottom: 12px;
&.ng-invalid.ng-touched {
border-color: red;
}
}
input {
p {
margin-top: 0;
margin-bottom: 1rem;
}
textarea {
width: 100%;
height: 52px;
color: #000000;
border: 1px solid #000000;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica,
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", Segoe UI Symbol;
font-size: 1rem;
color: #495057;
background: #ffffff;
padding: 0.5rem 0.75rem;
border: 1px solid #ced4da;
transition: background-color 0.15s, border-color 0.15s, box-shadow 0.15s;
-webkit-appearance: none;
appearance: none;
border-radius: 4px;
}
.terminal-list-container {
display: flex;
flex-wrap: wrap;
gap: 16px;
margin: 8px 0 16px;
.terminal-container {
width: calc(50% - 8px);
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
border: solid #09467f 1px;
border-radius: 16px;
overflow: hidden;
padding-bottom: 16px;
opacity: 0.5;
text-align: center;
&.selected {
opacity: 1;
}
img {
width: 100%;
color: #000000;
border: 1px solid #000000;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", Segoe UI Symbol;
font-size: 1rem;
color: #495057;
background: #ffffff;
padding: 0.5rem 0.75rem;
border: 1px solid #ced4da;
transition: background-color .15s, border-color .15s, box-shadow .15s;
-webkit-appearance: none;
appearance: none;
border-radius: 4px;
&.ng-dirty.ng-invalid {
border-color: red;
}
&.ng-invalid.ng-touched {
border-color: red;
}
}
height: 120px;
object-fit: cover;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
&__name {
}
textarea {
width: 100%;
height: 52px;
color: #000000;
border: 1px solid #000000;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", Segoe UI Symbol;
font-size: 1rem;
color: #495057;
background: #ffffff;
padding: 0.5rem 0.75rem;
border: 1px solid #ced4da;
transition: background-color .15s, border-color .15s, box-shadow .15s;
-webkit-appearance: none;
appearance: none;
border-radius: 4px;
}
.terminal-list-container {
display: flex;
flex-wrap: wrap;
gap: 16px;
margin: 8px 0 16px;
.terminal-container {
width: calc(50% - 8px);
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
border: solid #09467f 1px;
border-radius: 16px;
overflow: hidden;
padding-bottom: 16px;
opacity: .5;
text-align: center;
&.selected {
opacity: 1;
}
img {
width: 100%;
height: 120px;
object-fit: cover;
}
&__name {}
&__address {
font-size: 14px;
}
}
}
.terminal-list-label {
margin-left: 8px;
&__address {
font-size: 14px;
}
}
}
.terminal-list-label {
margin-left: 8px;
font-size: 14px;
}
.form-row-wide {
display: flex;
flex-direction: column;
}
#deliveryDate {
margin-left: 8px;
margin-bottom: 4px;
display: block;
font-size: 14px;
}
.bootom-info {
position: fixed;
width: 100%;
left: 0;
display: flex;
justify-content: space-between;
align-items: center;
bottom: 0;
padding: 18px;
background: #fff;
z-index: 3;
border-top: solid 1px #e7e7e7;
.subtotal {
font-weight: 600;
font-size: 20px;
display: flex;
flex-direction: column;
.products-count {
font-size: 12px;
font-weight: 400;
}
}
.form-row-wide {
display: flex;
flex-direction: column;
.elementor-button--checkout {
background-color: #09467f;
color: #fff;
border-radius: 6px;
display: flex;
justify-content: center;
align-items: center;
border: none;
padding: 12px;
font-size: 12px;
cursor: pointer;
}
#deliveryDate {
margin-left: 8px;
margin-bottom: 4px;
display: block;
font-size: 14px;
}
}
@media screen and (min-width: 650px) {
.bootom-info {
position: fixed;
bottom: 58px;
width: 100%;
display: flex;
padding: 12px 18px;
justify-content: space-between;
left: 0;
align-items: center;
background: #fff;
z-index: 9999;
.subtotal {
font-weight: 600;
font-size: 20px;
display: flex;
flex-direction: column;
.products-count {
font-size: 12px;
font-weight: 400;
}
}
.elementor-button--checkout {
background-color: #09467f;
color: #fff;
border-radius: 6px;
display: flex;
justify-content: center;
align-items: center;
border: none;
padding: 12px;
font-size: 12px;
cursor: pointer;
}
width: 450px;
right: 0;
left: auto;
}
@media screen and (min-width: 550px) {
.bootom-info {
bottom: 84px;
width: 500px;
left: 50%;
transform: translate(-50%, 0);
border: solid 1px #dfdfdf;
border-radius: 12px;
}
}
}
}
}

View File

@ -84,7 +84,7 @@ export class UserDataOrderComponent implements OnInit {
this.checkoutConfig = value
}
})
this.deliverData.deliveryDate = moment().add(this.checkoutConfig.timeDelivery.changeTime.defaultValue, 'minutes').toDate()
this.deliverData.deliveryDate = moment().add(this.checkoutConfig?.timeDelivery?.changeTime?.defaultValue || 0, 'minutes').toDate()
this.paymentMethods = this.checkoutConfig.payments.values
this.deliverData.paymentMethod = this.paymentMethods[this.checkoutConfig.payments.default]

View File

@ -1,112 +1,97 @@
<div [ngClass]="{
woocommerce: true,
'auth-page': showAuthoriztion
}">
<nav class="main-menu-container" isShow="false" #menu>
<ul>
<ng-container *ngFor="let page of mainPageList; let index = index; let last = last; let first = first;">
<li *ngIf="page.onSideBar" class="main-menu-container__item" [ngClass]="{
'cart': page.resName === 'cart',
'is-active': page === currentPageMain
}" [attr.data-counter]="page.resName === 'cart' ? cartCount : null" (click)="changeMainPage(page, $event)">
<mat-icon [ngClass]="{
'mat-icon': true,
'is-active': page === currentPageMain
}">
{{page.icon}}
</mat-icon>
<span>
{{page.name}}
</span>
</li>
<div
[ngClass]="{
woocommerce: true,
'auth-page': showAuthoriztion
}"
>
<div *ngIf="!showAuthoriztion" class="account-page">
<div *ngIf="showAuthoriztion" class="top-left-attribute"></div>
<div [ngSwitch]="currentPage.code" class="">
<ng-container *ngSwitchCase="PageCode.Orders">
<app-orders (deauthorization)="changePage(pageList[0])"></app-orders>
</ng-container>
</ul>
</nav>
<div [ngSwitch]="currentPageMain.code">
<ng-container *ngSwitchCase="MainPageCode.Account">
<div *ngIf="!showAuthoriztion" class="account-page">
<div *ngIf="showAuthoriztion" class="top-left-attribute"></div>
<div [ngSwitch]="currentPage.code" class="">
<ng-container *ngSwitchCase="PageCode.Orders">
<app-orders (deauthorization)="changePage(pageList[0])"></app-orders>
</ng-container>
<ng-container *ngSwitchCase="PageCode.BonusProgram">
<app-bonus-program (deauthorization)="changePage(pageList[0])"></app-bonus-program>
</ng-container>
<ng-container *ngSwitchCase="PageCode.UserData">
<app-user-data></app-user-data>
</ng-container>
<ng-container *ngSwitchCase="PageCode.RefSystem">
<app-ref-system></app-ref-system>
</ng-container>
</div>
<nav *ngIf="!showAuthoriztion" class="woocommerce-MyAccount-navigation">
<ul>
<ng-container *ngFor="let page of pageList; let index = index">
<li *ngIf="page.onSideBar" class="woocommerce-MyAccount-navigation-link" [ngClass]="{
<ng-container *ngSwitchCase="PageCode.BonusProgram">
<app-bonus-program
(deauthorization)="changePage(pageList[0])"
></app-bonus-program>
</ng-container>
<ng-container *ngSwitchCase="PageCode.UserData">
<app-user-data></app-user-data>
</ng-container>
<ng-container *ngSwitchCase="PageCode.RefSystem">
<app-ref-system></app-ref-system>
</ng-container>
</div>
<nav *ngIf="!showAuthoriztion" class="woocommerce-MyAccount-navigation">
<ul>
<ng-container *ngFor="let page of pageList; let index = index">
<li
*ngIf="page.onSideBar"
class="woocommerce-MyAccount-navigation-link"
[ngClass]="{
'is-active': page === currentPage,
first: index === 1
}" (click)="changePage(page, $event)">
<div class="container">
<img src="{{ './assets/menu-icons/' + page.resName + '.png' }}" alt="Иконка меню" />
<div class="menu-item-info">
<a href="#">{{ page.name }}</a>
<p>{{ page.description }}</p>
</div>
</div>
</li>
</ng-container>
<li class="woocommerce-MyAccount-navigation-link" (click)="logout()">
<div class="container">
<img src="./assets/menu-icons/exit.png" alt="Иконка меню" />
<div class="menu-item-info">
<a href="#">Выход</a>
</div>
}"
(click)="changePage(page, $event)"
>
<div class="container">
<img
src="{{ './assets/menu-icons/' + page.resName + '.png' }}"
alt="Иконка меню"
/>
<div class="menu-item-info">
<a href="#">{{ page.name }}</a>
<p>{{ page.description }}</p>
</div>
</li>
</ul>
</nav>
</div>
</ng-container>
<ng-container *ngSwitchCase="MainPageCode.Products">
<app-products></app-products>
</ng-container>
<ng-container *ngSwitchCase="MainPageCode.Cart">
<app-cart *ngIf="!showAuthoriztion" (showAuthoriztion)="checkAuthorization($event)"></app-cart>
</ng-container>
<ng-container *ngSwitchCase="MainPageCode.Info">
<app-info></app-info>
</ng-container>
<ng-container>
<app-auth *ngIf="showAuthoriztion && currentPageMain !== mainPageList[1]" [handleHttpError]="handleHttpErrorFunc"
(phoneConfirmed)="phoneConfirmed()"></app-auth>
</ng-container>
</div>
</li>
</ng-container>
<li class="woocommerce-MyAccount-navigation-link" (click)="logout()">
<div class="container">
<img src="./assets/menu-icons/exit.png" alt="Иконка меню" />
<div class="menu-item-info">
<a href="#">Выход</a>
</div>
</div>
</li>
</ul>
</nav>
</div>
<span class="version" [ngClass]="{
version: true
}">
v{{ version }}
</span>
<p-toast position="bottom-center" key="c" (onClose)="onReject()" [baseZIndex]="5000">
<p-toast
position="bottom-center"
key="c"
(onClose)="onReject()"
[baseZIndex]="5000"
>
<ng-template let-message pTemplate="message">
<div class="flex flex-column" style="flex: 1">
<div class="text-center">
<i class="pi pi-exclamation-triangle" style="font-size: 3rem"></i>
<h4>{{message.summary}}</h4>
<p style="font-weight: 600;">{{message.detail}}</p>
<h4>{{ message.summary }}</h4>
<p style="font-weight: 600">{{ message.detail }}</p>
</div>
<div class="grid p-fluid">
<div class="col-6">
<button type="button" pButton (click)="onConfirm()" label="Да" class="p-button-success"></button>
<button
type="button"
pButton
(click)="onConfirm()"
label="Да"
class="p-button-success"
></button>
</div>
<div class="col-6">
<button type="button" pButton (click)="onReject()" label="Нет" class="p-button-secondary"></button>
<button
type="button"
pButton
(click)="onReject()"
label="Нет"
class="p-button-secondary"
></button>
</div>
</div>
</div>
</ng-template>
</p-toast>
</div>
</div>

View File

@ -1,104 +1,215 @@
<div class="cart" *ngIf="!loading && order && !orderConfirmed" [ngStyle]="{margin: !order.products.length && 0}">
<div class="widget_shopping_cart_content" style="opacity: 1;">
<div class="elementor-menu-cart__products woocommerce-mini-cart cart woocommerce-cart-form__contents"
[ngStyle]="{margin: !order.products.length && 0}">
<div *ngFor="let product of order.products; let last = last">
<div class="elementor-menu-cart__product woocommerce-cart-form__cart-item cart_item"
style="grid-template-columns: 70px auto;">
<p-sidebar
[(visible)]="visibleSidebar"
[fullScreen]="isFullScreen"
[baseZIndex]="10000"
position="right"
>
<div
class="cart"
*ngIf="!loading && order && !orderConfirmed"
[ngStyle]="{ margin: !order.products.length && 0 }"
>
<div class="widget_shopping_cart_content" style="opacity: 1">
<div
class="elementor-menu-cart__products woocommerce-mini-cart cart woocommerce-cart-form__contents"
[ngStyle]="{ margin: !order.products.length && 0 }"
>
<div *ngFor="let product of order.products; let last = last">
<div
class="elementor-menu-cart__product woocommerce-cart-form__cart-item cart_item"
style="grid-template-columns: 70px auto"
>
<div class="elementor-menu-cart__product-image product-thumbnail">
<img
*ngIf="product.image"
width="70"
height="70"
src="{{ product.image }}"
class="attachment-woocommerce_thumbnail size-woocommerce_thumbnail"
alt="{{ product.name }}"
loading="lazy"
/>
<img
*ngIf="!product.image"
width="70"
height="70"
src="./assets/no-image.png"
class="attachment-woocommerce_thumbnail size-woocommerce_thumbnail"
alt="{{ product.name }}"
loading="lazy"
/>
</div>
<div
class="elementor-menu-cart__product-name product-name"
data-title="Product"
>
<span>{{ product.name }}</span>
<dl
*ngFor="let modifier of product.modifier_data"
class="variation"
[ngStyle]="{ margin: !modifier.options.length && 0 }"
>
<ng-container *ngFor="let option of modifier.options">
<dt
*ngIf="option.quantity"
style="max-width: 160px"
class="variation-"
>
{{ option.name }}:
</dt>
<dd
*ngIf="option.quantity"
style="
display: flex;
align-items: flex-end;
margin-bottom: 0;
"
class="variation-"
>
<p>
{{ option.quantity }} × {{ product.currency_symbol
}}{{ (option.price ?? 0) * option.quantity }}
</p>
</dd>
</ng-container>
</dl>
</div>
<div class="elementor-menu-cart__product-image product-thumbnail">
<img *ngIf="product.image" width="70" height="70" src="{{product.image}}"
class="attachment-woocommerce_thumbnail size-woocommerce_thumbnail" alt="{{product.name}}" loading="lazy">
<img *ngIf="!product.image" width="70" height="70" src="./assets/no-image.png"
class="attachment-woocommerce_thumbnail size-woocommerce_thumbnail" alt="{{product.name}}" loading="lazy">
</div>
<div class="elementor-menu-cart__product-name product-name" data-title="Product">
<span>{{product.name}}</span>
<dl *ngFor="let modifier of product.modifier_data" class="variation"
[ngStyle]="{margin: !modifier.options.length && 0}">
<ng-container *ngFor="let option of modifier.options">
<dt *ngIf="option.quantity" style="max-width: 160px;" class="variation-">{{option.name}}:</dt>
<dd *ngIf="option.quantity" style="display: flex; align-items: flex-end; margin-bottom: 0;" class="variation-">
<p>{{option.quantity}} × {{product.currency_symbol}}{{(option.price ?? 0) * option.quantity}}</p>
</dd>
</ng-container>
</dl>
</div>
<div class="elementor-menu-cart__product-price product-price" data-title="Price">
<span class="quantity">
<span class="product-quantity">{{product.amount}} × </span>
<span class="woocommerce-Price-amount amount">
<bdi>
<span class="woocommerce-Price-currencySymbol">{{product.currency_symbol}}</span>
{{product.finalPrice}}
</bdi>
<div
class="elementor-menu-cart__product-price product-price"
data-title="Price"
>
<span class="quantity">
<span class="product-quantity">{{ product.amount }} × </span>
<span class="woocommerce-Price-amount amount">
<bdi>
<span class="woocommerce-Price-currencySymbol">{{
product.currency_symbol
}}</span>
{{ product.finalPrice }}
</bdi>
</span>
</span>
</span>
<div class="product-change-amount">
<div class="product-change-amount__symbol" (click)="setAmount(product, 'minus')">
-
</div>
<div class="product-change-amount__symbol" (click)="setAmount(product, 'plus')">
+
<div class="product-change-amount">
<div
class="product-change-amount__symbol"
(click)="setAmount(product, 'minus')"
>
-
</div>
<div
class="product-change-amount__symbol"
(click)="setAmount(product, 'plus')"
>
+
</div>
</div>
</div>
</div>
<div class="elementor-menu-cart__product-remove product-remove">
<a href="#" class="remove_from_cart_button" aria-label="Remove this item"
(click)="removeFromCart($event, product.guid)"></a>
<div class="elementor-menu-cart__product-remove product-remove">
<a
href="#"
class="remove_from_cart_button"
aria-label="Remove this item"
(click)="removeFromCart($event, product.guid)"
></a>
</div>
</div>
<hr *ngIf="!last" />
</div>
<hr *ngIf="!last">
<button
*ngIf="order.products.length != 0"
class="clear-cart"
(click)="confirmClearCart()"
>
Очистить корзину
</button>
</div>
<button *ngIf="order.products.length != 0" class="clear-cart" (click)="confirmClearCart()">
Очистить корзину
</button>
</div>
<div *ngIf="order.products.length != 0" class="elementor-menu-cart__bottom-info">
<div class="elementor-menu-cart__subtotal">
<span class="products-count">Товаров: {{order.products.length}}</span>
<span class="woocommerce-Price-amount amount"><bdi><span
class="woocommerce-Price-currencySymbol">{{order.products[0].currency_symbol}}</span>{{order.price}}</bdi></span>
</div>
<div class="elementor-menu-cart__footer-buttons">
<a href="#" class="elementor-button elementor-button--checkout elementor-size-md"
(click)="confirmOrder($event)">
<span class="elementor-button-text">Оформление заказа</span>
</a>
<div
*ngIf="order.products.length != 0"
class="elementor-menu-cart__bottom-info"
>
<div class="elementor-menu-cart__subtotal">
<span class="products-count"
>Товаров: {{ order.products.length }}</span
>
<span class="woocommerce-Price-amount amount"
><bdi
><span class="woocommerce-Price-currencySymbol">{{
order.products[0].currency_symbol
}}</span
>{{ order.price }}</bdi
></span
>
</div>
<div class="elementor-menu-cart__footer-buttons">
<a
href="#"
class="elementor-button elementor-button--checkout elementor-size-md"
(click)="confirmOrder($event)"
>
<span class="elementor-button-text">Оформление заказа</span>
</a>
</div>
</div>
</div>
</div>
<p-toast position="bottom-center" key="c" (onClose)="onReject()" [baseZIndex]="5000">
<ng-template let-message pTemplate="message">
<div class="flex flex-column" style="flex: 1">
<div class="text-center">
<i class="pi pi-exclamation-triangle" style="font-size: 3rem"></i>
<h4>{{message.summary}}</h4>
<p style="font-weight: 600;">{{message.detail}}</p>
</div>
<div class="grid p-fluid">
<div class="col-6">
<button type="button" pButton (click)="onConfirm()" label="Да" class="p-button-success"></button>
<p-toast
position="bottom-center"
key="c"
(onClose)="onReject()"
[baseZIndex]="5000"
>
<ng-template let-message pTemplate="message">
<div class="flex flex-column" style="flex: 1">
<div class="text-center">
<i class="pi pi-exclamation-triangle" style="font-size: 3rem"></i>
<h4>{{ message.summary }}</h4>
<p style="font-weight: 600">{{ message.detail }}</p>
</div>
<div class="col-6">
<button type="button" pButton (click)="onReject()" label="Нет" class="p-button-secondary"></button>
<div class="grid p-fluid">
<div class="col-6">
<button
type="button"
pButton
(click)="onConfirm()"
label="Да"
class="p-button-success"
></button>
</div>
<div class="col-6">
<button
type="button"
pButton
(click)="onReject()"
label="Нет"
class="p-button-secondary"
></button>
</div>
</div>
</div>
</div>
</ng-template>
</p-toast>
</div>
<app-user-data-order *ngIf="orderConfirmed" (orderSubmitted)="orderSubmitted()"></app-user-data-order>
<div #loadingEl *ngIf="loading && !orderConfirmed">
<div class="angular-spinner-container" style="width: fit-content; height: 100%; margin: 16px auto;">
<p-progressSpinner styleClass="angular-spinner"></p-progressSpinner>
</ng-template>
</p-toast>
</div>
</div>
<div #empty *ngIf="!loading && (!order || !order.products.length)">
<div class="woocommerce-mini-cart__empty-message jupiterx-icon-shopping-cart-6">Корзина пустая.</div>
</div>
<app-user-data-order
*ngIf="orderConfirmed"
(orderSubmitted)="orderSubmitted()"
></app-user-data-order>
<div #loadingEl *ngIf="loading && !orderConfirmed">
<div
class="angular-spinner-container"
style="width: fit-content; height: 100%; margin: 16px auto"
>
<p-progressSpinner styleClass="angular-spinner"></p-progressSpinner>
</div>
</div>
<div #empty *ngIf="!loading && (!order || !order.products.length)">
<div
class="woocommerce-mini-cart__empty-message jupiterx-icon-shopping-cart-6"
>
Корзина пустая.
</div>
</div>
</p-sidebar>

View File

@ -1,234 +1,235 @@
:host {
.cart {
margin-top: 16px;
margin-bottom: 100px;
max-width: 400px;
margin-left: auto;
margin-right: auto;
.cart {
margin-top: 16px;
margin-bottom: 100px;
max-width: 400px;
margin-left: auto;
margin-right: auto;
}
.elementor-menu-cart {
&__product {
grid-template-columns: 71px auto;
grid-template-rows: var(
--price-quantity-position--grid-template-rows,
auto auto
);
position: relative;
display: grid;
padding-bottom: 0;
padding-right: 30px;
.variation {
display: grid;
grid-template-columns: max-content auto;
margin: 10px 8px;
color: var(--product-variations-color, #373a3c);
dt {
grid-column-start: 1;
font-weight: 700;
}
dd {
grid-column-start: 2;
-webkit-margin-start: 5px;
margin-inline-start: 5px;
margin-bottom: 0.5rem;
margin-left: 6px;
}
}
}
.elementor-menu-cart {
&__product {
grid-template-columns: 71px auto;
grid-template-rows: var(--price-quantity-position--grid-template-rows, auto auto);
position: relative;
display: grid;
padding-bottom: 0;
padding-right: 30px;
&__product-image {
grid-row-start: 1;
grid-row-end: 3;
width: 100%;
.variation {
display: grid;
grid-template-columns: max-content auto;
margin: 10px 8px;
color: var(--product-variations-color, #373a3c);
dt {
grid-column-start: 1;
font-weight: 700;
}
dd {
grid-column-start: 2;
-webkit-margin-start: 5px;
margin-inline-start: 5px;
margin-bottom: 0.5rem;
margin-left: 6px;
}
}
}
&__product-image {
grid-row-start: 1;
grid-row-end: 3;
width: 100%;
img {
border-radius: 6px;
object-fit: cover;
}
}
&__product-name {
grid-column-start: 2;
grid-column-end: 3;
margin: 0;
font-size: 14px;
padding-left: 20px;
}
&__product-price {
font-size: 14px;
padding-left: 20px;
grid-column-start: 2;
grid-column-end: 3;
-ms-flex-item-align: var(--price-quantity-position--align-self, end);
align-self: var(--price-quantity-position--align-self, end);
font-weight: 400;
}
&__product-remove {
color: #818a91;
width: var(--remove-item-button-size, 22px);
height: var(--remove-item-button-size, 22px);
border-radius: var(--remove-item-button-size, 22px);
border: 1px solid var(--remove-item-button-color, #d4d4d4);
text-align: center;
overflow: hidden;
position: absolute;
top: 0px;
right: 0;
bottom: 20px;
-webkit-transition: .3s;
-o-transition: .3s;
transition: .3s;
&::before,
&::after {
content: "";
position: absolute;
height: 1px;
width: 50%;
top: 50%;
left: 25%;
margin-top: -1px;
background: var(--remove-item-button-color, #d4d4d4);
z-index: 1;
-webkit-transition: .3s;
-o-transition: .3s;
transition: .3s;
}
&::before {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
&::after {
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
}
&>a {
display: block;
z-index: 2;
width: 100%;
height: 100%;
overflow: hidden;
opacity: 0;
position: absolute;
}
}
&__bottom-info {
position: fixed;
width: 100%;
left: 0;
display: flex;
justify-content: space-between;
align-items: center;
bottom: 58px;
padding: 18px;
background: #fff;
z-index: 3;
}
&__subtotal {
font-weight: 600;
font-size: 20px;
display: flex;
flex-direction: column;
& .products-count {
font-size: 12px;
font-weight: 400;
}
}
&__footer-buttons {
a {
padding: 12px;
display: block;
width: fit-content;
background: #09467f;
border-radius: 4px;
text-decoration: none;
color: #fff;
font-size: 12px;
}
}
img {
border-radius: 6px;
object-fit: cover;
}
}
.product-thumbnail {
background: #eee;
border-radius: 9px;
height: 70px;
&__product-name {
grid-column-start: 2;
grid-column-end: 3;
margin: 0;
font-size: 14px;
padding-left: 20px;
}
.product-change-amount {
width: 50px;
height: 30px;
margin-top: 4px;
border-radius: 5px;
display: flex;
border: solid #cbcbcb 1px;
color: #525252;
cursor: pointer;
user-select: none;
&__symbol {
width: 50%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
border-right: solid #cbcbcb 1px;
}
&__product-price {
font-size: 14px;
padding-left: 20px;
grid-column-start: 2;
grid-column-end: 3;
-ms-flex-item-align: var(--price-quantity-position--align-self, end);
align-self: var(--price-quantity-position--align-self, end);
font-weight: 400;
}
.cart-product {
&__supplements {
position: absolute;
right: 0;
bottom: 26px;
padding: 8px;
background: #f9b004;
color: #fff;
border-radius: 4px;
cursor: pointer;
}
}
&__product-remove {
color: #818a91;
width: var(--remove-item-button-size, 22px);
height: var(--remove-item-button-size, 22px);
border-radius: var(--remove-item-button-size, 22px);
border: 1px solid var(--remove-item-button-color, #d4d4d4);
text-align: center;
overflow: hidden;
position: absolute;
top: 0px;
right: 0;
bottom: 20px;
-webkit-transition: 0.3s;
-o-transition: 0.3s;
transition: 0.3s;
.woocommerce-mini-cart__empty-message {
text-align: center;
margin-top: 16px;
}
&::before,
&::after {
content: "";
position: absolute;
height: 1px;
width: 50%;
top: 50%;
left: 25%;
margin-top: -1px;
background: var(--remove-item-button-color, #d4d4d4);
z-index: 1;
-webkit-transition: 0.3s;
-o-transition: 0.3s;
transition: 0.3s;
}
hr {
width: 80%;
margin: 14px auto;
border-top: solid #d1d1d1 1px;
}
&::before {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.clear-cart {
padding: 8px;
border: none;
border-radius: 4px;
background: #d7120b;
color: #fff;
margin: 32px auto;
&::after {
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
}
& > a {
display: block;
z-index: 2;
width: 100%;
height: 100%;
overflow: hidden;
opacity: 0;
position: absolute;
}
}
@media screen and (min-width: 550px) {
.elementor-menu-cart__bottom-info {
bottom: 84px;
width: 500px;
left: 50%;
transform: translate(-50%, 0);
border: solid 1px #dfdfdf;
border-radius: 12px;
}
&__bottom-info {
position: fixed;
width: 100%;
left: 0;
display: flex;
justify-content: space-between;
align-items: center;
bottom: 0;
padding: 18px;
background: #fff;
z-index: 3;
border-top: solid 1px #e7e7e7;
}
}
&__subtotal {
font-weight: 600;
font-size: 20px;
display: flex;
flex-direction: column;
& .products-count {
font-size: 12px;
font-weight: 400;
}
}
&__footer-buttons {
a {
padding: 12px;
display: block;
width: fit-content;
background: #09467f;
border-radius: 4px;
text-decoration: none;
color: #fff;
font-size: 12px;
}
}
}
.product-thumbnail {
background: #eee;
border-radius: 9px;
height: 70px;
}
.product-change-amount {
width: 50px;
height: 30px;
margin-top: 4px;
border-radius: 5px;
display: flex;
border: solid #cbcbcb 1px;
color: #525252;
cursor: pointer;
user-select: none;
&__symbol {
width: 50%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
border-right: solid #cbcbcb 1px;
}
}
.cart-product {
&__supplements {
position: absolute;
right: 0;
bottom: 26px;
padding: 8px;
background: #f9b004;
color: #fff;
border-radius: 4px;
cursor: pointer;
}
}
.woocommerce-mini-cart__empty-message {
text-align: center;
margin-top: 16px;
}
hr {
width: 80%;
margin: 14px auto;
border-top: solid #d1d1d1 1px;
}
.clear-cart {
padding: 8px;
border: none;
border-radius: 4px;
background: #d7120b;
color: #fff;
margin: 32px auto;
display: block;
}
@media screen and (min-width: 650px) {
.elementor-menu-cart__bottom-info {
width: 450px;
right: 0;
left: auto;
}
}
}

View File

@ -1,4 +1,4 @@
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, HostListener, OnInit, Output } from '@angular/core';
import { MessageService } from 'primeng/api';
import { Order } from 'src/app/models/order';
import { OrderProduct } from 'src/app/models/order-product';
@ -16,6 +16,9 @@ export class CartComponent implements OnInit {
public orderConfirmed = false;
public order!: Order;
public price!: number;
public visibleSidebar: boolean = false;
public isFullScreen!: boolean;
public width!: number;
constructor(
private orderService: OrderService,
@ -24,9 +27,31 @@ export class CartComponent implements OnInit {
) { }
ngOnInit(): void {
this.width = window.innerWidth;
this.changeDullScreenMode()
this.loadCart()
}
// Изменение размера окна
@HostListener('window:resize', ['$event'])
onResize(event: any) {
this.width = event.target.innerWidth;
this.changeDullScreenMode()
}
toggleSideBar(): void{
this.visibleSidebar = !this.visibleSidebar;
this.loadCart()
}
changeDullScreenMode() {
if (this.width < 650) {
this.isFullScreen = true
} else {
this.isFullScreen = false
}
}
async loadCart(): Promise<void> {
this.loading = true;
this.order = await this.orderService.getOrder(true);

View File

@ -1,8 +1,8 @@
<div class="not-found-page">
<app-navbar></app-navbar>
<div class="not-found-page__container">
<h1>404</h1>
<p>Упс, что-то пошло не так!</p>
<button (click)="routeHome()">Вернуться на главную</button>
<a href="#" (click)="routeHome($event)">Перейти на главную</a>
<!-- <button (click)="routeHome()">Вернуться на главную</button> -->
</div>
</div>

View File

@ -1,27 +1,30 @@
:host {
.not-found-page {
height: calc(100vh - 70px);
&__container {
text-align: center;
margin-top: 32px;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
-moz-user-select: none;
-khtml-user-select: none;
user-select: none;
h1 {
font-size: 108px;
font-size: 136px;
font-weight: 600;
color: #09467f;
color: #252525;
}
p {
margin: 16px 0;
margin: 48px 0;
font-size: 14px;
}
button {
background-color: #09467f;
color: #fff;
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
padding: 12px;
margin: 0 auto;
border: 0;
a {
letter-spacing: 1px;
color: #252525;
border-bottom: 2px solid #252525;
font-weight: 600;
}
}
}

View File

@ -1,20 +1,23 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
@Component({
selector: 'app-not-found',
templateUrl: './not-found.component.html',
styleUrls: ['./not-found.component.scss']
styleUrls: ['./not-found.component.scss'],
})
export class NotFoundComponent implements OnInit {
constructor(private router: Router, private route: ActivatedRoute) {}
constructor(private router: Router) { }
ngOnInit(): void {}
ngOnInit(): void {
routeHome(event: MouseEvent) {
if (event) {
event.preventDefault();
}
this.router.navigate(['/'], {
relativeTo: this.route,
queryParamsHandling: 'merge',
});
}
routeHome() {
this.router.navigate(['/']);
}
}

View File

@ -112,6 +112,7 @@
margin: 0;
font-size: 30px;
font-weight: 500;
max-width: 150px;
}
button {
@ -234,17 +235,21 @@
@media screen and (max-width: 631px) {
.products-container {
max-width: 306px;
}
}
@media screen and (max-width: 450px) {
.products-container {
max-width: none;
max-width: 400px;
&__item {
width: 100%;
}
}
}
// @media screen and (max-width: 631px) {
// .products-container {
// // max-width: none;
// &__item {
// width: 100%;
// }
// }
// }
}

View File

@ -186,6 +186,11 @@ p-toast[key="c"] .p-toast {
bottom: 57px;
}
.p-sidebar-right {
width: 450px !important;
max-width: 85% !important;
}
@media screen and (min-width: 550px) {
p-toast[key="c"] .p-toast {
bottom: 73px;