diff --git a/ts/screens/profile/LanguagesPreferencesScreen.tsx b/ts/screens/profile/LanguagesPreferencesScreen.tsx index 2f1950a90d1..2e39b023d79 100644 --- a/ts/screens/profile/LanguagesPreferencesScreen.tsx +++ b/ts/screens/profile/LanguagesPreferencesScreen.tsx @@ -1,7 +1,9 @@ import { List } from "native-base"; +import * as pot from "italia-ts-commons/lib/pot"; import * as React from "react"; import { Alert } from "react-native"; import { connect } from "react-redux"; +import { fromNullable } from "fp-ts/lib/Option"; import { Locales, TranslationKeys } from "../../../locales/locales"; import { withLightModalContext } from "../../components/helpers/withLightModalContext"; import { ContextualHelpPropsMarkdown } from "../../components/screens/BaseScreenComponent"; @@ -15,12 +17,21 @@ import { preferredLanguageSaveSuccess } from "../../store/actions/persistedPrefe import { Dispatch } from "../../store/actions/types"; import { preferredLanguageSelector } from "../../store/reducers/persistedPreferences"; import { GlobalState } from "../../store/reducers/types"; -import { getLocalePrimaryWithFallback } from "../../utils/locale"; +import { + fromLocaleToPreferredLanguage, + getLocalePrimaryWithFallback +} from "../../utils/locale"; +import { profileUpsert } from "../../store/actions/profile"; +import { withLoadingSpinner } from "../../components/helpers/withLoadingSpinner"; +import { profileSelector } from "../../store/reducers/profile"; +import { showToast } from "../../utils/showToast"; type Props = LightModalContextInterface & ReturnType & ReturnType; +type State = { isLoading: boolean; selectedLocale?: Locales }; + const contextualHelpMarkdown: ContextualHelpPropsMarkdown = { title: "profile.preferences.language.contextualHelpTitle", body: "profile.preferences.language.contextualHelpContent" @@ -31,13 +42,17 @@ const iconSize = 12; /** * Allows the user to select one of the available Languages as preferred */ -class LanguagesPreferencesScreen extends React.PureComponent { - private isAlreadyPreferred = (language: Locales) => +class LanguagesPreferencesScreen extends React.PureComponent { + constructor(props: Props) { + super(props); + this.state = { isLoading: false }; + } + + private isAlreadyPreferred = (language: Locales) => // if the preferred Lanuage is not set, we check if language is the same in use - this.props.preferredLanguage + this.props.preferredLanguage .map(l => l === language) - .getOrElse(getLocalePrimaryWithFallback() === language) - ; + .getOrElse(getLocalePrimaryWithFallback() === language); private onLanguageSelected = (language: Locales) => { if (!this.isAlreadyPreferred(language)) { @@ -56,8 +71,9 @@ class LanguagesPreferencesScreen extends React.PureComponent { text: I18n.t("global.buttons.confirm"), style: "default", onPress: () => { - this.props.preferredLanguageSaveSuccess(language); - this.showModal(); + this.setState({ selectedLocale: language }, () => { + this.props.upsertProfile(language); + }); } } ], @@ -66,6 +82,29 @@ class LanguagesPreferencesScreen extends React.PureComponent { } }; + public componentDidUpdate(prevProps: Readonly) { + // start updating + if (pot.isUpdating(this.props.profile)) { + this.setState({ isLoading: true }); + return; + } + + // update completed + if (pot.isUpdating(prevProps.profile) && pot.isSome(this.props.profile)) { + this.setState({ isLoading: false }); + fromNullable(this.state.selectedLocale).map( + this.props.preferredLanguageSaveSuccess + ); + this.showModal(); + return; + } + + // update error + if (pot.isUpdating(prevProps.profile) && pot.isError(this.props.profile)) { + showToast(I18n.t("errors.profileUpdateError")); + } + } + private showModal() { this.props.showModal( { } public render() { - return ( + const ContainerComponent = withLoadingSpinner(() => ( { - ); + )); + return ; } } const mapStateToProps = (state: GlobalState) => ({ - preferredLanguage: preferredLanguageSelector(state) + preferredLanguage: preferredLanguageSelector(state), + profile: profileSelector(state) }); const mapDispatchToProps = (dispatch: Dispatch) => ({ @@ -128,6 +169,12 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ preferredLanguageSaveSuccess({ preferredLanguage: language }) + ), + upsertProfile: (language: Locales) => + dispatch( + profileUpsert.request({ + preferred_languages: [fromLocaleToPreferredLanguage(language)] + }) ) }); diff --git a/ts/store/actions/profile.ts b/ts/store/actions/profile.ts index 0c8ecf03e97..2c0371caa5a 100644 --- a/ts/store/actions/profile.ts +++ b/ts/store/actions/profile.ts @@ -10,7 +10,6 @@ import { createAsyncAction, createStandardAction } from "typesafe-actions"; -import { ExtendedProfile } from "../../../definitions/backend/ExtendedProfile"; import { InitializedProfile } from "../../../definitions/backend/InitializedProfile"; export const resetProfileState = createStandardAction("RESET_PROFILE_STATE")(); @@ -27,7 +26,7 @@ export const profileLoadFailure = createAction( resolve => (error: Error) => resolve(error, { error: true }) ); -type ProfileUpsertPayload = Partial>; +type ProfileUpsertPayload = Partial>; export const profileUpsert = createAsyncAction( "PROFILE_UPSERT_REQUEST", diff --git a/ts/utils/locale.ts b/ts/utils/locale.ts index d31fc9706b7..569c97a74e4 100644 --- a/ts/utils/locale.ts +++ b/ts/utils/locale.ts @@ -1,6 +1,7 @@ -import { Option, some } from "fp-ts/lib/Option"; +import { fromNullable, Option, some } from "fp-ts/lib/Option"; import { Locales } from "../../locales/locales"; import I18n, { translations } from "../i18n"; +import { PreferredLanguageEnum } from "../../definitions/backend/PreferredLanguage"; /** * Helpers for handling locales */ @@ -33,3 +34,16 @@ export const getLocalePrimaryWithFallback = (fallback: Locales = "en") => .filter(l => translations.some(t => t.toLowerCase() === l.toLowerCase())) .map(s => s as Locales) .getOrElse(fallback); + +const localePreferredLanguageMapping = new Map([ + ["it", PreferredLanguageEnum.it_IT], + ["en", PreferredLanguageEnum.en_GB] +]); + +// from a given Locales return the relative PreferredLanguageEnum (fallback is en_GB) +export const fromLocaleToPreferredLanguage = ( + locale: Locales +): PreferredLanguageEnum => + fromNullable(localePreferredLanguageMapping.get(locale)).getOrElse( + PreferredLanguageEnum.en_GB + );