diff --git a/mobile/app/profile/_layout.tsx b/mobile/app/profile/_layout.tsx
index 2d267936290b90e3d7922853babeb54d21d5594e..38c320f57c723487503397236c0c8ecbc2c6f3f7 100644
--- a/mobile/app/profile/_layout.tsx
+++ b/mobile/app/profile/_layout.tsx
@@ -28,6 +28,10 @@ export default function Layout() {
title: "Set Up Profile",
headerShown: true,
}}/>
+
);
}
\ No newline at end of file
diff --git a/mobile/app/profile/change_password.tsx b/mobile/app/profile/change_password.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..871eae2e7045ba694afab7037b508eaa2d33e1eb
--- /dev/null
+++ b/mobile/app/profile/change_password.tsx
@@ -0,0 +1,7 @@
+import { ChangePasswordPage } from "../../src/profile/screens/change_password_page";
+
+export default function ChangePasswordScreen() {
+ return (
+
+ );
+}
\ No newline at end of file
diff --git a/mobile/package-lock.json b/mobile/package-lock.json
index 8f3695020338e7d15e7ef3eca0240b54427bff74..e1b43956608d5e033814f97d6858ddeed19e005c 100644
--- a/mobile/package-lock.json
+++ b/mobile/package-lock.json
@@ -9,6 +9,7 @@
"version": "1.0.0",
"dependencies": {
"@gorhom/bottom-sheet": "^4.6.1",
+ "@react-native-async-storage/async-storage": "1.21.0",
"@react-native-community/datetimepicker": "7.6.1",
"@react-native-community/slider": "4.4.2",
"@react-native-picker/picker": "2.6.1",
@@ -3916,6 +3917,17 @@
"react": "^16.8 || ^17.0 || ^18.0"
}
},
+ "node_modules/@react-native-async-storage/async-storage": {
+ "version": "1.21.0",
+ "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.21.0.tgz",
+ "integrity": "sha512-JL0w36KuFHFCvnbOXRekqVAUplmOyT/OuCQkogo6X98MtpSaJOKEAeZnYO8JB0U/RIEixZaGI5px73YbRm/oag==",
+ "dependencies": {
+ "merge-options": "^3.0.4"
+ },
+ "peerDependencies": {
+ "react-native": "^0.0.0-0 || >=0.60 <1.0"
+ }
+ },
"node_modules/@react-native-community/cli": {
"version": "12.3.6",
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-12.3.6.tgz",
@@ -10232,6 +10244,14 @@
"node": ">=8"
}
},
+ "node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@@ -11548,6 +11568,17 @@
"resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz",
"integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA=="
},
+ "node_modules/merge-options": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz",
+ "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==",
+ "dependencies": {
+ "is-plain-obj": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
diff --git a/mobile/package.json b/mobile/package.json
index 380929d2fd3a053dabcf821bf5b8440f41d8518c..bb5ccad657f3d29e351b0c11e79b759fd6ee215f 100644
--- a/mobile/package.json
+++ b/mobile/package.json
@@ -42,7 +42,8 @@
"react-native-safe-area-context": "4.8.2",
"react-native-screens": "~3.29.0",
"react-native-svg": "14.1.0",
- "@react-native-picker/picker": "2.6.1"
+ "@react-native-picker/picker": "2.6.1",
+ "@react-native-async-storage/async-storage": "1.21.0"
},
"devDependencies": {
"@babel/core": "^7.20.0",
diff --git a/mobile/src/common/contexts/data_context.tsx b/mobile/src/common/contexts/data_context.tsx
index 83d3a4f8bb5936e797fce2bdd48c73ffac90a4d1..85b25dee5c0735ca0f2359efbbf062b9703f4059 100644
--- a/mobile/src/common/contexts/data_context.tsx
+++ b/mobile/src/common/contexts/data_context.tsx
@@ -20,6 +20,8 @@ import { ProfileRepository } from "../../profile/domain/repositories/profile_rep
import { ProfileDataSourceDev } from "../../profile/infrastructure/datasources/dev/profile_datasource";
import { ProfileRepositoryImpl } from "../../profile/infrastructure/repositories/profile_repository";
import { ActivityDatasourceProd } from "../../infrastructure/datasource/prod/activity_datasource";
+import { useTranslation } from "react-i18next";
+import { ProfileDataSourceProd } from "../../profile/infrastructure/datasources/prod/profile_datasource";
type DataContextType = {
statesRepository: StateRepository | null;
@@ -42,20 +44,26 @@ const DataContext = createContext({
});
export const DataContextProvider = ({ children }: DataContextProviderProps) => {
- //const statesDataSource = new StateDataSourceDev();
- const statesDataSource = new StateDataSourceProd();
+ const { i18n:{ language } } = useTranslation();
+ const statesDataSource = new StateDataSourceDev();
+ //const statesDataSource = new StateDataSourceProd(language);
const statesRepository = new StateRepositoryImpl(statesDataSource);
- //const authDataSource = new AuthDataSourceDev();
- const authDataSource = new AuthDatasourceProd();
+ //
+ const authDataSource = new AuthDataSourceDev();
+ //const authDataSource = new AuthDatasourceProd();
const authRepository = new AuthRepositoryImpl(authDataSource);
- //const activityDataSource = new ActivityDatasourceDev();
- const activityDataSource = new ActivityDatasourceProd();
+ //
+ const activityDataSource = new ActivityDatasourceDev();
+ //const activityDataSource = new ActivityDatasourceProd();
const activityRepository = new ActivityRepositoryDev(activityDataSource);
+ //
const travelDatasource = new TravelDatasourceDev();
const travelRepository = new TravelRepositoryImpl(travelDatasource);
+ //
const routeDatasource = new RouteDataSourceDev();
const routeRepository = new RouteRepositoryImpl(routeDatasource);
- const profileDataSource = new ProfileDataSourceDev();
+ //
+ const profileDataSource = new ProfileDataSourceProd();
const profileRepository = new ProfileRepositoryImpl(profileDataSource);
const value = {
diff --git a/mobile/src/infrastructure/datasource/prod/activity_datasource.ts b/mobile/src/infrastructure/datasource/prod/activity_datasource.ts
index 41e8b4acc45ec16568c2238cce136585b964b46a..4bd9cb84779cbb3eb5cd66c38090af32cbcc82fc 100644
--- a/mobile/src/infrastructure/datasource/prod/activity_datasource.ts
+++ b/mobile/src/infrastructure/datasource/prod/activity_datasource.ts
@@ -4,10 +4,12 @@ import { ActivityPlaceEntity } from "../../../domain/entities/activity_place_ent
import { API_URL } from "../../../common/constants/api";
import { ActivityPlaceModel } from "../../models/prod/activity_place_model";
import { activityPlaceModelToEntity } from "../../utils/activity_utils";
+import { Languages } from "../../../lang/translations";
export class ActivityDatasourceProd implements ActivityDataSource {
+ constructor(private lang: string = Languages.SPANISH) {}
async getPlaceActivity(activityId: number, townId: number, stateId: number, placeNumber: number): Promise {
- const { data, status } = await axios.get(`${API_URL}/point/${placeNumber}lang?lang=es`);
+ const { data, status } = await axios.get(`${API_URL}/point/${placeNumber}lang?lang=${this.lang}`);
if (status !== 200) {
throw new Error("Error al obtener la información del lugar");
}
diff --git a/mobile/src/infrastructure/datasource/prod/state_datasource.ts b/mobile/src/infrastructure/datasource/prod/state_datasource.ts
index 7007dbc9102bbe29f52b818df7e5e42c9f9bab8d..d3940f85204d62aa5d4b5880b95cc23a91776105 100644
--- a/mobile/src/infrastructure/datasource/prod/state_datasource.ts
+++ b/mobile/src/infrastructure/datasource/prod/state_datasource.ts
@@ -12,6 +12,10 @@ import { ActivityModel } from "../../models/prod/activity_model";
import { placeModelToEntity } from "../../utils/place_utils";
export class StateDataSourceProd implements StateDataSource {
+ private lang: string;
+ constructor(lang: string = 'es') {
+ this.lang = lang;
+ }
async getStates(): Promise {
const {status, data} = await axios.get(API_URL + '/state');
if (status !== 200) {
@@ -20,18 +24,15 @@ export class StateDataSourceProd implements StateDataSource {
return data.map(stateModelToEntity);
}
async getTowns(stateId: number): Promise {
- // TODO: get lang from user preferences
- const {status, data} = await axios.get(API_URL + '/state/' + stateId + '/town?lang=es');
+ const {status, data} = await axios.get(`${API_URL}/state/${stateId}/town?lang=${this.lang}`);
if (status !== 200) {
throw new Error('Error fetching towns');
}
return data.map(townModelToEntity);
}
async getTownActivities(townId: number): Promise {
- // TODO: get lang from user preferences
- // TODO: get townId from user preferences
console.log('townId', townId);
- const {status, data} = await axios.get(API_URL + `/place/town/${townId}/place?lang=es`);
+ const {status, data} = await axios.get(`${API_URL}/place/town/${townId}/place?lang=${this.lang}`);
if (status !== 200) {
throw new Error('Error fetching activities');
}
@@ -41,7 +42,7 @@ export class StateDataSourceProd implements StateDataSource {
async getActivityInfo(activityId: number): Promise {
// TODO: get lang from user preferences
// TODO: get townId from user preferences
- const {status, data} = await axios.get(API_URL + `/place/${activityId}`);
+ const {status, data} = await axios.get(`${API_URL}/place/${activityId}?lang=${this.lang}`);
if (status !== 200) {
throw new Error('Error fetching activity');
}
diff --git a/mobile/src/lang/components/language_icon.tsx b/mobile/src/lang/components/language_icon.tsx
index 94c31bcb393397b6fb97ee247b9aef6fc1c7605f..f2e212315a98681d98686def422ca71f7b6bf69f 100644
--- a/mobile/src/lang/components/language_icon.tsx
+++ b/mobile/src/lang/components/language_icon.tsx
@@ -1,15 +1,12 @@
import { Entypo } from '@expo/vector-icons';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { useTranslation } from 'react-i18next';
+import { useLang } from '../hooks/useLang';
export const LanguageIcon = () => {
- const { i18n } = useTranslation();
- const changeLanguage = () => {
- i18n.changeLanguage(i18n.language === 'en' ? 'es' : 'en');
- }
-
+ const { toggleLanguage } = useLang();
return (
-
+
);
diff --git a/mobile/src/lang/english_lang.ts b/mobile/src/lang/english_lang.ts
index 73fb800cb1e9261521b5a08579f3a53750a0aacc..f433c8effb7a7ca807b2e8cd71a661499a11cb61 100644
--- a/mobile/src/lang/english_lang.ts
+++ b/mobile/src/lang/english_lang.ts
@@ -23,10 +23,15 @@ export const ENGLISH_LANG: Lang = {
accountScreen:{
title: "Account",
logoutButton: "Logout",
+ changePasswordButton: "Change password",
changeLanguageButton: "Change App Language",
selectLanguage: "Select language",
saveButton: "Save",
},
+ changePasswordScreen:{
+ title: "Change password",
+ saveButton: "Save",
+ },
selectTownScreen:{
title: "Select Town",
},
diff --git a/mobile/src/lang/hooks/useLang.ts b/mobile/src/lang/hooks/useLang.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b871c59cccb30c859e7b3eae8d2b17f1982e23fb
--- /dev/null
+++ b/mobile/src/lang/hooks/useLang.ts
@@ -0,0 +1,21 @@
+import { useTranslation } from "react-i18next";
+import { Languages } from "../translations";
+import AsyncStorage from '@react-native-async-storage/async-storage'
+
+export const useLang = () => {
+ const { i18n } = useTranslation();
+ const changeLanguage = (lang: Languages) => {
+ i18n.changeLanguage(lang);
+ AsyncStorage.setItem("lang", lang);
+ }
+
+ const toggleLanguage = () => {
+ const lang = i18n.language === Languages.SPANISH ? Languages.ENGLISH : Languages.SPANISH;
+ changeLanguage(lang);
+ }
+
+ return {
+ changeLanguage,
+ toggleLanguage
+ };
+}
\ No newline at end of file
diff --git a/mobile/src/lang/lang.ts b/mobile/src/lang/lang.ts
index 8bd3a094ff9901f72c7f007d59e0c4f6f82d7f67..e4dff6305e419bf747aabd1dd8266722cd9a250d 100644
--- a/mobile/src/lang/lang.ts
+++ b/mobile/src/lang/lang.ts
@@ -22,9 +22,14 @@ export interface Lang {
title: string;
logoutButton: string;
changeLanguageButton: string;
+ changePasswordButton: string;
selectLanguage: string;
saveButton: string;
},
+ changePasswordScreen:{
+ title: string;
+ saveButton: string;
+ },
selectTownScreen:{
title: string;
},
diff --git a/mobile/src/lang/spanish_lang.ts b/mobile/src/lang/spanish_lang.ts
index 0d6591c9ecf8f9a8f5b8511299578535a9569076..e74e205a7fe0b6f0e320412aaa79b252c3cdb3ab 100644
--- a/mobile/src/lang/spanish_lang.ts
+++ b/mobile/src/lang/spanish_lang.ts
@@ -23,10 +23,15 @@ export const SPANISH_LANG: Lang = {
accountScreen:{
title: "Cuenta",
logoutButton: "Cerrar sesión",
+ changePasswordButton: "Cambiar contraseña",
changeLanguageButton: "Cambiar idioma de la aplicación",
selectLanguage: "Seleccionar idioma",
saveButton: "Guardar",
},
+ changePasswordScreen:{
+ title: "Cambiar contraseña",
+ saveButton: "Guardar",
+ },
selectTownScreen:{
title: "Seleccionar Pueblo",
},
diff --git a/mobile/src/lang/translations.ts b/mobile/src/lang/translations.ts
index 7bd0b31032751f8b4c0be791475bf4dea6763f1e..12d068c3a637aaaaca13ec1d85e9b610a6b81c1d 100644
--- a/mobile/src/lang/translations.ts
+++ b/mobile/src/lang/translations.ts
@@ -3,6 +3,7 @@ import { initReactI18next } from 'react-i18next';
import * as Localization from 'expo-localization';
import { SPANISH_LANG } from './spanish_lang';
import { ENGLISH_LANG } from './english_lang';
+import AsyncStorage from '@react-native-async-storage/async-storage';
i18n.use(initReactI18next).init({
compatibilityJSON: 'v3', // Necesario para compatibilidad con Expo
@@ -20,16 +21,28 @@ i18n.use(initReactI18next).init({
}
});
+export enum Languages {
+ ENGLISH = 'en',
+ SPANISH = 'es'
+};
+
export const AvailableLanguages = [
{
- key: 'en',
+ key: Languages.ENGLISH,
value: 'English'
},
{
- key: 'es',
+ key: Languages.SPANISH,
value: 'Español'
}
-]
+];
+
+(async () => {
+ const lang = await AsyncStorage.getItem("lang");
+ if (lang) {
+ i18n.changeLanguage(lang);
+ }
+})();
export default i18n;
diff --git a/mobile/src/profile/components/change_password_form.tsx b/mobile/src/profile/components/change_password_form.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..2057ee0ea4709e73b09f56c5da6b67f752306f3c
--- /dev/null
+++ b/mobile/src/profile/components/change_password_form.tsx
@@ -0,0 +1,67 @@
+import { Control, Controller } from "react-hook-form";
+import { View } from "react-native";
+import { EditProfileFormValues } from "../../hooks/useEditProfile";
+import { CustomTextInput } from "../../common/components/form/text_input";
+
+interface ChangePasswordFormProps {
+ control: any;
+ isActive?: boolean;
+}
+
+export const ChangePasswordForm = ({ control, isActive }: ChangePasswordFormProps) => {
+ return (
+
+ (
+
+ )}
+ />
+ (
+
+ )}
+ />
+ (
+
+ )}
+ />
+
+ );
+}
\ No newline at end of file
diff --git a/mobile/src/profile/domain/datasources/profile_datasource.ts b/mobile/src/profile/domain/datasources/profile_datasource.ts
index 28bc6c33ac5bb3cb383b954dbf938d321e08d274..50ae766950dc075a071fabca060abc5eb284ca07 100644
--- a/mobile/src/profile/domain/datasources/profile_datasource.ts
+++ b/mobile/src/profile/domain/datasources/profile_datasource.ts
@@ -4,4 +4,5 @@ export interface ProfileDataSource {
getInterests: () => Promise;
saveInterests: (options: IOption[]) => Promise;
setUpProfile: (birthdate: string, interests: IOption[]) => Promise;
+ changePassword: (oldPassword: string, newPassword: string) => Promise;
};
\ No newline at end of file
diff --git a/mobile/src/profile/domain/repositories/profile_repository.ts b/mobile/src/profile/domain/repositories/profile_repository.ts
index 7f8164b9fd5eb8218525f30a9de5331f6b60e050..98634810fd001fb0b1ee3e233bc24fbbce53d4f7 100644
--- a/mobile/src/profile/domain/repositories/profile_repository.ts
+++ b/mobile/src/profile/domain/repositories/profile_repository.ts
@@ -4,4 +4,5 @@ export interface ProfileRepository {
getInterests: () => Promise;
saveInterests: (options: IOption[]) => Promise;
setUpProfile: (birthdate: string, interests: IOption[]) => Promise;
+ changePassword: (oldPassword: string, newPassword: string) => Promise;
};
\ No newline at end of file
diff --git a/mobile/src/profile/hooks/useChangePassword.ts b/mobile/src/profile/hooks/useChangePassword.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d0f97a66e71f94dc045b72d426811c8c804ca5dc
--- /dev/null
+++ b/mobile/src/profile/hooks/useChangePassword.ts
@@ -0,0 +1,40 @@
+import { useState } from "react";
+import { useForm } from "react-hook-form"
+import { ApiRequestStatus } from "../../common/constants/api_request_states";
+import { useDataContext } from "../../common/contexts/data_context";
+import { router } from "expo-router";
+
+interface ChangePasswordValues {
+ oldPassword: string;
+ newPassword: string;
+ confirmPassword: string;
+}
+
+export const useChangePassword = () => {
+ const { control, handleSubmit, setError } = useForm();
+ const [status, setStatus] = useState(ApiRequestStatus.IDLE);
+ const { profileRepository } = useDataContext();
+
+ const setLoading = async () => {
+ setStatus(ApiRequestStatus.LOADING);
+ }
+
+ const request = async (values: ChangePasswordValues) => {
+ await setLoading();
+ try {
+ await profileRepository!.changePassword(values.oldPassword, values.newPassword);
+ setStatus(ApiRequestStatus.SUCCESS);
+ router.back();
+ } catch (error) {
+ setError("oldPassword", { type: "manual", message: "The current password is incorrect" });
+ setStatus(ApiRequestStatus.ERROR);
+ }
+ }
+
+ const onSubmit = async () => {
+ await handleSubmit(async (data) => {
+ await request(data);
+ })();
+ }
+ return { control, onSubmit, status };
+}
\ No newline at end of file
diff --git a/mobile/src/profile/infrastructure/datasources/dev/profile_datasource.ts b/mobile/src/profile/infrastructure/datasources/dev/profile_datasource.ts
index 1bf3b48e938501e80d530658116759be77c6264d..f7e598af23a97f74f462b8167a28d66fedbf5288 100644
--- a/mobile/src/profile/infrastructure/datasources/dev/profile_datasource.ts
+++ b/mobile/src/profile/infrastructure/datasources/dev/profile_datasource.ts
@@ -16,6 +16,10 @@ export class ProfileDataSourceDev implements ProfileDataSource {
];
}
+ async changePassword(oldPassword: string, newPassword: string): Promise {
+ console.log('Changing password', oldPassword, newPassword);
+ }
+
async saveInterests(options: IOption[]): Promise {
console.log('Saving interests', options);
}
diff --git a/mobile/src/profile/infrastructure/datasources/prod/profile_datasource.ts b/mobile/src/profile/infrastructure/datasources/prod/profile_datasource.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eee7b181c9fb28d18f058986906113a78a0eb9ea
--- /dev/null
+++ b/mobile/src/profile/infrastructure/datasources/prod/profile_datasource.ts
@@ -0,0 +1,26 @@
+import axios from "axios";
+import { IOption } from "../../../../common/domain/entities/option";
+import { ProfileDataSource } from "../../../domain/datasources/profile_datasource";
+import { API_URL } from "../../../../common/constants/api";
+
+export class ProfileDataSourceProd implements ProfileDataSource {
+ async getInterests(): Promise {
+ throw new Error('Method not implemented.');
+ }
+
+ async saveInterests(options: IOption[]): Promise {
+ throw new Error('Method not implemented.');
+ }
+
+ async setUpProfile(birthdate: string, interests: IOption[]): Promise {
+ throw new Error('Method not implemented.');
+ }
+
+ async changePassword(oldPassword: string, newPassword: string): Promise {
+ const {status, data} = await axios.patch(`${API_URL}/user/change-password`, {
+ prevPassword: oldPassword,
+ newPassword: newPassword
+ })
+ console.log(status, data);
+ }
+}
diff --git a/mobile/src/profile/infrastructure/repositories/profile_repository.ts b/mobile/src/profile/infrastructure/repositories/profile_repository.ts
index a71049bc530712c83551f09dda85e9a022352f89..4dea398544246e0c303255c7fff907195e023e3c 100644
--- a/mobile/src/profile/infrastructure/repositories/profile_repository.ts
+++ b/mobile/src/profile/infrastructure/repositories/profile_repository.ts
@@ -6,6 +6,9 @@ export class ProfileRepositoryImpl implements ProfileRepository {
constructor(
private dataSource: ProfileDataSource
){}
+ async changePassword (oldPassword: string, newPassword: string): Promise {
+ return this.dataSource.changePassword(oldPassword, newPassword);
+ };
async getInterests() {
return this.dataSource.getInterests();
}
diff --git a/mobile/src/profile/screens/account_page.tsx b/mobile/src/profile/screens/account_page.tsx
index 3bd39f9819b28aacc7a200452b3781fa14170f76..0a07160e468e39e192bb7f23ca8811812ac8b34d 100644
--- a/mobile/src/profile/screens/account_page.tsx
+++ b/mobile/src/profile/screens/account_page.tsx
@@ -21,9 +21,10 @@ import Modal from "react-native-modal";
import { set } from "react-hook-form";
import { AntDesign } from "@expo/vector-icons";
import RNPickerSelect from 'react-native-picker-select';
-import { AvailableLanguages } from "../../lang/translations";
+import { AvailableLanguages, Languages } from "../../lang/translations";
import i18n from 'i18next';
import { useTranslation } from "react-i18next";
+import { useLang } from "../../lang/hooks/useLang";
//TODO: Add source to CircleAvatar
const source = require("../../../assets/avatar.png");
@@ -56,11 +57,12 @@ export const AccountPage = () => {
/>
}
onPress={() => router.push("/profile/edit")}
- />
+ /> */}
}
- />*/}
+ title={LANG.t("accountScreen.changePasswordButton")}
+ leadingIcon={}
+ onPress={() => router.push("/profile/change_password")}
+ />
}
@@ -95,10 +97,10 @@ const ChangeLanguageModal = ({
onClose,
isVisible,
}: ChangeLanguageModalProps) => {
- const [selectedLanguage, setSelectedLanguage] = useState(null);
- const {i18n} = useTranslation();
+ const { changeLanguage } = useLang();
+ const [selectedLanguage, setSelectedLanguage] = useState(null);
const onSave = () => {
- i18n.changeLanguage(selectedLanguage || 'en');
+ changeLanguage(selectedLanguage || Languages.SPANISH);
onClose();
}
return (
diff --git a/mobile/src/profile/screens/change_password_page.tsx b/mobile/src/profile/screens/change_password_page.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..ccdc6eacb070e554ec57bdcaf0d733cb15a976c1
--- /dev/null
+++ b/mobile/src/profile/screens/change_password_page.tsx
@@ -0,0 +1,46 @@
+import { ScrollView, StyleSheet, TouchableOpacity, Text } from "react-native";
+import { ChangePasswordForm } from "../components/change_password_form";
+import { useChangePassword } from "../hooks/useChangePassword";
+import { LIGHT_THEME } from "../../common/constants/theme";
+
+export const ChangePasswordPage = () => {
+ const { control, onSubmit } = useChangePassword();
+ return (
+
+
+ {
+ //TODO: ADD a modal to show the success message
+ }
+
+ Change password
+
+
+ );
+};
+
+export const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ padding: 20,
+ },
+ innerContainer: {
+ alignItems: "center",
+ },
+ confirmBtn: {
+ backgroundColor: LIGHT_THEME.color.primary,
+ marginTop: 30,
+ padding: 10,
+ borderRadius: 20,
+ height: 40,
+ width: "70%",
+ justifyContent: "center",
+ alignItems: "center",
+ },
+ confirmBtnText: {
+ color: "white",
+ fontWeight: "bold",
+ },
+});