@escapenavigator/hooks 2.2.7 → 2.2.9

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.
@@ -135,10 +135,14 @@ export type PlayersAndVariationPickerProps = {
135
135
  hidePriceHints?: boolean;
136
136
  /**
137
137
  * Опция «Определимся на месте» (questroom.playersSelectMode=OPTIONAL).
138
- * Стоит первым пунктом и выбрана по умолчанию, но теги/строки состава
139
- * остаются видимыми — гость может указать точное число. Пока flex
140
- * выбран, ни одно число не подсвечено, ценовые подсказки скрыты:
141
- * хост рендерит «базовую стоимость от» сам.
138
+ * Выбрана по умолчанию. Пока flex выбран, ни одно число не подсвечено,
139
+ * ценовые подсказки скрыты: хост рендерит «базовую стоимость от» сам.
140
+ *
141
+ * Простой состав (только число человек) — чип стоит в одном ряду с
142
+ * числами, клик по числу снимает flex. Сложный (взрослые, дети,
143
+ * льготы) — пара чипов «Определимся на месте» / «Уже определились»:
144
+ * степперы видны только когда состав уже выбран, иначе заполненные
145
+ * строки спорят с «решим на месте».
142
146
  */
143
147
  flexPlayersOption?: {
144
148
  selected: boolean;
@@ -59,6 +59,29 @@ const react_i18next_1 = require("react-i18next");
59
59
  const use_players_and_variation_picker_1 = require("../use-players-and-variation-picker");
60
60
  const sync_composition_1 = require("./sync-composition");
61
61
  const ticket_row_1 = require("./ticket-row");
62
+ /**
63
+ * Подпись второго чипа сложного состава, пока ключа нет в каталоге переводов.
64
+ * Тон рядом с `decideOnSite` того же языка. Неизвестный язык — английский,
65
+ * как `fallbackLng` виджета.
66
+ */
67
+ const playersAlreadyDecidedFallback = {
68
+ ru: 'Уже определились',
69
+ en: 'Already decided',
70
+ sv: 'Redan bestämt',
71
+ de: 'Schon entschieden',
72
+ pl: 'Już ustaliliśmy',
73
+ es: 'Ya lo sabemos',
74
+ fr: 'Déjà décidé',
75
+ nl: 'Al besloten',
76
+ da: 'Allerede afgjort',
77
+ fi: 'Jo päätetty',
78
+ };
79
+ const playersAlreadyDecidedLabel = (translate, language) => {
80
+ const lng = (language || 'en').toLowerCase().split('-')[0];
81
+ return translate('prices:playersAlreadyDecided', {
82
+ defaultValue: playersAlreadyDecidedFallback[lng] || playersAlreadyDecidedFallback.en,
83
+ });
84
+ };
62
85
  /**
63
86
  * Единый пикер «вариация + состав», который используют админские модалки
64
87
  * заказа, виджет и пакет orders.
@@ -75,7 +98,7 @@ const PlayersAndVariationPicker = ({ slot, currentTariffId, currentDuration, loa
75
98
  * `useTranslation()` без нужных namespace'ов, а в CRM `prices` грузится
76
99
  * лениво. Декларируем их здесь — i18next догрузит бандлы и перерендерит.
77
100
  */
78
- const { ready: translationsReady } = (0, react_i18next_1.useTranslation)(['prices', 'common'], {
101
+ const { ready: translationsReady, i18n } = (0, react_i18next_1.useTranslation)(['prices', 'common'], {
79
102
  useSuspense: false,
80
103
  });
81
104
  const { loading: pickerLoading, options: pickerOptions, selectedOptionId, selectedVariation, buildVariationChange, selectVariation, details, } = (0, use_players_and_variation_picker_1.usePlayersAndVariationPicker)({
@@ -242,6 +265,20 @@ const PlayersAndVariationPicker = ({ slot, currentTariffId, currentDuration, loa
242
265
  }
243
266
  flexPlayersOption === null || flexPlayersOption === void 0 ? void 0 : flexPlayersOption.onSelect(true);
244
267
  };
268
+ /**
269
+ * Сложный состав: гость явно сказал, что число уже известно.
270
+ * Пока «на месте», степперы скрыты и крутить их было негде. Пустой
271
+ * состав (ещё никто не выбран) открываем минимальной группой — той же,
272
+ * по которой уже показана цена «от». Набранное раньше число не трогаем.
273
+ */
274
+ const handleSelectDecided = () => {
275
+ if (!flexSelected)
276
+ return;
277
+ if (totalHeads === 0 && effectiveMin > 0 && baseCategoryKey) {
278
+ applyComposition(Object.assign(Object.assign({}, _composition), { [baseCategoryKey]: effectiveMin }));
279
+ }
280
+ flexPlayersOption === null || flexPlayersOption === void 0 ? void 0 : flexPlayersOption.onSelect(false);
281
+ };
245
282
  /**
246
283
  * Единственная автоправка состава: смена вариации сузила сетку, и состав
247
284
  * торчит выше нового потолка — иначе на бэке `price[N]` = undefined →
@@ -419,29 +456,32 @@ const PlayersAndVariationPicker = ({ slot, currentTariffId, currentDuration, loa
419
456
  ? categoryTitle(baseCategory)
420
457
  : t('prices:choosePlayersAmount')),
421
458
  !hasExtraRows && !flexSelected && !!tariff[pricingHeads] && (react_1.default.createElement(typography_1.Typography.Text, { view: 'title', color: 'secondary' }, (0, format_amount_1.formatAmount)(tariff[pricingHeads], currency)))),
422
- (!!flexPlayersOption || !hasExtraRows) && (react_1.default.createElement(flex_1.Flex, { gap: 'xs', wrap: true, justify: 'start' },
459
+ hasExtraRows && flexPlayersOption ? (react_1.default.createElement(flex_1.Flex, { gap: 'xs', wrap: true, justify: 'start' },
460
+ react_1.default.createElement(tag_1.Tag, { key: 'flex-players', text: flexPlayersOption.label, onClick: handleSelectFlex, view: flexSelected ? 'primary-inverted' : 'primary' }),
461
+ react_1.default.createElement(tag_1.Tag, { key: 'players-decided', text: playersAlreadyDecidedLabel(t, i18n.resolvedLanguage || i18n.language), onClick: handleSelectDecided, view: flexSelected ? 'primary' : 'primary-inverted' }))) : ((!!flexPlayersOption || !hasExtraRows) && (react_1.default.createElement(flex_1.Flex, { gap: 'xs', wrap: true, justify: 'start' },
423
462
  !!flexPlayersOption && (react_1.default.createElement(tag_1.Tag, { key: 'flex-players', text: flexPlayersOption.label, onClick: handleSelectFlex, view: flexSelected ? 'primary-inverted' : 'primary' })),
424
463
  !hasExtraRows &&
425
464
  baseLevelOptions.map((level) => (react_1.default.createElement(tag_1.Tag, { key: `level-${level}`, text: `${level}`, onClick: () => handleSelectLevel(level), view: !flexSelected && pricingHeads === level
426
465
  ? 'primary-inverted'
427
- : 'primary' }))))),
428
- (hasExtraRows ? categories : addOnCategories).map((category) => {
429
- var _a, _b;
430
- const value = Math.max(0, _composition[category.key] || 0);
431
- const rowMax = (_a = maxByCategory[category.key]) !== null && _a !== void 0 ? _a : value;
432
- const plusLimitHint = value >= rowMax
433
- ? capacityReached
434
- ? t('prices:capacityReached', {
435
- count: capacityMax,
436
- defaultValue: 'Максимум {{count}} участников',
437
- })
438
- : t('prices:pricingMaxReached', {
439
- count: pricingMax,
440
- defaultValue: 'Максимум {{count}} участников по этому тарифу',
441
- })
442
- : undefined;
443
- return (react_1.default.createElement(ticket_row_1.TicketRow, { key: category.key, title: categoryTitle(category), priceHint: categoryPriceHint(category), description: ((_b = category.description) === null || _b === void 0 ? void 0 : _b.trim()) || undefined, value: value, min: 0, max: rowMax, minusLabel: t('prices:minus', { defaultValue: 'На одного меньше' }), plusLabel: t('prices:plus', { defaultValue: 'На одного больше' }), plusDisabledHint: plusLimitHint, onChange: (next) => handleChangeCategory(category.key, next) }));
444
- })),
466
+ : 'primary' })))))),
467
+ (hasExtraRows ? !flexSelected : true) &&
468
+ (hasExtraRows ? categories : addOnCategories).map((category) => {
469
+ var _a, _b;
470
+ const value = Math.max(0, _composition[category.key] || 0);
471
+ const rowMax = (_a = maxByCategory[category.key]) !== null && _a !== void 0 ? _a : value;
472
+ const plusLimitHint = value >= rowMax
473
+ ? capacityReached
474
+ ? t('prices:capacityReached', {
475
+ count: capacityMax,
476
+ defaultValue: 'Максимум {{count}} участников',
477
+ })
478
+ : t('prices:pricingMaxReached', {
479
+ count: pricingMax,
480
+ defaultValue: 'Максимум {{count}} участников по этому тарифу',
481
+ })
482
+ : undefined;
483
+ return (react_1.default.createElement(ticket_row_1.TicketRow, { key: category.key, title: categoryTitle(category), priceHint: categoryPriceHint(category), description: ((_b = category.description) === null || _b === void 0 ? void 0 : _b.trim()) || undefined, value: value, min: 0, max: rowMax, minusLabel: t('prices:minus', { defaultValue: 'На одного меньше' }), plusLabel: t('prices:plus', { defaultValue: 'На одного больше' }), plusDisabledHint: plusLimitHint, onChange: (next) => handleChangeCategory(category.key, next) }));
484
+ })),
445
485
  !hidePriceHints && !flexSelected && bookable && (react_1.default.createElement(flex_columns_1.FlexColumns, { columns: 1, gr: 4, gc: 0 }, priceSummary)),
446
486
  hidePriceHints && !flexSelected && bookable && (react_1.default.createElement("div", { style: {
447
487
  display: 'flex',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@escapenavigator/hooks",
3
- "version": "2.2.7",
3
+ "version": "2.2.9",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -14,9 +14,9 @@
14
14
  "test": "jest"
15
15
  },
16
16
  "dependencies": {
17
- "@escapenavigator/services": "^2.2.7",
18
- "@escapenavigator/types": "^2.2.6",
19
- "@escapenavigator/utils": "^2.2.6",
17
+ "@escapenavigator/services": "^2.2.8",
18
+ "@escapenavigator/types": "^2.2.7",
19
+ "@escapenavigator/utils": "^2.2.7",
20
20
  "libphonenumber-js": "^1.12.24",
21
21
  "react": "19.2.6",
22
22
  "react-phone-input-2": "^2.15.1"
@@ -32,5 +32,5 @@
32
32
  "ts-jest": "^29.1.1",
33
33
  "typescript": "^5.6"
34
34
  },
35
- "gitHead": "f218bc4b0618e6bb3f0fa12e17887290690916f9"
35
+ "gitHead": "8331e15dfa6ac28921249548f4df2c702669de37"
36
36
  }