@zenky/storefront-vue 0.9.40 → 0.9.43

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/dist/cjs/index.js CHANGED
@@ -3,10 +3,9 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var vue = require('vue');
6
- var lodashEs = require('lodash-es');
7
6
  var api = require('@zenky/api');
7
+ var lodashEs = require('lodash-es');
8
8
  var pinia = require('pinia');
9
- var ui = require('@zenky/ui');
10
9
  var events = require('@zenky/events');
11
10
  var dateFns = require('date-fns');
12
11
  var Pusher = require('pusher-js');
@@ -27,7 +26,11 @@ function useDataDestroyer(destroyer, errorHandler) {
27
26
  return true;
28
27
  }
29
28
  catch (e) {
30
- errorHandler(e);
29
+ errorHandler({
30
+ e,
31
+ error: api.getApiError(e),
32
+ message: api.getApiErrorMessage(e),
33
+ });
31
34
  }
32
35
  finally {
33
36
  destroying.value = false;
@@ -40,8 +43,18 @@ function useDataDestroyer(destroyer, errorHandler) {
40
43
  };
41
44
  }
42
45
 
43
- function getApiErrorHandler(providedHandler, defaultHandler) {
44
- return providedHandler ? providedHandler : defaultHandler;
46
+ function getApiErrorHandler(providedHandler, composableName, defaultMessage) {
47
+ if (typeof providedHandler === 'function') {
48
+ return providedHandler;
49
+ }
50
+ return function ({ e, error, message }) {
51
+ console.error(`[${composableName}] ${defaultMessage}`, {
52
+ message,
53
+ error,
54
+ e,
55
+ });
56
+ console.info(`[@zenky/storefront] Pass errorHandler argument to the ${composableName}() composable to properly handle this error.`);
57
+ };
45
58
  }
46
59
 
47
60
  exports.ZenkyInjection = void 0;
@@ -114,7 +127,11 @@ function usePaginatedLoader(provider, errorHandler) {
114
127
  }
115
128
  }
116
129
  catch (e) {
117
- errorHandler(e);
130
+ errorHandler({
131
+ e,
132
+ error: api.getApiError(e),
133
+ message: api.getApiErrorMessage(e),
134
+ });
118
135
  }
