@snabcentr/client-ui 3.54.1 → 3.55.0
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/catalog/catalog-filters/sc-catalog-filters.component.d.ts +14 -3
- package/esm2022/catalog/catalog-filters/sc-catalog-filters.component.mjs +42 -15
- package/esm2022/order/index.mjs +5 -1
- package/esm2022/order/models/i-new-order-form.mjs +2 -0
- package/esm2022/order/order-direction-items/sc-order-direction-items.component.mjs +39 -0
- package/esm2022/order/order-form/sc-order-form.component.mjs +545 -0
- package/esm2022/order/order-form/sc-order-form.config.mjs +7 -0
- package/fesm2022/snabcentr-client-ui.mjs +611 -21
- package/fesm2022/snabcentr-client-ui.mjs.map +1 -1
- package/order/index.d.ts +4 -0
- package/order/models/i-new-order-form.d.ts +39 -0
- package/order/order-direction-items/sc-order-direction-items.component.d.ts +29 -0
- package/order/order-form/sc-order-form.component.d.ts +264 -0
- package/order/order-form/sc-order-form.config.d.ts +20 -0
- package/package.json +2 -1
- package/release_notes.tmp +4 -2
- package/styles/tailwind/tailwind.scss +9 -0
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { InjectionToken, inject, Injectable, NgZone, signal, EventEmitter, ChangeDetectorRef, Directive, Input, Output, Pipe, ElementRef, HostListener, Renderer2, ContentChildren, NgModule, input, computed, Component, ChangeDetectionStrategy, Inject, HostBinding, model, output, SkipSelf, DestroyRef, effect, ContentChild, ViewChild, viewChild, Optional, contentChild, TemplateRef, forwardRef } from '@angular/core';
|
|
3
3
|
import * as i1 from '@snabcentr/client-core';
|
|
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, loadingPlaceholder, 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, SchemaOrgFactory, SC_COMPANY_INFO, ScFeedbackService } from '@snabcentr/client-core';
|
|
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, loadingPlaceholder, 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, ScDeliveryAddressService, ScOrdersService, ScUIService, SC_USER_INFO as SC_USER_INFO$1, ScPaymentType, ScDeliveryType, TERMINAL_PROVIDERS, ScOrderDraftsService, ScRouteKeys, ScSeoService, scOrderIsLoaded, ScFrequentlyAskedQuestionsService, SchemaOrgFactory, 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, Subscription, merge, skip, from, concatMap, noop } 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, Subscription, merge, skip, from, concatMap, noop, first, retry } 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';
|
|
10
|
-
import { TuiDay, TuiTime, TuiValueTransformer, TUI_IS_MOBILE, tuiControlValue, tuiIsPresent, tuiMarkControlAsTouchedAndValidate, tuiIsFalsy, TuiAutoFocus, TuiRepeatTimes, TuiHovered, TuiDayRange, TuiMonth, tuiPure, tuiProvide, tuiClamp, TUI_WINDOW_SIZE,
|
|
10
|
+
import { TuiDay, TuiTime, TuiValueTransformer, TUI_IS_MOBILE, tuiControlValue, tuiIsPresent, tuiMarkControlAsTouchedAndValidate, tuiIsFalsy, TuiAutoFocus, TuiRepeatTimes, TuiHovered, TuiDayRange, TuiMonth, tuiPure, tuiProvide, TuiValidationError, tuiClamp, TUI_WINDOW_SIZE, TUI_TRUE_HANDLER } from '@taiga-ui/cdk';
|
|
11
11
|
import * as i2$1 from '@taiga-ui/kit';
|
|
12
|
-
import { TUI_DATE_VALUE_TRANSFORMER, TuiPreview, TuiAvatar, TuiAccordionItem, TuiElasticContainer, TuiAccordion, TuiFieldErrorPipe, TuiFilterByInputPipe, TuiStringifyContentPipe, TuiDataListWrapper, TuiButtonLoading, TuiSortCountriesPipe, TuiStepper, TuiCarousel, TuiPush, TuiCheckbox, TuiFiles, TuiChip, TuiInputNumber, TuiBadge, TuiTooltip, TuiHighlight, TuiLineClamp, TuiFade, TuiRange, tuiInputNumberOptionsProvider, TuiDataListWrapperComponent, TuiChevron, TuiSelect, TuiInputSlider, TuiTreeService, TuiTreeItemContent, TUI_TREE_START, TUI_TREE_CONTENT, TUI_TREE_LOADING, TUI_TREE_LOADER, TuiTree, TuiPreviewDialogService, TUI_CONFIRM, tuiItemsHandlersProvider as tuiItemsHandlersProvider$1, TUI_PAGINATION_TEXTS, TuiAccordionDirective, TuiAccordionItemContent
|
|
12
|
+
import { TUI_DATE_VALUE_TRANSFORMER, TuiPreview, TuiAvatar, TuiAccordionItem, TuiElasticContainer, TuiAccordion, TuiFieldErrorPipe, TuiFilterByInputPipe, TuiStringifyContentPipe, TuiDataListWrapper, TuiButtonLoading, TuiSortCountriesPipe, TuiStepper, TuiCarousel, TuiPush, TuiCheckbox, TuiFiles, TuiChip, TuiInputNumber, TuiBadge, TuiTooltip, TuiHighlight, TuiLineClamp, TuiFade, TuiRange, tuiInputNumberOptionsProvider, TuiDataListWrapperComponent, TuiChevron, TuiSelect, TuiInputSlider, TuiTreeService, TuiTreeItemContent, TUI_TREE_START, TUI_TREE_CONTENT, TUI_TREE_LOADING, TUI_TREE_LOADER, TuiTree, TuiPreviewDialogService, tuiFilesAccepted, TuiInputFiles, TuiInputFilesDirective, TuiFilesComponent, TuiFile, TuiFileRejectedPipe, TUI_CONFIRM, tuiItemsHandlersProvider as tuiItemsHandlersProvider$1, TUI_PAGINATION_TEXTS, TuiAccordionDirective, TuiAccordionItemContent } from '@taiga-ui/kit';
|
|
13
13
|
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
|
14
14
|
import * as i1$1 from '@angular/forms';
|
|
15
15
|
import { FormControl, FormGroupDirective, NgControl, FormGroup, Validators, FormArray, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
16
16
|
import * as i1$2 from '@taiga-ui/core';
|
|
17
|
-
import { TuiButton, TuiDialog, TuiDialogService, TuiLink, TuiFallbackSrcPipe, TuiInitialsPipe, TuiIcon, TuiAppearance, TuiWithAppearance, TuiIcons, TuiWithIcons, TUI_DATA_LIST_HOST, tuiDropdownOptionsProvider, TuiLabel, TuiError, TuiLoader, TuiDataList, TuiNotification, TuiTextfield, TuiTitle, TuiNumberFormat, TuiHint, TUI_MONTHS, TuiScrollbar, tuiNumberFormatProvider, tuiItemsHandlersProvider, tuiTextfieldOptionsProvider, tuiHintOptionsProvider, TuiFormatNumberPipe, TuiHintDriver, TuiHintHover, TuiHintPosition, TuiHintDirective, TUI_BUTTON_OPTIONS, TUI_BUTTON_DEFAULT_OPTIONS, TUI_SPIN_ICONS, TuiSurface, tuiFadeIn } from '@taiga-ui/core';
|
|
17
|
+
import { TuiButton, TuiDialog, TuiDialogService, TuiLink, TuiFallbackSrcPipe, TuiInitialsPipe, TuiIcon, TuiAppearance, TuiWithAppearance, TuiIcons, TuiWithIcons, TUI_DATA_LIST_HOST, tuiDropdownOptionsProvider, TuiLabel, TuiError, TuiLoader, TuiDataList, TuiNotification, TuiTextfield, TuiTitle, TuiNumberFormat, TuiHint, TUI_MONTHS, TuiScrollbar, tuiNumberFormatProvider, tuiItemsHandlersProvider, tuiTextfieldOptionsProvider, tuiHintOptionsProvider, TuiFormatNumberPipe, TuiHintDriver, TuiHintHover, TuiHintPosition, TuiHintDirective, TuiDataListComponent, TuiOption, TUI_BUTTON_OPTIONS, TUI_BUTTON_DEFAULT_OPTIONS, TUI_SPIN_ICONS, TuiSurface, tuiFadeIn } from '@taiga-ui/core';
|
|
18
18
|
import { isValidPhoneNumber } from 'libphonenumber-js/max';
|
|
19
19
|
import * as i4 from '@taiga-ui/legacy/components/primitive-textfield';
|
|
20
20
|
import * as i3 from '@taiga-ui/legacy';
|
|
21
|
-
import { AbstractTuiControl, TuiInputModule, TuiTextfieldControllerModule, TuiComboBoxModule, TuiInputPhoneModule, TuiSelectModule, TuiInputPasswordModule, AbstractTuiNullableControl, TuiInputNumberComponent, TuiInputNumberModule, TuiIslandDirective, TuiTextareaModule } from '@taiga-ui/legacy';
|
|
21
|
+
import { AbstractTuiControl, TuiInputModule, TuiTextfieldControllerModule, TuiComboBoxModule, TuiInputPhoneModule, TuiSelectModule, TuiInputPasswordModule, AbstractTuiNullableControl, TuiInputNumberComponent, TuiInputNumberModule, TuiIslandDirective, TuiInputDateModule, TuiTextareaModule } from '@taiga-ui/legacy';
|
|
22
22
|
import { getCountries } from 'libphonenumber-js';
|
|
23
|
-
import { isNil, isUndefined, isObject } from 'lodash-es';
|
|
23
|
+
import { isNil, isUndefined, isObject, isArray, isString } from 'lodash-es';
|
|
24
24
|
import * as i5 from '@taiga-ui/core/components/label';
|
|
25
25
|
import * as i8 from '@maskito/angular';
|
|
26
26
|
import { MaskitoDirective } from '@maskito/angular';
|
|
@@ -33,6 +33,7 @@ import { QRCodeModule } from 'angularx-qrcode';
|
|
|
33
33
|
import * as i1$3 from '@taiga-ui/experimental';
|
|
34
34
|
import { TuiInputPhoneInternational, TuiAccordion as TuiAccordion$1 } from '@taiga-ui/experimental';
|
|
35
35
|
import * as i3$1 from '@taiga-ui/core/components/data-list';
|
|
36
|
+
import { TuiDataListDirective } from '@taiga-ui/core/components/data-list';
|
|
36
37
|
import * as i1$4 from '@taiga-ui/cdk/directives/item';
|
|
37
38
|
import * as i3$2 from '@ng-web-apis/intersection-observer';
|
|
38
39
|
import { IntersectionObserverService, WaIntersectionObserver } from '@ng-web-apis/intersection-observer';
|
|
@@ -49,6 +50,7 @@ import { TuiLineDaysChart, TuiLineDaysChartHint, TuiAxes } from '@taiga-ui/addon
|
|
|
49
50
|
import * as i5$2 from '@taiga-ui/kit/components/slider';
|
|
50
51
|
import * as i9 from 'angular8-yandex-maps';
|
|
51
52
|
import { AngularYandexMapsModule } from 'angular8-yandex-maps';
|
|
53
|
+
import { isValid, parse, format } from 'date-fns';
|
|
52
54
|
import * as i2$5 from '@taiga-ui/experimental/components/expand';
|
|
53
55
|
import * as i3$3 from '@taiga-ui/kit/components/data-list-wrapper';
|
|
54
56
|
import { TuiGroup } from '@taiga-ui/core/directives/group';
|
|
@@ -5771,6 +5773,20 @@ class ScCatalogFiltersComponent {
|
|
|
5771
5773
|
this.form.valueChanges.pipe(debounceTime(0), takeUntilDestroyed()).subscribe((filters) => {
|
|
5772
5774
|
this.catalogProductsFilters$.next(this.buildPropertyFilters(filters));
|
|
5773
5775
|
});
|
|
5776
|
+
// Внешний сброс фильтров (например, при смене категории): приводим форму к исходным значениям без повторной отправки в хранилище.
|
|
5777
|
+
this.catalogProductsFilters$
|
|
5778
|
+
.pipe(filter((value) => Object.keys(value).length === 0), takeUntilDestroyed())
|
|
5779
|
+
.subscribe(() => {
|
|
5780
|
+
this.resetAllFilters(false);
|
|
5781
|
+
});
|
|
5782
|
+
}
|
|
5783
|
+
/**
|
|
5784
|
+
* Возвращает текущие применённые фильтры из хранилища фильтров.
|
|
5785
|
+
*
|
|
5786
|
+
* Позволяет восстанавливать выбранные значения при пересоздании компонента (повторное открытие диалога или блока фильтров).
|
|
5787
|
+
*/
|
|
5788
|
+
getAppliedFilters() {
|
|
5789
|
+
return this.catalogProductsFilters$ instanceof BehaviorSubject ? this.catalogProductsFilters$.value : {};
|
|
5774
5790
|
}
|
|
5775
5791
|
/**
|
|
5776
5792
|
* Обновляет состав контролов формы на основе переданных фильтров.
|
|
@@ -5780,13 +5796,16 @@ class ScCatalogFiltersComponent {
|
|
|
5780
5796
|
updateFormControls(filters) {
|
|
5781
5797
|
this.formSyncs.unsubscribe();
|
|
5782
5798
|
this.formSyncs = new Subscription();
|
|
5799
|
+
const appliedFilters = this.getAppliedFilters();
|
|
5783
5800
|
Object.keys(this.form.controls).forEach((key) => {
|
|
5784
5801
|
this.form.removeControl(key, { emitEvent: false });
|
|
5785
5802
|
});
|
|
5786
5803
|
filters.forEach((item) => {
|
|
5804
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
5805
|
+
const appliedValue = appliedFilters[item.id];
|
|
5787
5806
|
switch (item.type) {
|
|
5788
5807
|
case 'checkbox': {
|
|
5789
|
-
const checkboxControl = this.createCheckboxFormControl(item);
|
|
5808
|
+
const checkboxControl = this.createCheckboxFormControl(item, appliedValue);
|
|
5790
5809
|
this.form.addControl(item.id, checkboxControl, { emitEvent: false });
|
|
5791
5810
|
// Single-select для !isMultiple: при выборе одного остальные снимаются.
|
|
5792
5811
|
if (!item.isMultiple && item.values.length > 1) {
|
|
@@ -5795,13 +5814,13 @@ class ScCatalogFiltersComponent {
|
|
|
5795
5814
|
break;
|
|
5796
5815
|
}
|
|
5797
5816
|
case 'range': {
|
|
5798
|
-
const rangeControl = this.createRangeFormControl(item);
|
|
5817
|
+
const rangeControl = this.createRangeFormControl(item, appliedValue);
|
|
5799
5818
|
this.form.addControl(item.id, rangeControl, { emitEvent: false });
|
|
5800
5819
|
this.formSyncs.add(this.syncRangeFromToAndSlider(rangeControl));
|
|
5801
5820
|
break;
|
|
5802
5821
|
}
|
|
5803
5822
|
case 'toggle':
|
|
5804
|
-
this.form.addControl(item.id, this.createToggleFormControl(item), { emitEvent: false });
|
|
5823
|
+
this.form.addControl(item.id, this.createToggleFormControl(item, appliedValue), { emitEvent: false });
|
|
5805
5824
|
break;
|
|
5806
5825
|
default:
|
|
5807
5826
|
break;
|
|
@@ -5848,9 +5867,11 @@ class ScCatalogFiltersComponent {
|
|
|
5848
5867
|
* Различие в API-выводе для одиночного значения (boolean вместо массива) обрабатывается в {@link processCheckboxFilter}.
|
|
5849
5868
|
*
|
|
5850
5869
|
* @param checkboxFilter Фильтр типа checkbox.
|
|
5870
|
+
* @param appliedValue Применённое ранее значение фильтра из хранилища фильтров.
|
|
5851
5871
|
*/
|
|
5852
|
-
createCheckboxFormControl(checkboxFilter) {
|
|
5853
|
-
const
|
|
5872
|
+
createCheckboxFormControl(checkboxFilter, appliedValue) {
|
|
5873
|
+
const appliedIds = Array.isArray(appliedValue) ? appliedValue : null;
|
|
5874
|
+
const isSelected = (id) => appliedIds?.includes(id) ?? checkboxFilter.selectedValues?.includes(id) ?? false;
|
|
5854
5875
|
const controls = {};
|
|
5855
5876
|
checkboxFilter.values.forEach((value) => {
|
|
5856
5877
|
controls[value.id] = new FormControl(isSelected(value.id), { nonNullable: true });
|
|
@@ -5874,10 +5895,14 @@ class ScCatalogFiltersComponent {
|
|
|
5874
5895
|
* Поля заполнены дефолтами и валидируются границами; округление значений — на стороне поля ввода Taiga.
|
|
5875
5896
|
*
|
|
5876
5897
|
* @param rangeFilter Фильтр типа range.
|
|
5898
|
+
* @param appliedValue Применённое ранее значение фильтра из хранилища фильтров.
|
|
5877
5899
|
*/
|
|
5878
|
-
createRangeFormControl(rangeFilter) {
|
|
5900
|
+
createRangeFormControl(rangeFilter, appliedValue) {
|
|
5879
5901
|
const { min, max } = rangeFilter;
|
|
5880
|
-
const
|
|
5902
|
+
const appliedRange = appliedValue && typeof appliedValue === 'object' && !Array.isArray(appliedValue) ? appliedValue : null;
|
|
5903
|
+
const defaults = this.getRangeDefaults(rangeFilter);
|
|
5904
|
+
const fromValue = Number(appliedRange?.from ?? defaults.from);
|
|
5905
|
+
const toValue = Number(appliedRange?.to ?? defaults.to);
|
|
5881
5906
|
return new FormGroup({
|
|
5882
5907
|
from: new FormControl(fromValue, { nonNullable: true, validators: [Validators.min(min), Validators.max(max)] }),
|
|
5883
5908
|
to: new FormControl(toValue, { nonNullable: true, validators: [Validators.min(min), Validators.max(max)] }),
|
|
@@ -5961,9 +5986,11 @@ class ScCatalogFiltersComponent {
|
|
|
5961
5986
|
* Создает FormControl для toggle.
|
|
5962
5987
|
*
|
|
5963
5988
|
* @param toggleFilter Фильтр типа toggle.
|
|
5989
|
+
* @param appliedValue Применённое ранее значение фильтра из хранилища фильтров.
|
|
5964
5990
|
*/
|
|
5965
|
-
createToggleFormControl(toggleFilter) {
|
|
5966
|
-
|
|
5991
|
+
createToggleFormControl(toggleFilter, appliedValue) {
|
|
5992
|
+
const appliedToggle = typeof appliedValue === 'boolean' ? appliedValue : undefined;
|
|
5993
|
+
return new FormControl(appliedToggle ?? toggleFilter.selectedValue ?? false, { nonNullable: true });
|
|
5967
5994
|
}
|
|
5968
5995
|
/**
|
|
5969
5996
|
* Обрабатывает checkbox: FormGroup → string[] выбранных id; для единственного значения — boolean (как toggle).
|
|
@@ -6086,8 +6113,10 @@ class ScCatalogFiltersComponent {
|
|
|
6086
6113
|
}
|
|
6087
6114
|
/**
|
|
6088
6115
|
* Сбрасывает все фильтры к исходным значениям.
|
|
6116
|
+
*
|
|
6117
|
+
* @param emitEvent Признак необходимости эмитить события изменения контролов (false — тихий сброс без отправки значений в хранилище фильтров).
|
|
6089
6118
|
*/
|
|
6090
|
-
resetAllFilters() {
|
|
6119
|
+
resetAllFilters(emitEvent = true) {
|
|
6091
6120
|
this.filters()?.forEach((filterItem) => {
|
|
6092
6121
|
const control = this.form.get(filterItem.id);
|
|
6093
6122
|
if (!control) {
|
|
@@ -6101,16 +6130,16 @@ class ScCatalogFiltersComponent {
|
|
|
6101
6130
|
// eslint-disable-next-line security/detect-object-injection
|
|
6102
6131
|
resetValue[id] = false;
|
|
6103
6132
|
});
|
|
6104
|
-
group.reset(resetValue);
|
|
6133
|
+
group.reset(resetValue, { emitEvent });
|
|
6105
6134
|
break;
|
|
6106
6135
|
}
|
|
6107
6136
|
case 'toggle':
|
|
6108
|
-
control.reset(false);
|
|
6137
|
+
control.reset(false, { emitEvent });
|
|
6109
6138
|
break;
|
|
6110
6139
|
case 'range': {
|
|
6111
6140
|
const group = control;
|
|
6112
6141
|
const defaults = this.getRangeDefaults(filterItem);
|
|
6113
|
-
group.reset({ from: defaults.from, to: defaults.to, slider: [defaults.from, defaults.to] });
|
|
6142
|
+
group.reset({ from: defaults.from, to: defaults.to, slider: [defaults.from, defaults.to] }, { emitEvent });
|
|
6114
6143
|
break;
|
|
6115
6144
|
}
|
|
6116
6145
|
default:
|
|
@@ -8639,6 +8668,567 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
8639
8668
|
args: [{ standalone: true, selector: 'sc-order-items-list-by-directions', imports: [ScOrderItemsListComponent, TuiButton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"flex flex-col gap-5\">\n <!-- \u0413\u0440\u0443\u043F\u043F\u044B \u0442\u043E\u0432\u0430\u0440\u043E\u0432 \u043F\u043E \u043D\u0430\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u044F\u043C \u043F\u0440\u043E\u0434\u0430\u0436. -->\n @for (direction of itemsByDirections(); track direction.direction?.id; let groupIndex = $index) {\n <div class=\"flex flex-col gap-2.5\">\n @if (direction.direction && itemsByDirections().length > 1) {\n <div class=\"text-base font-bold\">\u041D\u0430\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435 \u043F\u0440\u043E\u0434\u0430\u0436: {{ direction.direction.description }}</div>\n }\n\n <sc-order-items-list\n [items]=\"direction.items\"\n [selectable]=\"selectable()\"\n [editable]=\"editable()\"\n (selectedItemsIdsChange)=\"selectedItemsHandler($event, direction)\"\n />\n\n <!-- \u0424\u0443\u0442\u0435\u0440 \u0433\u0440\u0443\u043F\u043F\u044B \u0442\u043E\u0432\u0430\u0440\u043E\u0432. -->\n <div class=\"flex flex-col items-center sm:flex-row sm:items-start sm:flex-wrap-reverse grow gap-x-2.5 gap-y-4\">\n <ng-content select=\"[footerActions]\" />\n\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0435\u043D\u0438\u044F. -->\n @if (showContinueButton()) {\n <button\n tuiButton\n type=\"button\"\n [disabled]=\"direction.getItemsByIds(selectedItemsIds()).length === 0\"\n [iconStart]=\"continueButtonText().iconStart\"\n class=\"sm:ml-auto\"\n (click)=\"continueClick.emit(direction)\"\n >\n {{ continueButtonText().title }}\n </button>\n }\n </div>\n </div>\n }\n\n @if (nullItems().length) {\n <div class=\"flex flex-col gap-2.5\">\n <div class=\"text-base font-bold\">\u0422\u043E\u0432\u0430\u0440\u044B \u0438 \u0443\u0441\u043B\u0443\u0433\u0438, \u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435 \u043F\u0440\u0435\u0434\u043E\u0441\u0442\u0430\u0432\u043B\u044F\u044E\u0442\u0441\u044F.</div>\n\n <sc-order-items-list\n [items]=\"nullItems()\"\n [selectable]=\"false\"\n [editable]=\"editable()\"\n />\n </div>\n }\n</div>\n" }]
|
|
8640
8669
|
}] });
|
|
8641
8670
|
|
|
8671
|
+
/**
|
|
8672
|
+
* Список товаров заказа по направлению продаж с выбором позиций для оформления.
|
|
8673
|
+
*/
|
|
8674
|
+
class ScOrderDirectionItemsComponent {
|
|
8675
|
+
constructor() {
|
|
8676
|
+
/**
|
|
8677
|
+
* Товары направления.
|
|
8678
|
+
*/
|
|
8679
|
+
this.items = input.required();
|
|
8680
|
+
/**
|
|
8681
|
+
* Разрешить редактирование позиций (количество, удаление).
|
|
8682
|
+
*/
|
|
8683
|
+
this.editable = input(false);
|
|
8684
|
+
/**
|
|
8685
|
+
* Включить выбор позиций чекбоксами.
|
|
8686
|
+
*/
|
|
8687
|
+
this.selectable = input(true);
|
|
8688
|
+
/**
|
|
8689
|
+
* Время обработки и принятия заказов (из настроек окружения приложения).
|
|
8690
|
+
*/
|
|
8691
|
+
this.orderProcessingAcceptanceTime = input('');
|
|
8692
|
+
/**
|
|
8693
|
+
* Изменение выбора позиций для оформления.
|
|
8694
|
+
*/
|
|
8695
|
+
this.selectedItemsIdsChange = output();
|
|
8696
|
+
}
|
|
8697
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScOrderDirectionItemsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8698
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.14", type: ScOrderDirectionItemsComponent, isStandalone: true, selector: "sc-order-direction-items", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, orderProcessingAcceptanceTime: { classPropertyName: "orderProcessingAcceptanceTime", publicName: "orderProcessingAcceptanceTime", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedItemsIdsChange: "selectedItemsIdsChange" }, ngImport: i0, template: "<div class=\"flex flex-col gap-5\">\n <ul class=\"ml-4 list-disc text-tui-success-fill\">\n <li>\u0417\u0430\u044F\u0432\u043A\u0438 \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u044E\u0442\u0441\u044F \u043D\u0435 \u043F\u043E\u0437\u0434\u043D\u0435\u0435 {{ orderProcessingAcceptanceTime() }} \u043F\u043B\u0430\u043D\u0438\u0440\u0443\u0435\u043C\u043E\u0433\u043E \u0434\u043D\u044F \u043F\u043E\u0441\u0442\u0430\u0432\u043A\u0438.</li>\n <li>\u0417\u0430\u043A\u0430\u0437\u044B \u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u043E\u0439 \u043D\u0430 \u043F\u043E\u043D\u0435\u0434\u0435\u043B\u044C\u043D\u0438\u043A \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u044E\u0442\u0441\u044F \u0434\u043E {{ orderProcessingAcceptanceTime() }} \u043F\u044F\u0442\u043D\u0438\u0446\u044B.</li>\n <li>\u0417\u0430\u043A\u0430\u0437\u044B, \u0441\u043E\u0437\u0434\u0430\u043D\u043D\u044B\u0435 \u043F\u043E\u0437\u0434\u043D\u0435\u0435 {{ orderProcessingAcceptanceTime() }} \u043F\u044F\u0442\u043D\u0438\u0446\u044B \u0438\u043B\u0438 \u0432 \u0441\u0443\u0431\u0431\u043E\u0442\u0443/\u0432\u043E\u0441\u043A\u0440\u0435\u0441\u0435\u043D\u044C\u0435 \u0431\u0443\u0434\u0443\u0442 \u043E\u0431\u0440\u0430\u0431\u043E\u0442\u0430\u043D\u044B \u0432 \u0431\u0443\u0434\u043D\u0438\u0435 \u0434\u043D\u0438.</li>\n <li>\n \u0423\u043F\u0440\u0430\u0432\u043B\u044F\u0442\u044C \u0441\u043F\u0438\u0441\u043A\u043E\u043C \u043A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\u043E\u0432 \u0432\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u0432\n <a\n tuiLink\n routerLink=\"/profile\"\n >\n \u043B\u0438\u0447\u043D\u043E\u043C \u043A\u0430\u0431\u0438\u043D\u0435\u0442\u0435\n </a>\n .\n </li>\n </ul>\n\n <div class=\"sub-title\">\u0421\u043E\u0441\u0442\u0430\u0432 \u0437\u0430\u043A\u0430\u0437\u0430</div>\n\n <sc-order-items-list-by-directions\n [items]=\"items()\"\n [editable]=\"editable()\"\n [selectable]=\"selectable()\"\n [showContinueButton]=\"false\"\n (selectedItemsIdsChange)=\"selectedItemsIdsChange.emit($event)\"\n >\n <ng-content\n select=\"[footerActions]\"\n ngProjectAs=\"[footerActions]\"\n />\n </sc-order-items-list-by-directions>\n</div>\n", dependencies: [{ kind: "component", type: ScOrderItemsListByDirectionsComponent, selector: "sc-order-items-list-by-directions", inputs: ["items", "selectable", "editable", "showContinueButton", "continueButtonText", "selectedItemsIds"], outputs: ["continueClick", "selectedItemsIdsChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]", inputs: ["pseudo"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8699
|
+
}
|
|
8700
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScOrderDirectionItemsComponent, decorators: [{
|
|
8701
|
+
type: Component,
|
|
8702
|
+
args: [{ standalone: true, selector: 'sc-order-direction-items', imports: [ScOrderItemsListByDirectionsComponent, RouterLink, TuiLink], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"flex flex-col gap-5\">\n <ul class=\"ml-4 list-disc text-tui-success-fill\">\n <li>\u0417\u0430\u044F\u0432\u043A\u0438 \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u044E\u0442\u0441\u044F \u043D\u0435 \u043F\u043E\u0437\u0434\u043D\u0435\u0435 {{ orderProcessingAcceptanceTime() }} \u043F\u043B\u0430\u043D\u0438\u0440\u0443\u0435\u043C\u043E\u0433\u043E \u0434\u043D\u044F \u043F\u043E\u0441\u0442\u0430\u0432\u043A\u0438.</li>\n <li>\u0417\u0430\u043A\u0430\u0437\u044B \u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u043E\u0439 \u043D\u0430 \u043F\u043E\u043D\u0435\u0434\u0435\u043B\u044C\u043D\u0438\u043A \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u044E\u0442\u0441\u044F \u0434\u043E {{ orderProcessingAcceptanceTime() }} \u043F\u044F\u0442\u043D\u0438\u0446\u044B.</li>\n <li>\u0417\u0430\u043A\u0430\u0437\u044B, \u0441\u043E\u0437\u0434\u0430\u043D\u043D\u044B\u0435 \u043F\u043E\u0437\u0434\u043D\u0435\u0435 {{ orderProcessingAcceptanceTime() }} \u043F\u044F\u0442\u043D\u0438\u0446\u044B \u0438\u043B\u0438 \u0432 \u0441\u0443\u0431\u0431\u043E\u0442\u0443/\u0432\u043E\u0441\u043A\u0440\u0435\u0441\u0435\u043D\u044C\u0435 \u0431\u0443\u0434\u0443\u0442 \u043E\u0431\u0440\u0430\u0431\u043E\u0442\u0430\u043D\u044B \u0432 \u0431\u0443\u0434\u043D\u0438\u0435 \u0434\u043D\u0438.</li>\n <li>\n \u0423\u043F\u0440\u0430\u0432\u043B\u044F\u0442\u044C \u0441\u043F\u0438\u0441\u043A\u043E\u043C \u043A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\u043E\u0432 \u0432\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u0432\n <a\n tuiLink\n routerLink=\"/profile\"\n >\n \u043B\u0438\u0447\u043D\u043E\u043C \u043A\u0430\u0431\u0438\u043D\u0435\u0442\u0435\n </a>\n .\n </li>\n </ul>\n\n <div class=\"sub-title\">\u0421\u043E\u0441\u0442\u0430\u0432 \u0437\u0430\u043A\u0430\u0437\u0430</div>\n\n <sc-order-items-list-by-directions\n [items]=\"items()\"\n [editable]=\"editable()\"\n [selectable]=\"selectable()\"\n [showContinueButton]=\"false\"\n (selectedItemsIdsChange)=\"selectedItemsIdsChange.emit($event)\"\n >\n <ng-content\n select=\"[footerActions]\"\n ngProjectAs=\"[footerActions]\"\n />\n </sc-order-items-list-by-directions>\n</div>\n" }]
|
|
8703
|
+
}] });
|
|
8704
|
+
|
|
8705
|
+
/**
|
|
8706
|
+
* Токен настроек {@link ScOrderFormComponent}.
|
|
8707
|
+
* Если не предоставлен, сохранение и восстановление метаданных формы отключены.
|
|
8708
|
+
*/
|
|
8709
|
+
const SC_ORDER_FORM_CONFIG = new InjectionToken('SC_ORDER_FORM_CONFIG');
|
|
8710
|
+
|
|
8711
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion,rxjs/no-sharereplay,@typescript-eslint/no-unsafe-enum-comparison,@typescript-eslint/unbound-method,@typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-argument,security/detect-object-injection */
|
|
8712
|
+
/**
|
|
8713
|
+
* Форма оформления заказа.
|
|
8714
|
+
*/
|
|
8715
|
+
class ScOrderFormComponent {
|
|
8716
|
+
/**
|
|
8717
|
+
* Инициализирует экземпляр класса {@link ScOrderFormComponent}.
|
|
8718
|
+
*/
|
|
8719
|
+
constructor() {
|
|
8720
|
+
/**
|
|
8721
|
+
* Идентификатор направления продаж заказа.
|
|
8722
|
+
*/
|
|
8723
|
+
this.directionId = input.required();
|
|
8724
|
+
/**
|
|
8725
|
+
* Требовать подтверждённые контактные данные для оформления. Для черновика — `false`.
|
|
8726
|
+
*/
|
|
8727
|
+
this.enforceApprovedContacts = input(true);
|
|
8728
|
+
/**
|
|
8729
|
+
* Сохранять и восстанавливать черновые данные формы по направлению (метаданные). Для черновика — `false`.
|
|
8730
|
+
* Работает только если предоставлен токен {@link SC_ORDER_FORM_CONFIG}.
|
|
8731
|
+
*/
|
|
8732
|
+
this.persistMetadata = input(true);
|
|
8733
|
+
/**
|
|
8734
|
+
* Событие отправки валидной формы оформления. Полезная нагрузка — сырые значения формы.
|
|
8735
|
+
*/
|
|
8736
|
+
this.orderSubmit = output();
|
|
8737
|
+
/**
|
|
8738
|
+
* Сервис справочников.
|
|
8739
|
+
*/
|
|
8740
|
+
this.referencesService = inject(ScReferencesService);
|
|
8741
|
+
/**
|
|
8742
|
+
* Сервис работы с контрагентами.
|
|
8743
|
+
*/
|
|
8744
|
+
this.contragentService = inject(ScContragentService);
|
|
8745
|
+
/**
|
|
8746
|
+
* Сервис работы с адресами доставки.
|
|
8747
|
+
*/
|
|
8748
|
+
this.deliveryAddressService = inject(ScDeliveryAddressService);
|
|
8749
|
+
/**
|
|
8750
|
+
* Сервис для работы со складами.
|
|
8751
|
+
*/
|
|
8752
|
+
this.warehouseService = inject(ScWarehouseService);
|
|
8753
|
+
/**
|
|
8754
|
+
* Сервис для работы с заказами (загрузка дат доставки/самовывоза).
|
|
8755
|
+
*/
|
|
8756
|
+
this.ordersService = inject(ScOrdersService);
|
|
8757
|
+
/**
|
|
8758
|
+
* Сервис для работы с UI.
|
|
8759
|
+
*/
|
|
8760
|
+
this.uiService = inject(ScUIService);
|
|
8761
|
+
/**
|
|
8762
|
+
* Сервис конвертации данных.
|
|
8763
|
+
*/
|
|
8764
|
+
this.convertersService = inject(ScConvertersService);
|
|
8765
|
+
/**
|
|
8766
|
+
* Сервис работы с диалоговым окном.
|
|
8767
|
+
*/
|
|
8768
|
+
this.dialog = inject(TuiDialogService);
|
|
8769
|
+
/**
|
|
8770
|
+
* Провайдер данных о терминале.
|
|
8771
|
+
*/
|
|
8772
|
+
this.terminal = inject(IS_RUNNING_ON_TERMINAL);
|
|
8773
|
+
/**
|
|
8774
|
+
* Поток данных о текущем пользователе.
|
|
8775
|
+
*/
|
|
8776
|
+
this.user$ = inject(SC_USER_INFO$1);
|
|
8777
|
+
/**
|
|
8778
|
+
* Настройки формы оформления заказа. Если не предоставлены, метаданные формы не сохраняются.
|
|
8779
|
+
*/
|
|
8780
|
+
this.config = inject(SC_ORDER_FORM_CONFIG, { optional: true });
|
|
8781
|
+
/**
|
|
8782
|
+
* Признак выполнения скрипта на сервере.
|
|
8783
|
+
*/
|
|
8784
|
+
this.isServer = inject(IS_SERVER);
|
|
8785
|
+
/**
|
|
8786
|
+
* Ссылка для автоматического управления уничтожением зависимостей.
|
|
8787
|
+
*/
|
|
8788
|
+
this.destroyRef = inject(DestroyRef);
|
|
8789
|
+
/**
|
|
8790
|
+
* Задержка считывания сигналов формы, для избежания лишних обработок при смене значений.
|
|
8791
|
+
*/
|
|
8792
|
+
this.debounceTimeFormChange = 50;
|
|
8793
|
+
/**
|
|
8794
|
+
* Форма создания заказа.
|
|
8795
|
+
*/
|
|
8796
|
+
this.form = new FormGroup({
|
|
8797
|
+
contragentId: new FormControl(null, Validators.required),
|
|
8798
|
+
paymentType: new FormControl({ value: null, disabled: true }, Validators.required),
|
|
8799
|
+
deliveryType: new FormControl({ value: null, disabled: true }, Validators.required),
|
|
8800
|
+
deliveryDate: new FormControl({ value: null, disabled: true }, [
|
|
8801
|
+
Validators.required,
|
|
8802
|
+
({ value }) => {
|
|
8803
|
+
if (!value || this.deliveryDates().length === 0) {
|
|
8804
|
+
return null;
|
|
8805
|
+
}
|
|
8806
|
+
if (value && !this.deliveryDates().includes(value)) {
|
|
8807
|
+
return { serverResponse: 'Укажите корректную дату, или выберите из активных дат календаря' };
|
|
8808
|
+
}
|
|
8809
|
+
return null;
|
|
8810
|
+
},
|
|
8811
|
+
]),
|
|
8812
|
+
warehouseId: new FormControl({ value: null, disabled: true }, Validators.required),
|
|
8813
|
+
addressId: new FormControl({ value: null, disabled: true }, Validators.required),
|
|
8814
|
+
comment: new FormControl(null),
|
|
8815
|
+
image: new FormControl(null),
|
|
8816
|
+
});
|
|
8817
|
+
/**
|
|
8818
|
+
* Поле файла.
|
|
8819
|
+
*/
|
|
8820
|
+
this.controlFile = new FormControl(null);
|
|
8821
|
+
/**
|
|
8822
|
+
* {@link Observable} списка подтверждённых файлов.
|
|
8823
|
+
*/
|
|
8824
|
+
this.accepted$ = this.controlFile.valueChanges.pipe(map(() => tuiFilesAccepted(this.controlFile)));
|
|
8825
|
+
/**
|
|
8826
|
+
* Признак, что включён режим анимации предупреждения о неподтверждённых данных.
|
|
8827
|
+
*/
|
|
8828
|
+
this.warningShake = signal(false);
|
|
8829
|
+
/**
|
|
8830
|
+
* Признак, что контрагент является физическим лицом.
|
|
8831
|
+
*/
|
|
8832
|
+
this.isIndividual = signal(true);
|
|
8833
|
+
/**
|
|
8834
|
+
* Список возможных дат самовывоза со склада.
|
|
8835
|
+
*/
|
|
8836
|
+
this.warehouseDeliveryDates = signal([]);
|
|
8837
|
+
/**
|
|
8838
|
+
* Список возможных дат доставки.
|
|
8839
|
+
*/
|
|
8840
|
+
this.addressDeliveryDates = signal([]);
|
|
8841
|
+
/**
|
|
8842
|
+
* {@link Observable} списка контрагентов пользователя.
|
|
8843
|
+
*/
|
|
8844
|
+
this.contragents$ = this.contragentService.contragents$;
|
|
8845
|
+
/**
|
|
8846
|
+
* {@link Observable} списка адресов контрагента.
|
|
8847
|
+
*/
|
|
8848
|
+
this.addresses$ = this.deliveryAddressService.deliveryAddresses$.pipe(tap((deliveryAddresses) => {
|
|
8849
|
+
if (deliveryAddresses && this.form.controls.addressId.value && !deliveryAddresses.some((delivery) => delivery.id === this.form.controls.addressId.value)) {
|
|
8850
|
+
this.form.controls.addressId.reset();
|
|
8851
|
+
}
|
|
8852
|
+
}));
|
|
8853
|
+
/**
|
|
8854
|
+
* {@link Observable} списка складов.
|
|
8855
|
+
*/
|
|
8856
|
+
this.warehouses$ = this.warehouseService.getWarehouses$();
|
|
8857
|
+
/**
|
|
8858
|
+
* {@link Observable} ОПФ выбранного контрагента.
|
|
8859
|
+
*/
|
|
8860
|
+
this.opf$ = tuiControlValue(this.form.controls.contragentId).pipe(filter(tuiIsPresent), tap(() => {
|
|
8861
|
+
this.form.controls.paymentType.enable();
|
|
8862
|
+
this.form.controls.deliveryType.enable();
|
|
8863
|
+
}), switchMap((selectContragentId) => this.contragents$.pipe(filter(tuiIsPresent), map((contragents) => contragents.find((contragent) => contragent.id === selectContragentId)), map((contragent) => contragent?.opf), tap((opf) => {
|
|
8864
|
+
this.isIndividual.set(opf?.id === ScOpfList.individual.valueOf());
|
|
8865
|
+
}))), shareReplay(1), takeUntilDestroyed(this.destroyRef));
|
|
8866
|
+
/**
|
|
8867
|
+
* {@link Observable} типов оплаты заказа.
|
|
8868
|
+
*/
|
|
8869
|
+
this.paymentTypes$ = this.opf$.pipe(map((opf) => opf && (opf.id === ScOpfList.individual ? ScPaymentType.beznal2 : ScPaymentType.online)), switchMap((paymentTypeFilter) => this.referencesService.paymentTypes$.pipe(map((paymentTypes) => (paymentTypeFilter ? paymentTypes : [])), map((paymentTypes) => paymentTypes.filter((type) => type.id !== paymentTypeFilter)), tap((paymentTypes) => {
|
|
8870
|
+
if (this.form.controls.paymentType.value && !paymentTypes.some((payment) => payment.id === this.form.controls.paymentType.value)) {
|
|
8871
|
+
this.form.controls.paymentType.reset();
|
|
8872
|
+
}
|
|
8873
|
+
if (!this.form.controls.paymentType.value && paymentTypes.length === 1) {
|
|
8874
|
+
this.form.controls.paymentType.patchValue(paymentTypes[0].id);
|
|
8875
|
+
}
|
|
8876
|
+
}))));
|
|
8877
|
+
/**
|
|
8878
|
+
* {@link Observable} типов доставки заказа.
|
|
8879
|
+
*/
|
|
8880
|
+
this.deliveryTypes$ = this.opf$.pipe(switchMap((opf) => this.referencesService.deliveryTypes$.pipe(map((deliveryTypes) => (opf ? deliveryTypes : [])), switchMap((deliveryTypes) => this.deliveryAddressService.deliveryAddresses$.pipe(map((deliveryAddresses) => opf?.id === ScOpfList.individual && !(deliveryAddresses && deliveryAddresses.length > 0)
|
|
8881
|
+
? deliveryTypes.filter((type) => type.id !== ScDeliveryType.delivery)
|
|
8882
|
+
: deliveryTypes))), tap((deliveryTypes) => {
|
|
8883
|
+
if (this.form.controls.deliveryType.value && !deliveryTypes.some((delivery) => delivery.id === this.form.controls.deliveryType.value)) {
|
|
8884
|
+
this.form.controls.deliveryType.reset();
|
|
8885
|
+
}
|
|
8886
|
+
if (!this.form.controls.deliveryType.value && deliveryTypes.length === 1) {
|
|
8887
|
+
this.form.controls.deliveryType.patchValue(deliveryTypes[0].id);
|
|
8888
|
+
}
|
|
8889
|
+
}))));
|
|
8890
|
+
/**
|
|
8891
|
+
* Признак, что выбран тип оплаты наличными.
|
|
8892
|
+
*/
|
|
8893
|
+
this.isCashPaymentSelected = toSignal(tuiControlValue(this.form.controls.paymentType).pipe(map((paymentType) => paymentType === ScPaymentType.nal)), { initialValue: false });
|
|
8894
|
+
/**
|
|
8895
|
+
* Признак, что номер телефона подтверждён.
|
|
8896
|
+
*/
|
|
8897
|
+
this.isPhoneApproved = toSignal(this.user$.pipe(filter((user) => !user.isGuest), map((user) => user.contacts.phone.isApproved)), { initialValue: true });
|
|
8898
|
+
/**
|
|
8899
|
+
* Признак, что адрес электронной почты подтверждён пользователем.
|
|
8900
|
+
*/
|
|
8901
|
+
this.isEmailApprovedUser = toSignal(this.user$.pipe(filter((user) => !user.isGuest), map((user) => user.contacts.email.isApproved)), { initialValue: true });
|
|
8902
|
+
/**
|
|
8903
|
+
* Признак, что адрес электронной почты подтверждён или контрагент является физическим лицом.
|
|
8904
|
+
*/
|
|
8905
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
8906
|
+
this.isEmailApproved = computed(() => this.isEmailApprovedUser() || this.isIndividual());
|
|
8907
|
+
/**
|
|
8908
|
+
* Значение выбранного типа доставки.
|
|
8909
|
+
*/
|
|
8910
|
+
this.deliveryTypeValue = toSignal(tuiControlValue(this.form.controls.deliveryType), { initialValue: null });
|
|
8911
|
+
/**
|
|
8912
|
+
* Признак, что выбран тип доставки "Доставка".
|
|
8913
|
+
*/
|
|
8914
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
8915
|
+
this.isDelivery = computed(() => this.deliveryTypeValue() === ScDeliveryType.delivery);
|
|
8916
|
+
/**
|
|
8917
|
+
* Набор доступных дат в зависимости от типа доставки.
|
|
8918
|
+
*/
|
|
8919
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
8920
|
+
this.deliveryDates = computed(() => this.deliveryTypeValue() === ScDeliveryType.self_delivery ? this.warehouseDeliveryDates() : this.addressDeliveryDates());
|
|
8921
|
+
/**
|
|
8922
|
+
* Ссылка на элемент с предупреждением о неподтверждённых данных.
|
|
8923
|
+
*/
|
|
8924
|
+
this.unconfirmedDataWarning = viewChild('unconfirmedDataWarning');
|
|
8925
|
+
/**
|
|
8926
|
+
* Возвращает признак, что указанная дата недоступна для выбора.
|
|
8927
|
+
*
|
|
8928
|
+
* @param date Дата.
|
|
8929
|
+
*/
|
|
8930
|
+
this.deliveryDateFilter = (date) => !this.deliveryDates().includes(`${date.toString('YMD', '-')} 00:00:00`);
|
|
8931
|
+
// Автоматически выбираем единственного контрагента-физлицо.
|
|
8932
|
+
this.contragents$
|
|
8933
|
+
.pipe(filter((contragents) => !!contragents && contragents.length === 1), first(), filter(([contragent]) => contragent.opf.id === ScOpfList.individual.valueOf()), takeUntilDestroyed(this.destroyRef))
|
|
8934
|
+
.subscribe(([contragent]) => {
|
|
8935
|
+
this.form.controls.contragentId?.patchValue(contragent.id);
|
|
8936
|
+
});
|
|
8937
|
+
this.initFormChanges();
|
|
8938
|
+
}
|
|
8939
|
+
/** @inheritdoc */
|
|
8940
|
+
ngOnInit() {
|
|
8941
|
+
// Восстанавливаем и сохраняем черновые данные формы по направлению.
|
|
8942
|
+
if (this.persistMetadata()) {
|
|
8943
|
+
this.initMetadata();
|
|
8944
|
+
}
|
|
8945
|
+
}
|
|
8946
|
+
/**
|
|
8947
|
+
* Преобразует объекты в значения, отображаемое в поле ввода.
|
|
8948
|
+
*
|
|
8949
|
+
* @param items Выбранные объекты выпадающего списка.
|
|
8950
|
+
*/
|
|
8951
|
+
// eslint-disable-next-line class-methods-use-this
|
|
8952
|
+
stringify(items) {
|
|
8953
|
+
const itemsMap = new Map(items.map((item) => {
|
|
8954
|
+
// eslint-disable-next-line unicorn/no-nested-ternary,sonarjs/no-nested-conditional
|
|
8955
|
+
const name = 'name' in item ? item.name : 'address' in item ? item.address : '';
|
|
8956
|
+
return [item.id, name];
|
|
8957
|
+
}));
|
|
8958
|
+
return ({ $implicit }) => itemsMap.get($implicit) ?? '';
|
|
8959
|
+
}
|
|
8960
|
+
/**
|
|
8961
|
+
* Обрабатывает отправку формы: валидирует и эмитит данные заказа родителю.
|
|
8962
|
+
*/
|
|
8963
|
+
submit() {
|
|
8964
|
+
this.form.markAllAsTouched();
|
|
8965
|
+
if (!this.form.valid) {
|
|
8966
|
+
return;
|
|
8967
|
+
}
|
|
8968
|
+
const contactsApproved = !this.enforceApprovedContacts() || (this.isPhoneApproved() && this.isEmailApproved());
|
|
8969
|
+
if (!contactsApproved) {
|
|
8970
|
+
this.triggerUnconfirmedWarning();
|
|
8971
|
+
return;
|
|
8972
|
+
}
|
|
8973
|
+
this.orderSubmit.emit(this.form.getRawValue());
|
|
8974
|
+
}
|
|
8975
|
+
/**
|
|
8976
|
+
* Применяет к полям формы ошибки, пришедшие от сервера.
|
|
8977
|
+
*
|
|
8978
|
+
* @param error Ответ сервера с ошибками.
|
|
8979
|
+
*/
|
|
8980
|
+
applyServerErrors(error) {
|
|
8981
|
+
const { errors, message } = error.error;
|
|
8982
|
+
if (errors) {
|
|
8983
|
+
Object.keys(errors).forEach((key) => {
|
|
8984
|
+
if (key === 'deliveryDate' && isArray(errors[key])) {
|
|
8985
|
+
this.form.get(key)?.setErrors({ serverResponse: new TuiValidationError(errors[key].at(1) ?? errors[key].at(0)) });
|
|
8986
|
+
}
|
|
8987
|
+
else {
|
|
8988
|
+
this.form.get(key)?.setErrors({ serverResponse: new TuiValidationError(errors[key]) });
|
|
8989
|
+
}
|
|
8990
|
+
this.form.get(key)?.markAsTouched();
|
|
8991
|
+
});
|
|
8992
|
+
}
|
|
8993
|
+
else if (message) {
|
|
8994
|
+
this.form.setErrors({ serverResponse: new TuiValidationError(message) });
|
|
8995
|
+
}
|
|
8996
|
+
}
|
|
8997
|
+
/**
|
|
8998
|
+
* Удаляет файл из формы заказа.
|
|
8999
|
+
*/
|
|
9000
|
+
removeFile() {
|
|
9001
|
+
this.controlFile.reset();
|
|
9002
|
+
}
|
|
9003
|
+
/**
|
|
9004
|
+
* Открывает диалоговое окно добавления адреса доставки.
|
|
9005
|
+
*/
|
|
9006
|
+
addDeliveryAddress() {
|
|
9007
|
+
this.dialog
|
|
9008
|
+
.open(new PolymorpheusComponent(ScAddDeliveryAddressDialogComponent), {
|
|
9009
|
+
size: 'l',
|
|
9010
|
+
label: 'Добавление адреса доставки',
|
|
9011
|
+
})
|
|
9012
|
+
.subscribe();
|
|
9013
|
+
}
|
|
9014
|
+
/**
|
|
9015
|
+
* Открывает диалоговое окно добавления контрагента.
|
|
9016
|
+
*/
|
|
9017
|
+
addContragent() {
|
|
9018
|
+
this.dialog
|
|
9019
|
+
.open(new PolymorpheusComponent(ScAddContragentDialogComponent), {
|
|
9020
|
+
size: 'm',
|
|
9021
|
+
label: 'Добавление контрагента',
|
|
9022
|
+
})
|
|
9023
|
+
.subscribe();
|
|
9024
|
+
}
|
|
9025
|
+
/**
|
|
9026
|
+
* Запускает анимацию предупреждения о неподтверждённых данных и прокручивает к нему.
|
|
9027
|
+
*/
|
|
9028
|
+
triggerUnconfirmedWarning() {
|
|
9029
|
+
const element = this.unconfirmedDataWarning()?.nativeElement;
|
|
9030
|
+
if (!this.isServer && element) {
|
|
9031
|
+
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
9032
|
+
}
|
|
9033
|
+
this.warningShake.set(false);
|
|
9034
|
+
setTimeout(() => {
|
|
9035
|
+
this.warningShake.set(true);
|
|
9036
|
+
});
|
|
9037
|
+
}
|
|
9038
|
+
/**
|
|
9039
|
+
* Восстанавливает черновые данные формы из метаданных и инициализирует их сохранение.
|
|
9040
|
+
*/
|
|
9041
|
+
initMetadata() {
|
|
9042
|
+
const { config } = this;
|
|
9043
|
+
if (!config) {
|
|
9044
|
+
return;
|
|
9045
|
+
}
|
|
9046
|
+
combineLatest({
|
|
9047
|
+
orderMetadata: this.uiService.getNewOrderMetadata$(this.directionId()),
|
|
9048
|
+
user: this.user$.pipe(filter((user) => !user.isGuest)),
|
|
9049
|
+
})
|
|
9050
|
+
.pipe(first(), takeUntilDestroyed(this.destroyRef))
|
|
9051
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
9052
|
+
.subscribe(({ orderMetadata }) => {
|
|
9053
|
+
let deliveryDate = orderMetadata?.deliveryDate && isValid(parse(orderMetadata.deliveryDate, config.dateFormats.api, new Date())) ? orderMetadata.deliveryDate : null;
|
|
9054
|
+
// Если дата старого формата, то преобразуем её в новый формат.
|
|
9055
|
+
// TODO: Убрать этот блок когда все даты у клиентов встанут в нормальном формате.
|
|
9056
|
+
if (orderMetadata?.deliveryDate && !deliveryDate && isValid(parse(orderMetadata.deliveryDate, config.dateFormats.uiDate, new Date()))) {
|
|
9057
|
+
deliveryDate = format(parse(orderMetadata.deliveryDate, config.dateFormats.uiDate, new Date()), config.dateFormats.api);
|
|
9058
|
+
}
|
|
9059
|
+
if (tuiIsPresent(orderMetadata)) {
|
|
9060
|
+
this.form.patchValue({
|
|
9061
|
+
contragentId: orderMetadata.contragentId,
|
|
9062
|
+
paymentType: orderMetadata.contragentId ? orderMetadata.paymentType : null,
|
|
9063
|
+
deliveryType: orderMetadata.contragentId ? orderMetadata.deliveryType : null,
|
|
9064
|
+
deliveryDate: orderMetadata.contragentId && Boolean(orderMetadata.deliveryType) && deliveryDate ? deliveryDate : null,
|
|
9065
|
+
addressId: orderMetadata.deliveryType === ScDeliveryType.delivery && orderMetadata.addressId ? orderMetadata.addressId : null,
|
|
9066
|
+
warehouseId: orderMetadata.contragentId && Boolean(orderMetadata.deliveryType) ? orderMetadata.warehouseId : null,
|
|
9067
|
+
comment: orderMetadata.comment,
|
|
9068
|
+
});
|
|
9069
|
+
}
|
|
9070
|
+
});
|
|
9071
|
+
this.form.valueChanges.pipe(debounceTime(config.debounceTime), takeUntilDestroyed(this.destroyRef)).subscribe((newOrder) => {
|
|
9072
|
+
this.uiService.setNewOrderMetadata(this.directionId(), this.convertersService.removeNull(newOrder));
|
|
9073
|
+
});
|
|
9074
|
+
}
|
|
9075
|
+
/**
|
|
9076
|
+
* Инициализирует подписки на изменения полей формы.
|
|
9077
|
+
*/
|
|
9078
|
+
initFormChanges() {
|
|
9079
|
+
this.initFileChange();
|
|
9080
|
+
this.initWarehouseChange();
|
|
9081
|
+
this.initDeliveryDatesChange();
|
|
9082
|
+
this.initDateFieldActivationChange();
|
|
9083
|
+
}
|
|
9084
|
+
/**
|
|
9085
|
+
* Инициализирует подписку на изменение поля прикрепления файла.
|
|
9086
|
+
*/
|
|
9087
|
+
initFileChange() {
|
|
9088
|
+
this.controlFile.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((file) => {
|
|
9089
|
+
if (file && this.form.controls.image) {
|
|
9090
|
+
this.onUploadFile(file, this.form.controls.image);
|
|
9091
|
+
}
|
|
9092
|
+
else {
|
|
9093
|
+
this.form.controls.image?.reset();
|
|
9094
|
+
}
|
|
9095
|
+
});
|
|
9096
|
+
}
|
|
9097
|
+
/**
|
|
9098
|
+
* Инициализирует подписку на изменение выбранного склада.
|
|
9099
|
+
*/
|
|
9100
|
+
initWarehouseChange() {
|
|
9101
|
+
this.form.controls.warehouseId.valueChanges
|
|
9102
|
+
.pipe(filter((warehouseId) => tuiIsPresent(warehouseId) && this.warehouseService.getCurrentWarehouseIdSelect() !== warehouseId), debounceTime(0), takeUntilDestroyed(this.destroyRef))
|
|
9103
|
+
.subscribe((id) => {
|
|
9104
|
+
this.warehouseService.setWarehouseIdSelectChange(id);
|
|
9105
|
+
});
|
|
9106
|
+
}
|
|
9107
|
+
/**
|
|
9108
|
+
* Инициализирует подписку на изменение адреса доставки и выбранного склада для получения списка доступных дат доставки.
|
|
9109
|
+
*/
|
|
9110
|
+
initDeliveryDatesChange() {
|
|
9111
|
+
merge(tuiControlValue(this.form.controls.addressId).pipe(filter(tuiIsPresent), debounceTime(this.debounceTimeFormChange), switchMap((addressId) => this.deliveriesByAddress(addressId))), tuiControlValue(this.form.controls.warehouseId).pipe(filter(tuiIsPresent), debounceTime(this.debounceTimeFormChange), filter(() => this.form.controls.deliveryType.value === ScDeliveryType.self_delivery), switchMap((warehouseId) => this.deliveriesByWarehouse(warehouseId))))
|
|
9112
|
+
.pipe(catchError((error) => {
|
|
9113
|
+
this.form.controls.deliveryDate.disable();
|
|
9114
|
+
return throwError(() => error);
|
|
9115
|
+
}), retry(), takeUntilDestroyed(this.destroyRef))
|
|
9116
|
+
.subscribe((deliveryDates) => {
|
|
9117
|
+
const deliveryDateValue = this.form.controls.deliveryDate.value;
|
|
9118
|
+
if (deliveryDateValue && !deliveryDates.includes(deliveryDateValue)) {
|
|
9119
|
+
this.form.controls.deliveryDate.reset();
|
|
9120
|
+
}
|
|
9121
|
+
});
|
|
9122
|
+
}
|
|
9123
|
+
/**
|
|
9124
|
+
* Инициализирует подписку на изменение полей формы для блокирования/активации поля выбора даты.
|
|
9125
|
+
*/
|
|
9126
|
+
initDateFieldActivationChange() {
|
|
9127
|
+
merge(tuiControlValue(this.form.controls.deliveryType), this.form.controls.contragentId?.valueChanges.pipe(filter(() => this.form.controls.deliveryType.value === ScDeliveryType.delivery)) ?? of())
|
|
9128
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
9129
|
+
.subscribe(() => {
|
|
9130
|
+
this.form.controls.deliveryDate.disable();
|
|
9131
|
+
this.form.controls.warehouseId.disable();
|
|
9132
|
+
this.addressDeliveryDates.set([]);
|
|
9133
|
+
if (this.form.controls.deliveryType.value === ScDeliveryType.delivery) {
|
|
9134
|
+
this.form.controls.addressId.enable();
|
|
9135
|
+
this.warehouseService
|
|
9136
|
+
.getDeliveryWarehouse$()
|
|
9137
|
+
.pipe(first(), takeUntilDestroyed(this.destroyRef))
|
|
9138
|
+
// eslint-disable-next-line rxjs/no-nested-subscribe
|
|
9139
|
+
.subscribe((warehouse) => {
|
|
9140
|
+
this.form.controls.warehouseId.patchValue(warehouse.id);
|
|
9141
|
+
});
|
|
9142
|
+
}
|
|
9143
|
+
if (this.form.controls.deliveryType.value === ScDeliveryType.self_delivery) {
|
|
9144
|
+
this.form.controls.addressId.disable();
|
|
9145
|
+
this.form.controls.warehouseId.enable();
|
|
9146
|
+
}
|
|
9147
|
+
});
|
|
9148
|
+
}
|
|
9149
|
+
/**
|
|
9150
|
+
* Запрашивает даты доставки по адресу.
|
|
9151
|
+
*
|
|
9152
|
+
* @param addressId Идентификатор адреса доставки.
|
|
9153
|
+
*/
|
|
9154
|
+
deliveriesByAddress(addressId) {
|
|
9155
|
+
return this.ordersService.getDeliveriesData$(addressId).pipe(catchError((error) => {
|
|
9156
|
+
const message = error instanceof HttpErrorResponse ? error.error.message : undefined;
|
|
9157
|
+
this.form.controls.addressId.setErrors({
|
|
9158
|
+
serverResponse: message ?? `Ошибка сервера: пожалуйста, перезагрузите страницу и/или выполните запрос позже.`,
|
|
9159
|
+
});
|
|
9160
|
+
this.addressDeliveryDates.set([]);
|
|
9161
|
+
return throwError(() => error);
|
|
9162
|
+
}), tap((deliveryDates) => {
|
|
9163
|
+
this.addressDeliveryDates.set(deliveryDates);
|
|
9164
|
+
this.form.controls.deliveryDate.enable();
|
|
9165
|
+
}));
|
|
9166
|
+
}
|
|
9167
|
+
/**
|
|
9168
|
+
* Запрашивает даты самовывоза по складу.
|
|
9169
|
+
*
|
|
9170
|
+
* @param warehouseId Идентификатор склада.
|
|
9171
|
+
*/
|
|
9172
|
+
deliveriesByWarehouse(warehouseId) {
|
|
9173
|
+
return this.ordersService.getSelfDeliveriesData$(warehouseId).pipe(catchError((error) => {
|
|
9174
|
+
const message = error instanceof HttpErrorResponse ? error.error.message : undefined;
|
|
9175
|
+
this.form.controls.warehouseId.setErrors({
|
|
9176
|
+
serverResponse: message ?? `Ошибка сервера: пожалуйста, перезагрузите страницу и/или выполните запрос позже.`,
|
|
9177
|
+
});
|
|
9178
|
+
this.warehouseDeliveryDates.set([]);
|
|
9179
|
+
return throwError(() => error);
|
|
9180
|
+
}), tap((deliveryDates) => {
|
|
9181
|
+
this.warehouseDeliveryDates.set(deliveryDates);
|
|
9182
|
+
this.form.controls.deliveryDate.enable();
|
|
9183
|
+
}));
|
|
9184
|
+
}
|
|
9185
|
+
/**
|
|
9186
|
+
* Загружает файл в форму.
|
|
9187
|
+
*
|
|
9188
|
+
* @param file Файл.
|
|
9189
|
+
* @param filesControl Поле файла заказа.
|
|
9190
|
+
*/
|
|
9191
|
+
// eslint-disable-next-line class-methods-use-this
|
|
9192
|
+
onUploadFile(file, filesControl) {
|
|
9193
|
+
const reader = new FileReader();
|
|
9194
|
+
reader.addEventListener('load', () => {
|
|
9195
|
+
const { result } = reader;
|
|
9196
|
+
if (isString(result)) {
|
|
9197
|
+
filesControl.setValue(new ScUploadedFile(file.name, result));
|
|
9198
|
+
}
|
|
9199
|
+
});
|
|
9200
|
+
reader.readAsDataURL(file);
|
|
9201
|
+
}
|
|
9202
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScOrderFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9203
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ScOrderFormComponent, isStandalone: true, selector: "sc-order-form", inputs: { directionId: { classPropertyName: "directionId", publicName: "directionId", isSignal: true, isRequired: true, transformFunction: null }, enforceApprovedContacts: { classPropertyName: "enforceApprovedContacts", publicName: "enforceApprovedContacts", isSignal: true, isRequired: false, transformFunction: null }, persistMetadata: { classPropertyName: "persistMetadata", publicName: "persistMetadata", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { orderSubmit: "orderSubmit" }, providers: [TERMINAL_PROVIDERS], viewQueries: [{ propertyName: "unconfirmedDataWarning", first: true, predicate: ["unconfirmedDataWarning"], descendants: true, isSignal: true }], ngImport: i0, template: "@let user = user$ | async;\n\n<form\n [formGroup]=\"form\"\n scFocusFirstInvalidField\n [fieldOrder]=\"['contragentId', 'paymentType', 'deliveryType', 'warehouseId', 'addressId', 'deliveryDate', 'comment']\"\n (ngSubmit)=\"submit()\"\n class=\"flex flex-col gap-4\"\n>\n <ng-template #selectLoading> <tui-loader /> </ng-template>\n\n <!-- \u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442. -->\n @if (contragents$ | async; as contragents) {\n @if (contragents.length > 1 || user?.isOrg) {\n <div>\n <label tuiLabel>\n \u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\n <tui-select\n formControlName=\"contragentId\"\n [valueContent]=\"contragents ? stringify(contragents) : selectLoading\"\n >\n \u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\n <tui-data-list *tuiDataList>\n @for (contragent of contragents; track contragent.id) {\n <button\n tuiOption\n [value]=\"contragent.id\"\n >\n {{ contragent.name }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"contragentId\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n <a\n tuiLink\n iconStart=\"@tui.plus\"\n (click)=\"addContragent()\"\n class=\"mt-2 block\"\n >\n \u041D\u043E\u0432\u044B\u0439\n </a>\n </div>\n }\n }\n\n <!-- \u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B. -->\n <label tuiLabel>\n \u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B\n @let paymentTypes = paymentTypes$ | async;\n <tui-select\n formControlName=\"paymentType\"\n [valueContent]=\"paymentTypes ? stringify(paymentTypes) : selectLoading\"\n >\n \u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B\n <tui-data-list *tuiDataList>\n @for (type of paymentTypes; track type.id) {\n <button\n tuiOption\n [value]=\"type.id\"\n >\n {{ type.name }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"paymentType\"\n [error]=\"[] | tuiFieldError | async\"\n />\n @if (isCashPaymentSelected()) {\n <p class=\"text-xs text-tui-status-positive\">\u0417\u0430\u043A\u0430\u0437\u044B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u044F\u0442\u0441\u044F \u043F\u043E \u043F\u0440\u0435\u0434\u043E\u043F\u043B\u0430\u0442\u0435</p>\n }\n </label>\n\n <!-- \u041F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0435 \u043E \u043D\u0435\u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043D\u043D\u044B\u0445 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u043D\u044B\u0445 \u0434\u0430\u043D\u043D\u044B\u0445. -->\n @if (!isPhoneApproved() || !isEmailApproved()) {\n <div\n #unconfirmedDataWarning\n class=\"text-tui-text-negative\"\n [class.warning-shake]=\"warningShake()\"\n >\n \u0412\u043D\u0438\u043C\u0430\u043D\u0438\u0435! \u0414\u043B\u044F \u043E\u0444\u043E\u0440\u043C\u043B\u0435\u043D\u0438\u044F \u0437\u0430\u043A\u0430\u0437\u0430 \u043D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C\n @if (!isPhoneApproved()) {\n <span class=\"font-bold\"> \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0430 </span>\n }\n @if (!isPhoneApproved() && !isEmailApproved()) {\n <span> \u0438 </span>\n }\n @if (!isEmailApproved()) {\n <span class=\"font-bold\"> \u0430\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B </span>\n }\n <a\n tuiLink\n routerLink=\"/profile\"\n >\n \u0432 \u0432\u0430\u0448\u0435\u043C \u043F\u0440\u043E\u0444\u0438\u043B\u0435\n </a>\n </div>\n }\n\n <!-- \u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438. -->\n <label tuiLabel>\n \u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n @let deliveryTypes = deliveryTypes$ | async;\n <tui-select\n formControlName=\"deliveryType\"\n [valueContent]=\"deliveryTypes ? stringify(deliveryTypes) : selectLoading\"\n >\n \u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n <tui-data-list *tuiDataList>\n @for (delivery of deliveryTypes; track delivery.id) {\n <button\n tuiOption\n [value]=\"delivery.id\"\n >\n {{ delivery.name }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"deliveryType\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u0421\u043A\u043B\u0430\u0434. -->\n <label tuiLabel>\n \u0421\u043A\u043B\u0430\u0434\n @let warehouses = warehouses$ | async;\n <tui-select\n formControlName=\"warehouseId\"\n [valueContent]=\"warehouses ? stringify(warehouses) : selectLoading\"\n >\n \u0421\u043A\u043B\u0430\u0434\n <tui-data-list *tuiDataList>\n @if (!terminal.isRunningOnTerminal) {\n @for (warehouse of warehouses; track warehouse.id) {\n <button\n tuiOption\n [value]=\"warehouse.id\"\n >\n {{ warehouse.name }}\n </button>\n }\n } @else {\n @if (warehouseService.getCatalogWarehouseChange$() | async; as terminalWarehouse) {\n <button\n tuiOption\n [value]=\"terminalWarehouse.id\"\n >\n {{ terminalWarehouse.name }}\n </button>\n }\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"warehouseId\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438. -->\n @if (isDelivery()) {\n @let addresses = addresses$ | async;\n <div>\n <label tuiLabel>\n \u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n <tui-select\n formControlName=\"addressId\"\n [valueContent]=\"addresses ? stringify(addresses) : selectLoading\"\n >\n \u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n <tui-data-list *tuiDataList>\n @for (address of addresses; track address.id) {\n <button\n tuiOption\n [value]=\"address.id\"\n >\n {{ address.address }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n @if (addresses && addresses.length === 0) {\n <tui-error error=\"\u0423 \u043A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\u0430 \u043D\u0435\u0442 \u0430\u0434\u0440\u0435\u0441\u0430 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\" />\n }\n <tui-error\n formControlName=\"addressId\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n <a\n tuiLink\n iconStart=\"@tui.plus\"\n (click)=\"addDeliveryAddress()\"\n class=\"mt-2 block\"\n >\n \u041D\u043E\u0432\u044B\u0439\n </a>\n </div>\n }\n\n <!-- \u0414\u0430\u0442\u0430 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438/\u0441\u0430\u043C\u043E\u0432\u044B\u0432\u043E\u0437\u0430. -->\n <label tuiLabel>\n \u0416\u0435\u043B\u0430\u0435\u043C\u0430\u044F \u0434\u0430\u0442\u0430 {{ isDelivery() ? '\u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438' : '\u0441\u0430\u043C\u043E\u0432\u044B\u0432\u043E\u0437\u0430' }}\n <tui-input-date\n formControlName=\"deliveryDate\"\n [disabledItemHandler]=\"deliveryDateFilter\"\n >\n \u0416\u0435\u043B\u0430\u0435\u043C\u0430\u044F \u0434\u0430\u0442\u0430 {{ isDelivery() ? '\u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438' : '\u0441\u0430\u043C\u043E\u0432\u044B\u0432\u043E\u0437\u0430' }}\n </tui-input-date>\n <tui-error\n formControlName=\"deliveryDate\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u043A\u043B\u0438\u0435\u043D\u0442\u0430. -->\n <label tuiLabel>\n \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u043A\u043B\u0438\u0435\u043D\u0442\u0430 \u043A \u0437\u0430\u043A\u0430\u0437\u0443\n <tui-textarea\n formControlName=\"comment\"\n [expandable]=\"true\"\n [rows]=\"15\"\n >\n \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442\n </tui-textarea>\n <tui-error\n formControlName=\"comment\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u041F\u0440\u0438\u043A\u0440\u0435\u043F\u043B\u0435\u043D\u0438\u0435 \u0444\u0430\u0439\u043B\u0430 \u043A \u0437\u0430\u043A\u0430\u0437\u0443. -->\n <div>\n @if (!controlFile.value) {\n <label tuiInputFiles>\n <input\n accept=\"image/*\"\n tuiInputFiles\n [formControl]=\"controlFile\"\n />\n </label>\n }\n\n <tui-files class=\"tui-space_top-1\">\n @if (controlFile.value | tuiFileRejected: { accept: 'image/*' } | async; as file) {\n <tui-file\n state=\"error\"\n [file]=\"file\"\n (remove)=\"removeFile()\"\n />\n }\n\n @for (file of accepted$ | async; track file.name) {\n <tui-file\n [file]=\"file\"\n (remove)=\"removeFile()\"\n />\n }\n </tui-files>\n\n <tui-error\n [error]=\"['maxLength'] | tuiFieldError | async\"\n [formControl]=\"controlFile\"\n />\n <p class=\"tui-form__field-note\">\u041D\u0430\u043F\u0440\u0438\u043C\u0435\u0440, \u0444\u043E\u0442\u043E\u0433\u0440\u0430\u0444\u0438\u044E \u043F\u043E\u0432\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0439 \u0438 \u0434\u0435\u0444\u0444\u0435\u043A\u0442\u043E\u0432, \u0447\u0442\u043E \u043F\u043E\u0441\u043B\u0443\u0436\u0438\u0442 \u0434\u043E\u043A\u0430\u0437\u0430\u0442\u0435\u043B\u044C\u0441\u0442\u0432\u043E\u043C \u043D\u0435\u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044F \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u043E\u0433\u043E \u043A\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0442\u043E\u0432\u0430\u0440\u0430.</p>\n </div>\n</form>\n", dependencies: [{ 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: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "showLoader"] }, { kind: "directive", type: TuiLabel, selector: "label[tuiLabel]" }, { kind: "ngmodule", type: TuiSelectModule }, { kind: "component", type: i3.TuiSelectComponent, selector: "tui-select", inputs: ["stringify", "identityMatcher", "valueContent"] }, { kind: "directive", type: i3.TuiSelectDirective, selector: "tui-select" }, { kind: "component", type: i3$1.TuiDataListComponent, selector: "tui-data-list", inputs: ["emptyContent", "size"] }, { kind: "directive", type: i3$1.TuiDataListDirective, selector: "ng-template[tuiDataList]" }, { kind: "component", type: i3$1.TuiOption, selector: "button[tuiOption]:not([new]), a[tuiOption]:not([new]), label[tuiOption]:not([new])", inputs: ["disabled", "value"] }, { kind: "component", type: TuiError, selector: "tui-error", inputs: ["error"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]", inputs: ["pseudo"] }, { kind: "ngmodule", type: TuiInputDateModule }, { kind: "component", type: i3.TuiInputDateComponent, selector: "tui-input-date:not([multiple])", inputs: ["min", "max", "disabledItemHandler", "markerHandler", "items", "defaultActiveYearMonth"] }, { kind: "directive", type: i3.TuiInputDateDirective, selector: "tui-input-date:not([multiple])" }, { kind: "ngmodule", type: TuiTextareaModule }, { kind: "component", type: i3.TuiTextareaComponent, selector: "tui-textarea", inputs: ["rows", "maxLength", "expandable"] }, { kind: "directive", type: i3.TuiTextareaDirective, selector: "tui-textarea" }, { kind: "component", type: TuiInputFiles, selector: "label[tuiInputFiles]" }, { kind: "directive", type: TuiInputFilesDirective, selector: "input[tuiInputFiles]", outputs: ["reject"] }, { kind: "component", type: TuiFilesComponent, selector: "tui-files", inputs: ["max", "expanded"], outputs: ["expandedChange"] }, { kind: "component", type: TuiFile, selector: "tui-file,a[tuiFile],button[tuiFile]", inputs: ["file", "state", "size", "showDelete", "showSize", "leftContent"], outputs: ["remove"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: TuiFieldErrorPipe, name: "tuiFieldError" }, { kind: "pipe", type: TuiFileRejectedPipe, name: "tuiFileRejected" }, { kind: "directive", type: ScFocusFirstInvalidFieldDirective, selector: "form[formGroup][scFocusFirstInvalidField]", inputs: ["fieldOrder"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9204
|
+
}
|
|
9205
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScOrderFormComponent, decorators: [{
|
|
9206
|
+
type: Component,
|
|
9207
|
+
args: [{ standalone: true, selector: 'sc-order-form', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
9208
|
+
FormsModule,
|
|
9209
|
+
ReactiveFormsModule,
|
|
9210
|
+
RouterLink,
|
|
9211
|
+
TuiLoader,
|
|
9212
|
+
TuiLabel,
|
|
9213
|
+
TuiSelectModule,
|
|
9214
|
+
TuiDataListDirective,
|
|
9215
|
+
TuiDataListComponent,
|
|
9216
|
+
TuiOption,
|
|
9217
|
+
TuiError,
|
|
9218
|
+
TuiLink,
|
|
9219
|
+
TuiInputDateModule,
|
|
9220
|
+
TuiTextareaModule,
|
|
9221
|
+
TuiInputFiles,
|
|
9222
|
+
TuiInputFilesDirective,
|
|
9223
|
+
TuiFilesComponent,
|
|
9224
|
+
TuiFile,
|
|
9225
|
+
AsyncPipe,
|
|
9226
|
+
TuiFieldErrorPipe,
|
|
9227
|
+
TuiFileRejectedPipe,
|
|
9228
|
+
ScFocusFirstInvalidFieldDirective,
|
|
9229
|
+
], providers: [TERMINAL_PROVIDERS], template: "@let user = user$ | async;\n\n<form\n [formGroup]=\"form\"\n scFocusFirstInvalidField\n [fieldOrder]=\"['contragentId', 'paymentType', 'deliveryType', 'warehouseId', 'addressId', 'deliveryDate', 'comment']\"\n (ngSubmit)=\"submit()\"\n class=\"flex flex-col gap-4\"\n>\n <ng-template #selectLoading> <tui-loader /> </ng-template>\n\n <!-- \u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442. -->\n @if (contragents$ | async; as contragents) {\n @if (contragents.length > 1 || user?.isOrg) {\n <div>\n <label tuiLabel>\n \u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\n <tui-select\n formControlName=\"contragentId\"\n [valueContent]=\"contragents ? stringify(contragents) : selectLoading\"\n >\n \u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\n <tui-data-list *tuiDataList>\n @for (contragent of contragents; track contragent.id) {\n <button\n tuiOption\n [value]=\"contragent.id\"\n >\n {{ contragent.name }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"contragentId\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n <a\n tuiLink\n iconStart=\"@tui.plus\"\n (click)=\"addContragent()\"\n class=\"mt-2 block\"\n >\n \u041D\u043E\u0432\u044B\u0439\n </a>\n </div>\n }\n }\n\n <!-- \u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B. -->\n <label tuiLabel>\n \u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B\n @let paymentTypes = paymentTypes$ | async;\n <tui-select\n formControlName=\"paymentType\"\n [valueContent]=\"paymentTypes ? stringify(paymentTypes) : selectLoading\"\n >\n \u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B\n <tui-data-list *tuiDataList>\n @for (type of paymentTypes; track type.id) {\n <button\n tuiOption\n [value]=\"type.id\"\n >\n {{ type.name }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"paymentType\"\n [error]=\"[] | tuiFieldError | async\"\n />\n @if (isCashPaymentSelected()) {\n <p class=\"text-xs text-tui-status-positive\">\u0417\u0430\u043A\u0430\u0437\u044B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u044F\u0442\u0441\u044F \u043F\u043E \u043F\u0440\u0435\u0434\u043E\u043F\u043B\u0430\u0442\u0435</p>\n }\n </label>\n\n <!-- \u041F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0435 \u043E \u043D\u0435\u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043D\u043D\u044B\u0445 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u043D\u044B\u0445 \u0434\u0430\u043D\u043D\u044B\u0445. -->\n @if (!isPhoneApproved() || !isEmailApproved()) {\n <div\n #unconfirmedDataWarning\n class=\"text-tui-text-negative\"\n [class.warning-shake]=\"warningShake()\"\n >\n \u0412\u043D\u0438\u043C\u0430\u043D\u0438\u0435! \u0414\u043B\u044F \u043E\u0444\u043E\u0440\u043C\u043B\u0435\u043D\u0438\u044F \u0437\u0430\u043A\u0430\u0437\u0430 \u043D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C\n @if (!isPhoneApproved()) {\n <span class=\"font-bold\"> \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0430 </span>\n }\n @if (!isPhoneApproved() && !isEmailApproved()) {\n <span> \u0438 </span>\n }\n @if (!isEmailApproved()) {\n <span class=\"font-bold\"> \u0430\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B </span>\n }\n <a\n tuiLink\n routerLink=\"/profile\"\n >\n \u0432 \u0432\u0430\u0448\u0435\u043C \u043F\u0440\u043E\u0444\u0438\u043B\u0435\n </a>\n </div>\n }\n\n <!-- \u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438. -->\n <label tuiLabel>\n \u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n @let deliveryTypes = deliveryTypes$ | async;\n <tui-select\n formControlName=\"deliveryType\"\n [valueContent]=\"deliveryTypes ? stringify(deliveryTypes) : selectLoading\"\n >\n \u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n <tui-data-list *tuiDataList>\n @for (delivery of deliveryTypes; track delivery.id) {\n <button\n tuiOption\n [value]=\"delivery.id\"\n >\n {{ delivery.name }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"deliveryType\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u0421\u043A\u043B\u0430\u0434. -->\n <label tuiLabel>\n \u0421\u043A\u043B\u0430\u0434\n @let warehouses = warehouses$ | async;\n <tui-select\n formControlName=\"warehouseId\"\n [valueContent]=\"warehouses ? stringify(warehouses) : selectLoading\"\n >\n \u0421\u043A\u043B\u0430\u0434\n <tui-data-list *tuiDataList>\n @if (!terminal.isRunningOnTerminal) {\n @for (warehouse of warehouses; track warehouse.id) {\n <button\n tuiOption\n [value]=\"warehouse.id\"\n >\n {{ warehouse.name }}\n </button>\n }\n } @else {\n @if (warehouseService.getCatalogWarehouseChange$() | async; as terminalWarehouse) {\n <button\n tuiOption\n [value]=\"terminalWarehouse.id\"\n >\n {{ terminalWarehouse.name }}\n </button>\n }\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"warehouseId\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438. -->\n @if (isDelivery()) {\n @let addresses = addresses$ | async;\n <div>\n <label tuiLabel>\n \u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n <tui-select\n formControlName=\"addressId\"\n [valueContent]=\"addresses ? stringify(addresses) : selectLoading\"\n >\n \u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n <tui-data-list *tuiDataList>\n @for (address of addresses; track address.id) {\n <button\n tuiOption\n [value]=\"address.id\"\n >\n {{ address.address }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n @if (addresses && addresses.length === 0) {\n <tui-error error=\"\u0423 \u043A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\u0430 \u043D\u0435\u0442 \u0430\u0434\u0440\u0435\u0441\u0430 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\" />\n }\n <tui-error\n formControlName=\"addressId\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n <a\n tuiLink\n iconStart=\"@tui.plus\"\n (click)=\"addDeliveryAddress()\"\n class=\"mt-2 block\"\n >\n \u041D\u043E\u0432\u044B\u0439\n </a>\n </div>\n }\n\n <!-- \u0414\u0430\u0442\u0430 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438/\u0441\u0430\u043C\u043E\u0432\u044B\u0432\u043E\u0437\u0430. -->\n <label tuiLabel>\n \u0416\u0435\u043B\u0430\u0435\u043C\u0430\u044F \u0434\u0430\u0442\u0430 {{ isDelivery() ? '\u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438' : '\u0441\u0430\u043C\u043E\u0432\u044B\u0432\u043E\u0437\u0430' }}\n <tui-input-date\n formControlName=\"deliveryDate\"\n [disabledItemHandler]=\"deliveryDateFilter\"\n >\n \u0416\u0435\u043B\u0430\u0435\u043C\u0430\u044F \u0434\u0430\u0442\u0430 {{ isDelivery() ? '\u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438' : '\u0441\u0430\u043C\u043E\u0432\u044B\u0432\u043E\u0437\u0430' }}\n </tui-input-date>\n <tui-error\n formControlName=\"deliveryDate\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u043A\u043B\u0438\u0435\u043D\u0442\u0430. -->\n <label tuiLabel>\n \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u043A\u043B\u0438\u0435\u043D\u0442\u0430 \u043A \u0437\u0430\u043A\u0430\u0437\u0443\n <tui-textarea\n formControlName=\"comment\"\n [expandable]=\"true\"\n [rows]=\"15\"\n >\n \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442\n </tui-textarea>\n <tui-error\n formControlName=\"comment\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u041F\u0440\u0438\u043A\u0440\u0435\u043F\u043B\u0435\u043D\u0438\u0435 \u0444\u0430\u0439\u043B\u0430 \u043A \u0437\u0430\u043A\u0430\u0437\u0443. -->\n <div>\n @if (!controlFile.value) {\n <label tuiInputFiles>\n <input\n accept=\"image/*\"\n tuiInputFiles\n [formControl]=\"controlFile\"\n />\n </label>\n }\n\n <tui-files class=\"tui-space_top-1\">\n @if (controlFile.value | tuiFileRejected: { accept: 'image/*' } | async; as file) {\n <tui-file\n state=\"error\"\n [file]=\"file\"\n (remove)=\"removeFile()\"\n />\n }\n\n @for (file of accepted$ | async; track file.name) {\n <tui-file\n [file]=\"file\"\n (remove)=\"removeFile()\"\n />\n }\n </tui-files>\n\n <tui-error\n [error]=\"['maxLength'] | tuiFieldError | async\"\n [formControl]=\"controlFile\"\n />\n <p class=\"tui-form__field-note\">\u041D\u0430\u043F\u0440\u0438\u043C\u0435\u0440, \u0444\u043E\u0442\u043E\u0433\u0440\u0430\u0444\u0438\u044E \u043F\u043E\u0432\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0439 \u0438 \u0434\u0435\u0444\u0444\u0435\u043A\u0442\u043E\u0432, \u0447\u0442\u043E \u043F\u043E\u0441\u043B\u0443\u0436\u0438\u0442 \u0434\u043E\u043A\u0430\u0437\u0430\u0442\u0435\u043B\u044C\u0441\u0442\u0432\u043E\u043C \u043D\u0435\u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044F \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u043E\u0433\u043E \u043A\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0442\u043E\u0432\u0430\u0440\u0430.</p>\n </div>\n</form>\n" }]
|
|
9230
|
+
}], ctorParameters: () => [] });
|
|
9231
|
+
|
|
8642
9232
|
/**
|
|
8643
9233
|
* Компонент списка товаров, разбитых по наличию на складе:
|
|
8644
9234
|
* - в наличии на складе;
|
|
@@ -10391,5 +10981,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
10391
10981
|
* Generated bundle index. Do not edit.
|
|
10392
10982
|
*/
|
|
10393
10983
|
|
|
10394
|
-
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_FAQ_GROUP_QUERY_PARAM, SC_FAQ_PAGE_QUERY_PARAM, 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, ScCatalogFilterCollapsibleComponent, 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, ScPaginationLinksComponent, 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, cleanupRecaptchaArtifacts, phoneValidator, scAtLeastOneRequiredValidator, scBicValidator, scClientUiIconsName, scCorrespondentAccountValidator, scGetCurrentRoute, scGetFaqGroupQueryParams, scPasswordConfirmMatchingValidator, stepValidator, tuiDateValueTransformerDefaultProvider };
|
|
10984
|
+
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_FAQ_GROUP_QUERY_PARAM, SC_FAQ_PAGE_QUERY_PARAM, 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_FORM_CONFIG, 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, ScCatalogFilterCollapsibleComponent, 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, ScOrderDirectionItemsComponent, ScOrderFormComponent, ScOrderItemComponent, ScOrderItemsByDirection, ScOrderItemsListByDirectionsComponent, ScOrderItemsListByStockComponent, ScOrderItemsListComponent, ScOrderModule, ScPaginationLinksComponent, 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, cleanupRecaptchaArtifacts, phoneValidator, scAtLeastOneRequiredValidator, scBicValidator, scClientUiIconsName, scCorrespondentAccountValidator, scGetCurrentRoute, scGetFaqGroupQueryParams, scPasswordConfirmMatchingValidator, stepValidator, tuiDateValueTransformerDefaultProvider };
|
|
10395
10985
|
//# sourceMappingURL=snabcentr-client-ui.mjs.map
|