@influenzanet/case-web-app-core 2.9.2-staging → 2.9.4-staging

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.
@@ -0,0 +1,13 @@
1
+ export declare const BACKEND_ERRORS: {
2
+ readonly ACTION_FAILED: "action failed";
3
+ readonly PHONE_NOT_VALID: "phone not valid";
4
+ readonly PHONE_ALREADY_TAKEN: "phone number already taken";
5
+ readonly PHONE_ALREADY_VERIFIED: "phone number already verified";
6
+ readonly NO_PHONE_TO_EDIT: "user has no phone number to edit";
7
+ readonly WHATSAPP_UNAVAILABLE: "WhatsApp is not configured";
8
+ readonly SEND_FAILED: "failed to send verification code";
9
+ readonly TOO_MANY_ATTEMPTS: "too many attempts, phone number removed";
10
+ readonly CODE_EXPIRED: "verification code expired";
11
+ readonly INVALID_CODE: "invalid verification code";
12
+ readonly RATE_LIMITED: "too many phone verification attempts, try again later";
13
+ };
@@ -45,6 +45,7 @@ export interface ContactPreferences {
45
45
  sendNewsletterTo: string[];
46
46
  subscribedToWeekly: boolean;
47
47
  receiveWeeklyMessageDayOfWeek: number;
48
+ preferredChannels?: string[];
48
49
  }
49
50
  interface ContactInfoBase {
50
51
  id: string;
@@ -1,5 +1,3 @@
1
- import React from 'react';
2
- interface ChangeNotificationsProps {
3
- }
4
- declare const ChangeNotifications: React.FC<ChangeNotificationsProps>;
1
+ /// <reference types="react" />
2
+ declare const ChangeNotifications: () => JSX.Element;
5
3
  export default ChangeNotifications;
@@ -1,9 +1,4 @@
1
1
  import React from 'react';
2
- export declare const COUNTRY_CODES: {
3
- code: string;
4
- country: string;
5
- name: string;
6
- }[];
7
2
  interface PhoneNumberInputProps {
8
3
  value: string;
9
4
  onChange: (fullPhoneNumber: string) => void;
package/build/index.es.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
2
2
  import * as React$1 from 'react';
3
3
  import React__default$1, { Component, useEffect, useRef, useState, useCallback, useContext as useContext$1, useMemo, useLayoutEffect, useReducer, createContext, forwardRef as forwardRef$2, useImperativeHandle, createElement, Suspense } from 'react';
4
- import { LoadingPlaceholder, SimpleHeader, Footer, Avatar, containerClassName, ChevronUp, ChevronDown, Dialog, defaultDialogPaddingXClass, Checkbox, AlertBox, TextField, DialogBtn, useFetchTextFile, SelectField, TextLink, ConsentDialog, ConfirmDialog, EditBtn, AvatarSelector, SurveyList as SurveyList$1, getExternalOrLocalContentURL, ReportList as ReportList$1, TitleBar, ComposedLineAndScatterChartLoader, MapWithTimeSliderLoader, LinkList, handleOpenExternalPage, LogoCredits, SimpleCard, AccordionList, LoginCard, VideoPlayer, ImageContainer, ActionCard, MarkdownRenderer, ImageCard, TeaserImage, MarkdownLoader, getLocalizedString, SurveyView } from '@influenzanet/case-web-ui';
4
+ import { LoadingPlaceholder, SimpleHeader, Footer, Avatar, containerClassName, ChevronUp, ChevronDown, Dialog, defaultDialogPaddingXClass, Checkbox, AlertBox, TextField, DialogBtn, useFetchTextFile, SelectField, TextLink, ConsentDialog, ConfirmDialog, AvatarSelector, EditBtn, SurveyList as SurveyList$1, getExternalOrLocalContentURL, ReportList as ReportList$1, TitleBar, ComposedLineAndScatterChartLoader, MapWithTimeSliderLoader, LinkList, handleOpenExternalPage, LogoCredits, SimpleCard, AccordionList, LoginCard, VideoPlayer, ImageContainer, ActionCard, MarkdownRenderer, ImageCard, TeaserImage, MarkdownLoader, getLocalizedString, SurveyView } from '@influenzanet/case-web-ui';
5
5
  import { useTranslation, Trans, initReactI18next } from 'react-i18next';
6
6
  import { useSelector, useDispatch } from 'react-redux';
7
7
  import { combineReducers, applyMiddleware, createStore, compose } from 'redux';
@@ -20857,47 +20857,149 @@ var parseBooleanFlag = function (v, empty, other) {
20857
20857
  return other;
20858
20858
  };
20859
20859
 
20860
- // Lista dei prefissi internazionali più comuni
20861
- var COUNTRY_CODES$1 = [
20862
- { code: '+39', country: 'IT', name: 'Italy' },
20863
- { code: '+1', country: 'US', name: 'United States' },
20864
- { code: '+44', country: 'GB', name: 'United Kingdom' },
20865
- { code: '+33', country: 'FR', name: 'France' },
20866
- { code: '+49', country: 'DE', name: 'Germany' },
20867
- { code: '+34', country: 'ES', name: 'Spain' },
20868
- { code: '+31', country: 'NL', name: 'Netherlands' },
20869
- { code: '+41', country: 'CH', name: 'Switzerland' },
20870
- { code: '+43', country: 'AT', name: 'Austria' },
20871
- { code: '+32', country: 'BE', name: 'Belgium' },
20872
- { code: '+351', country: 'PT', name: 'Portugal' },
20873
- { code: '+30', country: 'GR', name: 'Greece' },
20874
- { code: '+46', country: 'SE', name: 'Sweden' },
20875
- { code: '+47', country: 'NO', name: 'Norway' },
20876
- { code: '+45', country: 'DK', name: 'Denmark' },
20877
- { code: '+358', country: 'FI', name: 'Finland' },
20878
- { code: '+48', country: 'PL', name: 'Poland' },
20879
- { code: '+420', country: 'CZ', name: 'Czech Republic' },
20880
- { code: '+36', country: 'HU', name: 'Hungary' },
20881
- { code: '+40', country: 'RO', name: 'Romania' },
20882
- { code: '+359', country: 'BG', name: 'Bulgaria' },
20883
- { code: '+385', country: 'HR', name: 'Croatia' },
20884
- { code: '+386', country: 'SI', name: 'Slovenia' },
20885
- { code: '+372', country: 'EE', name: 'Estonia' },
20886
- { code: '+371', country: 'LV', name: 'Latvia' },
20887
- { code: '+370', country: 'LT', name: 'Lithuania' },
20888
- ];
20860
+ var COUNTRY_CODES = [
20861
+ {
20862
+ code: "+39",
20863
+ country: "IT",
20864
+ name: "Italy"
20865
+ },
20866
+ {
20867
+ code: "+1",
20868
+ country: "US",
20869
+ name: "United States"
20870
+ },
20871
+ {
20872
+ code: "+44",
20873
+ country: "GB",
20874
+ name: "United Kingdom"
20875
+ },
20876
+ {
20877
+ code: "+33",
20878
+ country: "FR",
20879
+ name: "France"
20880
+ },
20881
+ {
20882
+ code: "+49",
20883
+ country: "DE",
20884
+ name: "Germany"
20885
+ },
20886
+ {
20887
+ code: "+34",
20888
+ country: "ES",
20889
+ name: "Spain"
20890
+ },
20891
+ {
20892
+ code: "+31",
20893
+ country: "NL",
20894
+ name: "Netherlands"
20895
+ },
20896
+ {
20897
+ code: "+41",
20898
+ country: "CH",
20899
+ name: "Switzerland"
20900
+ },
20901
+ {
20902
+ code: "+43",
20903
+ country: "AT",
20904
+ name: "Austria"
20905
+ },
20906
+ {
20907
+ code: "+32",
20908
+ country: "BE",
20909
+ name: "Belgium"
20910
+ },
20911
+ {
20912
+ code: "+351",
20913
+ country: "PT",
20914
+ name: "Portugal"
20915
+ },
20916
+ {
20917
+ code: "+30",
20918
+ country: "GR",
20919
+ name: "Greece"
20920
+ },
20921
+ {
20922
+ code: "+46",
20923
+ country: "SE",
20924
+ name: "Sweden"
20925
+ },
20926
+ {
20927
+ code: "+47",
20928
+ country: "NO",
20929
+ name: "Norway"
20930
+ },
20931
+ {
20932
+ code: "+45",
20933
+ country: "DK",
20934
+ name: "Denmark"
20935
+ },
20936
+ {
20937
+ code: "+358",
20938
+ country: "FI",
20939
+ name: "Finland"
20940
+ },
20941
+ {
20942
+ code: "+48",
20943
+ country: "PL",
20944
+ name: "Poland"
20945
+ },
20946
+ {
20947
+ code: "+420",
20948
+ country: "CZ",
20949
+ name: "Czech Republic"
20950
+ },
20951
+ {
20952
+ code: "+36",
20953
+ country: "HU",
20954
+ name: "Hungary"
20955
+ },
20956
+ {
20957
+ code: "+40",
20958
+ country: "RO",
20959
+ name: "Romania"
20960
+ },
20961
+ {
20962
+ code: "+359",
20963
+ country: "BG",
20964
+ name: "Bulgaria"
20965
+ },
20966
+ {
20967
+ code: "+385",
20968
+ country: "HR",
20969
+ name: "Croatia"
20970
+ },
20971
+ {
20972
+ code: "+386",
20973
+ country: "SI",
20974
+ name: "Slovenia"
20975
+ },
20976
+ {
20977
+ code: "+372",
20978
+ country: "EE",
20979
+ name: "Estonia"
20980
+ },
20981
+ {
20982
+ code: "+371",
20983
+ country: "LV",
20984
+ name: "Latvia"
20985
+ },
20986
+ {
20987
+ code: "+370",
20988
+ country: "LT",
20989
+ name: "Lithuania"
20990
+ }
20991
+ ];
20992
+
20889
20993
  var PhoneNumberInput = function (_a) {
20890
20994
  var value = _a.value, onChange = _a.onChange, label = _a.label, placeholder = _a.placeholder, className = _a.className, autoFocus = _a.autoFocus, disabled = _a.disabled, error = _a.error, onBlur = _a.onBlur;
20891
20995
  var t = useTranslation(['dialogs']).t;
20892
- // Estrai il prefisso e il numero dal valore completo
20996
+ // Extract country code and number from the full value
20893
20997
  var _b = useState(function () {
20894
- // Cerca quale prefisso corrisponde al valore attuale
20895
- var matchingCode = COUNTRY_CODES$1.find(function (country) { return value.startsWith(country.code); });
20896
- return (matchingCode === null || matchingCode === void 0 ? void 0 : matchingCode.code) || '+39'; // Default Italia
20998
+ var matchingCode = COUNTRY_CODES.find(function (country) { return value.startsWith(country.code); });
20999
+ return (matchingCode === null || matchingCode === void 0 ? void 0 : matchingCode.code) || '+39';
20897
21000
  }), countryCode = _b[0], setCountryCode = _b[1];
20898
21001
  var _c = useState(function () {
20899
- // Rimuovi il prefisso dal numero
20900
- var matchingCode = COUNTRY_CODES$1.find(function (country) { return value.startsWith(country.code); });
21002
+ var matchingCode = COUNTRY_CODES.find(function (country) { return value.startsWith(country.code); });
20901
21003
  return matchingCode ? value.substring(matchingCode.code.length) : value;
20902
21004
  }), phoneNumber = _c[0], setPhoneNumber = _c[1];
20903
21005
  var handleCountryCodeChange = function (newCode) {
@@ -20905,12 +21007,12 @@ var PhoneNumberInput = function (_a) {
20905
21007
  onChange(newCode + phoneNumber);
20906
21008
  };
20907
21009
  var handlePhoneNumberChange = function (newNumber) {
20908
- // Rimuovi caratteri non numerici (eccetto spazi e trattini per leggibilità)
21010
+ // Strip non-numeric characters (keep spaces and hyphens for readability)
20909
21011
  var cleanNumber = newNumber.replace(/[^\d\s-]/g, '');
20910
21012
  setPhoneNumber(cleanNumber);
20911
21013
  onChange(countryCode + cleanNumber);
20912
21014
  };
20913
- return (jsxs("div", __assign({ className: className }, { children: [label && (jsx("label", __assign({ className: "form-label mb-1" }, { children: label }), void 0)), jsxs("div", __assign({ className: "d-flex" }, { children: [jsx(SelectField, { className: "me-2", style: { width: '120px', flexShrink: 0 }, value: countryCode, onChange: function (event) { return handleCountryCodeChange(event.target.value); }, disabled: disabled, values: COUNTRY_CODES$1.map(function (country) { return ({
21015
+ return (jsxs("div", __assign({ className: className }, { children: [label && (jsx("label", __assign({ className: "form-label mb-1" }, { children: label }), void 0)), jsxs("div", __assign({ className: "d-flex" }, { children: [jsx(SelectField, { className: "me-2", style: { width: '120px', flexShrink: 0 }, value: countryCode, onChange: function (event) { return handleCountryCodeChange(event.target.value); }, disabled: disabled, values: COUNTRY_CODES.map(function (country) { return ({
20914
21016
  code: country.code,
20915
21017
  label: "".concat(country.code, " ").concat(country.country)
20916
21018
  }); }) }, void 0), jsx(TextField, { type: "text", placeholder: placeholder || t('addPhone.phoneInputPlaceholder'), value: phoneNumber, autoFocus: autoFocus, autoComplete: "tel", disabled: disabled, className: "flex-grow-1", onChange: function (event) { return handlePhoneNumberChange(event.target.value); }, onBlur: onBlur, style: { marginBottom: 0 } }, void 0)] }), void 0), jsxs("small", __assign({ className: "text-muted mt-1 d-block" }, { children: [t('addPhone.completeNumber'), ": ", countryCode + phoneNumber] }), void 0), error && (jsx("div", __assign({ className: "text-danger mt-1 small" }, { children: error }), void 0))] }), void 0));
@@ -21540,7 +21642,7 @@ var ChangeLanguage = function (props) {
21540
21642
  : null, jsx(AlertBox, { type: "info", content: t('changeLanguage.info') }, void 0), jsx(AlertBox, { type: "danger", className: "mt-2", hide: !error, closable: true, onClose: function () { return setError(''); }, useIcon: true, content: error }, void 0), jsxs("div", __assign({ className: "d-flex flex-wrap" }, { children: [jsx(DialogBtn, { className: "mt-2 me-2", type: "button", color: "primary", outlined: true, label: t('changeLanguage.cancelBtn'), onClick: function () { return handleClose(); } }, void 0), jsx(DialogBtn, { className: "mt-2", type: "submit", color: "primary", loading: loading, disabled: loading, label: t('changeLanguage.confirmBtn'), onClick: function () { return changeLanguage(); } }, void 0)] }), void 0)] }), void 0) }), void 0));
21541
21643
  };
21542
21644
 
21543
- var ChangeNotifications = function (props) {
21645
+ var ChangeNotifications = function () {
21544
21646
  var _a, _b;
21545
21647
  var t = useTranslation(['dialogs']).t;
21546
21648
  var dispatch = useDispatch();
@@ -21551,11 +21653,11 @@ var ChangeNotifications = function (props) {
21551
21653
  var _d = useState(''), error = _d[0], setError = _d[1];
21552
21654
  var _e = useState(false), changed = _e[0], setChanged = _e[1];
21553
21655
  var _f = useState(false), weeklyEnabled = _f[0], setWeeklyEnabled = _f[1];
21554
- var _g = useState(false), weeklyPhone = _g[0], setWeeklyPhone = _g[1];
21555
- var _h = useState(false), newsletterEnabled = _h[0], setNewsletterEnabled = _h[1];
21656
+ var _g = useState(false), newsletterEnabled = _g[0], setNewsletterEnabled = _g[1];
21657
+ var _h = useState(true), channelEmail = _h[0], setChannelEmail = _h[1];
21658
+ var _j = useState(false), channelWhatsapp = _j[0], setChannelWhatsapp = _j[1];
21556
21659
  var phoneInfo = currentUser.contactInfos.find(function (info) { return info.type === 'phone'; });
21557
- var isPhonePresent = phoneInfo ? true : false;
21558
- var confirmedPhone = ((_b = phoneInfo === null || phoneInfo === void 0 ? void 0 : phoneInfo.confirmedAt) !== null && _b !== void 0 ? _b : 0) > 0 ? true : false;
21660
+ var confirmedPhone = ((_b = phoneInfo === null || phoneInfo === void 0 ? void 0 : phoneInfo.confirmedAt) !== null && _b !== void 0 ? _b : 0) > 0;
21559
21661
  useEffect(function () {
21560
21662
  if (open) {
21561
21663
  fetchUser();
@@ -21566,7 +21668,15 @@ var ChangeNotifications = function (props) {
21566
21668
  var _a;
21567
21669
  setNewsletterEnabled(currentUser.contactPreferences.subscribedToNewsletter ? true : false);
21568
21670
  setWeeklyEnabled(currentUser.contactPreferences.subscribedToWeekly ? true : false);
21569
- setWeeklyPhone(currentUser.contactPreferences.sendNewsletterTo.includes((_a = phoneInfo === null || phoneInfo === void 0 ? void 0 : phoneInfo.id) !== null && _a !== void 0 ? _a : '') ? true : false);
21671
+ var channels = (_a = currentUser.contactPreferences.preferredChannels) !== null && _a !== void 0 ? _a : [];
21672
+ if (channels.length === 0) {
21673
+ setChannelEmail(true);
21674
+ setChannelWhatsapp(false);
21675
+ }
21676
+ else {
21677
+ setChannelEmail(channels.includes('email'));
21678
+ setChannelWhatsapp(channels.includes('whatsapp'));
21679
+ }
21570
21680
  }, [currentUser]);
21571
21681
  var fetchUser = function () { return __awaiter(void 0, void 0, void 0, function () {
21572
21682
  var user, e_1;
@@ -21588,7 +21698,7 @@ var ChangeNotifications = function (props) {
21588
21698
  return [3 /*break*/, 4];
21589
21699
  case 3:
21590
21700
  e_1 = _a.sent();
21591
- console.log(e_1.respomse);
21701
+ console.error(e_1.response);
21592
21702
  setLoading(false);
21593
21703
  return [3 /*break*/, 4];
21594
21704
  case 4: return [2 /*return*/];
@@ -21600,21 +21710,32 @@ var ChangeNotifications = function (props) {
21600
21710
  setLoading(false);
21601
21711
  dispatch(dialogActions.closeDialog());
21602
21712
  };
21713
+ var handleChannelEmail = function (value) {
21714
+ if (!value && !channelWhatsapp)
21715
+ return;
21716
+ setChanged(true);
21717
+ setChannelEmail(value);
21718
+ };
21719
+ var handleChannelWhatsapp = function (value) {
21720
+ if (!value && !channelEmail)
21721
+ return;
21722
+ setChanged(true);
21723
+ setChannelWhatsapp(value);
21724
+ };
21603
21725
  var submitForm = function (event) { return __awaiter(void 0, void 0, void 0, function () {
21604
- var contactPreferences, user, e_2;
21726
+ var preferredChannels, contactPreferences, user, e_2;
21605
21727
  return __generator$1(this, function (_a) {
21606
21728
  switch (_a.label) {
21607
21729
  case 0:
21608
21730
  event.preventDefault();
21609
21731
  setLoading(true);
21610
21732
  setError("");
21611
- contactPreferences = __assign(__assign({}, currentUser.contactPreferences), { subscribedToWeekly: weeklyEnabled, subscribedToNewsletter: newsletterEnabled });
21612
- if (weeklyPhone && isPhonePresent && confirmedPhone && (phoneInfo === null || phoneInfo === void 0 ? void 0 : phoneInfo.id)) {
21613
- contactPreferences.sendNewsletterTo = __spreadArray$1(__spreadArray$1([], contactPreferences.sendNewsletterTo, true), [phoneInfo.id], false);
21614
- }
21615
- if (!weeklyPhone && isPhonePresent && confirmedPhone && (phoneInfo === null || phoneInfo === void 0 ? void 0 : phoneInfo.id)) {
21616
- contactPreferences.sendNewsletterTo = contactPreferences.sendNewsletterTo.filter(function (id) { return id !== phoneInfo.id; });
21617
- }
21733
+ preferredChannels = [];
21734
+ if (channelEmail)
21735
+ preferredChannels.push('email');
21736
+ if (channelWhatsapp)
21737
+ preferredChannels.push('whatsapp');
21738
+ contactPreferences = __assign(__assign({}, currentUser.contactPreferences), { subscribedToWeekly: weeklyEnabled, subscribedToNewsletter: newsletterEnabled, preferredChannels: preferredChannels });
21618
21739
  _a.label = 1;
21619
21740
  case 1:
21620
21741
  _a.trys.push([1, 3, , 4]);
@@ -21645,19 +21766,14 @@ var ChangeNotifications = function (props) {
21645
21766
  return (jsx(Dialog, __assign({ open: open, title: t('changeNotifications.title'), onClose: handleClose, ariaLabelledBy: "changeNotificationsDialogTitle" }, { children: jsx("div", __assign({ className: clsx(defaultDialogPaddingXClass, 'py-3', 'bg-grey-1') }, { children: jsxs("form", __assign({ onSubmit: submitForm }, { children: [jsx("label", __assign({ className: "mb-1 form-label", htmlFor: "weeklyEmail" }, { children: t('dialogs:changeNotifications.weeklyReminder.label') }), void 0), jsx(Checkbox, __assign({ id: "weeklyEmail", name: "weeklyEmail", checked: weeklyEnabled, onChange: function (value) {
21646
21767
  setChanged(true);
21647
21768
  setWeeklyEnabled(value);
21648
- } }, { children: weeklyEnabled ?
21649
- t('dialogs:changeNotifications.weeklyReminder.on') :
21650
- t('dialogs:changeNotifications.weeklyReminder.off') }), void 0), jsx("label", __assign({ className: "mb-1 form-label mt-2", htmlFor: "weeklyPhone" }, { children: t('dialogs:changeNotifications.weeklyReminderPhone.label') }), void 0), confirmedPhone && (jsx(Checkbox, __assign({ id: "weeklyPhone", name: "weeklyPhone", checked: weeklyPhone, onChange: function (value) {
21651
- setChanged(true);
21652
- setWeeklyPhone(value);
21653
- } }, { children: weeklyPhone ?
21654
- t('dialogs:changeNotifications.weeklyReminderPhone.on') :
21655
- t('dialogs:changeNotifications.weeklyReminderPhone.off') }), void 0)), (!confirmedPhone && !isPhonePresent) && (jsx(EditBtn, __assign({ onClick: function () { return dispatch(dialogActions.openDialogWithoutPayload({ type: 'addPhone' })); } }, { children: t('dialogs:changeNotifications.addPhone') }), void 0)), (!confirmedPhone && isPhonePresent) && (jsx(AlertBox, { className: "mt-2", type: "info", content: t('changeNotifications.phoneNotConfirmed') }, void 0)), (!confirmedPhone && isPhonePresent) && (jsx(Button$1, __assign({ className: "mt-2", onClick: function () { return dispatch(dialogActions.openDialogWithoutPayload({ type: 'addPhone' })); }, variant: "link" }, { children: t('dialogs:changeNotifications.verifyPhone') }), void 0)), jsx("label", __assign({ className: "mt-2 mb-1 form-label", htmlFor: "newsletter" }, { children: t('dialogs:changeNotifications.newsletter.label') }), void 0), jsx(Checkbox, __assign({ id: "newsletter", name: "newsletter", checked: newsletterEnabled, onChange: function (value) {
21769
+ } }, { children: weeklyEnabled
21770
+ ? t('dialogs:changeNotifications.weeklyReminder.on')
21771
+ : t('dialogs:changeNotifications.weeklyReminder.off') }), void 0), jsx("label", __assign({ className: "mt-2 mb-1 form-label", htmlFor: "newsletter" }, { children: t('dialogs:changeNotifications.newsletter.label') }), void 0), jsx(Checkbox, __assign({ id: "newsletter", name: "newsletter", checked: newsletterEnabled, onChange: function (value) {
21656
21772
  setChanged(true);
21657
21773
  setNewsletterEnabled(value);
21658
- } }, { children: newsletterEnabled ?
21659
- t('dialogs:changeNotifications.newsletter.on') :
21660
- t('dialogs:changeNotifications.newsletter.off') }), void 0), jsx(AlertBox, { type: "info", className: "mt-2", content: t('changeNotifications.info') }, void 0), jsx(AlertBox, { type: "danger", className: "mt-2", hide: !error, closable: true, onClose: function () { return setError(''); }, useIcon: true, content: error }, void 0), jsxs("div", __assign({ className: "d-flex flex-wrap" }, { children: [jsx(DialogBtn, { className: "mt-2 me-2", type: "button", color: "primary", outlined: true, label: t('changeNotifications.cancelBtn'), onClick: function () { return handleClose(); } }, void 0), jsx(DialogBtn, { className: "mt-2", type: "submit", color: "primary", loading: loading, disabled: loading || !changed, label: t('changeNotifications.submitBtn') }, void 0)] }), void 0)] }), void 0) }), void 0) }), void 0));
21774
+ } }, { children: newsletterEnabled
21775
+ ? t('dialogs:changeNotifications.newsletter.on')
21776
+ : t('dialogs:changeNotifications.newsletter.off') }), void 0), jsx("hr", { className: "my-3" }, void 0), jsx("label", __assign({ className: "mb-1 form-label" }, { children: t('dialogs:changeNotifications.channels.label') }), void 0), jsx(Checkbox, __assign({ id: "channelEmail", name: "channelEmail", checked: channelEmail }, { disabled: !confirmedPhone && channelEmail }, { onChange: handleChannelEmail }, { children: t('dialogs:changeNotifications.channels.email') }), void 0), jsx(Checkbox, __assign({ id: "channelWhatsapp", name: "channelWhatsapp", checked: channelWhatsapp }, { disabled: !confirmedPhone }, { onChange: handleChannelWhatsapp }, { children: t('dialogs:changeNotifications.channels.whatsapp') }), void 0), !confirmedPhone && (jsx(AlertBox, { type: "warning", className: "mt-2", content: t('dialogs:changeNotifications.channels.whatsappDisabled') }, void 0)), confirmedPhone && (jsx("p", __assign({ className: "mt-1", style: { fontSize: '0.8rem', color: '#888', fontStyle: 'italic' } }, { children: t('dialogs:changeNotifications.channels.note') }), void 0)), jsx(AlertBox, { type: "danger", className: "mt-2", hide: !error, closable: true, onClose: function () { return setError(''); }, useIcon: true, content: error }, void 0), jsxs("div", __assign({ className: "d-flex flex-wrap" }, { children: [jsx(DialogBtn, { className: "mt-2 me-2", type: "button", color: "primary", outlined: true, label: t('changeNotifications.cancelBtn'), onClick: function () { return handleClose(); } }, void 0), jsx(DialogBtn, { className: "mt-2", type: "submit", color: "primary", loading: loading, disabled: loading || !changed, label: t('changeNotifications.submitBtn') }, void 0)] }), void 0)] }), void 0) }), void 0) }), void 0));
21661
21777
  };
21662
21778
 
21663
21779
  var ChangePassword = function (props) {
@@ -22308,6 +22424,22 @@ var PasswordForgotten = function () {
22308
22424
  return (jsx(Dialog, __assign({ open: open, title: t('passwordForgotten.title'), onClose: handleClose, ariaLabelledBy: "passwordForgottenTitle" }, { children: jsxs("div", __assign({ className: clsx(defaultDialogPaddingXClass, 'py-3', 'bg-grey-1') }, { children: [jsx(AlertBox, { className: "mb-2", type: "info", useIcon: false, content: t('passwordForgotten.info') }, void 0), jsx(AlertBox, { className: "mb-2", hide: !success, type: "success", useIcon: true, content: t('passwordForgotten.successMessage') }, void 0), jsx(AlertBox, { className: "mb-2", hide: !error, type: "danger", useIcon: true, content: error, closable: true, onClose: function () { return setError(''); } }, void 0), jsxs("form", __assign({ onSubmit: onResetPasswordClicked }, { children: [jsx(TextField, { id: "email", label: t("passwordForgotten.emailInputLabel"), placeholder: t("passwordForgotten.emailInputPlaceholder"), type: "email", name: "email", className: "mb-2", value: email, required: true, onChange: emailChanged }, void 0), jsx(DialogBtn, { type: "submit", label: t('passwordForgotten.submitBtn'), disabled: loading || disabled || email.length < 3, loading: loading, loadingLabel: t('loadingMsg') }, void 0)] }), void 0)] }), void 0) }), void 0));
22309
22425
  };
22310
22426
 
22427
+ // Backend error messages used in phone/WhatsApp dialog error handling.
22428
+ // Keep in sync with user-management-service gRPC status messages.
22429
+ var BACKEND_ERRORS = {
22430
+ ACTION_FAILED: 'action failed',
22431
+ PHONE_NOT_VALID: 'phone not valid',
22432
+ PHONE_ALREADY_TAKEN: 'phone number already taken',
22433
+ PHONE_ALREADY_VERIFIED: 'phone number already verified',
22434
+ NO_PHONE_TO_EDIT: 'user has no phone number to edit',
22435
+ WHATSAPP_UNAVAILABLE: 'WhatsApp is not configured',
22436
+ SEND_FAILED: 'failed to send verification code',
22437
+ TOO_MANY_ATTEMPTS: 'too many attempts, phone number removed',
22438
+ CODE_EXPIRED: 'verification code expired',
22439
+ INVALID_CODE: 'invalid verification code',
22440
+ RATE_LIMITED: 'too many phone verification attempts, try again later',
22441
+ };
22442
+
22311
22443
  var ChangePhone = function () {
22312
22444
  var _a;
22313
22445
  var t = useTranslation(['dialogs']).t;
@@ -22382,13 +22514,13 @@ var ChangePhone = function () {
22382
22514
  }); };
22383
22515
  var handleError = function (errorMsg) {
22384
22516
  switch (errorMsg) {
22385
- case 'action failed':
22517
+ case BACKEND_ERRORS.ACTION_FAILED:
22386
22518
  setError(t('changePhone.errors.wrongPasswordOrAccountId'));
22387
22519
  break;
22388
- case 'phone not valid':
22520
+ case BACKEND_ERRORS.PHONE_NOT_VALID:
22389
22521
  setError(t('changePhone.errors.wrongPhoneFormat'));
22390
22522
  break;
22391
- case 'phone number already taken':
22523
+ case BACKEND_ERRORS.PHONE_ALREADY_TAKEN:
22392
22524
  setError(t('changePhone.errors.phoneAlreadyTaken'));
22393
22525
  break;
22394
22526
  default:
@@ -22474,29 +22606,6 @@ var DeletePhone = function (props) {
22474
22606
  return (jsx(Dialog, __assign({ open: open, title: t('deletePhone.title'), color: "danger", onClose: handleClose, ariaLabelledBy: "deletePhoneDialogTitle" }, { children: jsxs("div", __assign({ className: clsx(defaultDialogPaddingXClass, 'py-3', 'bg-grey-1') }, { children: [jsx(AlertBox, { type: "danger", content: t('dialogs:deletePhone.info') }, void 0), jsx(AlertBox, { className: "mt-2", type: "danger", hide: !error, closable: true, onClose: function () { return setError(''); }, content: error }, void 0), jsxs("div", __assign({ className: "d-flex flex-wrap" }, { children: [jsx(DialogBtn, { className: "mt-2 me-2", type: "button", color: "primary", label: t('deletePhone.cancelBtn'), onClick: function () { return handleClose(); } }, void 0), jsx(DialogBtn, { type: "button", color: "danger", className: "mt-2", loading: loading, outlined: true, label: t('deletePhone.confirmBtn'), onClick: function () { return onDeletePhone(); } }, void 0)] }), void 0)] }), void 0) }), void 0));
22475
22607
  };
22476
22608
 
22477
- // Lista dei prefissi internazionali più comuni
22478
- var COUNTRY_CODES = [
22479
- { code: '+39', country: 'IT', name: 'Italy' },
22480
- { code: '+1', country: 'US', name: 'United States' },
22481
- { code: '+44', country: 'GB', name: 'United Kingdom' },
22482
- { code: '+33', country: 'FR', name: 'France' },
22483
- { code: '+49', country: 'DE', name: 'Germany' },
22484
- { code: '+34', country: 'ES', name: 'Spain' },
22485
- { code: '+31', country: 'NL', name: 'Netherlands' },
22486
- { code: '+41', country: 'CH', name: 'Switzerland' },
22487
- { code: '+43', country: 'AT', name: 'Austria' },
22488
- { code: '+32', country: 'BE', name: 'Belgium' },
22489
- { code: '+351', country: 'PT', name: 'Portugal' },
22490
- { code: '+30', country: 'GR', name: 'Greece' },
22491
- { code: '+46', country: 'SE', name: 'Sweden' },
22492
- { code: '+47', country: 'NO', name: 'Norway' },
22493
- { code: '+45', country: 'DK', name: 'Denmark' },
22494
- { code: '+358', country: 'FI', name: 'Finland' },
22495
- { code: '+48', country: 'PL', name: 'Poland' },
22496
- { code: '+420', country: 'CZ', name: 'Czech Republic' },
22497
- { code: '+36', country: 'HU', name: 'Hungary' },
22498
- { code: '+40', country: 'RO', name: 'Romania' },
22499
- ];
22500
22609
  var AddPhone = function () {
22501
22610
  var _a;
22502
22611
  var t = useTranslation(['dialogs']).t;
@@ -22509,7 +22618,7 @@ var AddPhone = function () {
22509
22618
  var _e = useState({
22510
22619
  countryCode: '+39',
22511
22620
  phoneNumber: '',
22512
- newPhone: '' // Numero completo con prefisso
22621
+ newPhone: ''
22513
22622
  }), formData = _e[0], setFormData = _e[1];
22514
22623
  useEffect(function () {
22515
22624
  if (!open) {
@@ -22589,13 +22698,13 @@ var AddPhone = function () {
22589
22698
  }); };
22590
22699
  var handleError = function (errorMsg) {
22591
22700
  switch (errorMsg) {
22592
- case 'action failed':
22701
+ case BACKEND_ERRORS.ACTION_FAILED:
22593
22702
  setError(t('addPhone.errors.wrongPasswordOrAccountId'));
22594
22703
  break;
22595
- case 'phone not valid':
22704
+ case BACKEND_ERRORS.PHONE_NOT_VALID:
22596
22705
  setError(t('addPhone.errors.wrongPhoneFormat'));
22597
22706
  break;
22598
- case 'phone number already taken':
22707
+ case BACKEND_ERRORS.PHONE_ALREADY_TAKEN:
22599
22708
  setError(t('addPhone.errors.phoneAlreadyTaken'));
22600
22709
  break;
22601
22710
  default:
@@ -22653,29 +22762,22 @@ var VerifyWhatsApp = function () {
22653
22762
  setError('');
22654
22763
  _c.label = 1;
22655
22764
  case 1:
22656
- _c.trys.push([1, 4, 5, 6]);
22657
- // First delete existing phone number
22658
- return [4 /*yield*/, deletePhoneReq()];
22765
+ _c.trys.push([1, 3, 4, 5]);
22766
+ return [4 /*yield*/, resendWhatsAppCodeReq()];
22659
22767
  case 2:
22660
- // First delete existing phone number
22661
- _c.sent();
22662
- // Then re-add it (this will send the WhatsApp code)
22663
- return [4 /*yield*/, newAccountPhoneReq(phoneNumber)];
22664
- case 3:
22665
- // Then re-add it (this will send the WhatsApp code)
22666
22768
  _c.sent();
22667
22769
  setError('');
22668
- return [3 /*break*/, 6];
22669
- case 4:
22770
+ return [3 /*break*/, 5];
22771
+ case 3:
22670
22772
  e_1 = _c.sent();
22671
22773
  console.error(e_1);
22672
22774
  errorResponse = e_1;
22673
22775
  setError(((_b = (_a = errorResponse.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) || t('verifyWhatsApp.errors.unknown'));
22674
- return [3 /*break*/, 6];
22675
- case 5:
22776
+ return [3 /*break*/, 5];
22777
+ case 4:
22676
22778
  setResendLoading(false);
22677
22779
  return [7 /*endfinally*/];
22678
- case 6: return [2 /*return*/];
22780
+ case 5: return [2 /*return*/];
22679
22781
  }
22680
22782
  });
22681
22783
  }); };
@@ -24085,8 +24187,6 @@ var AccountSettings = function (props) {
24085
24187
  if (!isAuth) {
24086
24188
  return jsx("div", __assign({ className: "bg-warning-light p-3" }, { children: 'authentication needed' }), void 0);
24087
24189
  }
24088
- console.log('phoneInfo:', phoneInfo);
24089
- console.log('confirmedAt:', phoneInfo === null || phoneInfo === void 0 ? void 0 : phoneInfo.confirmedAt);
24090
24190
  var handleResendCode = function () { return __awaiter(void 0, void 0, void 0, function () {
24091
24191
  var error_1;
24092
24192
  return __generator$1(this, function (_a) {
@@ -24100,7 +24200,6 @@ var AccountSettings = function (props) {
24100
24200
  return [4 /*yield*/, resendWhatsAppCodeReq()];
24101
24201
  case 2:
24102
24202
  _a.sent();
24103
- console.log('Opening dialog with phone:', phoneInfo === null || phoneInfo === void 0 ? void 0 : phoneInfo.phone);
24104
24203
  // Use requestAnimationFrame to wait for React to finish rendering
24105
24204
  requestAnimationFrame(function () {
24106
24205
  dispatch(dialogActions.openVerifyWhatsAppDialog({
@@ -34576,7 +34675,7 @@ var PhoneVerificationBanner = function () {
34576
34675
  var handleGoToProfile = function () {
34577
34676
  history.push('/settings');
34578
34677
  };
34579
- return (jsx("div", __assign({ className: "alert alert-warning mb-0", role: "alert", style: { borderRadius: 0 } }, { children: jsx("div", __assign({ className: "container" }, { children: jsxs("div", __assign({ className: "row align-items-center" }, { children: [jsxs("div", __assign({ className: "col-12 col-md-9" }, { children: [jsx("span", __assign({ className: "material-icons align-middle me-2", style: { fontSize: '1.5rem' } }, { children: "warning" }), void 0), jsx("strong", { children: t('phoneVerificationBanner.title') }, void 0), ' ', t('phoneVerificationBanner.message')] }), void 0), jsx("div", __assign({ className: "col-12 col-md-3 text-md-end mt-2 mt-md-0" }, { children: jsx(DialogBtn, { type: "button", color: "danger", onClick: handleGoToProfile, label: t('phoneVerificationBanner.button') }, void 0) }), void 0)] }), void 0) }), void 0) }), void 0));
34678
+ return (jsx("div", __assign({ className: "alert alert-warning mb-0", role: "alert", style: { borderRadius: 0 } }, { children: jsx("div", __assign({ className: "container" }, { children: jsxs("div", __assign({ className: "row align-items-center" }, { children: [jsxs("div", __assign({ className: "col-12 col-md-9" }, { children: [jsx("span", __assign({ className: "material-icons align-middle me-2", style: { fontSize: '1.5rem' } }, { children: "warning" }), void 0), jsx("strong", { children: t('phoneVerificationBanner.title') }, void 0), ' ', t('phoneVerificationBanner.message')] }), void 0), jsx("div", __assign({ className: "col-12 col-md-3 text-md-end mt-2 mt-md-0" }, { children: jsx(DialogBtn, { type: "button", color: "primary", onClick: handleGoToProfile, label: t('phoneVerificationBanner.button') }, void 0) }), void 0)] }), void 0) }), void 0) }), void 0));
34580
34679
  };
34581
34680
 
34582
34681
  var coreReduxActions = {