119
136
  finally {
120
137
  state.value.loading = false;
@@ -144,7 +161,11 @@ function useListLoader(provider, errorHandler) {
144
161
  items.value = await provider(request);
145
162
  }
146
163
  catch (e) {
147
- errorHandler(e);
164
+ errorHandler({
165
+ e,
166
+ error: api.getApiError(e),
167
+ message: api.getApiErrorMessage(e),
168
+ });
148
169
  }
149
170
  finally {
150
171
  state.value.loading = false;
@@ -172,7 +193,11 @@ function useItemLoader(provider, errorHandler) {
172
193
  item.value = await provider(id, request);
173
194
  }
174
195
  catch (e) {
175
- errorHandler(e);
196
+ errorHandler({
197
+ e,
198
+ error: api.getApiError(e),
199
+ message: api.getApiErrorMessage(e),
200
+ });
176
201
  }
177
202
  finally {
178
203
  state.value.loading = false;
@@ -200,7 +225,11 @@ function useDataLoader(provider, errorHandler) {
200
225
  data.value = await provider();
201
226
  }
202
227
  catch (e) {
203
- errorHandler(e);
228
+ errorHandler({
229
+ e,
230
+ error: api.getApiError(e),
231
+ message: api.getApiErrorMessage(e),
232
+ });
204
233
  }
205
234
  finally {
206
235
  state.value.loading = false;
@@ -392,19 +421,19 @@ const useStoreStore = pinia.defineStore({
392
421
  });
393
422
 
394
423
  function useDadata() {
395
- const { cityId } = useStoreStore();
424
+ const { cityId } = pinia.storeToRefs(useStoreStore());
396
425
  const query = vue.ref(null);
397
426
  const loading = vue.ref(false);
398
427
  const results = vue.ref([]);
399
428
  vue.watch(query, lodashEs.debounce(async () => {
400
- if (loading.value || !query.value || !cityId) {
429
+ if (loading.value || !query.value || !cityId.value) {
401
430
  return;
402
431
  }
403
432
  try {
404
433
  loading.value = true;
405
434
  const { suggestions } = await api.getAddressSuggestions({
406
435
  query: query.value,
407
- city_id: cityId,
436
+ city_id: cityId.value,
408
437
  });
409
438
  results.value = suggestions;
410
439
  }
@@ -504,6 +533,15 @@ const getAddressForm = () => ({
504
533
  floor: '',
505
534
  has_intercom: true,
506
535
  });
536
+ exports.AddressFormValueError = void 0;
537
+ (function (AddressFormValueError) {
538
+ AddressFormValueError["DaDataSuggestionRequired"] = "dadata.suggestion_required";
539
+ AddressFormValueError["CityRequired"] = "plain.city_required";
540
+ AddressFormValueError["StreetRequired"] = "plain.street_required";
541
+ AddressFormValueError["HouseRequired"] = "plain.house_required";
542
+ AddressFormValueError["StockRequired"] = "stock_required";
543
+ AddressFormValueError["TableRequired"] = "table_required";
544
+ })(exports.AddressFormValueError || (exports.AddressFormValueError = {}));
507
545
  function useAddressFormValue(form, resolver, address) {
508
546
  const errors = [];
509
547
  let data = {};
@@ -531,18 +569,18 @@ function useAddressFormValue(form, resolver, address) {
531
569
  };
532
570
  }
533
571
  else {
534
- errors.push('Нужно выбрать улицу из выпадающего списка.');
572
+ errors.push(exports.AddressFormValueError.DaDataSuggestionRequired);
535
573
  }
536
574
  }
537
575
  else if (resolver === 'plain') {
538
576
  if (!form.city) {
539
- errors.push('Нужно указать город.');
577
+ errors.push(exports.AddressFormValueError.CityRequired);
540
578
  }
541
579
  else if (!form.street) {
542
- errors.push('Нужно указать улицу.');
580
+ errors.push(exports.AddressFormValueError.StreetRequired);
543
581
  }
544
582
  else if (!form.house) {
545
- errors.push('Нужно указать номер дома.');
583
+ errors.push(exports.AddressFormValueError.HouseRequired);
546
584
  }
547
585
  else {
548
586
  data = {
@@ -820,9 +858,7 @@ function useCategoryFeaturesList(categoryId, errorHandler) {
820
858
  return [];
821
859
  }
822
860
  return api.getCategoryFeatures(categoryId);
823
- }, getApiErrorHandler(errorHandler, function (e) {
824
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить список фильтров.'));
825
- }));
861
+ }, getApiErrorHandler(errorHandler, 'useCategoryFeaturesList', 'Unable to load category features list.'));
826
862
  }
827
863
  function useCategoryFeaturesGroupsList(categoryId, errorHandler) {
828
864
  return useListLoader(async function () {
@@ -830,25 +866,17 @@ function useCategoryFeaturesGroupsList(categoryId, errorHandler) {
830
866
  return [];
831
867
  }
832
868
  return api.getCategoryFeaturesGroups(categoryId);
833
- }, getApiErrorHandler(errorHandler, function (e) {
834
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить список фильтров.'));
835
- }));
869
+ }, getApiErrorHandler(errorHandler, 'useCategoryFeaturesGroupsList', 'Unable to load category features groups list.'));
836
870
  }
837
871
 
838
872
  function useArticlesList(errorHandler) {
839
- return usePaginatedLoader(api.getArticles, getApiErrorHandler(errorHandler, function (e) {
840
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить список статей.'));
841
- }));
873
+ return usePaginatedLoader(api.getArticles, getApiErrorHandler(errorHandler, 'useArticlesList', 'Unable to load articles list.'));
842
874
  }
843
875
  function useArticleCategoriesList(errorHandler) {
844
- return usePaginatedLoader(api.getArticleCategories, getApiErrorHandler(errorHandler, function (e) {
845
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить список категорий статей.'));
846
- }));
876
+ return usePaginatedLoader(api.getArticleCategories, getApiErrorHandler(errorHandler, 'useArticleCategoriesList', 'Unable to load article categories list.'));
847
877
  }
848
878
  function useArticleItem(errorHandler) {
849
- return useItemLoader(api.getArticle, getApiErrorHandler(errorHandler, function (e) {
850
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить статью.'));
851
- }));
879
+ return useItemLoader(api.getArticle, getApiErrorHandler(errorHandler, 'useArticleItem', 'Unable to load article.'));
852
880
  }
853
881
 
854
882
  exports.AuthenticationStage = void 0;
@@ -865,26 +893,45 @@ exports.AuthenticationEvent = void 0;
865
893
  })(exports.AuthenticationEvent || (exports.AuthenticationEvent = {}));
866
894
  exports.AuthenticationResultType = void 0;
867
895
  (function (AuthenticationResultType) {
868
- AuthenticationResultType["Pending"] = "pending";
869
896
  AuthenticationResultType["Validation"] = "validation";
870
897
  AuthenticationResultType["Failed"] = "failed";
871
898
  AuthenticationResultType["Completed"] = "completed";
872
899
  AuthenticationResultType["Stage"] = "stage";
873
900
  })(exports.AuthenticationResultType || (exports.AuthenticationResultType = {}));
901
+ exports.AuthenticationFailureReason = void 0;
902
+ (function (AuthenticationFailureReason) {
903
+ AuthenticationFailureReason["ApiError"] = "api_error";
904
+ AuthenticationFailureReason["InProgress"] = "in_progress";
905
+ AuthenticationFailureReason["Cooldown"] = "cooldown";
906
+ AuthenticationFailureReason["PhoneRequired"] = "phone_required";
907
+ AuthenticationFailureReason["PasswordRequired"] = "password_required";
908
+ AuthenticationFailureReason["CodeRequired"] = "code_required";
909
+ })(exports.AuthenticationFailureReason || (exports.AuthenticationFailureReason = {}));
910
+ exports.AddressResultType = void 0;
911
+ (function (AddressResultType) {
912
+ AddressResultType["Failed"] = "failed";
913
+ AddressResultType["Completed"] = "completed";
914
+ })(exports.AddressResultType || (exports.AddressResultType = {}));
915
+ exports.AddressResultReason = void 0;
916
+ (function (AddressResultReason) {
917
+ AddressResultReason["InProgress"] = "in_progress";
918
+ AddressResultReason["Validation"] = "validation";
919
+ AddressResultReason["ApiError"] = "api_error";
920
+ })(exports.AddressResultReason || (exports.AddressResultReason = {}));
874
921
 
875
922
  function useAuthenticationStatusChecker(form, emit) {
876
923
  const active = vue.ref(false);
877
924
  const check = async () => {
878
925
  if (active.value) {
879
926
  return {
880
- type: exports.AuthenticationResultType.Pending,
927
+ type: exports.AuthenticationResultType.Failed,
928
+ reason: exports.AuthenticationFailureReason.InProgress,
881
929
  };
882
930
  }
883
931
  else if (!form.value.phone.number || !form.value.phone.country) {
884
- ui.useNotification('error', 'Ошибка', 'Нужно указать номер телефона.');
885
932
  return {
886
933
  type: exports.AuthenticationResultType.Validation,
887
- data: 'phone',
934
+ reason: exports.AuthenticationFailureReason.PhoneRequired,
888
935
  };
889
936
  }
890
937
  active.value = true;
@@ -893,32 +940,33 @@ function useAuthenticationStatusChecker(form, emit) {
893
940
  if (!status.registered) {
894
941
  emit(exports.AuthenticationEvent.Stage, exports.AuthenticationStage.Register);
895
942
  return {
896
- type: exports.AuthenticationResultType.Completed,
943
+ type: exports.AuthenticationResultType.Stage,
897
944
  data: exports.AuthenticationStage.Register,
898
945
  };
899
946
  }
900
947
  else if (!status.confirmed) {
901
948
  emit(exports.AuthenticationEvent.Stage, exports.AuthenticationStage.Confirmation);
902
949
  return {
903
- type: exports.AuthenticationResultType.Completed,
950
+ type: exports.AuthenticationResultType.Stage,
904
951
  data: exports.AuthenticationStage.Confirmation,
905
952
  };
906
953
  }
907
954
  emit(exports.AuthenticationEvent.Stage, exports.AuthenticationStage.Login);
908
955
  return {
909
- type: exports.AuthenticationResultType.Completed,
956
+ type: exports.AuthenticationResultType.Stage,
910
957
  data: exports.AuthenticationStage.Login,
911
958
  };
912
959
  }
913
960
  catch (e) {
914
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось проверить статус регистрации. Повторите попытку.'));
961
+ return {
962
+ type: exports.AuthenticationResultType.Failed,
963
+ reason: exports.AuthenticationFailureReason.ApiError,
964
+ error: api.getApiError(e),
965
+ };
915
966
  }
916
967
  finally {
917
968
  active.value = false;
918
969
  }
919
- return {
920
- type: exports.AuthenticationResultType.Failed,
921
- };
922
970
  };
923
971
  return {
924
972
  active,
@@ -1015,21 +1063,20 @@ function useLogin(form, emit) {
1015
1063
  const login = async () => {
1016
1064
  if (active.value) {
1017
1065
  return {
1018
- type: exports.AuthenticationResultType.Pending,
1066
+ type: exports.AuthenticationResultType.Failed,
1067
+ reason: exports.AuthenticationFailureReason.InProgress,
1019
1068
  };
1020
1069
  }
1021
1070
  else if (!form.value.phone.number || !form.value.phone.country) {
1022
- ui.useNotification('error', 'Ошибка', 'Нужно указать номер телефона.');
1023
1071
  return {
1024
1072
  type: exports.AuthenticationResultType.Validation,
1025
- data: 'phone',
1073
+ reason: exports.AuthenticationFailureReason.PhoneRequired,
1026
1074
  };
1027
1075
  }
1028
1076
  else if (!form.value.password) {
1029
- ui.useNotification('error', 'Ошибка', 'Нужно указать пароль.');
1030
1077
  return {
1031
1078
  type: exports.AuthenticationResultType.Validation,
1032
- data: 'password',
1079
+ reason: exports.AuthenticationFailureReason.PasswordRequired,
1033
1080
  };
1034
1081
  }
1035
1082
  active.value = true;
@@ -1037,7 +1084,6 @@ function useLogin(form, emit) {
1037
1084
  const { token } = await api.login({ number: form.value.phone.number, country: form.value.phone.country }, form.value.password);
1038
1085
  const { setToken } = useCustomerStore();
1039
1086
  const customer = await setToken(token);
1040
- ui.useNotification('success', 'Успешный вход', 'Вы успешно вошли в ваш аккаунт!');
1041
1087
  emit(exports.AuthenticationEvent.Completed);
1042
1088
  return {
1043
1089
  type: exports.AuthenticationResultType.Completed,
@@ -1045,14 +1091,15 @@ function useLogin(form, emit) {
1045
1091
  };
1046
1092
  }
1047
1093
  catch (e) {
1048
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Указан неправильный пароль.'));
1094
+ return {
1095
+ type: exports.AuthenticationResultType.Failed,
1096
+ reason: exports.AuthenticationFailureReason.ApiError,
1097
+ error: api.getApiError(e),
1098
+ };
1049
1099
  }
1050
1100
  finally {
1051
1101
  active.value = false;
1052
1102
  }
1053
- return {
1054
- type: exports.AuthenticationResultType.Failed,
1055
- };
1056
1103
  };
1057
1104
  return {
1058
1105
  active,
@@ -1124,26 +1171,25 @@ function useRequest(form, active) {
1124
1171
  const request = async () => {
1125
1172
  if (active.value) {
1126
1173
  return {
1127
- type: exports.AuthenticationResultType.Pending,
1174
+ type: exports.AuthenticationResultType.Failed,
1175
+ reason: exports.AuthenticationFailureReason.InProgress,
1128
1176
  };
1129
1177
  }
1130
1178
  else if (seconds.value > 0) {
1131
- ui.useNotification('error', 'Ошибка', 'Нужно подождать перед повторной отправкой кода сброса пароля.');
1132
1179
  return {
1133
- type: exports.AuthenticationResultType.Pending,
1180
+ type: exports.AuthenticationResultType.Failed,
1181
+ reason: exports.AuthenticationFailureReason.Cooldown,
1134
1182
  };
1135
1183
  }
1136
1184
  else if (!form.value.phone.number || !form.value.phone.country) {
1137
- ui.useNotification('error', 'Ошибка', 'Нужно указать номер телефона.');
1138
1185
  return {
1139
1186
  type: exports.AuthenticationResultType.Validation,
1140
- data: 'phone',
1187
+ reason: exports.AuthenticationFailureReason.PhoneRequired,
1141
1188
  };
1142
1189
  }
1143
1190
  active.value = true;
1144
1191
  try {
1145
1192
  await api.requestPasswordResetCode(form.value.phone);
1146
- ui.useNotification('success', 'Код отправлен', 'Код сброса пароля был отправлен на ваш номер.');
1147
1193
  sent.value = true;
1148
1194
  start();
1149
1195
  return {
@@ -1151,14 +1197,15 @@ function useRequest(form, active) {
1151
1197
  };
1152
1198
  }
1153
1199
  catch (e) {
1154
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Нужно подождать перед повторной отправкой кода сброса пароля.'));
1200
+ return {
1201
+ type: exports.AuthenticationResultType.Failed,
1202
+ reason: exports.AuthenticationFailureReason.ApiError,
1203
+ error: api.getApiError(e),
1204
+ };
1155
1205
  }
1156
1206
  finally {
1157
1207
  active.value = false;
1158
1208
  }
1159
- return {
1160
- type: exports.AuthenticationResultType.Failed,
1161
- };
1162
1209
  };
1163
1210
  return {
1164
1211
  seconds,
@@ -1171,28 +1218,26 @@ function useReset(form, active, emit) {
1171
1218
  const reset = async () => {
1172
1219
  if (active.value) {
1173
1220
  return {
1174
- type: exports.AuthenticationResultType.Pending,
1221
+ type: exports.AuthenticationResultType.Failed,
1222
+ reason: exports.AuthenticationFailureReason.InProgress,
1175
1223
  };
1176
1224
  }
1177
1225
  else if (!form.value.phone.number || !form.value.phone.country) {
1178
- ui.useNotification('error', 'Ошибка', 'Нужно указать номер телефона.');
1179
1226
  return {
1180
1227
  type: exports.AuthenticationResultType.Validation,
1181
- data: 'phone',
1228
+ reason: exports.AuthenticationFailureReason.PhoneRequired,
1182
1229
  };
1183
1230
  }
1184
1231
  else if (!form.value.password) {
1185
- ui.useNotification('error', 'Ошибка', 'Нужно придумать новый пароль.');
1186
1232
  return {
1187
1233
  type: exports.AuthenticationResultType.Validation,
1188
- data: 'password',
1234
+ reason: exports.AuthenticationFailureReason.PasswordRequired,
1189
1235
  };
1190
1236
  }
1191
1237
  else if (!form.value.confirmation_code) {
1192
- ui.useNotification('error', 'Ошибка', 'Нужно указать код из SMS.');
1193
1238
  return {
1194
1239
  type: exports.AuthenticationResultType.Validation,
1195
- data: 'confirmation_code',
1240
+ reason: exports.AuthenticationFailureReason.CodeRequired,
1196
1241
  };
1197
1242
  }
1198
1243
  active.value = true;
@@ -1200,7 +1245,6 @@ function useReset(form, active, emit) {
1200
1245
  const result = await api.resetPassword(form.value.phone, form.value.confirmation_code, form.value.password);
1201
1246
  const store = useCustomerStore();
1202
1247
  await store.setToken(result.token);
1203
- ui.useNotification('success', 'Пароль изменён', 'Вы успешно изменили пароль и вошли в свой аккаунт.');
1204
1248
  emit(exports.AuthenticationEvent.Completed);
1205
1249
  return {
1206
1250
  type: exports.AuthenticationResultType.Completed,
@@ -1208,14 +1252,15 @@ function useReset(form, active, emit) {
1208
1252
  };
1209
1253
  }
1210
1254
  catch (e) {
1211
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Указан неправильный код сброса пароля.'));
1255
+ return {
1256
+ type: exports.AuthenticationResultType.Failed,
1257
+ reason: exports.AuthenticationFailureReason.ApiError,
1258
+ error: api.getApiError(e),
1259
+ };
1212
1260
  }
1213
1261
  finally {
1214
1262
  active.value = false;
1215
1263
  }
1216
- return {
1217
- type: exports.AuthenticationResultType.Failed,
1218
- };
1219
1264
  };
1220
1265
  return {
1221
1266
  reset,
@@ -1240,21 +1285,20 @@ function useRegistration(form, emit) {
1240
1285
  const register = async () => {
1241
1286
  if (active.value) {
1242
1287
  return {
1243
- type: exports.AuthenticationResultType.Pending,
1288
+ type: exports.AuthenticationResultType.Failed,
1289
+ reason: exports.AuthenticationFailureReason.InProgress,
1244
1290
  };
1245
1291
  }
1246
1292
  else if (!form.value.phone.number || !form.value.phone.country) {
1247
- ui.useNotification('error', 'Ошибка', 'Нужно указать номер телефона.');
1248
1293
  return {
1249
1294
  type: exports.AuthenticationResultType.Validation,
1250
- data: 'phone',
1295
+ reason: exports.AuthenticationFailureReason.PhoneRequired,
1251
1296
  };
1252
1297
  }
1253
1298
  else if (!form.value.password) {
1254
- ui.useNotification('error', 'Ошибка', 'Нужно придумать пароль.');
1255
1299
  return {
1256
1300
  type: exports.AuthenticationResultType.Validation,
1257
- data: 'password',
1301
+ reason: exports.AuthenticationFailureReason.PasswordRequired,
1258
1302
  };
1259
1303
  }
1260
1304
  active.value = true;
@@ -1262,7 +1306,6 @@ function useRegistration(form, emit) {
1262
1306
  const result = await api.register(form.value.phone, form.value.password);
1263
1307
  if (!result.confirmation_required) {
1264
1308
  emit(exports.AuthenticationEvent.Completed);
1265
- ui.useNotification('success', 'Успешная регистрация', 'Вы успешно зарегистрировались!');
1266
1309
  return {
1267
1310
  type: exports.AuthenticationResultType.Completed,
1268
1311
  };
@@ -1274,14 +1317,15 @@ function useRegistration(form, emit) {
1274
1317
  };
1275
1318
  }
1276
1319
  catch (e) {
1277
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Этот телефон уже зарегистрирован.'));
1320
+ return {
1321
+ type: exports.AuthenticationResultType.Failed,
1322
+ reason: exports.AuthenticationFailureReason.ApiError,
1323
+ error: api.getApiError(e),
1324
+ };
1278
1325
  }
1279
1326
  finally {
1280
1327
  active.value = false;
1281
1328
  }
1282
- return {
1283
- type: exports.AuthenticationResultType.Failed,
1284
- };
1285
1329
  };
1286
1330
  return {
1287
1331
  active,
@@ -1294,20 +1338,20 @@ function useResend(form, active) {
1294
1338
  const resend = async () => {
1295
1339
  if (active.value) {
1296
1340
  return {
1297
- type: exports.AuthenticationResultType.Pending,
1341
+ type: exports.AuthenticationResultType.Failed,
1342
+ reason: exports.AuthenticationFailureReason.InProgress,
1298
1343
  };
1299
1344
  }
1300
1345
  else if (seconds.value > 0) {
1301
- ui.useNotification('error', 'Ошибка', 'Нужно подождать перед повторной отправкой кода подтверждения.');
1302
1346
  return {
1303
- type: exports.AuthenticationResultType.Pending,
1347
+ type: exports.AuthenticationResultType.Failed,
1348
+ reason: exports.AuthenticationFailureReason.Cooldown,
1304
1349
  };
1305
1350
  }
1306
1351
  else if (!form.value.phone.number || !form.value.phone.country) {
1307
- ui.useNotification('error', 'Ошибка', 'Нужно указать номер телефона.');
1308
1352
  return {
1309
1353
  type: exports.AuthenticationResultType.Validation,
1310
- data: 'phone',
1354
+ reason: exports.AuthenticationFailureReason.PhoneRequired,
1311
1355
  };
1312
1356
  }
1313
1357
  active.value = true;
@@ -1319,14 +1363,15 @@ function useResend(form, active) {
1319
1363
  };
1320
1364
  }
1321
1365
  catch (e) {
1322
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Нужно подождать перед повторной отправкой кода подтверждения.'));
1366
+ return {
1367
+ type: exports.AuthenticationResultType.Failed,
1368
+ reason: exports.AuthenticationFailureReason.ApiError,
1369
+ error: api.getApiError(e),
1370
+ };
1323
1371
  }
1324
1372
  finally {
1325
1373
  active.value = false;
1326
1374
  }
1327
- return {
1328
- type: exports.AuthenticationResultType.Failed,
1329
- };
1330
1375
  };
1331
1376
  return {
1332
1377
  seconds,
@@ -1339,28 +1384,26 @@ function useConfirm(form, active, emit) {
1339
1384
  const confirm = async (withPassword = false) => {
1340
1385
  if (active.value) {
1341
1386
  return {
1342
- type: exports.AuthenticationResultType.Pending,
1387
+ type: exports.AuthenticationResultType.Failed,
1388
+ reason: exports.AuthenticationFailureReason.InProgress,
1343
1389
  };
1344
1390
  }
1345
1391
  else if (!form.value.phone.number || !form.value.phone.country) {
1346
- ui.useNotification('error', 'Ошибка', 'Нужно указать номер телефона.');
1347
1392
  return {
1348
1393
  type: exports.AuthenticationResultType.Validation,
1349
- data: 'phone',
1394
+ reason: exports.AuthenticationFailureReason.PhoneRequired,
1350
1395
  };
1351
1396
  }
1352
1397
  else if (!form.value.confirmation_code) {
1353
- ui.useNotification('error', 'Ошибка', 'Нужно указать код из SMS.');
1354
1398
  return {
1355
1399
  type: exports.AuthenticationResultType.Validation,
1356
- data: 'confirmation_code',
1400
+ reason: exports.AuthenticationFailureReason.CodeRequired,
1357
1401
  };
1358
1402
  }
1359
1403
  else if (withPassword && !form.value.password) {
1360
- ui.useNotification('error', 'Ошибка', 'Нужно указать новый пароль.');
1361
1404
  return {
1362
1405
  type: exports.AuthenticationResultType.Validation,
1363
- data: 'password',
1406
+ reason: exports.AuthenticationFailureReason.PasswordRequired,
1364
1407
  };
1365
1408
  }
1366
1409
  active.value = true;
@@ -1368,7 +1411,6 @@ function useConfirm(form, active, emit) {
1368
1411
  const result = await api.confirm(form.value.phone, form.value.confirmation_code, withPassword ? form.value.password : null);
1369
1412
  const store = useCustomerStore();
1370
1413
  await store.setToken(result.token);
1371
- ui.useNotification('success', 'Успешное подтверждение телефона', 'Вы успешно подтвердили телефон и вошли в свой аккаунт.');
1372
1414
  emit(exports.AuthenticationEvent.Completed);
1373
1415
  return {
1374
1416
  type: exports.AuthenticationResultType.Completed,
@@ -1376,20 +1418,21 @@ function useConfirm(form, active, emit) {
1376
1418
  };
1377
1419
  }
1378
1420
  catch (e) {
1379
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Указан неправильный код подтверждения.'));
1380
1421
  if (api.getApiErrorCode(e) === 'auth.registration.password_required') {
1381
1422
  return {
1382
1423
  type: exports.AuthenticationResultType.Validation,
1383
- data: 'password',
1424
+ reason: exports.AuthenticationFailureReason.PasswordRequired,
1384
1425
  };
1385
1426
  }
1427
+ return {
1428
+ type: exports.AuthenticationResultType.Failed,
1429
+ reason: exports.AuthenticationFailureReason.ApiError,
1430
+ error: api.getApiError(e),
1431
+ };
1386
1432
  }
1387
1433
  finally {
1388
1434
  active.value = false;
1389
1435
  }
1390
- return {
1391
- type: exports.AuthenticationResultType.Failed,
1392
- };
1393
1436
  };
1394
1437
  return {
1395
1438
  confirm,
@@ -1410,14 +1453,10 @@ const usePhoneConfirmation = (form, emit) => {
1410
1453
  };
1411
1454
 
1412
1455
  function useDeliveryAddressesList(errorHandler) {
1413
- return usePaginatedLoader(api.getCustomerAddresses, getApiErrorHandler(errorHandler, function (e) {
1414
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить адреса доставки.'));
1415
- }));
1456
+ return usePaginatedLoader(api.getCustomerAddresses, getApiErrorHandler(errorHandler, 'useDeliveryAddressesList', 'Unable to load delivery addresses list.'));
1416
1457
  }
1417
1458
  function useDeliveryAddressDestroyer(errorHandler) {
1418
- return useDataDestroyer(api.deleteAddress, getApiErrorHandler(errorHandler, function (e) {
1419
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось удалить адрес доставки.'));
1420
- }));
1459
+ return useDataDestroyer(api.deleteAddress, getApiErrorHandler(errorHandler, 'useDeliveryAddressDestroyer', 'Unable to delete delivery address.'));
1421
1460
  }
1422
1461
  function useEditAddressForm(address) {
1423
1462
  var _a, _b;
@@ -1447,12 +1486,18 @@ function useEditAddressForm(address) {
1447
1486
  const form = vue.ref(addressFields);
1448
1487
  const save = async () => {
1449
1488
  if (saving.value) {
1450
- return false;
1489
+ return {
1490
+ type: exports.AddressResultType.Failed,
1491
+ reason: exports.AddressResultReason.InProgress,
1492
+ };
1451
1493
  }
1452
1494
  const { errors, data } = useAddressFormValue(form.value, address.resolver, address);
1453
1495
  if (errors.length > 0) {
1454
- ui.useNotification('error', 'Ошибка', errors[0]);
1455
- return false;
1496
+ return {
1497
+ type: exports.AddressResultType.Failed,
1498
+ reason: exports.AddressResultReason.Validation,
1499
+ data: errors,
1500
+ };
1456
1501
  }
1457
1502
  saving.value = true;
1458
1503
  try {
@@ -1462,16 +1507,20 @@ function useEditAddressForm(address) {
1462
1507
  name: form.value.name,
1463
1508
  },
1464
1509
  });
1465
- ui.useNotification('success', 'Адрес сохранён', 'Адрес был успешно сохранён!');
1466
- return true;
1510
+ return {
1511
+ type: exports.AddressResultType.Completed,
1512
+ };
1467
1513
  }
1468
1514
  catch (e) {
1469
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось сохранить адрес. Повторите попытку.'));
1515
+ return {
1516
+ type: exports.AddressResultType.Failed,
1517
+ reason: exports.AddressResultReason.ApiError,
1518
+ error: api.getApiError(e),
1519
+ };
1470
1520
  }
1471
1521
  finally {
1472
1522
  saving.value = false;
1473
1523
  }
1474
- return false;
1475
1524
  };
1476
1525
  return {
1477
1526
  form,
@@ -1491,25 +1540,17 @@ function useCustomer() {
1491
1540
  }
1492
1541
 
1493
1542
  function useOrdersList(errorHandler) {
1494
- return usePaginatedLoader(api.getCustomerOrders, getApiErrorHandler(errorHandler, function (e) {
1495
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить список заказов.'));
1496
- }));
1543
+ return usePaginatedLoader(api.getCustomerOrders, getApiErrorHandler(errorHandler, 'useOrdersList', 'Unable to load orders list.'));
1497
1544
  }
1498
1545
  function useOrderItem(errorHandler) {
1499
- return useItemLoader(api.getOrder, getApiErrorHandler(errorHandler, function (e) {
1500
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Заказ не найден.'));
1501
- }));
1546
+ return useItemLoader(api.getOrder, getApiErrorHandler(errorHandler, 'useOrderItem', 'Unable to load order.'));
1502
1547
  }
1503
1548
 
1504
1549
  function usePaymentMethodsList(errorHandler) {
1505
- return usePaginatedLoader(api.getCustomerPaymentMethods, getApiErrorHandler(errorHandler, function (e) {
1506
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить способы оплаты.'));
1507
- }));
1550
+ return usePaginatedLoader(api.getCustomerPaymentMethods, getApiErrorHandler(errorHandler, 'usePaymentMethodsList', 'Unable to load payment methods.'));
1508
1551
  }
1509
1552
  function usePaymentMethodDestroyer(errorHandler) {
1510
- return useDataDestroyer(api.deleteCustomerPaymentMethod, getApiErrorHandler(errorHandler, function (e) {
1511
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось удалить способ оплаты.'));
1512
- }));
1553
+ return useDataDestroyer(api.deleteCustomerPaymentMethod, getApiErrorHandler(errorHandler, 'usePaymentMethodDestroyer', 'Unable to delete payment method.'));
1513
1554
  }
1514
1555
 
1515
1556
  function getFirstMedium(media, sizes = ['large', 'medium'], preferWebp = true) {
@@ -1547,15 +1588,35 @@ function getFirstMedium(media, sizes = ['large', 'medium'], preferWebp = true) {
1547
1588
  }
1548
1589
 
1549
1590
  function useOffersList(errorHandler) {
1550
- return usePaginatedLoader(api.getOffers, getApiErrorHandler(errorHandler, function (e) {
1551
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить список акций.'));
1552
- }));
1591
+ return usePaginatedLoader(api.getOffers, getApiErrorHandler(errorHandler, 'useOffersList', 'Unable to load offers list.'));
1553
1592
  }
1554
1593
  function useOfferItem(errorHandler) {
1555
- return useItemLoader(api.getOffer, getApiErrorHandler(errorHandler, function (e) {
1556
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить акцию.'));
1557
- }));
1558
- }
1594
+ return useItemLoader(api.getOffer, getApiErrorHandler(errorHandler, 'useOfferItem', 'Unable to load offer.'));
1595
+ }
1596
+
1597
+ exports.OrderCheckoutResultType = void 0;
1598
+ (function (OrderCheckoutResultType) {
1599
+ OrderCheckoutResultType["Validation"] = "validation";
1600
+ OrderCheckoutResultType["Completed"] = "completed";
1601
+ OrderCheckoutResultType["Failed"] = "failed";
1602
+ })(exports.OrderCheckoutResultType || (exports.OrderCheckoutResultType = {}));
1603
+ exports.OrderCheckoutResultReason = void 0;
1604
+ (function (OrderCheckoutResultReason) {
1605
+ OrderCheckoutResultReason["InProgress"] = "in_progress";
1606
+ OrderCheckoutResultReason["Cooldown"] = "cooldown";
1607
+ OrderCheckoutResultReason["ApiError"] = "api_error";
1608
+ OrderCheckoutResultReason["OrderNotReady"] = "order_not_ready";
1609
+ OrderCheckoutResultReason["PhoneRequired"] = "phone_required";
1610
+ OrderCheckoutResultReason["FirstNameRequired"] = "first_name_required";
1611
+ OrderCheckoutResultReason["CodeRequired"] = "code_required";
1612
+ OrderCheckoutResultReason["AddressError"] = "address_error";
1613
+ })(exports.OrderCheckoutResultReason || (exports.OrderCheckoutResultReason = {}));
1614
+ exports.BillSuggestionType = void 0;
1615
+ (function (BillSuggestionType) {
1616
+ BillSuggestionType["Bill"] = "bill";
1617
+ BillSuggestionType["NoChange"] = "no_change";
1618
+ BillSuggestionType["Custom"] = "custom";
1619
+ })(exports.BillSuggestionType || (exports.BillSuggestionType = {}));
1559
1620
 
1560
1621
  function getUpdatedVariants(currentOrder, order) {
1561
1622
  var _a, _b;
@@ -1702,7 +1763,9 @@ const useOrderStore = pinia.defineStore({
1702
1763
  return await this.load(storeId, cityId, order.id, order.token);
1703
1764
  }
1704
1765
  catch (e) {
1705
- ui.useNotification('error', 'Ошибка инициализации заказа', 'Не удалось инициализировать заказ. Обновите страницу.');
1766
+ events.useOrderInitializationFailed().publish({
1767
+ error: api.getApiError(e),
1768
+ });
1706
1769
  }
1707
1770
  return false;
1708
1771
  },
@@ -1737,7 +1800,14 @@ const useOrderStore = pinia.defineStore({
1737
1800
  return true;
1738
1801
  }
1739
1802
  catch (e) {
1740
- ui.useNotification('error', 'Товар не добавлен', api.getApiErrorMessage(e, 'Не удалось добавить товар в корзину. Повторите попытку'));
1803
+ events.useProductQuantityIncreaseFailed().publish({
1804
+ error: api.getApiError(e),
1805
+ order: this.order,
1806
+ productVariantId,
1807
+ quantity,
1808
+ modifiers,
1809
+ promotion,
1810
+ });
1741
1811
  }
1742
1812
  return false;
1743
1813
  },
@@ -1767,7 +1837,14 @@ const useOrderStore = pinia.defineStore({
1767
1837
  return true;
1768
1838
  }
1769
1839
  catch (e) {
1770
- ui.useNotification('error', 'Товар не удалён', api.getApiErrorMessage(e, 'Не удалось удалить товар из корзины. Повторите попытку'));
1840
+ events.useProductQuantityDecreaseFailed().publish({
1841
+ error: api.getApiError(e),
1842
+ order: this.order,
1843
+ productVariantId,
1844
+ quantity,
1845
+ modifiers,
1846
+ promotion,
1847
+ });
1771
1848
  }
1772
1849
  return false;
1773
1850
  },
@@ -1910,40 +1987,62 @@ function useCheckoutConfirmation(order) {
1910
1987
  }));
1911
1988
  const confirm = async () => {
1912
1989
  if (confirming.value) {
1913
- return null;
1990
+ return {
1991
+ type: exports.OrderCheckoutResultType.Failed,
1992
+ reason: exports.OrderCheckoutResultReason.InProgress,
1993
+ };
1914
1994
  }
1915
1995
  else if (!form.value.code) {
1916
- ui.useNotification('error', 'Ошибка', 'Нужно указать код из SMS.');
1917
- return null;
1996
+ return {
1997
+ type: exports.OrderCheckoutResultType.Validation,
1998
+ reason: exports.OrderCheckoutResultReason.CodeRequired,
1999
+ };
1918
2000
  }
1919
2001
  confirming.value = true;
1920
2002
  try {
1921
- return await api.confirmOrder(credentials.value, form.value);
2003
+ const response = await api.confirmOrder(credentials.value, form.value);
2004
+ return {
2005
+ type: exports.OrderCheckoutResultType.Completed,
2006
+ data: response,
2007
+ };
1922
2008
  }
1923
2009
  catch (e) {
1924
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось подтвердить заказ.'));
2010
+ return {
2011
+ type: exports.OrderCheckoutResultType.Failed,
2012
+ reason: exports.OrderCheckoutResultReason.ApiError,
2013
+ error: api.getApiError(e),
2014
+ };
1925
2015
  }
1926
2016
  finally {
1927
2017
  confirming.value = false;
1928
2018
  }
1929
- return null;
1930
2019
  };
1931
2020
  const resendCode = async () => {
1932
2021
  if (resending.value) {
1933
- return;
2022
+ return {
2023
+ type: exports.OrderCheckoutResultType.Failed,
2024
+ reason: exports.OrderCheckoutResultReason.InProgress,
2025
+ };
1934
2026
  }
1935
2027
  resending.value = true;
1936
2028
  try {
1937
2029
  const result = await api.resendOrderConfirmationCode(credentials.value);
1938
2030
  if (result.success) {
1939
- ui.useNotification('success', 'Код выслан', 'Код был повторно выслан на ваш телефон.');
1940
- }
1941
- else {
1942
- ui.useNotification('error', 'Ошибка', 'Не удалось выслать код подтверждения. Повторите попытку позднее.');
2031
+ return {
2032
+ type: exports.OrderCheckoutResultType.Completed,
2033
+ };
1943
2034
  }
2035
+ return {
2036
+ type: exports.OrderCheckoutResultType.Failed,
2037
+ reason: exports.OrderCheckoutResultReason.Cooldown,
2038
+ };
1944
2039
  }
1945
2040
  catch (e) {
1946
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось выслать код подтверждения.'));
2041
+ return {
2042
+ type: exports.OrderCheckoutResultType.Failed,
2043
+ reason: exports.OrderCheckoutResultReason.ApiError,
2044
+ error: api.getApiError(e),
2045
+ };
1947
2046
  }
1948
2047
  finally {
1949
2048
  resending.value = false;
@@ -1986,26 +2085,43 @@ function useCustomerCheckoutForm(emit) {
1986
2085
  }
1987
2086
  const save = async () => {
1988
2087
  if (!credentials.value) {
1989
- return;
2088
+ return {
2089
+ type: exports.OrderCheckoutResultType.Failed,
2090
+ reason: exports.OrderCheckoutResultReason.OrderNotReady,
2091
+ };
1990
2092
  }
1991
2093
  else if (saving.value) {
1992
- return;
2094
+ return {
2095
+ type: exports.OrderCheckoutResultType.Failed,
2096
+ reason: exports.OrderCheckoutResultReason.InProgress,
2097
+ };
1993
2098
  }
1994
2099
  else if (!form.value.phone.number || !form.value.phone.country) {
1995
- ui.useNotification('error', 'Ошибка', 'Нужно указать номер телефона.');
1996
- return;
2100
+ return {
2101
+ type: exports.OrderCheckoutResultType.Validation,
2102
+ reason: exports.OrderCheckoutResultReason.PhoneRequired,
2103
+ };
1997
2104
  }
1998
2105
  else if (!form.value.first_name) {
1999
- ui.useNotification('error', 'Ошибка', 'Нужно указать имя.');
2000
- return;
2106
+ return {
2107
+ type: exports.OrderCheckoutResultType.Validation,
2108
+ reason: exports.OrderCheckoutResultReason.FirstNameRequired,
2109
+ };
2001
2110
  }
2002
2111
  saving.value = true;
2003
2112
  try {
2004
2113
  await api.setOrderCheckoutCustomer(credentials.value, form.value);
2005
2114
  emit('completed');
2115
+ return {
2116
+ type: exports.OrderCheckoutResultType.Completed,
2117
+ };
2006
2118
  }
2007
2119
  catch (e) {
2008
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось сохранить контактные данные.'));
2120
+ return {
2121
+ type: exports.OrderCheckoutResultType.Failed,
2122
+ reason: exports.OrderCheckoutResultReason.ApiError,
2123
+ error: api.getApiError(e),
2124
+ };
2009
2125
  }
2010
2126
  finally {
2011
2127
  saving.value = false;
@@ -2057,7 +2173,7 @@ function useOrderVariants() {
2057
2173
  variants,
2058
2174
  };
2059
2175
  }
2060
- const useVariantControls = (variant, modifiers, modifiersHash, promotion) => {
2176
+ const useVariantControls = (variant, modifiers, modifiersHash, promotion, callback) => {
2061
2177
  const { order } = pinia.storeToRefs(useOrderStore());
2062
2178
  const { add: addVariant, remove: removeVariant } = useOrderStore();
2063
2179
  const loading = vue.ref(false);
@@ -2091,10 +2207,9 @@ const useVariantControls = (variant, modifiers, modifiersHash, promotion) => {
2091
2207
  }
2092
2208
  else {
2093
2209
  result = await removeVariant(variant.value.id, quantity, modifiers.value, promotion.value);
2094
- ui.useNotification('success', 'Товар удалён', `Товар${variant.value.name ? ` «${variant.value.name}»` : ''} удалён из корзины!`);
2095
2210
  }
2096
- if (result) {
2097
- ui.useNotification('success', `Товар ${type === 'add' ? 'добавлен' : 'удалён'}`, `Товар${variant.value.name ? ` «${variant.value.name}»` : ''} ${type === 'add' ? 'добавлен в корзину' : 'удалён из корзины'}!`);
2211
+ if (typeof callback === 'function') {
2212
+ callback(type, result);
2098
2213
  }
2099
2214
  loading.value = false;
2100
2215
  };
@@ -2179,7 +2294,7 @@ function getDeliveryPayload(form, addressesResolver) {
2179
2294
  data.stock_id = form.pickup.stock_id;
2180
2295
  }
2181
2296
  else {
2182
- errors.push('Нужно выбрать точку самовывоза.');
2297
+ errors.push(exports.AddressFormValueError.StockRequired);
2183
2298
  }
2184
2299
  }
2185
2300
  else if (form.method === 'on_premise') {
@@ -2187,13 +2302,13 @@ function getDeliveryPayload(form, addressesResolver) {
2187
2302
  data.stock_id = form.on_premise.stock_id;
2188
2303
  }
2189
2304
  else {
2190
- errors.push('Нужно выбрать точку самовывоза.');
2305
+ errors.push(exports.AddressFormValueError.StockRequired);
2191
2306
  }
2192
2307
  if (form.on_premise.table) {
2193
2308
  data.on_premise = { table: form.on_premise.table };
2194
2309
  }
2195
2310
  else {
2196
- errors.push('Нужно указать номер стола.');
2311
+ errors.push(exports.AddressFormValueError.TableRequired);
2197
2312
  }
2198
2313
  }
2199
2314
  else if (form.method === 'delivery') {
@@ -2260,23 +2375,39 @@ function useDeliveryCheckoutForm(emit) {
2260
2375
  });
2261
2376
  const save = async () => {
2262
2377
  if (!credentials.value || !addressesResolver.value) {
2263
- return;
2378
+ return {
2379
+ type: exports.OrderCheckoutResultType.Failed,
2380
+ reason: exports.OrderCheckoutResultReason.OrderNotReady,
2381
+ };
2264
2382
  }
2265
2383
  else if (saving.value) {
2266
- return;
2384
+ return {
2385
+ type: exports.OrderCheckoutResultType.Failed,
2386
+ reason: exports.OrderCheckoutResultReason.InProgress,
2387
+ };
2267
2388
  }
2268
2389
  const { data, errors } = getDeliveryPayload(form.value, addressesResolver.value);
2269
2390
  if (errors.length > 0) {
2270
- ui.useNotification('error', 'Ошибка', errors[0]);
2271
- return;
2391
+ return {
2392
+ type: exports.OrderCheckoutResultType.Validation,
2393
+ reason: exports.OrderCheckoutResultReason.AddressError,
2394
+ data: errors,
2395
+ };
2272
2396
  }
2273
2397
  saving.value = true;
2274
2398
  try {
2275
2399
  await api.setOrderCheckoutDelivery(credentials.value, data);
2276
2400
  emit('completed');
2401
+ return {
2402
+ type: exports.OrderCheckoutResultType.Completed,
2403
+ };
2277
2404
  }
2278
2405
  catch (e) {
2279
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось сохранить способ доставки.'));
2406
+ return {
2407
+ type: exports.OrderCheckoutResultType.Failed,
2408
+ reason: exports.OrderCheckoutResultReason.ApiError,
2409
+ error: api.getApiError(e),
2410
+ };
2280
2411
  }
2281
2412
  finally {
2282
2413
  saving.value = false;
@@ -2302,7 +2433,6 @@ function getPaymentMethod(settings) {
2302
2433
  return available[0];
2303
2434
  }
2304
2435
  function useBillSuggestions(unpaidAmount, staticAmounts = [10, 50, 200, 5000], availableBills = [100, 500, 1000]) {
2305
- const { totalPrice } = useTotalPrice();
2306
2436
  const getClosestMultipleOf = (price, amount) => Math.ceil(price / amount) * amount;
2307
2437
  const suggestions = vue.computed(() => {
2308
2438
  const items = new Set([
@@ -2313,19 +2443,16 @@ function useBillSuggestions(unpaidAmount, staticAmounts = [10, 50, 200, 5000], a
2313
2443
  const bills = [...items]
2314
2444
  .filter((suggestion) => suggestion > unpaidAmount.value)
2315
2445
  .sort((first, second) => (first - second))
2316
- .map((amount) => {
2317
- var _a, _b;
2318
- return ({
2319
- value: amount,
2320
- label: `${(_a = totalPrice.value) === null || _a === void 0 ? void 0 : _a.currency.prefix}${amount}${(_b = totalPrice.value) === null || _b === void 0 ? void 0 : _b.currency.suffix}`,
2321
- });
2322
- });
2446
+ .map((amount) => ({
2447
+ value: amount,
2448
+ type: exports.BillSuggestionType.Bill,
2449
+ }));
2323
2450
  bills.unshift({
2324
- label: 'Без сдачи',
2451
+ type: exports.BillSuggestionType.NoChange,
2325
2452
  value: '',
2326
2453
  });
2327
2454
  bills.push({
2328
- label: 'Другая',
2455
+ type: exports.BillSuggestionType.Custom,
2329
2456
  value: 'custom',
2330
2457
  });
2331
2458
  return bills;
@@ -2356,7 +2483,6 @@ function useBonusesPreviewChecker(order, credentials, bonuses, setBonuses) {
2356
2483
  unpaidAmount.value = preview.unpaid;
2357
2484
  if (parseFloat(bonuses.value) > parseFloat(preview.bonuses.trimmed)) {
2358
2485
  setBonuses(preview.bonuses.trimmed);
2359
- ui.useNotification('warning', 'Сумма бонусов изменена', 'Вы указали сумму бонусов, превышающую лимит списания. Мы изменили сумму на максимально доступную.');
2360
2486
  }
2361
2487
  }
2362
2488
  catch (e) {
@@ -2409,18 +2535,31 @@ function useDeliveryPaymentsForm(emit) {
2409
2535
  });
2410
2536
  const save = async () => {
2411
2537
  if (!credentials.value) {
2412
- return;
2538
+ return {
2539
+ type: exports.OrderCheckoutResultType.Failed,
2540
+ reason: exports.OrderCheckoutResultReason.OrderNotReady,
2541
+ };
2413
2542
  }
2414
2543
  else if (saving.value) {
2415
- return;
2544
+ return {
2545
+ type: exports.OrderCheckoutResultType.Failed,
2546
+ reason: exports.OrderCheckoutResultReason.InProgress,
2547
+ };
2416
2548
  }
2417
2549
  const payments = getPaymentsPayload(form.value);
2418
2550
  try {
2419
2551
  await api.setOrderCheckoutPayment(credentials.value, { payments });
2420
2552
  emit('completed');
2553
+ return {
2554
+ type: exports.OrderCheckoutResultType.Completed,
2555
+ };
2421
2556
  }
2422
2557
  catch (e) {
2423
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось сохранить способ оплаты.'));
2558
+ return {
2559
+ type: exports.OrderCheckoutResultType.Failed,
2560
+ reason: exports.OrderCheckoutResultReason.ApiError,
2561
+ error: api.getApiError(e),
2562
+ };
2424
2563
  }
2425
2564
  finally {
2426
2565
  saving.value = false;
@@ -2453,16 +2592,22 @@ function useCheckoutSummary(emit) {
2453
2592
  const saving = vue.ref(false);
2454
2593
  const save = async () => {
2455
2594
  if (!credentials.value) {
2456
- return;
2595
+ return {
2596
+ type: exports.OrderCheckoutResultType.Failed,
2597
+ reason: exports.OrderCheckoutResultReason.OrderNotReady,
2598
+ };
2457
2599
  }
2458
2600
  else if (saving.value) {
2459
- return;
2601
+ return {
2602
+ type: exports.OrderCheckoutResultType.Failed,
2603
+ reason: exports.OrderCheckoutResultReason.InProgress,
2604
+ };
2460
2605
  }
2461
2606
  const payload = {
2462
2607
  notes: form.value.notes,
2463
2608
  };
2464
2609
  if (hasPersonsCount.value && form.value.persons_count) {
2465
- payload.notes = `Персон: ${form.value.persons_count}\n\n${payload.notes}`.trim();
2610
+ payload.persons_count = form.value.persons_count;
2466
2611
  }
2467
2612
  saving.value = true;
2468
2613
  try {
@@ -2476,9 +2621,16 @@ function useCheckoutSummary(emit) {
2476
2621
  if (store.value && city.value) {
2477
2622
  await orderStore.recreate(store.value.id, city.value.id);
2478
2623
  }
2624
+ return {
2625
+ type: exports.OrderCheckoutResultType.Completed,
2626
+ };
2479
2627
  }
2480
2628
  catch (e) {
2481
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось оформить заказ.'));
2629
+ return {
2630
+ type: exports.OrderCheckoutResultType.Failed,
2631
+ reason: exports.OrderCheckoutResultReason.ApiError,
2632
+ error: api.getApiError(e),
2633
+ };
2482
2634
  }
2483
2635
  finally {
2484
2636
  saving.value = false;
@@ -2700,11 +2852,7 @@ function useModifiers(product, variant, recalculate) {
2700
2852
  modifiers.value = getModifiers(product, variant);
2701
2853
  });
2702
2854
  vue.watch(selectedModifiers, async () => {
2703
- const hash = await recalculate(selectedModifiers);
2704
- if (hash === null) {
2705
- return;
2706
- }
2707
- modifiersHash.value = hash;
2855
+ modifiersHash.value = await recalculate(selectedModifiers);
2708
2856
  });
2709
2857
  return {
2710
2858
  modifiers,
@@ -2867,9 +3015,7 @@ function useVariant(variants) {
2867
3015
  }
2868
3016
 
2869
3017
  function useProductItem(errorHandler) {
2870
- return useItemLoader(api.getProduct, getApiErrorHandler(errorHandler, function (e) {
2871
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Товар не найден.'));
2872
- }));
3018
+ return useItemLoader(api.getProduct, getApiErrorHandler(errorHandler, 'useProductItem', 'Unable to load product.'));
2873
3019
  }
2874
3020
  function useProductCard(item) {
2875
3021
  var _a;
@@ -2904,9 +3050,7 @@ function useProductCard(item) {
2904
3050
  }
2905
3051
 
2906
3052
  function useProductsPricesRange(categoryId, errorHandler) {
2907
- return useDataLoader(async () => api.getProductsPricesRange(categoryId), getApiErrorHandler(errorHandler, function (e) {
2908
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить диапазон цен.'));
2909
- }));
3053
+ return useDataLoader(async () => api.getProductsPricesRange(categoryId), getApiErrorHandler(errorHandler, 'useProductsPricesRange', 'Unable to load product prices range.'));
2910
3054
  }
2911
3055
 
2912
3056
  function useFeaturesFilters(categoryId, values) {
@@ -3104,9 +3248,7 @@ function getCategoryIdFromSource(source) {
3104
3248
  return source.id;
3105
3249
  }
3106
3250
  function useProductsList(config, errorHandler) {
3107
- const productsLoader = usePaginatedLoader(api.getProducts, getApiErrorHandler(errorHandler, function (e) {
3108
- ui.useNotification('error', 'Ошибка', api.getApiErrorMessage(e, 'Не удалось загрузить товары.'));
3109
- }));
3251
+ const productsLoader = usePaginatedLoader(api.getProducts, getApiErrorHandler(errorHandler, 'useProductsList', 'Unable to load products list.'));
3110
3252
  const store = useStoreStore();
3111
3253
  const cityId = vue.computed(() => store.cityId);
3112
3254
  const sorting = vue.ref(config.value.sorting || exports.ProductsSorting.Manual);