diff --git a/angular/angular.json b/angular/angular.json index b2f746b..1a45518 100644 --- a/angular/angular.json +++ b/angular/angular.json @@ -34,7 +34,7 @@ "src/firebase-messaging-sw.js" ], "styles": [ - "./node_modules/@angular/material/prebuilt-themes/pink-bluegrey.css", + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "node_modules/mdb-angular-ui-kit/assets/scss/mdb.scss", "node_modules/primeng/resources/themes/saga-blue/theme.css", "node_modules/primeicons/primeicons.css", @@ -114,7 +114,7 @@ "src/manifest.webmanifest" ], "styles": [ - "./node_modules/@angular/material/prebuilt-themes/pink-bluegrey.css", + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "src/styles.scss" ], "scripts": [] diff --git a/angular/src/app/app.component.ts b/angular/src/app/app.component.ts index 5f13811..f21d6ba 100644 --- a/angular/src/app/app.component.ts +++ b/angular/src/app/app.component.ts @@ -1,23 +1,20 @@ import { Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { PrimeNGConfig } from 'primeng/api'; -import * as ConfigActions from './state/config/config.actions' +import * as ConfigActions from './state/config/config.actions'; @Component({ selector: 'app-root', templateUrl: './app.component.html', - styleUrls: ['./app.component.scss'] + styleUrls: ['./app.component.scss'], }) export class AppComponent implements OnInit { title = 'Sakura'; - constructor(private primengConfig: PrimeNGConfig, - private store: Store) {} + constructor(private primengConfig: PrimeNGConfig, private store: Store) {} ngOnInit() { - this.primengConfig.ripple = true; + this.primengConfig.ripple = false; this.store.dispatch(ConfigActions.getConfig()); } - - } diff --git a/angular/src/app/app.module.ts b/angular/src/app/app.module.ts index 50c4472..4b0ca8a 100644 --- a/angular/src/app/app.module.ts +++ b/angular/src/app/app.module.ts @@ -60,6 +60,15 @@ import {MatTabsModule} from '@angular/material/tabs'; import { ModifierComponent } from './components/modifier/modifier.component'; import { OptionComponent } from './components/option/option.component'; import { ChangeQuantityOptionDirective } from './directives/change-quantity-option.directive'; +import {MatSelectModule} from '@angular/material/select'; +import {MatFormFieldModule, MAT_FORM_FIELD_DEFAULT_OPTIONS} from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import {MatBottomSheetModule} from '@angular/material/bottom-sheet'; +import { TerminalListComponent } from './components/terminal-list/terminal-list.component'; +import {MatButtonModule} from '@angular/material/button'; +import {MatListModule} from '@angular/material/list'; +import {MatSnackBarModule} from '@angular/material/snack-bar'; +import { SnackBarComponent } from './components/snack-bar/snack-bar.component'; const routes: Routes = [ { path: '', redirectTo: 'products', pathMatch: 'full' }, @@ -95,7 +104,9 @@ const routes: Routes = [ MenuComponent, ModifierComponent, OptionComponent, - ChangeQuantityOptionDirective + ChangeQuantityOptionDirective, + TerminalListComponent, + SnackBarComponent ], imports: [ BrowserModule, @@ -137,9 +148,16 @@ const routes: Routes = [ InputTextModule, SidebarModule, RippleModule, - MatTabsModule + MatTabsModule, + MatSelectModule, + MatFormFieldModule, + MatInputModule, + MatBottomSheetModule, + MatButtonModule, + MatListModule, + MatSnackBarModule ], - providers: [DialogService, MessageService, MessagingService ], + providers: [DialogService, MessageService, MessagingService, {provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: {appearance: 'outline'}} ], bootstrap: [AppComponent] }) export class AppModule { } diff --git a/angular/src/app/components/menu/menu.component.scss b/angular/src/app/components/menu/menu.component.scss index 92aa5dc..444a331 100644 --- a/angular/src/app/components/menu/menu.component.scss +++ b/angular/src/app/components/menu/menu.component.scss @@ -1,3 +1,5 @@ +@import "src/sass/mixins"; + :host { .main-menu-container { // position: fixed; @@ -41,7 +43,7 @@ } } - &:hover { + @include hover-supported() { color: #252525; a { diff --git a/angular/src/app/components/product-modal/product-modal.component.html b/angular/src/app/components/product-modal/product-modal.component.html index b737b68..10ae47b 100644 --- a/angular/src/app/components/product-modal/product-modal.component.html +++ b/angular/src/app/components/product-modal/product-modal.component.html @@ -8,7 +8,7 @@ }}" alt="{{ product.name }}" /> -

Lorem ipsum dolor sit amet consectetur adipisicing elit. Quasi quas libero consequatur dolorum itaque dolor deserunt aut facilis debitis!

+

{{product.description}}

+ {{ data.text }} +
+ + +
+
diff --git a/angular/src/app/components/snack-bar/snack-bar.component.scss b/angular/src/app/components/snack-bar/snack-bar.component.scss new file mode 100644 index 0000000..5f85c62 --- /dev/null +++ b/angular/src/app/components/snack-bar/snack-bar.component.scss @@ -0,0 +1,18 @@ +:host { + .snack-bar { + display: flex; + align-items: center; + justify-content: space-between; + span { + color: #323232; + } + .buttons { + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: nowrap; + flex-direction: row; + gap: 8px; + } + } +} diff --git a/angular/src/app/components/snack-bar/snack-bar.component.spec.ts b/angular/src/app/components/snack-bar/snack-bar.component.spec.ts new file mode 100644 index 0000000..7131666 --- /dev/null +++ b/angular/src/app/components/snack-bar/snack-bar.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SnackBarComponent } from './snack-bar.component'; + +describe('SnackBarComponent', () => { + let component: SnackBarComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SnackBarComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(SnackBarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/angular/src/app/components/snack-bar/snack-bar.component.ts b/angular/src/app/components/snack-bar/snack-bar.component.ts new file mode 100644 index 0000000..332ba0c --- /dev/null +++ b/angular/src/app/components/snack-bar/snack-bar.component.ts @@ -0,0 +1,23 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatSnackBarRef, MAT_SNACK_BAR_DATA } from '@angular/material/snack-bar'; + +@Component({ + selector: 'app-snack-bar', + templateUrl: './snack-bar.component.html', + styleUrls: ['./snack-bar.component.scss'] +}) +export class SnackBarComponent implements OnInit { + + constructor(@Inject(MAT_SNACK_BAR_DATA) public data: {text: string}, private _matSnackBarRef: MatSnackBarRef) { } + + ngOnInit(): void { + } + + buttonClick(result: 'yes' | 'no') { + if (result === 'yes') { + this._matSnackBarRef.dismissWithAction() + } else { + this._matSnackBarRef.dismiss() + } + } +} diff --git a/angular/src/app/components/terminal-list/terminal-list.component.html b/angular/src/app/components/terminal-list/terminal-list.component.html new file mode 100644 index 0000000..1c12550 --- /dev/null +++ b/angular/src/app/components/terminal-list/terminal-list.component.html @@ -0,0 +1,13 @@ + +
+ {{ item.label }} +
+
diff --git a/angular/src/app/components/terminal-list/terminal-list.component.scss b/angular/src/app/components/terminal-list/terminal-list.component.scss new file mode 100644 index 0000000..e7b759b --- /dev/null +++ b/angular/src/app/components/terminal-list/terminal-list.component.scss @@ -0,0 +1,21 @@ +@import 'src/sass/mixins'; + +:host { + .list-item { + padding: 12px; + font-size: 14px; + border-radius: 6px; + transition: all .4s ease; + text-align: center; + font-weight: 600; + cursor: pointer; + &.active { + background-color: var(--orange-main); + color: #fff; + } + @include hover-supported() { + background-color: #eee; + color: #000; + } + } +} diff --git a/angular/src/app/components/terminal-list/terminal-list.component.spec.ts b/angular/src/app/components/terminal-list/terminal-list.component.spec.ts new file mode 100644 index 0000000..2b41b3b --- /dev/null +++ b/angular/src/app/components/terminal-list/terminal-list.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TerminalListComponent } from './terminal-list.component'; + +describe('TerminalListComponent', () => { + let component: TerminalListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TerminalListComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(TerminalListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/angular/src/app/components/terminal-list/terminal-list.component.ts b/angular/src/app/components/terminal-list/terminal-list.component.ts new file mode 100644 index 0000000..98f755c --- /dev/null +++ b/angular/src/app/components/terminal-list/terminal-list.component.ts @@ -0,0 +1,25 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatBottomSheetRef, MAT_BOTTOM_SHEET_DATA } from '@angular/material/bottom-sheet'; + +export interface IListData { + list: Array; + active: any; +} + +@Component({ + selector: 'app-terminal-list', + templateUrl: './terminal-list.component.html', + styleUrls: ['./terminal-list.component.scss'] +}) +export class TerminalListComponent implements OnInit { + + constructor(@Inject(MAT_BOTTOM_SHEET_DATA) public data: IListData, private _bottomSheetRef: MatBottomSheetRef) { } + + ngOnInit(): void { + } + + selectItem(item: any) { + this._bottomSheetRef.dismiss(item) + } + +} diff --git a/angular/src/app/components/user-data-order/user-data-order.component.html b/angular/src/app/components/user-data-order/user-data-order.component.html index 4049439..52080c0 100644 --- a/angular/src/app/components/user-data-order/user-data-order.component.html +++ b/angular/src/app/components/user-data-order/user-data-order.component.html @@ -1,26 +1,69 @@ -
-
-

Оформление заказа

-

- Произошла ошибка. Попробуйте позже. +

+ +

Оформление заказа

+

+ Произошла ошибка. Попробуйте позже. +

+
+

+ +

+
+

+

-
-

- -

-
-

- -

-

- -

-

- -

-
- -
+

+ +

+

+ +

+
+

+ + +

+ -

- +
+
+

+ + +

+

+ + +

+

+ + + +

+ -

- -

-
-
-
- Товаров: {{order.products.length}} - {{order.products[0].currency_symbol}}{{order.price}} -
- -
-

Такой адрес не найден! Введите правильный адрес

- +

+ +

+
+
+
+ Товаров: {{ order.products.length }} + {{ + order.products[0].currency_symbol + }}{{ order.price }} +
+ +
+

+ Такой адрес не найден! Введите правильный адрес +

+
-
- -
+
+ +
- - \ No newline at end of file + + diff --git a/angular/src/app/components/user-data-order/user-data-order.component.scss b/angular/src/app/components/user-data-order/user-data-order.component.scss index 012640d..e6492b6 100644 --- a/angular/src/app/components/user-data-order/user-data-order.component.scss +++ b/angular/src/app/components/user-data-order/user-data-order.component.scss @@ -1,6 +1,6 @@ :host { .woocommerce-shipping-fields__field-wrapper { - margin: 8px auto 0 auto; + margin: 8px auto 100px auto; max-width: 400px; } diff --git a/angular/src/app/components/user-data-order/user-data-order.component.ts b/angular/src/app/components/user-data-order/user-data-order.component.ts index b5226b1..63ff7de 100644 --- a/angular/src/app/components/user-data-order/user-data-order.component.ts +++ b/angular/src/app/components/user-data-order/user-data-order.component.ts @@ -16,6 +16,7 @@ import { Order } from 'src/app/models/order'; import { Store } from '@ngrx/store'; import * as fromConfig from '../../state/config/config.reducer' import { lastValueFrom } from 'rxjs'; +import { GetTerminalsService } from 'src/app/services/get-terminals.service'; @@ -43,6 +44,7 @@ export class UserDataOrderComponent implements OnInit, OnDestroy { private intervalTimeDelivery!: any public userData: UserData = { + name: '', first_name: null, last_name: null, street: null, @@ -50,6 +52,7 @@ export class UserDataOrderComponent implements OnInit, OnDestroy { flat: null, city: this.cities[0], phone: null, + selectedTerminal: null }; public deliverData: DeliveryData = { deliveryDate: null, @@ -75,14 +78,14 @@ export class UserDataOrderComponent implements OnInit, OnDestroy { private wpJsonService: WpJsonService, private http: HttpClient, private cookiesService: CookiesService, - private store: Store + private store: Store, + private _getTerminals: GetTerminalsService ) { } async ngOnInit() { this.checkAuthorization(true) this._createMainForm(); this.getTerminalList(); - this.selectedTerminal = JSON.parse(this.cookiesService.getItem('selectedTerminal') || '') this.checkoutConfig$.subscribe({ next: (value: any) => { this.checkoutConfig = value @@ -99,21 +102,18 @@ export class UserDataOrderComponent implements OnInit, OnDestroy { } - getTerminalList() { - this.http.get('./assets/terminal_list1.json').subscribe({ - next: (value) => { - this.terminalList = value - }, - error: (err) => { - console.error(err); - - } - }) - // this.wpJsonService.getTerminalList().subscribe({ + async getTerminalList() { + // this.http.get('./assets/terminal_list1.json').subscribe({ // next: (value) => { // this.terminalList = value + // }, + // error: (err) => { + // console.error(err); // } // }) + const _getTerminals = await this._getTerminals.getTerminalList() + this.terminalList = _getTerminals.list + this.selectedTerminal = _getTerminals.active } checkAuthorization(showAuthoriztion: boolean, forced = false) { @@ -235,8 +235,9 @@ export class UserDataOrderComponent implements OnInit, OnDestroy { // await this.autoCompleteService.setCity(this.userData.city); const isSelfDelivery = this.deliverData.deliveryType?.name === "Самовывоз" return this.fb.group({ + selectedTerminal: [{ value: this.selectedTerminal, disabled: true }, []], phone: [this.userData.phone], - first_name: [this.userData.first_name, [Validators.required, Validators.minLength(2), Validators.maxLength(255),]], + first_name: [this.userData.name, [Validators.required, Validators.minLength(2), Validators.maxLength(255),]], // last_name: [this.userData.last_name, [Validators.required, Validators.minLength(2), Validators.maxLength(255),]], street: [{ value: this.userData.street, disabled: isSelfDelivery }, isSelfDelivery ?? [Validators.required, Validators.minLength(2), Validators.maxLength(255),]], house: [{ value: this.userData.house, disabled: isSelfDelivery }, isSelfDelivery ?? [Validators.required, Validators.maxLength(10), Validators.pattern('^\\d+[-|\\d]+\\d+$|^\\d*$')]], @@ -250,7 +251,7 @@ export class UserDataOrderComponent implements OnInit, OnDestroy { this.deliverData.deliveryType = this.deliveryTypes[0]; return this.fb.group({ deliveryDate: [{ value: this.deliverData.deliveryDate, disabled: this.checkoutConfig.timeDelivery.changeTime.disabled }, []], - deliveryType: [{ value: this.deliverData.deliveryType, disabled: this.checkoutConfig.delivery.disabled }, [Validators.required]], + deliveryType: [{ value: this.deliverData.deliveryType, disabled: this.checkoutConfig.delivery.disabled || this.deliveryTypes.length < 2 }, [Validators.required]], paymentMethod: [{ value: this.deliverData.paymentMethod, disabled: this.checkoutConfig.payments.disabled }, [Validators.required]], persons: [this.deliverData.persons, [Validators.required, Validators.minLength(2), Validators.maxLength(255),]], comment: [this.deliverData.comment, [Validators.maxLength(255),]] diff --git a/angular/src/app/interface/data.ts b/angular/src/app/interface/data.ts index 65b0be3..e9d9443 100644 --- a/angular/src/app/interface/data.ts +++ b/angular/src/app/interface/data.ts @@ -251,4 +251,11 @@ export interface UserData { flat: string | null; city: string; phone: string | null; + selectedTerminal: ITerminal | null; + name: string +} + +export interface ITerminal { + label: string; + id: string; } diff --git a/angular/src/app/models/order.ts b/angular/src/app/models/order.ts index 0ba1fe6..836a5a4 100644 --- a/angular/src/app/models/order.ts +++ b/angular/src/app/models/order.ts @@ -62,7 +62,7 @@ export class Order { city: '' }, amount: this.price, - terminal_id: this.terminal_id + terminal_id: this.userData?.selectedTerminal?.id || this.terminal_id }, } } diff --git a/angular/src/app/pages/cart/cart.component.ts b/angular/src/app/pages/cart/cart.component.ts index 211d900..1be7bdb 100644 --- a/angular/src/app/pages/cart/cart.component.ts +++ b/angular/src/app/pages/cart/cart.component.ts @@ -1,14 +1,25 @@ -import { Component, EventEmitter, HostListener, OnInit, Output } from '@angular/core'; +import { + Component, + EventEmitter, + HostListener, + OnInit, + Output, +} from '@angular/core'; +import { MatSnackBar } from '@angular/material/snack-bar'; import { MessageService } from 'primeng/api'; +import { SnackBarComponent } from 'src/app/components/snack-bar/snack-bar.component'; import { Order } from 'src/app/models/order'; import { OrderProduct } from 'src/app/models/order-product'; -import { CartService, ProductAmountAction } from 'src/app/services/cart.service'; +import { + CartService, + ProductAmountAction, +} from 'src/app/services/cart.service'; import { OrderService } from 'src/app/services/order.service'; @Component({ selector: 'app-cart', templateUrl: './cart.component.html', - styleUrls: ['./cart.component.scss'] + styleUrls: ['./cart.component.scss'], }) export class CartComponent implements OnInit { @Output() showAuthoriztion = new EventEmitter(); @@ -24,25 +35,26 @@ export class CartComponent implements OnInit { private orderService: OrderService, private cartService: CartService, private messageService: MessageService, - ) { } + private _snackBar: MatSnackBar + ) {} ngOnInit(): void { this.width = window.innerWidth; - this.changeDullScreenMode() - this.loadCart() + this.changeDullScreenMode(); + this.loadCart(); } // Изменение размера окна @HostListener('window:resize', ['$event']) onResize(event: any) { - this.width = event.target.innerWidth; - this.changeDullScreenMode() + this.width = event.target.innerWidth; + this.changeDullScreenMode(); } - toggleSideBar(): void{ + toggleSideBar(): void { this.visibleSidebar = !this.visibleSidebar; this.orderConfirmed = false; - this.loadCart() + this.loadCart(); } hide() { @@ -51,25 +63,25 @@ export class CartComponent implements OnInit { changeDullScreenMode() { if (this.width < 650) { - this.isFullScreen = true + this.isFullScreen = true; } else { - this.isFullScreen = false + this.isFullScreen = false; } } async loadCart(): Promise { this.loading = true; this.order = await this.orderService.getOrder(true); - if (this.order) this.price = this.order.price - this.loading = false; + if (this.order) this.price = this.order.price; + this.loading = false; } - removeFromCart(event: Event, guid: string): void{ + removeFromCart(event: Event, guid: string): void { event.preventDefault(); this.orderService.removeFromCart(guid); } - confirmOrder(event: Event): void{ + confirmOrder(event: Event): void { event.preventDefault(); this.showAuthoriztion.emit(true); this.orderConfirmed = true; @@ -78,23 +90,42 @@ export class CartComponent implements OnInit { setAmount(product: OrderProduct, method: 'plus' | 'minus') { if (method === 'plus') { - this.cartService.changeAmountProduct(product.guid, ProductAmountAction.increment) - product.amount++ + this.cartService.changeAmountProduct( + product.guid, + ProductAmountAction.increment + ); + product.amount++; this.price = this.price + Number(product.price); } else if (method === 'minus' && product.amount > 1) { - this.cartService.changeAmountProduct(product.guid, ProductAmountAction.decrement) - product.amount-- + this.cartService.changeAmountProduct( + product.guid, + ProductAmountAction.decrement + ); + product.amount--; this.price = this.price - Number(product.price); } } orderSubmitted(orderid: number) { - this.visibleSidebar = false - this.messageService.add({ severity: 'success', summary: `Заказ оформлен! Номер заказа: ${orderid}` }); + this.visibleSidebar = false; + this._snackBar.open(`Заказ оформлен! Номер заказа: ${orderid}`, 'Ок') } confirmClearCart() { - this.messageService.add({ key: 'c', sticky: true, severity: 'warn', summary: 'Вы уверены, что хотите очистить корзину?' }); + const snackBar = this._snackBar.openFromComponent(SnackBarComponent, { + duration: 4000, + data: { + text: 'Очистить корзину?', + }, + }); + snackBar.afterDismissed().subscribe(({ dismissedByAction }) => { + if (dismissedByAction) { + this.cartService.clearCart(); + this.loadCart(); + this.visibleSidebar = false; + } + }); + // this.messageService.add({ key: 'c', sticky: true, severity: 'warn', summary: 'Вы уверены, что хотите очистить корзину?' }); } onReject() { @@ -102,10 +133,9 @@ export class CartComponent implements OnInit { } onConfirm() { - this.cartService.clearCart() - this.loadCart() - this.visibleSidebar = false + this.cartService.clearCart(); + this.loadCart(); + this.visibleSidebar = false; this.messageService.clear('c'); } - } diff --git a/angular/src/app/pages/products/products.component.html b/angular/src/app/pages/products/products.component.html index 4ccacfb..b8a9849 100644 --- a/angular/src/app/pages/products/products.component.html +++ b/angular/src/app/pages/products/products.component.html @@ -1,9 +1,6 @@
-
- - +
-
{{ product.name }}

- {{product.description}} + {{ product.description }}

- Lorem ipsum dolor sit amet consectetur adipisicing elit. Odio - consequuntur voluptates est. + {{ product.description }}

- - - -
-
- -

{{ message.summary }}

-

{{ message.detail }}

-
-
-
- -
-
- -
-
-
-
-
{ - this.confirmTerminalList() - }, 0) + await this.getTerminalList(); + this.getData(); + // this.messageService.add({ + // severity: 'info', + // summary: 'В одном заказе могут быть товары только из выбранного пункта выдачи', + // life: 5000 + // }); this.loading = false; } async getTerminalList() { - const terminalList = (await lastValueFrom( - this.wpJsonService.getTerminalList() - )) - this.terminalList = this.toTreeJson(this.keyValue(terminalList), terminalList) - const terminalFromCookie = JSON.parse(this.cookiesService.getItem('selectedTerminal') || 'null') - - const conditionDelete = this.terminalList.find((terminal: any) => JSON.stringify(terminal) === JSON.stringify(terminalFromCookie)) - if (!conditionDelete) { - this.cookiesService.deleteCookie('selectedTerminal') - } - - this.selectedTerminal = JSON.parse(this.cookiesService.getItem('selectedTerminal') || 'null') || this.terminalList[0] - this.cartService.changeTerminal(this.selectedTerminal) - } - - confirmTerminalList() { - if (this.cartService.cartCount) return - this.messageService.clear(); - this.messageService.add({ key: 'c', sticky: true, severity: 'warn', summary: 'Вам подходит пункт выдачи?', detail: this.selectedTerminal.label }); - } - - onConfirm() { - this.messageService.add({ - severity: 'info', - summary: 'В одном заказе могут быть товары только из выбранного пункта выдачи', - life: 5000 - }); - this.messageService.clear('c'); - } - - onReject() { - this.messageService.clear('c'); - this.messageService.add({ - severity: 'info', - summary: 'Выберите пункт выдачи. В одном заказе могут быть товары только из выбранного пункта.', - life: 6000 - }); + const _getTerminals = await this._getTerminals.getTerminalList() + this.terminalList = _getTerminals.list + this.selectedTerminal = _getTerminals.active } getData() { - this.wpJsonService.getAllData(`${this.selectedTerminal.label}${this.selectedTerminal.id}`).subscribe({ - next: (value) => { - this.products = value.products - this.groups = value.groups - this.groups.unshift( - { + this.wpJsonService + .getAllData(`${this.selectedTerminal.label}${this.selectedTerminal.id}`) + .subscribe({ + next: (value) => { + this.products = value.products; + this.groups = value.groups; + this.groups.unshift({ id: uuidv4(), - label: 'Все' - } - ) - this.selectedGroup = this.groups[0] - this.modifiersGroups = value.modifiers_groups - this.modifiers = value.modifiers + label: 'Все', + }); + this.selectedGroup = this.groups[0]; + this.modifiersGroups = value.modifiers_groups; + this.modifiers = value.modifiers; - this.route.queryParams.subscribe((params) => { - if (params['group']) { - this.selectedGroup = this.groups.find((group) => group.label === params['group']) || this.groups[0] - } - }) - } - }) + this.route.queryParams.subscribe((params) => { + if (params['group']) { + this.selectedGroup = + this.groups.find((group) => group.label === params['group']) || + this.groups[0]; + } + }); + }, + }); } onPageChange(event: any) { @@ -121,24 +90,37 @@ export class ProductsComponent implements OnInit { } filterByGroup(group?: Group) { - if (!this.selectedGroup) return [] + if (!this.selectedGroup) return []; if (this.selectedGroup.label === 'Все') { - if (group) return JSON.parse(JSON.stringify(this.products.filter((product) => product.groupId === group.id))).slice(0, 4) - return this.products + if (group) + return JSON.parse( + JSON.stringify( + this.products.filter((product) => product.groupId === group.id) + ) + ).slice(0, 4); + return this.products; } - return JSON.parse(JSON.stringify(this.products.filter((product) => product.groupId === this.selectedGroup.id))) + return JSON.parse( + JSON.stringify( + this.products.filter( + (product) => product.groupId === this.selectedGroup.id + ) + ) + ); } cropList(list: Array, quantity: number) { - return list.slice(this.currentPage, this.currentPage + quantity) + return list.slice(this.currentPage, this.currentPage + quantity); } addToCart(event: MouseEvent, product: Product) { if (event) { - event.preventDefault() + event.preventDefault(); } - const productModalWidth = product.modifiers_group.length ? '94vw' : '50vw' - const productModalMaxWidth = product.modifiers_group.length ? '1400px' : '500px' + const productModalWidth = product.modifiers_group.length ? '94vw' : '50vw'; + const productModalMaxWidth = product.modifiers_group.length + ? '1400px' + : '500px'; const ref = this.dialogService.open(ProductModalComponent, { header: product.name, width: 'fit-content', @@ -147,7 +129,7 @@ export class ProductsComponent implements OnInit { 'min-width': '300px', 'max-height': '90vh', 'border-radius': '1.125rem', - width: productModalWidth + width: productModalWidth, }, contentStyle: { 'max-height': '90vh', @@ -158,67 +140,46 @@ export class ProductsComponent implements OnInit { data: { product: product, modifiersGroups: this.modifiersGroups, - modifiers: this.modifiers + modifiers: this.modifiers, }, baseZIndex: 10000, autoZIndex: true, dismissableMask: true, closeOnEscape: true, }); - } - changeTerminal() { - setTimeout(() => { - this.products.length = 0; - this.loading = true; - this.getData() - this.cartService.changeTerminal(this.selectedTerminal); - this.loading = false; - this.router.navigate([]); - this.currentPage = 0 - }, 0); + showTerminals() { + const bottomSheet = this._bottomSheet.open(TerminalListComponent, { + data: { + list: this.terminalList, + active: this.selectedTerminal, + }, + ariaLabel: 'Список точек', + }); + bottomSheet.afterDismissed().subscribe((selectedTerminal) => { + if (!selectedTerminal) return; + setTimeout(() => { + this.products.length = 0; + this.loading = true; + this.selectedTerminal = selectedTerminal; + this.getData(); + this.cartService.changeTerminal(this.selectedTerminal); + this.loading = false; + this.router.navigate([]); + this.currentPage = 0; + }, 0); + }); } changeGroup(group: Group) { - this.selectedGroup = group + this.selectedGroup = group; this.router.navigate([], { queryParams: { group: group.label, }, queryParamsHandling: 'merge', }); - this.currentPage = 0 + this.currentPage = 0; } - - onGroupUnselect(event: any) { - setTimeout(() => { - this.selectedGroup = event.node - }, 0); - } - - onTerminalUnselect(event: any) { - setTimeout(() => { - this.selectedTerminal = event.node - this.cartService.changeTerminal(this.selectedTerminal) - }, 0); - } - - keyValue(obj: Object) { - return Object.keys(obj) - } - - toTreeJson(array: Array, terminalList: any): Array { - let treeJson: Object[] = [] - for (const key of array) { - treeJson.push( - { - label: key, - id: terminalList[key] - } - ) - } - return treeJson - } - } diff --git a/angular/src/app/services/get-terminals.service.ts b/angular/src/app/services/get-terminals.service.ts new file mode 100644 index 0000000..2cf46a6 --- /dev/null +++ b/angular/src/app/services/get-terminals.service.ts @@ -0,0 +1,76 @@ +import { Injectable } from '@angular/core'; +import { lastValueFrom } from 'rxjs'; +import { ITerminal } from '../interface/data'; +import { CartService } from './cart.service'; +import { CookiesService } from './cookies.service'; +import { WpJsonService } from './wp-json.service'; + +export interface IGetTerminalList { + list: ITerminal[]; + active: ITerminal; +} + +@Injectable({ + providedIn: 'root' +}) +export class GetTerminalsService { + public terminalList!: ITerminal[]; + public selectedTerminal!: ITerminal; + + constructor( + private wpJsonService: WpJsonService, + public cartService: CartService, + private cookiesService: CookiesService, + ) { } + + async getTerminalList(): Promise { + const terminalList = await lastValueFrom( + this.wpJsonService.getTerminalList() + ); + this.terminalList = this.toTreeJson( + this.keyValue(terminalList), + terminalList + ); + const terminalFromCookie = JSON.parse( + this.cookiesService.getItem('selectedTerminal') || 'null' + ); + + const conditionDelete = this.terminalList.find( + (terminal: any) => + JSON.stringify(terminal) === JSON.stringify(terminalFromCookie) + ); + if (!conditionDelete) { + this.cookiesService.deleteCookie('selectedTerminal'); + } + + const selectedTerminal = terminalFromCookie + ? this.terminalList.find( + (value: any) => value.id === terminalFromCookie.id + ) + : null; + if (!selectedTerminal) { + this.cartService.clearCart(); + } + this.selectedTerminal = selectedTerminal || this.terminalList[0]; + this.cartService.changeTerminal(this.selectedTerminal); + return { + list: this.terminalList, + active: this.selectedTerminal + } + } + + toTreeJson(array: Array, terminalList: any): Array { + let treeJson: ITerminal[] = []; + for (const key of array) { + treeJson.push({ + label: key, + id: terminalList[key], + }); + } + return treeJson; + } + + keyValue(obj: Object) { + return Object.keys(obj); + } +} diff --git a/angular/src/app/services/order.service.ts b/angular/src/app/services/order.service.ts index 525bee2..07dae2f 100644 --- a/angular/src/app/services/order.service.ts +++ b/angular/src/app/services/order.service.ts @@ -42,14 +42,20 @@ export class OrderService { const cart = this.cartService.getCart(); if (cart.products.length) { + const token = this.cookiesService.getItem('token') || ''; const products = await this.getProducts(cart); - const additionalInfo = this.jsonRpcService.rpc( - { - method: 'getAdditionalInfo', - params: [], - }, - RpcService.authService, - true + // const additionalInfo = this.jsonRpcService.rpc( + // { + // method: 'getAdditionalInfo', + // params: [], + // }, + // RpcService.authService, + // true + // ); + const additionalInfo = this.wpJsonService.getCustomerInfo( + environment.systemId, + token, + environment.icardProxy ); const tokenData = this.jsonRpcService.rpc( @@ -64,14 +70,15 @@ export class OrderService { const info = await lastValueFrom( forkJoin([additionalInfo, tokenData, products]) ); - const token = this.cookiesService.getItem('token'); + const customer_info = info[0]?.customer_info + const terminal = JSON.parse( this.cookiesService.getItem('selectedTerminal') || 'null' ) || this.cartService.selectedTerminal$; this.order = new Order({ products: products, - userData: info[0]?.data, + userData: customer_info, phone: info[1].data?.mobile_number, token: token, terminal_id: terminal.id, @@ -95,6 +102,10 @@ export class OrderService { const productSub = allData.products.find( (product: any) => product.id === cart.products[i].id ); + if (!productSub) { + this.cartService.removeFromCart(cart.products[i].guid); + break; + } const product = Object.assign(cloneDeep(cart.products[i]), { category_id: 0, price: productSub.price, diff --git a/angular/src/sass/_mixins.scss b/angular/src/sass/_mixins.scss new file mode 100644 index 0000000..d29ed1c --- /dev/null +++ b/angular/src/sass/_mixins.scss @@ -0,0 +1,7 @@ +@mixin hover-supported { + @media not all and (pointer: coarse) { + &:hover { + @content; + } + } +} diff --git a/angular/src/styles.scss b/angular/src/styles.scss index 791419d..7560685 100644 --- a/angular/src/styles.scss +++ b/angular/src/styles.scss @@ -3,6 +3,7 @@ @import '~@fortawesome/fontawesome-free/scss/solid.scss'; @import '~@fortawesome/fontawesome-free/scss/regular.scss'; @import '~@fortawesome/fontawesome-free/scss/brands.scss'; +@import 'src/sass/mixins'; // @import '~mdb-angular-ui-kit/assets/scss/mdb.scss'; @@ -24,6 +25,17 @@ table{border-collapse:collapse;border-spacing:0} font-family: 'Raleway', sans-serif; } +div.cdk-overlay-container { + z-index: 11200; +} + +.mat-snack-bar-container { + transform: scale(1); + opacity: 1; + background: #fff; + color: #323232; +} + .p-inputtext { width: 100%; border: 1px solid #B8DEFF; @@ -52,9 +64,11 @@ table{border-collapse:collapse;border-spacing:0} border-color: #f9b004; } -.p-selectbutton .p-button.p-highlight:hover { - background: #f9b004; - border-color: #f9b004; +.p-selectbutton .p-button.p-highlight { + @include hover-supported() { + background: #f9b004; + border-color: #f9b004; + } } mark { @@ -254,3 +268,6 @@ body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; background: html, body { height: 100%; } body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } + +html, body { height: 100%; } +body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }