@snabcentr/client-ui 3.51.15 → 3.52.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/configurators/index.d.ts +1 -0
- package/configurators/models/index.d.ts +1 -0
- package/configurators/models/sandwich_m2/sc-i-sandwich-m2-settings.d.ts +18 -0
- package/configurators/sandwich/sc-sandwich.component.d.ts +24 -0
- package/configurators/sandwich_m2/index.d.ts +4 -0
- package/configurators/sandwich_m2/sandwich-m2-skeleton/sc-sandwich-m2-skeleton.component.d.ts +8 -0
- package/configurators/sandwich_m2/sc-i-new-cart-item-sandwich-m2.d.ts +23 -0
- package/configurators/sandwich_m2/sc-sandwich-m2-item-submit-state.d.ts +13 -0
- package/configurators/sandwich_m2/sc-sandwich-m2.component.d.ts +267 -0
- package/directives/next-input-focus/sc-next-input-focus.directive.d.ts +14 -5
- package/esm2022/configurators/index.mjs +2 -1
- package/esm2022/configurators/models/index.mjs +2 -1
- package/esm2022/configurators/models/sandwich_m2/sc-i-sandwich-m2-settings.mjs +2 -0
- package/esm2022/configurators/sandwich/sc-sandwich.component.mjs +57 -6
- package/esm2022/configurators/sandwich_m2/index.mjs +5 -0
- package/esm2022/configurators/sandwich_m2/sandwich-m2-skeleton/sc-sandwich-m2-skeleton.component.mjs +14 -0
- package/esm2022/configurators/sandwich_m2/sc-i-new-cart-item-sandwich-m2.mjs +2 -0
- package/esm2022/configurators/sandwich_m2/sc-sandwich-m2-item-submit-state.mjs +5 -0
- package/esm2022/configurators/sandwich_m2/sc-sandwich-m2.component.mjs +561 -0
- package/esm2022/directives/next-input-focus/sc-next-input-focus.directive.mjs +39 -12
- package/fesm2022/snabcentr-client-ui.mjs +651 -16
- package/fesm2022/snabcentr-client-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/release_notes.tmp +3 -3
- package/styles/tailwind/tailwind.scss +72 -0
|
@@ -3,7 +3,7 @@ import { InjectionToken, inject, Injectable, NgZone, signal, EventEmitter, Chang
|
|
|
3
3
|
import * as i1 from '@snabcentr/client-core';
|
|
4
4
|
import { ScContactsService, ScUserService, ScLocationsService, ScAuthService, SEARCH_TERM, ScUnitsHelper, ScImageHelper, SC_PATH_IMAGE_NOT_FOUND, ScImage, ScPhoneService, ScUserMetrikaService, ScUserMetrikaGoalsEnum, IS_RUNNING_ON_TERMINAL, ScVCardService, ScVerificationService, ScISuggestionType, SC_MIN_LENGTH_SEARCH_TERM, ScConvertersService, ScOpfList, ScReferencesService, ScContragentService, ScBannerService, ScMediaImageTransformerPipe, ScCartService, ScUploadedFile, SC_ORDER_LOADER, ScMimeTypes, ScCatalogService, SC_URLS, IS_SERVER, ScWarehouseService, SEARCH_TERM_PROVIDERS, ScPaginationService, SC_NEXT_PAGE_PAGINATION_CLICK, SC_PRODUCT_PAGINATION_OPTIONS, ScCatalogFilterService, ScIdOrSlugPipe, SC_CATEGORY_INFO, ScConfiguratorService, RESPONSE, ScIconTypesEnum, ScDocumentInfoTypesEnum, ScOrderDraftsService, ScRouteKeys, ScSeoService, scOrderIsLoaded, ScFrequentlyAskedQuestionsService, SC_COMPANY_INFO, ScFeedbackService } from '@snabcentr/client-core';
|
|
5
5
|
import * as i5$1 from 'rxjs';
|
|
6
|
-
import { EMPTY, BehaviorSubject, switchMap, of, shareReplay, map, Subject, filter, tap, catchError, finalize, startWith, share, timer, scan, takeWhile, endWith, distinctUntilChanged, debounceTime, throwError, combineLatest, Observable, pairwise, merge, noop, first
|
|
6
|
+
import { EMPTY, BehaviorSubject, switchMap, of, shareReplay, map, Subject, filter, tap, catchError, finalize, startWith, share, timer, scan, takeWhile, endWith, distinctUntilChanged, debounceTime, throwError, combineLatest, Observable, pairwise, merge, skip, from, concatMap, noop, first } from 'rxjs';
|
|
7
7
|
import { WA_WINDOW } from '@ng-web-apis/common';
|
|
8
8
|
import { takeUntilDestroyed, toSignal, outputFromObservable, toObservable } from '@angular/core/rxjs-interop';
|
|
9
9
|
import * as i4$1 from '@taiga-ui/cdk';
|
|
@@ -25,7 +25,7 @@ import * as i5 from '@taiga-ui/core/components/label';
|
|
|
25
25
|
import * as i8 from '@maskito/angular';
|
|
26
26
|
import { MaskitoDirective } from '@maskito/angular';
|
|
27
27
|
import * as i2$2 from '@angular/common';
|
|
28
|
-
import { DOCUMENT, CommonModule, NgIf, AsyncPipe, NgFor, NgClass } from '@angular/common';
|
|
28
|
+
import { DOCUMENT, CommonModule, NgIf, AsyncPipe, DecimalPipe, NgFor, NgClass } from '@angular/common';
|
|
29
29
|
import * as i2$3 from '@taiga-ui/polymorpheus';
|
|
30
30
|
import { POLYMORPHEUS_CONTEXT, PolymorpheusComponent, PolymorpheusTemplate, PolymorpheusOutlet, injectContext } from '@taiga-ui/polymorpheus';
|
|
31
31
|
import * as i2 from 'angularx-qrcode';
|
|
@@ -838,36 +838,63 @@ const ScLinks = [ScTelLinkDirective, ScEmailLinkDirective, ScPhoneFormatPipe];
|
|
|
838
838
|
/* eslint-disable lodash/prefer-lodash-method */
|
|
839
839
|
/**
|
|
840
840
|
* Директива для перехода по нажатию клавиши enter на следующее поле ввода формы.
|
|
841
|
+
* Поддерживает как legacy Taiga UI v3 контролы (AbstractTuiControl), так и новые v4
|
|
842
|
+
* (tui-textfield + нативные input) — через DOM-fallback.
|
|
841
843
|
*/
|
|
842
844
|
class ScNextInputFocusDirective {
|
|
845
|
+
constructor() {
|
|
846
|
+
/**
|
|
847
|
+
* Элемент формы.
|
|
848
|
+
*/
|
|
849
|
+
this.el = inject(ElementRef);
|
|
850
|
+
}
|
|
843
851
|
/**
|
|
844
|
-
*
|
|
852
|
+
* По Enter — переход на следующее редактируемое поле формы.
|
|
853
|
+
* Сначала пробует legacy Taiga UI v3 контролы, затем DOM fallback для v4.
|
|
845
854
|
*
|
|
846
|
-
* @param event
|
|
855
|
+
* @param event Событие нажатия клавиши.
|
|
847
856
|
*/
|
|
848
857
|
onFormKeyDownEnter(event) {
|
|
849
858
|
if (event.code !== 'Enter' && event.key !== 'Enter') {
|
|
850
859
|
return;
|
|
851
860
|
}
|
|
852
861
|
event.preventDefault();
|
|
853
|
-
|
|
854
|
-
const
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
862
|
+
// Taiga UI v3: переход через AbstractTuiControl (legacy-обёртки tui-input, tui-input-number и др.).
|
|
863
|
+
const legacy = this.legacyControls.toArray();
|
|
864
|
+
const legacyIndex = legacy.findIndex((control) => control.focused);
|
|
865
|
+
if (legacyIndex !== -1) {
|
|
866
|
+
const next = legacy[legacyIndex + 1]?.nativeFocusableElement;
|
|
867
|
+
if (next) {
|
|
868
|
+
next.focus();
|
|
869
|
+
return;
|
|
859
870
|
}
|
|
860
871
|
}
|
|
872
|
+
// Taiga UI v4: переход через DOM — ищем нативные input внутри формы (tui-textfield + директивы).
|
|
873
|
+
const { target } = event;
|
|
874
|
+
if (!(target instanceof HTMLInputElement) || target.type === 'range') {
|
|
875
|
+
return;
|
|
876
|
+
}
|
|
877
|
+
// eslint-disable-next-line unicorn/prefer-spread
|
|
878
|
+
const inputs = Array.from(this.el.nativeElement.querySelectorAll('input')).filter((element) => element.type !== 'range' && !element.readOnly && !element.disabled);
|
|
879
|
+
const currentIndex = inputs.indexOf(target);
|
|
880
|
+
if (currentIndex === -1) {
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
const nextInput = inputs.at(currentIndex + 1);
|
|
884
|
+
if (nextInput) {
|
|
885
|
+
nextInput.focus();
|
|
886
|
+
nextInput.select();
|
|
887
|
+
}
|
|
861
888
|
}
|
|
862
889
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScNextInputFocusDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
863
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: ScNextInputFocusDirective, selector: "form[ScNextInputFocus]", host: { listeners: { "keydown": "onFormKeyDownEnter($event)" } }, queries: [{ propertyName: "
|
|
890
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: ScNextInputFocusDirective, selector: "form[ScNextInputFocus]", host: { listeners: { "keydown": "onFormKeyDownEnter($event)" } }, queries: [{ propertyName: "legacyControls", predicate: AbstractTuiControl, descendants: true }], ngImport: i0 }); }
|
|
864
891
|
}
|
|
865
892
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScNextInputFocusDirective, decorators: [{
|
|
866
893
|
type: Directive,
|
|
867
894
|
args: [{
|
|
868
895
|
selector: 'form[ScNextInputFocus]',
|
|
869
896
|
}]
|
|
870
|
-
}], propDecorators: {
|
|
897
|
+
}], propDecorators: { legacyControls: [{
|
|
871
898
|
type: ContentChildren,
|
|
872
899
|
args: [AbstractTuiControl, { descendants: true }]
|
|
873
900
|
}], onFormKeyDownEnter: [{
|
|
@@ -5870,14 +5897,22 @@ class ScSandwichComponent {
|
|
|
5870
5897
|
* Выбранный продукт (материал для раскроя).
|
|
5871
5898
|
*/
|
|
5872
5899
|
this.product = new FormControl(null, { validators: Validators.required });
|
|
5900
|
+
/**
|
|
5901
|
+
* Сигнал текущего выбранного продукта — используется в шаблоне для диапазонов и кнопок.
|
|
5902
|
+
*/
|
|
5903
|
+
this.productSignal = toSignal(tuiControlValue(this.product), { initialValue: null });
|
|
5873
5904
|
/**
|
|
5874
5905
|
* Субъект для ручного запуска расчёта.
|
|
5875
5906
|
*/
|
|
5876
5907
|
this.calculateTrigger$ = new Subject();
|
|
5908
|
+
/**
|
|
5909
|
+
* Источник начального результата расчёта для режима редактирования.
|
|
5910
|
+
*/
|
|
5911
|
+
this.seedCalculateResult$ = new BehaviorSubject(undefined);
|
|
5877
5912
|
/**
|
|
5878
5913
|
* {@link Observable} расчета оптимизации раскладки.
|
|
5879
5914
|
*/
|
|
5880
|
-
this.calculate$ = merge(merge(tuiControlValue(this.product), tuiControlValue(this.items)).pipe(
|
|
5915
|
+
this.calculate$ = merge(this.seedCalculateResult$, merge(tuiControlValue(this.product).pipe(skip(1)), tuiControlValue(this.items).pipe(skip(1))).pipe(
|
|
5881
5916
|
// eslint-disable-next-line unicorn/no-useless-undefined
|
|
5882
5917
|
map(() => undefined)), this.calculateTrigger$.pipe(switchMap(() => {
|
|
5883
5918
|
const productId = this.product.value?.id ?? null;
|
|
@@ -5906,6 +5941,14 @@ class ScSandwichComponent {
|
|
|
5906
5941
|
* Валидатор для длины изделия.
|
|
5907
5942
|
*/
|
|
5908
5943
|
this.validatorLength$ = tuiControlValue(this.product).pipe(map((product) => Validators.min(product?.properties?.length ?? 0)));
|
|
5944
|
+
/**
|
|
5945
|
+
* Текст ограничения по ширине («от … до …»), пока выбран товар.
|
|
5946
|
+
*/
|
|
5947
|
+
this.widthRangeText = computed(() => this.formatRange(this.settings()?.minWidth ?? null, this.productSignal()?.properties?.width ?? null, 'мм'));
|
|
5948
|
+
/**
|
|
5949
|
+
* Текст ограничения по длине («от … до …»), пока выбран товар.
|
|
5950
|
+
*/
|
|
5951
|
+
this.lengthRangeText = computed(() => this.formatRange(this.settings()?.minLength ?? null, this.productSignal()?.properties?.length ?? null, 'мм'));
|
|
5909
5952
|
/**
|
|
5910
5953
|
* Признак того, что выполняется запрос на отправку данных выполняется.
|
|
5911
5954
|
*/
|
|
@@ -6039,6 +6082,28 @@ class ScSandwichComponent {
|
|
|
6039
6082
|
}))
|
|
6040
6083
|
.subscribe();
|
|
6041
6084
|
}
|
|
6085
|
+
/**
|
|
6086
|
+
* Форматирование диапазона «от … до …» с учётом отсутствующих границ.
|
|
6087
|
+
*
|
|
6088
|
+
* @param min Нижняя граница.
|
|
6089
|
+
* @param max Верхняя граница.
|
|
6090
|
+
* @param unit Единица измерения.
|
|
6091
|
+
*/
|
|
6092
|
+
// eslint-disable-next-line class-methods-use-this
|
|
6093
|
+
formatRange(min, max, unit) {
|
|
6094
|
+
const hasMin = min != null && min > 0;
|
|
6095
|
+
const hasMax = max != null && max > 0;
|
|
6096
|
+
if (!hasMin && !hasMax) {
|
|
6097
|
+
return null;
|
|
6098
|
+
}
|
|
6099
|
+
if (hasMin && hasMax) {
|
|
6100
|
+
return `от ${min} ${unit} до ${max} ${unit}`;
|
|
6101
|
+
}
|
|
6102
|
+
if (hasMin) {
|
|
6103
|
+
return `от ${min} ${unit}`;
|
|
6104
|
+
}
|
|
6105
|
+
return `до ${max} ${unit}`;
|
|
6106
|
+
}
|
|
6042
6107
|
/**
|
|
6043
6108
|
* Устанавливает начальные значения для полей формы.
|
|
6044
6109
|
*/
|
|
@@ -6058,6 +6123,19 @@ class ScSandwichComponent {
|
|
|
6058
6123
|
if (!configuratorParameters?.items.length) {
|
|
6059
6124
|
this.addItem();
|
|
6060
6125
|
}
|
|
6126
|
+
// Сбрасываем seed и при наличии сохранённого calculationId восстанавливаем результат расчёта —
|
|
6127
|
+
// чтобы в режиме редактирования сразу была видна кнопка «Изменить», а не «Рассчитать».
|
|
6128
|
+
// eslint-disable-next-line unicorn/no-useless-undefined
|
|
6129
|
+
this.seedCalculateResult$.next(undefined);
|
|
6130
|
+
const existingCalculationId = configuratorParameters?.calculationId;
|
|
6131
|
+
const existingQuantity = this.orderItem()?.quantity;
|
|
6132
|
+
if (existingCalculationId && existingQuantity != null && existingQuantity > 0) {
|
|
6133
|
+
this.seedCalculateResult$.next({
|
|
6134
|
+
id: existingCalculationId,
|
|
6135
|
+
quantity: existingQuantity,
|
|
6136
|
+
sheets: [],
|
|
6137
|
+
});
|
|
6138
|
+
}
|
|
6061
6139
|
}
|
|
6062
6140
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSandwichComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6063
6141
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ScSandwichComponent, isStandalone: true, selector: "sc-sandwich", inputs: { settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null }, categoryId: { classPropertyName: "categoryId", publicName: "categoryId", isSignal: true, isRequired: true, transformFunction: null }, editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, orderItem: { classPropertyName: "orderItem", publicName: "orderItem", isSignal: true, isRequired: true, transformFunction: null }, orderId: { classPropertyName: "orderId", publicName: "orderId", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { toggleShowEvent: "toggleShowEvent" }, providers: [
|
|
@@ -6069,7 +6147,7 @@ class ScSandwichComponent {
|
|
|
6069
6147
|
stringify: signal((x) => x.name),
|
|
6070
6148
|
identityMatcher: signal((a, b) => a.id === b.id),
|
|
6071
6149
|
}),
|
|
6072
|
-
], ngImport: i0, template: "@if (!orderItem() && settings()?.allowShowTable) {\n <div class=\"mb-5 flex justify-center\">\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"toggleShowEvent.emit()\"\n type=\"button\"\n iconStart=\"@tui.layout-list\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0432 \u0432\u0438\u0434\u0435 \u0441\u043F\u0438\u0441\u043A\u0430\n </button>\n </div>\n}\n<div class=\"\">\n @let calculateResult = calculateResult$ | async;\n @let products = products$ | async;\n @let productValue = product.value;\n @let validatorWidth = validatorWidth$ | async;\n @let validatorLength = validatorLength$ | async;\n\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit(calculateResult)\"\n ScNextInputFocus\n class=\"flex flex-col gap-3\"\n >\n <label\n tuiLabel\n class=\"grow\"\n >\n \u0422\u043E\u0432\u0430\u0440\n <tui-textfield\n tuiChevron\n [tuiTextfieldCleaner]=\"false\"\n >\n <input\n tuiChevron\n tuiSelect\n [formControl]=\"product\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\"\n />\n\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n @if (productValue) {\n <div class=\"ml-2 text-tui-text-secondary\">\n \u0421\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C:\n <span class=\"font-bold\">{{ productValue.costRub?.toLocaleString() }} {{ productValue.currency.symbol }}/\u0448\u0442.</span>\n </div>\n }\n <tui-error\n [formControl]=\"product\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (product.value && validatorWidth && validatorLength) {\n <p class=\"w-full font-bold\">\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439</p>\n <p class=\"w-full\">\n \u041C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0448\u0438\u0440\u0438\u043D\u0430: {{ settings()?.minWidth }} \u043C\u043C.\n <br />\n \u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0448\u0438\u0440\u0438\u043D\u0430: {{ product.value.properties?.width }} \u043C\u043C.\n <br />\n \u041C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0434\u043B\u0438\u043D\u0430: {{ settings()?.minLength }} \u043C\u043C.\n <br />\n \u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0434\u043B\u0438\u043D\u0430: {{ product.value.properties?.length }} \u043C\u043C.\n <br />\n </p>\n <div\n formArrayName=\"items\"\n class=\"flex flex-col gap-3\"\n >\n @for (item of items.controls; track item) {\n <div\n class=\"flex grow gap-2\"\n [formGroupName]=\"$index\"\n >\n <div class=\"grid grow grid-cols-3 gap-2\">\n <label tuiLabel>\n \u0428\u0438\u0440\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"width\"\n [min]=\"settings()?.minWidth ?? 0\"\n [max]=\"product.value.properties?.width ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n placeholder=\"\u0428\u0438\u0440\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n @if (product.value) {\n <div class=\"slider-ticks-labels\">\n <span> 0 </span>\n <span>{{ product.value.properties?.width }}</span>\n </div>\n }\n <tui-error\n formControlName=\"width\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u0414\u043B\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"length\"\n [min]=\"settings()?.minLength ?? 0\"\n [max]=\"product.value.properties?.length ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n placeholder=\"\u0414\u043B\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n @if (product.value) {\n <div class=\"slider-ticks-labels\">\n <span> 0 </span>\n <span>{{ product.value.properties?.length }}</span>\n </div>\n }\n <tui-error\n formControlName=\"length\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n <label tuiLabel>\n <span class=\"whitespace-nowrap\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442</span>\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n tuiInputNumber\n formControlName=\"count\"\n [min]=\"1\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"count\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n <button\n tuiIconButton\n (click)=\"removeItem($index)\"\n [disabled]=\"items.length <= 1\"\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.trash-2\"\n appearance=\"secondary\"\n class=\"mt-6\"\n [style.flex]=\"'0 0 auto'\"\n ></button>\n </div>\n }\n </div>\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\n class=\"self-center\"\n iconStart=\"@tui.plus\"\n >\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\n </button>\n } @else if (product.value) {\n <tui-error error=\"\u0420\u0430\u0441\u0447\u0435\u0442 \u043F\u043E \u043F\u0440\u043E\u0434\u0443\u043A\u0442\u0443 \u043D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u0435\u043D. \u041E\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044C \u043A \u043C\u0435\u043D\u0435\u0434\u0436\u0435\u0440\u0443\" />\n }\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 \u0440\u0430\u0441\u043F\u0438\u043B\u0430\n <tui-textfield>\n <input\n tuiTextfield\n formControlName=\"marker\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 \u0440\u0430\u0441\u043F\u0438\u043B\u0430\"\n autocomplete=\"marker\"\n />\n </tui-textfield>\n\n <tui-error\n formControlName=\"marker\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (product.value) {\n <tui-loader [showLoader]=\"isCalculateLoading()\">\n @if (calculateResult) {\n <div class=\"mt-2 flex flex-wrap items-end gap-2\">\n <div>\n \u0418\u0442\u043E\u0433\u043E: <span class=\"whitespace-nowrap text-xl font-bold\">{{ getTotalCost(calculateResult).toLocaleString() }} {{ product.value.currency.symbol }}</span>\n </div>\n @if (calculateResult?.quantity && productValue) {\n <div class=\"whitespace-nowrap text-lg text-sc-dark-grey\">\n <span class=\"font-bold\">({{ calculateResult.quantity }} \u0448\u0442.</span> x\n <span class=\"font-bold\">{{ productValue.costRub?.toLocaleString() }} {{ productValue.currency.symbol }}/\u0448\u0442.)</span>\n </div>\n }\n </div>\n }\n </tui-loader>\n }\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n @if (!calculateResult) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"items.invalid || isCalculateLoading()\"\n (click)=\"triggerCalculate()\"\n type=\"button\"\n class=\"self-center\"\n iconStart=\"@tui.calculator\"\n >\n \u0420\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u0442\u044C\n </button>\n } @else {\n <button\n [disabled]=\"form.invalid || isSubmitLoading()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"self-center\"\n iconStart=\"@tui.check\"\n >\n {{ !orderItem() ? '\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0432 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' : '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' }}\n </button>\n }\n </form>\n</div>\n", styles: [":host{display:block;width:100%;max-width:30rem}.slider-ticks-labels{--t-offset: calc($thumb / 2);display:flex;font:var(--tui-font-text-s);margin-inline-start:var(--t-offset);margin-inline-end:var(--t-offset);color:var(--tui-text-secondary)}.slider-ticks-labels>*{position:relative;flex:2;text-align:center}.slider-ticks-labels>*:first-child{left:calc(-1 * var(--t-offset));inset-inline-start:calc(-1 * var(--t-offset));flex:1;text-align:start}.slider-ticks-labels>*:last-child{right:calc(-1 * var(--t-offset));flex:1;text-align:end}@supports (inset-inline-end: 0){.slider-ticks-labels>*:last-child{right:unset;inset-inline-end:calc(-1 * var(--t-offset))}}tui-input-slider+.slider-ticks-labels{margin-inline-start:calc(var(--tui-radius-m) / 2 + var(--t-offset))}tui-textfield+.slider-ticks-labels{--t-offset: calc(var(--tui-radius-m) / 2 + $thumb / 2)}tui-textfield[data-size=l]+.slider-ticks-labels{--t-offset: calc(var(--tui-radius-l) / 2 + $thumb / 2)}tui-input-range:not([new])+.slider-ticks-labels,tui-range+.slider-ticks-labels{--t-offset: $thumb}tui-input-range[new]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, $input-size) + $thumb)}\n"], dependencies: [{ kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: ScNextInputFocusModule }, { kind: "directive", type: ScNextInputFocusDirective, selector: "form[ScNextInputFocus]" }, { kind: "directive", type: TuiLabel, selector: "label[tuiLabel]" }, { kind: "component", type: TuiDataListWrapperComponent, selector: "tui-data-list-wrapper:not([labels]), tui-data-list-wrapper:not([labels])[new]", inputs: ["items", "disabledItemHandler", "emptyContent", "size", "itemContent"], outputs: ["itemClick"] }, { kind: "component", type: TuiError, selector: "tui-error", inputs: ["error"] }, { kind: "component", type: i1$2.TuiTextfieldComponent, selector: "tui-textfield:not([multi])" }, { kind: "directive", type: i1$2.TuiTextfieldDirective, selector: "input[tuiTextfield]:not([tuiInputCard]):not([tuiInputExpire]):not([tuiInputCVC])" }, { kind: "directive", type: i1$2.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }, { kind: "directive", type: i1$2.TuiTextfieldDropdownDirective, selector: "ng-template[tuiTextfieldDropdown]" }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "directive", type: i2$1.TuiSelectDirective, selector: "input[tuiSelect]" }, { kind: "directive", type: i2$1.TuiInputNumberDirective, selector: "input[tuiInputNumber]", inputs: ["min", "max", "prefix", "postfix"] }, { kind: "directive", type: TuiNumberFormat, selector: "[tuiNumberFormat]", inputs: ["tuiNumberFormat"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: TuiFieldErrorPipe, name: "tuiFieldError" }, { kind: "component", type: i5$2.TuiSliderComponent, selector: "input[type=range][tuiSlider]", inputs: ["size", "segments"] }, { kind: "directive", type: i2$1.TuiInputSliderDirective, selector: "input[tuiInputSlider]" }, { kind: "directive", type: ScSelectOnFocusinDirective, selector: "tui-input-number, tui-input, tui-input-phone, tui-input-date, tui-input-password, input[tuiInputNumber], input[tuiTextfield], input[tuiInputSlider]" }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "showLoader"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6150
|
+
], ngImport: i0, template: "@if (!orderItem() && settings()?.allowShowTable) {\n <div class=\"mb-5 flex justify-center\">\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"toggleShowEvent.emit()\"\n type=\"button\"\n iconStart=\"@tui.layout-list\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0432 \u0432\u0438\u0434\u0435 \u0441\u043F\u0438\u0441\u043A\u0430\n </button>\n </div>\n}\n<div>\n @let calculateResult = calculateResult$ | async;\n @let products = products$ | async;\n @let productValue = product.value;\n @let validatorWidth = validatorWidth$ | async;\n @let validatorLength = validatorLength$ | async;\n\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit(calculateResult)\"\n ScNextInputFocus\n class=\"flex flex-col gap-3\"\n >\n <label\n tuiLabel\n class=\"grow\"\n >\n \u0422\u043E\u0432\u0430\u0440\n <tui-textfield\n tuiChevron\n [tuiTextfieldCleaner]=\"false\"\n >\n <input\n tuiChevron\n tuiSelect\n [formControl]=\"product\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\"\n />\n\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error\n [formControl]=\"product\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (productValue && productValue.costRub) {\n <div class=\"-mt-1 text-sm text-tui-text-secondary\">\n <span class=\"font-bold\">{{ productValue.code }}</span>\n \u2014 {{ productValue.costRub.toLocaleString() }} {{ productValue.currency.symbol }}/\u0448\u0442.\n </div>\n }\n\n @if (product.value && validatorWidth && validatorLength) {\n <div class=\"mt-4 flex flex-col gap-1.5\">\n <div class=\"w-full font-bold\">\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439</div>\n <div class=\"flex flex-col gap-1 text-sm text-tui-text-secondary\">\n @if (widthRangeText()) {\n <div>\u0428\u0438\u0440\u0438\u043D\u0430 {{ widthRangeText() }}.</div>\n }\n @if (lengthRangeText()) {\n <div>\u0414\u043B\u0438\u043D\u0430 {{ lengthRangeText() }}.</div>\n }\n </div>\n </div>\n } @else if (product.value) {\n <tui-error error=\"\u0420\u0430\u0441\u0447\u0435\u0442 \u043F\u043E \u043F\u0440\u043E\u0434\u0443\u043A\u0442\u0443 \u043D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u0435\u043D. \u041E\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044C \u043A \u043C\u0435\u043D\u0435\u0434\u0436\u0435\u0440\u0443\" />\n }\n\n <div\n formArrayName=\"items\"\n class=\"flex flex-col gap-3\"\n >\n @for (item of items.controls; track item) {\n <div\n class=\"flex grow gap-2\"\n [formGroupName]=\"$index\"\n >\n <div class=\"grid grow grid-cols-1 items-start gap-2 sm:grid-cols-3\">\n <label tuiLabel>\n \u0428\u0438\u0440\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"width\"\n [min]=\"settings()?.minWidth ?? 0\"\n [max]=\"product.value?.properties?.width ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value\"\n placeholder=\"\u0428\u0438\u0440\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n @if (product.value) {\n <div class=\"slider-ticks-labels\">\n <span> 0 </span>\n <span>{{ product.value.properties?.width }}</span>\n </div>\n }\n <tui-error\n formControlName=\"width\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u0414\u043B\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"length\"\n [min]=\"settings()?.minLength ?? 0\"\n [max]=\"product.value?.properties?.length ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value\"\n placeholder=\"\u0414\u043B\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n @if (product.value) {\n <div class=\"slider-ticks-labels\">\n <span> 0 </span>\n <span>{{ product.value.properties?.length }}</span>\n </div>\n }\n <tui-error\n formControlName=\"length\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n <label tuiLabel>\n <span class=\"whitespace-nowrap\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442</span>\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n tuiInputNumber\n formControlName=\"count\"\n [min]=\"1\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value\"\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"count\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n <button\n tuiIconButton\n (click)=\"removeItem($index)\"\n [disabled]=\"!product.value || items.length <= 1\"\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.trash-2\"\n appearance=\"secondary\"\n class=\"mt-6\"\n [style.flex]=\"'0 0 auto'\"\n ></button>\n </div>\n }\n </div>\n @if (product.value) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\n class=\"self-center\"\n iconStart=\"@tui.plus\"\n >\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\n </button>\n }\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 \u0440\u0430\u0441\u043F\u0438\u043B\u0430\n <tui-textfield>\n <input\n tuiTextfield\n formControlName=\"marker\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 \u0440\u0430\u0441\u043F\u0438\u043B\u0430\"\n autocomplete=\"marker\"\n />\n </tui-textfield>\n\n <tui-error\n formControlName=\"marker\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (product.value) {\n <tui-loader [showLoader]=\"isCalculateLoading()\">\n @if (calculateResult) {\n <div class=\"mt-2 flex flex-wrap items-end gap-2\">\n <div>\n \u0418\u0442\u043E\u0433\u043E: <span class=\"whitespace-nowrap text-xl font-bold\">{{ getTotalCost(calculateResult).toLocaleString() }} {{ product.value.currency.symbol }}</span>\n </div>\n @if (calculateResult?.quantity && productValue) {\n <div class=\"whitespace-nowrap text-lg text-sc-dark-grey\">\n <span class=\"font-bold\">({{ calculateResult.quantity }} \u0448\u0442.</span> x\n <span class=\"font-bold\">{{ productValue.costRub?.toLocaleString() }} {{ productValue.currency.symbol }}/\u0448\u0442.)</span>\n </div>\n }\n </div>\n }\n </tui-loader>\n }\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n @if (!calculateResult) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"items.invalid || isCalculateLoading()\"\n (click)=\"triggerCalculate()\"\n type=\"button\"\n class=\"self-center\"\n iconStart=\"@tui.calculator\"\n >\n \u0420\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u0442\u044C\n </button>\n } @else {\n <button\n [disabled]=\"form.invalid || isSubmitLoading()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"self-center\"\n iconStart=\"@tui.check\"\n >\n {{ !orderItem() ? '\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0432 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' : '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' }}\n </button>\n }\n </form>\n</div>\n", styles: [":host{display:block;width:100%;max-width:30rem}.slider-ticks-labels{--t-offset: calc($thumb / 2);display:flex;font:var(--tui-font-text-s);margin-inline-start:var(--t-offset);margin-inline-end:var(--t-offset);color:var(--tui-text-secondary)}.slider-ticks-labels>*{position:relative;flex:2;text-align:center}.slider-ticks-labels>*:first-child{left:calc(-1 * var(--t-offset));inset-inline-start:calc(-1 * var(--t-offset));flex:1;text-align:start}.slider-ticks-labels>*:last-child{right:calc(-1 * var(--t-offset));flex:1;text-align:end}@supports (inset-inline-end: 0){.slider-ticks-labels>*:last-child{right:unset;inset-inline-end:calc(-1 * var(--t-offset))}}tui-input-slider+.slider-ticks-labels{margin-inline-start:calc(var(--tui-radius-m) / 2 + var(--t-offset))}tui-textfield+.slider-ticks-labels{--t-offset: calc(var(--tui-radius-m) / 2 + $thumb / 2)}tui-textfield[data-size=l]+.slider-ticks-labels{--t-offset: calc(var(--tui-radius-l) / 2 + $thumb / 2)}tui-input-range:not([new])+.slider-ticks-labels,tui-range+.slider-ticks-labels{--t-offset: $thumb}tui-input-range[new]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, $input-size) + $thumb)}\n"], dependencies: [{ kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: ScNextInputFocusModule }, { kind: "directive", type: ScNextInputFocusDirective, selector: "form[ScNextInputFocus]" }, { kind: "directive", type: TuiLabel, selector: "label[tuiLabel]" }, { kind: "component", type: TuiDataListWrapperComponent, selector: "tui-data-list-wrapper:not([labels]), tui-data-list-wrapper:not([labels])[new]", inputs: ["items", "disabledItemHandler", "emptyContent", "size", "itemContent"], outputs: ["itemClick"] }, { kind: "component", type: TuiError, selector: "tui-error", inputs: ["error"] }, { kind: "component", type: i1$2.TuiTextfieldComponent, selector: "tui-textfield:not([multi])" }, { kind: "directive", type: i1$2.TuiTextfieldDirective, selector: "input[tuiTextfield]:not([tuiInputCard]):not([tuiInputExpire]):not([tuiInputCVC])" }, { kind: "directive", type: i1$2.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }, { kind: "directive", type: i1$2.TuiTextfieldDropdownDirective, selector: "ng-template[tuiTextfieldDropdown]" }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "directive", type: i2$1.TuiSelectDirective, selector: "input[tuiSelect]" }, { kind: "directive", type: i2$1.TuiInputNumberDirective, selector: "input[tuiInputNumber]", inputs: ["min", "max", "prefix", "postfix"] }, { kind: "directive", type: TuiNumberFormat, selector: "[tuiNumberFormat]", inputs: ["tuiNumberFormat"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: TuiFieldErrorPipe, name: "tuiFieldError" }, { kind: "component", type: i5$2.TuiSliderComponent, selector: "input[type=range][tuiSlider]", inputs: ["size", "segments"] }, { kind: "directive", type: i2$1.TuiInputSliderDirective, selector: "input[tuiInputSlider]" }, { kind: "directive", type: ScSelectOnFocusinDirective, selector: "tui-input-number, tui-input, tui-input-phone, tui-input-date, tui-input-password, input[tuiInputNumber], input[tuiTextfield], input[tuiInputSlider]" }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "showLoader"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6073
6151
|
}
|
|
6074
6152
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSandwichComponent, decorators: [{
|
|
6075
6153
|
type: Component,
|
|
@@ -6101,7 +6179,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
6101
6179
|
stringify: signal((x) => x.name),
|
|
6102
6180
|
identityMatcher: signal((a, b) => a.id === b.id),
|
|
6103
6181
|
}),
|
|
6104
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!orderItem() && settings()?.allowShowTable) {\n <div class=\"mb-5 flex justify-center\">\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"toggleShowEvent.emit()\"\n type=\"button\"\n iconStart=\"@tui.layout-list\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0432 \u0432\u0438\u0434\u0435 \u0441\u043F\u0438\u0441\u043A\u0430\n </button>\n </div>\n}\n<div class=\"\">\n @let calculateResult = calculateResult$ | async;\n @let products = products$ | async;\n @let productValue = product.value;\n @let validatorWidth = validatorWidth$ | async;\n @let validatorLength = validatorLength$ | async;\n\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit(calculateResult)\"\n ScNextInputFocus\n class=\"flex flex-col gap-3\"\n >\n <label\n tuiLabel\n class=\"grow\"\n >\n \u0422\u043E\u0432\u0430\u0440\n <tui-textfield\n tuiChevron\n [tuiTextfieldCleaner]=\"false\"\n >\n <input\n tuiChevron\n tuiSelect\n [formControl]=\"product\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\"\n />\n\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n @if (productValue) {\n <div class=\"ml-2 text-tui-text-secondary\">\n \u0421\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C:\n <span class=\"font-bold\">{{ productValue.costRub?.toLocaleString() }} {{ productValue.currency.symbol }}/\u0448\u0442.</span>\n </div>\n }\n <tui-error\n [formControl]=\"product\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (product.value && validatorWidth && validatorLength) {\n <p class=\"w-full font-bold\">\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439</p>\n <p class=\"w-full\">\n \u041C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0448\u0438\u0440\u0438\u043D\u0430: {{ settings()?.minWidth }} \u043C\u043C.\n <br />\n \u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0448\u0438\u0440\u0438\u043D\u0430: {{ product.value.properties?.width }} \u043C\u043C.\n <br />\n \u041C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0434\u043B\u0438\u043D\u0430: {{ settings()?.minLength }} \u043C\u043C.\n <br />\n \u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0434\u043B\u0438\u043D\u0430: {{ product.value.properties?.length }} \u043C\u043C.\n <br />\n </p>\n <div\n formArrayName=\"items\"\n class=\"flex flex-col gap-3\"\n >\n @for (item of items.controls; track item) {\n <div\n class=\"flex grow gap-2\"\n [formGroupName]=\"$index\"\n >\n <div class=\"grid grow grid-cols-3 gap-2\">\n <label tuiLabel>\n \u0428\u0438\u0440\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"width\"\n [min]=\"settings()?.minWidth ?? 0\"\n [max]=\"product.value.properties?.width ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n placeholder=\"\u0428\u0438\u0440\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n @if (product.value) {\n <div class=\"slider-ticks-labels\">\n <span> 0 </span>\n <span>{{ product.value.properties?.width }}</span>\n </div>\n }\n <tui-error\n formControlName=\"width\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u0414\u043B\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"length\"\n [min]=\"settings()?.minLength ?? 0\"\n [max]=\"product.value.properties?.length ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n placeholder=\"\u0414\u043B\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n @if (product.value) {\n <div class=\"slider-ticks-labels\">\n <span> 0 </span>\n <span>{{ product.value.properties?.length }}</span>\n </div>\n }\n <tui-error\n formControlName=\"length\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n <label tuiLabel>\n <span class=\"whitespace-nowrap\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442</span>\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n tuiInputNumber\n formControlName=\"count\"\n [min]=\"1\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"count\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n <button\n tuiIconButton\n (click)=\"removeItem($index)\"\n [disabled]=\"items.length <= 1\"\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.trash-2\"\n appearance=\"secondary\"\n class=\"mt-6\"\n [style.flex]=\"'0 0 auto'\"\n ></button>\n </div>\n }\n </div>\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\n class=\"self-center\"\n iconStart=\"@tui.plus\"\n >\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\n </button>\n } @else if (product.value) {\n <tui-error error=\"\u0420\u0430\u0441\u0447\u0435\u0442 \u043F\u043E \u043F\u0440\u043E\u0434\u0443\u043A\u0442\u0443 \u043D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u0435\u043D. \u041E\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044C \u043A \u043C\u0435\u043D\u0435\u0434\u0436\u0435\u0440\u0443\" />\n }\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 \u0440\u0430\u0441\u043F\u0438\u043B\u0430\n <tui-textfield>\n <input\n tuiTextfield\n formControlName=\"marker\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 \u0440\u0430\u0441\u043F\u0438\u043B\u0430\"\n autocomplete=\"marker\"\n />\n </tui-textfield>\n\n <tui-error\n formControlName=\"marker\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (product.value) {\n <tui-loader [showLoader]=\"isCalculateLoading()\">\n @if (calculateResult) {\n <div class=\"mt-2 flex flex-wrap items-end gap-2\">\n <div>\n \u0418\u0442\u043E\u0433\u043E: <span class=\"whitespace-nowrap text-xl font-bold\">{{ getTotalCost(calculateResult).toLocaleString() }} {{ product.value.currency.symbol }}</span>\n </div>\n @if (calculateResult?.quantity && productValue) {\n <div class=\"whitespace-nowrap text-lg text-sc-dark-grey\">\n <span class=\"font-bold\">({{ calculateResult.quantity }} \u0448\u0442.</span> x\n <span class=\"font-bold\">{{ productValue.costRub?.toLocaleString() }} {{ productValue.currency.symbol }}/\u0448\u0442.)</span>\n </div>\n }\n </div>\n }\n </tui-loader>\n }\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n @if (!calculateResult) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"items.invalid || isCalculateLoading()\"\n (click)=\"triggerCalculate()\"\n type=\"button\"\n class=\"self-center\"\n iconStart=\"@tui.calculator\"\n >\n \u0420\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u0442\u044C\n </button>\n } @else {\n <button\n [disabled]=\"form.invalid || isSubmitLoading()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"self-center\"\n iconStart=\"@tui.check\"\n >\n {{ !orderItem() ? '\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0432 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' : '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' }}\n </button>\n }\n </form>\n</div>\n", styles: [":host{display:block;width:100%;max-width:30rem}.slider-ticks-labels{--t-offset: calc($thumb / 2);display:flex;font:var(--tui-font-text-s);margin-inline-start:var(--t-offset);margin-inline-end:var(--t-offset);color:var(--tui-text-secondary)}.slider-ticks-labels>*{position:relative;flex:2;text-align:center}.slider-ticks-labels>*:first-child{left:calc(-1 * var(--t-offset));inset-inline-start:calc(-1 * var(--t-offset));flex:1;text-align:start}.slider-ticks-labels>*:last-child{right:calc(-1 * var(--t-offset));flex:1;text-align:end}@supports (inset-inline-end: 0){.slider-ticks-labels>*:last-child{right:unset;inset-inline-end:calc(-1 * var(--t-offset))}}tui-input-slider+.slider-ticks-labels{margin-inline-start:calc(var(--tui-radius-m) / 2 + var(--t-offset))}tui-textfield+.slider-ticks-labels{--t-offset: calc(var(--tui-radius-m) / 2 + $thumb / 2)}tui-textfield[data-size=l]+.slider-ticks-labels{--t-offset: calc(var(--tui-radius-l) / 2 + $thumb / 2)}tui-input-range:not([new])+.slider-ticks-labels,tui-range+.slider-ticks-labels{--t-offset: $thumb}tui-input-range[new]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, $input-size) + $thumb)}\n"] }]
|
|
6182
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!orderItem() && settings()?.allowShowTable) {\n <div class=\"mb-5 flex justify-center\">\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"toggleShowEvent.emit()\"\n type=\"button\"\n iconStart=\"@tui.layout-list\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0432 \u0432\u0438\u0434\u0435 \u0441\u043F\u0438\u0441\u043A\u0430\n </button>\n </div>\n}\n<div>\n @let calculateResult = calculateResult$ | async;\n @let products = products$ | async;\n @let productValue = product.value;\n @let validatorWidth = validatorWidth$ | async;\n @let validatorLength = validatorLength$ | async;\n\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit(calculateResult)\"\n ScNextInputFocus\n class=\"flex flex-col gap-3\"\n >\n <label\n tuiLabel\n class=\"grow\"\n >\n \u0422\u043E\u0432\u0430\u0440\n <tui-textfield\n tuiChevron\n [tuiTextfieldCleaner]=\"false\"\n >\n <input\n tuiChevron\n tuiSelect\n [formControl]=\"product\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\"\n />\n\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error\n [formControl]=\"product\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (productValue && productValue.costRub) {\n <div class=\"-mt-1 text-sm text-tui-text-secondary\">\n <span class=\"font-bold\">{{ productValue.code }}</span>\n \u2014 {{ productValue.costRub.toLocaleString() }} {{ productValue.currency.symbol }}/\u0448\u0442.\n </div>\n }\n\n @if (product.value && validatorWidth && validatorLength) {\n <div class=\"mt-4 flex flex-col gap-1.5\">\n <div class=\"w-full font-bold\">\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439</div>\n <div class=\"flex flex-col gap-1 text-sm text-tui-text-secondary\">\n @if (widthRangeText()) {\n <div>\u0428\u0438\u0440\u0438\u043D\u0430 {{ widthRangeText() }}.</div>\n }\n @if (lengthRangeText()) {\n <div>\u0414\u043B\u0438\u043D\u0430 {{ lengthRangeText() }}.</div>\n }\n </div>\n </div>\n } @else if (product.value) {\n <tui-error error=\"\u0420\u0430\u0441\u0447\u0435\u0442 \u043F\u043E \u043F\u0440\u043E\u0434\u0443\u043A\u0442\u0443 \u043D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u0435\u043D. \u041E\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044C \u043A \u043C\u0435\u043D\u0435\u0434\u0436\u0435\u0440\u0443\" />\n }\n\n <div\n formArrayName=\"items\"\n class=\"flex flex-col gap-3\"\n >\n @for (item of items.controls; track item) {\n <div\n class=\"flex grow gap-2\"\n [formGroupName]=\"$index\"\n >\n <div class=\"grid grow grid-cols-1 items-start gap-2 sm:grid-cols-3\">\n <label tuiLabel>\n \u0428\u0438\u0440\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"width\"\n [min]=\"settings()?.minWidth ?? 0\"\n [max]=\"product.value?.properties?.width ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value\"\n placeholder=\"\u0428\u0438\u0440\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n @if (product.value) {\n <div class=\"slider-ticks-labels\">\n <span> 0 </span>\n <span>{{ product.value.properties?.width }}</span>\n </div>\n }\n <tui-error\n formControlName=\"width\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u0414\u043B\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"length\"\n [min]=\"settings()?.minLength ?? 0\"\n [max]=\"product.value?.properties?.length ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value\"\n placeholder=\"\u0414\u043B\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n @if (product.value) {\n <div class=\"slider-ticks-labels\">\n <span> 0 </span>\n <span>{{ product.value.properties?.length }}</span>\n </div>\n }\n <tui-error\n formControlName=\"length\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n <label tuiLabel>\n <span class=\"whitespace-nowrap\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442</span>\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n tuiInputNumber\n formControlName=\"count\"\n [min]=\"1\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value\"\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"count\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n <button\n tuiIconButton\n (click)=\"removeItem($index)\"\n [disabled]=\"!product.value || items.length <= 1\"\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.trash-2\"\n appearance=\"secondary\"\n class=\"mt-6\"\n [style.flex]=\"'0 0 auto'\"\n ></button>\n </div>\n }\n </div>\n @if (product.value) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\n class=\"self-center\"\n iconStart=\"@tui.plus\"\n >\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\n </button>\n }\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 \u0440\u0430\u0441\u043F\u0438\u043B\u0430\n <tui-textfield>\n <input\n tuiTextfield\n formControlName=\"marker\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 \u0440\u0430\u0441\u043F\u0438\u043B\u0430\"\n autocomplete=\"marker\"\n />\n </tui-textfield>\n\n <tui-error\n formControlName=\"marker\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (product.value) {\n <tui-loader [showLoader]=\"isCalculateLoading()\">\n @if (calculateResult) {\n <div class=\"mt-2 flex flex-wrap items-end gap-2\">\n <div>\n \u0418\u0442\u043E\u0433\u043E: <span class=\"whitespace-nowrap text-xl font-bold\">{{ getTotalCost(calculateResult).toLocaleString() }} {{ product.value.currency.symbol }}</span>\n </div>\n @if (calculateResult?.quantity && productValue) {\n <div class=\"whitespace-nowrap text-lg text-sc-dark-grey\">\n <span class=\"font-bold\">({{ calculateResult.quantity }} \u0448\u0442.</span> x\n <span class=\"font-bold\">{{ productValue.costRub?.toLocaleString() }} {{ productValue.currency.symbol }}/\u0448\u0442.)</span>\n </div>\n }\n </div>\n }\n </tui-loader>\n }\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n @if (!calculateResult) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"items.invalid || isCalculateLoading()\"\n (click)=\"triggerCalculate()\"\n type=\"button\"\n class=\"self-center\"\n iconStart=\"@tui.calculator\"\n >\n \u0420\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u0442\u044C\n </button>\n } @else {\n <button\n [disabled]=\"form.invalid || isSubmitLoading()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"self-center\"\n iconStart=\"@tui.check\"\n >\n {{ !orderItem() ? '\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0432 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' : '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' }}\n </button>\n }\n </form>\n</div>\n", styles: [":host{display:block;width:100%;max-width:30rem}.slider-ticks-labels{--t-offset: calc($thumb / 2);display:flex;font:var(--tui-font-text-s);margin-inline-start:var(--t-offset);margin-inline-end:var(--t-offset);color:var(--tui-text-secondary)}.slider-ticks-labels>*{position:relative;flex:2;text-align:center}.slider-ticks-labels>*:first-child{left:calc(-1 * var(--t-offset));inset-inline-start:calc(-1 * var(--t-offset));flex:1;text-align:start}.slider-ticks-labels>*:last-child{right:calc(-1 * var(--t-offset));flex:1;text-align:end}@supports (inset-inline-end: 0){.slider-ticks-labels>*:last-child{right:unset;inset-inline-end:calc(-1 * var(--t-offset))}}tui-input-slider+.slider-ticks-labels{margin-inline-start:calc(var(--tui-radius-m) / 2 + var(--t-offset))}tui-textfield+.slider-ticks-labels{--t-offset: calc(var(--tui-radius-m) / 2 + $thumb / 2)}tui-textfield[data-size=l]+.slider-ticks-labels{--t-offset: calc(var(--tui-radius-l) / 2 + $thumb / 2)}tui-input-range:not([new])+.slider-ticks-labels,tui-range+.slider-ticks-labels{--t-offset: $thumb}tui-input-range[new]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, $input-size) + $thumb)}\n"] }]
|
|
6105
6183
|
}], propDecorators: { orderId: [{
|
|
6106
6184
|
type: Input
|
|
6107
6185
|
}] } });
|
|
@@ -6118,6 +6196,563 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
6118
6196
|
args: [{ standalone: true, selector: 'sc-sandwich-skeleton', template: "<div class=\"w-100\">\n <div class=\"flex flex-col gap-3\">\n <!-- \u041F\u043E\u043B\u0435 \u0432\u044B\u0431\u043E\u0440\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n\n <!-- \u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \"\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439\". -->\n <div class=\"my-1.5 h-5 w-1/3 rounded bg-sc-light-grey\"></div>\n\n <!-- \u0422\u0435\u043A\u0441\u0442 \u0441 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0430\u043C\u0438. -->\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-2/3 rounded bg-sc-light-grey\"></div>\n <div class=\"my-1 h-3 w-2/3 rounded bg-sc-light-grey\"></div>\n <div class=\"my-1 h-3 w-2/3 rounded bg-sc-light-grey\"></div>\n <div class=\"my-1 h-3 w-2/3 rounded bg-sc-light-grey\"></div>\n </div>\n\n <!-- \u0411\u043B\u043E\u043A \u0441 \u0438\u0437\u0434\u0435\u043B\u0438\u044F\u043C\u0438. -->\n <div class=\"flex flex-col gap-3\">\n <!-- \u041F\u0435\u0440\u0432\u043E\u0435 \u0438\u0437\u0434\u0435\u043B\u0438\u0435. -->\n <div class=\"flex grow gap-4\">\n <div class=\"grid grow grid-cols-3 gap-4\">\n <!-- \u0428\u0438\u0440\u0438\u043D\u0430. -->\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-1/2 rounded bg-sc-light-grey\"></div>\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n <div class=\"my-1 h-3 w-1/3 rounded bg-sc-light-grey\"></div>\n <div class=\"my-1 h-2 w-2/3 rounded bg-sc-light-grey\"></div>\n </div>\n <!-- \u0414\u043B\u0438\u043D\u0430. -->\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-1/2 rounded bg-sc-light-grey\"></div>\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n <div class=\"my-1 h-3 w-1/3 rounded bg-sc-light-grey\"></div>\n <div class=\"my-1 h-2 w-2/3 rounded bg-sc-light-grey\"></div>\n </div>\n <!-- \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E. -->\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-1/2 rounded bg-sc-light-grey\"></div>\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n </div>\n </div>\n <div class=\"mt-6 size-8 shrink-0 rounded-sm bg-sc-light-grey\"></div>\n </div>\n </div>\n\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \"\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\". -->\n <button\n tuiButton\n appearance=\"secondary\"\n class=\"sc-skeleton self-center\"\n ></button>\n\n <!-- \u041F\u043E\u043B\u0435 \"\u0418\u0442\u043E\u0433\u043E\u0432\u043E\u0435 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u043B\u0438\u0441\u0442\u043E\u0432\". -->\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n\n <!-- \u041F\u043E\u043B\u0435 \"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\". -->\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n\n <!-- \u0418\u0442\u043E\u0433\u043E\u0432\u0430\u044F \u0441\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C. -->\n <div class=\"my-2.5 h-6 w-1/3 rounded bg-sc-light-grey\"></div>\n\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0438. -->\n <button\n tuiButton\n class=\"sc-skeleton self-center\"\n ></button>\n </div>\n</div>\n" }]
|
|
6119
6197
|
}] });
|
|
6120
6198
|
|
|
6199
|
+
/**
|
|
6200
|
+
* Начальное состояние позиции — используется при инициализации и сбросе формы.
|
|
6201
|
+
*/
|
|
6202
|
+
const IDLE_ITEM_STATE = 'idle';
|
|
6203
|
+
|
|
6204
|
+
/* eslint-disable security/detect-object-injection,@typescript-eslint/unbound-method */
|
|
6205
|
+
/**
|
|
6206
|
+
* Конфигуратор распила сэндвич-панелей по площади.
|
|
6207
|
+
*/
|
|
6208
|
+
class ScSandwichM2Component {
|
|
6209
|
+
constructor() {
|
|
6210
|
+
/**
|
|
6211
|
+
* Настройки для конфигуратора распила сэндвич-панелей по площади.
|
|
6212
|
+
*/
|
|
6213
|
+
this.settings = input();
|
|
6214
|
+
/**
|
|
6215
|
+
* Идентификатор категории.
|
|
6216
|
+
*/
|
|
6217
|
+
this.categoryId = input.required();
|
|
6218
|
+
/**
|
|
6219
|
+
* Название конфигуратора.
|
|
6220
|
+
*/
|
|
6221
|
+
this.editor = input.required();
|
|
6222
|
+
/**
|
|
6223
|
+
* Позиция товара/услуги в корзине.
|
|
6224
|
+
*/
|
|
6225
|
+
this.orderItem = input.required();
|
|
6226
|
+
/**
|
|
6227
|
+
* Событие переключения отображения товаров.
|
|
6228
|
+
*/
|
|
6229
|
+
this.toggleShowEvent = output();
|
|
6230
|
+
/**
|
|
6231
|
+
* Форма добавления/редактирования продукта в корзине.
|
|
6232
|
+
*/
|
|
6233
|
+
this.form = new FormGroup({
|
|
6234
|
+
productCategoryId: new FormControl(null, { validators: Validators.required }),
|
|
6235
|
+
configurator: new FormControl(null, { validators: Validators.required }),
|
|
6236
|
+
items: new FormArray([]),
|
|
6237
|
+
});
|
|
6238
|
+
/**
|
|
6239
|
+
* Сервис получения и редактирования списка товаров заказа (корзина / заказ / черновик = заказ).
|
|
6240
|
+
*/
|
|
6241
|
+
this.orderService = inject(SC_ORDER_LOADER);
|
|
6242
|
+
/**
|
|
6243
|
+
* Сервис конвертации данных.
|
|
6244
|
+
*/
|
|
6245
|
+
this.convertersService = inject(ScConvertersService);
|
|
6246
|
+
/**
|
|
6247
|
+
* Контекст диалогового окна, в котором открыт компонент.
|
|
6248
|
+
*/
|
|
6249
|
+
this.context = inject(POLYMORPHEUS_CONTEXT, { optional: true });
|
|
6250
|
+
/**
|
|
6251
|
+
* Сервис для работы с каталогом.
|
|
6252
|
+
*/
|
|
6253
|
+
this.catalogService = inject(ScCatalogService);
|
|
6254
|
+
/**
|
|
6255
|
+
* {@link Observable} списка товаров категории.
|
|
6256
|
+
*/
|
|
6257
|
+
this.products$ = toObservable(this.categoryId).pipe(switchMap((categoryId) => {
|
|
6258
|
+
if (!categoryId) {
|
|
6259
|
+
return of([]);
|
|
6260
|
+
}
|
|
6261
|
+
return this.catalogService.getProductsCategoryCached$({ categoryId: Number(categoryId) }).pipe(map((products) => products ?? []));
|
|
6262
|
+
}));
|
|
6263
|
+
/**
|
|
6264
|
+
* Выбранный продукт.
|
|
6265
|
+
*/
|
|
6266
|
+
this.product = new FormControl(null, { validators: Validators.required });
|
|
6267
|
+
/**
|
|
6268
|
+
* Сигнал текущего выбранного продукта — обновляется при `valueChanges` контрола `product`.
|
|
6269
|
+
*/
|
|
6270
|
+
this.productSignal = toSignal(tuiControlValue(this.product), { initialValue: null });
|
|
6271
|
+
/**
|
|
6272
|
+
* Сигнал содержимого FormArray позиций — пересчитывается при любом изменении значений.
|
|
6273
|
+
*/
|
|
6274
|
+
this.itemsValue = toSignal(tuiControlValue(this.items).pipe(map(() => this.items.controls.map((c) => c.getRawValue()))), {
|
|
6275
|
+
initialValue: [],
|
|
6276
|
+
});
|
|
6277
|
+
/**
|
|
6278
|
+
* Признак того, что выполняется запрос на отправку данных.
|
|
6279
|
+
*/
|
|
6280
|
+
this.isSubmitLoading = computed(() => this.itemStates().includes('loading'));
|
|
6281
|
+
/**
|
|
6282
|
+
* Состояние отправки каждой позиции — параллельный массив к контролу `items` формы.
|
|
6283
|
+
*/
|
|
6284
|
+
this.itemStates = signal([]);
|
|
6285
|
+
/**
|
|
6286
|
+
* Признак режима редактирования существующей позиции — `orderItem` задан.
|
|
6287
|
+
*/
|
|
6288
|
+
this.isEditingExistingItem = computed(() => this.orderItem() != null);
|
|
6289
|
+
/**
|
|
6290
|
+
* Признак того, что отправлять больше нечего — все позиции либо успешно
|
|
6291
|
+
* отправлены, либо находятся в процессе отправки.
|
|
6292
|
+
*/
|
|
6293
|
+
this.hasNoPendingItems = computed(() => {
|
|
6294
|
+
const states = this.itemStates();
|
|
6295
|
+
if (this.items.length === 0) {
|
|
6296
|
+
return true;
|
|
6297
|
+
}
|
|
6298
|
+
return this.items.controls.every((_, index) => {
|
|
6299
|
+
const state = states[index] ?? IDLE_ITEM_STATE;
|
|
6300
|
+
return state === 'success' || state === 'loading';
|
|
6301
|
+
});
|
|
6302
|
+
});
|
|
6303
|
+
/**
|
|
6304
|
+
* Суммарная площадь всех позиций (м²), рассчитанная локально.
|
|
6305
|
+
*/
|
|
6306
|
+
this.totalAreaM2 = computed(() => {
|
|
6307
|
+
let total = 0;
|
|
6308
|
+
this.itemsValue().forEach((value) => {
|
|
6309
|
+
total += this.rowTotalPartsAreaM2(value);
|
|
6310
|
+
});
|
|
6311
|
+
return total;
|
|
6312
|
+
});
|
|
6313
|
+
/**
|
|
6314
|
+
* Итоговая стоимость по всем позициям (локальный расчёт).
|
|
6315
|
+
*/
|
|
6316
|
+
this.totalCost = computed(() => {
|
|
6317
|
+
const cost = this.productSignal()?.costRub ?? 0;
|
|
6318
|
+
const area = this.totalAreaM2();
|
|
6319
|
+
return Math.round(area * cost * 100) / 100;
|
|
6320
|
+
});
|
|
6321
|
+
/**
|
|
6322
|
+
* Текст ограничения по ширине («от … до …»), пока есть выбранный товар.
|
|
6323
|
+
*/
|
|
6324
|
+
this.widthRangeText = computed(() => this.formatRange(this.settings()?.minWidth ?? null, this.productSignal()?.properties?.width ?? null, 'мм'));
|
|
6325
|
+
/**
|
|
6326
|
+
* Текст ограничения по длине («от … до …»), пока есть выбранный товар.
|
|
6327
|
+
*/
|
|
6328
|
+
this.lengthRangeText = computed(() => this.formatRange(this.settings()?.minLength ?? null, this.productSignal()?.properties?.length ?? null, 'мм'));
|
|
6329
|
+
/**
|
|
6330
|
+
* Ссылка для автоматического управления уничтожением зависимостей.
|
|
6331
|
+
*/
|
|
6332
|
+
this.destroyRef = inject(DestroyRef);
|
|
6333
|
+
}
|
|
6334
|
+
/**
|
|
6335
|
+
* Валидаторы ширины/длины: пока товар не выбран — не накладываем min/max каталога (поля read-only без товара).
|
|
6336
|
+
*
|
|
6337
|
+
* @param min Нижняя граница размера из настроек конфигуратора.
|
|
6338
|
+
* @param maxUpper Верхняя граница из свойств выбранного товара.
|
|
6339
|
+
*/
|
|
6340
|
+
dimensionValidators(min, maxUpper) {
|
|
6341
|
+
const chosenProduct = this.product.value;
|
|
6342
|
+
if (!chosenProduct) {
|
|
6343
|
+
return [];
|
|
6344
|
+
}
|
|
6345
|
+
return [Validators.required, Validators.min(min), ...(maxUpper != null && maxUpper > 0 ? [Validators.max(maxUpper)] : []), stepValidator(1)];
|
|
6346
|
+
}
|
|
6347
|
+
/**
|
|
6348
|
+
* Обновляет валидаторы размерных полей после смены товара или настроек.
|
|
6349
|
+
*/
|
|
6350
|
+
updateItemsValidators() {
|
|
6351
|
+
const settings = this.settings();
|
|
6352
|
+
const minWidth = settings?.minWidth ?? 0.01;
|
|
6353
|
+
const minLength = settings?.minLength ?? 0.01;
|
|
6354
|
+
const chosenProduct = this.product.value;
|
|
6355
|
+
this.items.controls.forEach((group) => {
|
|
6356
|
+
group.get('width')?.setValidators(this.dimensionValidators(minWidth, chosenProduct?.properties?.width));
|
|
6357
|
+
group.get('length')?.setValidators(this.dimensionValidators(minLength, chosenProduct?.properties?.length));
|
|
6358
|
+
group.get('width')?.updateValueAndValidity({ emitEvent: false });
|
|
6359
|
+
group.get('length')?.updateValueAndValidity({ emitEvent: false });
|
|
6360
|
+
});
|
|
6361
|
+
}
|
|
6362
|
+
/**
|
|
6363
|
+
* Форматирование диапазона «от … до …» с учётом отсутствующих границ.
|
|
6364
|
+
*
|
|
6365
|
+
* @param min Нижняя граница диапазона.
|
|
6366
|
+
* @param max Верхняя граница диапазона.
|
|
6367
|
+
* @param unit Единица измерения для подписи.
|
|
6368
|
+
*/
|
|
6369
|
+
// eslint-disable-next-line class-methods-use-this
|
|
6370
|
+
formatRange(min, max, unit) {
|
|
6371
|
+
const hasMin = min != null && min > 0;
|
|
6372
|
+
const hasMax = max != null && max > 0;
|
|
6373
|
+
if (!hasMin && !hasMax) {
|
|
6374
|
+
return null;
|
|
6375
|
+
}
|
|
6376
|
+
if (hasMin && hasMax) {
|
|
6377
|
+
return `от ${min} ${unit} до ${max} ${unit}`;
|
|
6378
|
+
}
|
|
6379
|
+
if (hasMin) {
|
|
6380
|
+
return `от ${min} ${unit}`;
|
|
6381
|
+
}
|
|
6382
|
+
return `до ${max} ${unit}`;
|
|
6383
|
+
}
|
|
6384
|
+
/**
|
|
6385
|
+
* Массив изделий.
|
|
6386
|
+
*/
|
|
6387
|
+
get items() {
|
|
6388
|
+
return this.form.controls.items;
|
|
6389
|
+
}
|
|
6390
|
+
/**
|
|
6391
|
+
* {@inheritDoc}
|
|
6392
|
+
*/
|
|
6393
|
+
ngOnInit() {
|
|
6394
|
+
this.setDefaultFormValue();
|
|
6395
|
+
this.products$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((products) => {
|
|
6396
|
+
if (this.product.value != null || products.length === 0) {
|
|
6397
|
+
return;
|
|
6398
|
+
}
|
|
6399
|
+
/* При загрузке списка автоматически выбираем первый материал. */
|
|
6400
|
+
this.product.setValue(products[0], { emitEvent: true });
|
|
6401
|
+
});
|
|
6402
|
+
this.product.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((chosenProduct) => {
|
|
6403
|
+
this.updateItemsValidators();
|
|
6404
|
+
if (chosenProduct) {
|
|
6405
|
+
this.items.controls.forEach((item) => {
|
|
6406
|
+
const value = item.getRawValue();
|
|
6407
|
+
const maxW = chosenProduct.properties?.width;
|
|
6408
|
+
const maxL = chosenProduct.properties?.length;
|
|
6409
|
+
item.patchValue({
|
|
6410
|
+
width: maxW ? Math.min(value.width, maxW) : value.width,
|
|
6411
|
+
length: maxL ? Math.min(value.length, maxL) : value.length,
|
|
6412
|
+
});
|
|
6413
|
+
});
|
|
6414
|
+
/*
|
|
6415
|
+
* Смена продукта — сбрасываем состояние позиций: границы каталога изменились,
|
|
6416
|
+
* успешная отправка больше не отражает текущее состояние.
|
|
6417
|
+
*/
|
|
6418
|
+
this.resetAllItemStates();
|
|
6419
|
+
}
|
|
6420
|
+
});
|
|
6421
|
+
}
|
|
6422
|
+
/**
|
|
6423
|
+
* Создает группу для изделия.
|
|
6424
|
+
*
|
|
6425
|
+
* @param item Параметры изделия.
|
|
6426
|
+
* @param item.width Ширина изделия.
|
|
6427
|
+
* @param item.length Длина изделия.
|
|
6428
|
+
* @param item.count Количество изделий.
|
|
6429
|
+
* @param item.marker Маркер позиции.
|
|
6430
|
+
*/
|
|
6431
|
+
createItemGroup(item) {
|
|
6432
|
+
const group = new FormGroup({
|
|
6433
|
+
width: new FormControl(item?.width ?? 0, { nonNullable: true }),
|
|
6434
|
+
length: new FormControl(item?.length ?? 0, { nonNullable: true }),
|
|
6435
|
+
count: new FormControl(item?.count ?? 1, {
|
|
6436
|
+
validators: [Validators.required, Validators.min(1), stepValidator(1)],
|
|
6437
|
+
nonNullable: true,
|
|
6438
|
+
}),
|
|
6439
|
+
marker: new FormControl(item?.marker ?? null),
|
|
6440
|
+
});
|
|
6441
|
+
// Любое изменение значений позиции сбрасывает её состояние отправки —
|
|
6442
|
+
// ранее успешный submit становится неактуальным при правке полей,
|
|
6443
|
+
// ошибку валидации сервера тоже сбрасываем.
|
|
6444
|
+
group.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
|
|
6445
|
+
const index = this.items.controls.indexOf(group);
|
|
6446
|
+
if (index !== -1) {
|
|
6447
|
+
this.resetItemState(index);
|
|
6448
|
+
['width', 'length', 'count', 'marker'].forEach((field) => {
|
|
6449
|
+
const control = group.get(field);
|
|
6450
|
+
if (control?.hasError('serverResponse')) {
|
|
6451
|
+
const errors = { ...control.errors };
|
|
6452
|
+
delete errors['serverResponse'];
|
|
6453
|
+
control.setErrors(Object.keys(errors).length > 0 ? errors : null);
|
|
6454
|
+
}
|
|
6455
|
+
});
|
|
6456
|
+
}
|
|
6457
|
+
});
|
|
6458
|
+
return group;
|
|
6459
|
+
}
|
|
6460
|
+
/**
|
|
6461
|
+
* Сбрасывает состояние одной позиции на `idle`, если оно было `success`/`error`.
|
|
6462
|
+
*
|
|
6463
|
+
* @param index Индекс позиции.
|
|
6464
|
+
*/
|
|
6465
|
+
resetItemState(index) {
|
|
6466
|
+
const states = this.itemStates();
|
|
6467
|
+
const current = states[index];
|
|
6468
|
+
if (current === 'success' || current === 'error') {
|
|
6469
|
+
const updated = [...states];
|
|
6470
|
+
updated[index] = 'idle';
|
|
6471
|
+
this.itemStates.set(updated);
|
|
6472
|
+
}
|
|
6473
|
+
}
|
|
6474
|
+
/**
|
|
6475
|
+
* Сбрасывает состояния всех позиций на `idle`.
|
|
6476
|
+
*/
|
|
6477
|
+
resetAllItemStates() {
|
|
6478
|
+
this.itemStates.set(this.items.controls.map(() => IDLE_ITEM_STATE));
|
|
6479
|
+
}
|
|
6480
|
+
/**
|
|
6481
|
+
* Возвращает состояние позиции по индексу (по умолчанию `idle`).
|
|
6482
|
+
*
|
|
6483
|
+
* @param index Индекс позиции.
|
|
6484
|
+
*/
|
|
6485
|
+
getItemState(index) {
|
|
6486
|
+
return this.itemStates()[index] ?? IDLE_ITEM_STATE;
|
|
6487
|
+
}
|
|
6488
|
+
/**
|
|
6489
|
+
* Признак того, что позиция отправляется (поля должны быть заблокированы).
|
|
6490
|
+
*
|
|
6491
|
+
* @param index Индекс позиции.
|
|
6492
|
+
*/
|
|
6493
|
+
isItemLoading(index) {
|
|
6494
|
+
return this.getItemState(index) === 'loading';
|
|
6495
|
+
}
|
|
6496
|
+
/**
|
|
6497
|
+
* Признак того, что позиция успешно отправлена и её поля нужно заблокировать.
|
|
6498
|
+
*
|
|
6499
|
+
* @param index Индекс позиции.
|
|
6500
|
+
*/
|
|
6501
|
+
isItemLocked(index) {
|
|
6502
|
+
return this.getItemState(index) === 'success';
|
|
6503
|
+
}
|
|
6504
|
+
/**
|
|
6505
|
+
* Добавляет новое изделие в форму.
|
|
6506
|
+
*/
|
|
6507
|
+
addItem() {
|
|
6508
|
+
this.items.push(this.createItemGroup());
|
|
6509
|
+
this.itemStates.update((states) => [...states, 'idle']);
|
|
6510
|
+
this.updateItemsValidators();
|
|
6511
|
+
}
|
|
6512
|
+
/**
|
|
6513
|
+
* Удаляет изделие из формы.
|
|
6514
|
+
*
|
|
6515
|
+
* @param index Индекс изделия.
|
|
6516
|
+
*/
|
|
6517
|
+
removeItem(index) {
|
|
6518
|
+
this.items.removeAt(index);
|
|
6519
|
+
this.itemStates.update((states) => {
|
|
6520
|
+
const updated = [...states];
|
|
6521
|
+
updated.splice(index, 1);
|
|
6522
|
+
return updated;
|
|
6523
|
+
});
|
|
6524
|
+
this.updateItemsValidators();
|
|
6525
|
+
}
|
|
6526
|
+
/**
|
|
6527
|
+
* Площадь одной единицы изделия без учёта количества, м².
|
|
6528
|
+
*
|
|
6529
|
+
* @param value Значения размеров изделия.
|
|
6530
|
+
* @param value.width Ширина изделия.
|
|
6531
|
+
* @param value.length Длина изделия.
|
|
6532
|
+
*/
|
|
6533
|
+
// eslint-disable-next-line class-methods-use-this
|
|
6534
|
+
pieceAreaM2(value) {
|
|
6535
|
+
const { width, length } = value;
|
|
6536
|
+
if (!width || !length) {
|
|
6537
|
+
return 0;
|
|
6538
|
+
}
|
|
6539
|
+
return (width * length) / 1_000_000;
|
|
6540
|
+
}
|
|
6541
|
+
/**
|
|
6542
|
+
* Суммарная площадь по строке позиции: площадь единицы × количество, м².
|
|
6543
|
+
*
|
|
6544
|
+
* @param value Значения позиции.
|
|
6545
|
+
* @param value.width Ширина изделия.
|
|
6546
|
+
* @param value.length Длина изделия.
|
|
6547
|
+
* @param value.count Количество изделий.
|
|
6548
|
+
*/
|
|
6549
|
+
rowTotalPartsAreaM2(value) {
|
|
6550
|
+
const qty = value.count;
|
|
6551
|
+
if (!qty || !value.width || value.length === 0) {
|
|
6552
|
+
return 0;
|
|
6553
|
+
}
|
|
6554
|
+
return this.pieceAreaM2(value) * qty;
|
|
6555
|
+
}
|
|
6556
|
+
/**
|
|
6557
|
+
* Возвращает приблизительную стоимость строки (локальный расчёт — на всю строку позиции).
|
|
6558
|
+
*
|
|
6559
|
+
* @param value Значения изделия.
|
|
6560
|
+
* @param value.width Ширина изделия.
|
|
6561
|
+
* @param value.length Длина изделия.
|
|
6562
|
+
* @param value.count Количество изделий.
|
|
6563
|
+
*/
|
|
6564
|
+
rowCost(value) {
|
|
6565
|
+
const area = this.rowTotalPartsAreaM2(value);
|
|
6566
|
+
const cost = this.product.value?.costRub ?? 0;
|
|
6567
|
+
return Math.round(area * cost * 100) / 100;
|
|
6568
|
+
}
|
|
6569
|
+
/**
|
|
6570
|
+
* Обновляет состояние позиции на указанное значение.
|
|
6571
|
+
*
|
|
6572
|
+
* @param index Индекс позиции.
|
|
6573
|
+
* @param state Новое состояние.
|
|
6574
|
+
*/
|
|
6575
|
+
setItemState(index, state) {
|
|
6576
|
+
this.itemStates.update((states) => {
|
|
6577
|
+
const updated = [...states];
|
|
6578
|
+
updated[index] = state;
|
|
6579
|
+
return updated;
|
|
6580
|
+
});
|
|
6581
|
+
}
|
|
6582
|
+
/**
|
|
6583
|
+
* Применяет ошибки серверной валидации к контролам формы.
|
|
6584
|
+
* Сервер возвращает ключи вида `items.0.<field>` — переводим в фактический индекс позиции.
|
|
6585
|
+
*
|
|
6586
|
+
* @param error Ответ сервера.
|
|
6587
|
+
* @param index Индекс позиции в форме.
|
|
6588
|
+
*/
|
|
6589
|
+
applyServerValidationErrors(error, index) {
|
|
6590
|
+
if (!(error instanceof HttpErrorResponse)) {
|
|
6591
|
+
return;
|
|
6592
|
+
}
|
|
6593
|
+
const { errors, message } = error.error;
|
|
6594
|
+
if (errors) {
|
|
6595
|
+
Object.keys(errors).forEach((key) => {
|
|
6596
|
+
this.form.get(['items', index, key])?.setErrors({ serverResponse: errors[key] });
|
|
6597
|
+
});
|
|
6598
|
+
}
|
|
6599
|
+
else if (message) {
|
|
6600
|
+
this.form.setErrors({ serverResponse: [message] });
|
|
6601
|
+
}
|
|
6602
|
+
}
|
|
6603
|
+
/**
|
|
6604
|
+
* Обработчик добавления/редактирования продукта в корзине.
|
|
6605
|
+
*/
|
|
6606
|
+
onSubmit() {
|
|
6607
|
+
if (this.form.invalid || !this.product.value) {
|
|
6608
|
+
return;
|
|
6609
|
+
}
|
|
6610
|
+
const productId = this.product.value.id;
|
|
6611
|
+
const productCategoryId = Number(this.categoryId());
|
|
6612
|
+
const configurator = this.editor();
|
|
6613
|
+
const orderData = this.orderItem();
|
|
6614
|
+
const indexesToSubmit = this.items.controls
|
|
6615
|
+
.map((_, index) => index)
|
|
6616
|
+
.filter((index) => {
|
|
6617
|
+
const state = this.getItemState(index);
|
|
6618
|
+
return state !== 'success' && state !== 'loading';
|
|
6619
|
+
});
|
|
6620
|
+
if (indexesToSubmit.length === 0) {
|
|
6621
|
+
return;
|
|
6622
|
+
}
|
|
6623
|
+
// Позиции отправляются последовательно: каждая следующая — только после ответа предыдущей.
|
|
6624
|
+
// При ошибке цепочка прерывается; диалог не закрывается.
|
|
6625
|
+
from(indexesToSubmit)
|
|
6626
|
+
.pipe(concatMap((index, position) => {
|
|
6627
|
+
// Editing-режим: первая позиция (index 0) обновляется, остальные добавляются.
|
|
6628
|
+
const isEdit = orderData != null && index === 0 && position === 0;
|
|
6629
|
+
this.setItemState(index, 'loading');
|
|
6630
|
+
return this.buildItemRequest$(index, productId, productCategoryId, configurator, isEdit, orderData).pipe(tap(() => {
|
|
6631
|
+
this.setItemState(index, 'success');
|
|
6632
|
+
}), catchError((error) => {
|
|
6633
|
+
this.applyServerValidationErrors(error, index);
|
|
6634
|
+
this.setItemState(index, 'error');
|
|
6635
|
+
return throwError(() => error);
|
|
6636
|
+
}));
|
|
6637
|
+
}), takeUntilDestroyed(this.destroyRef))
|
|
6638
|
+
.subscribe({
|
|
6639
|
+
complete: () => {
|
|
6640
|
+
if (this.context) {
|
|
6641
|
+
this.context.$implicit.complete();
|
|
6642
|
+
}
|
|
6643
|
+
else {
|
|
6644
|
+
this.setDefaultFormValue();
|
|
6645
|
+
}
|
|
6646
|
+
},
|
|
6647
|
+
});
|
|
6648
|
+
}
|
|
6649
|
+
/**
|
|
6650
|
+
* Формирует HTTP-запрос для одной позиции формы.
|
|
6651
|
+
*
|
|
6652
|
+
* @param index Индекс позиции в форме.
|
|
6653
|
+
* @param productId Идентификатор выбранного продукта.
|
|
6654
|
+
* @param productCategoryId Идентификатор категории.
|
|
6655
|
+
* @param configurator Название конфигуратора.
|
|
6656
|
+
* @param isEdit Режим обновления существующей позиции.
|
|
6657
|
+
* @param orderData Текущая позиция заказа (только в режиме редактирования).
|
|
6658
|
+
*/
|
|
6659
|
+
buildItemRequest$(index, productId, productCategoryId, configurator, isEdit, orderData) {
|
|
6660
|
+
const itemValue = this.items.at(index).getRawValue();
|
|
6661
|
+
const payload = this.convertersService.removeNull({
|
|
6662
|
+
productCategoryId,
|
|
6663
|
+
configurator,
|
|
6664
|
+
productId,
|
|
6665
|
+
width: itemValue.width,
|
|
6666
|
+
length: itemValue.length,
|
|
6667
|
+
quantity: itemValue.count,
|
|
6668
|
+
marker: itemValue.marker,
|
|
6669
|
+
});
|
|
6670
|
+
return isEdit && orderData != null
|
|
6671
|
+
? this.orderService.updateProduct$(orderData.id, payload, this.orderId)
|
|
6672
|
+
: this.orderService.addProduct$(payload, this.orderId);
|
|
6673
|
+
}
|
|
6674
|
+
/**
|
|
6675
|
+
* Устанавливает начальные значения для полей формы.
|
|
6676
|
+
*/
|
|
6677
|
+
setDefaultFormValue() {
|
|
6678
|
+
this.form.reset({
|
|
6679
|
+
productCategoryId: Number(this.categoryId()),
|
|
6680
|
+
configurator: this.editor(),
|
|
6681
|
+
});
|
|
6682
|
+
this.items.clear();
|
|
6683
|
+
const orderItem = this.orderItem();
|
|
6684
|
+
this.items.push(this.createItemGroup({
|
|
6685
|
+
width: (orderItem?.width ?? 0) * 1000,
|
|
6686
|
+
length: (orderItem?.length ?? 0) * 1000,
|
|
6687
|
+
count: orderItem?.quantity ?? 1,
|
|
6688
|
+
marker: orderItem?.marker ?? null,
|
|
6689
|
+
}));
|
|
6690
|
+
this.itemStates.set(this.items.controls.map(() => IDLE_ITEM_STATE));
|
|
6691
|
+
this.updateItemsValidators();
|
|
6692
|
+
this.form.markAsUntouched();
|
|
6693
|
+
}
|
|
6694
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSandwichM2Component, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6695
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ScSandwichM2Component, isStandalone: true, selector: "sc-sandwich-m2", inputs: { settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null }, categoryId: { classPropertyName: "categoryId", publicName: "categoryId", isSignal: true, isRequired: true, transformFunction: null }, editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, orderItem: { classPropertyName: "orderItem", publicName: "orderItem", isSignal: true, isRequired: true, transformFunction: null }, orderId: { classPropertyName: "orderId", publicName: "orderId", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { toggleShowEvent: "toggleShowEvent" }, providers: [
|
|
6696
|
+
tuiNumberFormatProvider({ precision: 0 }),
|
|
6697
|
+
tuiInputNumberOptionsProvider({
|
|
6698
|
+
min: 0,
|
|
6699
|
+
}),
|
|
6700
|
+
tuiItemsHandlersProvider({
|
|
6701
|
+
stringify: signal((x) => x.name),
|
|
6702
|
+
identityMatcher: signal((a, b) => a.id === b.id),
|
|
6703
|
+
}),
|
|
6704
|
+
], ngImport: i0, template: "@if (!orderItem() && settings()?.allowShowTable) {\n <div class=\"mb-5 flex justify-center\">\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"toggleShowEvent.emit()\"\n type=\"button\"\n iconStart=\"@tui.layout-list\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0432 \u0432\u0438\u0434\u0435 \u0441\u043F\u0438\u0441\u043A\u0430\n </button>\n </div>\n}\n<div class=\"\">\n @let products = products$ | async;\n @let productValue = product.value;\n\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit()\"\n ScNextInputFocus\n class=\"flex flex-col gap-2\"\n >\n <label\n tuiLabel\n class=\"grow\"\n >\n \u0422\u043E\u0432\u0430\u0440\n <tui-textfield\n tuiChevron\n [tuiTextfieldCleaner]=\"false\"\n >\n <input\n tuiChevron\n tuiSelect\n [formControl]=\"product\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\"\n />\n\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error\n [formControl]=\"product\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (productValue && productValue.costRub !== undefined) {\n <div class=\"-mt-1 text-sm text-tui-text-secondary\">\n <span class=\"font-bold\">{{ productValue.code }}</span>\n \u2014\n {{ productValue.costRub.toLocaleString() }} {{ productValue.currency.symbol }}/\u043C\u00B2\n </div>\n }\n\n @if (productValue) {\n <div class=\"mt-4 mb-3 flex flex-col gap-1.5\">\n <div class=\"w-full font-bold\">\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439</div>\n <div class=\"flex flex-col gap-1 text-sm text-tui-text-secondary\">\n @let wt = widthRangeText();\n @let lt = lengthRangeText();\n @if (wt) {\n <div>\u0428\u0438\u0440\u0438\u043D\u0430 {{ wt }}.</div>\n }\n @if (lt) {\n <div>\u0414\u043B\u0438\u043D\u0430 {{ lt }}.</div>\n }\n </div>\n </div>\n }\n\n <div class=\"flex flex-col gap-3\">\n <div\n formArrayName=\"items\"\n class=\"flex flex-col gap-3\"\n >\n @for (item of items.controls; track item) {\n @if ($index > 0) {\n <hr class=\"border-sc-grey h-px\" />\n }\n @let itemIndex = $index;\n <div\n class=\"relative flex flex-col gap-1\"\n [formGroupName]=\"itemIndex\"\n >\n @if (isItemLocked(itemIndex)) {\n <div class=\"pointer-events-none absolute right-3 bottom-0 z-10 flex size-8 items-center justify-center\">\n <tui-icon\n icon=\"@tui.check\"\n class=\"text-tui-status-positive\"\n />\n </div>\n }\n <tui-loader [showLoader]=\"isItemLoading(itemIndex)\">\n <div\n [class.opacity-70]=\"isItemLocked(itemIndex)\"\n class=\"flex min-w-0 items-start gap-2\"\n >\n <div class=\"flex min-w-0 flex-1 flex-col gap-3\">\n <div class=\"flex flex-col gap-3 lg:!flex-row lg:!items-start lg:!gap-6\">\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 1: \u0448\u0438\u0440\u0438\u043D\u0430 + \u0434\u043B\u0438\u043D\u0430 -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!flex-[2]\">\n <label tuiLabel>\n \u0428\u0438\u0440\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"width\"\n [min]=\"settings()?.minWidth ?? 0\"\n [max]=\"product.value?.properties?.width ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n [tuiAutoFocus]=\"!$first\"\n placeholder=\"\u0428\u0438\u0440\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"width\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u0414\u043B\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"length\"\n [min]=\"settings()?.minLength ?? 0\"\n [max]=\"product.value?.properties?.length ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u0414\u043B\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"length\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 2: \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E + \u043C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 (\u043D\u0430 lg 1fr | 2fr) -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!grid-cols-[1fr_2fr] lg:!flex-[3]\">\n <label tuiLabel>\n <span class=\"whitespace-nowrap\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442</span>\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n tuiInputNumber\n formControlName=\"count\"\n [min]=\"1\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"count\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiTextfield\n formControlName=\"marker\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"marker\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n </div>\n\n @let rowVal = item.getRawValue();\n\n @if (rowVal.width > 0 && rowVal.length > 0) {\n <div class=\"mt-1 flex flex-col gap-y-1 text-sm lg:!flex-row lg:!gap-6\">\n @if (pieceAreaM2(rowVal) > 0) {\n <div class=\"lg:!flex-[2]\">\n \u041F\u043B\u043E\u0449\u0430\u0434\u044C (S) =\n <span class=\"font-bold\">{{ pieceAreaM2(rowVal) | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue && rowCost(rowVal) > 0) {\n <div class=\"lg:!flex-[3]\">\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"font-bold\">{{ rowCost(rowVal).toLocaleString() }} {{ productValue.currency.symbol }}</span>\n </div>\n }\n </div>\n }\n </div>\n\n @if (!isEditingExistingItem()) {\n <button\n tuiIconButton\n title=\"\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\"\n (click)=\"removeItem(itemIndex)\"\n [disabled]=\"items.length <= 1 || !product.value || isItemLoading(itemIndex)\"\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.trash-2\"\n appearance=\"secondary\"\n class=\"mt-6 shrink-0 lg:!ml-4\"\n [style.flex]=\"'0 0 auto'\"\n ></button>\n }\n </div>\n </tui-loader>\n </div>\n }\n </div>\n\n @if (productValue) {\n <hr class=\"border-sc-grey h-px\" />\n <div class=\"min-w-0 gap-1 pt-2 text-right\">\n @if (totalAreaM2() > 0) {\n <div>\n \u041E\u0431\u0449\u0430\u044F \u043F\u043B\u043E\u0449\u0430\u0434\u044C:\n <span class=\"font-bold\">{{ totalAreaM2() | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue.costRub && totalCost() > 0) {\n <div>\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"whitespace-nowrap text-xl font-bold\"> {{ totalCost().toLocaleString() }} {{ productValue.currency.symbol }} </span>\n </div>\n }\n </div>\n }\n </div>\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n\n <div class=\"flex flex-wrap items-center gap-3\">\n @if (productValue && !isEditingExistingItem()) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"!product.value || items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\n iconStart=\"@tui.plus\"\n >\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\n </button>\n }\n <button\n type=\"submit\"\n [disabled]=\"form.invalid || isSubmitLoading() || hasNoPendingItems()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"ml-auto\"\n iconStart=\"@tui.check\"\n >\n {{ !orderItem() ? '\u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' : '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' }}\n </button>\n </div>\n </form>\n</div>\n", styles: [":host{display:block;width:100%;max-width:36rem}.row-summary{color:var(--tui-text-secondary);font-size:.75rem}\n"], dependencies: [{ kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: ScNextInputFocusModule }, { kind: "directive", type: ScNextInputFocusDirective, selector: "form[ScNextInputFocus]" }, { kind: "directive", type: TuiLabel, selector: "label[tuiLabel]" }, { kind: "component", type: TuiDataListWrapperComponent, selector: "tui-data-list-wrapper:not([labels]), tui-data-list-wrapper:not([labels])[new]", inputs: ["items", "disabledItemHandler", "emptyContent", "size", "itemContent"], outputs: ["itemClick"] }, { kind: "component", type: TuiError, selector: "tui-error", inputs: ["error"] }, { kind: "component", type: i1$2.TuiTextfieldComponent, selector: "tui-textfield:not([multi])" }, { kind: "directive", type: i1$2.TuiTextfieldDirective, selector: "input[tuiTextfield]:not([tuiInputCard]):not([tuiInputExpire]):not([tuiInputCVC])" }, { kind: "directive", type: i1$2.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }, { kind: "directive", type: i1$2.TuiTextfieldDropdownDirective, selector: "ng-template[tuiTextfieldDropdown]" }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "directive", type: i2$1.TuiSelectDirective, selector: "input[tuiSelect]" }, { kind: "directive", type: i2$1.TuiInputNumberDirective, selector: "input[tuiInputNumber]", inputs: ["min", "max", "prefix", "postfix"] }, { kind: "directive", type: TuiNumberFormat, selector: "[tuiNumberFormat]", inputs: ["tuiNumberFormat"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DecimalPipe, name: "number" }, { kind: "pipe", type: TuiFieldErrorPipe, name: "tuiFieldError" }, { kind: "component", type: i5$2.TuiSliderComponent, selector: "input[type=range][tuiSlider]", inputs: ["size", "segments"] }, { kind: "directive", type: i2$1.TuiInputSliderDirective, selector: "input[tuiInputSlider]" }, { kind: "directive", type: ScSelectOnFocusinDirective, selector: "tui-input-number, tui-input, tui-input-phone, tui-input-date, tui-input-password, input[tuiInputNumber], input[tuiTextfield], input[tuiInputSlider]" }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "showLoader"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "component", type: TuiIcon, selector: "tui-icon", inputs: ["icon", "background"] }, { kind: "directive", type: TuiAutoFocus, selector: "[tuiAutoFocus]", inputs: ["tuiAutoFocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6705
|
+
}
|
|
6706
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSandwichM2Component, decorators: [{
|
|
6707
|
+
type: Component,
|
|
6708
|
+
args: [{ standalone: true, selector: 'sc-sandwich-m2', imports: [
|
|
6709
|
+
TuiButton,
|
|
6710
|
+
FormsModule,
|
|
6711
|
+
ReactiveFormsModule,
|
|
6712
|
+
ScNextInputFocusModule,
|
|
6713
|
+
TuiLabel,
|
|
6714
|
+
TuiDataListWrapperComponent,
|
|
6715
|
+
TuiError,
|
|
6716
|
+
TuiTextfield,
|
|
6717
|
+
TuiChevron,
|
|
6718
|
+
TuiSelect,
|
|
6719
|
+
TuiInputNumber,
|
|
6720
|
+
TuiNumberFormat,
|
|
6721
|
+
AsyncPipe,
|
|
6722
|
+
DecimalPipe,
|
|
6723
|
+
TuiFieldErrorPipe,
|
|
6724
|
+
TuiInputSlider,
|
|
6725
|
+
ScSelectOnFocusinDirective,
|
|
6726
|
+
TuiLoader,
|
|
6727
|
+
TuiButtonLoading,
|
|
6728
|
+
TuiIcon,
|
|
6729
|
+
TuiAutoFocus,
|
|
6730
|
+
], providers: [
|
|
6731
|
+
tuiNumberFormatProvider({ precision: 0 }),
|
|
6732
|
+
tuiInputNumberOptionsProvider({
|
|
6733
|
+
min: 0,
|
|
6734
|
+
}),
|
|
6735
|
+
tuiItemsHandlersProvider({
|
|
6736
|
+
stringify: signal((x) => x.name),
|
|
6737
|
+
identityMatcher: signal((a, b) => a.id === b.id),
|
|
6738
|
+
}),
|
|
6739
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!orderItem() && settings()?.allowShowTable) {\n <div class=\"mb-5 flex justify-center\">\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"toggleShowEvent.emit()\"\n type=\"button\"\n iconStart=\"@tui.layout-list\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0432 \u0432\u0438\u0434\u0435 \u0441\u043F\u0438\u0441\u043A\u0430\n </button>\n </div>\n}\n<div class=\"\">\n @let products = products$ | async;\n @let productValue = product.value;\n\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit()\"\n ScNextInputFocus\n class=\"flex flex-col gap-2\"\n >\n <label\n tuiLabel\n class=\"grow\"\n >\n \u0422\u043E\u0432\u0430\u0440\n <tui-textfield\n tuiChevron\n [tuiTextfieldCleaner]=\"false\"\n >\n <input\n tuiChevron\n tuiSelect\n [formControl]=\"product\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\"\n />\n\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error\n [formControl]=\"product\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (productValue && productValue.costRub !== undefined) {\n <div class=\"-mt-1 text-sm text-tui-text-secondary\">\n <span class=\"font-bold\">{{ productValue.code }}</span>\n \u2014\n {{ productValue.costRub.toLocaleString() }} {{ productValue.currency.symbol }}/\u043C\u00B2\n </div>\n }\n\n @if (productValue) {\n <div class=\"mt-4 mb-3 flex flex-col gap-1.5\">\n <div class=\"w-full font-bold\">\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439</div>\n <div class=\"flex flex-col gap-1 text-sm text-tui-text-secondary\">\n @let wt = widthRangeText();\n @let lt = lengthRangeText();\n @if (wt) {\n <div>\u0428\u0438\u0440\u0438\u043D\u0430 {{ wt }}.</div>\n }\n @if (lt) {\n <div>\u0414\u043B\u0438\u043D\u0430 {{ lt }}.</div>\n }\n </div>\n </div>\n }\n\n <div class=\"flex flex-col gap-3\">\n <div\n formArrayName=\"items\"\n class=\"flex flex-col gap-3\"\n >\n @for (item of items.controls; track item) {\n @if ($index > 0) {\n <hr class=\"border-sc-grey h-px\" />\n }\n @let itemIndex = $index;\n <div\n class=\"relative flex flex-col gap-1\"\n [formGroupName]=\"itemIndex\"\n >\n @if (isItemLocked(itemIndex)) {\n <div class=\"pointer-events-none absolute right-3 bottom-0 z-10 flex size-8 items-center justify-center\">\n <tui-icon\n icon=\"@tui.check\"\n class=\"text-tui-status-positive\"\n />\n </div>\n }\n <tui-loader [showLoader]=\"isItemLoading(itemIndex)\">\n <div\n [class.opacity-70]=\"isItemLocked(itemIndex)\"\n class=\"flex min-w-0 items-start gap-2\"\n >\n <div class=\"flex min-w-0 flex-1 flex-col gap-3\">\n <div class=\"flex flex-col gap-3 lg:!flex-row lg:!items-start lg:!gap-6\">\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 1: \u0448\u0438\u0440\u0438\u043D\u0430 + \u0434\u043B\u0438\u043D\u0430 -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!flex-[2]\">\n <label tuiLabel>\n \u0428\u0438\u0440\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"width\"\n [min]=\"settings()?.minWidth ?? 0\"\n [max]=\"product.value?.properties?.width ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n [tuiAutoFocus]=\"!$first\"\n placeholder=\"\u0428\u0438\u0440\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"width\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u0414\u043B\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"length\"\n [min]=\"settings()?.minLength ?? 0\"\n [max]=\"product.value?.properties?.length ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u0414\u043B\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"length\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 2: \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E + \u043C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 (\u043D\u0430 lg 1fr | 2fr) -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!grid-cols-[1fr_2fr] lg:!flex-[3]\">\n <label tuiLabel>\n <span class=\"whitespace-nowrap\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442</span>\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n tuiInputNumber\n formControlName=\"count\"\n [min]=\"1\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"count\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiTextfield\n formControlName=\"marker\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"marker\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n </div>\n\n @let rowVal = item.getRawValue();\n\n @if (rowVal.width > 0 && rowVal.length > 0) {\n <div class=\"mt-1 flex flex-col gap-y-1 text-sm lg:!flex-row lg:!gap-6\">\n @if (pieceAreaM2(rowVal) > 0) {\n <div class=\"lg:!flex-[2]\">\n \u041F\u043B\u043E\u0449\u0430\u0434\u044C (S) =\n <span class=\"font-bold\">{{ pieceAreaM2(rowVal) | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue && rowCost(rowVal) > 0) {\n <div class=\"lg:!flex-[3]\">\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"font-bold\">{{ rowCost(rowVal).toLocaleString() }} {{ productValue.currency.symbol }}</span>\n </div>\n }\n </div>\n }\n </div>\n\n @if (!isEditingExistingItem()) {\n <button\n tuiIconButton\n title=\"\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\"\n (click)=\"removeItem(itemIndex)\"\n [disabled]=\"items.length <= 1 || !product.value || isItemLoading(itemIndex)\"\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.trash-2\"\n appearance=\"secondary\"\n class=\"mt-6 shrink-0 lg:!ml-4\"\n [style.flex]=\"'0 0 auto'\"\n ></button>\n }\n </div>\n </tui-loader>\n </div>\n }\n </div>\n\n @if (productValue) {\n <hr class=\"border-sc-grey h-px\" />\n <div class=\"min-w-0 gap-1 pt-2 text-right\">\n @if (totalAreaM2() > 0) {\n <div>\n \u041E\u0431\u0449\u0430\u044F \u043F\u043B\u043E\u0449\u0430\u0434\u044C:\n <span class=\"font-bold\">{{ totalAreaM2() | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue.costRub && totalCost() > 0) {\n <div>\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"whitespace-nowrap text-xl font-bold\"> {{ totalCost().toLocaleString() }} {{ productValue.currency.symbol }} </span>\n </div>\n }\n </div>\n }\n </div>\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n\n <div class=\"flex flex-wrap items-center gap-3\">\n @if (productValue && !isEditingExistingItem()) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"!product.value || items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\n iconStart=\"@tui.plus\"\n >\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\n </button>\n }\n <button\n type=\"submit\"\n [disabled]=\"form.invalid || isSubmitLoading() || hasNoPendingItems()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"ml-auto\"\n iconStart=\"@tui.check\"\n >\n {{ !orderItem() ? '\u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' : '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' }}\n </button>\n </div>\n </form>\n</div>\n", styles: [":host{display:block;width:100%;max-width:36rem}.row-summary{color:var(--tui-text-secondary);font-size:.75rem}\n"] }]
|
|
6740
|
+
}], propDecorators: { orderId: [{
|
|
6741
|
+
type: Input
|
|
6742
|
+
}] } });
|
|
6743
|
+
|
|
6744
|
+
/**
|
|
6745
|
+
* Skeleton конфигуратора распила сэндвич-панелей по площади.
|
|
6746
|
+
*/
|
|
6747
|
+
class ScSandwichM2SkeletonComponent {
|
|
6748
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSandwichM2SkeletonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6749
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ScSandwichM2SkeletonComponent, isStandalone: true, selector: "sc-sandwich-m2-skeleton", ngImport: i0, template: "<div class=\"w-100\">\n <div class=\"flex flex-col gap-3\">\n <!-- \u041F\u043E\u043B\u0435 \u0432\u044B\u0431\u043E\u0440\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n\n <!-- \u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \"\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439\". -->\n <div class=\"my-1.5 h-5 w-1/3 rounded bg-sc-light-grey\"></div>\n\n <!-- \u0422\u0435\u043A\u0441\u0442 \u0441 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0430\u043C\u0438. -->\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-2/3 rounded bg-sc-light-grey\"></div>\n <div class=\"my-1 h-3 w-2/3 rounded bg-sc-light-grey\"></div>\n <div class=\"my-1 h-3 w-2/3 rounded bg-sc-light-grey\"></div>\n <div class=\"my-1 h-3 w-2/3 rounded bg-sc-light-grey\"></div>\n </div>\n\n <!-- \u0411\u043B\u043E\u043A \u0441 \u0438\u0437\u0434\u0435\u043B\u0438\u044F\u043C\u0438. -->\n <div class=\"flex flex-col gap-3\">\n <div class=\"flex grow gap-4\">\n <div class=\"grid grow grid-cols-4 gap-4\">\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-1/2 rounded bg-sc-light-grey\"></div>\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n </div>\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-1/2 rounded bg-sc-light-grey\"></div>\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n </div>\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-1/2 rounded bg-sc-light-grey\"></div>\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n </div>\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-1/2 rounded bg-sc-light-grey\"></div>\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n </div>\n </div>\n <div class=\"mt-6 size-8 shrink-0 rounded-sm bg-sc-light-grey\"></div>\n </div>\n </div>\n\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \"\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\". -->\n <button\n tuiButton\n appearance=\"secondary\"\n class=\"sc-skeleton self-center\"\n ></button>\n\n <!-- \u0418\u0442\u043E\u0433\u043E\u0432\u0430\u044F \u043F\u043B\u043E\u0449\u0430\u0434\u044C \u0438 \u0441\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C. -->\n <div class=\"my-2.5 h-6 w-1/3 rounded bg-sc-light-grey\"></div>\n\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0438. -->\n <button\n tuiButton\n class=\"sc-skeleton self-center\"\n ></button>\n </div>\n</div>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6750
|
+
}
|
|
6751
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSandwichM2SkeletonComponent, decorators: [{
|
|
6752
|
+
type: Component,
|
|
6753
|
+
args: [{ standalone: true, selector: 'sc-sandwich-m2-skeleton', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"w-100\">\n <div class=\"flex flex-col gap-3\">\n <!-- \u041F\u043E\u043B\u0435 \u0432\u044B\u0431\u043E\u0440\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n\n <!-- \u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \"\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439\". -->\n <div class=\"my-1.5 h-5 w-1/3 rounded bg-sc-light-grey\"></div>\n\n <!-- \u0422\u0435\u043A\u0441\u0442 \u0441 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0430\u043C\u0438. -->\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-2/3 rounded bg-sc-light-grey\"></div>\n <div class=\"my-1 h-3 w-2/3 rounded bg-sc-light-grey\"></div>\n <div class=\"my-1 h-3 w-2/3 rounded bg-sc-light-grey\"></div>\n <div class=\"my-1 h-3 w-2/3 rounded bg-sc-light-grey\"></div>\n </div>\n\n <!-- \u0411\u043B\u043E\u043A \u0441 \u0438\u0437\u0434\u0435\u043B\u0438\u044F\u043C\u0438. -->\n <div class=\"flex flex-col gap-3\">\n <div class=\"flex grow gap-4\">\n <div class=\"grid grow grid-cols-4 gap-4\">\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-1/2 rounded bg-sc-light-grey\"></div>\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n </div>\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-1/2 rounded bg-sc-light-grey\"></div>\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n </div>\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-1/2 rounded bg-sc-light-grey\"></div>\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n </div>\n <div class=\"flex flex-col gap-1\">\n <div class=\"my-1 h-3 w-1/2 rounded bg-sc-light-grey\"></div>\n <div class=\"mb-4 mt-2 h-10 w-full rounded-sm bg-sc-light-grey\"></div>\n </div>\n </div>\n <div class=\"mt-6 size-8 shrink-0 rounded-sm bg-sc-light-grey\"></div>\n </div>\n </div>\n\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \"\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\". -->\n <button\n tuiButton\n appearance=\"secondary\"\n class=\"sc-skeleton self-center\"\n ></button>\n\n <!-- \u0418\u0442\u043E\u0433\u043E\u0432\u0430\u044F \u043F\u043B\u043E\u0449\u0430\u0434\u044C \u0438 \u0441\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C. -->\n <div class=\"my-2.5 h-6 w-1/3 rounded bg-sc-light-grey\"></div>\n\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0438. -->\n <button\n tuiButton\n class=\"sc-skeleton self-center\"\n ></button>\n </div>\n</div>\n" }]
|
|
6754
|
+
}] });
|
|
6755
|
+
|
|
6121
6756
|
/**
|
|
6122
6757
|
* Компонент карточки менеджера Push-уведомлений.
|
|
6123
6758
|
*/
|
|
@@ -9294,5 +9929,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
9294
9929
|
* Generated bundle index. Do not edit.
|
|
9295
9930
|
*/
|
|
9296
9931
|
|
|
9297
|
-
export { AbstractScPriceCard, AuthMethod, CURRENT_COUNTRY_ID, CostWithDiscountComponent, FilesAndDocumentsComponent, FilesAndDocumentsModule, FinishDateTimeTransformerDirective, IS_DEFAULT_COUNTRY, MAX_FILES_IN_FORM_INPUT, SC_ALLOW_SELECT_TERMINATED, SC_BANNER_DURATION, SC_CATALOG_PRODUCTS_FILTERS, SC_CATALOG_SHOW_PRODUCTS_RECURSIVELY, SC_DATE_FORMATTER, SC_DEBOUNCE_TIME_DEFAULT, SC_DIALOG_SERVICE_TOKEN, SC_ERROR_CHANGE_HANDLER, SC_HELP_NOTIFICATION_CLOSE, SC_HELP_NOTIFICATION_LIMIT, SC_HIDDEN_PRINT_ELEMENTS, SC_MANAGER_QR_HANDLER, SC_NOTIFY_WHEN_IN_STOCK_REQUIRED_FIELDS, SC_ORDER_OPTIONS, SC_PAGE_SIZE_OPTIONS$1 as SC_PAGE_SIZE_OPTIONS, SC_SHOW_HELP_NOTIFICATION_IN_PHONE_INPUT, SC_USER_CITY_INFO, SC_USER_INFO, SC_USER_PROVIDERS, SC_VERIFICATION_CODE_TIMEOUT, ScAccordionComponent, ScAccordionContentDirective, ScAccordionModule, ScAddContactDialogComponent, ScAddContragentBankAccountsDialogComponent, ScAddContragentDialogComponent, ScAddDeliveryAddressDialogComponent, ScAddOrEditingCartItemDialogComponent, ScAddOrEditingCartItemFormComponent, ScAddressesSelectionFieldComponent, ScAuthModule, ScBannerComponent, ScBannerModule, ScBrandsListComponent, ScBrandsListModule, ScCartAddProductsFromCsvDialogComponent, ScCatalogFiltersComponent, ScCatalogModule, ScCategoryCardComponent, ScContactsAccordionComponent, ScContactsModule, ScContragentsAccordionComponent, ScContragentsAccordionItemComponent, ScContragentsModule, ScDeliveryAddressAccordionComponent, ScDeliveryAddressAccordionItemComponent, ScDeliveryAddressModule, ScDownloadPriceListComponent, ScDraftComponent, ScEmailLinkDirective, ScErrorBlockStatusComponent, ScErrorHandlerComponent, ScFavoriteButtonComponent, ScFeedbackFormComponent, ScFocusFirstInvalidFieldDirective, ScFormFieldsModule, ScFormatDatePipe, ScFrequentlyAskedQuestionsComponent, ScFrequentlyAskedQuestionsGroupSelectorComponent, ScFrequentlyAskedQuestionsWithGroupsComponent, ScGratitudeComponent, ScHelpNotificationService, ScHoverImageCarouselComponent, ScInputQuantityComponent, ScLinks, ScManagerCardComponent, ScManagerCardPushComponent, ScNewContactFormComponent, ScNewContragentBankAccountsFormComponent, ScNewContragentFormComponent, ScNewsCardComponent, ScNewsCardSkeletonComponent, ScNewsModule, ScNextInputFocusDirective, ScNextInputFocusModule, ScNoindexDirective, ScNoindexWrapperComponent, ScNotifyWhenInStockDialogComponent, ScOrderAccessorDirective, ScOrderItemComponent, ScOrderItemsByDirection, ScOrderItemsListByDirectionsComponent, ScOrderItemsListByStockComponent, ScOrderItemsListComponent, ScOrderModule, ScPaymentStatusComponent, ScPersonalDataProcessingPolicyComponent, ScPhoneFormatPipe, ScPreviewSampleComponent, ScPreviewSampleModule, ScPreviewSamplesMosquitoComponent, ScPriceCardComponent, ScPriceCardInlineComponent, ScPriceHistoryComponent, ScPriceListPaginationComponent, ScPriceWarehouseStockComponent, ScPrintDirective, ScPrintService, ScPrivacyPolicyComponent, ScProductInAllWarehousesPipe, ScProfileAccordionsContentComponent, ScProfileModule, ScPublicOfferComponent, ScQRCodeDialogComponent, ScQRCodeModule, ScResetUserPasswordComponent, ScResourcePreviewComponent, ScSandwichComponent, ScSandwichSkeletonComponent, ScSelectOnFocusinDirective, ScSeoTagsComponent, ScShareButtonComponent, ScShareButtonModule, ScSignInFormByEmailComponent, ScSignInFormByPhoneComponent, ScSignInFormComponent, ScSignUpFormComponent, ScSimpleSignUpFormComponent, ScSuggestionFieldComponent, ScTelLinkDirective, ScTerminalLinkDirective, ScUpdateUserInfoDialogComponent, ScUserManagersComponent, ScUserModule, ScUserPhoneApproveDialogComponent, ScVerificationModule, ScVerificationPhoneCheckFormComponent, TreeDirective, TreeIconService, TreeLoaderService, TreeTopDirective, phoneValidator, scAtLeastOneRequiredValidator, scBicValidator, scClientUiIconsName, scCorrespondentAccountValidator, scGetCurrentRoute, scPasswordConfirmMatchingValidator, stepValidator, tuiDateValueTransformerDefaultProvider };
|
|
9932
|
+
export { AbstractScPriceCard, AuthMethod, CURRENT_COUNTRY_ID, CostWithDiscountComponent, FilesAndDocumentsComponent, FilesAndDocumentsModule, FinishDateTimeTransformerDirective, IDLE_ITEM_STATE, IS_DEFAULT_COUNTRY, MAX_FILES_IN_FORM_INPUT, SC_ALLOW_SELECT_TERMINATED, SC_BANNER_DURATION, SC_CATALOG_PRODUCTS_FILTERS, SC_CATALOG_SHOW_PRODUCTS_RECURSIVELY, SC_DATE_FORMATTER, SC_DEBOUNCE_TIME_DEFAULT, SC_DIALOG_SERVICE_TOKEN, SC_ERROR_CHANGE_HANDLER, SC_HELP_NOTIFICATION_CLOSE, SC_HELP_NOTIFICATION_LIMIT, SC_HIDDEN_PRINT_ELEMENTS, SC_MANAGER_QR_HANDLER, SC_NOTIFY_WHEN_IN_STOCK_REQUIRED_FIELDS, SC_ORDER_OPTIONS, SC_PAGE_SIZE_OPTIONS$1 as SC_PAGE_SIZE_OPTIONS, SC_SHOW_HELP_NOTIFICATION_IN_PHONE_INPUT, SC_USER_CITY_INFO, SC_USER_INFO, SC_USER_PROVIDERS, SC_VERIFICATION_CODE_TIMEOUT, ScAccordionComponent, ScAccordionContentDirective, ScAccordionModule, ScAddContactDialogComponent, ScAddContragentBankAccountsDialogComponent, ScAddContragentDialogComponent, ScAddDeliveryAddressDialogComponent, ScAddOrEditingCartItemDialogComponent, ScAddOrEditingCartItemFormComponent, ScAddressesSelectionFieldComponent, ScAuthModule, ScBannerComponent, ScBannerModule, ScBrandsListComponent, ScBrandsListModule, ScCartAddProductsFromCsvDialogComponent, ScCatalogFiltersComponent, ScCatalogModule, ScCategoryCardComponent, ScContactsAccordionComponent, ScContactsModule, ScContragentsAccordionComponent, ScContragentsAccordionItemComponent, ScContragentsModule, ScDeliveryAddressAccordionComponent, ScDeliveryAddressAccordionItemComponent, ScDeliveryAddressModule, ScDownloadPriceListComponent, ScDraftComponent, ScEmailLinkDirective, ScErrorBlockStatusComponent, ScErrorHandlerComponent, ScFavoriteButtonComponent, ScFeedbackFormComponent, ScFocusFirstInvalidFieldDirective, ScFormFieldsModule, ScFormatDatePipe, ScFrequentlyAskedQuestionsComponent, ScFrequentlyAskedQuestionsGroupSelectorComponent, ScFrequentlyAskedQuestionsWithGroupsComponent, ScGratitudeComponent, ScHelpNotificationService, ScHoverImageCarouselComponent, ScInputQuantityComponent, ScLinks, ScManagerCardComponent, ScManagerCardPushComponent, ScNewContactFormComponent, ScNewContragentBankAccountsFormComponent, ScNewContragentFormComponent, ScNewsCardComponent, ScNewsCardSkeletonComponent, ScNewsModule, ScNextInputFocusDirective, ScNextInputFocusModule, ScNoindexDirective, ScNoindexWrapperComponent, ScNotifyWhenInStockDialogComponent, ScOrderAccessorDirective, ScOrderItemComponent, ScOrderItemsByDirection, ScOrderItemsListByDirectionsComponent, ScOrderItemsListByStockComponent, ScOrderItemsListComponent, ScOrderModule, ScPaymentStatusComponent, ScPersonalDataProcessingPolicyComponent, ScPhoneFormatPipe, ScPreviewSampleComponent, ScPreviewSampleModule, ScPreviewSamplesMosquitoComponent, ScPriceCardComponent, ScPriceCardInlineComponent, ScPriceHistoryComponent, ScPriceListPaginationComponent, ScPriceWarehouseStockComponent, ScPrintDirective, ScPrintService, ScPrivacyPolicyComponent, ScProductInAllWarehousesPipe, ScProfileAccordionsContentComponent, ScProfileModule, ScPublicOfferComponent, ScQRCodeDialogComponent, ScQRCodeModule, ScResetUserPasswordComponent, ScResourcePreviewComponent, ScSandwichComponent, ScSandwichM2Component, ScSandwichM2SkeletonComponent, ScSandwichSkeletonComponent, ScSelectOnFocusinDirective, ScSeoTagsComponent, ScShareButtonComponent, ScShareButtonModule, ScSignInFormByEmailComponent, ScSignInFormByPhoneComponent, ScSignInFormComponent, ScSignUpFormComponent, ScSimpleSignUpFormComponent, ScSuggestionFieldComponent, ScTelLinkDirective, ScTerminalLinkDirective, ScUpdateUserInfoDialogComponent, ScUserManagersComponent, ScUserModule, ScUserPhoneApproveDialogComponent, ScVerificationModule, ScVerificationPhoneCheckFormComponent, TreeDirective, TreeIconService, TreeLoaderService, TreeTopDirective, phoneValidator, scAtLeastOneRequiredValidator, scBicValidator, scClientUiIconsName, scCorrespondentAccountValidator, scGetCurrentRoute, scPasswordConfirmMatchingValidator, stepValidator, tuiDateValueTransformerDefaultProvider };
|
|
9298
9933
|
//# sourceMappingURL=snabcentr-client-ui.mjs.map
|