@snabcentr/client-ui 5.9.0 → 5.15.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/fesm2022/snabcentr-client-ui.mjs +1070 -333
- package/fesm2022/snabcentr-client-ui.mjs.map +1 -1
- package/package.json +3 -3
- package/release_notes.tmp +12 -4
- package/styles/tailwind/tailwind.scss +62 -2
- package/types/snabcentr-client-ui.d.ts +663 -112
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, Injectable, NgZone, EventEmitter, Output, Input, ChangeDetectionStrategy, Component, signal, ChangeDetectorRef, Directive, Pipe, ElementRef, Renderer2, HostListener, input, computed, model, output, DestroyRef, effect, ViewChild, ContentChild, viewChild, HostBinding, ContentChildren, forwardRef, contentChild, TemplateRef, RESPONSE_INIT, ViewEncapsulation } from '@angular/core';
|
|
3
|
-
import { ScContactsService, ScUserService, ScLocationsService, ScSuggestionService, ScISuggestionType, SC_MIN_LENGTH_SEARCH_TERM, ScAuthService, SEARCH_TERM, ScUnitsHelper, ScImageHelper, SC_PATH_IMAGE_NOT_FOUND, ScImage, ScPhoneService, ScUserMetrikaService, ScUserMetrikaGoalsEnum, ScVCardService, IS_RUNNING_ON_TERMINAL, ScVerificationService, ScConvertersService, ScReferencesService, ScOpfList, ScBannerService, ScMediaImageTransformerPipe, ScCartService, ScUploadedFile, loadingPlaceholder, SC_ORDER_LOADER, ScMimeTypes, ScCatalogService, ScWarehouseService, SEARCH_TERM_PROVIDERS, ScPaginationService, SC_NEXT_PAGE_PAGINATION_CLICK, SC_PRODUCT_PAGINATION_OPTIONS, ScCatalogFilterService, ScIdOrSlugPipe, SC_CATEGORY_INFO, ScConfiguratorService, ScContragentService, ScDeliveryAddressService, SC_URLS, IS_SERVER, ScIconTypesEnum, ScDocumentInfoTypesEnum, ScFilesService, ScOrdersService, ScUIService, SC_USER_INFO as SC_USER_INFO$1, ScPaymentType, ScDeliveryType, TERMINAL_PROVIDERS, ScOrderDraftsService, ScRouteKeys, ScSeoService, scOrderIsLoaded, SC_PAGE_QUERY_PARAM, ScFrequentlyAskedQuestionsService, SchemaOrgFactory, scGetPageQueryParamChanges, ScNewsService, SC_COMPANY_INFO, ScFeedbackService } from '@snabcentr/client-core';
|
|
4
|
-
import { EMPTY, BehaviorSubject, switchMap, of, shareReplay, filter, map, debounceTime, startWith, catchError, throwError, share, Subject, tap, finalize, timer, scan, takeWhile, endWith, distinctUntilChanged, combineLatest,
|
|
2
|
+
import { InjectionToken, inject, Injectable, NgZone, RendererFactory2, EventEmitter, Output, Input, ChangeDetectionStrategy, Component, signal, ChangeDetectorRef, Directive, Pipe, ElementRef, Renderer2, HostListener, input, computed, model, output, DestroyRef, effect, ViewChild, ContentChild, viewChild, HostBinding, ContentChildren, forwardRef, contentChild, TemplateRef, RESPONSE_INIT, ViewEncapsulation, Injector, viewChildren, afterNextRender } from '@angular/core';
|
|
3
|
+
import { ScContactsService, ScUserService, ScLocationsService, IS_BROWSER, ScSuggestionService, ScISuggestionType, SC_MIN_LENGTH_SEARCH_TERM, ScAuthService, SEARCH_TERM, ScUnitsHelper, ScImageHelper, SC_PATH_IMAGE_NOT_FOUND, ScImage, ScPhoneService, ScUserMetrikaService, ScUserMetrikaGoalsEnum, ScVCardService, IS_RUNNING_ON_TERMINAL, ScVerificationService, ScConvertersService, ScReferencesService, ScOpfList, ScNumberHelper, ScBannerService, ScMediaImageTransformerPipe, ScCartService, ScUploadedFile, loadingPlaceholder, SC_ORDER_LOADER, ScMimeTypes, ScCatalogService, ScWarehouseService, SEARCH_TERM_PROVIDERS, ScPaginationService, SC_NEXT_PAGE_PAGINATION_CLICK, SC_PRODUCT_PAGINATION_OPTIONS, ScCatalogFilterService, ScIdOrSlugPipe, SC_CATEGORY_INFO, ScConfiguratorService, ScContragentService, ScDeliveryAddressService, SC_URLS, IS_SERVER, ScIconTypesEnum, ScDocumentInfoTypesEnum, ScFilesService, ScOrdersService, ScUIService, SC_USER_INFO as SC_USER_INFO$1, ScPaymentType, ScDeliveryType, TERMINAL_PROVIDERS, ScOrderDraftsService, ScRouteKeys, ScSeoService, scOrderIsLoaded, SC_PAGE_QUERY_PARAM, ScFrequentlyAskedQuestionsService, SchemaOrgFactory, scGetPageQueryParamChanges, ScNewsService, SC_COMPANY_INFO, ScFeedbackService } from '@snabcentr/client-core';
|
|
4
|
+
import { EMPTY, BehaviorSubject, switchMap, of, shareReplay, filter, map, Observable, debounceTime, startWith, catchError, throwError, share, Subject, tap, finalize, timer, scan, takeWhile, endWith, distinctUntilChanged, combineLatest, pairwise, Subscription, merge, skip, from, concatMap, noop as noop$1, first, retry, fromEvent, animationFrames, take, takeUntil, defer, timeout, ignoreElements } from 'rxjs';
|
|
5
5
|
import { WA_WINDOW, WA_NAVIGATOR } from '@ng-web-apis/common';
|
|
6
6
|
import { takeUntilDestroyed, toSignal, outputFromObservable, toObservable } from '@angular/core/rxjs-interop';
|
|
7
|
-
import { tuiIsPresent, TuiDay, TuiTime, TuiValueTransformer, tuiControlValue, tuiMarkControlAsTouchedAndValidate, TuiAutoFocus, TuiHovered, TuiDayRange, TuiMonth, tuiProvide, TuiValidationError, tuiClamp,
|
|
7
|
+
import { tuiIsPresent, TuiDay, TuiTime, TuiValueTransformer, tuiControlValue, tuiMarkControlAsTouchedAndValidate, TuiAutoFocus, TuiHovered, TuiDayRange, TuiMonth, tuiProvide, TuiValidationError, TUI_WINDOW_SIZE, tuiClamp, tuiZonefree, TUI_TRUE_HANDLER } from '@taiga-ui/cdk';
|
|
8
8
|
import * as i1$1 from '@taiga-ui/kit';
|
|
9
9
|
import { tuiInputDateOptionsProvider, TuiAvatar, TuiInitialsPipe, TuiButtonLoading, TuiSortCountriesPipe, TuiPush, TuiInputPhoneInternational, TuiPassword, TuiChevron, TuiSelect, TuiDataListWrapperComponent, TuiStringifyContentPipe, TuiComboBox, TuiStepper, TuiAccordionDirective, TuiAccordion, TuiFiles, TuiChip, TuiInputNumber, TuiLineClamp, TuiBadge, TuiInputNumberDirective, TuiTooltip, TuiHighlight, TuiFade, TuiRange, tuiInputNumberOptionsProvider, TuiInputSlider, TuiPushComponent, TuiTreeService, TuiTreeItemContent, TUI_TREE_START, TUI_TREE_CONTENT, TUI_TREE_LOADING, TuiTreeComponent, TuiTreeChildren, TuiTreeControllerDirective, TUI_TREE_LOADER, TuiPreviewDialogService, TuiPreview, tuiFilesAccepted, TuiInputDate, TuiTextarea, TUI_CONFIRM, TuiDataListWrapper, TUI_PAGINATION_TEXTS, TuiInputPhone } from '@taiga-ui/kit';
|
|
10
|
+
import * as i1$2 from '@angular/common';
|
|
11
|
+
import { DOCUMENT, AsyncPipe, NgTemplateOutlet, NgClass, CommonModule } from '@angular/common';
|
|
10
12
|
import { HttpErrorResponse, HttpClient } from '@angular/common/http';
|
|
11
13
|
import * as i1 from '@angular/forms';
|
|
12
14
|
import { NgControl, FormControl, FormGroupDirective, ReactiveFormsModule, FormGroup, Validators, FormsModule, FormArray, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
13
15
|
import * as i2 from '@taiga-ui/core';
|
|
14
|
-
import { TUI_DATA_LIST_HOST, TuiLoader, TuiDataList, TuiDialogService, TuiLink, TuiButton, TuiIcon, TuiAppearance, TuiWithAppearance, TuiIcons, TuiWithIcons, TuiLabel, TuiTextfield, TuiInput, TuiError, TuiCheckbox, tuiDropdownOptionsProvider, TuiOption, TuiFilterByInputPipe, TuiCarouselComponent, TuiCarousel, TuiNumberFormat, TuiHint, TuiHintDirective, TuiHintDriver, TuiHintHover, TuiHintPosition, TUI_MONTHS, TuiScrollbar, tuiNumberFormatProvider, tuiItemsHandlersProvider, TuiNotification, TuiTitle,
|
|
15
|
-
import * as i1$2 from '@angular/common';
|
|
16
|
-
import { AsyncPipe, DOCUMENT, NgTemplateOutlet, NgClass, CommonModule, DecimalPipe } from '@angular/common';
|
|
16
|
+
import { TUI_DATA_LIST_HOST, TuiLoader, TuiDataList, TuiDialogService, TuiLink, TuiButton, TuiIcon, TuiAppearance, TuiWithAppearance, TuiIcons, TuiWithIcons, TuiLabel, TuiTextfield, TuiInput, TuiError, TuiCheckbox, tuiDropdownOptionsProvider, TuiOption, TuiFilterByInputPipe, TuiCarouselComponent, TuiCarousel, TuiNumberFormat, TuiFormatNumberPipe, TuiHint, TuiHintDirective, TuiHintDriver, TuiHintHover, TuiHintPosition, TUI_MONTHS, TuiScrollbar, tuiNumberFormatProvider, tuiItemsHandlersProvider, TuiNotification, TuiTitle, tuiTextfieldOptionsProvider, tuiHintOptionsProvider, TuiNotificationService, TuiIconPipe, TUI_BUTTON_DEFAULT_OPTIONS, TUI_BUTTON_OPTIONS, TUI_COMMON_ICONS } from '@taiga-ui/core';
|
|
17
17
|
import { isValidPhoneNumber } from 'libphonenumber-js/max';
|
|
18
18
|
import { MaskitoDirective } from '@maskito/angular';
|
|
19
19
|
import { getCountries } from 'libphonenumber-js';
|
|
@@ -33,7 +33,6 @@ import { TuiElasticContainer, TuiCardLarge, TuiBlockStatusComponent, TuiBlockSta
|
|
|
33
33
|
import * as i2$1 from '@taiga-ui/core/components/expand';
|
|
34
34
|
import { WaIntersectionObserverService } from '@ng-web-apis/intersection-observer';
|
|
35
35
|
import * as i2$2 from '@taiga-ui/cdk/directives/item';
|
|
36
|
-
import { TuiAmountPipe, TuiCurrencyPipe } from '@taiga-ui/addon-commerce';
|
|
37
36
|
import * as i3$1 from '@taiga-ui/core/components/textfield';
|
|
38
37
|
import { RouterLink, RouterModule, ActivatedRoute, Router, NavigationStart } from '@angular/router';
|
|
39
38
|
import * as i2$3 from '@taiga-ui/core/components/label';
|
|
@@ -42,10 +41,10 @@ import { TuiAxes, TuiLineDaysChart } from '@taiga-ui/addon-charts';
|
|
|
42
41
|
import { tuiPure } from '@taiga-ui/legacy';
|
|
43
42
|
import * as i6 from '@taiga-ui/core/components/slider';
|
|
44
43
|
import { YaMapComponent } from 'angular8-yandex-maps';
|
|
44
|
+
import { TuiCurrencyPipe } from '@taiga-ui/addon-commerce';
|
|
45
45
|
import { isValid, parse, format } from 'date-fns';
|
|
46
46
|
import * as i6$1 from '@taiga-ui/core/components/calendar';
|
|
47
|
-
import
|
|
48
|
-
import { RecaptchaComponent, RecaptchaFormsModule, RecaptchaModule } from 'ng-recaptcha-2';
|
|
47
|
+
import { Clipboard } from '@angular/cdk/clipboard';
|
|
49
48
|
|
|
50
49
|
/**
|
|
51
50
|
* Поток для закрытия уведомлений помощи.
|
|
@@ -333,36 +332,6 @@ const SC_HIDDEN_PRINT_ELEMENTS = new InjectionToken('SC_HIDDEN_PRINT_ELEMENTS',
|
|
|
333
332
|
providedIn: 'root',
|
|
334
333
|
});
|
|
335
334
|
|
|
336
|
-
/**
|
|
337
|
-
* Селектор iframe reCAPTCHA.
|
|
338
|
-
*/
|
|
339
|
-
const RECAPTCHA_IFRAME_SELECTOR = 'iframe[src*="recaptcha"]';
|
|
340
|
-
/**
|
|
341
|
-
* Селектор хоста reCAPTCHA.
|
|
342
|
-
*/
|
|
343
|
-
const RECAPTCHA_HOST_SELECTOR = 're-captcha';
|
|
344
|
-
/**
|
|
345
|
-
* Освобождает ресурсы reCAPTCHA и удаляет осиротевшие iframe после смены маршрута.
|
|
346
|
-
*
|
|
347
|
-
* @param documentReference Объект документа.
|
|
348
|
-
* @param windowReference Объект окна браузера.
|
|
349
|
-
*/
|
|
350
|
-
function cleanupRecaptchaArtifacts(documentReference, windowReference) {
|
|
351
|
-
const windowWithRecaptcha = windowReference;
|
|
352
|
-
try {
|
|
353
|
-
windowWithRecaptcha.grecaptcha?.reset();
|
|
354
|
-
}
|
|
355
|
-
catch {
|
|
356
|
-
// Ошибки reCAPTCHA не должны блокировать навигацию.
|
|
357
|
-
}
|
|
358
|
-
documentReference.querySelectorAll(RECAPTCHA_IFRAME_SELECTOR).forEach((iframe) => {
|
|
359
|
-
if (iframe.closest(RECAPTCHA_HOST_SELECTOR)) {
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
iframe.remove();
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
|
|
366
335
|
/**
|
|
367
336
|
* Сервис по работе с печатью страницы.
|
|
368
337
|
*/
|
|
@@ -408,6 +377,107 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
408
377
|
}]
|
|
409
378
|
}] });
|
|
410
379
|
|
|
380
|
+
/**
|
|
381
|
+
* Сервис для вставки в {@link Document} внешних и дополнительных скриптов.
|
|
382
|
+
*/
|
|
383
|
+
class ScScriptsService {
|
|
384
|
+
constructor() {
|
|
385
|
+
/**
|
|
386
|
+
* Объект {@link Document}, предоставляющий доступ к DOM страницы.
|
|
387
|
+
*/
|
|
388
|
+
this.document = inject(DOCUMENT);
|
|
389
|
+
/**
|
|
390
|
+
* Объект {@link Renderer2}, предоставляющий доступ к DOM страницы.
|
|
391
|
+
*/
|
|
392
|
+
this.renderer = inject(RendererFactory2).createRenderer(null, null);
|
|
393
|
+
/**
|
|
394
|
+
* Признак того, что скрипт выполняется в браузере.
|
|
395
|
+
*/
|
|
396
|
+
this.isBrowser = inject(IS_BROWSER);
|
|
397
|
+
/**
|
|
398
|
+
* {@link NgZone} для вставки скриптов вне зоны Angular.
|
|
399
|
+
*/
|
|
400
|
+
this.ngZone = inject(NgZone);
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Вставляет в конец {@link Document.body} скрипты, заданные строками HTML, вне зоны Angular. Из каждой строки берётся первый `<script>`. На сервере ничего не делает.
|
|
404
|
+
* Принимает только доверенные строки из конфигурации приложения: строка разбирается как HTML и может выполнить код.
|
|
405
|
+
*
|
|
406
|
+
* @param scriptStrings Строки HTML скриптов.
|
|
407
|
+
*/
|
|
408
|
+
appendScripts(scriptStrings) {
|
|
409
|
+
if (!this.isBrowser) {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
this.ngZone.runOutsideAngular(() => {
|
|
413
|
+
scriptStrings.forEach((scriptString) => {
|
|
414
|
+
const script = this.createScript(scriptString);
|
|
415
|
+
if (script) {
|
|
416
|
+
this.renderer.appendChild(this.document.body, script);
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Загружает внешний скрипт: при подписке добавляет его в {@link Document.head}, после загрузки выдаёт элемент скрипта и завершается.
|
|
423
|
+
* Если скрипт не загрузился или подписка отменена раньше, удаляет его со страницы; удаление не отменяет загрузку и выполнение уже вставленного скрипта. На сервере завершается без загрузки.
|
|
424
|
+
*
|
|
425
|
+
* @param url Адрес скрипта.
|
|
426
|
+
*/
|
|
427
|
+
loadScript$(url) {
|
|
428
|
+
if (!this.isBrowser) {
|
|
429
|
+
return EMPTY;
|
|
430
|
+
}
|
|
431
|
+
return new Observable((subscriber) => {
|
|
432
|
+
const script = this.renderer.createElement('script');
|
|
433
|
+
let isLoaded = false;
|
|
434
|
+
const unlistenLoad = this.renderer.listen(script, 'load', () => {
|
|
435
|
+
isLoaded = true;
|
|
436
|
+
subscriber.next(script);
|
|
437
|
+
subscriber.complete();
|
|
438
|
+
});
|
|
439
|
+
const unlistenError = this.renderer.listen(script, 'error', () => {
|
|
440
|
+
subscriber.error(new Error(`Failed to load script ${url}`));
|
|
441
|
+
});
|
|
442
|
+
this.renderer.setProperty(script, 'src', url);
|
|
443
|
+
this.renderer.appendChild(this.document.head, script);
|
|
444
|
+
return () => {
|
|
445
|
+
unlistenLoad();
|
|
446
|
+
unlistenError();
|
|
447
|
+
if (!isLoaded) {
|
|
448
|
+
this.removeScript(script);
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Удаляет скрипт со страницы. При подключённых анимациях Angular узел удаляется при ближайшей проверке изменений.
|
|
455
|
+
*
|
|
456
|
+
* @param script Элемент скрипта.
|
|
457
|
+
*/
|
|
458
|
+
removeScript(script) {
|
|
459
|
+
this.renderer.removeChild(script.parentNode, script);
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Создаёт {@link HTMLScriptElement} из строки HTML скрипта.
|
|
463
|
+
*
|
|
464
|
+
* @param scriptString Строка HTML скрипта.
|
|
465
|
+
*/
|
|
466
|
+
createScript(scriptString) {
|
|
467
|
+
const range = this.document.createRange();
|
|
468
|
+
const fragment = range.createContextualFragment(scriptString);
|
|
469
|
+
return fragment.querySelector('script');
|
|
470
|
+
}
|
|
471
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScScriptsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
472
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScScriptsService, providedIn: 'root' }); }
|
|
473
|
+
}
|
|
474
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScScriptsService, decorators: [{
|
|
475
|
+
type: Injectable,
|
|
476
|
+
args: [{
|
|
477
|
+
providedIn: 'root',
|
|
478
|
+
}]
|
|
479
|
+
}] });
|
|
480
|
+
|
|
411
481
|
/* eslint-disable class-methods-use-this */
|
|
412
482
|
/**
|
|
413
483
|
* Компонент подсказок для поля ввода.
|
|
@@ -2249,15 +2319,14 @@ function scPasswordConfirmMatchingValidator(passwordKey, passwordConfirmKey) {
|
|
|
2249
2319
|
* Проверяет кратность значения.
|
|
2250
2320
|
*
|
|
2251
2321
|
* @param step Шаг кратности.
|
|
2252
|
-
* @param precision Точность, количество чисел после запятой.
|
|
2253
2322
|
*/
|
|
2254
|
-
function stepValidator(step
|
|
2323
|
+
function stepValidator(step) {
|
|
2255
2324
|
return ({ value }) => {
|
|
2256
2325
|
if (!step) {
|
|
2257
2326
|
return null;
|
|
2258
2327
|
}
|
|
2259
2328
|
if (value) {
|
|
2260
|
-
return
|
|
2329
|
+
return ScNumberHelper.isMultipleOf(value, step) ? null : { error: `Число не кратно ${step}` };
|
|
2261
2330
|
}
|
|
2262
2331
|
return null;
|
|
2263
2332
|
};
|
|
@@ -3187,14 +3256,14 @@ class ScBannerComponent {
|
|
|
3187
3256
|
}
|
|
3188
3257
|
}
|
|
3189
3258
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScBannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3190
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScBannerComponent, isStandalone: true, selector: "sc-banner", inputs: { navigateButton: { classPropertyName: "navigateButton", publicName: "navigateButton", isSignal: false, isRequired: false, transformFunction: null }, duration: { classPropertyName: "duration", publicName: "duration", isSignal: false, isRequired: false, transformFunction: null }, bannerLocation: { classPropertyName: "bannerLocation", publicName: "bannerLocation", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { loadBannersEvent: "loadBannersEvent", clickBannerEvent: "clickBannerEvent" }, host: { attributes: { "ngSkipHydration": "true" }, properties: { "class.!hidden": "totalItems() === 0", "style.aspect-ratio": "this.aspectRatio" } }, providers: [WaIntersectionObserverService], queries: [{ propertyName: "bannersListRef", predicate: ["banner"] }], viewQueries: [{ propertyName: "carouselRef", first: true, predicate: TuiCarouselComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@let effectiveDuration = totalItems() > 1 ? duration : 0;\n\n<tui-carousel\n [duration]=\"effectiveDuration\"\n [attr.resizable]=\"resizable\"\n [max]=\"maxIndex()\"\n class=\"size-full overflow-hidden rounded-xl bg-white\"\n [(index)]=\"currentBannerId\"\n>\n <ng-container *tuiItem=\"let slide\">\n @let banner = slide < banners().length ? banners()[slide] : undefined;\n @if (banner) {\n @switch (banner.mediaType) {\n @case ('image') {\n <a\n (click)=\"onClick(banner)\"\n target=\"_blank\"\n [title]=\"banner.title\"\n [style.aspect-ratio]=\"aspectRatio\"\n [attr.href]=\"banner.url ? banner.url : null\"\n class=\"size-full\"\n >\n <picture>\n @if (banner.mediaFileWebp) {\n <source\n type=\"image/webp\"\n [srcset]=\"banner.mediaFileWebp | scMediaImageTransformer\"\n />\n }\n <img\n [src]=\"banner.mediaFile | scMediaImageTransformer: true\"\n [alt]=\"banner.title\"\n class=\"size-full object-cover\"\n />\n </picture>\n </a>\n }\n }\n } @else {\n @let contentRef = bannersListRef.get(slide - banners().length);\n @if (contentRef) {\n <div\n [style.aspect-ratio]=\"aspectRatio\"\n class=\"size-full overflow-hidden\"\n >\n <ng-container [ngTemplateOutlet]=\"contentRef\"></ng-container>\n </div>\n }\n }\n </ng-container>\n</tui-carousel>\n\n@if (navigateButton &&
|
|
3259
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScBannerComponent, isStandalone: true, selector: "sc-banner", inputs: { navigateButton: { classPropertyName: "navigateButton", publicName: "navigateButton", isSignal: false, isRequired: false, transformFunction: null }, duration: { classPropertyName: "duration", publicName: "duration", isSignal: false, isRequired: false, transformFunction: null }, bannerLocation: { classPropertyName: "bannerLocation", publicName: "bannerLocation", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { loadBannersEvent: "loadBannersEvent", clickBannerEvent: "clickBannerEvent" }, host: { attributes: { "ngSkipHydration": "true" }, properties: { "class.!hidden": "totalItems() === 0", "style.aspect-ratio": "this.aspectRatio" } }, providers: [WaIntersectionObserverService], queries: [{ propertyName: "bannersListRef", predicate: ["banner"] }], viewQueries: [{ propertyName: "carouselRef", first: true, predicate: TuiCarouselComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@let effectiveDuration = totalItems() > 1 ? duration : 0;\n\n<tui-carousel\n [duration]=\"effectiveDuration\"\n [attr.resizable]=\"resizable\"\n [max]=\"maxIndex()\"\n class=\"size-full overflow-hidden rounded-xl bg-white\"\n [(index)]=\"currentBannerId\"\n>\n <ng-container *tuiItem=\"let slide\">\n @let banner = slide < banners().length ? banners()[slide] : undefined;\n @if (banner) {\n @switch (banner.mediaType) {\n @case ('image') {\n <a\n (click)=\"onClick(banner)\"\n target=\"_blank\"\n [title]=\"banner.title\"\n [style.aspect-ratio]=\"aspectRatio\"\n [attr.href]=\"banner.url ? banner.url : null\"\n class=\"size-full\"\n >\n <picture>\n @if (banner.mediaFileWebp) {\n <source\n type=\"image/webp\"\n [srcset]=\"banner.mediaFileWebp | scMediaImageTransformer\"\n />\n }\n <img\n [src]=\"banner.mediaFile | scMediaImageTransformer: true\"\n [alt]=\"banner.title\"\n class=\"size-full object-cover\"\n />\n </picture>\n </a>\n }\n }\n } @else {\n @let contentRef = bannersListRef.get(slide - banners().length);\n @if (contentRef) {\n <div\n [style.aspect-ratio]=\"aspectRatio\"\n class=\"size-full overflow-hidden\"\n >\n <ng-container [ngTemplateOutlet]=\"contentRef\"></ng-container>\n </div>\n }\n }\n </ng-container>\n</tui-carousel>\n\n@if (navigateButton && totalItems() > 1) {\n <div\n tuiTheme=\"light\"\n class=\"flex items-center\"\n >\n <button\n tuiIconButton\n size=\"m\"\n [style.border-radius.%]=\"100\"\n appearance=\"flat\"\n (click)=\"carouselRef().prev()\"\n class=\"!absolute left-2\"\n >\n <tui-icon icon=\"@tui.chevron-left\" />\n </button>\n <button\n tuiIconButton\n size=\"m\"\n [style.border-radius.%]=\"100\"\n appearance=\"flat\"\n (click)=\"carouselRef().next()\"\n class=\"!absolute right-2\"\n >\n <tui-icon icon=\"@tui.chevron-right\" />\n </button>\n </div>\n}\n", styles: [":host{--tui-carousel-padding: 0;display:flex;position:relative}::ng-deep tui-carousel[resizable=true] .t-scroller,::ng-deep tui-carousel[resizable=true] .t-items{width:100%;height:100%}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.TuiCarouselComponent, selector: "tui-carousel", inputs: ["index", "min", "max"], outputs: ["indexChange"] }, { kind: "directive", type: i2.TuiCarouselDirective, selector: "tui-carousel[duration]", inputs: ["duration"], exportAs: ["tuiCarousel"] }, { kind: "directive", type: i2$2.TuiItem, selector: "[tuiItem]" }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiIcon, selector: "tui-icon:not([tuiBadge])", inputs: ["background"] }, { kind: "pipe", type: ScMediaImageTransformerPipe, name: "scMediaImageTransformer" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3191
3260
|
}
|
|
3192
3261
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScBannerComponent, decorators: [{
|
|
3193
3262
|
type: Component,
|
|
3194
3263
|
args: [{ selector: 'sc-banner', providers: [WaIntersectionObserverService], host: {
|
|
3195
3264
|
ngSkipHydration: 'true',
|
|
3196
3265
|
'[class.!hidden]': 'totalItems() === 0',
|
|
3197
|
-
}, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgTemplateOutlet, TuiCarousel, TuiButton, TuiIcon, ScMediaImageTransformerPipe], template: "@let effectiveDuration = totalItems() > 1 ? duration : 0;\n\n<tui-carousel\n [duration]=\"effectiveDuration\"\n [attr.resizable]=\"resizable\"\n [max]=\"maxIndex()\"\n class=\"size-full overflow-hidden rounded-xl bg-white\"\n [(index)]=\"currentBannerId\"\n>\n <ng-container *tuiItem=\"let slide\">\n @let banner = slide < banners().length ? banners()[slide] : undefined;\n @if (banner) {\n @switch (banner.mediaType) {\n @case ('image') {\n <a\n (click)=\"onClick(banner)\"\n target=\"_blank\"\n [title]=\"banner.title\"\n [style.aspect-ratio]=\"aspectRatio\"\n [attr.href]=\"banner.url ? banner.url : null\"\n class=\"size-full\"\n >\n <picture>\n @if (banner.mediaFileWebp) {\n <source\n type=\"image/webp\"\n [srcset]=\"banner.mediaFileWebp | scMediaImageTransformer\"\n />\n }\n <img\n [src]=\"banner.mediaFile | scMediaImageTransformer: true\"\n [alt]=\"banner.title\"\n class=\"size-full object-cover\"\n />\n </picture>\n </a>\n }\n }\n } @else {\n @let contentRef = bannersListRef.get(slide - banners().length);\n @if (contentRef) {\n <div\n [style.aspect-ratio]=\"aspectRatio\"\n class=\"size-full overflow-hidden\"\n >\n <ng-container [ngTemplateOutlet]=\"contentRef\"></ng-container>\n </div>\n }\n }\n </ng-container>\n</tui-carousel>\n\n@if (navigateButton &&
|
|
3266
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgTemplateOutlet, TuiCarousel, TuiButton, TuiIcon, ScMediaImageTransformerPipe], template: "@let effectiveDuration = totalItems() > 1 ? duration : 0;\n\n<tui-carousel\n [duration]=\"effectiveDuration\"\n [attr.resizable]=\"resizable\"\n [max]=\"maxIndex()\"\n class=\"size-full overflow-hidden rounded-xl bg-white\"\n [(index)]=\"currentBannerId\"\n>\n <ng-container *tuiItem=\"let slide\">\n @let banner = slide < banners().length ? banners()[slide] : undefined;\n @if (banner) {\n @switch (banner.mediaType) {\n @case ('image') {\n <a\n (click)=\"onClick(banner)\"\n target=\"_blank\"\n [title]=\"banner.title\"\n [style.aspect-ratio]=\"aspectRatio\"\n [attr.href]=\"banner.url ? banner.url : null\"\n class=\"size-full\"\n >\n <picture>\n @if (banner.mediaFileWebp) {\n <source\n type=\"image/webp\"\n [srcset]=\"banner.mediaFileWebp | scMediaImageTransformer\"\n />\n }\n <img\n [src]=\"banner.mediaFile | scMediaImageTransformer: true\"\n [alt]=\"banner.title\"\n class=\"size-full object-cover\"\n />\n </picture>\n </a>\n }\n }\n } @else {\n @let contentRef = bannersListRef.get(slide - banners().length);\n @if (contentRef) {\n <div\n [style.aspect-ratio]=\"aspectRatio\"\n class=\"size-full overflow-hidden\"\n >\n <ng-container [ngTemplateOutlet]=\"contentRef\"></ng-container>\n </div>\n }\n }\n </ng-container>\n</tui-carousel>\n\n@if (navigateButton && totalItems() > 1) {\n <div\n tuiTheme=\"light\"\n class=\"flex items-center\"\n >\n <button\n tuiIconButton\n size=\"m\"\n [style.border-radius.%]=\"100\"\n appearance=\"flat\"\n (click)=\"carouselRef().prev()\"\n class=\"!absolute left-2\"\n >\n <tui-icon icon=\"@tui.chevron-left\" />\n </button>\n <button\n tuiIconButton\n size=\"m\"\n [style.border-radius.%]=\"100\"\n appearance=\"flat\"\n (click)=\"carouselRef().next()\"\n class=\"!absolute right-2\"\n >\n <tui-icon icon=\"@tui.chevron-right\" />\n </button>\n </div>\n}\n", styles: [":host{--tui-carousel-padding: 0;display:flex;position:relative}::ng-deep tui-carousel[resizable=true] .t-scroller,::ng-deep tui-carousel[resizable=true] .t-items{width:100%;height:100%}\n"] }]
|
|
3198
3267
|
}], propDecorators: { carouselRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => TuiCarouselComponent), { isSignal: true }] }], navigateButton: [{
|
|
3199
3268
|
type: Input
|
|
3200
3269
|
}], duration: [{
|
|
@@ -3358,6 +3427,10 @@ class ScAddOrEditingCartItemFormComponent {
|
|
|
3358
3427
|
* Шаг изменения метража.
|
|
3359
3428
|
*/
|
|
3360
3429
|
this.lengthStep = computed(() => ScUnitsHelper.getProductLengthMultiplicity(this.product()), ...(ngDevMode ? [{ debugName: "lengthStep" }] : /* istanbul ignore next */ []));
|
|
3430
|
+
/**
|
|
3431
|
+
* Количество знаков после запятой в поле метража.
|
|
3432
|
+
*/
|
|
3433
|
+
this.lengthPrecision = computed(() => ScNumberHelper.getDecimalsCount(this.lengthStep()), ...(ngDevMode ? [{ debugName: "lengthPrecision" }] : /* istanbul ignore next */ []));
|
|
3361
3434
|
/**
|
|
3362
3435
|
* Подсказка по минимальному и максимальному метражу товара.
|
|
3363
3436
|
*/
|
|
@@ -3375,6 +3448,10 @@ class ScAddOrEditingCartItemFormComponent {
|
|
|
3375
3448
|
* {@link Output} события редактирования товара в корзине.
|
|
3376
3449
|
*/
|
|
3377
3450
|
this.editCartItem = output();
|
|
3451
|
+
/**
|
|
3452
|
+
* Настройки вывода сумм в рублях.
|
|
3453
|
+
*/
|
|
3454
|
+
this.moneyFormat = ScNumberHelper.getMoneyFormat();
|
|
3378
3455
|
/**
|
|
3379
3456
|
* Сервис для сбора метрик о действиях пользователей.
|
|
3380
3457
|
*/
|
|
@@ -3402,7 +3479,7 @@ class ScAddOrEditingCartItemFormComponent {
|
|
|
3402
3479
|
const step = this.lengthStep();
|
|
3403
3480
|
if (this.isLengthConfigurator() && this.lengthStep() && this.form.controls.quantity.value && step) {
|
|
3404
3481
|
// Если есть конфигуратор длины, рассчитываем начально значение длины.
|
|
3405
|
-
this.form.controls.length?.patchValue(this.form.controls.quantity.value
|
|
3482
|
+
this.form.controls.length?.patchValue(ScNumberHelper.multiplyByStep(this.form.controls.quantity.value, step));
|
|
3406
3483
|
}
|
|
3407
3484
|
// Добавляем валидацию шага для количества.
|
|
3408
3485
|
this.form.controls.quantity.addValidators(stepValidator(ScUnitsHelper.getProductMultiplicity(this.product())));
|
|
@@ -3419,12 +3496,11 @@ class ScAddOrEditingCartItemFormComponent {
|
|
|
3419
3496
|
}
|
|
3420
3497
|
// Если изменилось количество — пересчитываем длину.
|
|
3421
3498
|
if (previous.quantity !== current.quantity && this.form.controls.quantity.value) {
|
|
3422
|
-
|
|
3423
|
-
lengthControl.patchValue(newValue);
|
|
3499
|
+
lengthControl.patchValue(ScNumberHelper.multiplyByStep(this.form.controls.quantity.value, step));
|
|
3424
3500
|
}
|
|
3425
3501
|
// Если изменилась длина — пересчитываем количество и возвращаем значение длины.
|
|
3426
3502
|
if (previous.length !== current.length && lengthControl.value) {
|
|
3427
|
-
const newValue = lengthControl.value
|
|
3503
|
+
const newValue = ScNumberHelper.divideByStep(lengthControl.value, step);
|
|
3428
3504
|
this.form.controls.quantity.patchValue(newValue);
|
|
3429
3505
|
return { length: step, quantity: newValue };
|
|
3430
3506
|
}
|
|
@@ -3432,7 +3508,7 @@ class ScAddOrEditingCartItemFormComponent {
|
|
|
3432
3508
|
return { length: step, quantity: current.quantity };
|
|
3433
3509
|
}),
|
|
3434
3510
|
// Считаем стоимость: цена * длина * количество.
|
|
3435
|
-
map(({ length, quantity }) => (this.product().costRub ?? 0) * (length ?? 1) * quantity)
|
|
3511
|
+
map(({ length, quantity }) => ScNumberHelper.roundMoney((this.product().costRub ?? 0) * (length ?? 1) * quantity)));
|
|
3436
3512
|
}
|
|
3437
3513
|
/**
|
|
3438
3514
|
* Обработчик события шага метража.
|
|
@@ -3444,11 +3520,8 @@ class ScAddOrEditingCartItemFormComponent {
|
|
|
3444
3520
|
if (!this.productIsMeasurable() || !lengthControl) {
|
|
3445
3521
|
return;
|
|
3446
3522
|
}
|
|
3447
|
-
const
|
|
3448
|
-
|
|
3449
|
-
// Округляем до ближайшего кратного числа.
|
|
3450
|
-
newLength = Math.round(newLength / step) * step;
|
|
3451
|
-
lengthControl.setValue(Number(newLength.toFixed(2)));
|
|
3523
|
+
const newLength = Math.max(this.minLength() ?? step, ScNumberHelper.addStep(lengthControl.value ?? 0, step));
|
|
3524
|
+
lengthControl.setValue(ScNumberHelper.snapToStep(newLength, Math.abs(step)));
|
|
3452
3525
|
}
|
|
3453
3526
|
/**
|
|
3454
3527
|
* Обработчик события шага количества.
|
|
@@ -3457,7 +3530,8 @@ class ScAddOrEditingCartItemFormComponent {
|
|
|
3457
3530
|
*/
|
|
3458
3531
|
onStepQuantity(step) {
|
|
3459
3532
|
const quantity = this.form.controls.quantity.value ?? 0;
|
|
3460
|
-
|
|
3533
|
+
const multipleQuantity = ScNumberHelper.addStep(quantity, -ScNumberHelper.remainder(quantity, Math.abs(step)));
|
|
3534
|
+
this.form.controls.quantity.setValue(Math.max(this.productMultiplicity(), ScNumberHelper.addStep(multipleQuantity, step)));
|
|
3461
3535
|
}
|
|
3462
3536
|
/**
|
|
3463
3537
|
* Обработчик события отправки формы.
|
|
@@ -3485,11 +3559,12 @@ class ScAddOrEditingCartItemFormComponent {
|
|
|
3485
3559
|
}
|
|
3486
3560
|
}
|
|
3487
3561
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScAddOrEditingCartItemFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3488
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScAddOrEditingCartItemFormComponent, isStandalone: true, selector: "sc-add-or-editing-cart-item-form", inputs: { product: { classPropertyName: "product", publicName: "product", isSignal: true, isRequired: true, transformFunction: null }, orderItem: { classPropertyName: "orderItem", publicName: "orderItem", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { addProduct: "addProduct", editCartItem: "editCartItem" }, ngImport: i0, template: "<!-- \u0424\u043E\u0440\u043C\u0430 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0438\u044F \u0438\u0437\u043C\u0435\u0440\u044F\u0435\u043C\u043E\u0433\u043E \u0442\u043E\u0432\u0430\u0440\u0430. -->\n@if (product()) {\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit()\"\n ScNextInputFocus\n class=\"flex flex-col gap-2\"\n >\n @let step = lengthStep();\n <!-- \u0414\u043B\u0438\u043D\u0430 \u0442\u043E\u0432\u0430\u0440\u0430 (\u043C\u0435\u0442\u0440\u0430\u0436) -->\n @if (productIsMeasurable()) {\n <label tuiLabel>\n \u041C\u0435\u0442\u0440\u0430\u0436, {{ product().unit.name }}\n @if (!step || maxLength()) {\n {{ lengthHint() }}\n }\n <tui-textfield>\n <input\n tuiInputNumber\n formControlName=\"length\"\n [tuiNumberFormat]=\"{ precision:
|
|
3562
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScAddOrEditingCartItemFormComponent, isStandalone: true, selector: "sc-add-or-editing-cart-item-form", inputs: { product: { classPropertyName: "product", publicName: "product", isSignal: true, isRequired: true, transformFunction: null }, orderItem: { classPropertyName: "orderItem", publicName: "orderItem", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { addProduct: "addProduct", editCartItem: "editCartItem" }, ngImport: i0, template: "<!-- \u0424\u043E\u0440\u043C\u0430 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0438\u044F \u0438\u0437\u043C\u0435\u0440\u044F\u0435\u043C\u043E\u0433\u043E \u0442\u043E\u0432\u0430\u0440\u0430. -->\n@if (product()) {\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit()\"\n ScNextInputFocus\n class=\"flex flex-col gap-2\"\n >\n @let step = lengthStep();\n <!-- \u0414\u043B\u0438\u043D\u0430 \u0442\u043E\u0432\u0430\u0440\u0430 (\u043C\u0435\u0442\u0440\u0430\u0436) -->\n @if (productIsMeasurable()) {\n <label tuiLabel>\n \u041C\u0435\u0442\u0440\u0430\u0436, {{ product().unit.name }}\n @if (!step || maxLength()) {\n {{ lengthHint() }}\n }\n <tui-textfield>\n <input\n tuiInputNumber\n formControlName=\"length\"\n [tuiNumberFormat]=\"{ precision: lengthPrecision() }\"\n [max]=\"maxLength() || null\"\n [min]=\"minLength() || null\"\n (keydown.arrowDown)=\"onStepLength(-(lengthStep() ?? 0.01))\"\n (keydown.arrowUp)=\"onStepLength(lengthStep() ?? 0.01)\"\n autocomplete=\"length\"\n placeholder=\"\u041C\u0435\u0442\u0440\u0430\u0436\"\n />\n </tui-textfield>\n <tui-error formControlName=\"length\" />\n @if (lengthStep()) {\n <p class=\"tui-form__field-note\">\u041C\u0435\u0442\u0440\u0430\u0436 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043A\u0440\u0430\u0442\u0435\u043D {{ lengthStep() }}</p>\n }\n </label>\n }\n <!-- \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0442\u043E\u0432\u0430\u0440\u0430 -->\n <label tuiLabel>\n \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442.\n <tui-textfield>\n @if (isLengthConfigurator() && productMultiplicity() && step) {\n <span\n tuiChip\n size=\"s\"\n appearance=\"negative\"\n class=\"font-bold\"\n >\n x {{ step }} {{ product().unit.name }}\n </span>\n }\n <input\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n tuiInputNumber\n [tuiNumberFormat]=\"{ decimalMode: 'not-zero' }\"\n [min]=\"productMultiplicity()\"\n (keydown.arrowDown)=\"onStepQuantity(-productMultiplicity())\"\n (keydown.arrowUp)=\"onStepQuantity(productMultiplicity())\"\n formControlName=\"quantity\"\n autocomplete=\"quantity\"\n />\n </tui-textfield>\n <p class=\"tui-form__field-note\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043A\u0440\u0430\u0442\u043D\u043E {{ productMultiplicity() }}</p>\n <tui-error formControlName=\"quantity\" />\n </label>\n <!-- \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 -->\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiInput\n autocomplete=\"marker\"\n formControlName=\"marker\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\"\n />\n </tui-textfield>\n <tui-error formControlName=\"marker\" />\n </label>\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0438\u044F / \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430 \u0432 \u043A\u043E\u0440\u0437\u0438\u043D\u0443 -->\n <div class=\"flex flex-col items-center\">\n @let cost = totalCost$ | async;\n @if (cost) {\n <div>\n \u0418\u0442\u043E\u0433\u043E:<span class=\"text-2xl font-bold\">\n {{ cost | tuiFormatNumber: moneyFormat }}\n {{ product().currency.symbol }}\n </span>\n </div>\n }\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0438\u044F / \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430 \u0432 \u043A\u043E\u0440\u0437\u0438\u043D\u0443 -->\n <button\n tuiButton\n iconStart=\"@tui.check\"\n [disabled]=\"form.invalid\"\n [loading]=\"isLoading()\"\n type=\"submit\"\n class=\"mt-2\"\n >\n {{ orderItem() ? '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' : '\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0432 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' }}\n </button>\n </div>\n </form>\n}\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: ScNextInputFocusDirective, selector: "form[ScNextInputFocus]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: TuiLabel, selector: "label[tuiLabel]" }, { kind: "directive", type: ScSelectOnFocusinDirective, selector: "tui-input-number, tui-input, tui-input-phone, tui-input-date, tui-input-password, input[tuiInput], input[tuiInputNumber], input[tuiTextfield], input[tuiInputSlider]" }, { kind: "directive", type: TuiNumberFormat, selector: "[tuiNumberFormat]", inputs: ["tuiNumberFormat"] }, { kind: "component", type: i2.TuiErrorComponent, selector: "tui-error", inputs: ["error"] }, { kind: "directive", type: i2.TuiErrorDirective, selector: "tui-error[ngModel], tui-error[formControlName], tui-error[formControl], tui-error[formGroup], tui-error[formGroupName], tui-error[formArrayName], tui-error[formArray]", inputs: ["order"] }, { kind: "component", type: i3$1.TuiTextfieldComponent, selector: "tui-textfield:not([multi])", inputs: ["content", "filler"] }, { kind: "directive", type: i2.TuiInputDirective, selector: "input[tuiInput]", inputs: ["readOnly", "invalid", "focused", "state"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "directive", type: i1$1.TuiInputNumberDirective, selector: "input[tuiInputNumber]" }, { kind: "directive", type: TuiChip, selector: "[tuiChip]", inputs: ["size"] }, { kind: "pipe", type: TuiFormatNumberPipe, name: "tuiFormatNumber" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3489
3563
|
}
|
|
3490
3564
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScAddOrEditingCartItemFormComponent, decorators: [{
|
|
3491
3565
|
type: Component,
|
|
3492
3566
|
args: [{ standalone: true, selector: 'sc-add-or-editing-cart-item-form', imports: [
|
|
3567
|
+
TuiFormatNumberPipe,
|
|
3493
3568
|
FormsModule,
|
|
3494
3569
|
ScNextInputFocusDirective,
|
|
3495
3570
|
ReactiveFormsModule,
|
|
@@ -3506,9 +3581,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
3506
3581
|
TuiButtonLoading,
|
|
3507
3582
|
AsyncPipe,
|
|
3508
3583
|
TuiInputNumber,
|
|
3509
|
-
TuiAmountPipe,
|
|
3510
3584
|
TuiChip,
|
|
3511
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- \u0424\u043E\u0440\u043C\u0430 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0438\u044F \u0438\u0437\u043C\u0435\u0440\u044F\u0435\u043C\u043E\u0433\u043E \u0442\u043E\u0432\u0430\u0440\u0430. -->\n@if (product()) {\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit()\"\n ScNextInputFocus\n class=\"flex flex-col gap-2\"\n >\n @let step = lengthStep();\n <!-- \u0414\u043B\u0438\u043D\u0430 \u0442\u043E\u0432\u0430\u0440\u0430 (\u043C\u0435\u0442\u0440\u0430\u0436) -->\n @if (productIsMeasurable()) {\n <label tuiLabel>\n \u041C\u0435\u0442\u0440\u0430\u0436, {{ product().unit.name }}\n @if (!step || maxLength()) {\n {{ lengthHint() }}\n }\n <tui-textfield>\n <input\n tuiInputNumber\n formControlName=\"length\"\n [tuiNumberFormat]=\"{ precision:
|
|
3585
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- \u0424\u043E\u0440\u043C\u0430 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0438\u044F \u0438\u0437\u043C\u0435\u0440\u044F\u0435\u043C\u043E\u0433\u043E \u0442\u043E\u0432\u0430\u0440\u0430. -->\n@if (product()) {\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit()\"\n ScNextInputFocus\n class=\"flex flex-col gap-2\"\n >\n @let step = lengthStep();\n <!-- \u0414\u043B\u0438\u043D\u0430 \u0442\u043E\u0432\u0430\u0440\u0430 (\u043C\u0435\u0442\u0440\u0430\u0436) -->\n @if (productIsMeasurable()) {\n <label tuiLabel>\n \u041C\u0435\u0442\u0440\u0430\u0436, {{ product().unit.name }}\n @if (!step || maxLength()) {\n {{ lengthHint() }}\n }\n <tui-textfield>\n <input\n tuiInputNumber\n formControlName=\"length\"\n [tuiNumberFormat]=\"{ precision: lengthPrecision() }\"\n [max]=\"maxLength() || null\"\n [min]=\"minLength() || null\"\n (keydown.arrowDown)=\"onStepLength(-(lengthStep() ?? 0.01))\"\n (keydown.arrowUp)=\"onStepLength(lengthStep() ?? 0.01)\"\n autocomplete=\"length\"\n placeholder=\"\u041C\u0435\u0442\u0440\u0430\u0436\"\n />\n </tui-textfield>\n <tui-error formControlName=\"length\" />\n @if (lengthStep()) {\n <p class=\"tui-form__field-note\">\u041C\u0435\u0442\u0440\u0430\u0436 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043A\u0440\u0430\u0442\u0435\u043D {{ lengthStep() }}</p>\n }\n </label>\n }\n <!-- \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0442\u043E\u0432\u0430\u0440\u0430 -->\n <label tuiLabel>\n \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442.\n <tui-textfield>\n @if (isLengthConfigurator() && productMultiplicity() && step) {\n <span\n tuiChip\n size=\"s\"\n appearance=\"negative\"\n class=\"font-bold\"\n >\n x {{ step }} {{ product().unit.name }}\n </span>\n }\n <input\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n tuiInputNumber\n [tuiNumberFormat]=\"{ decimalMode: 'not-zero' }\"\n [min]=\"productMultiplicity()\"\n (keydown.arrowDown)=\"onStepQuantity(-productMultiplicity())\"\n (keydown.arrowUp)=\"onStepQuantity(productMultiplicity())\"\n formControlName=\"quantity\"\n autocomplete=\"quantity\"\n />\n </tui-textfield>\n <p class=\"tui-form__field-note\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043A\u0440\u0430\u0442\u043D\u043E {{ productMultiplicity() }}</p>\n <tui-error formControlName=\"quantity\" />\n </label>\n <!-- \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 -->\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiInput\n autocomplete=\"marker\"\n formControlName=\"marker\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\"\n />\n </tui-textfield>\n <tui-error formControlName=\"marker\" />\n </label>\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0438\u044F / \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430 \u0432 \u043A\u043E\u0440\u0437\u0438\u043D\u0443 -->\n <div class=\"flex flex-col items-center\">\n @let cost = totalCost$ | async;\n @if (cost) {\n <div>\n \u0418\u0442\u043E\u0433\u043E:<span class=\"text-2xl font-bold\">\n {{ cost | tuiFormatNumber: moneyFormat }}\n {{ product().currency.symbol }}\n </span>\n </div>\n }\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0438\u044F / \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430 \u0432 \u043A\u043E\u0440\u0437\u0438\u043D\u0443 -->\n <button\n tuiButton\n iconStart=\"@tui.check\"\n [disabled]=\"form.invalid\"\n [loading]=\"isLoading()\"\n type=\"submit\"\n class=\"mt-2\"\n >\n {{ orderItem() ? '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' : '\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0432 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' }}\n </button>\n </div>\n </form>\n}\n" }]
|
|
3512
3586
|
}], propDecorators: { product: [{ type: i0.Input, args: [{ isSignal: true, alias: "product", required: true }] }], orderItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "orderItem", required: false }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], addProduct: [{ type: i0.Output, args: ["addProduct"] }], editCartItem: [{ type: i0.Output, args: ["editCartItem"] }] } });
|
|
3513
3587
|
|
|
3514
3588
|
/* eslint-disable sonarjs/no-nested-template-literals,@typescript-eslint/unbound-method,@typescript-eslint/no-unused-vars */
|
|
@@ -3985,9 +4059,9 @@ class ScInputQuantityComponent {
|
|
|
3985
4059
|
*/
|
|
3986
4060
|
incident(checkUpdateOn = false) {
|
|
3987
4061
|
const current = this.formControl.value ?? 0;
|
|
3988
|
-
const remainder = (
|
|
3989
|
-
const step = this.step -
|
|
3990
|
-
const newValue = Math.max(
|
|
4062
|
+
const remainder = ScNumberHelper.remainder(current, this.step);
|
|
4063
|
+
const step = ScNumberHelper.addStep(this.step, -remainder);
|
|
4064
|
+
const newValue = Math.max(ScNumberHelper.addStep(current, step), this._ignoreStepValidators ? 1 : Math.max(step, 0));
|
|
3991
4065
|
this.formControl.setValue(newValue);
|
|
3992
4066
|
if (checkUpdateOn) {
|
|
3993
4067
|
this.onChange(newValue);
|
|
@@ -4000,9 +4074,9 @@ class ScInputQuantityComponent {
|
|
|
4000
4074
|
*/
|
|
4001
4075
|
decrement(checkUpdateOn = false) {
|
|
4002
4076
|
const current = this.formControl.value ?? 0;
|
|
4003
|
-
const remainder = (
|
|
4077
|
+
const remainder = ScNumberHelper.remainder(current, this.step);
|
|
4004
4078
|
const step = -remainder || -this.step;
|
|
4005
|
-
const newValue = Math.max(
|
|
4079
|
+
const newValue = Math.max(ScNumberHelper.addStep(current, step), this._ignoreStepValidators ? 1 : Math.max(step, 0));
|
|
4006
4080
|
this.formControl.setValue(newValue);
|
|
4007
4081
|
if (checkUpdateOn) {
|
|
4008
4082
|
this.onChange(newValue);
|
|
@@ -4459,7 +4533,11 @@ class ScPriceHistoryComponent {
|
|
|
4459
4533
|
*
|
|
4460
4534
|
* @param value Значение оси Y.
|
|
4461
4535
|
*/
|
|
4462
|
-
this.yStringify = (value) => `${
|
|
4536
|
+
this.yStringify = (value) => `${ScNumberHelper.formatMoney(value)} ₽`;
|
|
4537
|
+
/**
|
|
4538
|
+
* Настройки вывода цен в рублях.
|
|
4539
|
+
*/
|
|
4540
|
+
this.moneyFormat = ScNumberHelper.getMoneyFormat();
|
|
4463
4541
|
if (this.context) {
|
|
4464
4542
|
this.product = this.context.data.product;
|
|
4465
4543
|
}
|
|
@@ -4528,7 +4606,7 @@ class ScPriceHistoryComponent {
|
|
|
4528
4606
|
}, []));
|
|
4529
4607
|
}
|
|
4530
4608
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScPriceHistoryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4531
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScPriceHistoryComponent, isStandalone: true, selector: "sc-price-history", inputs: { product: "product" }, ngImport: i0, template: "<tui-loader [loading]=\"!!(loadingHistory$ | async)\"> </tui-loader>\n\n@if ((loadingHistory$ | async) === false) {\n <div class=\"flex flex-col items-center\">\n @if (priceInfo$ | async; as priceInfo) {\n <div class=\"w-174 mb-1 text-end text-lg font-bold\">\u043E\u0442 {{ priceInfo.min
|
|
4609
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScPriceHistoryComponent, isStandalone: true, selector: "sc-price-history", inputs: { product: "product" }, ngImport: i0, template: "<tui-loader [loading]=\"!!(loadingHistory$ | async)\"> </tui-loader>\n\n@if ((loadingHistory$ | async) === false) {\n <div class=\"flex flex-col items-center\">\n @if (priceInfo$ | async; as priceInfo) {\n <div class=\"w-174 mb-1 text-end text-lg font-bold\">\u043E\u0442 {{ priceInfo.min | tuiFormatNumber: moneyFormat }} \u20BD \u0434\u043E {{ priceInfo.max | tuiFormatNumber: moneyFormat }} \u20BD</div>\n @if (history$ | async; as history) {\n @if (range$ | async; as range) {\n <div class=\"relative h-56 w-full p-5 text-tui-primary\">\n @let labels = computeLabels(range);\n <tui-axes\n class=\"h-full\"\n [axisXLabels]=\"labels\"\n [horizontalLines]=\"5\"\n [verticalLines]=\"labels.length + 1\"\n >\n @let height = priceInfo.max - priceInfo.min;\n @if ((height / 100) * paddingPercent; as padding) {\n <tui-line-days-chart\n [height]=\"height + (height / 100) * paddingPercent * 2\"\n [smoothingFactor]=\"10\"\n [y]=\"priceInfo.min - (height / 100) * paddingPercent\"\n [value]=\"computeValue(range, history)\"\n [xStringify]=\"xStringify\"\n [yStringify]=\"yStringify\"\n [hintContent]=\"hint\"\n class=\"chart\"\n ></tui-line-days-chart>\n }\n </tui-axes>\n </div>\n }\n }\n } @else {\n <p class=\"text-base font-bold\">\u0426\u0435\u043D\u0430 \u043D\u0430 \u0442\u043E\u0432\u0430\u0440 \u043D\u0435 \u0438\u0437\u043C\u0435\u043D\u044F\u043B\u0430\u0441\u044C</p>\n }\n <ng-template\n #hint\n let-data\n >\n <div class=\"font-bold\">{{ data[1] | tuiFormatNumber: moneyFormat }} \u20BD</div>\n <div>{{ data[0] }}</div>\n </ng-template>\n </div>\n}\n", dependencies: [{ kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "loading"] }, { kind: "component", type: TuiAxes, selector: "tui-axes", inputs: ["axisXLabels", "axisYInset", "axisYLabels", "axisYName", "axisYSecondaryInset", "axisYSecondaryLabels", "axisYSecondaryName", "centeredXLabels", "horizontalLines", "horizontalLinesHandler", "verticalLines", "verticalLinesHandler"] }, { kind: "component", type: TuiLineDaysChart, selector: "tui-line-days-chart", inputs: ["y", "height", "smoothingFactor", "hintContent", "xStringify", "yStringify", "dots", "value"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: TuiFormatNumberPipe, name: "tuiFormatNumber" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4532
4610
|
}
|
|
4533
4611
|
__decorate([
|
|
4534
4612
|
tuiPure
|
|
@@ -4538,7 +4616,7 @@ __decorate([
|
|
|
4538
4616
|
], ScPriceHistoryComponent.prototype, "computeValue", null);
|
|
4539
4617
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScPriceHistoryComponent, decorators: [{
|
|
4540
4618
|
type: Component,
|
|
4541
|
-
args: [{ selector: 'sc-price-history', changeDetection: ChangeDetectionStrategy.OnPush, imports: [TuiLoader, TuiAxes, TuiLineDaysChart, AsyncPipe], template: "<tui-loader [loading]=\"!!(loadingHistory$ | async)\"> </tui-loader>\n\n@if ((loadingHistory$ | async) === false) {\n <div class=\"flex flex-col items-center\">\n @if (priceInfo$ | async; as priceInfo) {\n <div class=\"w-174 mb-1 text-end text-lg font-bold\">\u043E\u0442 {{ priceInfo.min
|
|
4619
|
+
args: [{ selector: 'sc-price-history', changeDetection: ChangeDetectionStrategy.OnPush, imports: [TuiLoader, TuiAxes, TuiLineDaysChart, AsyncPipe, TuiFormatNumberPipe], template: "<tui-loader [loading]=\"!!(loadingHistory$ | async)\"> </tui-loader>\n\n@if ((loadingHistory$ | async) === false) {\n <div class=\"flex flex-col items-center\">\n @if (priceInfo$ | async; as priceInfo) {\n <div class=\"w-174 mb-1 text-end text-lg font-bold\">\u043E\u0442 {{ priceInfo.min | tuiFormatNumber: moneyFormat }} \u20BD \u0434\u043E {{ priceInfo.max | tuiFormatNumber: moneyFormat }} \u20BD</div>\n @if (history$ | async; as history) {\n @if (range$ | async; as range) {\n <div class=\"relative h-56 w-full p-5 text-tui-primary\">\n @let labels = computeLabels(range);\n <tui-axes\n class=\"h-full\"\n [axisXLabels]=\"labels\"\n [horizontalLines]=\"5\"\n [verticalLines]=\"labels.length + 1\"\n >\n @let height = priceInfo.max - priceInfo.min;\n @if ((height / 100) * paddingPercent; as padding) {\n <tui-line-days-chart\n [height]=\"height + (height / 100) * paddingPercent * 2\"\n [smoothingFactor]=\"10\"\n [y]=\"priceInfo.min - (height / 100) * paddingPercent\"\n [value]=\"computeValue(range, history)\"\n [xStringify]=\"xStringify\"\n [yStringify]=\"yStringify\"\n [hintContent]=\"hint\"\n class=\"chart\"\n ></tui-line-days-chart>\n }\n </tui-axes>\n </div>\n }\n }\n } @else {\n <p class=\"text-base font-bold\">\u0426\u0435\u043D\u0430 \u043D\u0430 \u0442\u043E\u0432\u0430\u0440 \u043D\u0435 \u0438\u0437\u043C\u0435\u043D\u044F\u043B\u0430\u0441\u044C</p>\n }\n <ng-template\n #hint\n let-data\n >\n <div class=\"font-bold\">{{ data[1] | tuiFormatNumber: moneyFormat }} \u20BD</div>\n <div>{{ data[0] }}</div>\n </ng-template>\n </div>\n}\n" }]
|
|
4542
4620
|
}], ctorParameters: () => [], propDecorators: { product: [{
|
|
4543
4621
|
type: Input
|
|
4544
4622
|
}], computeLabels: [], computeValue: [] } });
|
|
@@ -4711,7 +4789,7 @@ class ScCatalogFiltersComponent {
|
|
|
4711
4789
|
* {@link Observable} фильтров категории.
|
|
4712
4790
|
*/
|
|
4713
4791
|
this.filters = toSignal(inject(SC_CATEGORY_INFO).pipe(catchError(() => EMPTY), filter(tuiIsPresent), switchMap((category) => this.catalogFilterService.getFilters$(this.idOrSlugPipe.transform(category), this.isRecursively)), filter(tuiIsPresent), map((filters) => filters
|
|
4714
|
-
.filter((item) =>
|
|
4792
|
+
.filter((item) => this.isRenderableFilter(item))
|
|
4715
4793
|
.map((item) => (item.type === 'checkbox' ? { ...item, values: [...item.values].sort((a, b) => a.label.localeCompare(b.label)) } : item))), tap((filters) => {
|
|
4716
4794
|
this.updateFormControls(filters);
|
|
4717
4795
|
}), share()));
|
|
@@ -4728,6 +4806,22 @@ class ScCatalogFiltersComponent {
|
|
|
4728
4806
|
this.resetAllFilters(false);
|
|
4729
4807
|
});
|
|
4730
4808
|
}
|
|
4809
|
+
/**
|
|
4810
|
+
* Проверяет, что фильтр пригоден для вывода: у checkbox есть непустой список значений, у range заданы разные границы.
|
|
4811
|
+
* Некорректные фильтры из ответа API пропускаются, чтобы не ломать вывод остальных.
|
|
4812
|
+
*
|
|
4813
|
+
* @param item Фильтр каталога.
|
|
4814
|
+
*/
|
|
4815
|
+
isRenderableFilter(item) {
|
|
4816
|
+
switch (item.type) {
|
|
4817
|
+
case 'checkbox':
|
|
4818
|
+
return Array.isArray(item.values) && item.values.length > 0;
|
|
4819
|
+
case 'range':
|
|
4820
|
+
return !isNil(item.min) && !isNil(item.max) && item.min !== item.max;
|
|
4821
|
+
default:
|
|
4822
|
+
return true;
|
|
4823
|
+
}
|
|
4824
|
+
}
|
|
4731
4825
|
/**
|
|
4732
4826
|
* Обновляет состав контролов формы на основе переданных фильтров.
|
|
4733
4827
|
*
|
|
@@ -5086,6 +5180,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
5086
5180
|
*/
|
|
5087
5181
|
class ScSandwichComponent {
|
|
5088
5182
|
constructor() {
|
|
5183
|
+
/**
|
|
5184
|
+
* Настройки вывода сумм в рублях.
|
|
5185
|
+
*/
|
|
5186
|
+
this.moneyFormat = ScNumberHelper.getMoneyFormat();
|
|
5089
5187
|
/**
|
|
5090
5188
|
* Данные настроек окружения.
|
|
5091
5189
|
*/
|
|
@@ -5289,7 +5387,7 @@ class ScSandwichComponent {
|
|
|
5289
5387
|
return 0;
|
|
5290
5388
|
}
|
|
5291
5389
|
const totalCost = calculateResult.quantity * this.product.value.costRub;
|
|
5292
|
-
return
|
|
5390
|
+
return ScNumberHelper.roundMoney(totalCost);
|
|
5293
5391
|
}
|
|
5294
5392
|
/**
|
|
5295
5393
|
* Обработчик добавления/редактирования продукта в корзине.
|
|
@@ -5404,11 +5502,12 @@ class ScSandwichComponent {
|
|
|
5404
5502
|
stringify: signal((x) => x.name),
|
|
5405
5503
|
identityMatcher: signal((a, b) => a.id === b.id),
|
|
5406
5504
|
}),
|
|
5407
|
-
], 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 *tuiDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error [formControl]=\"product\" />\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 formControlName=\"width\" />\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 formControlName=\"length\" />\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 formControlName=\"count\" />\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 appearance=\"secondary\"\n class=\"mt-6\"\n [style.flex]=\"'0 0 auto'\"\n >\n <tui-icon icon=\"@tui.trash-2\" />\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 tuiInput\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 formControlName=\"marker\" />\n </label>\n\n @if (product.value) {\n <tui-loader [loading]=\"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 [formGroup]=\"form\" />\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: $thumb-radius;display:flex;font:var(--tui-typography-body-s);color:var(--tui-text-secondary);margin:.25rem var(--t-offset) 0}.slider-ticks-labels>*{position:relative;flex:2;text-align:center}.slider-ticks-labels>*:first-child{inset-inline-start:calc(-1 * var(--t-offset));flex:1;text-align:start}.slider-ticks-labels>*:last-child{inset-inline-end:calc(-1 * var(--t-offset));flex:1;text-align:end}tui-range+.slider-ticks-labels{--t-offset: $thumb-diameter}tui-textfield[data-size=l]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"l\") + $thumb-radius)}tui-textfield[data-size=m]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"m\") + $thumb-radius)}tui-textfield[data-size=s]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"s\") + $thumb-radius)}tui-input-range[data-size=l]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"l\") + $thumb-diameter)}tui-input-range[data-size=m]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"m\") + $thumb-diameter)}tui-input-range[data-size=s]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"s\") + $thumb-diameter)}.slider-ticks-labels{color:var(--tui-text-secondary)}\n"], dependencies: [{ kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiIcon, selector: "tui-icon:not([tuiBadge])", inputs: ["background"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { 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])", inputs: ["items", "emptyContent", "size", "itemContent"], outputs: ["itemClick"] }, { kind: "component", type: i2.TuiErrorComponent, selector: "tui-error", inputs: ["error"] }, { kind: "directive", type: i2.TuiErrorDirective, selector: "tui-error[ngModel], tui-error[formControlName], tui-error[formControl], tui-error[formGroup], tui-error[formGroupName], tui-error[formArrayName], tui-error[formArray]", inputs: ["order"] }, { kind: "component", type: i3$1.TuiTextfieldComponent, selector: "tui-textfield:not([multi])", inputs: ["content", "filler"] }, { kind: "directive", type: i3$1.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }, { kind: "directive", type: i3.TuiDropdownContent, selector: "ng-template[tuiDropdown]" }, { kind: "directive", type: i2.TuiInputDirective, selector: "input[tuiInput]", inputs: ["readOnly", "invalid", "focused", "state"] }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "directive", type: i1$1.TuiSelectDirective, selector: "input[tuiSelect]" }, { kind: "directive", type: i1$1.TuiInputNumberDirective, selector: "input[tuiInputNumber]" }, { kind: "directive", type: TuiNumberFormat, selector: "[tuiNumberFormat]", inputs: ["tuiNumberFormat"] }, { kind: "component", type: i6.TuiSliderComponent, selector: "input[type=range][tuiSlider]", inputs: ["segments"] }, { kind: "directive", type: i1$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[tuiInput], input[tuiInputNumber], input[tuiTextfield], input[tuiInputSlider]" }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "loading"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5505
|
+
], 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 *tuiDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error [formControl]=\"product\" />\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 | tuiFormatNumber: moneyFormat }} {{ 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 formControlName=\"width\" />\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 formControlName=\"length\" />\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 formControlName=\"count\" />\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 appearance=\"secondary\"\n class=\"mt-6\"\n [style.flex]=\"'0 0 auto'\"\n >\n <tui-icon icon=\"@tui.trash-2\" />\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 tuiInput\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 formControlName=\"marker\" />\n </label>\n\n @if (product.value) {\n <tui-loader [loading]=\"isCalculateLoading()\">\n @if (calculateResult) {\n <div class=\"mt-2 flex flex-wrap items-end gap-2\">\n <div>\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"whitespace-nowrap text-xl font-bold\"\n >{{ getTotalCost(calculateResult) | tuiFormatNumber: moneyFormat }} {{ product.value.currency.symbol }}</span\n >\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\"\n >{{ productValue.costRub === undefined ? '' : (productValue.costRub | tuiFormatNumber: moneyFormat) }}\n {{ productValue.currency.symbol }}/\u0448\u0442.)</span\n >\n </div>\n }\n </div>\n }\n </tui-loader>\n }\n\n <tui-error [formGroup]=\"form\" />\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: $thumb-radius;display:flex;font:var(--tui-typography-body-s);color:var(--tui-text-secondary);margin:.25rem var(--t-offset) 0}.slider-ticks-labels>*{position:relative;flex:2;text-align:center}.slider-ticks-labels>*:first-child{inset-inline-start:calc(-1 * var(--t-offset));flex:1;text-align:start}.slider-ticks-labels>*:last-child{inset-inline-end:calc(-1 * var(--t-offset));flex:1;text-align:end}tui-range+.slider-ticks-labels{--t-offset: $thumb-diameter}tui-textfield[data-size=l]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"l\") + $thumb-radius)}tui-textfield[data-size=m]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"m\") + $thumb-radius)}tui-textfield[data-size=s]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"s\") + $thumb-radius)}tui-input-range[data-size=l]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"l\") + $thumb-diameter)}tui-input-range[data-size=m]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"m\") + $thumb-diameter)}tui-input-range[data-size=s]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"s\") + $thumb-diameter)}.slider-ticks-labels{color:var(--tui-text-secondary)}\n"], dependencies: [{ kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiIcon, selector: "tui-icon:not([tuiBadge])", inputs: ["background"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { 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])", inputs: ["items", "emptyContent", "size", "itemContent"], outputs: ["itemClick"] }, { kind: "component", type: i2.TuiErrorComponent, selector: "tui-error", inputs: ["error"] }, { kind: "directive", type: i2.TuiErrorDirective, selector: "tui-error[ngModel], tui-error[formControlName], tui-error[formControl], tui-error[formGroup], tui-error[formGroupName], tui-error[formArrayName], tui-error[formArray]", inputs: ["order"] }, { kind: "component", type: i3$1.TuiTextfieldComponent, selector: "tui-textfield:not([multi])", inputs: ["content", "filler"] }, { kind: "directive", type: i3$1.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }, { kind: "directive", type: i3.TuiDropdownContent, selector: "ng-template[tuiDropdown]" }, { kind: "directive", type: i2.TuiInputDirective, selector: "input[tuiInput]", inputs: ["readOnly", "invalid", "focused", "state"] }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "directive", type: i1$1.TuiSelectDirective, selector: "input[tuiSelect]" }, { kind: "directive", type: i1$1.TuiInputNumberDirective, selector: "input[tuiInputNumber]" }, { kind: "directive", type: TuiNumberFormat, selector: "[tuiNumberFormat]", inputs: ["tuiNumberFormat"] }, { kind: "component", type: i6.TuiSliderComponent, selector: "input[type=range][tuiSlider]", inputs: ["segments"] }, { kind: "directive", type: i1$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[tuiInput], input[tuiInputNumber], input[tuiTextfield], input[tuiInputSlider]" }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "loading"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "pipe", type: TuiFormatNumberPipe, name: "tuiFormatNumber" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5408
5506
|
}
|
|
5409
5507
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScSandwichComponent, decorators: [{
|
|
5410
5508
|
type: Component,
|
|
5411
5509
|
args: [{ standalone: true, selector: 'sc-sandwich', imports: [
|
|
5510
|
+
TuiFormatNumberPipe,
|
|
5412
5511
|
TuiButton,
|
|
5413
5512
|
TuiIcon,
|
|
5414
5513
|
FormsModule,
|
|
@@ -5436,7 +5535,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
5436
5535
|
stringify: signal((x) => x.name),
|
|
5437
5536
|
identityMatcher: signal((a, b) => a.id === b.id),
|
|
5438
5537
|
}),
|
|
5439
|
-
], 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 *tuiDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error [formControl]=\"product\" />\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 formControlName=\"width\" />\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 formControlName=\"length\" />\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 formControlName=\"count\" />\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 appearance=\"secondary\"\n class=\"mt-6\"\n [style.flex]=\"'0 0 auto'\"\n >\n <tui-icon icon=\"@tui.trash-2\" />\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 tuiInput\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 formControlName=\"marker\" />\n </label>\n\n @if (product.value) {\n <tui-loader [loading]=\"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 [formGroup]=\"form\" />\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: $thumb-radius;display:flex;font:var(--tui-typography-body-s);color:var(--tui-text-secondary);margin:.25rem var(--t-offset) 0}.slider-ticks-labels>*{position:relative;flex:2;text-align:center}.slider-ticks-labels>*:first-child{inset-inline-start:calc(-1 * var(--t-offset));flex:1;text-align:start}.slider-ticks-labels>*:last-child{inset-inline-end:calc(-1 * var(--t-offset));flex:1;text-align:end}tui-range+.slider-ticks-labels{--t-offset: $thumb-diameter}tui-textfield[data-size=l]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"l\") + $thumb-radius)}tui-textfield[data-size=m]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"m\") + $thumb-radius)}tui-textfield[data-size=s]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"s\") + $thumb-radius)}tui-input-range[data-size=l]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"l\") + $thumb-diameter)}tui-input-range[data-size=m]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"m\") + $thumb-diameter)}tui-input-range[data-size=s]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"s\") + $thumb-diameter)}.slider-ticks-labels{color:var(--tui-text-secondary)}\n"] }]
|
|
5538
|
+
], 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 *tuiDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error [formControl]=\"product\" />\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 | tuiFormatNumber: moneyFormat }} {{ 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 formControlName=\"width\" />\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 formControlName=\"length\" />\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 formControlName=\"count\" />\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 appearance=\"secondary\"\n class=\"mt-6\"\n [style.flex]=\"'0 0 auto'\"\n >\n <tui-icon icon=\"@tui.trash-2\" />\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 tuiInput\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 formControlName=\"marker\" />\n </label>\n\n @if (product.value) {\n <tui-loader [loading]=\"isCalculateLoading()\">\n @if (calculateResult) {\n <div class=\"mt-2 flex flex-wrap items-end gap-2\">\n <div>\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"whitespace-nowrap text-xl font-bold\"\n >{{ getTotalCost(calculateResult) | tuiFormatNumber: moneyFormat }} {{ product.value.currency.symbol }}</span\n >\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\"\n >{{ productValue.costRub === undefined ? '' : (productValue.costRub | tuiFormatNumber: moneyFormat) }}\n {{ productValue.currency.symbol }}/\u0448\u0442.)</span\n >\n </div>\n }\n </div>\n }\n </tui-loader>\n }\n\n <tui-error [formGroup]=\"form\" />\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: $thumb-radius;display:flex;font:var(--tui-typography-body-s);color:var(--tui-text-secondary);margin:.25rem var(--t-offset) 0}.slider-ticks-labels>*{position:relative;flex:2;text-align:center}.slider-ticks-labels>*:first-child{inset-inline-start:calc(-1 * var(--t-offset));flex:1;text-align:start}.slider-ticks-labels>*:last-child{inset-inline-end:calc(-1 * var(--t-offset));flex:1;text-align:end}tui-range+.slider-ticks-labels{--t-offset: $thumb-diameter}tui-textfield[data-size=l]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"l\") + $thumb-radius)}tui-textfield[data-size=m]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"m\") + $thumb-radius)}tui-textfield[data-size=s]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"s\") + $thumb-radius)}tui-input-range[data-size=l]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"l\") + $thumb-diameter)}tui-input-range[data-size=m]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"m\") + $thumb-diameter)}tui-input-range[data-size=s]+.slider-ticks-labels{--t-offset: calc(map-get($track-inset, \"s\") + $thumb-diameter)}.slider-ticks-labels{color:var(--tui-text-secondary)}\n"] }]
|
|
5440
5539
|
}], propDecorators: { settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: false }] }], categoryId: [{ type: i0.Input, args: [{ isSignal: true, alias: "categoryId", required: true }] }], editor: [{ type: i0.Input, args: [{ isSignal: true, alias: "editor", required: true }] }], orderItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "orderItem", required: true }] }], orderId: [{
|
|
5441
5540
|
type: Input
|
|
5442
5541
|
}], toggleShowEvent: [{ type: i0.Output, args: ["toggleShowEvent"] }] } });
|
|
@@ -5496,6 +5595,14 @@ class ScSandwichM2Component {
|
|
|
5496
5595
|
* Сервис получения и редактирования списка товаров заказа (корзина / заказ / черновик = заказ).
|
|
5497
5596
|
*/
|
|
5498
5597
|
this.orderService = inject(SC_ORDER_LOADER);
|
|
5598
|
+
/**
|
|
5599
|
+
* Настройки вывода сумм в рублях.
|
|
5600
|
+
*/
|
|
5601
|
+
this.moneyFormat = ScNumberHelper.getMoneyFormat();
|
|
5602
|
+
/**
|
|
5603
|
+
* Настройки вывода площади.
|
|
5604
|
+
*/
|
|
5605
|
+
this.areaFormat = ScNumberHelper.areaFormat;
|
|
5499
5606
|
/**
|
|
5500
5607
|
* Сервис конвертации данных.
|
|
5501
5608
|
*/
|
|
@@ -5573,7 +5680,7 @@ class ScSandwichM2Component {
|
|
|
5573
5680
|
this.totalCost = computed(() => {
|
|
5574
5681
|
const cost = this.productSignal()?.costRub ?? 0;
|
|
5575
5682
|
const area = this.totalAreaM2();
|
|
5576
|
-
return
|
|
5683
|
+
return ScNumberHelper.roundMoney(area * cost);
|
|
5577
5684
|
}, ...(ngDevMode ? [{ debugName: "totalCost" }] : /* istanbul ignore next */ []));
|
|
5578
5685
|
/**
|
|
5579
5686
|
* Текст ограничения по ширине («от … до …»), пока есть выбранный товар.
|
|
@@ -5821,7 +5928,7 @@ class ScSandwichM2Component {
|
|
|
5821
5928
|
rowCost(value) {
|
|
5822
5929
|
const area = this.rowTotalPartsAreaM2(value);
|
|
5823
5930
|
const cost = this.product.value?.costRub ?? 0;
|
|
5824
|
-
return
|
|
5931
|
+
return ScNumberHelper.roundMoney(area * cost);
|
|
5825
5932
|
}
|
|
5826
5933
|
/**
|
|
5827
5934
|
* Обновляет состояние позиции на указанное значение.
|
|
@@ -5939,8 +6046,8 @@ class ScSandwichM2Component {
|
|
|
5939
6046
|
this.items.clear();
|
|
5940
6047
|
const orderItem = this.orderItem();
|
|
5941
6048
|
this.items.push(this.createItemGroup({
|
|
5942
|
-
width: (orderItem?.width ?? 0) * 1000,
|
|
5943
|
-
length: (orderItem?.length ?? 0) * 1000,
|
|
6049
|
+
width: Math.round((orderItem?.width ?? 0) * 1000),
|
|
6050
|
+
length: Math.round((orderItem?.length ?? 0) * 1000),
|
|
5944
6051
|
count: orderItem?.quantity ?? 1,
|
|
5945
6052
|
marker: orderItem?.marker ?? null,
|
|
5946
6053
|
}));
|
|
@@ -5958,11 +6065,12 @@ class ScSandwichM2Component {
|
|
|
5958
6065
|
stringify: signal((x) => x.name),
|
|
5959
6066
|
identityMatcher: signal((a, b) => a.id === b.id),
|
|
5960
6067
|
}),
|
|
5961
|
-
], 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 *tuiDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error [formControl]=\"product\" />\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 [loading]=\"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 formControlName=\"width\" />\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 formControlName=\"length\" />\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 formControlName=\"count\" />\n </label>\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiInput\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 formControlName=\"marker\" />\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 [formGroup]=\"form\" />\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.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { 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])", inputs: ["items", "emptyContent", "size", "itemContent"], outputs: ["itemClick"] }, { kind: "component", type: i2.TuiErrorComponent, selector: "tui-error", inputs: ["error"] }, { kind: "directive", type: i2.TuiErrorDirective, selector: "tui-error[ngModel], tui-error[formControlName], tui-error[formControl], tui-error[formGroup], tui-error[formGroupName], tui-error[formArrayName], tui-error[formArray]", inputs: ["order"] }, { kind: "component", type: i3$1.TuiTextfieldComponent, selector: "tui-textfield:not([multi])", inputs: ["content", "filler"] }, { kind: "directive", type: i3$1.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }, { kind: "directive", type: i3.TuiDropdownContent, selector: "ng-template[tuiDropdown]" }, { kind: "directive", type: i2.TuiInputDirective, selector: "input[tuiInput]", inputs: ["readOnly", "invalid", "focused", "state"] }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "directive", type: i1$1.TuiSelectDirective, selector: "input[tuiSelect]" }, { kind: "directive", type: i1$1.TuiInputNumberDirective, selector: "input[tuiInputNumber]" }, { kind: "directive", type: TuiNumberFormat, selector: "[tuiNumberFormat]", inputs: ["tuiNumberFormat"] }, { kind: "component", type: i6.TuiSliderComponent, selector: "input[type=range][tuiSlider]", inputs: ["segments"] }, { kind: "directive", type: i1$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[tuiInput], input[tuiInputNumber], input[tuiTextfield], input[tuiInputSlider]" }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "loading"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "component", type: TuiIcon, selector: "tui-icon:not([tuiBadge])", inputs: ["background"] }, { kind: "directive", type: TuiAutoFocus, selector: "[tuiAutoFocus]", inputs: ["tuiAutoFocus"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DecimalPipe, name: "number" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6068
|
+
], 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 *tuiDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error [formControl]=\"product\" />\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 | tuiFormatNumber: moneyFormat }} {{ 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 [loading]=\"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 formControlName=\"width\" />\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 formControlName=\"length\" />\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 formControlName=\"count\" />\n </label>\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiInput\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 formControlName=\"marker\" />\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) | tuiFormatNumber: areaFormat }} \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) | tuiFormatNumber: moneyFormat }} {{ 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() | tuiFormatNumber: areaFormat }} \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() | tuiFormatNumber: moneyFormat }} {{ productValue.currency.symbol }} </span>\n </div>\n }\n </div>\n }\n </div>\n\n <tui-error [formGroup]=\"form\" />\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.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { 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])", inputs: ["items", "emptyContent", "size", "itemContent"], outputs: ["itemClick"] }, { kind: "component", type: i2.TuiErrorComponent, selector: "tui-error", inputs: ["error"] }, { kind: "directive", type: i2.TuiErrorDirective, selector: "tui-error[ngModel], tui-error[formControlName], tui-error[formControl], tui-error[formGroup], tui-error[formGroupName], tui-error[formArrayName], tui-error[formArray]", inputs: ["order"] }, { kind: "component", type: i3$1.TuiTextfieldComponent, selector: "tui-textfield:not([multi])", inputs: ["content", "filler"] }, { kind: "directive", type: i3$1.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }, { kind: "directive", type: i3.TuiDropdownContent, selector: "ng-template[tuiDropdown]" }, { kind: "directive", type: i2.TuiInputDirective, selector: "input[tuiInput]", inputs: ["readOnly", "invalid", "focused", "state"] }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "directive", type: i1$1.TuiSelectDirective, selector: "input[tuiSelect]" }, { kind: "directive", type: i1$1.TuiInputNumberDirective, selector: "input[tuiInputNumber]" }, { kind: "directive", type: TuiNumberFormat, selector: "[tuiNumberFormat]", inputs: ["tuiNumberFormat"] }, { kind: "component", type: i6.TuiSliderComponent, selector: "input[type=range][tuiSlider]", inputs: ["segments"] }, { kind: "directive", type: i1$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[tuiInput], input[tuiInputNumber], input[tuiTextfield], input[tuiInputSlider]" }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "loading"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "component", type: TuiIcon, selector: "tui-icon:not([tuiBadge])", inputs: ["background"] }, { kind: "directive", type: TuiAutoFocus, selector: "[tuiAutoFocus]", inputs: ["tuiAutoFocus"] }, { kind: "pipe", type: TuiFormatNumberPipe, name: "tuiFormatNumber" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5962
6069
|
}
|
|
5963
6070
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScSandwichM2Component, decorators: [{
|
|
5964
6071
|
type: Component,
|
|
5965
6072
|
args: [{ standalone: true, selector: 'sc-sandwich-m2', imports: [
|
|
6073
|
+
TuiFormatNumberPipe,
|
|
5966
6074
|
TuiButton,
|
|
5967
6075
|
FormsModule,
|
|
5968
6076
|
ReactiveFormsModule,
|
|
@@ -5976,7 +6084,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
5976
6084
|
TuiInputNumber,
|
|
5977
6085
|
TuiNumberFormat,
|
|
5978
6086
|
AsyncPipe,
|
|
5979
|
-
DecimalPipe,
|
|
5980
6087
|
TuiInputSlider,
|
|
5981
6088
|
ScSelectOnFocusinDirective,
|
|
5982
6089
|
TuiLoader,
|
|
@@ -5992,7 +6099,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
5992
6099
|
stringify: signal((x) => x.name),
|
|
5993
6100
|
identityMatcher: signal((a, b) => a.id === b.id),
|
|
5994
6101
|
}),
|
|
5995
|
-
], 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 *tuiDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error [formControl]=\"product\" />\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 [loading]=\"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 formControlName=\"width\" />\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 formControlName=\"length\" />\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 formControlName=\"count\" />\n </label>\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiInput\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 formControlName=\"marker\" />\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 [formGroup]=\"form\" />\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"] }]
|
|
6102
|
+
], 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 *tuiDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error [formControl]=\"product\" />\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 | tuiFormatNumber: moneyFormat }} {{ 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 [loading]=\"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 formControlName=\"width\" />\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 formControlName=\"length\" />\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 formControlName=\"count\" />\n </label>\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiInput\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 formControlName=\"marker\" />\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) | tuiFormatNumber: areaFormat }} \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) | tuiFormatNumber: moneyFormat }} {{ 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() | tuiFormatNumber: areaFormat }} \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() | tuiFormatNumber: moneyFormat }} {{ productValue.currency.symbol }} </span>\n </div>\n }\n </div>\n }\n </div>\n\n <tui-error [formGroup]=\"form\" />\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"] }]
|
|
5996
6103
|
}], propDecorators: { settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: false }] }], categoryId: [{ type: i0.Input, args: [{ isSignal: true, alias: "categoryId", required: true }] }], editor: [{ type: i0.Input, args: [{ isSignal: true, alias: "editor", required: true }] }], orderItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "orderItem", required: true }] }], orderId: [{
|
|
5997
6104
|
type: Input
|
|
5998
6105
|
}], toggleShowEvent: [{ type: i0.Output, args: ["toggleShowEvent"] }] } });
|
|
@@ -6740,14 +6847,6 @@ class ScAddDeliveryAddressDialogComponent {
|
|
|
6740
6847
|
}),
|
|
6741
6848
|
});
|
|
6742
6849
|
}
|
|
6743
|
-
/**
|
|
6744
|
-
* Округляет координаты до 6 цифр после запятой.
|
|
6745
|
-
*
|
|
6746
|
-
* @param coords Координаты точки.
|
|
6747
|
-
*/
|
|
6748
|
-
static roundCoordinate(coords) {
|
|
6749
|
-
return coords.map((coord) => Math.round(coord * 1e6) / 1e6);
|
|
6750
|
-
}
|
|
6751
6850
|
/** @inheritdoc */
|
|
6752
6851
|
ngAfterViewInit() {
|
|
6753
6852
|
this.userMetrikaService.emitUserMetrikaEvent({
|
|
@@ -6780,7 +6879,7 @@ class ScAddDeliveryAddressDialogComponent {
|
|
|
6780
6879
|
*/
|
|
6781
6880
|
onSelectedAddress(suggestion) {
|
|
6782
6881
|
if ('addressString' in suggestion && suggestion.geoCoordinates) {
|
|
6783
|
-
const coords =
|
|
6882
|
+
const coords = [suggestion.geoCoordinates.lat, suggestion.geoCoordinates.long].map((coord) => ScNumberHelper.roundCoordinate(coord));
|
|
6784
6883
|
this.addressPlacemark ??= this.createPlacemark(coords);
|
|
6785
6884
|
this.setGeoCoordinates(coords);
|
|
6786
6885
|
if (!this.yaMap?.geoObjects.getLength()) {
|
|
@@ -6803,8 +6902,8 @@ class ScAddDeliveryAddressDialogComponent {
|
|
|
6803
6902
|
this.addressPlacemark.geometry?.setCoordinates(coords);
|
|
6804
6903
|
this.form.patchValue({
|
|
6805
6904
|
coordinates: {
|
|
6806
|
-
lat:
|
|
6807
|
-
long:
|
|
6905
|
+
lat: coords[0],
|
|
6906
|
+
long: coords[1],
|
|
6808
6907
|
},
|
|
6809
6908
|
});
|
|
6810
6909
|
}
|
|
@@ -6840,7 +6939,7 @@ class ScAddDeliveryAddressDialogComponent {
|
|
|
6840
6939
|
placemark.events.add('dragend', () => {
|
|
6841
6940
|
const coord = this.addressPlacemark?.geometry?.getCoordinates();
|
|
6842
6941
|
if (coord) {
|
|
6843
|
-
this.setGeoCoordinates(
|
|
6942
|
+
this.setGeoCoordinates(coord.map((value) => ScNumberHelper.roundCoordinate(value)));
|
|
6844
6943
|
}
|
|
6845
6944
|
});
|
|
6846
6945
|
return placemark;
|
|
@@ -7086,6 +7185,10 @@ class ScErrorBlockStatusComponent {
|
|
|
7086
7185
|
* Создает сигнал изменения строкового представления об ошибке.
|
|
7087
7186
|
*/
|
|
7088
7187
|
this.pageErrorChange = output();
|
|
7188
|
+
/**
|
|
7189
|
+
* Статус ответа, когда код ошибки не является HTTP-статусом (0 при обрыве соединения с API).
|
|
7190
|
+
*/
|
|
7191
|
+
this.unavailableResponseStatus = 503;
|
|
7089
7192
|
/**
|
|
7090
7193
|
* Признак, что текущий скрипт исполняется на сервере.
|
|
7091
7194
|
*/
|
|
@@ -7102,11 +7205,19 @@ class ScErrorBlockStatusComponent {
|
|
|
7102
7205
|
if (this.code() !== null) {
|
|
7103
7206
|
this.pageErrorChange.emit(this.error());
|
|
7104
7207
|
if (this.isServer && this.responseInit) {
|
|
7105
|
-
this.responseInit.status = this.code()
|
|
7208
|
+
this.responseInit.status = this.getResponseStatus(this.code());
|
|
7106
7209
|
}
|
|
7107
7210
|
}
|
|
7108
7211
|
});
|
|
7109
7212
|
}
|
|
7213
|
+
/**
|
|
7214
|
+
* Возвращает HTTP-статус ответа для кода ошибки; код вне 400-599 заменяется на {@link unavailableResponseStatus}.
|
|
7215
|
+
*
|
|
7216
|
+
* @param code Код ошибки.
|
|
7217
|
+
*/
|
|
7218
|
+
getResponseStatus(code) {
|
|
7219
|
+
return code !== null && code >= 400 && code <= 599 ? code : this.unavailableResponseStatus;
|
|
7220
|
+
}
|
|
7110
7221
|
/**
|
|
7111
7222
|
* Возвращает описание ошибки.
|
|
7112
7223
|
*
|
|
@@ -7754,28 +7865,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
7754
7865
|
}]
|
|
7755
7866
|
}], propDecorators: { orderId: [{ type: i0.Input, args: [{ isSignal: true, alias: "orderId", required: false }] }] } });
|
|
7756
7867
|
|
|
7757
|
-
/**
|
|
7758
|
-
* Группа позиций заказа по направлению продаж.
|
|
7759
|
-
*/
|
|
7760
|
-
class ScOrderItemsByDirection {
|
|
7761
|
-
/**
|
|
7762
|
-
* @param direction Направление продаж.
|
|
7763
|
-
* @param allItems Все элементы заказа.
|
|
7764
|
-
*/
|
|
7765
|
-
constructor(direction, allItems) {
|
|
7766
|
-
this.direction = direction;
|
|
7767
|
-
this.items = allItems.filter((item) => item.salesDirection === direction.id);
|
|
7768
|
-
}
|
|
7769
|
-
/**
|
|
7770
|
-
* Получает список позиций заказа по идентификаторам.
|
|
7771
|
-
*
|
|
7772
|
-
* @param itemsIds Идентификаторы позиций.
|
|
7773
|
-
*/
|
|
7774
|
-
getItemsByIds(itemsIds) {
|
|
7775
|
-
return this.items.filter((item) => itemsIds.includes(item.id));
|
|
7776
|
-
}
|
|
7777
|
-
}
|
|
7778
|
-
|
|
7779
7868
|
/**
|
|
7780
7869
|
* Компонент карточки элемента корзины.
|
|
7781
7870
|
*/
|
|
@@ -7790,6 +7879,10 @@ class ScOrderItemComponent extends AbstractScPriceCard {
|
|
|
7790
7879
|
* Событие нажатия на кнопку редактирования конфигурации.
|
|
7791
7880
|
*/
|
|
7792
7881
|
this.clickSettings = output();
|
|
7882
|
+
/**
|
|
7883
|
+
* Настройки вывода сумм в рублях.
|
|
7884
|
+
*/
|
|
7885
|
+
this.moneyFormat = ScNumberHelper.getMoneyFormat();
|
|
7793
7886
|
/**
|
|
7794
7887
|
* Сервис диалогового окна предварительного просмотра.
|
|
7795
7888
|
*/
|
|
@@ -7833,7 +7926,7 @@ class ScOrderItemComponent extends AbstractScPriceCard {
|
|
|
7833
7926
|
appearance: signal('textfield'),
|
|
7834
7927
|
}),
|
|
7835
7928
|
tuiHintOptionsProvider({ direction: 'top', showDelay: 100, hideDelay: 100 }),
|
|
7836
|
-
], usesInheritance: true, ngImport: i0, template: "@if (product && orderItem) {\n <div class=\"@container relative flex w-full gap-4 rounded-xl p-1 text-body-s hover:bg-tui-background-neutral-1\">\n <sc-noindex-wrapper>\n @let isDisabled = product.isHidden || product.isNull;\n <sc-hover-image-carousel\n (click)=\"isDisabled ? null : clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n [isShowActions]=\"false\"\n class=\"aspect-square w-24 shrink-0 cursor-pointer self-start\"\n />\n <div class=\"flex w-full flex-col gap-y-1 gap-x-4 @5xl:flex-row @5xl:items-center @5xl:gap-5\">\n <div class=\"flex min-w-0 flex-1 flex-col gap-1\">\n <div\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </div>\n <div class=\"flex flex-col gap-1\">\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n [class.disabled]=\"isDisabled\"\n class=\"!text-body-m-bold\"\n >\n {{ product.name }}\n </a>\n @if (product.supplierSku) {\n <span class=\"text-tui-text-02\"> \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }} </span>\n }\n @if (product.pack) {\n <div class=\"flex items-center gap-1 text-tui-text-02\">\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n @if (product.ignoreMinCountCheck) {\n <tui-icon\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n tuiHintDirection=\"top\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n }\n </div>\n }\n\n <sc-cost-with-discount\n scPrint=\"cost\"\n [product]=\"product\"\n />\n </div>\n @if (orderItem.specificationImgUrl) {\n <a\n tuiLink\n (click)=\"showSpecification(specificationPreview)\"\n [class.disabled]=\"isDisabled\"\n >\n \u0421\u043F\u0435\u0446\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F\n </a>\n }\n <ng-template\n #specificationPreview\n let-preview\n >\n <tui-preview\n [rotatable]=\"false\"\n [zoomable]=\"false\"\n >\n <img\n *polymorpheusOutlet=\"orderItem.specificationImgUrl as src\"\n alt=\"preview\"\n [src]=\"orderItem.specificationImgUrl\"\n />\n <button\n iconStart=\"@tui.x\"\n title=\"Close\"\n tuiIconButton\n tuiPreviewAction\n type=\"button\"\n (click)=\"preview.complete()\"\n ></button>\n </tui-preview>\n </ng-template>\n </div>\n <div class=\"grid grid-cols-1 @lg:grid-cols-3 gap-2 @2xl:gap-4 @2xl:grid-rows-1\">\n <div class=\"grid grid-cols-1 items-center @lg:gap-2 @2xl:grid-cols-2 @lg:col-span-2\">\n <!-- \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls() && showQuantityControl) {\n <!-- \u041F\u043E\u043B\u0435 \u0432\u0432\u043E\u0434\u0430 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n <sc-input-quantity\n #inputQuantity\n [tuiAutoFocus]=\"autoFocuseQuantityInput()\"\n [formControl]=\"quantityControl\"\n size=\"m\"\n [showCross]=\"false\"\n [isDisabled]=\"isDisabled\"\n [step]=\"getProductMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-32 shrink-0\"\n />\n } @else {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n >\n <div class=\"!text-body-m text-start\">\n \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E:\n <strong> {{ orderItem.quantity }} \u0448\u0442.</strong>\n </div>\n </button>\n }\n\n @let showAdditionalInfo = orderItem.configurator || orderItem.height || orderItem.length || orderItem.width || orderItem.marker;\n @if (showAdditionalInfo) {\n <div class=\"flex items-center gap-2 @lg:gap-3 max-w-min\">\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls()) {\n <button\n tuiIconButton\n [disabled]=\"isDisabled\"\n [loading]=\"showLoader()\"\n (click)=\"clickSettings.emit()\"\n size=\"s\"\n [appearance]=\"isConfiguratorHintVisible() ? 'primary' : 'secondary'\"\n class=\"shrink-0\"\n >\n <tui-icon icon=\"@tui.settings\" />\n </button>\n }\n\n <!-- \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F \u043E \u0442\u043E\u0432\u0430\u0440\u0435. -->\n <div\n class=\"flex flex-col gap-x-1 text-tui-base-07\"\n [class.text-body-m]=\"!isShowEditControls()\"\n >\n @if (orderItem.marker) {\n <p>\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430: {{ orderItem.marker }}</p>\n }\n @if (orderItem.width) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0448\u0438\u0440\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0428\u0438\u0440\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.width }} \u043C.</span>\n </button>\n }\n @if (orderItem.height) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432\u044B\u0441\u043E\u0442\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0412\u044B\u0441\u043E\u0442\u0430: <span class=\"text-body-s-bold\">{{ orderItem.height }} \u043C.</span>\n </button>\n } @else if (orderItem.length) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0434\u043B\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0414\u043B\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.length }} \u043C.</span>\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- \u0421\u0443\u043C\u043C\u0430 \u0442\u043E\u0432\u0430\u0440\u0430 \u0438 \u0441\u043A\u043B\u0430\u0434\u0441\u043A\u043E\u0435 \u043D\u0430\u043B\u0438\u0447\u0438\u0435. -->\n <div\n scPrint=\"cost\"\n class=\"flex min-w-[11rem] flex-col @lg:justify-end @2xl:!justify-center text-body-m\"\n >\n <p class=\"whitespace-nowrap\">\n \u0421\u0443\u043C\u043C\u0430:\n <strong> {{ orderItem.costRub | tuiFormatNumber: { precision: 2, decimalSeparator: '.', rounding: 'ceil' } }} {{ 'RUB' | tuiCurrency }}</strong>\n </p>\n <sc-price-warehouse-stock\n scPrint=\"defaultNoPrint\"\n [product]=\"product\"\n />\n </div>\n </div>\n </div>\n </sc-noindex-wrapper>\n </div>\n} @else {\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiIcon, selector: "tui-icon:not([tuiBadge])", inputs: ["background"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.TuiHintDirective, selector: "[tuiHint]:not(ng-container):not(ng-template)", inputs: ["tuiHint", "tuiHintContext", "tuiHintAppearance"], outputs: ["tuiHintVisible"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]" }, { kind: "directive", type: TuiHighlight, selector: "[tuiHighlight]", inputs: ["tuiHighlight", "tuiHighlightColor"] }, { kind: "directive", type: TuiAutoFocus, selector: "[tuiAutoFocus]", inputs: ["tuiAutoFocus"] }, { kind: "component", type: ScHoverImageCarouselComponent, selector: "sc-hover-image-carousel", inputs: ["images", "isShowActions", "productName"] }, { kind: "component", type: CostWithDiscountComponent, selector: "sc-cost-with-discount", inputs: ["product", "size"] }, { kind: "component", type: ScPriceWarehouseStockComponent, selector: "sc-price-warehouse-stock", inputs: ["classList", "product", "withStockHint", "fromMain"] }, { kind: "component", type: ScInputQuantityComponent, selector: "sc-input-quantity", inputs: ["step", "showLoader", "showCross", "appearance", "isDisabled", "size", "ignoreStepValidators"], outputs: ["clickClearEvent"] }, { kind: "component", type: i1$1.TuiPreviewComponent, selector: "tui-preview", inputs: ["zoomable", "rotatable", "initialScale"] }, { kind: "directive", type: i1$1.TuiPreviewAction, selector: "[tuiPreviewAction]" }, { kind: "component", type: ScNoindexWrapperComponent, selector: "sc-noindex-wrapper" }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "directive", type: ScPrintDirective, selector: "[scPrint]", inputs: ["scPrint"] }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type: TuiCurrencyPipe, name: "tuiCurrency" }, { kind: "pipe", type: TuiFormatNumberPipe, name: "tuiFormatNumber" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7929
|
+
], usesInheritance: true, ngImport: i0, template: "@if (product && orderItem) {\n <div class=\"@container relative flex w-full gap-4 rounded-xl p-1 text-body-s hover:bg-tui-background-neutral-1\">\n <sc-noindex-wrapper>\n @let isDisabled = product.isHidden || product.isNull;\n <sc-hover-image-carousel\n (click)=\"isDisabled ? null : clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n [isShowActions]=\"false\"\n class=\"aspect-square w-24 shrink-0 cursor-pointer self-start\"\n />\n <div class=\"flex w-full flex-col gap-y-1 gap-x-4 @5xl:flex-row @5xl:items-center @5xl:gap-5\">\n <div class=\"flex min-w-0 flex-1 flex-col gap-1\">\n <div\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </div>\n <div class=\"flex flex-col gap-1\">\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n [class.disabled]=\"isDisabled\"\n class=\"!text-body-m-bold\"\n >\n {{ product.name }}\n </a>\n @if (product.supplierSku) {\n <span class=\"text-tui-text-02\"> \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }} </span>\n }\n @if (product.pack) {\n <div class=\"flex items-center gap-1 text-tui-text-02\">\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n @if (product.ignoreMinCountCheck) {\n <tui-icon\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n tuiHintDirection=\"top\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n }\n </div>\n }\n\n <sc-cost-with-discount\n scPrint=\"cost\"\n [product]=\"product\"\n />\n </div>\n @if (orderItem.specificationImgUrl) {\n <a\n tuiLink\n (click)=\"showSpecification(specificationPreview)\"\n [class.disabled]=\"isDisabled\"\n >\n \u0421\u043F\u0435\u0446\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F\n </a>\n }\n <ng-template\n #specificationPreview\n let-preview\n >\n <tui-preview\n [rotatable]=\"false\"\n [zoomable]=\"false\"\n >\n <img\n *polymorpheusOutlet=\"orderItem.specificationImgUrl as src\"\n alt=\"preview\"\n [src]=\"orderItem.specificationImgUrl\"\n />\n <button\n iconStart=\"@tui.x\"\n title=\"Close\"\n tuiIconButton\n tuiPreviewAction\n type=\"button\"\n (click)=\"preview.complete()\"\n ></button>\n </tui-preview>\n </ng-template>\n </div>\n <div class=\"grid grid-cols-1 @lg:grid-cols-3 gap-2 @2xl:gap-4 @2xl:grid-rows-1\">\n <div class=\"grid grid-cols-1 items-center @lg:gap-2 @2xl:grid-cols-2 @lg:col-span-2\">\n <!-- \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls() && showQuantityControl) {\n <!-- \u041F\u043E\u043B\u0435 \u0432\u0432\u043E\u0434\u0430 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n <sc-input-quantity\n #inputQuantity\n [tuiAutoFocus]=\"autoFocuseQuantityInput()\"\n [formControl]=\"quantityControl\"\n size=\"m\"\n [showCross]=\"false\"\n [isDisabled]=\"isDisabled\"\n [step]=\"getProductMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-32 shrink-0\"\n />\n } @else {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n >\n <div class=\"!text-body-m text-start\">\n \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E:\n <strong> {{ orderItem.quantity }} \u0448\u0442.</strong>\n </div>\n </button>\n }\n\n @let showAdditionalInfo = orderItem.configurator || orderItem.height || orderItem.length || orderItem.width || orderItem.marker;\n @if (showAdditionalInfo) {\n <div class=\"flex items-center gap-2 @lg:gap-3 max-w-min\">\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls()) {\n <button\n tuiIconButton\n [disabled]=\"isDisabled\"\n [loading]=\"showLoader()\"\n (click)=\"clickSettings.emit()\"\n size=\"s\"\n [appearance]=\"isConfiguratorHintVisible() ? 'primary' : 'secondary'\"\n class=\"shrink-0\"\n >\n <tui-icon icon=\"@tui.settings\" />\n </button>\n }\n\n <!-- \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F \u043E \u0442\u043E\u0432\u0430\u0440\u0435. -->\n <div\n class=\"flex flex-col gap-x-1 text-tui-base-07\"\n [class.text-body-m]=\"!isShowEditControls()\"\n >\n @if (orderItem.marker) {\n <p>\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430: {{ orderItem.marker }}</p>\n }\n @if (orderItem.width) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0448\u0438\u0440\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0428\u0438\u0440\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.width }} \u043C.</span>\n </button>\n }\n @if (orderItem.height) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432\u044B\u0441\u043E\u0442\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0412\u044B\u0441\u043E\u0442\u0430: <span class=\"text-body-s-bold\">{{ orderItem.height }} \u043C.</span>\n </button>\n } @else if (orderItem.length) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0434\u043B\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0414\u043B\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.length }} \u043C.</span>\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- \u0421\u0443\u043C\u043C\u0430 \u0442\u043E\u0432\u0430\u0440\u0430 \u0438 \u0441\u043A\u043B\u0430\u0434\u0441\u043A\u043E\u0435 \u043D\u0430\u043B\u0438\u0447\u0438\u0435. -->\n <div\n scPrint=\"cost\"\n class=\"flex min-w-[11rem] flex-col @lg:justify-end @2xl:!justify-center text-body-m\"\n >\n <p class=\"whitespace-nowrap\">\n \u0421\u0443\u043C\u043C\u0430:\n <strong> {{ orderItem.costRub | tuiFormatNumber: moneyFormat }} {{ 'RUB' | tuiCurrency }}</strong>\n </p>\n <sc-price-warehouse-stock\n scPrint=\"defaultNoPrint\"\n [product]=\"product\"\n />\n </div>\n </div>\n </div>\n </sc-noindex-wrapper>\n </div>\n} @else {\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiIcon, selector: "tui-icon:not([tuiBadge])", inputs: ["background"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.TuiHintDirective, selector: "[tuiHint]:not(ng-container):not(ng-template)", inputs: ["tuiHint", "tuiHintContext", "tuiHintAppearance"], outputs: ["tuiHintVisible"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]" }, { kind: "directive", type: TuiHighlight, selector: "[tuiHighlight]", inputs: ["tuiHighlight", "tuiHighlightColor"] }, { kind: "directive", type: TuiAutoFocus, selector: "[tuiAutoFocus]", inputs: ["tuiAutoFocus"] }, { kind: "component", type: ScHoverImageCarouselComponent, selector: "sc-hover-image-carousel", inputs: ["images", "isShowActions", "productName"] }, { kind: "component", type: CostWithDiscountComponent, selector: "sc-cost-with-discount", inputs: ["product", "size"] }, { kind: "component", type: ScPriceWarehouseStockComponent, selector: "sc-price-warehouse-stock", inputs: ["classList", "product", "withStockHint", "fromMain"] }, { kind: "component", type: ScInputQuantityComponent, selector: "sc-input-quantity", inputs: ["step", "showLoader", "showCross", "appearance", "isDisabled", "size", "ignoreStepValidators"], outputs: ["clickClearEvent"] }, { kind: "component", type: i1$1.TuiPreviewComponent, selector: "tui-preview", inputs: ["zoomable", "rotatable", "initialScale"] }, { kind: "directive", type: i1$1.TuiPreviewAction, selector: "[tuiPreviewAction]" }, { kind: "component", type: ScNoindexWrapperComponent, selector: "sc-noindex-wrapper" }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "directive", type: ScPrintDirective, selector: "[scPrint]", inputs: ["scPrint"] }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type: TuiCurrencyPipe, name: "tuiCurrency" }, { kind: "pipe", type: TuiFormatNumberPipe, name: "tuiFormatNumber" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7837
7930
|
}
|
|
7838
7931
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScOrderItemComponent, decorators: [{
|
|
7839
7932
|
type: Component,
|
|
@@ -7869,13 +7962,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
7869
7962
|
appearance: signal('textfield'),
|
|
7870
7963
|
}),
|
|
7871
7964
|
tuiHintOptionsProvider({ direction: 'top', showDelay: 100, hideDelay: 100 }),
|
|
7872
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (product && orderItem) {\n <div class=\"@container relative flex w-full gap-4 rounded-xl p-1 text-body-s hover:bg-tui-background-neutral-1\">\n <sc-noindex-wrapper>\n @let isDisabled = product.isHidden || product.isNull;\n <sc-hover-image-carousel\n (click)=\"isDisabled ? null : clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n [isShowActions]=\"false\"\n class=\"aspect-square w-24 shrink-0 cursor-pointer self-start\"\n />\n <div class=\"flex w-full flex-col gap-y-1 gap-x-4 @5xl:flex-row @5xl:items-center @5xl:gap-5\">\n <div class=\"flex min-w-0 flex-1 flex-col gap-1\">\n <div\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </div>\n <div class=\"flex flex-col gap-1\">\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n [class.disabled]=\"isDisabled\"\n class=\"!text-body-m-bold\"\n >\n {{ product.name }}\n </a>\n @if (product.supplierSku) {\n <span class=\"text-tui-text-02\"> \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }} </span>\n }\n @if (product.pack) {\n <div class=\"flex items-center gap-1 text-tui-text-02\">\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n @if (product.ignoreMinCountCheck) {\n <tui-icon\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n tuiHintDirection=\"top\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n }\n </div>\n }\n\n <sc-cost-with-discount\n scPrint=\"cost\"\n [product]=\"product\"\n />\n </div>\n @if (orderItem.specificationImgUrl) {\n <a\n tuiLink\n (click)=\"showSpecification(specificationPreview)\"\n [class.disabled]=\"isDisabled\"\n >\n \u0421\u043F\u0435\u0446\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F\n </a>\n }\n <ng-template\n #specificationPreview\n let-preview\n >\n <tui-preview\n [rotatable]=\"false\"\n [zoomable]=\"false\"\n >\n <img\n *polymorpheusOutlet=\"orderItem.specificationImgUrl as src\"\n alt=\"preview\"\n [src]=\"orderItem.specificationImgUrl\"\n />\n <button\n iconStart=\"@tui.x\"\n title=\"Close\"\n tuiIconButton\n tuiPreviewAction\n type=\"button\"\n (click)=\"preview.complete()\"\n ></button>\n </tui-preview>\n </ng-template>\n </div>\n <div class=\"grid grid-cols-1 @lg:grid-cols-3 gap-2 @2xl:gap-4 @2xl:grid-rows-1\">\n <div class=\"grid grid-cols-1 items-center @lg:gap-2 @2xl:grid-cols-2 @lg:col-span-2\">\n <!-- \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls() && showQuantityControl) {\n <!-- \u041F\u043E\u043B\u0435 \u0432\u0432\u043E\u0434\u0430 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n <sc-input-quantity\n #inputQuantity\n [tuiAutoFocus]=\"autoFocuseQuantityInput()\"\n [formControl]=\"quantityControl\"\n size=\"m\"\n [showCross]=\"false\"\n [isDisabled]=\"isDisabled\"\n [step]=\"getProductMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-32 shrink-0\"\n />\n } @else {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n >\n <div class=\"!text-body-m text-start\">\n \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E:\n <strong> {{ orderItem.quantity }} \u0448\u0442.</strong>\n </div>\n </button>\n }\n\n @let showAdditionalInfo = orderItem.configurator || orderItem.height || orderItem.length || orderItem.width || orderItem.marker;\n @if (showAdditionalInfo) {\n <div class=\"flex items-center gap-2 @lg:gap-3 max-w-min\">\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls()) {\n <button\n tuiIconButton\n [disabled]=\"isDisabled\"\n [loading]=\"showLoader()\"\n (click)=\"clickSettings.emit()\"\n size=\"s\"\n [appearance]=\"isConfiguratorHintVisible() ? 'primary' : 'secondary'\"\n class=\"shrink-0\"\n >\n <tui-icon icon=\"@tui.settings\" />\n </button>\n }\n\n <!-- \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F \u043E \u0442\u043E\u0432\u0430\u0440\u0435. -->\n <div\n class=\"flex flex-col gap-x-1 text-tui-base-07\"\n [class.text-body-m]=\"!isShowEditControls()\"\n >\n @if (orderItem.marker) {\n <p>\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430: {{ orderItem.marker }}</p>\n }\n @if (orderItem.width) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0448\u0438\u0440\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0428\u0438\u0440\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.width }} \u043C.</span>\n </button>\n }\n @if (orderItem.height) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432\u044B\u0441\u043E\u0442\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0412\u044B\u0441\u043E\u0442\u0430: <span class=\"text-body-s-bold\">{{ orderItem.height }} \u043C.</span>\n </button>\n } @else if (orderItem.length) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0434\u043B\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0414\u043B\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.length }} \u043C.</span>\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- \u0421\u0443\u043C\u043C\u0430 \u0442\u043E\u0432\u0430\u0440\u0430 \u0438 \u0441\u043A\u043B\u0430\u0434\u0441\u043A\u043E\u0435 \u043D\u0430\u043B\u0438\u0447\u0438\u0435. -->\n <div\n scPrint=\"cost\"\n class=\"flex min-w-[11rem] flex-col @lg:justify-end @2xl:!justify-center text-body-m\"\n >\n <p class=\"whitespace-nowrap\">\n \u0421\u0443\u043C\u043C\u0430:\n <strong> {{ orderItem.costRub | tuiFormatNumber: { precision: 2, decimalSeparator: '.', rounding: 'ceil' } }} {{ 'RUB' | tuiCurrency }}</strong>\n </p>\n <sc-price-warehouse-stock\n scPrint=\"defaultNoPrint\"\n [product]=\"product\"\n />\n </div>\n </div>\n </div>\n </sc-noindex-wrapper>\n </div>\n} @else {\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n}\n" }]
|
|
7965
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (product && orderItem) {\n <div class=\"@container relative flex w-full gap-4 rounded-xl p-1 text-body-s hover:bg-tui-background-neutral-1\">\n <sc-noindex-wrapper>\n @let isDisabled = product.isHidden || product.isNull;\n <sc-hover-image-carousel\n (click)=\"isDisabled ? null : clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n [isShowActions]=\"false\"\n class=\"aspect-square w-24 shrink-0 cursor-pointer self-start\"\n />\n <div class=\"flex w-full flex-col gap-y-1 gap-x-4 @5xl:flex-row @5xl:items-center @5xl:gap-5\">\n <div class=\"flex min-w-0 flex-1 flex-col gap-1\">\n <div\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </div>\n <div class=\"flex flex-col gap-1\">\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n [class.disabled]=\"isDisabled\"\n class=\"!text-body-m-bold\"\n >\n {{ product.name }}\n </a>\n @if (product.supplierSku) {\n <span class=\"text-tui-text-02\"> \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }} </span>\n }\n @if (product.pack) {\n <div class=\"flex items-center gap-1 text-tui-text-02\">\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n @if (product.ignoreMinCountCheck) {\n <tui-icon\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n tuiHintDirection=\"top\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n }\n </div>\n }\n\n <sc-cost-with-discount\n scPrint=\"cost\"\n [product]=\"product\"\n />\n </div>\n @if (orderItem.specificationImgUrl) {\n <a\n tuiLink\n (click)=\"showSpecification(specificationPreview)\"\n [class.disabled]=\"isDisabled\"\n >\n \u0421\u043F\u0435\u0446\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F\n </a>\n }\n <ng-template\n #specificationPreview\n let-preview\n >\n <tui-preview\n [rotatable]=\"false\"\n [zoomable]=\"false\"\n >\n <img\n *polymorpheusOutlet=\"orderItem.specificationImgUrl as src\"\n alt=\"preview\"\n [src]=\"orderItem.specificationImgUrl\"\n />\n <button\n iconStart=\"@tui.x\"\n title=\"Close\"\n tuiIconButton\n tuiPreviewAction\n type=\"button\"\n (click)=\"preview.complete()\"\n ></button>\n </tui-preview>\n </ng-template>\n </div>\n <div class=\"grid grid-cols-1 @lg:grid-cols-3 gap-2 @2xl:gap-4 @2xl:grid-rows-1\">\n <div class=\"grid grid-cols-1 items-center @lg:gap-2 @2xl:grid-cols-2 @lg:col-span-2\">\n <!-- \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls() && showQuantityControl) {\n <!-- \u041F\u043E\u043B\u0435 \u0432\u0432\u043E\u0434\u0430 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n <sc-input-quantity\n #inputQuantity\n [tuiAutoFocus]=\"autoFocuseQuantityInput()\"\n [formControl]=\"quantityControl\"\n size=\"m\"\n [showCross]=\"false\"\n [isDisabled]=\"isDisabled\"\n [step]=\"getProductMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-32 shrink-0\"\n />\n } @else {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n >\n <div class=\"!text-body-m text-start\">\n \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E:\n <strong> {{ orderItem.quantity }} \u0448\u0442.</strong>\n </div>\n </button>\n }\n\n @let showAdditionalInfo = orderItem.configurator || orderItem.height || orderItem.length || orderItem.width || orderItem.marker;\n @if (showAdditionalInfo) {\n <div class=\"flex items-center gap-2 @lg:gap-3 max-w-min\">\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls()) {\n <button\n tuiIconButton\n [disabled]=\"isDisabled\"\n [loading]=\"showLoader()\"\n (click)=\"clickSettings.emit()\"\n size=\"s\"\n [appearance]=\"isConfiguratorHintVisible() ? 'primary' : 'secondary'\"\n class=\"shrink-0\"\n >\n <tui-icon icon=\"@tui.settings\" />\n </button>\n }\n\n <!-- \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F \u043E \u0442\u043E\u0432\u0430\u0440\u0435. -->\n <div\n class=\"flex flex-col gap-x-1 text-tui-base-07\"\n [class.text-body-m]=\"!isShowEditControls()\"\n >\n @if (orderItem.marker) {\n <p>\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430: {{ orderItem.marker }}</p>\n }\n @if (orderItem.width) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0448\u0438\u0440\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0428\u0438\u0440\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.width }} \u043C.</span>\n </button>\n }\n @if (orderItem.height) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432\u044B\u0441\u043E\u0442\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0412\u044B\u0441\u043E\u0442\u0430: <span class=\"text-body-s-bold\">{{ orderItem.height }} \u043C.</span>\n </button>\n } @else if (orderItem.length) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0434\u043B\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0414\u043B\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.length }} \u043C.</span>\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- \u0421\u0443\u043C\u043C\u0430 \u0442\u043E\u0432\u0430\u0440\u0430 \u0438 \u0441\u043A\u043B\u0430\u0434\u0441\u043A\u043E\u0435 \u043D\u0430\u043B\u0438\u0447\u0438\u0435. -->\n <div\n scPrint=\"cost\"\n class=\"flex min-w-[11rem] flex-col @lg:justify-end @2xl:!justify-center text-body-m\"\n >\n <p class=\"whitespace-nowrap\">\n \u0421\u0443\u043C\u043C\u0430:\n <strong> {{ orderItem.costRub | tuiFormatNumber: moneyFormat }} {{ 'RUB' | tuiCurrency }}</strong>\n </p>\n <sc-price-warehouse-stock\n scPrint=\"defaultNoPrint\"\n [product]=\"product\"\n />\n </div>\n </div>\n </div>\n </sc-noindex-wrapper>\n </div>\n} @else {\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n}\n" }]
|
|
7873
7966
|
}], propDecorators: { clickSettings: [{ type: i0.Output, args: ["clickSettings"] }], isShowEditControls: [{ type: i0.Input, args: [{ isSignal: true, alias: "isShowEditControls", required: false }] }] } });
|
|
7874
7967
|
|
|
7875
7968
|
/* eslint-disable no-param-reassign */
|
|
7876
7969
|
/**
|
|
7877
7970
|
* Компонент списка товаров корзины, заказа или черновика.
|
|
7878
|
-
* Позиции разбиты.
|
|
7879
7971
|
*/
|
|
7880
7972
|
class ScOrderItemsListComponent {
|
|
7881
7973
|
constructor() {
|
|
@@ -7925,7 +8017,7 @@ class ScOrderItemsListComponent {
|
|
|
7925
8017
|
const items = this.itemsSignal();
|
|
7926
8018
|
const selectedItemsIds = this.selectedItemsIds();
|
|
7927
8019
|
const selectable = this.selectable();
|
|
7928
|
-
return items.filter((item) => !selectable || selectedItemsIds.includes(item.id)).reduce((sum, item) => sum + item.costRub, 0);
|
|
8020
|
+
return ScNumberHelper.roundMoney(items.filter((item) => !selectable || selectedItemsIds.includes(item.id)).reduce((sum, item) => sum + item.costRub, 0));
|
|
7929
8021
|
}, ...(ngDevMode ? [{ debugName: "sumSelectedItems" }] : /* istanbul ignore next */ []));
|
|
7930
8022
|
/**
|
|
7931
8023
|
* Сервис получения и редактирования списка товаров заказа (корзина / заказ / черновик = заказ).
|
|
@@ -7936,6 +8028,10 @@ class ScOrderItemsListComponent {
|
|
|
7936
8028
|
* Признак, что можно редактировать позиции.
|
|
7937
8029
|
*/
|
|
7938
8030
|
this.canEdit = computed(() => this.editable() && 'updateProduct$' in this.orderItemsListLoader, ...(ngDevMode ? [{ debugName: "canEdit" }] : /* istanbul ignore next */ []));
|
|
8031
|
+
/**
|
|
8032
|
+
* Настройки вывода сумм в рублях.
|
|
8033
|
+
*/
|
|
8034
|
+
this.moneyFormat = ScNumberHelper.getMoneyFormat();
|
|
7939
8035
|
/**
|
|
7940
8036
|
* Ссылка для автоматического управления уничтожением зависимостей.
|
|
7941
8037
|
*/
|
|
@@ -8055,20 +8151,26 @@ class ScOrderItemsListComponent {
|
|
|
8055
8151
|
this.scDialogService.openPriceHistoryChartDialog(product);
|
|
8056
8152
|
}
|
|
8057
8153
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScOrderItemsListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8058
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScOrderItemsListComponent, isStandalone: true, selector: "sc-order-items-list", inputs: { selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: false, isRequired: true, transformFunction: null } }, outputs: { selectedItemsIdsChange: "selectedItemsIdsChange" }, ngImport: i0, template: "<div\n [formGroup]=\"selectionFormGroup\"\n class=\"flex flex-col gap-5\"\n>\n
|
|
8154
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScOrderItemsListComponent, isStandalone: true, selector: "sc-order-items-list", inputs: { selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: false, isRequired: true, transformFunction: null } }, outputs: { selectedItemsIdsChange: "selectedItemsIdsChange" }, ngImport: i0, template: "<div\n [formGroup]=\"selectionFormGroup\"\n class=\"flex flex-col gap-5\"\n>\n @for (item of itemsSignal(); track item.id) {\n @if ($index !== 0) {\n <hr class=\"mt-auto h-px w-full bg-tui-clear\" />\n }\n\n <div class=\"flex items-center gap-4 relative\">\n @let isActive = !selectable() || selectionFormGroup.get(item.id)?.value;\n\n <!-- \u0427\u0435\u043A\u0431\u043E\u043A\u0441 \u0432\u044B\u0431\u043E\u0440\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (selectable()) {\n <input\n tuiCheckbox\n [disabled]=\"itemComponent.showLoader()\"\n type=\"checkbox\"\n size=\"m\"\n [formControlName]=\"item.id\"\n />\n }\n\n <!-- \u041A\u0430\u0440\u0442\u043E\u0447\u043A\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n <sc-order-item\n #itemComponent\n [product]=\"item.product\"\n [orderItem]=\"item\"\n [showQuantityControl]=\"canEdit() && !item.configurator\"\n [isShowEditControls]=\"canEdit()\"\n class=\"w-full duration-200\"\n [class.opacity-60]=\"selectable() && !selectionFormGroup.get(item.id)?.value\"\n (clickCardEvent)=\"openProductInfoDialog(item.product, item, orderOptions?.orderId())\"\n (quantityValueChanges)=\"patchItem($event, itemComponent)\"\n (clickPriceHistoryEvent)=\"openPriceHistoryChartDialog(item.product)\"\n (clickSettings)=\"openSettingsDialog(item)\"\n [class.pointer-events-none]=\"!isActive\"\n />\n\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (canEdit()) {\n <button\n tuiIconButton\n (click)=\"deleteItem(item, itemComponent)\"\n [loading]=\"itemComponent.showLoader()\"\n size=\"s\"\n appearance=\"secondary\"\n class=\"!absolute left-1 top-1 lg:!relative lg:left-0 lg:top-0 lg:!self-center\"\n >\n <tui-icon icon=\"@tui.trash\" />\n </button>\n }\n </div>\n }\n\n <!-- \u0424\u0443\u0442\u0435\u0440 \u0441\u043F\u0438\u0441\u043A\u0430. -->\n <div\n scPrint=\"cost\"\n class=\"flex flex-col items-end gap-2.5\"\n >\n @let totalSum = sumSelectedItems();\n <!-- \u0418\u0442\u043E\u0433\u043E\u0432\u0430\u044F \u0441\u0443\u043C\u043C\u0430. -->\n <div class=\"text-base font-bold\">\u0418\u0442\u043E\u0433\u043E: {{ totalSum | tuiFormatNumber: moneyFormat }} {{ 'RUB' | tuiCurrency }}</div>\n </div>\n</div>\n", dependencies: [{ kind: "component", type: ScOrderItemComponent, selector: "sc-order-item", inputs: ["isShowEditControls"], outputs: ["clickSettings"] }, { kind: "directive", type: ScPrintDirective, selector: "[scPrint]", inputs: ["scPrint"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: TuiCheckbox, selector: "input[type=\"checkbox\"][tuiCheckbox]" }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiIcon, selector: "tui-icon:not([tuiBadge])", inputs: ["background"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "pipe", type: TuiCurrencyPipe, name: "tuiCurrency" }, { kind: "pipe", type: TuiFormatNumberPipe, name: "tuiFormatNumber" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8059
8155
|
}
|
|
8060
8156
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScOrderItemsListComponent, decorators: [{
|
|
8061
8157
|
type: Component,
|
|
8062
|
-
args: [{ standalone: true, selector: 'sc-order-items-list', imports: [ScOrderItemComponent, ScPrintDirective, ReactiveFormsModule, TuiCheckbox, TuiButton, TuiIcon, TuiButtonLoading, TuiCurrencyPipe, AsyncPipe, TuiFormatNumberPipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n [formGroup]=\"selectionFormGroup\"\n class=\"flex flex-col gap-5\"\n>\n
|
|
8158
|
+
args: [{ standalone: true, selector: 'sc-order-items-list', imports: [ScOrderItemComponent, ScPrintDirective, ReactiveFormsModule, TuiCheckbox, TuiButton, TuiIcon, TuiButtonLoading, TuiCurrencyPipe, AsyncPipe, TuiFormatNumberPipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n [formGroup]=\"selectionFormGroup\"\n class=\"flex flex-col gap-5\"\n>\n @for (item of itemsSignal(); track item.id) {\n @if ($index !== 0) {\n <hr class=\"mt-auto h-px w-full bg-tui-clear\" />\n }\n\n <div class=\"flex items-center gap-4 relative\">\n @let isActive = !selectable() || selectionFormGroup.get(item.id)?.value;\n\n <!-- \u0427\u0435\u043A\u0431\u043E\u043A\u0441 \u0432\u044B\u0431\u043E\u0440\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (selectable()) {\n <input\n tuiCheckbox\n [disabled]=\"itemComponent.showLoader()\"\n type=\"checkbox\"\n size=\"m\"\n [formControlName]=\"item.id\"\n />\n }\n\n <!-- \u041A\u0430\u0440\u0442\u043E\u0447\u043A\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n <sc-order-item\n #itemComponent\n [product]=\"item.product\"\n [orderItem]=\"item\"\n [showQuantityControl]=\"canEdit() && !item.configurator\"\n [isShowEditControls]=\"canEdit()\"\n class=\"w-full duration-200\"\n [class.opacity-60]=\"selectable() && !selectionFormGroup.get(item.id)?.value\"\n (clickCardEvent)=\"openProductInfoDialog(item.product, item, orderOptions?.orderId())\"\n (quantityValueChanges)=\"patchItem($event, itemComponent)\"\n (clickPriceHistoryEvent)=\"openPriceHistoryChartDialog(item.product)\"\n (clickSettings)=\"openSettingsDialog(item)\"\n [class.pointer-events-none]=\"!isActive\"\n />\n\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (canEdit()) {\n <button\n tuiIconButton\n (click)=\"deleteItem(item, itemComponent)\"\n [loading]=\"itemComponent.showLoader()\"\n size=\"s\"\n appearance=\"secondary\"\n class=\"!absolute left-1 top-1 lg:!relative lg:left-0 lg:top-0 lg:!self-center\"\n >\n <tui-icon icon=\"@tui.trash\" />\n </button>\n }\n </div>\n }\n\n <!-- \u0424\u0443\u0442\u0435\u0440 \u0441\u043F\u0438\u0441\u043A\u0430. -->\n <div\n scPrint=\"cost\"\n class=\"flex flex-col items-end gap-2.5\"\n >\n @let totalSum = sumSelectedItems();\n <!-- \u0418\u0442\u043E\u0433\u043E\u0432\u0430\u044F \u0441\u0443\u043C\u043C\u0430. -->\n <div class=\"text-base font-bold\">\u0418\u0442\u043E\u0433\u043E: {{ totalSum | tuiFormatNumber: moneyFormat }} {{ 'RUB' | tuiCurrency }}</div>\n </div>\n</div>\n" }]
|
|
8063
8159
|
}], propDecorators: { selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], selectedItemsIdsChange: [{ type: i0.Output, args: ["selectedItemsIdsChange"] }], items: [{
|
|
8064
8160
|
type: Input,
|
|
8065
8161
|
args: [{ required: true }]
|
|
8066
8162
|
}] } });
|
|
8067
8163
|
|
|
8068
|
-
|
|
8164
|
+
/**
|
|
8165
|
+
* Список позиций заказа с действиями и блоком позиций, которые больше не предоставляются.
|
|
8166
|
+
*/
|
|
8167
|
+
class ScOrderItemsListWithActionsComponent {
|
|
8168
|
+
/**
|
|
8169
|
+
* Инициализирует экземпляр класса {@link ScOrderItemsListWithActionsComponent}.
|
|
8170
|
+
*/
|
|
8069
8171
|
constructor() {
|
|
8070
8172
|
/**
|
|
8071
|
-
*
|
|
8173
|
+
* Товары заказа.
|
|
8072
8174
|
*/
|
|
8073
8175
|
this.items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
8074
8176
|
/**
|
|
@@ -8080,66 +8182,42 @@ class ScOrderItemsListByDirectionsComponent {
|
|
|
8080
8182
|
*/
|
|
8081
8183
|
this.editable = input(false, ...(ngDevMode ? [{ debugName: "editable" }] : /* istanbul ignore next */ []));
|
|
8082
8184
|
/**
|
|
8083
|
-
*
|
|
8084
|
-
*/
|
|
8085
|
-
this.showContinueButton = input(true, ...(ngDevMode ? [{ debugName: "showContinueButton" }] : /* istanbul ignore next */ []));
|
|
8086
|
-
/**
|
|
8087
|
-
* Текст кнопки продолжения.
|
|
8088
|
-
*/
|
|
8089
|
-
this.continueButtonText = input({ title: 'Заказать', iconStart: '@tui.shopping-cart' }, ...(ngDevMode ? [{ debugName: "continueButtonText" }] : /* istanbul ignore next */ []));
|
|
8090
|
-
/**
|
|
8091
|
-
* Событие клика на кнопку продолжения.
|
|
8092
|
-
*/
|
|
8093
|
-
this.continueClick = output();
|
|
8094
|
-
/**
|
|
8095
|
-
* Список направлений продаж из справочника.
|
|
8096
|
-
*/
|
|
8097
|
-
this.directions = toSignal(inject(ScReferencesService).directions$, { initialValue: undefined });
|
|
8098
|
-
/**
|
|
8099
|
-
* Позиции корзины, сгруппированные по направлениям продаж.
|
|
8100
|
-
* Если передан cartDirections, используется он, иначе группировка выполняется автоматически.
|
|
8185
|
+
* Позиции, доступные для заказа.
|
|
8101
8186
|
*/
|
|
8102
|
-
this.
|
|
8103
|
-
const items = this.items().filter((item) => !item.product.isNull && !item.product.isHidden);
|
|
8104
|
-
const directions = this.directions();
|
|
8105
|
-
return directions?.map((direction) => new ScOrderItemsByDirection(direction, items)).filter((group) => group.items.length > 0) ?? [];
|
|
8106
|
-
}, ...(ngDevMode ? [{ debugName: "itemsByDirections" }] : /* istanbul ignore next */ []));
|
|
8187
|
+
this.availableItems = computed(() => this.items().filter((item) => !item.product.isNull && !item.product.isHidden), ...(ngDevMode ? [{ debugName: "availableItems" }] : /* istanbul ignore next */ []));
|
|
8107
8188
|
/**
|
|
8108
8189
|
* Позиции корзины, которые больше не предоставляются.
|
|
8109
8190
|
*/
|
|
8110
8191
|
this.nullItems = computed(() => this.items().filter((item) => item.product.isNull || item.product.isHidden), ...(ngDevMode ? [{ debugName: "nullItems" }] : /* istanbul ignore next */ []));
|
|
8111
8192
|
/**
|
|
8112
|
-
*
|
|
8193
|
+
* Идентификаторы выбранных позиций.
|
|
8113
8194
|
*/
|
|
8114
8195
|
this.selectedItemsIds = model([], ...(ngDevMode ? [{ debugName: "selectedItemsIds" }] : /* istanbul ignore next */ []));
|
|
8196
|
+
// Оставляет в выборе только доступные позиции: без них список выбора не отрисовывается и выбор не сбрасывает.
|
|
8197
|
+
effect(() => {
|
|
8198
|
+
const availableIds = new Set(this.availableItems().map((item) => item.id));
|
|
8199
|
+
const selectedItemsIds = this.selectedItemsIds();
|
|
8200
|
+
const actualIds = selectedItemsIds.filter((id) => availableIds.has(id));
|
|
8201
|
+
if (actualIds.length !== selectedItemsIds.length) {
|
|
8202
|
+
this.selectedItemsIds.set(actualIds);
|
|
8203
|
+
}
|
|
8204
|
+
});
|
|
8115
8205
|
}
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
*
|
|
8119
|
-
* @param itemsIds Идентификаторы выбранных позиций.
|
|
8120
|
-
* @param direction Направление продаж.
|
|
8121
|
-
*/
|
|
8122
|
-
selectedItemsHandler(itemsIds, direction) {
|
|
8123
|
-
this.selectedItemsIds.update((previous) => [
|
|
8124
|
-
...previous.filter((id) => !direction.items.some((item) => item.id === id) && this.items().some((item) => item.id === id)),
|
|
8125
|
-
...itemsIds,
|
|
8126
|
-
]);
|
|
8127
|
-
}
|
|
8128
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScOrderItemsListByDirectionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8129
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScOrderItemsListByDirectionsComponent, isStandalone: true, selector: "sc-order-items-list-by-directions", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, showContinueButton: { classPropertyName: "showContinueButton", publicName: "showContinueButton", isSignal: true, isRequired: false, transformFunction: null }, continueButtonText: { classPropertyName: "continueButtonText", publicName: "continueButtonText", isSignal: true, isRequired: false, transformFunction: null }, selectedItemsIds: { classPropertyName: "selectedItemsIds", publicName: "selectedItemsIds", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { continueClick: "continueClick", selectedItemsIds: "selectedItemsIdsChange" }, ngImport: i0, 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", dependencies: [{ kind: "component", type: ScOrderItemsListComponent, selector: "sc-order-items-list", inputs: ["selectable", "editable", "items"], outputs: ["selectedItemsIdsChange"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8206
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScOrderItemsListWithActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8207
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScOrderItemsListWithActionsComponent, isStandalone: true, selector: "sc-order-items-list-with-actions", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, selectedItemsIds: { classPropertyName: "selectedItemsIds", publicName: "selectedItemsIds", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedItemsIds: "selectedItemsIdsChange" }, ngImport: i0, template: "<div class=\"flex flex-col gap-5\">\n <div class=\"flex flex-col gap-2.5\">\n @if (availableItems().length) {\n <sc-order-items-list\n [items]=\"availableItems()\"\n [selectable]=\"selectable()\"\n [editable]=\"editable()\"\n (selectedItemsIdsChange)=\"selectedItemsIds.set($event)\"\n />\n }\n\n <!-- \u0424\u0443\u0442\u0435\u0440 \u0441\u043F\u0438\u0441\u043A\u0430 \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 </div>\n </div>\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", dependencies: [{ kind: "component", type: ScOrderItemsListComponent, selector: "sc-order-items-list", inputs: ["selectable", "editable", "items"], outputs: ["selectedItemsIdsChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8130
8208
|
}
|
|
8131
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
8209
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScOrderItemsListWithActionsComponent, decorators: [{
|
|
8132
8210
|
type: Component,
|
|
8133
|
-
args: [{
|
|
8134
|
-
}],
|
|
8211
|
+
args: [{ selector: 'sc-order-items-list-with-actions', imports: [ScOrderItemsListComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"flex flex-col gap-5\">\n <div class=\"flex flex-col gap-2.5\">\n @if (availableItems().length) {\n <sc-order-items-list\n [items]=\"availableItems()\"\n [selectable]=\"selectable()\"\n [editable]=\"editable()\"\n (selectedItemsIdsChange)=\"selectedItemsIds.set($event)\"\n />\n }\n\n <!-- \u0424\u0443\u0442\u0435\u0440 \u0441\u043F\u0438\u0441\u043A\u0430 \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 </div>\n </div>\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" }]
|
|
8212
|
+
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], selectedItemsIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItemsIds", required: false }] }, { type: i0.Output, args: ["selectedItemsIdsChange"] }] } });
|
|
8135
8213
|
|
|
8136
8214
|
/**
|
|
8137
|
-
* Список товаров заказа
|
|
8215
|
+
* Список товаров оформляемого заказа с выбором позиций.
|
|
8138
8216
|
*/
|
|
8139
|
-
class
|
|
8217
|
+
class ScNewOrderItemsComponent {
|
|
8140
8218
|
constructor() {
|
|
8141
8219
|
/**
|
|
8142
|
-
* Товары
|
|
8220
|
+
* Товары заказа.
|
|
8143
8221
|
*/
|
|
8144
8222
|
this.items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
8145
8223
|
/**
|
|
@@ -8159,12 +8237,12 @@ class ScOrderDirectionItemsComponent {
|
|
|
8159
8237
|
*/
|
|
8160
8238
|
this.selectedItemsIdsChange = output();
|
|
8161
8239
|
}
|
|
8162
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
8163
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type:
|
|
8240
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScNewOrderItemsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8241
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: ScNewOrderItemsComponent, isStandalone: true, selector: "sc-new-order-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-with-actions\n [items]=\"items()\"\n [editable]=\"editable()\"\n [selectable]=\"selectable()\"\n (selectedItemsIdsChange)=\"selectedItemsIdsChange.emit($event)\"\n >\n <ng-content\n select=\"[footerActions]\"\n ngProjectAs=\"[footerActions]\"\n />\n </sc-order-items-list-with-actions>\n</div>\n", dependencies: [{ kind: "component", type: ScOrderItemsListWithActionsComponent, selector: "sc-order-items-list-with-actions", inputs: ["items", "selectable", "editable", "selectedItemsIds"], outputs: ["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]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8164
8242
|
}
|
|
8165
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
8243
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScNewOrderItemsComponent, decorators: [{
|
|
8166
8244
|
type: Component,
|
|
8167
|
-
args: [{ selector: 'sc-order-
|
|
8245
|
+
args: [{ selector: 'sc-new-order-items', imports: [ScOrderItemsListWithActionsComponent, 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-with-actions\n [items]=\"items()\"\n [editable]=\"editable()\"\n [selectable]=\"selectable()\"\n (selectedItemsIdsChange)=\"selectedItemsIdsChange.emit($event)\"\n >\n <ng-content\n select=\"[footerActions]\"\n ngProjectAs=\"[footerActions]\"\n />\n </sc-order-items-list-with-actions>\n</div>\n" }]
|
|
8168
8246
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], orderProcessingAcceptanceTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "orderProcessingAcceptanceTime", required: false }] }], selectedItemsIdsChange: [{ type: i0.Output, args: ["selectedItemsIdsChange"] }] } });
|
|
8169
8247
|
|
|
8170
8248
|
/**
|
|
@@ -8182,19 +8260,10 @@ class ScOrderFormComponent {
|
|
|
8182
8260
|
* Инициализирует экземпляр класса {@link ScOrderFormComponent}.
|
|
8183
8261
|
*/
|
|
8184
8262
|
constructor() {
|
|
8185
|
-
/**
|
|
8186
|
-
* Идентификатор направления продаж заказа.
|
|
8187
|
-
*/
|
|
8188
|
-
this.directionId = input.required(...(ngDevMode ? [{ debugName: "directionId" }] : /* istanbul ignore next */ []));
|
|
8189
8263
|
/**
|
|
8190
8264
|
* Требовать подтверждённые контактные данные для оформления. Для черновика — `false`.
|
|
8191
8265
|
*/
|
|
8192
8266
|
this.enforceApprovedContacts = input(true, ...(ngDevMode ? [{ debugName: "enforceApprovedContacts" }] : /* istanbul ignore next */ []));
|
|
8193
|
-
/**
|
|
8194
|
-
* Сохранять и восстанавливать черновые данные формы по направлению (метаданные). Для черновика — `false`.
|
|
8195
|
-
* Работает только если предоставлен токен {@link SC_ORDER_FORM_CONFIG}.
|
|
8196
|
-
*/
|
|
8197
|
-
this.persistMetadata = input(true, ...(ngDevMode ? [{ debugName: "persistMetadata" }] : /* istanbul ignore next */ []));
|
|
8198
8267
|
/**
|
|
8199
8268
|
* Событие отправки валидной формы оформления. Полезная нагрузка — сырые значения формы.
|
|
8200
8269
|
*/
|
|
@@ -8426,10 +8495,7 @@ class ScOrderFormComponent {
|
|
|
8426
8495
|
}
|
|
8427
8496
|
/** @inheritdoc */
|
|
8428
8497
|
ngOnInit() {
|
|
8429
|
-
|
|
8430
|
-
if (this.persistMetadata()) {
|
|
8431
|
-
this.initMetadata();
|
|
8432
|
-
}
|
|
8498
|
+
this.initMetadata();
|
|
8433
8499
|
}
|
|
8434
8500
|
/**
|
|
8435
8501
|
* Преобразует объекты в значения, отображаемое в поле ввода.
|
|
@@ -8524,7 +8590,7 @@ class ScOrderFormComponent {
|
|
|
8524
8590
|
});
|
|
8525
8591
|
}
|
|
8526
8592
|
/**
|
|
8527
|
-
* Восстанавливает черновые данные формы из метаданных и инициализирует их
|
|
8593
|
+
* Восстанавливает черновые данные формы из метаданных и инициализирует их сохранение, если предоставлен токен {@link SC_ORDER_FORM_CONFIG}.
|
|
8528
8594
|
*/
|
|
8529
8595
|
initMetadata() {
|
|
8530
8596
|
const { config } = this;
|
|
@@ -8532,7 +8598,7 @@ class ScOrderFormComponent {
|
|
|
8532
8598
|
return;
|
|
8533
8599
|
}
|
|
8534
8600
|
combineLatest({
|
|
8535
|
-
orderMetadata: this.uiService.getNewOrderMetadata$(
|
|
8601
|
+
orderMetadata: this.uiService.getNewOrderMetadata$(),
|
|
8536
8602
|
user: this.user$.pipe(filter((user) => !user.isGuest)),
|
|
8537
8603
|
})
|
|
8538
8604
|
.pipe(first(), takeUntilDestroyed(this.destroyRef))
|
|
@@ -8557,7 +8623,7 @@ class ScOrderFormComponent {
|
|
|
8557
8623
|
}
|
|
8558
8624
|
});
|
|
8559
8625
|
this.form.valueChanges.pipe(debounceTime(config.debounceTime), takeUntilDestroyed(this.destroyRef)).subscribe((newOrder) => {
|
|
8560
|
-
this.uiService.setNewOrderMetadata(this.
|
|
8626
|
+
this.uiService.setNewOrderMetadata(this.convertersService.removeNull(newOrder));
|
|
8561
8627
|
});
|
|
8562
8628
|
}
|
|
8563
8629
|
/**
|
|
@@ -8688,7 +8754,7 @@ class ScOrderFormComponent {
|
|
|
8688
8754
|
reader.readAsDataURL(file);
|
|
8689
8755
|
}
|
|
8690
8756
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScOrderFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8691
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", 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-textfield\n tuiChevron\n [content]=\"contragents ? stringify(contragents) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"contragentId\"\n placeholder=\"\u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\n <tui-error formControlName=\"contragentId\" />\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-textfield\n tuiChevron\n [content]=\"paymentTypes ? stringify(paymentTypes) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"paymentType\"\n placeholder=\"\u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\n <tui-error formControlName=\"paymentType\" />\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-textfield\n tuiChevron\n [content]=\"deliveryTypes ? stringify(deliveryTypes) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"deliveryType\"\n placeholder=\"\u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\n <tui-error formControlName=\"deliveryType\" />\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-textfield\n tuiChevron\n [content]=\"warehouses ? stringify(warehouses) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"warehouseId\"\n placeholder=\"\u0421\u043A\u043B\u0430\u0434\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\n <tui-error formControlName=\"warehouseId\" />\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-textfield\n tuiChevron\n [content]=\"addresses ? stringify(addresses) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"addressId\"\n placeholder=\"\u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\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 formControlName=\"addressId\" />\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-textfield [disabledItemHandler]=\"deliveryDateFilter\">\n <input\n tuiInputDate\n formControlName=\"deliveryDate\"\n [placeholder]=\"'\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 />\n <tui-calendar\n *tuiDropdown\n [markerHandler]=\"deliveryDateMarker\"\n [max]=\"maxDeliveryDay()\"\n [min]=\"minDeliveryDay()\"\n />\n </tui-textfield>\n <tui-error formControlName=\"deliveryDate\" />\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-textfield>\n <textarea\n tuiTextarea\n formControlName=\"comment\"\n placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442\"\n [max]=\"15\"\n ></textarea>\n </tui-textfield>\n <tui-error formControlName=\"comment\" />\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\n tuiInputFiles\n class=\"self-start !min-h-0 !p-0\"\n >\n <input\n accept=\"image/*\"\n tuiInputFiles\n [formControl]=\"controlFile\"\n class=\"opacity-0\"\n />\n <ng-template>\n <button\n tuiButton\n type=\"button\"\n tabindex=\"-1\"\n appearance=\"secondary\"\n size=\"m\"\n iconStart=\"@tui.paperclip\"\n >\n \u041F\u0440\u0438\u043A\u0440\u0435\u043F\u0438\u0442\u044C \u0444\u0430\u0439\u043B\n </button>\n </ng-template>\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 [order]=\"['maxLength']\"\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", styles: ["tui-calendar:has(.t-dots) .t-cell:has(.t-dots){opacity:1;font-weight:700;color:var(--tui-text-primary);border-radius:var(--tui-radius-m);box-shadow:inset 0 0 0 .125rem color-mix(in srgb,var(--tui-background-accent-1) 33%,transparent)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.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: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "loading"] }, { kind: "directive", type: TuiLabel, selector: "label[tuiLabel]" }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "directive", type: i1$1.TuiSelectDirective, selector: "input[tuiSelect]" }, { kind: "component", type: i3$1.TuiTextfieldComponent, selector: "tui-textfield:not([multi])", inputs: ["content", "filler"] }, { kind: "directive", type: i3.TuiDropdownContent, selector: "ng-template[tuiDropdown]" }, { kind: "component", type: i2.TuiDataListComponent, selector: "tui-data-list", inputs: ["emptyContent", "size"] }, { kind: "directive", type: i2.TuiOption, selector: "button[tuiOption], a[tuiOption], label[tuiOption]", inputs: ["disabled"] }, { kind: "directive", type: i2.TuiOptionWithValue, selector: "button[tuiOption][value], a[tuiOption][value], label[tuiOption][value]", inputs: ["disabled", "value"] }, { kind: "component", type: i2.TuiErrorComponent, selector: "tui-error", inputs: ["error"] }, { kind: "directive", type: i2.TuiErrorDirective, selector: "tui-error[ngModel], tui-error[formControlName], tui-error[formControl], tui-error[formGroup], tui-error[formGroupName], tui-error[formArrayName], tui-error[formArray]", inputs: ["order"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]" }, { kind: "directive", type: i1$1.TuiInputDateDirective, selector: "input[tuiInputDate]", inputs: ["max", "min"] }, { kind: "component", type: i6$1.TuiCalendar, selector: "tui-calendar", inputs: ["disabledItemHandler", "min", "max", "minViewedMonth", "maxViewedMonth", "showAdjacent", "markerHandler", "initialView", "month", "hoveredItem", "value"], outputs: ["monthChange", "hoveredItemChange", "valueChange", "dayClick"] }, { kind: "component", type: i1$1.TuiTextareaComponent, selector: "textarea[tuiTextarea]", inputs: ["min", "max", "content"] }, { kind: "component", type: i1$1.TuiFile, selector: "tui-file,a[tuiFile],button[tuiFile]", inputs: ["file", "state", "size", "showDelete", "showSize", "leftContent"], outputs: ["remove"] }, { kind: "component", type: i1$1.TuiInputFiles, selector: "label[tuiInputFiles]", inputs: ["tuiInputFiles"] }, { kind: "component", type: i1$1.TuiFilesComponent, selector: "tui-files", inputs: ["max", "expanded"], outputs: ["expandedChange"] }, { kind: "directive", type: i1$1.TuiInputFilesDirective, selector: "input[tuiInputFiles]", outputs: ["reject"] }, { kind: "directive", type: ScFocusFirstInvalidFieldDirective, selector: "form[formGroup][scFocusFirstInvalidField]", inputs: ["fieldOrder"] }, { kind: "pipe", type: i1$1.TuiFileRejectedPipe, name: "tuiFileRejected" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
8757
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScOrderFormComponent, isStandalone: true, selector: "sc-order-form", inputs: { enforceApprovedContacts: { classPropertyName: "enforceApprovedContacts", publicName: "enforceApprovedContacts", 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-textfield\n tuiChevron\n [content]=\"contragents ? stringify(contragents) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"contragentId\"\n placeholder=\"\u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\n <tui-error formControlName=\"contragentId\" />\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-textfield\n tuiChevron\n [content]=\"paymentTypes ? stringify(paymentTypes) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"paymentType\"\n placeholder=\"\u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\n <tui-error formControlName=\"paymentType\" />\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-textfield\n tuiChevron\n [content]=\"deliveryTypes ? stringify(deliveryTypes) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"deliveryType\"\n placeholder=\"\u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\n <tui-error formControlName=\"deliveryType\" />\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-textfield\n tuiChevron\n [content]=\"warehouses ? stringify(warehouses) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"warehouseId\"\n placeholder=\"\u0421\u043A\u043B\u0430\u0434\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\n <tui-error formControlName=\"warehouseId\" />\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-textfield\n tuiChevron\n [content]=\"addresses ? stringify(addresses) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"addressId\"\n placeholder=\"\u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\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 formControlName=\"addressId\" />\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-textfield [disabledItemHandler]=\"deliveryDateFilter\">\n <input\n tuiInputDate\n formControlName=\"deliveryDate\"\n [placeholder]=\"'\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 />\n <tui-calendar\n *tuiDropdown\n [markerHandler]=\"deliveryDateMarker\"\n [max]=\"maxDeliveryDay()\"\n [min]=\"minDeliveryDay()\"\n />\n </tui-textfield>\n <tui-error formControlName=\"deliveryDate\" />\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-textfield>\n <textarea\n tuiTextarea\n formControlName=\"comment\"\n placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442\"\n [max]=\"15\"\n ></textarea>\n </tui-textfield>\n <tui-error formControlName=\"comment\" />\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\n tuiInputFiles\n class=\"self-start !min-h-0 !p-0\"\n >\n <input\n accept=\"image/*\"\n tuiInputFiles\n [formControl]=\"controlFile\"\n class=\"opacity-0\"\n />\n <ng-template>\n <button\n tuiButton\n type=\"button\"\n tabindex=\"-1\"\n appearance=\"secondary\"\n size=\"m\"\n iconStart=\"@tui.paperclip\"\n >\n \u041F\u0440\u0438\u043A\u0440\u0435\u043F\u0438\u0442\u044C \u0444\u0430\u0439\u043B\n </button>\n </ng-template>\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 [order]=\"['maxLength']\"\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", styles: ["tui-calendar:has(.t-dots) .t-cell:has(.t-dots){opacity:1;font-weight:700;color:var(--tui-text-primary);border-radius:var(--tui-radius-m);box-shadow:inset 0 0 0 .125rem color-mix(in srgb,var(--tui-background-accent-1) 33%,transparent)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.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: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "loading"] }, { kind: "directive", type: TuiLabel, selector: "label[tuiLabel]" }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "directive", type: i1$1.TuiSelectDirective, selector: "input[tuiSelect]" }, { kind: "component", type: i3$1.TuiTextfieldComponent, selector: "tui-textfield:not([multi])", inputs: ["content", "filler"] }, { kind: "directive", type: i3.TuiDropdownContent, selector: "ng-template[tuiDropdown]" }, { kind: "component", type: i2.TuiDataListComponent, selector: "tui-data-list", inputs: ["emptyContent", "size"] }, { kind: "directive", type: i2.TuiOption, selector: "button[tuiOption], a[tuiOption], label[tuiOption]", inputs: ["disabled"] }, { kind: "directive", type: i2.TuiOptionWithValue, selector: "button[tuiOption][value], a[tuiOption][value], label[tuiOption][value]", inputs: ["disabled", "value"] }, { kind: "component", type: i2.TuiErrorComponent, selector: "tui-error", inputs: ["error"] }, { kind: "directive", type: i2.TuiErrorDirective, selector: "tui-error[ngModel], tui-error[formControlName], tui-error[formControl], tui-error[formGroup], tui-error[formGroupName], tui-error[formArrayName], tui-error[formArray]", inputs: ["order"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]" }, { kind: "directive", type: i1$1.TuiInputDateDirective, selector: "input[tuiInputDate]", inputs: ["max", "min"] }, { kind: "component", type: i6$1.TuiCalendar, selector: "tui-calendar", inputs: ["disabledItemHandler", "min", "max", "minViewedMonth", "maxViewedMonth", "showAdjacent", "markerHandler", "initialView", "month", "hoveredItem", "value"], outputs: ["monthChange", "hoveredItemChange", "valueChange", "dayClick"] }, { kind: "component", type: i1$1.TuiTextareaComponent, selector: "textarea[tuiTextarea]", inputs: ["min", "max", "content"] }, { kind: "component", type: i1$1.TuiFile, selector: "tui-file,a[tuiFile],button[tuiFile]", inputs: ["file", "state", "size", "showDelete", "showSize", "leftContent"], outputs: ["remove"] }, { kind: "component", type: i1$1.TuiInputFiles, selector: "label[tuiInputFiles]", inputs: ["tuiInputFiles"] }, { kind: "component", type: i1$1.TuiFilesComponent, selector: "tui-files", inputs: ["max", "expanded"], outputs: ["expandedChange"] }, { kind: "directive", type: i1$1.TuiInputFilesDirective, selector: "input[tuiInputFiles]", outputs: ["reject"] }, { kind: "directive", type: ScFocusFirstInvalidFieldDirective, selector: "form[formGroup][scFocusFirstInvalidField]", inputs: ["fieldOrder"] }, { kind: "pipe", type: i1$1.TuiFileRejectedPipe, name: "tuiFileRejected" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
8692
8758
|
}
|
|
8693
8759
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScOrderFormComponent, decorators: [{
|
|
8694
8760
|
type: Component,
|
|
@@ -8711,7 +8777,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
8711
8777
|
AsyncPipe,
|
|
8712
8778
|
ScFocusFirstInvalidFieldDirective,
|
|
8713
8779
|
], 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-textfield\n tuiChevron\n [content]=\"contragents ? stringify(contragents) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"contragentId\"\n placeholder=\"\u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\n <tui-error formControlName=\"contragentId\" />\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-textfield\n tuiChevron\n [content]=\"paymentTypes ? stringify(paymentTypes) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"paymentType\"\n placeholder=\"\u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\n <tui-error formControlName=\"paymentType\" />\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-textfield\n tuiChevron\n [content]=\"deliveryTypes ? stringify(deliveryTypes) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"deliveryType\"\n placeholder=\"\u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\n <tui-error formControlName=\"deliveryType\" />\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-textfield\n tuiChevron\n [content]=\"warehouses ? stringify(warehouses) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"warehouseId\"\n placeholder=\"\u0421\u043A\u043B\u0430\u0434\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\n <tui-error formControlName=\"warehouseId\" />\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-textfield\n tuiChevron\n [content]=\"addresses ? stringify(addresses) : selectLoading\"\n >\n <input\n tuiSelect\n formControlName=\"addressId\"\n placeholder=\"\u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\"\n />\n <tui-data-list *tuiDropdown>\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-textfield>\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 formControlName=\"addressId\" />\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-textfield [disabledItemHandler]=\"deliveryDateFilter\">\n <input\n tuiInputDate\n formControlName=\"deliveryDate\"\n [placeholder]=\"'\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 />\n <tui-calendar\n *tuiDropdown\n [markerHandler]=\"deliveryDateMarker\"\n [max]=\"maxDeliveryDay()\"\n [min]=\"minDeliveryDay()\"\n />\n </tui-textfield>\n <tui-error formControlName=\"deliveryDate\" />\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-textfield>\n <textarea\n tuiTextarea\n formControlName=\"comment\"\n placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442\"\n [max]=\"15\"\n ></textarea>\n </tui-textfield>\n <tui-error formControlName=\"comment\" />\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\n tuiInputFiles\n class=\"self-start !min-h-0 !p-0\"\n >\n <input\n accept=\"image/*\"\n tuiInputFiles\n [formControl]=\"controlFile\"\n class=\"opacity-0\"\n />\n <ng-template>\n <button\n tuiButton\n type=\"button\"\n tabindex=\"-1\"\n appearance=\"secondary\"\n size=\"m\"\n iconStart=\"@tui.paperclip\"\n >\n \u041F\u0440\u0438\u043A\u0440\u0435\u043F\u0438\u0442\u044C \u0444\u0430\u0439\u043B\n </button>\n </ng-template>\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 [order]=\"['maxLength']\"\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", styles: ["tui-calendar:has(.t-dots) .t-cell:has(.t-dots){opacity:1;font-weight:700;color:var(--tui-text-primary);border-radius:var(--tui-radius-m);box-shadow:inset 0 0 0 .125rem color-mix(in srgb,var(--tui-background-accent-1) 33%,transparent)}\n"] }]
|
|
8714
|
-
}], ctorParameters: () => [], propDecorators: {
|
|
8780
|
+
}], ctorParameters: () => [], propDecorators: { enforceApprovedContacts: [{ type: i0.Input, args: [{ isSignal: true, alias: "enforceApprovedContacts", required: false }] }], orderSubmit: [{ type: i0.Output, args: ["orderSubmit"] }], unconfirmedDataWarning: [{ type: i0.ViewChild, args: ['unconfirmedDataWarning', { isSignal: true }] }] } });
|
|
8715
8781
|
|
|
8716
8782
|
/**
|
|
8717
8783
|
* Компонент списка товаров, разбитых по наличию на складе:
|
|
@@ -8807,9 +8873,9 @@ class ScDraftComponent {
|
|
|
8807
8873
|
*/
|
|
8808
8874
|
this.draft = model(null, ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
|
|
8809
8875
|
/**
|
|
8810
|
-
* Идентификаторы выбранных
|
|
8876
|
+
* Идентификаторы позиций черновика, выбранных для оформления заказа.
|
|
8811
8877
|
*/
|
|
8812
|
-
this.selectedItemsIds =
|
|
8878
|
+
this.selectedItemsIds = signal([], ...(ngDevMode ? [{ debugName: "selectedItemsIds" }] : /* istanbul ignore next */ []));
|
|
8813
8879
|
/**
|
|
8814
8880
|
* Источник события удаления или отмены заказа.
|
|
8815
8881
|
*/
|
|
@@ -8844,13 +8910,10 @@ class ScDraftComponent {
|
|
|
8844
8910
|
}
|
|
8845
8911
|
}
|
|
8846
8912
|
/**
|
|
8847
|
-
* Переход к оформлению заказа
|
|
8848
|
-
*
|
|
8849
|
-
* @param direction Группа позиций по направлению продаж.
|
|
8913
|
+
* Переход к оформлению заказа из выбранных позиций.
|
|
8850
8914
|
*/
|
|
8851
|
-
goToNewOrder(
|
|
8852
|
-
|
|
8853
|
-
this.router.navigate(['orders', 'new', this.draft()?.id, direction.direction.id, 'draft'], { queryParams: { itemsIds: ids } }).catch(noop$1);
|
|
8915
|
+
goToNewOrder() {
|
|
8916
|
+
this.router.navigate(['orders', 'new', this.draft()?.id, 'draft'], { queryParams: { itemsIds: this.selectedItemsIds() } }).catch(noop$1);
|
|
8854
8917
|
}
|
|
8855
8918
|
/**
|
|
8856
8919
|
* Удаляет черновик и перенаправляет к списку черновиков.
|
|
@@ -8876,22 +8939,22 @@ class ScDraftComponent {
|
|
|
8876
8939
|
});
|
|
8877
8940
|
}
|
|
8878
8941
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScDraftComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8879
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScDraftComponent, isStandalone: true, selector: "sc-draft", inputs: { draft: { classPropertyName: "draft", publicName: "draft", isSignal: true, isRequired: false, transformFunction: null }
|
|
8942
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScDraftComponent, isStandalone: true, selector: "sc-draft", inputs: { draft: { classPropertyName: "draft", publicName: "draft", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { draft: "draftChange", deleteEvent: "deleteEvent" }, providers: [
|
|
8880
8943
|
{
|
|
8881
8944
|
provide: SC_ORDER_LOADER,
|
|
8882
8945
|
useExisting: ScOrderDraftsService,
|
|
8883
8946
|
},
|
|
8884
|
-
], ngImport: i0, template: "@let items = draft()?.products;\n\n@if (items) {\n <div class=\"flex flex-col gap-12\">\n <div class=\"flex flex-col gap-5\">\n @if (items.length) {\n <sc-order-items-list-
|
|
8947
|
+
], ngImport: i0, template: "@let items = draft()?.products;\n\n@if (items) {\n <div class=\"flex flex-col gap-12\">\n <div class=\"flex flex-col gap-5\">\n @if (items.length) {\n <sc-order-items-list-with-actions\n scOrder\n [orderId]=\"draft()?.id\"\n [items]=\"items\"\n [editable]=\"isDraftPage()\"\n (selectedItemsIdsChange)=\"selectedItemsIds.set($event)\"\n >\n <div\n footerActions\n class=\"flex w-full flex-col items-center gap-x-2.5 gap-y-4 sm:flex-row sm:flex-wrap sm:items-start\"\n >\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"clearDraft()\"\n iconStart=\"@tui.trash-2\"\n >\n \u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\n </button>\n\n <button\n tuiButton\n type=\"button\"\n class=\"sm:ml-auto\"\n iconStart=\"@tui.shopping-cart\"\n [disabled]=\"selectedItemsIds().length === 0\"\n (click)=\"goToNewOrder()\"\n >\n \u0417\u0430\u043A\u0430\u0437\u0430\u0442\u044C\n </button>\n </div>\n </sc-order-items-list-with-actions>\n } @else {\n <p class=\"text-base font-bold\">\u0427\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u043F\u0443\u0441\u0442.</p>\n <div\n footerActions\n class=\"flex gap-2\"\n >\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"clearDraft()\"\n iconStart=\"@tui.trash-2\"\n >\n \u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\n </button>\n </div>\n }\n </div>\n </div>\n} @else {\n <div class=\"flex flex-col gap-12\">\n <div class=\"flex flex-col gap-5\">\n @for (item of [1, 2, 3, 4]; track item) {\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n }\n <div class=\"flex gap-2\">\n <div class=\"tui-skeleton h-10 w-40 rounded-md\"></div>\n <div class=\"tui-skeleton h-10 w-36 rounded-md\"></div>\n </div>\n </div>\n </div>\n}\n", dependencies: [{ kind: "component", type: ScOrderItemsListWithActionsComponent, selector: "sc-order-items-list-with-actions", inputs: ["items", "selectable", "editable", "selectedItemsIds"], outputs: ["selectedItemsIdsChange"] }, { kind: "directive", type: ScOrderAccessorDirective, selector: "[scOrder]", inputs: ["orderId"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8885
8948
|
}
|
|
8886
8949
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScDraftComponent, decorators: [{
|
|
8887
8950
|
type: Component,
|
|
8888
|
-
args: [{ standalone: true, selector: 'sc-draft', imports: [
|
|
8951
|
+
args: [{ standalone: true, selector: 'sc-draft', imports: [ScOrderItemsListWithActionsComponent, ScOrderAccessorDirective, TuiButton, TuiIcons], providers: [
|
|
8889
8952
|
{
|
|
8890
8953
|
provide: SC_ORDER_LOADER,
|
|
8891
8954
|
useExisting: ScOrderDraftsService,
|
|
8892
8955
|
},
|
|
8893
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let items = draft()?.products;\n\n@if (items) {\n <div class=\"flex flex-col gap-12\">\n <div class=\"flex flex-col gap-5\">\n @if (items.length) {\n <sc-order-items-list-
|
|
8894
|
-
}], propDecorators: { draft: [{ type: i0.Input, args: [{ isSignal: true, alias: "draft", required: false }] }, { type: i0.Output, args: ["draftChange"] }],
|
|
8956
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let items = draft()?.products;\n\n@if (items) {\n <div class=\"flex flex-col gap-12\">\n <div class=\"flex flex-col gap-5\">\n @if (items.length) {\n <sc-order-items-list-with-actions\n scOrder\n [orderId]=\"draft()?.id\"\n [items]=\"items\"\n [editable]=\"isDraftPage()\"\n (selectedItemsIdsChange)=\"selectedItemsIds.set($event)\"\n >\n <div\n footerActions\n class=\"flex w-full flex-col items-center gap-x-2.5 gap-y-4 sm:flex-row sm:flex-wrap sm:items-start\"\n >\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"clearDraft()\"\n iconStart=\"@tui.trash-2\"\n >\n \u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\n </button>\n\n <button\n tuiButton\n type=\"button\"\n class=\"sm:ml-auto\"\n iconStart=\"@tui.shopping-cart\"\n [disabled]=\"selectedItemsIds().length === 0\"\n (click)=\"goToNewOrder()\"\n >\n \u0417\u0430\u043A\u0430\u0437\u0430\u0442\u044C\n </button>\n </div>\n </sc-order-items-list-with-actions>\n } @else {\n <p class=\"text-base font-bold\">\u0427\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u043F\u0443\u0441\u0442.</p>\n <div\n footerActions\n class=\"flex gap-2\"\n >\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"clearDraft()\"\n iconStart=\"@tui.trash-2\"\n >\n \u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\n </button>\n </div>\n }\n </div>\n </div>\n} @else {\n <div class=\"flex flex-col gap-12\">\n <div class=\"flex flex-col gap-5\">\n @for (item of [1, 2, 3, 4]; track item) {\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n }\n <div class=\"flex gap-2\">\n <div class=\"tui-skeleton h-10 w-40 rounded-md\"></div>\n <div class=\"tui-skeleton h-10 w-36 rounded-md\"></div>\n </div>\n </div>\n </div>\n}\n" }]
|
|
8957
|
+
}], propDecorators: { draft: [{ type: i0.Input, args: [{ isSignal: true, alias: "draft", required: false }] }, { type: i0.Output, args: ["draftChange"] }], deleteEvent: [{ type: i0.Output, args: ["deleteEvent"] }] } });
|
|
8895
8958
|
|
|
8896
8959
|
/**
|
|
8897
8960
|
* Компонент статуса оплаты заказа.
|
|
@@ -8929,113 +8992,577 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
8929
8992
|
const SC_FAQ_GROUP_QUERY_PARAM = 'group';
|
|
8930
8993
|
|
|
8931
8994
|
/**
|
|
8932
|
-
*
|
|
8995
|
+
* Префикс якоря (fragment) ссылки на конкретный вопрос.
|
|
8933
8996
|
*/
|
|
8934
|
-
|
|
8935
|
-
constructor() {
|
|
8936
|
-
/**
|
|
8937
|
-
* {@link InputSignal} списка группы часто задаваемых вопросов.
|
|
8938
|
-
*/
|
|
8939
|
-
this.items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
8940
|
-
/**
|
|
8941
|
-
* {@link InputSignal} отображения загрузки.
|
|
8942
|
-
*/
|
|
8943
|
-
this.showLoading = input(false, ...(ngDevMode ? [{ debugName: "showLoading" }] : /* istanbul ignore next */ []));
|
|
8944
|
-
/**
|
|
8945
|
-
* Признак, что приложение запущено на сервере.
|
|
8946
|
-
*/
|
|
8947
|
-
this.isServer = inject(IS_SERVER);
|
|
8948
|
-
}
|
|
8949
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScFrequentlyAskedQuestionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8950
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScFrequentlyAskedQuestionsComponent, isStandalone: true, selector: "sc-frequently-asked-questions", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, showLoading: { classPropertyName: "showLoading", publicName: "showLoading", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "ngSkipHydration": "true" } }, providers: [
|
|
8951
|
-
{
|
|
8952
|
-
provide: TUI_BUTTON_OPTIONS,
|
|
8953
|
-
useValue: {
|
|
8954
|
-
...TUI_BUTTON_DEFAULT_OPTIONS,
|
|
8955
|
-
size: 'l',
|
|
8956
|
-
},
|
|
8957
|
-
},
|
|
8958
|
-
], ngImport: i0, template: "<tui-loader\n [loading]=\"showLoading()\"\n [overlay]=\"true\"\n>\n <tui-accordion\n class=\"accordion\"\n [closeOthers]=\"false\"\n >\n @for (item of items(); track item.id) {\n <button\n [tuiAccordion]=\"isServer\"\n class=\"!whitespace-normal !text-body-m-bold\"\n >\n {{ item.question }}\n </button>\n <tui-expand>\n <div [innerHTML]=\"item.answer\"></div>\n </tui-expand>\n }\n </tui-accordion>\n</tui-loader>\n", styles: [".accordion{border-radius:0}.accordion,.accordion[data-size=s],.accordion[data-size=m],.accordion[data-size=l],.accordion .tui-list{font:inherit}.accordion [tuiAccordion]{border-block:1px solid var(--tui-border-normal);border-block-end-color:#fff!important;font-weight:400;border-color:var(--tui-border-normal);-webkit-mask:none;mask:none;block-size:auto;padding-block:.5rem;min-block-size:var(--t-size)}.accordion [tuiAccordion]._open{border-block-end-color:var(--tui-border-normal)!important}.accordion tui-expand,.accordion [tuiAccordion]{box-shadow:none;white-space:normal}\n"], dependencies: [{ kind: "component", type: i1$1.TuiAccordionComponent, selector: "tui-accordion", inputs: ["closeOthers", "size"] }, { kind: "directive", type: i1$1.TuiAccordionDirective, selector: "button[tuiAccordion]", inputs: ["tuiAccordion"], outputs: ["tuiAccordionChange"] }, { kind: "component", type: i2$1.TuiExpand, selector: "tui-expand", inputs: ["expanded"] }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "loading"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
8959
|
-
}
|
|
8960
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScFrequentlyAskedQuestionsComponent, decorators: [{
|
|
8961
|
-
type: Component,
|
|
8962
|
-
args: [{ selector: 'sc-frequently-asked-questions', imports: [TuiAccordion, TuiLoader], providers: [
|
|
8963
|
-
{
|
|
8964
|
-
provide: TUI_BUTTON_OPTIONS,
|
|
8965
|
-
useValue: {
|
|
8966
|
-
...TUI_BUTTON_DEFAULT_OPTIONS,
|
|
8967
|
-
size: 'l',
|
|
8968
|
-
},
|
|
8969
|
-
},
|
|
8970
|
-
], host: { ngSkipHydration: 'true' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<tui-loader\n [loading]=\"showLoading()\"\n [overlay]=\"true\"\n>\n <tui-accordion\n class=\"accordion\"\n [closeOthers]=\"false\"\n >\n @for (item of items(); track item.id) {\n <button\n [tuiAccordion]=\"isServer\"\n class=\"!whitespace-normal !text-body-m-bold\"\n >\n {{ item.question }}\n </button>\n <tui-expand>\n <div [innerHTML]=\"item.answer\"></div>\n </tui-expand>\n }\n </tui-accordion>\n</tui-loader>\n", styles: [".accordion{border-radius:0}.accordion,.accordion[data-size=s],.accordion[data-size=m],.accordion[data-size=l],.accordion .tui-list{font:inherit}.accordion [tuiAccordion]{border-block:1px solid var(--tui-border-normal);border-block-end-color:#fff!important;font-weight:400;border-color:var(--tui-border-normal);-webkit-mask:none;mask:none;block-size:auto;padding-block:.5rem;min-block-size:var(--t-size)}.accordion [tuiAccordion]._open{border-block-end-color:var(--tui-border-normal)!important}.accordion tui-expand,.accordion [tuiAccordion]{box-shadow:none;white-space:normal}\n"] }]
|
|
8971
|
-
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], showLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLoading", required: false }] }] } });
|
|
8972
|
-
|
|
8997
|
+
const SC_FAQ_QUESTION_ANCHOR_PREFIX = 'question-';
|
|
8973
8998
|
/**
|
|
8974
|
-
* Возвращает
|
|
8999
|
+
* Возвращает якорь (fragment) ссылки на вопрос.
|
|
8975
9000
|
*
|
|
8976
|
-
*
|
|
9001
|
+
* @param questionId Идентификатор вопроса.
|
|
9002
|
+
*/
|
|
9003
|
+
const scGetFaqQuestionAnchor = (questionId) => `${SC_FAQ_QUESTION_ANCHOR_PREFIX}${questionId}`;
|
|
9004
|
+
/**
|
|
9005
|
+
* Возвращает идентификатор вопроса из якоря (fragment) ссылки или `null`, если якорь не ссылается на вопрос.
|
|
8977
9006
|
*
|
|
8978
|
-
* @param
|
|
9007
|
+
* @param fragment Якорь (fragment) адреса.
|
|
8979
9008
|
*/
|
|
8980
|
-
const
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
}
|
|
9009
|
+
const scGetFaqQuestionIdFromAnchor = (fragment) => {
|
|
9010
|
+
if (!fragment?.startsWith(SC_FAQ_QUESTION_ANCHOR_PREFIX)) {
|
|
9011
|
+
return null;
|
|
9012
|
+
}
|
|
9013
|
+
const questionId = Number(fragment.slice(SC_FAQ_QUESTION_ANCHOR_PREFIX.length));
|
|
9014
|
+
return Number.isInteger(questionId) && questionId > 0 ? questionId : null;
|
|
9015
|
+
};
|
|
8984
9016
|
|
|
8985
9017
|
/**
|
|
8986
|
-
*
|
|
9018
|
+
* Диалоговое окно "Поделиться": варианты, как поделиться ссылкой.
|
|
9019
|
+
*
|
|
9020
|
+
* На терминале вместо вариантов отображается только QR-код ссылки.
|
|
8987
9021
|
*/
|
|
8988
|
-
class
|
|
8989
|
-
/**
|
|
8990
|
-
* Инициализирует экземпляр класса {@link ScFrequentlyAskedQuestionsGroupSelectorComponent}.
|
|
8991
|
-
*/
|
|
9022
|
+
class ScShareDialogComponent {
|
|
8992
9023
|
constructor() {
|
|
8993
9024
|
/**
|
|
8994
|
-
*
|
|
9025
|
+
* Провайдер данных о терминале.
|
|
8995
9026
|
*/
|
|
8996
|
-
this.
|
|
9027
|
+
this.terminal = inject(IS_RUNNING_ON_TERMINAL);
|
|
8997
9028
|
/**
|
|
8998
|
-
*
|
|
9029
|
+
* Контекст диалогового окна, в котором открыт компонент.
|
|
8999
9030
|
*/
|
|
9000
|
-
this.
|
|
9031
|
+
this.context = inject(POLYMORPHEUS_CONTEXT);
|
|
9001
9032
|
/**
|
|
9002
|
-
*
|
|
9033
|
+
* Сервис копирования текста в буфер обмена.
|
|
9003
9034
|
*/
|
|
9004
|
-
this.
|
|
9035
|
+
this.clipboard = inject(Clipboard);
|
|
9005
9036
|
/**
|
|
9006
|
-
*
|
|
9037
|
+
* Ссылка на объект окна браузера.
|
|
9007
9038
|
*/
|
|
9008
|
-
this.
|
|
9039
|
+
this.window = inject(WA_WINDOW);
|
|
9009
9040
|
/**
|
|
9010
|
-
*
|
|
9041
|
+
* Сервис уведомлений.
|
|
9011
9042
|
*/
|
|
9012
|
-
this.
|
|
9043
|
+
this.alerts = inject(TuiNotificationService);
|
|
9013
9044
|
/**
|
|
9014
|
-
*
|
|
9045
|
+
* Сервис для работы с диалоговыми окнами.
|
|
9015
9046
|
*/
|
|
9016
|
-
this.
|
|
9047
|
+
this.dialog = inject(TuiDialogService);
|
|
9017
9048
|
/**
|
|
9018
|
-
*
|
|
9049
|
+
* Сервис для сбора метрик о действиях пользователей.
|
|
9019
9050
|
*/
|
|
9020
|
-
this.
|
|
9021
|
-
|
|
9022
|
-
|
|
9023
|
-
|
|
9024
|
-
|
|
9025
|
-
|
|
9026
|
-
|
|
9027
|
-
|
|
9028
|
-
this.
|
|
9029
|
-
|
|
9030
|
-
|
|
9031
|
-
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9051
|
+
this.userMetrikaService = inject(ScUserMetrikaService);
|
|
9052
|
+
/**
|
|
9053
|
+
* {@link Signal} формата отображения вариантов: в строку на широких экранах, списком на узких.
|
|
9054
|
+
*/
|
|
9055
|
+
this.viewMode = toSignal(inject(IS_SERVER) ? of('list') : inject(TUI_WINDOW_SIZE).pipe(map((rect) => (rect.width > 768 ? 'row' : 'list'))), { initialValue: 'list' });
|
|
9056
|
+
/**
|
|
9057
|
+
* Заголовок ссылки, которой необходимо поделиться.
|
|
9058
|
+
*/
|
|
9059
|
+
this.title = this.context.data.title;
|
|
9060
|
+
/**
|
|
9061
|
+
* Ссылка, которой необходимо поделиться.
|
|
9062
|
+
*/
|
|
9063
|
+
this.shareUrl = this.context.data.shareUrl;
|
|
9064
|
+
/**
|
|
9065
|
+
* Ссылка отправки по Email.
|
|
9066
|
+
*/
|
|
9067
|
+
this.emailLink = `mailto:?subject=${encodeURIComponent(['ООО Снабцентр', this.title].filter(Boolean).join(' - '))}&body=${encodeURIComponent(this.shareUrl)}`;
|
|
9068
|
+
/**
|
|
9069
|
+
* Ссылка отправки во ВКонтакте.
|
|
9070
|
+
*/
|
|
9071
|
+
this.vkLink = `https://vk.com/share.php?url=${encodeURIComponent(this.shareUrl)}`;
|
|
9072
|
+
/**
|
|
9073
|
+
* Ссылка отправки в Telegram.
|
|
9074
|
+
*/
|
|
9075
|
+
this.telegramLink = `https://t.me/share/url?url=${encodeURIComponent(this.shareUrl)}`;
|
|
9076
|
+
}
|
|
9077
|
+
/** @inheritDoc */
|
|
9078
|
+
ngOnInit() {
|
|
9079
|
+
this.userMetrikaService.emitUserMetrikaEvent({
|
|
9080
|
+
target: ScUserMetrikaGoalsEnum.shareShow,
|
|
9036
9081
|
});
|
|
9037
9082
|
}
|
|
9038
|
-
|
|
9083
|
+
/**
|
|
9084
|
+
* Открывает окно перехода в социальную сеть.
|
|
9085
|
+
*
|
|
9086
|
+
* @param shareLink Ссылка перехода в социальную сеть.
|
|
9087
|
+
* @param socialMedia Slug социальной сети.
|
|
9088
|
+
*/
|
|
9089
|
+
openShareWindow(shareLink, socialMedia) {
|
|
9090
|
+
this.emitShareClick(socialMedia);
|
|
9091
|
+
this.window.open(shareLink, 'sharer', 'status=0,toolbar=0,width=650,height=500');
|
|
9092
|
+
}
|
|
9093
|
+
/**
|
|
9094
|
+
* Копирует ссылку в буфер обмена.
|
|
9095
|
+
*/
|
|
9096
|
+
copyShareLink() {
|
|
9097
|
+
this.emitShareClick('copy_to_clipboard');
|
|
9098
|
+
if (this.clipboard.copy(this.shareUrl)) {
|
|
9099
|
+
this.alerts.open('Ссылка скопирована в буфер обмена.', { appearance: 'positive' }).subscribe();
|
|
9100
|
+
}
|
|
9101
|
+
else {
|
|
9102
|
+
this.alerts.open('Не удалось скопировать ссылку в буфер обмена.', { appearance: 'negative' }).subscribe();
|
|
9103
|
+
}
|
|
9104
|
+
}
|
|
9105
|
+
/**
|
|
9106
|
+
* Открывает диалоговое окно с QR-кодом ссылки.
|
|
9107
|
+
*/
|
|
9108
|
+
showQRCode() {
|
|
9109
|
+
this.emitShareClick('qr');
|
|
9110
|
+
this.userMetrikaService.emitUserMetrikaEvent({
|
|
9111
|
+
target: ScUserMetrikaGoalsEnum.qrShow,
|
|
9112
|
+
});
|
|
9113
|
+
this.dialog
|
|
9114
|
+
.open(new PolymorpheusComponent(ScQRCodeDialogComponent), {
|
|
9115
|
+
size: 's',
|
|
9116
|
+
label: this.title || 'QR-код',
|
|
9117
|
+
data: { qrdata: this.shareUrl },
|
|
9118
|
+
})
|
|
9119
|
+
.subscribe();
|
|
9120
|
+
}
|
|
9121
|
+
/**
|
|
9122
|
+
* Отправляет метрику выбора варианта "Поделиться".
|
|
9123
|
+
*
|
|
9124
|
+
* @param shareLinkName Наименование варианта.
|
|
9125
|
+
*/
|
|
9126
|
+
emitShareClick(shareLinkName) {
|
|
9127
|
+
this.userMetrikaService.emitUserMetrikaEvent({
|
|
9128
|
+
target: ScUserMetrikaGoalsEnum.shareClick,
|
|
9129
|
+
params: {
|
|
9130
|
+
share_link_name: shareLinkName,
|
|
9131
|
+
},
|
|
9132
|
+
});
|
|
9133
|
+
}
|
|
9134
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScShareDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9135
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScShareDialogComponent, isStandalone: true, selector: "sc-share-dialog", ngImport: i0, template: "@if (terminal.isRunningOnTerminal) {\n <p class=\"-mt-2 mb-3 text-tui-text-02\">\u0421\u043A\u0430\u043D\u0438\u0440\u0443\u0439\u0442\u0435 QR-\u043A\u043E\u0434.</p>\n <qrcode\n [margin]=\"0\"\n [qrdata]=\"shareUrl\"\n [width]=\"250\"\n elementType=\"img\"\n ></qrcode>\n} @else {\n @let isRow = viewMode() === 'row';\n @let appearance = isRow ? 'flat' : 'outline';\n @let buttonClass = isRow ? 'button _row' : 'button w-full !justify-start';\n @let iconClass = isRow ? '!m-0 !size-8' : '!m-0 !size-6';\n @let iconSize = isRow ? 32 : 24;\n\n <div\n class=\"gap-2\"\n [class.flex]=\"isRow\"\n [class.grid]=\"!isRow\"\n [class.grid-cols-2]=\"!isRow\"\n >\n <a\n tuiButton\n size=\"m\"\n scEmailLink\n linkLocation=\"share-link\"\n automation-id=\"sc-share-dialog__email\"\n [appearance]=\"appearance\"\n [class]=\"buttonClass\"\n [href]=\"emailLink\"\n >\n <img\n [src]=\"'@tui.sc.img.email' | tuiIcon\"\n alt=\"Email\"\n [width]=\"iconSize\"\n [height]=\"iconSize\"\n [class]=\"iconClass\"\n />\n <span>Email</span>\n </a>\n <a\n tuiButton\n size=\"m\"\n target=\"_blank\"\n automation-id=\"sc-share-dialog__vk\"\n [appearance]=\"appearance\"\n [class]=\"buttonClass\"\n [href]=\"vkLink\"\n (click)=\"$event.preventDefault(); openShareWindow(vkLink, 'vk')\"\n >\n <img\n [src]=\"'@tui.sc.img.vk' | tuiIcon\"\n alt=\"\u0412\u041A\u043E\u043D\u0442\u0430\u043A\u0442\u0435\"\n [width]=\"iconSize\"\n [height]=\"iconSize\"\n [class]=\"iconClass\"\n />\n <span>\u0412\u041A\u043E\u043D\u0442\u0430\u043A\u0442\u0435</span>\n </a>\n <a\n tuiButton\n size=\"m\"\n target=\"_blank\"\n automation-id=\"sc-share-dialog__telegram\"\n [appearance]=\"appearance\"\n [class]=\"buttonClass\"\n [href]=\"telegramLink\"\n (click)=\"$event.preventDefault(); openShareWindow(telegramLink, 'telegram')\"\n >\n <img\n [src]=\"'@tui.sc.img.telegram' | tuiIcon\"\n alt=\"Telegram\"\n [width]=\"iconSize\"\n [height]=\"iconSize\"\n [class]=\"iconClass\"\n />\n <span>Telegram</span>\n </a>\n <button\n tuiButton\n size=\"m\"\n type=\"button\"\n automation-id=\"sc-share-dialog__copy\"\n [appearance]=\"appearance\"\n [class]=\"buttonClass\"\n (click)=\"copyShareLink()\"\n >\n <img\n [src]=\"'@tui.sc.img.copy' | tuiIcon\"\n alt=\"\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C\"\n [width]=\"iconSize\"\n [height]=\"iconSize\"\n [class]=\"iconClass\"\n />\n <span>\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C</span>\n </button>\n <button\n tuiButton\n size=\"m\"\n type=\"button\"\n automation-id=\"sc-share-dialog__qr\"\n [appearance]=\"appearance\"\n [class]=\"buttonClass\"\n (click)=\"showQRCode()\"\n >\n <img\n [src]=\"'@tui.sc.img.qr-code' | tuiIcon\"\n alt=\"QR-\u043A\u043E\u0434\"\n [width]=\"iconSize\"\n [height]=\"iconSize\"\n [class]=\"iconClass\"\n />\n <span>QR-\u043A\u043E\u0434</span>\n </button>\n </div>\n}\n", styles: [".button._row{--tui-padding: .625rem;--t-gap: 0 !important}.button._row span{max-width:0;overflow:hidden;opacity:0;transition-duration:.5s}.button._row:hover span{opacity:1;max-width:11.5rem;padding-left:1rem}\n"], dependencies: [{ kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "directive", type: ScEmailLinkDirective, selector: "a[scEmailLink]", inputs: ["linkLocation"] }, { kind: "component", type: QRCodeComponent, selector: "qrcode", inputs: ["allowEmptyString", "colorDark", "colorLight", "cssClass", "elementType", "errorCorrectionLevel", "imageSrc", "imageHeight", "imageWidth", "margin", "qrdata", "scale", "version", "width", "alt", "ariaLabel", "title"], outputs: ["qrCodeURL"] }, { kind: "pipe", type: TuiIconPipe, name: "tuiIcon" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9136
|
+
}
|
|
9137
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScShareDialogComponent, decorators: [{
|
|
9138
|
+
type: Component,
|
|
9139
|
+
args: [{ standalone: true, selector: 'sc-share-dialog', imports: [TuiButton, TuiIconPipe, ScEmailLinkDirective, QRCodeComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (terminal.isRunningOnTerminal) {\n <p class=\"-mt-2 mb-3 text-tui-text-02\">\u0421\u043A\u0430\u043D\u0438\u0440\u0443\u0439\u0442\u0435 QR-\u043A\u043E\u0434.</p>\n <qrcode\n [margin]=\"0\"\n [qrdata]=\"shareUrl\"\n [width]=\"250\"\n elementType=\"img\"\n ></qrcode>\n} @else {\n @let isRow = viewMode() === 'row';\n @let appearance = isRow ? 'flat' : 'outline';\n @let buttonClass = isRow ? 'button _row' : 'button w-full !justify-start';\n @let iconClass = isRow ? '!m-0 !size-8' : '!m-0 !size-6';\n @let iconSize = isRow ? 32 : 24;\n\n <div\n class=\"gap-2\"\n [class.flex]=\"isRow\"\n [class.grid]=\"!isRow\"\n [class.grid-cols-2]=\"!isRow\"\n >\n <a\n tuiButton\n size=\"m\"\n scEmailLink\n linkLocation=\"share-link\"\n automation-id=\"sc-share-dialog__email\"\n [appearance]=\"appearance\"\n [class]=\"buttonClass\"\n [href]=\"emailLink\"\n >\n <img\n [src]=\"'@tui.sc.img.email' | tuiIcon\"\n alt=\"Email\"\n [width]=\"iconSize\"\n [height]=\"iconSize\"\n [class]=\"iconClass\"\n />\n <span>Email</span>\n </a>\n <a\n tuiButton\n size=\"m\"\n target=\"_blank\"\n automation-id=\"sc-share-dialog__vk\"\n [appearance]=\"appearance\"\n [class]=\"buttonClass\"\n [href]=\"vkLink\"\n (click)=\"$event.preventDefault(); openShareWindow(vkLink, 'vk')\"\n >\n <img\n [src]=\"'@tui.sc.img.vk' | tuiIcon\"\n alt=\"\u0412\u041A\u043E\u043D\u0442\u0430\u043A\u0442\u0435\"\n [width]=\"iconSize\"\n [height]=\"iconSize\"\n [class]=\"iconClass\"\n />\n <span>\u0412\u041A\u043E\u043D\u0442\u0430\u043A\u0442\u0435</span>\n </a>\n <a\n tuiButton\n size=\"m\"\n target=\"_blank\"\n automation-id=\"sc-share-dialog__telegram\"\n [appearance]=\"appearance\"\n [class]=\"buttonClass\"\n [href]=\"telegramLink\"\n (click)=\"$event.preventDefault(); openShareWindow(telegramLink, 'telegram')\"\n >\n <img\n [src]=\"'@tui.sc.img.telegram' | tuiIcon\"\n alt=\"Telegram\"\n [width]=\"iconSize\"\n [height]=\"iconSize\"\n [class]=\"iconClass\"\n />\n <span>Telegram</span>\n </a>\n <button\n tuiButton\n size=\"m\"\n type=\"button\"\n automation-id=\"sc-share-dialog__copy\"\n [appearance]=\"appearance\"\n [class]=\"buttonClass\"\n (click)=\"copyShareLink()\"\n >\n <img\n [src]=\"'@tui.sc.img.copy' | tuiIcon\"\n alt=\"\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C\"\n [width]=\"iconSize\"\n [height]=\"iconSize\"\n [class]=\"iconClass\"\n />\n <span>\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C</span>\n </button>\n <button\n tuiButton\n size=\"m\"\n type=\"button\"\n automation-id=\"sc-share-dialog__qr\"\n [appearance]=\"appearance\"\n [class]=\"buttonClass\"\n (click)=\"showQRCode()\"\n >\n <img\n [src]=\"'@tui.sc.img.qr-code' | tuiIcon\"\n alt=\"QR-\u043A\u043E\u0434\"\n [width]=\"iconSize\"\n [height]=\"iconSize\"\n [class]=\"iconClass\"\n />\n <span>QR-\u043A\u043E\u0434</span>\n </button>\n </div>\n}\n", styles: [".button._row{--tui-padding: .625rem;--t-gap: 0 !important}.button._row span{max-width:0;overflow:hidden;opacity:0;transition-duration:.5s}.button._row:hover span{opacity:1;max-width:11.5rem;padding-left:1rem}\n"] }]
|
|
9140
|
+
}] });
|
|
9141
|
+
|
|
9142
|
+
/**
|
|
9143
|
+
* Сервис открытия диалогового окна "Поделиться".
|
|
9144
|
+
*/
|
|
9145
|
+
class ScShareService {
|
|
9146
|
+
constructor() {
|
|
9147
|
+
/**
|
|
9148
|
+
* Сервис для работы с диалоговыми окнами.
|
|
9149
|
+
*/
|
|
9150
|
+
this.dialog = inject(TuiDialogService);
|
|
9151
|
+
}
|
|
9152
|
+
/**
|
|
9153
|
+
* Открывает диалоговое окно "Поделиться".
|
|
9154
|
+
*
|
|
9155
|
+
* @param title Заголовок ссылки, которой необходимо поделиться.
|
|
9156
|
+
* @param shareUrl Абсолютная ссылка, которой необходимо поделиться.
|
|
9157
|
+
*/
|
|
9158
|
+
openShareDialog(title, shareUrl) {
|
|
9159
|
+
this.dialog
|
|
9160
|
+
.open(new PolymorpheusComponent(ScShareDialogComponent), {
|
|
9161
|
+
size: 's',
|
|
9162
|
+
label: 'Поделиться',
|
|
9163
|
+
data: { title, shareUrl },
|
|
9164
|
+
})
|
|
9165
|
+
.subscribe();
|
|
9166
|
+
}
|
|
9167
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScShareService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
9168
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScShareService, providedIn: 'root' }); }
|
|
9169
|
+
}
|
|
9170
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScShareService, decorators: [{
|
|
9171
|
+
type: Injectable,
|
|
9172
|
+
args: [{
|
|
9173
|
+
providedIn: 'root',
|
|
9174
|
+
}]
|
|
9175
|
+
}] });
|
|
9176
|
+
|
|
9177
|
+
/**
|
|
9178
|
+
* Кнопка "Поделиться": открывает диалоговое окно с вариантами, как поделиться ссылкой.
|
|
9179
|
+
*
|
|
9180
|
+
* Ссылка формируется из {@link routerPath} относительно маршрутизации приложения, либо берётся из {@link shareUrl},
|
|
9181
|
+
* а если не задано ни то, ни другое - используется адрес текущей страницы.
|
|
9182
|
+
*/
|
|
9183
|
+
class ScShareButtonComponent {
|
|
9184
|
+
constructor() {
|
|
9185
|
+
/**
|
|
9186
|
+
* {@link InputSignal} заголовка ссылки, которой необходимо поделиться.
|
|
9187
|
+
*/
|
|
9188
|
+
this.title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
9189
|
+
/**
|
|
9190
|
+
* {@link InputSignal} ссылки, которой необходимо поделиться (абсолютной или относительно корня сайта).
|
|
9191
|
+
*/
|
|
9192
|
+
this.shareUrl = input(...(ngDevMode ? [undefined, { debugName: "shareUrl" }] : /* istanbul ignore next */ []));
|
|
9193
|
+
/**
|
|
9194
|
+
* {@link InputSignal} команд маршрутизатора, из которых формируется ссылка относительно маршрутизации приложения.
|
|
9195
|
+
*/
|
|
9196
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9197
|
+
this.routerPath = input(...(ngDevMode ? [undefined, { debugName: "routerPath" }] : /* istanbul ignore next */ []));
|
|
9198
|
+
/**
|
|
9199
|
+
* {@link InputSignal} параметров формирования ссылки из {@link routerPath}.
|
|
9200
|
+
*/
|
|
9201
|
+
this.routerCreationOptions = input(...(ngDevMode ? [undefined, { debugName: "routerCreationOptions" }] : /* istanbul ignore next */ []));
|
|
9202
|
+
/**
|
|
9203
|
+
* {@link InputSignal} формата внешнего вида кнопки.
|
|
9204
|
+
*/
|
|
9205
|
+
this.appearance = input('secondary', ...(ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []));
|
|
9206
|
+
/**
|
|
9207
|
+
* {@link InputSignal} размера кнопки.
|
|
9208
|
+
*/
|
|
9209
|
+
this.size = input('m', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
9210
|
+
/**
|
|
9211
|
+
* {@link InputSignal} признака, что подпись "Поделиться" отображается постоянно.
|
|
9212
|
+
*/
|
|
9213
|
+
this.showLabel = input(false, ...(ngDevMode ? [{ debugName: "showLabel" }] : /* istanbul ignore next */ []));
|
|
9214
|
+
/**
|
|
9215
|
+
* {@link InputSignal} признака, что кнопка раскрывается с появлением подписи "Поделиться" при наведении.
|
|
9216
|
+
*/
|
|
9217
|
+
this.expandable = input(false, ...(ngDevMode ? [{ debugName: "expandable" }] : /* istanbul ignore next */ []));
|
|
9218
|
+
/**
|
|
9219
|
+
* Ссылка на объект документа.
|
|
9220
|
+
*/
|
|
9221
|
+
this.document = inject(DOCUMENT);
|
|
9222
|
+
/**
|
|
9223
|
+
* Сервис маршрутизации.
|
|
9224
|
+
*/
|
|
9225
|
+
this.router = inject(Router);
|
|
9226
|
+
/**
|
|
9227
|
+
* Сервис открытия диалогового окна "Поделиться".
|
|
9228
|
+
*/
|
|
9229
|
+
this.shareService = inject(ScShareService);
|
|
9230
|
+
/**
|
|
9231
|
+
* {@link Signal} ссылки, которой необходимо поделиться, заданной через входные параметры.
|
|
9232
|
+
*/
|
|
9233
|
+
this.href = computed(() => {
|
|
9234
|
+
const routerPath = this.routerPath();
|
|
9235
|
+
const url = routerPath ? this.router.createUrlTree(routerPath, this.routerCreationOptions()).toString() : this.shareUrl();
|
|
9236
|
+
return url ? decodeURIComponent(url) : undefined;
|
|
9237
|
+
}, ...(ngDevMode ? [{ debugName: "href" }] : /* istanbul ignore next */ []));
|
|
9238
|
+
}
|
|
9239
|
+
/**
|
|
9240
|
+
* Возвращает адрес текущей страницы.
|
|
9241
|
+
*/
|
|
9242
|
+
get currentUrl() {
|
|
9243
|
+
return decodeURIComponent(this.router.url);
|
|
9244
|
+
}
|
|
9245
|
+
/**
|
|
9246
|
+
* Обработчик нажатия на кнопку: открывает диалоговое окно "Поделиться".
|
|
9247
|
+
*
|
|
9248
|
+
* @param event Событие нажатия.
|
|
9249
|
+
*/
|
|
9250
|
+
openShareDialog(event) {
|
|
9251
|
+
event.preventDefault();
|
|
9252
|
+
this.shareService.openShareDialog(this.title(), this.getAbsoluteUrl(this.href() ?? this.currentUrl));
|
|
9253
|
+
}
|
|
9254
|
+
/**
|
|
9255
|
+
* Возвращает абсолютную ссылку.
|
|
9256
|
+
*
|
|
9257
|
+
* @param url Абсолютная ссылка или ссылка относительно корня сайта.
|
|
9258
|
+
*/
|
|
9259
|
+
getAbsoluteUrl(url) {
|
|
9260
|
+
return /^https?:\/\//.test(url) ? url : `${this.document.location.origin}${url}`;
|
|
9261
|
+
}
|
|
9262
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScShareButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9263
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScShareButtonComponent, isStandalone: true, selector: "sc-share-button", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, shareUrl: { classPropertyName: "shareUrl", publicName: "shareUrl", isSignal: true, isRequired: false, transformFunction: null }, routerPath: { classPropertyName: "routerPath", publicName: "routerPath", isSignal: true, isRequired: false, transformFunction: null }, routerCreationOptions: { classPropertyName: "routerCreationOptions", publicName: "routerCreationOptions", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showLabel: { classPropertyName: "showLabel", publicName: "showLabel", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (showLabel() || expandable()) {\n <a\n tuiButton\n iconStart=\"@tui.share-2\"\n [appearance]=\"appearance()\"\n [size]=\"size()\"\n [attr.href]=\"href() ?? currentUrl\"\n [class._expandable]=\"expandable()\"\n (click)=\"openShareDialog($event)\"\n >\n <span>\u041F\u043E\u0434\u0435\u043B\u0438\u0442\u044C\u0441\u044F</span>\n </a>\n} @else {\n <a\n tuiIconButton\n iconStart=\"@tui.share-2\"\n title=\"\u041F\u043E\u0434\u0435\u043B\u0438\u0442\u044C\u0441\u044F\"\n aria-label=\"\u041F\u043E\u0434\u0435\u043B\u0438\u0442\u044C\u0441\u044F\"\n [appearance]=\"appearance()\"\n [size]=\"size()\"\n [attr.href]=\"href() ?? currentUrl\"\n (click)=\"openShareDialog($event)\"\n ></a>\n}\n", styles: ["a._expandable{--t-gap: 0 !important}a._expandable span{max-width:0;overflow:hidden;opacity:0;transition-duration:.5s}a._expandable:hover span{opacity:1;max-width:11.5rem;padding-left:1rem}\n"], dependencies: [{ kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9264
|
+
}
|
|
9265
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScShareButtonComponent, decorators: [{
|
|
9266
|
+
type: Component,
|
|
9267
|
+
args: [{ standalone: true, selector: 'sc-share-button', imports: [TuiButton], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (showLabel() || expandable()) {\n <a\n tuiButton\n iconStart=\"@tui.share-2\"\n [appearance]=\"appearance()\"\n [size]=\"size()\"\n [attr.href]=\"href() ?? currentUrl\"\n [class._expandable]=\"expandable()\"\n (click)=\"openShareDialog($event)\"\n >\n <span>\u041F\u043E\u0434\u0435\u043B\u0438\u0442\u044C\u0441\u044F</span>\n </a>\n} @else {\n <a\n tuiIconButton\n iconStart=\"@tui.share-2\"\n title=\"\u041F\u043E\u0434\u0435\u043B\u0438\u0442\u044C\u0441\u044F\"\n aria-label=\"\u041F\u043E\u0434\u0435\u043B\u0438\u0442\u044C\u0441\u044F\"\n [appearance]=\"appearance()\"\n [size]=\"size()\"\n [attr.href]=\"href() ?? currentUrl\"\n (click)=\"openShareDialog($event)\"\n ></a>\n}\n", styles: ["a._expandable{--t-gap: 0 !important}a._expandable span{max-width:0;overflow:hidden;opacity:0;transition-duration:.5s}a._expandable:hover span{opacity:1;max-width:11.5rem;padding-left:1rem}\n"] }]
|
|
9268
|
+
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], shareUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "shareUrl", required: false }] }], routerPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "routerPath", required: false }] }], routerCreationOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "routerCreationOptions", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }] } });
|
|
9269
|
+
|
|
9270
|
+
/**
|
|
9271
|
+
* Ссылки на мессенджеры контакта по номеру телефона.
|
|
9272
|
+
*
|
|
9273
|
+
* На терминале вместо перехода в мессенджер отображается QR-код ссылки.
|
|
9274
|
+
*/
|
|
9275
|
+
class ScShareMessengersLinksComponent {
|
|
9276
|
+
constructor() {
|
|
9277
|
+
/**
|
|
9278
|
+
* {@link InputSignal} телефона контакта.
|
|
9279
|
+
*/
|
|
9280
|
+
this.phone = input.required(...(ngDevMode ? [{ debugName: "phone" }] : /* istanbul ignore next */ []));
|
|
9281
|
+
/**
|
|
9282
|
+
* {@link InputSignal} размера кнопок.
|
|
9283
|
+
*/
|
|
9284
|
+
this.size = input('s', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
9285
|
+
/**
|
|
9286
|
+
* Сервис для сбора метрик о действиях пользователей.
|
|
9287
|
+
*/
|
|
9288
|
+
this.userMetrikaService = inject(ScUserMetrikaService);
|
|
9289
|
+
/**
|
|
9290
|
+
* Ссылка на объект окна браузера.
|
|
9291
|
+
*/
|
|
9292
|
+
this.window = inject(WA_WINDOW);
|
|
9293
|
+
/**
|
|
9294
|
+
* Провайдер данных о терминале.
|
|
9295
|
+
*/
|
|
9296
|
+
this.terminal = inject(IS_RUNNING_ON_TERMINAL);
|
|
9297
|
+
/**
|
|
9298
|
+
* Сервис для работы с диалоговыми окнами.
|
|
9299
|
+
*/
|
|
9300
|
+
this.dialog = inject(TuiDialogService);
|
|
9301
|
+
}
|
|
9302
|
+
/**
|
|
9303
|
+
* Открывает окно перехода в мессенджер.
|
|
9304
|
+
*
|
|
9305
|
+
* @param shareLink Ссылка перехода в мессенджер.
|
|
9306
|
+
* @param socialMedia Slug мессенджера.
|
|
9307
|
+
*/
|
|
9308
|
+
openShareWindow(shareLink, socialMedia) {
|
|
9309
|
+
this.userMetrikaService.emitUserMetrikaEvent({
|
|
9310
|
+
target: ScUserMetrikaGoalsEnum.shareClick,
|
|
9311
|
+
params: {
|
|
9312
|
+
share_link_name: socialMedia,
|
|
9313
|
+
phone: this.phone(),
|
|
9314
|
+
},
|
|
9315
|
+
});
|
|
9316
|
+
if (this.terminal.isRunningOnTerminal) {
|
|
9317
|
+
this.dialog
|
|
9318
|
+
.open(new PolymorpheusComponent(ScQRCodeDialogComponent), {
|
|
9319
|
+
size: 's',
|
|
9320
|
+
label: socialMedia,
|
|
9321
|
+
data: { qrdata: shareLink },
|
|
9322
|
+
})
|
|
9323
|
+
.subscribe();
|
|
9324
|
+
}
|
|
9325
|
+
else {
|
|
9326
|
+
this.window.open(shareLink, 'sharer', 'status=0,toolbar=0,width=650,height=500');
|
|
9327
|
+
}
|
|
9328
|
+
}
|
|
9329
|
+
/**
|
|
9330
|
+
* Проверяет, что номер телефона подходит для использования в мессенджерах.
|
|
9331
|
+
*
|
|
9332
|
+
* @param value Номер телефона.
|
|
9333
|
+
*/
|
|
9334
|
+
// eslint-disable-next-line class-methods-use-this
|
|
9335
|
+
isValidPhoneNumberForMessenger(value) {
|
|
9336
|
+
return ScPhoneService.isValidPhoneNumberForMessenger(value);
|
|
9337
|
+
}
|
|
9338
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScShareMessengersLinksComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9339
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScShareMessengersLinksComponent, isStandalone: true, selector: "sc-share-messengers-links", inputs: { phone: { classPropertyName: "phone", publicName: "phone", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (isValidPhoneNumberForMessenger(phone())) {\n @let phoneNumber = phone() | scPhoneFormat: 'cleanWithPlus';\n\n <button\n tuiIconButton\n type=\"button\"\n appearance=\"mono\"\n iconStart=\"@tui.sc.telegram\"\n title=\"Telegram\"\n aria-label=\"Telegram\"\n [size]=\"size()\"\n (click)=\"openShareWindow('https://t.me/' + phoneNumber, 'telegram')\"\n ></button>\n}\n", dependencies: [{ kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "pipe", type: ScPhoneFormatPipe, name: "scPhoneFormat" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9340
|
+
}
|
|
9341
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScShareMessengersLinksComponent, decorators: [{
|
|
9342
|
+
type: Component,
|
|
9343
|
+
args: [{ standalone: true, selector: 'sc-share-messengers-links', imports: [TuiButton, ScPhoneFormatPipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (isValidPhoneNumberForMessenger(phone())) {\n @let phoneNumber = phone() | scPhoneFormat: 'cleanWithPlus';\n\n <button\n tuiIconButton\n type=\"button\"\n appearance=\"mono\"\n iconStart=\"@tui.sc.telegram\"\n title=\"Telegram\"\n aria-label=\"Telegram\"\n [size]=\"size()\"\n (click)=\"openShareWindow('https://t.me/' + phoneNumber, 'telegram')\"\n ></button>\n}\n" }]
|
|
9344
|
+
}], propDecorators: { phone: [{ type: i0.Input, args: [{ isSignal: true, alias: "phone", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
9345
|
+
|
|
9346
|
+
/**
|
|
9347
|
+
* Компонент часто задаваемых вопросов.
|
|
9348
|
+
*/
|
|
9349
|
+
class ScFrequentlyAskedQuestionsComponent {
|
|
9350
|
+
/**
|
|
9351
|
+
* Инициализирует экземпляр класса {@link ScFrequentlyAskedQuestionsComponent}.
|
|
9352
|
+
*/
|
|
9353
|
+
constructor() {
|
|
9354
|
+
/**
|
|
9355
|
+
* {@link InputSignal} списка группы часто задаваемых вопросов.
|
|
9356
|
+
*/
|
|
9357
|
+
this.items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
9358
|
+
/**
|
|
9359
|
+
* {@link InputSignal} отображения загрузки.
|
|
9360
|
+
*/
|
|
9361
|
+
this.showLoading = input(false, ...(ngDevMode ? [{ debugName: "showLoading" }] : /* istanbul ignore next */ []));
|
|
9362
|
+
/**
|
|
9363
|
+
* {@link InputSignal} параметров прокрутки к вопросу из якоря.
|
|
9364
|
+
*/
|
|
9365
|
+
this.scrollOptions = input({ behavior: 'instant', block: 'center' }, ...(ngDevMode ? [{ debugName: "scrollOptions" }] : /* istanbul ignore next */ []));
|
|
9366
|
+
/**
|
|
9367
|
+
* {@link InputSignal} количества кадров удержания вопроса из якоря в поле зрения (около 5 секунд).
|
|
9368
|
+
*/
|
|
9369
|
+
this.scrollHoldFrames = input(300, ...(ngDevMode ? [{ debugName: "scrollHoldFrames" }] : /* istanbul ignore next */ []));
|
|
9370
|
+
/**
|
|
9371
|
+
* Признак, что приложение запущено на сервере.
|
|
9372
|
+
*/
|
|
9373
|
+
this.isServer = inject(IS_SERVER);
|
|
9374
|
+
/**
|
|
9375
|
+
* {@link WritableSignal} идентификаторов раскрытых вопросов.
|
|
9376
|
+
*/
|
|
9377
|
+
this.openedIds = signal(new Set(), ...(ngDevMode ? [{ debugName: "openedIds" }] : /* istanbul ignore next */ []));
|
|
9378
|
+
/**
|
|
9379
|
+
* Возвращает якорь ссылки на вопрос.
|
|
9380
|
+
*/
|
|
9381
|
+
this.getAnchor = scGetFaqQuestionAnchor;
|
|
9382
|
+
/**
|
|
9383
|
+
* Активный маршрут.
|
|
9384
|
+
*/
|
|
9385
|
+
this.route = inject(ActivatedRoute);
|
|
9386
|
+
/**
|
|
9387
|
+
* Инжектор компонента.
|
|
9388
|
+
*/
|
|
9389
|
+
this.injector = inject(Injector);
|
|
9390
|
+
/**
|
|
9391
|
+
* Ссылка на уничтожение компонента.
|
|
9392
|
+
*/
|
|
9393
|
+
this.destroyRef = inject(DestroyRef);
|
|
9394
|
+
/**
|
|
9395
|
+
* {@link Signal} ссылок на заголовки вопросов.
|
|
9396
|
+
*/
|
|
9397
|
+
this.questionHeaders = viewChildren('questionHeader', ...(ngDevMode ? [{ debugName: "questionHeaders" }] : /* istanbul ignore next */ []));
|
|
9398
|
+
// На сервере все вопросы раскрыты.
|
|
9399
|
+
if (this.isServer) {
|
|
9400
|
+
return;
|
|
9401
|
+
}
|
|
9402
|
+
// Раскрываем вопрос из якоря и прокручиваем к нему: якорь может смениться на открытой странице, список загрузиться позже.
|
|
9403
|
+
combineLatest([this.route.fragment, toObservable(this.items)])
|
|
9404
|
+
.pipe(map(([fragment, items]) => {
|
|
9405
|
+
const questionId = scGetFaqQuestionIdFromAnchor(fragment);
|
|
9406
|
+
return questionId !== null && items.some((item) => item.id === questionId) ? questionId : null;
|
|
9407
|
+
}), filter(tuiIsPresent), takeUntilDestroyed())
|
|
9408
|
+
.subscribe((questionId) => {
|
|
9409
|
+
this.onOpenedChange(questionId, true);
|
|
9410
|
+
afterNextRender(() => {
|
|
9411
|
+
const header = this.getQuestionHeader(questionId);
|
|
9412
|
+
if (header) {
|
|
9413
|
+
this.scrollToHeader(header);
|
|
9414
|
+
}
|
|
9415
|
+
}, { injector: this.injector });
|
|
9416
|
+
});
|
|
9417
|
+
}
|
|
9418
|
+
/**
|
|
9419
|
+
* Возвращает параметры формирования ссылки на вопрос: текущая страница с её query-параметрами и якорем вопроса.
|
|
9420
|
+
*
|
|
9421
|
+
* @param questionId Идентификатор вопроса.
|
|
9422
|
+
*/
|
|
9423
|
+
getShareLinkOptions(questionId) {
|
|
9424
|
+
return {
|
|
9425
|
+
relativeTo: this.route,
|
|
9426
|
+
queryParamsHandling: 'preserve',
|
|
9427
|
+
fragment: scGetFaqQuestionAnchor(questionId),
|
|
9428
|
+
};
|
|
9429
|
+
}
|
|
9430
|
+
/**
|
|
9431
|
+
* Обработчик изменения состояния раскрытия вопроса.
|
|
9432
|
+
*
|
|
9433
|
+
* @param questionId Идентификатор вопроса.
|
|
9434
|
+
* @param opened Признак, что вопрос раскрыт.
|
|
9435
|
+
*/
|
|
9436
|
+
onOpenedChange(questionId, opened) {
|
|
9437
|
+
this.openedIds.update((ids) => {
|
|
9438
|
+
const nextIds = new Set(ids);
|
|
9439
|
+
if (opened) {
|
|
9440
|
+
nextIds.add(questionId);
|
|
9441
|
+
}
|
|
9442
|
+
else {
|
|
9443
|
+
nextIds.delete(questionId);
|
|
9444
|
+
}
|
|
9445
|
+
return nextIds;
|
|
9446
|
+
});
|
|
9447
|
+
}
|
|
9448
|
+
/**
|
|
9449
|
+
* Возвращает элемент заголовка вопроса.
|
|
9450
|
+
*
|
|
9451
|
+
* @param questionId Идентификатор вопроса.
|
|
9452
|
+
*/
|
|
9453
|
+
getQuestionHeader(questionId) {
|
|
9454
|
+
const anchor = scGetFaqQuestionAnchor(questionId);
|
|
9455
|
+
return this.questionHeaders().find((header) => header.nativeElement.id === anchor)?.nativeElement;
|
|
9456
|
+
}
|
|
9457
|
+
/**
|
|
9458
|
+
* Прокручивает страницу к заголовку вопроса и удерживает его в поле зрения.
|
|
9459
|
+
*
|
|
9460
|
+
* @param header Элемент заголовка вопроса.
|
|
9461
|
+
*/
|
|
9462
|
+
scrollToHeader(header) {
|
|
9463
|
+
const getTop = () => Math.round(header.getBoundingClientRect().top);
|
|
9464
|
+
const userScroll$ = merge(fromEvent(globalThis, 'wheel'), fromEvent(globalThis, 'touchstart'), fromEvent(globalThis, 'keydown'), fromEvent(globalThis, 'mousedown'));
|
|
9465
|
+
// Мгновенно: плавная прокрутка не выполняется в скрытой вкладке.
|
|
9466
|
+
header.scrollIntoView(this.scrollOptions());
|
|
9467
|
+
let expectedTop = getTop();
|
|
9468
|
+
// Повторяем прокрутку, если вопрос сдвинула догрузка страницы или чужая прокрутка, пока пользователь не начнёт прокручивать сам.
|
|
9469
|
+
animationFrames()
|
|
9470
|
+
.pipe(take(this.scrollHoldFrames()), map(getTop), filter((top) => top !== expectedTop), takeUntilDestroyed(this.destroyRef), takeUntil(userScroll$))
|
|
9471
|
+
.subscribe(() => {
|
|
9472
|
+
header.scrollIntoView(this.scrollOptions());
|
|
9473
|
+
expectedTop = getTop();
|
|
9474
|
+
});
|
|
9475
|
+
}
|
|
9476
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScFrequentlyAskedQuestionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9477
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScFrequentlyAskedQuestionsComponent, isStandalone: true, selector: "sc-frequently-asked-questions", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, showLoading: { classPropertyName: "showLoading", publicName: "showLoading", isSignal: true, isRequired: false, transformFunction: null }, scrollOptions: { classPropertyName: "scrollOptions", publicName: "scrollOptions", isSignal: true, isRequired: false, transformFunction: null }, scrollHoldFrames: { classPropertyName: "scrollHoldFrames", publicName: "scrollHoldFrames", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "ngSkipHydration": "true" } }, providers: [
|
|
9478
|
+
{
|
|
9479
|
+
provide: TUI_BUTTON_OPTIONS,
|
|
9480
|
+
useValue: {
|
|
9481
|
+
...TUI_BUTTON_DEFAULT_OPTIONS,
|
|
9482
|
+
size: 'l',
|
|
9483
|
+
},
|
|
9484
|
+
},
|
|
9485
|
+
], viewQueries: [{ propertyName: "questionHeaders", predicate: ["questionHeader"], descendants: true, isSignal: true }], ngImport: i0, template: "<tui-loader\n [loading]=\"showLoading()\"\n [overlay]=\"true\"\n>\n <tui-accordion\n class=\"accordion\"\n [closeOthers]=\"false\"\n >\n @for (item of items(); track item.id) {\n @let anchor = getAnchor(item.id);\n\n <button\n #questionHeader\n [id]=\"anchor\"\n [tuiAccordion]=\"isServer || openedIds().has(item.id)\"\n (tuiAccordionChange)=\"onOpenedChange(item.id, !!$event)\"\n class=\"!whitespace-normal !text-body-m-bold\"\n >\n <span class=\"grow\">{{ item.question }}</span>\n <sc-share-button\n appearance=\"flat\"\n size=\"s\"\n class=\"shrink-0\"\n [title]=\"item.question\"\n [routerPath]=\"[]\"\n [routerCreationOptions]=\"getShareLinkOptions(item.id)\"\n (click)=\"$event.stopPropagation()\"\n />\n </button>\n <tui-expand>\n <div [innerHTML]=\"item.answer\"></div>\n </tui-expand>\n }\n </tui-accordion>\n</tui-loader>\n", styles: [".accordion{border-radius:0}.accordion,.accordion[data-size=s],.accordion[data-size=m],.accordion[data-size=l],.accordion .tui-list{font:inherit}.accordion [tuiAccordion]{border-block:1px solid var(--tui-border-normal);border-block-end-color:#fff!important;font-weight:400;border-color:var(--tui-border-normal);-webkit-mask:none;mask:none;block-size:auto;padding-block:.5rem;min-block-size:var(--t-size)}.accordion [tuiAccordion]._open{border-block-end-color:var(--tui-border-normal)!important}.accordion tui-expand,.accordion [tuiAccordion]{box-shadow:none;white-space:normal}\n"], dependencies: [{ kind: "component", type: i1$1.TuiAccordionComponent, selector: "tui-accordion", inputs: ["closeOthers", "size"] }, { kind: "directive", type: i1$1.TuiAccordionDirective, selector: "button[tuiAccordion]", inputs: ["tuiAccordion"], outputs: ["tuiAccordionChange"] }, { kind: "component", type: i2$1.TuiExpand, selector: "tui-expand", inputs: ["expanded"] }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "loading"] }, { kind: "component", type: ScShareButtonComponent, selector: "sc-share-button", inputs: ["title", "shareUrl", "routerPath", "routerCreationOptions", "appearance", "size", "showLabel", "expandable"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9486
|
+
}
|
|
9487
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScFrequentlyAskedQuestionsComponent, decorators: [{
|
|
9488
|
+
type: Component,
|
|
9489
|
+
args: [{ selector: 'sc-frequently-asked-questions', imports: [TuiAccordion, TuiLoader, ScShareButtonComponent], providers: [
|
|
9490
|
+
{
|
|
9491
|
+
provide: TUI_BUTTON_OPTIONS,
|
|
9492
|
+
useValue: {
|
|
9493
|
+
...TUI_BUTTON_DEFAULT_OPTIONS,
|
|
9494
|
+
size: 'l',
|
|
9495
|
+
},
|
|
9496
|
+
},
|
|
9497
|
+
], host: { ngSkipHydration: 'true' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<tui-loader\n [loading]=\"showLoading()\"\n [overlay]=\"true\"\n>\n <tui-accordion\n class=\"accordion\"\n [closeOthers]=\"false\"\n >\n @for (item of items(); track item.id) {\n @let anchor = getAnchor(item.id);\n\n <button\n #questionHeader\n [id]=\"anchor\"\n [tuiAccordion]=\"isServer || openedIds().has(item.id)\"\n (tuiAccordionChange)=\"onOpenedChange(item.id, !!$event)\"\n class=\"!whitespace-normal !text-body-m-bold\"\n >\n <span class=\"grow\">{{ item.question }}</span>\n <sc-share-button\n appearance=\"flat\"\n size=\"s\"\n class=\"shrink-0\"\n [title]=\"item.question\"\n [routerPath]=\"[]\"\n [routerCreationOptions]=\"getShareLinkOptions(item.id)\"\n (click)=\"$event.stopPropagation()\"\n />\n </button>\n <tui-expand>\n <div [innerHTML]=\"item.answer\"></div>\n </tui-expand>\n }\n </tui-accordion>\n</tui-loader>\n", styles: [".accordion{border-radius:0}.accordion,.accordion[data-size=s],.accordion[data-size=m],.accordion[data-size=l],.accordion .tui-list{font:inherit}.accordion [tuiAccordion]{border-block:1px solid var(--tui-border-normal);border-block-end-color:#fff!important;font-weight:400;border-color:var(--tui-border-normal);-webkit-mask:none;mask:none;block-size:auto;padding-block:.5rem;min-block-size:var(--t-size)}.accordion [tuiAccordion]._open{border-block-end-color:var(--tui-border-normal)!important}.accordion tui-expand,.accordion [tuiAccordion]{box-shadow:none;white-space:normal}\n"] }]
|
|
9498
|
+
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], showLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLoading", required: false }] }], scrollOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollOptions", required: false }] }], scrollHoldFrames: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollHoldFrames", required: false }] }], questionHeaders: [{ type: i0.ViewChildren, args: ['questionHeader', { isSignal: true }] }] } });
|
|
9499
|
+
|
|
9500
|
+
/**
|
|
9501
|
+
* Возвращает query-параметры ссылки на группу часто задаваемых вопросов.
|
|
9502
|
+
*
|
|
9503
|
+
* При смене группы пагинация сбрасывается на первую страницу.
|
|
9504
|
+
*
|
|
9505
|
+
* @param group Группа вопросов.
|
|
9506
|
+
*/
|
|
9507
|
+
const scGetFaqGroupQueryParams = (group) => ({
|
|
9508
|
+
[SC_FAQ_GROUP_QUERY_PARAM]: group.id ?? null,
|
|
9509
|
+
[SC_PAGE_QUERY_PARAM]: null,
|
|
9510
|
+
});
|
|
9511
|
+
|
|
9512
|
+
/**
|
|
9513
|
+
* Компонент выбора группы часто задаваемых вопросов.
|
|
9514
|
+
*/
|
|
9515
|
+
class ScFrequentlyAskedQuestionsGroupSelectorComponent {
|
|
9516
|
+
/**
|
|
9517
|
+
* Инициализирует экземпляр класса {@link ScFrequentlyAskedQuestionsGroupSelectorComponent}.
|
|
9518
|
+
*/
|
|
9519
|
+
constructor() {
|
|
9520
|
+
/**
|
|
9521
|
+
* Сервис маршрутизации.
|
|
9522
|
+
*/
|
|
9523
|
+
this.router = inject(Router);
|
|
9524
|
+
/**
|
|
9525
|
+
* Активный маршрут.
|
|
9526
|
+
*/
|
|
9527
|
+
this.route = inject(ActivatedRoute);
|
|
9528
|
+
/**
|
|
9529
|
+
* {@link Observable} списка группы часто задаваемых вопросов.
|
|
9530
|
+
*/
|
|
9531
|
+
this.groups$ = inject(ScFrequentlyAskedQuestionsService).groups$;
|
|
9532
|
+
/**
|
|
9533
|
+
* {@link FormControl} выбранной группы.
|
|
9534
|
+
*/
|
|
9535
|
+
this.groupControl = new FormControl(null);
|
|
9536
|
+
/**
|
|
9537
|
+
* {@link InputSignal} идентификатора выбранной группы.
|
|
9538
|
+
*/
|
|
9539
|
+
this.selectedGroupId = input(null, ...(ngDevMode ? [{ debugName: "selectedGroupId" }] : /* istanbul ignore next */ []));
|
|
9540
|
+
/**
|
|
9541
|
+
* Формат отображения. 'list' - в виде списка, 'select' в виде выпадающего списка.
|
|
9542
|
+
*/
|
|
9543
|
+
this.viewMode = input('list', ...(ngDevMode ? [{ debugName: "viewMode" }] : /* istanbul ignore next */ []));
|
|
9544
|
+
/**
|
|
9545
|
+
* Возвращает query-параметры ссылки на группу вопросов.
|
|
9546
|
+
*/
|
|
9547
|
+
this.getGroupQueryParams = scGetFaqGroupQueryParams;
|
|
9548
|
+
// Синхронизирует значение выпадающего списка с выбранной группой.
|
|
9549
|
+
combineLatest([this.groups$, toObservable(this.selectedGroupId)])
|
|
9550
|
+
.pipe(takeUntilDestroyed())
|
|
9551
|
+
.subscribe(([groups, selectedGroupId]) => {
|
|
9552
|
+
this.groupControl.setValue(groups.find((group) => (group.id ?? null) === selectedGroupId) ?? null, { emitEvent: false });
|
|
9553
|
+
});
|
|
9554
|
+
// Выбор группы в выпадающем списке переводит на адрес этой группы.
|
|
9555
|
+
this.groupControl.valueChanges.pipe(filter(tuiIsPresent), takeUntilDestroyed()).subscribe((group) => {
|
|
9556
|
+
this.router
|
|
9557
|
+
.navigate([], {
|
|
9558
|
+
relativeTo: this.route,
|
|
9559
|
+
queryParams: this.getGroupQueryParams(group),
|
|
9560
|
+
queryParamsHandling: 'merge',
|
|
9561
|
+
})
|
|
9562
|
+
.catch(noop$1);
|
|
9563
|
+
});
|
|
9564
|
+
}
|
|
9565
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScFrequentlyAskedQuestionsGroupSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9039
9566
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScFrequentlyAskedQuestionsGroupSelectorComponent, isStandalone: true, selector: "sc-frequently-asked-questions-group-selector", inputs: { selectedGroupId: { classPropertyName: "selectedGroupId", publicName: "selectedGroupId", isSignal: true, isRequired: false, transformFunction: null }, viewMode: { classPropertyName: "viewMode", publicName: "viewMode", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
9040
9567
|
tuiItemsHandlersProvider({
|
|
9041
9568
|
stringify: signal((item) => item.name),
|
|
@@ -9219,7 +9746,9 @@ class ScFrequentlyAskedQuestionsWithGroupsComponent {
|
|
|
9219
9746
|
.pipe(startWith(null))), tap((data) => {
|
|
9220
9747
|
if (data) {
|
|
9221
9748
|
const pageTitle = 'Часто задаваемые вопросы - FAQ';
|
|
9222
|
-
|
|
9749
|
+
// Якорь вопроса не входит в адрес страницы.
|
|
9750
|
+
const pagePath = this.router.url.split('#')[0];
|
|
9751
|
+
this.seoService.setByDefault(pageTitle, undefined, this.schemaOrgFactory.generateForFaqPage(data.data, pagePath, pageTitle));
|
|
9223
9752
|
}
|
|
9224
9753
|
}), shareReplay({ refCount: true, bufferSize: 1 }));
|
|
9225
9754
|
/**
|
|
@@ -9250,7 +9779,7 @@ class ScFrequentlyAskedQuestionsWithGroupsComponent {
|
|
|
9250
9779
|
this.pageQueryParam = SC_PAGE_QUERY_PARAM;
|
|
9251
9780
|
}
|
|
9252
9781
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScFrequentlyAskedQuestionsWithGroupsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9253
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScFrequentlyAskedQuestionsWithGroupsComponent, isStandalone: true, selector: "sc-frequently-asked-questions-with-groups", outputs: { clickSendQuestion: "clickSendQuestion" }, host: { attributes: { "ngSkipHydration": "true" } }, ngImport: i0, template: "@let items = data$ | async;\n@let pageCount = pageCount$ | async;\n@let viewMode = viewMode$ | async;\n\n@if (viewMode) {\n <div\n class=\"flex gap-6\"\n [class.flex-col]=\"viewMode === 'select'\"\n >\n <div class=\"flex flex-col gap-7\">\n <sc-frequently-asked-questions-group-selector\n [selectedGroupId]=\"groupId$ | async\"\n [viewMode]=\"viewMode\"\n class=\"shrink-0\"\n [class.w-64]=\"viewMode !== 'select'\"\n />\n @if (viewMode === 'list') {\n <button\n tuiButton\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.circle-help\"\n appearance=\"secondary\"\n (click)=\"clickSendQuestion.emit()\"\n class=\"self-center\"\n >\n \u0417\u0430\u0434\u0430\u0442\u044C \u0432\u043E\u043F\u0440\u043E\u0441\n </button>\n }\n </div>\n <div class=\"grow\">\n @if (items && items.length) {\n <sc-frequently-asked-questions\n [items]=\"items\"\n [showLoading]=\"isLoading()\"\n />\n @if (pageCount && pageCount > 1) {\n <sc-pagination-links\n [length]=\"pageCount\"\n [index]=\"(currentPage$ | async) ?? 1\"\n [queryParam]=\"pageQueryParam\"\n class=\"mt-4\"\n />\n }\n } @else {\n <p class=\"text-body-s-bold\">\u0421\u043F\u0438\u0441\u043E\u043A \u0432\u043E\u043F\u0440\u043E\u0441\u043E\u0432 \u043F\u0443\u0441\u0442</p>\n }\n </div>\n </div>\n}\n", dependencies: [{ kind: "component", type: ScFrequentlyAskedQuestionsGroupSelectorComponent, selector: "sc-frequently-asked-questions-group-selector", inputs: ["selectedGroupId", "viewMode"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: ScFrequentlyAskedQuestionsComponent, selector: "sc-frequently-asked-questions", inputs: ["items", "showLoading"] }, { kind: "component", type: ScPaginationLinksComponent, selector: "sc-pagination-links", inputs: ["length", "index", "queryParam", "activePadding", "sidePadding"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9782
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScFrequentlyAskedQuestionsWithGroupsComponent, isStandalone: true, selector: "sc-frequently-asked-questions-with-groups", outputs: { clickSendQuestion: "clickSendQuestion" }, host: { attributes: { "ngSkipHydration": "true" } }, ngImport: i0, template: "@let items = data$ | async;\n@let pageCount = pageCount$ | async;\n@let viewMode = viewMode$ | async;\n\n@if (viewMode) {\n <div\n class=\"flex gap-6\"\n [class.flex-col]=\"viewMode === 'select'\"\n >\n <div class=\"flex flex-col gap-7\">\n <sc-frequently-asked-questions-group-selector\n [selectedGroupId]=\"groupId$ | async\"\n [viewMode]=\"viewMode\"\n class=\"shrink-0\"\n [class.w-64]=\"viewMode !== 'select'\"\n />\n @if (viewMode === 'list') {\n <button\n tuiButton\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.circle-help\"\n appearance=\"secondary\"\n (click)=\"clickSendQuestion.emit()\"\n class=\"self-center\"\n >\n \u0417\u0430\u0434\u0430\u0442\u044C \u0432\u043E\u043F\u0440\u043E\u0441\n </button>\n }\n </div>\n <div class=\"grow\">\n @if (items && items.length) {\n <sc-frequently-asked-questions\n [items]=\"items\"\n [showLoading]=\"isLoading()\"\n />\n @if (pageCount && pageCount > 1) {\n <sc-pagination-links\n [length]=\"pageCount\"\n [index]=\"(currentPage$ | async) ?? 1\"\n [queryParam]=\"pageQueryParam\"\n class=\"mt-4\"\n />\n }\n } @else {\n <p class=\"text-body-s-bold\">\u0421\u043F\u0438\u0441\u043E\u043A \u0432\u043E\u043F\u0440\u043E\u0441\u043E\u0432 \u043F\u0443\u0441\u0442</p>\n }\n </div>\n </div>\n}\n", dependencies: [{ kind: "component", type: ScFrequentlyAskedQuestionsGroupSelectorComponent, selector: "sc-frequently-asked-questions-group-selector", inputs: ["selectedGroupId", "viewMode"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: ScFrequentlyAskedQuestionsComponent, selector: "sc-frequently-asked-questions", inputs: ["items", "showLoading", "scrollOptions", "scrollHoldFrames"] }, { kind: "component", type: ScPaginationLinksComponent, selector: "sc-pagination-links", inputs: ["length", "index", "queryParam", "activePadding", "sidePadding"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9254
9783
|
}
|
|
9255
9784
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScFrequentlyAskedQuestionsWithGroupsComponent, decorators: [{
|
|
9256
9785
|
type: Component,
|
|
@@ -9538,6 +10067,255 @@ const scGetCurrentRoute = (route) => {
|
|
|
9538
10067
|
return currentRoute;
|
|
9539
10068
|
};
|
|
9540
10069
|
|
|
10070
|
+
/**
|
|
10071
|
+
* Токен времени ожидания загрузки скрипта Yandex SmartCaptcha в миллисекундах.
|
|
10072
|
+
*/
|
|
10073
|
+
const SC_SMART_CAPTCHA_LOAD_TIMEOUT = new InjectionToken('SC_SMART_CAPTCHA_LOAD_TIMEOUT', {
|
|
10074
|
+
factory: () => 20_000,
|
|
10075
|
+
});
|
|
10076
|
+
|
|
10077
|
+
/**
|
|
10078
|
+
* Сервис загрузки скрипта Yandex SmartCaptcha.
|
|
10079
|
+
*/
|
|
10080
|
+
class ScSmartCaptchaLoaderService {
|
|
10081
|
+
constructor() {
|
|
10082
|
+
/**
|
|
10083
|
+
* Сервис для вставки внешних скриптов.
|
|
10084
|
+
*/
|
|
10085
|
+
this.scriptsService = inject(ScScriptsService);
|
|
10086
|
+
/**
|
|
10087
|
+
* Окно браузера с API Yandex SmartCaptcha.
|
|
10088
|
+
*/
|
|
10089
|
+
this.window = inject(WA_WINDOW);
|
|
10090
|
+
/**
|
|
10091
|
+
* Признак того, что приложение запущено в браузере.
|
|
10092
|
+
*/
|
|
10093
|
+
this.isBrowser = inject(IS_BROWSER);
|
|
10094
|
+
/**
|
|
10095
|
+
* Время ожидания загрузки скрипта в миллисекундах.
|
|
10096
|
+
*/
|
|
10097
|
+
this.loadTimeout = inject(SC_SMART_CAPTCHA_LOAD_TIMEOUT);
|
|
10098
|
+
/**
|
|
10099
|
+
* Имя функции окна, которую скрипт вызывает после загрузки.
|
|
10100
|
+
*/
|
|
10101
|
+
this.onloadCallbackName = 'scSmartCaptchaOnload';
|
|
10102
|
+
/**
|
|
10103
|
+
* Адрес скрипта.
|
|
10104
|
+
*/
|
|
10105
|
+
this.scriptUrl = `https://smartcaptcha.cloud.yandex.ru/captcha.js?render=onload&onload=${this.onloadCallbackName}`;
|
|
10106
|
+
/**
|
|
10107
|
+
* Загрузка API, общая для всех виджетов. Скрипт загружается один раз; отписка и истечение ожидания у подписчика загрузку не прерывают, после ошибки следующая подписка загружает скрипт заново.
|
|
10108
|
+
*/
|
|
10109
|
+
this.loading$ = defer(() => this.load$()).pipe(shareReplay(1));
|
|
10110
|
+
/**
|
|
10111
|
+
* {@link Observable} API Yandex SmartCaptcha. Значения и ошибки приходят вне зоны Angular, ожидание первого значения ограничено {@link SC_SMART_CAPTCHA_LOAD_TIMEOUT}.
|
|
10112
|
+
*/
|
|
10113
|
+
this.api$ = this.loading$.pipe(timeout({ first: this.loadTimeout }), tuiZonefree());
|
|
10114
|
+
}
|
|
10115
|
+
/**
|
|
10116
|
+
* Возвращает API Yandex SmartCaptcha, при необходимости загружая скрипт. На сервере ничего не возвращает.
|
|
10117
|
+
*/
|
|
10118
|
+
load$() {
|
|
10119
|
+
if (!this.isBrowser) {
|
|
10120
|
+
return EMPTY;
|
|
10121
|
+
}
|
|
10122
|
+
if (this.window.smartCaptcha) {
|
|
10123
|
+
return of(this.window.smartCaptcha);
|
|
10124
|
+
}
|
|
10125
|
+
return merge(this.onload$(), this.scriptsService.loadScript$(this.scriptUrl).pipe(ignoreElements()));
|
|
10126
|
+
}
|
|
10127
|
+
/**
|
|
10128
|
+
* Ждёт вызова функции из параметра `onload` адреса скрипта и возвращает API, которое скрипт к этому моменту создал.
|
|
10129
|
+
*/
|
|
10130
|
+
onload$() {
|
|
10131
|
+
return new Observable((subscriber) => {
|
|
10132
|
+
this.window[this.onloadCallbackName] = () => {
|
|
10133
|
+
if (this.window.smartCaptcha) {
|
|
10134
|
+
subscriber.next(this.window.smartCaptcha);
|
|
10135
|
+
subscriber.complete();
|
|
10136
|
+
}
|
|
10137
|
+
else {
|
|
10138
|
+
subscriber.error(new Error('Yandex SmartCaptcha API is unavailable'));
|
|
10139
|
+
}
|
|
10140
|
+
};
|
|
10141
|
+
return () => {
|
|
10142
|
+
this.window[this.onloadCallbackName] = undefined;
|
|
10143
|
+
};
|
|
10144
|
+
});
|
|
10145
|
+
}
|
|
10146
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScSmartCaptchaLoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
10147
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScSmartCaptchaLoaderService, providedIn: 'root' }); }
|
|
10148
|
+
}
|
|
10149
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScSmartCaptchaLoaderService, decorators: [{
|
|
10150
|
+
type: Injectable,
|
|
10151
|
+
args: [{
|
|
10152
|
+
providedIn: 'root',
|
|
10153
|
+
}]
|
|
10154
|
+
}] });
|
|
10155
|
+
|
|
10156
|
+
/**
|
|
10157
|
+
* Токен настроек Yandex SmartCaptcha. Задаётся приложением.
|
|
10158
|
+
*/
|
|
10159
|
+
const SC_SMART_CAPTCHA_SETTINGS = new InjectionToken('SC_SMART_CAPTCHA_SETTINGS');
|
|
10160
|
+
|
|
10161
|
+
/* eslint-disable no-use-before-define */
|
|
10162
|
+
/**
|
|
10163
|
+
* Виджет Yandex SmartCaptcha. Значение поля ввода - токен прохождения проверки, `null` пока проверка не пройдена или токен истёк.
|
|
10164
|
+
*/
|
|
10165
|
+
class ScSmartCaptchaComponent {
|
|
10166
|
+
/**
|
|
10167
|
+
* Инициализирует экземпляр класса {@link ScSmartCaptchaComponent}.
|
|
10168
|
+
*/
|
|
10169
|
+
constructor() {
|
|
10170
|
+
/**
|
|
10171
|
+
* Контейнер, в котором отрисовывается виджет.
|
|
10172
|
+
*/
|
|
10173
|
+
this.container = viewChild.required('container');
|
|
10174
|
+
/**
|
|
10175
|
+
* Настройки Yandex SmartCaptcha.
|
|
10176
|
+
*/
|
|
10177
|
+
this.settings = inject(SC_SMART_CAPTCHA_SETTINGS);
|
|
10178
|
+
/**
|
|
10179
|
+
* Сервис загрузки скрипта Yandex SmartCaptcha.
|
|
10180
|
+
*/
|
|
10181
|
+
this.loader = inject(ScSmartCaptchaLoaderService);
|
|
10182
|
+
/**
|
|
10183
|
+
* {@link NgZone} для отрисовки виджета вне зоны Angular и возврата его событий в зону.
|
|
10184
|
+
*/
|
|
10185
|
+
this.ngZone = inject(NgZone);
|
|
10186
|
+
/**
|
|
10187
|
+
* Ссылка для автоматического управления уничтожением зависимостей.
|
|
10188
|
+
*/
|
|
10189
|
+
this.destroyRef = inject(DestroyRef);
|
|
10190
|
+
/**
|
|
10191
|
+
* Признак того, что капчу не удалось загрузить.
|
|
10192
|
+
*/
|
|
10193
|
+
this.hasError = signal(false, ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
10194
|
+
/**
|
|
10195
|
+
* Функции отписки от событий виджета.
|
|
10196
|
+
*/
|
|
10197
|
+
this.unsubscribers = [];
|
|
10198
|
+
/**
|
|
10199
|
+
* Обработчик изменения значения поля ввода.
|
|
10200
|
+
*/
|
|
10201
|
+
this.onChange = noop$1;
|
|
10202
|
+
/**
|
|
10203
|
+
* Обработчик касания поля ввода.
|
|
10204
|
+
*/
|
|
10205
|
+
this.onTouched = noop$1;
|
|
10206
|
+
afterNextRender(() => {
|
|
10207
|
+
this.load();
|
|
10208
|
+
});
|
|
10209
|
+
this.destroyRef.onDestroy(() => {
|
|
10210
|
+
this.destroyWidget();
|
|
10211
|
+
});
|
|
10212
|
+
}
|
|
10213
|
+
/** @inheritDoc */
|
|
10214
|
+
writeValue(token) {
|
|
10215
|
+
const { api, widgetId } = this;
|
|
10216
|
+
if (!token && api && widgetId !== undefined) {
|
|
10217
|
+
this.ngZone.runOutsideAngular(() => {
|
|
10218
|
+
api.reset(widgetId);
|
|
10219
|
+
});
|
|
10220
|
+
}
|
|
10221
|
+
}
|
|
10222
|
+
/** @inheritDoc */
|
|
10223
|
+
registerOnChange(onChange) {
|
|
10224
|
+
this.onChange = onChange;
|
|
10225
|
+
}
|
|
10226
|
+
/** @inheritDoc */
|
|
10227
|
+
registerOnTouched(onTouched) {
|
|
10228
|
+
this.onTouched = onTouched;
|
|
10229
|
+
}
|
|
10230
|
+
/**
|
|
10231
|
+
* Повторяет загрузку капчи после ошибки.
|
|
10232
|
+
*/
|
|
10233
|
+
retry() {
|
|
10234
|
+
this.hasError.set(false);
|
|
10235
|
+
this.load();
|
|
10236
|
+
}
|
|
10237
|
+
/**
|
|
10238
|
+
* Загружает API Yandex SmartCaptcha и отрисовывает виджет (API приходит вне зоны Angular). При ошибке загрузки или отрисовки показывает сообщение.
|
|
10239
|
+
*/
|
|
10240
|
+
load() {
|
|
10241
|
+
this.loader.api$
|
|
10242
|
+
.pipe(tap((api) => {
|
|
10243
|
+
this.render(api);
|
|
10244
|
+
}), takeUntilDestroyed(this.destroyRef))
|
|
10245
|
+
.subscribe({
|
|
10246
|
+
error: () => {
|
|
10247
|
+
this.showError();
|
|
10248
|
+
},
|
|
10249
|
+
});
|
|
10250
|
+
}
|
|
10251
|
+
/**
|
|
10252
|
+
* Отрисовывает виджет и подписывается на его события.
|
|
10253
|
+
*
|
|
10254
|
+
* @param api API Yandex SmartCaptcha.
|
|
10255
|
+
*/
|
|
10256
|
+
render(api) {
|
|
10257
|
+
const widgetId = api.render(this.container().nativeElement, { sitekey: this.settings.sitekey, hl: this.settings.language });
|
|
10258
|
+
this.api = api;
|
|
10259
|
+
this.widgetId = widgetId;
|
|
10260
|
+
this.unsubscribers = [
|
|
10261
|
+
api.subscribe(widgetId, 'success', (token) => {
|
|
10262
|
+
this.updateValue(isString(token) ? token : null);
|
|
10263
|
+
}),
|
|
10264
|
+
api.subscribe(widgetId, 'token-expired', () => {
|
|
10265
|
+
this.updateValue(null);
|
|
10266
|
+
api.reset(widgetId);
|
|
10267
|
+
}),
|
|
10268
|
+
api.subscribe(widgetId, 'javascript-error', () => {
|
|
10269
|
+
this.showError();
|
|
10270
|
+
}),
|
|
10271
|
+
];
|
|
10272
|
+
}
|
|
10273
|
+
/**
|
|
10274
|
+
* Передаёт форме новое значение токена.
|
|
10275
|
+
*
|
|
10276
|
+
* @param token Токен прохождения проверки.
|
|
10277
|
+
*/
|
|
10278
|
+
updateValue(token) {
|
|
10279
|
+
this.ngZone.run(() => {
|
|
10280
|
+
this.onChange(token);
|
|
10281
|
+
this.onTouched();
|
|
10282
|
+
});
|
|
10283
|
+
}
|
|
10284
|
+
/**
|
|
10285
|
+
* Удаляет виджет, очищает токен и показывает сообщение об ошибке.
|
|
10286
|
+
*/
|
|
10287
|
+
showError() {
|
|
10288
|
+
this.destroyWidget();
|
|
10289
|
+
this.ngZone.run(() => {
|
|
10290
|
+
this.hasError.set(true);
|
|
10291
|
+
this.onChange(null);
|
|
10292
|
+
});
|
|
10293
|
+
}
|
|
10294
|
+
/**
|
|
10295
|
+
* Удаляет виджет вместе с созданными им элементами и обработчиками.
|
|
10296
|
+
*/
|
|
10297
|
+
destroyWidget() {
|
|
10298
|
+
this.unsubscribers.forEach((unsubscribe) => {
|
|
10299
|
+
unsubscribe();
|
|
10300
|
+
});
|
|
10301
|
+
this.unsubscribers = [];
|
|
10302
|
+
const { api, widgetId } = this;
|
|
10303
|
+
if (api && widgetId !== undefined) {
|
|
10304
|
+
this.ngZone.runOutsideAngular(() => {
|
|
10305
|
+
api.destroy(widgetId);
|
|
10306
|
+
});
|
|
10307
|
+
}
|
|
10308
|
+
this.api = undefined;
|
|
10309
|
+
this.widgetId = undefined;
|
|
10310
|
+
}
|
|
10311
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScSmartCaptchaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
10312
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScSmartCaptchaComponent, isStandalone: true, selector: "sc-smart-captcha", providers: [tuiProvide(NG_VALUE_ACCESSOR, ScSmartCaptchaComponent, true)], viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #container\n class=\"min-h-[7.375rem]\"\n [class.hidden]=\"hasError()\"\n></div>\n@if (hasError()) {\n <p\n role=\"alert\"\n class=\"text-body-s text-tui-text-negative\"\n >\n \u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0443 \u00AB\u042F \u043D\u0435 \u0440\u043E\u0431\u043E\u0442\u00BB.\n <button\n tuiLink\n type=\"button\"\n (click)=\"retry()\"\n >\n \u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C\n </button>\n </p>\n}\n", dependencies: [{ kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
10313
|
+
}
|
|
10314
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScSmartCaptchaComponent, decorators: [{
|
|
10315
|
+
type: Component,
|
|
10316
|
+
args: [{ standalone: true, selector: 'sc-smart-captcha', imports: [TuiLink], providers: [tuiProvide(NG_VALUE_ACCESSOR, ScSmartCaptchaComponent, true)], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n #container\n class=\"min-h-[7.375rem]\"\n [class.hidden]=\"hasError()\"\n></div>\n@if (hasError()) {\n <p\n role=\"alert\"\n class=\"text-body-s text-tui-text-negative\"\n >\n \u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0443 \u00AB\u042F \u043D\u0435 \u0440\u043E\u0431\u043E\u0442\u00BB.\n <button\n tuiLink\n type=\"button\"\n (click)=\"retry()\"\n >\n \u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C\n </button>\n </p>\n}\n" }]
|
|
10317
|
+
}], ctorParameters: () => [], propDecorators: { container: [{ type: i0.ViewChild, args: ['container', { isSignal: true }] }] } });
|
|
10318
|
+
|
|
9541
10319
|
/**
|
|
9542
10320
|
* Компонент формы обратной связи.
|
|
9543
10321
|
*/
|
|
@@ -9609,7 +10387,7 @@ class ScFeedbackFormComponent {
|
|
|
9609
10387
|
}
|
|
9610
10388
|
}));
|
|
9611
10389
|
/**
|
|
9612
|
-
* Поле ввода
|
|
10390
|
+
* Поле ввода токена капчи, имя `recaptcha` задано API.
|
|
9613
10391
|
*/
|
|
9614
10392
|
this.recaptchaControl = new FormControl(null, Validators.required);
|
|
9615
10393
|
/**
|
|
@@ -9651,8 +10429,10 @@ class ScFeedbackFormComponent {
|
|
|
9651
10429
|
}),
|
|
9652
10430
|
// eslint-disable-next-line rxjs/no-implicit-any-catch
|
|
9653
10431
|
catchError((error) => {
|
|
10432
|
+
// Токен капчи одноразовый: для повторной отправки нужна новая проверка.
|
|
10433
|
+
this.recaptchaControl.reset();
|
|
9654
10434
|
this.form.markAllAsTouched();
|
|
9655
|
-
const { errors, message } = error.error;
|
|
10435
|
+
const { errors, message } = (error.error ?? {});
|
|
9656
10436
|
if (errors) {
|
|
9657
10437
|
Object.keys(errors).forEach((key) => {
|
|
9658
10438
|
const control = this.form.get(key);
|
|
@@ -9689,16 +10469,6 @@ class ScFeedbackFormComponent {
|
|
|
9689
10469
|
* Список стран.
|
|
9690
10470
|
*/
|
|
9691
10471
|
this.countries = getCountries();
|
|
9692
|
-
/**
|
|
9693
|
-
* Это решение ошибки #4940, было @see [предложено](https://github.com/DethAriel/ng-recaptcha/issues/123#issuecomment-426112101) автором {@link RecaptchaComponent}.
|
|
9694
|
-
*/
|
|
9695
|
-
RecaptchaComponent.prototype.ngOnDestroy = function () {
|
|
9696
|
-
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
9697
|
-
if (this['subscription']) {
|
|
9698
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/dot-notation
|
|
9699
|
-
this['subscription'].unsubscribe();
|
|
9700
|
-
}
|
|
9701
|
-
};
|
|
9702
10472
|
merge(this.accepted$, this.user$, this.loadedFile.valueChanges.pipe(tap((files) => {
|
|
9703
10473
|
this.form.controls.files.reset([]);
|
|
9704
10474
|
this.onUploadFile(files);
|
|
@@ -9822,7 +10592,7 @@ class ScFeedbackFormComponent {
|
|
|
9822
10592
|
return ScPhoneService.isValidPhoneNumberForMessenger(value);
|
|
9823
10593
|
}
|
|
9824
10594
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScFeedbackFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9825
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScFeedbackFormComponent, isStandalone: true, selector: "sc-feedback-form", inputs: { slugInput: { classPropertyName: "slugInput", publicName: "slug", isSignal: true, isRequired: false, transformFunction: null }, fieldsInput: { classPropertyName: "fieldsInput", publicName: "fields", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clickOffer: "clickOffer", sendSuccess: "sendSuccess" }, ngImport: i0, template: "@let fieldsList = fields();\n@if (fieldsList.length > 0) {\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit.next()\"\n class=\"flex flex-col justify-between gap-4\"\n >\n <!-- \u0424\u0418\u041E -->\n @if (fieldsList.includes('name')) {\n <label tuiLabel>\n \u0424\u0418\u041E\n <tui-textfield>\n <input\n tuiInput\n formControlName=\"name\"\n placeholder=\"\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0412\u0430\u0448\u0438 \u0424.\u0418.\u041E.\"\n />\n </tui-textfield>\n <tui-error formControlName=\"name\" />\n </label>\n }\n <!-- \u0422\u0435\u043B\u0435\u0444\u043E\u043D -->\n @if (fieldsList.includes('phone')) {\n <label tuiLabel>\n \u0422\u0435\u043B\u0435\u0444\u043E\u043D\n <tui-textfield>\n <input\n formControlName=\"phone\"\n tuiInputPhoneInternational\n [countrySearch]=\"true\"\n [countries]=\"(countries | tuiSortCountries) || []\"\n autocomplete=\"phone\"\n placeholder=\"\u0422\u0435\u043B\u0435\u0444\u043E\u043D\"\n />\n </tui-textfield>\n <tui-error formControlName=\"phone\" />\n </label>\n @if (fieldsList.includes('isShouldUseMessenger') && form.controls.phone.value && isValidPhoneNumberForMessenger(form.controls.phone.value)) {\n <label tuiLabel>\n <input\n formControlName=\"isShouldUseMessenger\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span tuiTitle> \u041D\u0430\u043F\u0438\u0441\u0430\u0442\u044C \u0432 \u043C\u0435\u0441\u0441\u0435\u043D\u0434\u0436\u0435\u0440\u0430\u0445, \u0430 \u043D\u0435 \u0437\u0432\u043E\u043D\u0438\u0442\u044C </span>\n </label>\n }\n }\n <!-- \u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B -->\n @if (fieldsList.includes('email')) {\n <label tuiLabel>\n \u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B\n <tui-textfield>\n <input\n tuiInput\n formControlName=\"email\"\n placeholder=\"\u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B\"\n />\n <sc-suggestion-field\n *tuiDropdown\n [type]=\"suggestionType.email\"\n />\n </tui-textfield>\n <tui-error formControlName=\"email\" />\n </label>\n }\n <!-- \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 -->\n @if (fieldsList.includes('message')) {\n <label tuiLabel>\n \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439\n <tui-textfield>\n <textarea\n tuiTextarea\n formControlName=\"message\"\n [min]=\"3\"\n [max]=\"6\"\n placeholder=\"\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439\"\n ></textarea>\n </tui-textfield>\n <tui-error formControlName=\"message\" />\n </label>\n }\n <!-- \u0424\u0430\u0439\u043B\u044B -->\n @if (fieldsList.includes('files')) {\n <div class=\"flex flex-col gap-1\">\n <label\n tuiInputFiles\n class=\"self-start !min-h-0 !p-0\"\n >\n <input\n #validator=\"tuiInputFilesValidator\"\n accept=\".doc,.docx,.pdf,image/*\"\n tuiInputFiles\n [formControl]=\"loadedFile\"\n [multiple]=\"true\"\n (reject)=\"onReject($event)\"\n class=\"opacity-0\"\n />\n <ng-template>\n <button\n tuiButton\n type=\"button\"\n tabindex=\"-1\"\n appearance=\"secondary\"\n size=\"m\"\n iconStart=\"@tui.paperclip\"\n >\n \u041F\u0440\u0438\u043A\u0440\u0435\u043F\u0438\u0442\u044C \u0444\u0430\u0439\u043B\n </button>\n </ng-template>\n </label>\n @if (loadedFile.invalid) {\n <tui-error\n [order]=\"['maxLength']\"\n [formControl]=\"loadedFile\"\n />\n }\n @let accepted = accepted$ | async;\n @if (accepted?.length || rejected.length) {\n <tui-files class=\"tui-space_top-1\">\n @for (file of accepted; track file) {\n <tui-file\n [file]=\"file\"\n (remove)=\"onRemove(file)\"\n />\n }\n @for (file of rejected; track file) {\n <tui-file\n state=\"error\"\n [file]=\"(file | tuiFileRejected: validator | async) || file\"\n (remove)=\"onRemove(file)\"\n />\n }\n </tui-files>\n }\n </div>\n }\n <!-- recaptcha -->\n @if (form.get('recaptcha')) {\n <div\n class=\"mb-3 max-h-20 overflow-hidden duration-500\"\n [ngClass]=\"{ '!max-h-0 !-m-2': form.get('recaptcha')?.valid }\"\n >\n <re-captcha formControlName=\"recaptcha\" />\n </div>\n }\n <!-- \u042D\u043B\u0435\u043C\u0435\u043D\u0442\u044B \u0443\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u044F -->\n <div class=\"flex flex-wrap items-center gap-3\">\n <button\n tuiButton\n [disabled]=\"form.invalid\"\n [loading]=\"!!(loading$ | async)\"\n type=\"submit\"\n iconStart=\"@tui.sc.send\"\n class=\"self-center\"\n >\n \u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C\n </button>\n <div class=\"grow basis-60 text-body-s\">\n \u041D\u0430\u0436\u0438\u043C\u0430\u044F \u043D\u0430 \u043A\u043D\u043E\u043F\u043A\u0443, \u0432\u044B \u0441\u043E\u0433\u043B\u0430\u0448\u0430\u0435\u0442\u0435\u0441\u044C \u0441\n <button\n tuiLink\n [style.text-decoration-line]=\"'underline'\"\n type=\"button\"\n (click)=\"context?.data?.onClickOfferHandler(); clickOffer.emit()\"\n >\n \u041F\u043E\u043B\u0438\u0442\u0438\u043A\u043E\u0439 \u043A\u043E\u043D\u0444\u0438\u0434\u0435\u043D\u0446\u0438\u0430\u043B\u044C\u043D\u043E\u0441\u0442\u0438\n </button>\n </div>\n </div>\n </form>\n}\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: i2.TuiErrorComponent, selector: "tui-error", inputs: ["error"] }, { kind: "directive", type: i2.TuiErrorDirective, selector: "tui-error[ngModel], tui-error[formControlName], tui-error[formControl], tui-error[formGroup], tui-error[formGroupName], tui-error[formArrayName], tui-error[formArray]", inputs: ["order"] }, { kind: "component", type: ScSuggestionFieldComponent, selector: "sc-suggestion-field", inputs: ["type"], outputs: ["selectedClick"] }, { kind: "directive", type: i2$3.TuiLabel, selector: "label[tuiLabel]" }, { kind: "component", type: i3$1.TuiTextfieldComponent, selector: "tui-textfield:not([multi])", inputs: ["content", "filler"] }, { kind: "directive", type: i3.TuiDropdownContent, selector: "ng-template[tuiDropdown]" }, { kind: "directive", type: i2.TuiInputDirective, selector: "input[tuiInput]", inputs: ["readOnly", "invalid", "focused", "state"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "ngmodule", type: RecaptchaFormsModule }, { kind: "directive", type: i6$2.RecaptchaValueAccessorDirective, selector: "re-captcha[formControlName],re-captcha[formControl],re-captcha[ngModel]" }, { kind: "ngmodule", type: RecaptchaModule }, { kind: "component", type: i6$2.RecaptchaComponent, selector: "re-captcha", inputs: ["id", "siteKey", "theme", "type", "size", "tabIndex", "badge", "errorMode"], outputs: ["resolved", "error", "errored"], exportAs: ["reCaptcha"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]" }, { kind: "component", type: i1$1.TuiTextareaComponent, selector: "textarea[tuiTextarea]", inputs: ["min", "max", "content"] }, { kind: "component", type: TuiCheckbox, selector: "input[type=\"checkbox\"][tuiCheckbox]" }, { kind: "directive", type: TuiTitle, selector: "[tuiTitle]", inputs: ["tuiTitle"] }, { kind: "component", type: i1$1.TuiFile, selector: "tui-file,a[tuiFile],button[tuiFile]", inputs: ["file", "state", "size", "showDelete", "showSize", "leftContent"], outputs: ["remove"] }, { kind: "component", type: i1$1.TuiInputFiles, selector: "label[tuiInputFiles]", inputs: ["tuiInputFiles"] }, { kind: "component", type: i1$1.TuiFilesComponent, selector: "tui-files", inputs: ["max", "expanded"], outputs: ["expandedChange"] }, { kind: "directive", type: i1$1.TuiInputFilesDirective, selector: "input[tuiInputFiles]", outputs: ["reject"] }, { kind: "component", type: i1$1.TuiInputPhoneInternationalComponent, selector: "input[tuiInputPhoneInternational]", inputs: ["countrySearch", "countryIsoCode", "countries"], outputs: ["countryIsoCodeChange"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TuiFileRejectedPipe, name: "tuiFileRejected" }, { kind: "pipe", type: TuiSortCountriesPipe, name: "tuiSortCountries" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
10595
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ScFeedbackFormComponent, isStandalone: true, selector: "sc-feedback-form", inputs: { slugInput: { classPropertyName: "slugInput", publicName: "slug", isSignal: true, isRequired: false, transformFunction: null }, fieldsInput: { classPropertyName: "fieldsInput", publicName: "fields", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clickOffer: "clickOffer", sendSuccess: "sendSuccess" }, ngImport: i0, template: "@let fieldsList = fields();\n@if (fieldsList.length > 0) {\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit.next()\"\n class=\"flex flex-col justify-between gap-4\"\n >\n <!-- \u0424\u0418\u041E -->\n @if (fieldsList.includes('name')) {\n <label tuiLabel>\n \u0424\u0418\u041E\n <tui-textfield>\n <input\n tuiInput\n formControlName=\"name\"\n placeholder=\"\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0412\u0430\u0448\u0438 \u0424.\u0418.\u041E.\"\n />\n </tui-textfield>\n <tui-error formControlName=\"name\" />\n </label>\n }\n <!-- \u0422\u0435\u043B\u0435\u0444\u043E\u043D -->\n @if (fieldsList.includes('phone')) {\n <label tuiLabel>\n \u0422\u0435\u043B\u0435\u0444\u043E\u043D\n <tui-textfield>\n <input\n formControlName=\"phone\"\n tuiInputPhoneInternational\n [countrySearch]=\"true\"\n [countries]=\"(countries | tuiSortCountries) || []\"\n autocomplete=\"phone\"\n placeholder=\"\u0422\u0435\u043B\u0435\u0444\u043E\u043D\"\n />\n </tui-textfield>\n <tui-error formControlName=\"phone\" />\n </label>\n @if (fieldsList.includes('isShouldUseMessenger') && form.controls.phone.value && isValidPhoneNumberForMessenger(form.controls.phone.value)) {\n <label tuiLabel>\n <input\n formControlName=\"isShouldUseMessenger\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span tuiTitle> \u041D\u0430\u043F\u0438\u0441\u0430\u0442\u044C \u0432 \u043C\u0435\u0441\u0441\u0435\u043D\u0434\u0436\u0435\u0440\u0430\u0445, \u0430 \u043D\u0435 \u0437\u0432\u043E\u043D\u0438\u0442\u044C </span>\n </label>\n }\n }\n <!-- \u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B -->\n @if (fieldsList.includes('email')) {\n <label tuiLabel>\n \u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B\n <tui-textfield>\n <input\n tuiInput\n formControlName=\"email\"\n placeholder=\"\u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B\"\n />\n <sc-suggestion-field\n *tuiDropdown\n [type]=\"suggestionType.email\"\n />\n </tui-textfield>\n <tui-error formControlName=\"email\" />\n </label>\n }\n <!-- \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 -->\n @if (fieldsList.includes('message')) {\n <label tuiLabel>\n \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439\n <tui-textfield>\n <textarea\n tuiTextarea\n formControlName=\"message\"\n [min]=\"3\"\n [max]=\"6\"\n placeholder=\"\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439\"\n ></textarea>\n </tui-textfield>\n <tui-error formControlName=\"message\" />\n </label>\n }\n <!-- \u0424\u0430\u0439\u043B\u044B -->\n @if (fieldsList.includes('files')) {\n <div class=\"flex flex-col gap-1\">\n <label\n tuiInputFiles\n class=\"self-start !min-h-0 !p-0\"\n >\n <input\n #validator=\"tuiInputFilesValidator\"\n accept=\".doc,.docx,.pdf,image/*\"\n tuiInputFiles\n [formControl]=\"loadedFile\"\n [multiple]=\"true\"\n (reject)=\"onReject($event)\"\n class=\"opacity-0\"\n />\n <ng-template>\n <button\n tuiButton\n type=\"button\"\n tabindex=\"-1\"\n appearance=\"secondary\"\n size=\"m\"\n iconStart=\"@tui.paperclip\"\n >\n \u041F\u0440\u0438\u043A\u0440\u0435\u043F\u0438\u0442\u044C \u0444\u0430\u0439\u043B\n </button>\n </ng-template>\n </label>\n @if (loadedFile.invalid) {\n <tui-error\n [order]=\"['maxLength']\"\n [formControl]=\"loadedFile\"\n />\n }\n @let accepted = accepted$ | async;\n @if (accepted?.length || rejected.length) {\n <tui-files class=\"tui-space_top-1\">\n @for (file of accepted; track file) {\n <tui-file\n [file]=\"file\"\n (remove)=\"onRemove(file)\"\n />\n }\n @for (file of rejected; track file) {\n <tui-file\n state=\"error\"\n [file]=\"(file | tuiFileRejected: validator | async) || file\"\n (remove)=\"onRemove(file)\"\n />\n }\n </tui-files>\n }\n </div>\n }\n <!-- \u041A\u0430\u043F\u0447\u0430 -->\n @if (form.get('recaptcha'); as recaptcha) {\n <div\n class=\"mb-3 max-h-[7.5rem] overflow-hidden duration-500\"\n [ngClass]=\"{ '!max-h-0 !-m-2': recaptcha.valid }\"\n [attr.inert]=\"recaptcha.valid ? '' : null\"\n >\n <sc-smart-captcha formControlName=\"recaptcha\" />\n </div>\n @if (recaptcha.getError('serverResponse'); as serverErrors) {\n <tui-error [error]=\"serverErrors.join(' ')\" />\n }\n }\n <!-- \u042D\u043B\u0435\u043C\u0435\u043D\u0442\u044B \u0443\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u044F -->\n <div class=\"flex flex-wrap items-center gap-3\">\n <button\n tuiButton\n [disabled]=\"form.invalid\"\n [loading]=\"!!(loading$ | async)\"\n type=\"submit\"\n iconStart=\"@tui.sc.send\"\n class=\"self-center\"\n >\n \u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C\n </button>\n <div class=\"grow basis-60 text-body-s\">\n \u041D\u0430\u0436\u0438\u043C\u0430\u044F \u043D\u0430 \u043A\u043D\u043E\u043F\u043A\u0443, \u0432\u044B \u0441\u043E\u0433\u043B\u0430\u0448\u0430\u0435\u0442\u0435\u0441\u044C \u0441\n <button\n tuiLink\n [style.text-decoration-line]=\"'underline'\"\n type=\"button\"\n (click)=\"context?.data?.onClickOfferHandler(); clickOffer.emit()\"\n >\n \u041F\u043E\u043B\u0438\u0442\u0438\u043A\u043E\u0439 \u043A\u043E\u043D\u0444\u0438\u0434\u0435\u043D\u0446\u0438\u0430\u043B\u044C\u043D\u043E\u0441\u0442\u0438\n </button>\n </div>\n </div>\n </form>\n}\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: i2.TuiErrorComponent, selector: "tui-error", inputs: ["error"] }, { kind: "directive", type: i2.TuiErrorDirective, selector: "tui-error[ngModel], tui-error[formControlName], tui-error[formControl], tui-error[formGroup], tui-error[formGroupName], tui-error[formArrayName], tui-error[formArray]", inputs: ["order"] }, { kind: "component", type: ScSuggestionFieldComponent, selector: "sc-suggestion-field", inputs: ["type"], outputs: ["selectedClick"] }, { kind: "directive", type: i2$3.TuiLabel, selector: "label[tuiLabel]" }, { kind: "component", type: i3$1.TuiTextfieldComponent, selector: "tui-textfield:not([multi])", inputs: ["content", "filler"] }, { kind: "directive", type: i3.TuiDropdownContent, selector: "ng-template[tuiDropdown]" }, { kind: "directive", type: i2.TuiInputDirective, selector: "input[tuiInput]", inputs: ["readOnly", "invalid", "focused", "state"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "component", type: ScSmartCaptchaComponent, selector: "sc-smart-captcha" }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]" }, { kind: "component", type: i1$1.TuiTextareaComponent, selector: "textarea[tuiTextarea]", inputs: ["min", "max", "content"] }, { kind: "component", type: TuiCheckbox, selector: "input[type=\"checkbox\"][tuiCheckbox]" }, { kind: "directive", type: TuiTitle, selector: "[tuiTitle]", inputs: ["tuiTitle"] }, { kind: "component", type: i1$1.TuiFile, selector: "tui-file,a[tuiFile],button[tuiFile]", inputs: ["file", "state", "size", "showDelete", "showSize", "leftContent"], outputs: ["remove"] }, { kind: "component", type: i1$1.TuiInputFiles, selector: "label[tuiInputFiles]", inputs: ["tuiInputFiles"] }, { kind: "component", type: i1$1.TuiFilesComponent, selector: "tui-files", inputs: ["max", "expanded"], outputs: ["expandedChange"] }, { kind: "directive", type: i1$1.TuiInputFilesDirective, selector: "input[tuiInputFiles]", outputs: ["reject"] }, { kind: "component", type: i1$1.TuiInputPhoneInternationalComponent, selector: "input[tuiInputPhoneInternational]", inputs: ["countrySearch", "countryIsoCode", "countries"], outputs: ["countryIsoCodeChange"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TuiFileRejectedPipe, name: "tuiFileRejected" }, { kind: "pipe", type: TuiSortCountriesPipe, name: "tuiSortCountries" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9826
10596
|
}
|
|
9827
10597
|
__decorate([
|
|
9828
10598
|
tuiPure
|
|
@@ -9840,8 +10610,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
9840
10610
|
TuiButton,
|
|
9841
10611
|
TuiButtonLoading,
|
|
9842
10612
|
TuiLabel,
|
|
9843
|
-
|
|
9844
|
-
RecaptchaModule,
|
|
10613
|
+
ScSmartCaptchaComponent,
|
|
9845
10614
|
TuiLink,
|
|
9846
10615
|
TuiTextarea,
|
|
9847
10616
|
TuiCheckbox,
|
|
@@ -9850,7 +10619,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
9850
10619
|
TuiInputPhoneInternational,
|
|
9851
10620
|
...TuiInput,
|
|
9852
10621
|
TuiSortCountriesPipe,
|
|
9853
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let fieldsList = fields();\n@if (fieldsList.length > 0) {\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit.next()\"\n class=\"flex flex-col justify-between gap-4\"\n >\n <!-- \u0424\u0418\u041E -->\n @if (fieldsList.includes('name')) {\n <label tuiLabel>\n \u0424\u0418\u041E\n <tui-textfield>\n <input\n tuiInput\n formControlName=\"name\"\n placeholder=\"\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0412\u0430\u0448\u0438 \u0424.\u0418.\u041E.\"\n />\n </tui-textfield>\n <tui-error formControlName=\"name\" />\n </label>\n }\n <!-- \u0422\u0435\u043B\u0435\u0444\u043E\u043D -->\n @if (fieldsList.includes('phone')) {\n <label tuiLabel>\n \u0422\u0435\u043B\u0435\u0444\u043E\u043D\n <tui-textfield>\n <input\n formControlName=\"phone\"\n tuiInputPhoneInternational\n [countrySearch]=\"true\"\n [countries]=\"(countries | tuiSortCountries) || []\"\n autocomplete=\"phone\"\n placeholder=\"\u0422\u0435\u043B\u0435\u0444\u043E\u043D\"\n />\n </tui-textfield>\n <tui-error formControlName=\"phone\" />\n </label>\n @if (fieldsList.includes('isShouldUseMessenger') && form.controls.phone.value && isValidPhoneNumberForMessenger(form.controls.phone.value)) {\n <label tuiLabel>\n <input\n formControlName=\"isShouldUseMessenger\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span tuiTitle> \u041D\u0430\u043F\u0438\u0441\u0430\u0442\u044C \u0432 \u043C\u0435\u0441\u0441\u0435\u043D\u0434\u0436\u0435\u0440\u0430\u0445, \u0430 \u043D\u0435 \u0437\u0432\u043E\u043D\u0438\u0442\u044C </span>\n </label>\n }\n }\n <!-- \u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B -->\n @if (fieldsList.includes('email')) {\n <label tuiLabel>\n \u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B\n <tui-textfield>\n <input\n tuiInput\n formControlName=\"email\"\n placeholder=\"\u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B\"\n />\n <sc-suggestion-field\n *tuiDropdown\n [type]=\"suggestionType.email\"\n />\n </tui-textfield>\n <tui-error formControlName=\"email\" />\n </label>\n }\n <!-- \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 -->\n @if (fieldsList.includes('message')) {\n <label tuiLabel>\n \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439\n <tui-textfield>\n <textarea\n tuiTextarea\n formControlName=\"message\"\n [min]=\"3\"\n [max]=\"6\"\n placeholder=\"\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439\"\n ></textarea>\n </tui-textfield>\n <tui-error formControlName=\"message\" />\n </label>\n }\n <!-- \u0424\u0430\u0439\u043B\u044B -->\n @if (fieldsList.includes('files')) {\n <div class=\"flex flex-col gap-1\">\n <label\n tuiInputFiles\n class=\"self-start !min-h-0 !p-0\"\n >\n <input\n #validator=\"tuiInputFilesValidator\"\n accept=\".doc,.docx,.pdf,image/*\"\n tuiInputFiles\n [formControl]=\"loadedFile\"\n [multiple]=\"true\"\n (reject)=\"onReject($event)\"\n class=\"opacity-0\"\n />\n <ng-template>\n <button\n tuiButton\n type=\"button\"\n tabindex=\"-1\"\n appearance=\"secondary\"\n size=\"m\"\n iconStart=\"@tui.paperclip\"\n >\n \u041F\u0440\u0438\u043A\u0440\u0435\u043F\u0438\u0442\u044C \u0444\u0430\u0439\u043B\n </button>\n </ng-template>\n </label>\n @if (loadedFile.invalid) {\n <tui-error\n [order]=\"['maxLength']\"\n [formControl]=\"loadedFile\"\n />\n }\n @let accepted = accepted$ | async;\n @if (accepted?.length || rejected.length) {\n <tui-files class=\"tui-space_top-1\">\n @for (file of accepted; track file) {\n <tui-file\n [file]=\"file\"\n (remove)=\"onRemove(file)\"\n />\n }\n @for (file of rejected; track file) {\n <tui-file\n state=\"error\"\n [file]=\"(file | tuiFileRejected: validator | async) || file\"\n (remove)=\"onRemove(file)\"\n />\n }\n </tui-files>\n }\n </div>\n }\n <!--
|
|
10622
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let fieldsList = fields();\n@if (fieldsList.length > 0) {\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit.next()\"\n class=\"flex flex-col justify-between gap-4\"\n >\n <!-- \u0424\u0418\u041E -->\n @if (fieldsList.includes('name')) {\n <label tuiLabel>\n \u0424\u0418\u041E\n <tui-textfield>\n <input\n tuiInput\n formControlName=\"name\"\n placeholder=\"\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0412\u0430\u0448\u0438 \u0424.\u0418.\u041E.\"\n />\n </tui-textfield>\n <tui-error formControlName=\"name\" />\n </label>\n }\n <!-- \u0422\u0435\u043B\u0435\u0444\u043E\u043D -->\n @if (fieldsList.includes('phone')) {\n <label tuiLabel>\n \u0422\u0435\u043B\u0435\u0444\u043E\u043D\n <tui-textfield>\n <input\n formControlName=\"phone\"\n tuiInputPhoneInternational\n [countrySearch]=\"true\"\n [countries]=\"(countries | tuiSortCountries) || []\"\n autocomplete=\"phone\"\n placeholder=\"\u0422\u0435\u043B\u0435\u0444\u043E\u043D\"\n />\n </tui-textfield>\n <tui-error formControlName=\"phone\" />\n </label>\n @if (fieldsList.includes('isShouldUseMessenger') && form.controls.phone.value && isValidPhoneNumberForMessenger(form.controls.phone.value)) {\n <label tuiLabel>\n <input\n formControlName=\"isShouldUseMessenger\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span tuiTitle> \u041D\u0430\u043F\u0438\u0441\u0430\u0442\u044C \u0432 \u043C\u0435\u0441\u0441\u0435\u043D\u0434\u0436\u0435\u0440\u0430\u0445, \u0430 \u043D\u0435 \u0437\u0432\u043E\u043D\u0438\u0442\u044C </span>\n </label>\n }\n }\n <!-- \u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B -->\n @if (fieldsList.includes('email')) {\n <label tuiLabel>\n \u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B\n <tui-textfield>\n <input\n tuiInput\n formControlName=\"email\"\n placeholder=\"\u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B\"\n />\n <sc-suggestion-field\n *tuiDropdown\n [type]=\"suggestionType.email\"\n />\n </tui-textfield>\n <tui-error formControlName=\"email\" />\n </label>\n }\n <!-- \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 -->\n @if (fieldsList.includes('message')) {\n <label tuiLabel>\n \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439\n <tui-textfield>\n <textarea\n tuiTextarea\n formControlName=\"message\"\n [min]=\"3\"\n [max]=\"6\"\n placeholder=\"\u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439\"\n ></textarea>\n </tui-textfield>\n <tui-error formControlName=\"message\" />\n </label>\n }\n <!-- \u0424\u0430\u0439\u043B\u044B -->\n @if (fieldsList.includes('files')) {\n <div class=\"flex flex-col gap-1\">\n <label\n tuiInputFiles\n class=\"self-start !min-h-0 !p-0\"\n >\n <input\n #validator=\"tuiInputFilesValidator\"\n accept=\".doc,.docx,.pdf,image/*\"\n tuiInputFiles\n [formControl]=\"loadedFile\"\n [multiple]=\"true\"\n (reject)=\"onReject($event)\"\n class=\"opacity-0\"\n />\n <ng-template>\n <button\n tuiButton\n type=\"button\"\n tabindex=\"-1\"\n appearance=\"secondary\"\n size=\"m\"\n iconStart=\"@tui.paperclip\"\n >\n \u041F\u0440\u0438\u043A\u0440\u0435\u043F\u0438\u0442\u044C \u0444\u0430\u0439\u043B\n </button>\n </ng-template>\n </label>\n @if (loadedFile.invalid) {\n <tui-error\n [order]=\"['maxLength']\"\n [formControl]=\"loadedFile\"\n />\n }\n @let accepted = accepted$ | async;\n @if (accepted?.length || rejected.length) {\n <tui-files class=\"tui-space_top-1\">\n @for (file of accepted; track file) {\n <tui-file\n [file]=\"file\"\n (remove)=\"onRemove(file)\"\n />\n }\n @for (file of rejected; track file) {\n <tui-file\n state=\"error\"\n [file]=\"(file | tuiFileRejected: validator | async) || file\"\n (remove)=\"onRemove(file)\"\n />\n }\n </tui-files>\n }\n </div>\n }\n <!-- \u041A\u0430\u043F\u0447\u0430 -->\n @if (form.get('recaptcha'); as recaptcha) {\n <div\n class=\"mb-3 max-h-[7.5rem] overflow-hidden duration-500\"\n [ngClass]=\"{ '!max-h-0 !-m-2': recaptcha.valid }\"\n [attr.inert]=\"recaptcha.valid ? '' : null\"\n >\n <sc-smart-captcha formControlName=\"recaptcha\" />\n </div>\n @if (recaptcha.getError('serverResponse'); as serverErrors) {\n <tui-error [error]=\"serverErrors.join(' ')\" />\n }\n }\n <!-- \u042D\u043B\u0435\u043C\u0435\u043D\u0442\u044B \u0443\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u044F -->\n <div class=\"flex flex-wrap items-center gap-3\">\n <button\n tuiButton\n [disabled]=\"form.invalid\"\n [loading]=\"!!(loading$ | async)\"\n type=\"submit\"\n iconStart=\"@tui.sc.send\"\n class=\"self-center\"\n >\n \u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C\n </button>\n <div class=\"grow basis-60 text-body-s\">\n \u041D\u0430\u0436\u0438\u043C\u0430\u044F \u043D\u0430 \u043A\u043D\u043E\u043F\u043A\u0443, \u0432\u044B \u0441\u043E\u0433\u043B\u0430\u0448\u0430\u0435\u0442\u0435\u0441\u044C \u0441\n <button\n tuiLink\n [style.text-decoration-line]=\"'underline'\"\n type=\"button\"\n (click)=\"context?.data?.onClickOfferHandler(); clickOffer.emit()\"\n >\n \u041F\u043E\u043B\u0438\u0442\u0438\u043A\u043E\u0439 \u043A\u043E\u043D\u0444\u0438\u0434\u0435\u043D\u0446\u0438\u0430\u043B\u044C\u043D\u043E\u0441\u0442\u0438\n </button>\n </div>\n </div>\n </form>\n}\n" }]
|
|
9854
10623
|
}], ctorParameters: () => [], propDecorators: { slugInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "slug", required: false }] }], fieldsInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "fields", required: false }] }], clickOffer: [{ type: i0.Output, args: ["clickOffer"] }], sendSuccess: [{ type: i0.Output, args: ["sendSuccess"] }], isValidPhoneNumberForMessenger: [] } });
|
|
9855
10624
|
|
|
9856
10625
|
/**
|
|
@@ -9879,38 +10648,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
9879
10648
|
args: [{ selector: 'sc-gratitude', imports: [TuiIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"flex flex-col items-center gap-4 py-14 text-center\">\n <tui-icon\n icon=\"@tui.circle-check\"\n class=\"!size-20 !text-5xl text-tui-success-fill\"\n />\n <p class=\"text-h5\">\u0421\u043F\u0430\u0441\u0438\u0431\u043E!</p>\n <p\n [innerHTML]=\"context?.data?.subTitle ?? '\u0412\u0430\u0448\u0438 \u0434\u0430\u043D\u043D\u044B\u0435 \u0443\u0441\u043F\u0435\u0448\u043D\u043E \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u044B. \u041C\u044B \u0441\u0432\u044F\u0436\u0435\u043C\u0441\u044F \u0441 \u0432\u0430\u043C\u0438 \u0432 \u0431\u043B\u0438\u0436\u0430\u0439\u0448\u0435\u0435 \u0432\u0440\u0435\u043C\u044F.'\"\n class=\"mx-2 text-body-m\"\n ></p>\n</div>\n" }]
|
|
9880
10649
|
}], ctorParameters: () => [] });
|
|
9881
10650
|
|
|
9882
|
-
/**
|
|
9883
|
-
* Компонент кнопки "Поделиться".
|
|
9884
|
-
*/
|
|
9885
|
-
class ScShareButtonComponent {
|
|
9886
|
-
constructor() {
|
|
9887
|
-
/**
|
|
9888
|
-
* Формат внешнего вида кнопки.
|
|
9889
|
-
*/
|
|
9890
|
-
this.appearance = 'secondary';
|
|
9891
|
-
/**
|
|
9892
|
-
* Размер кнопки.
|
|
9893
|
-
*/
|
|
9894
|
-
this.size = 'm';
|
|
9895
|
-
/**
|
|
9896
|
-
* Событие клика по кнопке "Поделиться".
|
|
9897
|
-
*/
|
|
9898
|
-
this.clickShareEvent = new EventEmitter();
|
|
9899
|
-
}
|
|
9900
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScShareButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9901
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: ScShareButtonComponent, isStandalone: true, selector: "sc-share-button", inputs: { appearance: "appearance", size: "size" }, outputs: { clickShareEvent: "clickShareEvent" }, ngImport: i0, template: "<button\n tuiIconButton\n [appearance]=\"appearance\"\n [size]=\"size\"\n (click)=\"$event.stopPropagation(); clickShareEvent.emit()\"\n>\n <tui-icon icon=\"@tui.share-2\" />\n</button>\n", dependencies: [{ kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiIcon, selector: "tui-icon:not([tuiBadge])", inputs: ["background"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
9902
|
-
}
|
|
9903
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ScShareButtonComponent, decorators: [{
|
|
9904
|
-
type: Component,
|
|
9905
|
-
args: [{ selector: 'sc-share-button', changeDetection: ChangeDetectionStrategy.OnPush, imports: [TuiButton, TuiIcon], template: "<button\n tuiIconButton\n [appearance]=\"appearance\"\n [size]=\"size\"\n (click)=\"$event.stopPropagation(); clickShareEvent.emit()\"\n>\n <tui-icon icon=\"@tui.share-2\" />\n</button>\n" }]
|
|
9906
|
-
}], propDecorators: { appearance: [{
|
|
9907
|
-
type: Input
|
|
9908
|
-
}], size: [{
|
|
9909
|
-
type: Input
|
|
9910
|
-
}], clickShareEvent: [{
|
|
9911
|
-
type: Output
|
|
9912
|
-
}] } });
|
|
9913
|
-
|
|
9914
10651
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
9915
10652
|
/**
|
|
9916
10653
|
* Компонент смены пароля пользователя.
|
|
@@ -10368,5 +11105,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
10368
11105
|
* Generated bundle index. Do not edit.
|
|
10369
11106
|
*/
|
|
10370
11107
|
|
|
10371
|
-
export { AbstractScPriceCard, AuthMethod, CURRENT_COUNTRY_ID, CostWithDiscountComponent, FilesAndDocumentsComponent, 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_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, ScAddContactDialogComponent, ScAddContragentBankAccountsDialogComponent, ScAddContragentDialogComponent, ScAddDeliveryAddressDialogComponent, ScAddOrEditingCartItemDialogComponent, ScAddOrEditingCartItemFormComponent, ScAddressesSelectionFieldComponent, ScBannerComponent, ScBrandsListComponent, ScCartAddProductsFromCsvDialogComponent, ScCatalogFilterCollapsibleComponent, ScCatalogFiltersComponent, ScCategoryCardComponent, ScContactsAccordionComponent, ScContragentsAccordionComponent, ScContragentsAccordionItemComponent, ScDeliveryAddressAccordionComponent, ScDeliveryAddressAccordionItemComponent, ScDownloadPriceListComponent, ScDraftComponent, ScEmailLinkDirective, ScErrorBlockStatusComponent, ScErrorHandlerComponent, ScFavoriteButtonComponent, ScFeedbackFormComponent, ScFocusFirstInvalidFieldDirective, ScFormatDatePipe, ScFrequentlyAskedQuestionsComponent, ScFrequentlyAskedQuestionsGroupSelectorComponent, ScFrequentlyAskedQuestionsWithGroupsComponent, ScGratitudeComponent, ScHelpNotificationService, ScHoverImageCarouselComponent, ScInputQuantityComponent, ScLinks, ScManagerCardComponent, ScManagerCardPushComponent, ScNewContactFormComponent, ScNewContragentBankAccountsFormComponent, ScNewContragentFormComponent, ScNewsCardComponent, ScNewsCardSkeletonComponent, ScNewsListComponent, ScNextInputFocusDirective, ScNoindexDirective, ScNoindexWrapperComponent, ScNotifyWhenInStockDialogComponent, ScOrderAccessorDirective,
|
|
11108
|
+
export { AbstractScPriceCard, AuthMethod, CURRENT_COUNTRY_ID, CostWithDiscountComponent, FilesAndDocumentsComponent, 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_QUESTION_ANCHOR_PREFIX, 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_SMART_CAPTCHA_LOAD_TIMEOUT, SC_SMART_CAPTCHA_SETTINGS, SC_USER_CITY_INFO, SC_USER_INFO, SC_USER_PROVIDERS, SC_VERIFICATION_CODE_TIMEOUT, ScAccordionComponent, ScAccordionContentDirective, ScAddContactDialogComponent, ScAddContragentBankAccountsDialogComponent, ScAddContragentDialogComponent, ScAddDeliveryAddressDialogComponent, ScAddOrEditingCartItemDialogComponent, ScAddOrEditingCartItemFormComponent, ScAddressesSelectionFieldComponent, ScBannerComponent, ScBrandsListComponent, ScCartAddProductsFromCsvDialogComponent, ScCatalogFilterCollapsibleComponent, ScCatalogFiltersComponent, ScCategoryCardComponent, ScContactsAccordionComponent, ScContragentsAccordionComponent, ScContragentsAccordionItemComponent, ScDeliveryAddressAccordionComponent, ScDeliveryAddressAccordionItemComponent, ScDownloadPriceListComponent, ScDraftComponent, ScEmailLinkDirective, ScErrorBlockStatusComponent, ScErrorHandlerComponent, ScFavoriteButtonComponent, ScFeedbackFormComponent, ScFocusFirstInvalidFieldDirective, ScFormatDatePipe, ScFrequentlyAskedQuestionsComponent, ScFrequentlyAskedQuestionsGroupSelectorComponent, ScFrequentlyAskedQuestionsWithGroupsComponent, ScGratitudeComponent, ScHelpNotificationService, ScHoverImageCarouselComponent, ScInputQuantityComponent, ScLinks, ScManagerCardComponent, ScManagerCardPushComponent, ScNewContactFormComponent, ScNewContragentBankAccountsFormComponent, ScNewContragentFormComponent, ScNewOrderItemsComponent, ScNewsCardComponent, ScNewsCardSkeletonComponent, ScNewsListComponent, ScNextInputFocusDirective, ScNoindexDirective, ScNoindexWrapperComponent, ScNotifyWhenInStockDialogComponent, ScOrderAccessorDirective, ScOrderFormComponent, ScOrderItemComponent, ScOrderItemsListByStockComponent, ScOrderItemsListComponent, ScOrderItemsListWithActionsComponent, ScPaginationLinksComponent, ScPaymentStatusComponent, ScPersonalDataProcessingPolicyComponent, ScPhoneFormatPipe, ScPreviewSampleComponent, ScPreviewSamplesMosquitoComponent, ScPriceCardComponent, ScPriceCardInlineComponent, ScPriceHistoryComponent, ScPriceListPaginationComponent, ScPriceWarehouseStockComponent, ScPrintDirective, ScPrintService, ScPrivacyPolicyComponent, ScProductInAllWarehousesPipe, ScProfileAccordionsContentComponent, ScPublicOfferComponent, ScQRCodeDialogComponent, ScResetUserPasswordComponent, ScResourcePreviewComponent, ScSandwichComponent, ScSandwichM2Component, ScSandwichM2SkeletonComponent, ScSandwichSkeletonComponent, ScScriptsService, ScSelectOnFocusinDirective, ScSeoTagsComponent, ScShareButtonComponent, ScShareDialogComponent, ScShareMessengersLinksComponent, ScShareService, ScSignInFormByEmailComponent, ScSignInFormByPhoneComponent, ScSignInFormComponent, ScSignUpFormComponent, ScSimpleSignUpFormComponent, ScSmartCaptchaComponent, ScSmartCaptchaLoaderService, ScSuggestionFieldComponent, ScTelLinkDirective, ScTerminalLinkDirective, ScUpdateUserInfoDialogComponent, ScUserManagersComponent, ScUserPhoneApproveDialogComponent, ScVerificationPhoneCheckFormComponent, TreeDirective, TreeIconService, TreeLoaderService, TreeTopDirective, phoneValidator, scAtLeastOneRequiredValidator, scBicValidator, scClientUiIconsName, scCorrespondentAccountValidator, scGetCurrentRoute, scGetFaqGroupQueryParams, scGetFaqQuestionAnchor, scGetFaqQuestionIdFromAnchor, scPasswordConfirmMatchingValidator, stepValidator, tuiDateValueTransformerDefaultProvider };
|
|
10372
11109
|
//# sourceMappingURL=snabcentr-client-ui.mjs.map
|