diff --git a/mobile/package-lock.json b/mobile/package-lock.json
index e1b43956608d5e033814f97d6858ddeed19e005c..0145b231234c29d0f5f771069b70279cbf49d14a 100644
--- a/mobile/package-lock.json
+++ b/mobile/package-lock.json
@@ -21,6 +21,7 @@
"expo-checkbox": "~2.7.0",
"expo-constants": "~15.4.5",
"expo-image-picker": "~14.7.1",
+ "expo-linear-gradient": "~12.7.2",
"expo-linking": "~6.2.2",
"expo-localization": "~14.8.4",
"expo-router": "~3.4.8",
@@ -8869,6 +8870,14 @@
"expo": "*"
}
},
+ "node_modules/expo-linear-gradient": {
+ "version": "12.7.2",
+ "resolved": "https://registry.npmjs.org/expo-linear-gradient/-/expo-linear-gradient-12.7.2.tgz",
+ "integrity": "sha512-Wwb2EF18ywgrlTodcXJ6Yt/UEcKitRMdXPNyP/IokmeKh4emoq9DxZJpZdkXm3HUTLlbRpi6/t32jrFVqXB9AQ==",
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
"node_modules/expo-linking": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-6.2.2.tgz",
diff --git a/mobile/package.json b/mobile/package.json
index bb5ccad657f3d29e351b0c11e79b759fd6ee215f..1afc8f7383e522475aa86d41c87f72abdcfc8d93 100644
--- a/mobile/package.json
+++ b/mobile/package.json
@@ -43,7 +43,8 @@
"react-native-screens": "~3.29.0",
"react-native-svg": "14.1.0",
"@react-native-picker/picker": "2.6.1",
- "@react-native-async-storage/async-storage": "1.21.0"
+ "@react-native-async-storage/async-storage": "1.21.0",
+ "expo-linear-gradient": "~12.7.2"
},
"devDependencies": {
"@babel/core": "^7.20.0",
diff --git a/mobile/src/common/components/animated_background.tsx b/mobile/src/common/components/animated_background.tsx
index 7c208a9eb3827e4690e671af31cabf456eee19b9..b06ea8e6c9cdc769ce8196df42407581e12a382b 100644
--- a/mobile/src/common/components/animated_background.tsx
+++ b/mobile/src/common/components/animated_background.tsx
@@ -1,13 +1,18 @@
import { Animated, Image, View } from "react-native";
import { PlaceInfoEntity } from "../../domain/entities/place_info_entity";
import { useAnimatedSelectedIndex } from "../../hooks/useAnimatedSelectedIndex";
+import { LinearGradient } from "expo-linear-gradient";
+import { LIGHT_THEME } from "../constants/theme";
interface AnimatedBackgroundProps {
- imageUri?: string;
- backgroundImageAnimation: Animated.Value;
-};
+ imageUri?: string;
+ backgroundImageAnimation: Animated.Value;
+}
-export const AnimatedBackground = ({ imageUri, backgroundImageAnimation }: AnimatedBackgroundProps) => {
+export const AnimatedBackground = ({
+ imageUri,
+ backgroundImageAnimation,
+}: AnimatedBackgroundProps) => {
return (
-
);
};
diff --git a/mobile/src/common/components/caroussel/caroussel.tsx b/mobile/src/common/components/caroussel/caroussel.tsx
index b78eee7555a84506652f13e3214f9fdd5465727d..edcdd508f0b83550dca90193f696a6e7f4be2761 100644
--- a/mobile/src/common/components/caroussel/caroussel.tsx
+++ b/mobile/src/common/components/caroussel/caroussel.tsx
@@ -1,9 +1,18 @@
-import { View, Animated, Text, Dimensions, Image, NativeSyntheticEvent, NativeScrollEvent } from "react-native";
+import {
+ View,
+ Animated,
+ Text,
+ Dimensions,
+ Image,
+ NativeSyntheticEvent,
+ NativeScrollEvent,
+} from "react-native";
import { PlaceInfoEntity } from "../../../domain/entities/place_info_entity";
import { useRef } from "react";
import { StateDataSource } from "../../../domain/datasources/state_datasource";
import { CarousselTile } from "./caroussel_tile";
import { router } from "expo-router";
+import { BLANK_ITEM_WIDTH, ITEM_WIDTH } from "../../constants/caroussel";
interface CarousselProps {
data: PlaceInfoEntity[];
@@ -11,9 +20,6 @@ interface CarousselProps {
onIndexChange?: (index: number) => void;
}
-const ITEM_WIDTH = Dimensions.get("window").width * 0.7;
-const BLANK_ITEM_WIDTH = Dimensions.get("window").width * 0.15;
-
export const Caroussel = ({ data, onPress, onIndexChange }: CarousselProps) => {
const scrollX = useRef(new Animated.Value(0)).current;
const finalData = [
@@ -36,57 +42,58 @@ export const Caroussel = ({ data, onPress, onIndexChange }: CarousselProps) => {
onIndexChange && onIndexChange(index);
});
return (
- item.id.toString()}
- horizontal
- showsHorizontalScrollIndicator={false}
- decelerationRate={0}
- initialNumToRender={1}
-
- bounces={false}
- snapToInterval={ITEM_WIDTH}
- onScroll={Animated.event([{ nativeEvent: { contentOffset: { x: scrollX } } }], {
- useNativeDriver: true,
- })}
- renderItem={({ item, index }) => {
- if (item.id === -1 || item.id === -2) {
- return ;
- }
- const inputRange = [
- (index - 2) * ITEM_WIDTH,
- (index - 1) * ITEM_WIDTH,
- index * ITEM_WIDTH,
- ];
+ item.id.toString()}
+ horizontal
+ showsHorizontalScrollIndicator={false}
+ decelerationRate={0}
+ initialNumToRender={1}
+ bounces={false}
+ snapToInterval={ITEM_WIDTH}
+ onScroll={Animated.event(
+ [{ nativeEvent: { contentOffset: { x: scrollX } } }],
+ {
+ useNativeDriver: true,
+ }
+ )}
+ renderItem={({ item, index }) => {
+ if (item.id === -1 || item.id === -2) {
+ return ;
+ }
+ const inputRange = [
+ (index - 2) * ITEM_WIDTH,
+ (index - 1) * ITEM_WIDTH,
+ index * ITEM_WIDTH,
+ ];
- const translateY = scrollX.interpolate({
- inputRange,
- outputRange: [100, 0, 100],
- });
+ const translateY = scrollX.interpolate({
+ inputRange,
+ outputRange: [100, 0, 100],
+ });
- const opacity = scrollX.interpolate({
- inputRange,
- outputRange: [0.6, 1, 0.6],
- });
- const scale = scrollX.interpolate({
- inputRange,
- outputRange: [0.8, 1, 0.8],
- });
- return (
- {
- if (item.id !== -1 && item.id !== -2) {
- onPress && onPress(item.id);
- }
- }
- }
- />
- );
- }}
- />
+ const opacity = scrollX.interpolate({
+ inputRange,
+ outputRange: [0.6, 1, 0.6],
+ });
+ const scale = scrollX.interpolate({
+ inputRange,
+ outputRange: [0.8, 1, 0.8],
+ });
+ return (
+ {
+ if (item.id !== -1 && item.id !== -2) {
+ onPress && onPress(item.id);
+ }
+ }}
+ />
+ );
+ }}
+ />
);
};
diff --git a/mobile/src/common/components/caroussel/caroussel_tile.tsx b/mobile/src/common/components/caroussel/caroussel_tile.tsx
index 65a61985b1f67f3e6baf10c4c84eb179028374b0..e4caa023f7801776d0f44e65649a6bbcef75380a 100644
--- a/mobile/src/common/components/caroussel/caroussel_tile.tsx
+++ b/mobile/src/common/components/caroussel/caroussel_tile.tsx
@@ -9,6 +9,7 @@ import {
} from "react-native";
import { PlaceInfoEntity } from "../../../domain/entities/place_info_entity";
import { Link } from "expo-router";
+import { ITEM_HEIGHT, ITEM_WIDTH } from "../../constants/caroussel";
interface CarousselTileProps {
onPress?: () => void;
@@ -18,10 +19,6 @@ interface CarousselTileProps {
opacity: Animated.AnimatedInterpolation;
}
-const ITEM_WIDTH = Dimensions.get("window").width * 0.7;
-const BLANK_ITEM_WIDTH = Dimensions.get("window").width * 0.15;
-const ITEM_HEIGHT = Dimensions.get("window").height * 0.7;
-
export const CarousselTile = memo(
({ translateY, scale, opacity, item, onPress }: CarousselTileProps) => {
return (
diff --git a/mobile/src/common/constants/caroussel.ts b/mobile/src/common/constants/caroussel.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b508be41a7e60094dd02ecc87175a3a008746ac0
--- /dev/null
+++ b/mobile/src/common/constants/caroussel.ts
@@ -0,0 +1,7 @@
+import { Dimensions } from "react-native";
+
+export const CARROUSEL_HEIGHT = Dimensions.get("window").height * 0.5;
+export const CARROUSEL_WIDTH = Dimensions.get("window").width;
+export const ITEM_WIDTH = CARROUSEL_WIDTH * 0.8;
+export const BLANK_ITEM_WIDTH = CARROUSEL_WIDTH * 0.1;
+export const ITEM_HEIGHT = CARROUSEL_HEIGHT * 0.7;
\ No newline at end of file
diff --git a/mobile/src/common/contexts/data_context.tsx b/mobile/src/common/contexts/data_context.tsx
index 85b25dee5c0735ca0f2359efbbf062b9703f4059..1dc6dc0878ea9a02eab65e062ebf765dd1c49009 100644
--- a/mobile/src/common/contexts/data_context.tsx
+++ b/mobile/src/common/contexts/data_context.tsx
@@ -43,37 +43,32 @@ const DataContext = createContext({
profileRepository: null
});
+const getProductionContext = (language: string): DataContextType => {
+ return {
+ statesRepository: new StateRepositoryImpl(new StateDataSourceProd(language)),
+ authRepository: new AuthRepositoryImpl(new AuthDatasourceProd()),
+ activityRepository: new ActivityRepositoryDev(new ActivityDatasourceProd()),
+ travelRepository: new TravelRepositoryImpl(new TravelDatasourceDev()),
+ routeRepository: new RouteRepositoryImpl(new RouteDataSourceDev()),
+ profileRepository: new ProfileRepositoryImpl(new ProfileDataSourceProd(language))
+ };
+}
+
+const getDevelopmentContext = (): DataContextType => {
+ return {
+ statesRepository: new StateRepositoryImpl(new StateDataSourceDev()),
+ authRepository: new AuthRepositoryImpl(new AuthDataSourceDev()),
+ activityRepository: new ActivityRepositoryDev(new ActivityDatasourceDev()),
+ travelRepository: new TravelRepositoryImpl(new TravelDatasourceDev()),
+ routeRepository: new RouteRepositoryImpl(new RouteDataSourceDev()),
+ profileRepository: new ProfileRepositoryImpl(new ProfileDataSourceDev())
+ };
+}
+
export const DataContextProvider = ({ children }: DataContextProviderProps) => {
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 authRepository = new AuthRepositoryImpl(authDataSource);
- //
- 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 ProfileDataSourceProd();
- const profileRepository = new ProfileRepositoryImpl(profileDataSource);
- const value = {
- statesRepository,
- authRepository,
- activityRepository,
- travelRepository,
- routeRepository,
- profileRepository
- };
+ const value = getDevelopmentContext();
return (
diff --git a/mobile/src/components/activity_bottom_sheet/activity_bottom_sheet.tsx b/mobile/src/components/activity_bottom_sheet/activity_bottom_sheet.tsx
index 4fd826d2db91d43e9e67751b779fc1dec657aee3..ae97e81a2265e0dabfe3eab13f1ce7a1fe0172ef 100644
--- a/mobile/src/components/activity_bottom_sheet/activity_bottom_sheet.tsx
+++ b/mobile/src/components/activity_bottom_sheet/activity_bottom_sheet.tsx
@@ -58,7 +58,7 @@ export const ActivityBottomSheet = ({
item}
ItemSeparatorComponent={() => }
diff --git a/mobile/src/components/activity_tile/activity_tile.tsx b/mobile/src/components/activity_tile/activity_tile.tsx
index bea8a19d35b63f186d85f39a36e0931a76a69c1c..73471a4d04cc6fcf419c3eaad585c9b1454449cf 100644
--- a/mobile/src/components/activity_tile/activity_tile.tsx
+++ b/mobile/src/components/activity_tile/activity_tile.tsx
@@ -1,6 +1,7 @@
import { View, Text, StyleSheet, Image, TouchableOpacity } from "react-native";
import { ActivityInfoEntity } from "../../domain/entities/activity_info_entity";
import { LIGHT_THEME } from "../../common/constants/theme";
+import { ScrollView } from "react-native-gesture-handler";
interface ActivityTileProps {
activity: ActivityInfoEntity;
@@ -21,6 +22,11 @@ export const ActivityTile = ({ activity, onPress }: ActivityTileProps) => {
{activity.name}
{activity.location}
+
+ {
+ activity.tags?.map(tag => {tag})
+ }
+
);
@@ -28,7 +34,7 @@ export const ActivityTile = ({ activity, onPress }: ActivityTileProps) => {
const styles = StyleSheet.create({
container: {
- height: 300,
+ height: 320,
width: "100%",
backgroundColor: LIGHT_THEME.color.white,
elevation: 5,
@@ -44,4 +50,13 @@ const styles = StyleSheet.create({
fontSize: 18,
fontWeight: "bold",
},
+ tag: {
+ backgroundColor: LIGHT_THEME.color.primary,
+ color: LIGHT_THEME.color.white,
+ height: 30,
+ paddingVertical: 5,
+ paddingHorizontal: 10,
+ borderRadius: 15,
+ marginHorizontal: 5,
+ },
});
diff --git a/mobile/src/hooks/useAnimatedSelectedIndex.ts b/mobile/src/hooks/useAnimatedSelectedIndex.ts
index 4f56c218173cc032ae861133406ee887351b5355..4c2f8549e5c195644ec5f9ce99ea117e063cfdd5 100644
--- a/mobile/src/hooks/useAnimatedSelectedIndex.ts
+++ b/mobile/src/hooks/useAnimatedSelectedIndex.ts
@@ -9,6 +9,8 @@ export const useAnimatedSelectedIndex = (startMilliseconds: number = 500, endMil
const onIndexChange = useCallback((index: number) => {
if (index !== selectedState.current) {
+ setTimeout(() => {}, 100);
+ if (index == selectedState.current) return;
console.log("Index changed to: ", index);
selectedState.current = index;
Animated.timing(backgroundImageAnimation, {
diff --git a/mobile/src/infrastructure/models/prod/activity_model.ts b/mobile/src/infrastructure/models/prod/activity_model.ts
index 228e187d89a96d037f2fea9c2c01415ec13bf59a..6327e300c0e60ef1701279960257df88d62e49cc 100644
--- a/mobile/src/infrastructure/models/prod/activity_model.ts
+++ b/mobile/src/infrastructure/models/prod/activity_model.ts
@@ -10,4 +10,11 @@ export interface ActivityModel {
closeAt: number;
startDate: Date | null;
endDate: Date | null;
+ categories?: TagModel[];
+}
+
+export interface TagModel {
+ idCategory: number;
+ language: string;
+ name: string;
}
diff --git a/mobile/src/infrastructure/utils/place_utils.ts b/mobile/src/infrastructure/utils/place_utils.ts
index 3e16b116e32ad5376abe06599128da895d73aaca..d0937a3bccec62471452498556d67203651a16b9 100644
--- a/mobile/src/infrastructure/utils/place_utils.ts
+++ b/mobile/src/infrastructure/utils/place_utils.ts
@@ -10,6 +10,6 @@ export const placeModelToEntity = (placeModel: ActivityModel): ActivityInfoEntit
location: placeModel.coords,
townId: placeModel.idTown,
available: 'open',
- tags: undefined,
+ tags: placeModel.categories?.map(tag => tag.name) || undefined,
}
}
\ 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 50ae766950dc075a071fabca060abc5eb284ca07..6a9e0a3af089a747874ee23433698e8610ded31e 100644
--- a/mobile/src/profile/domain/datasources/profile_datasource.ts
+++ b/mobile/src/profile/domain/datasources/profile_datasource.ts
@@ -2,6 +2,7 @@ import { IOption } from "../../../common/domain/entities/option";
export interface ProfileDataSource {
getInterests: () => Promise;
+ getUserInterests: () => Promise;
saveInterests: (options: IOption[]) => Promise;
setUpProfile: (birthdate: string, interests: IOption[]) => Promise;
changePassword: (oldPassword: string, newPassword: string) => Promise;
diff --git a/mobile/src/profile/domain/repositories/profile_repository.ts b/mobile/src/profile/domain/repositories/profile_repository.ts
index 98634810fd001fb0b1ee3e233bc24fbbce53d4f7..728307e27caa3e3783e4915cb399dc9db8aa0992 100644
--- a/mobile/src/profile/domain/repositories/profile_repository.ts
+++ b/mobile/src/profile/domain/repositories/profile_repository.ts
@@ -2,6 +2,7 @@ import { IOption } from "../../../common/domain/entities/option";
export interface ProfileRepository {
getInterests: () => Promise;
+ getUserInterests: () => Promise;
saveInterests: (options: IOption[]) => Promise;
setUpProfile: (birthdate: string, interests: IOption[]) => Promise;
changePassword: (oldPassword: string, newPassword: string) => Promise;
diff --git a/mobile/src/profile/hooks/useChangeInterests.ts b/mobile/src/profile/hooks/useChangeInterests.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cb1449f7cfa192347ecdc2bce63d5cc8c3f54ebf
--- /dev/null
+++ b/mobile/src/profile/hooks/useChangeInterests.ts
@@ -0,0 +1,33 @@
+import { useEffect, useState } from "react";
+import { useGetInterests } from "./useGetInterests";
+import { IOption } from "../../common/domain/entities/option";
+import { ApiRequestStatus } from "../../common/constants/api_request_states";
+import { useDataContext } from "../../common/contexts/data_context";
+
+
+export const useChangeInterests = () => {
+ const { profileRepository } = useDataContext();
+ const [interests, setInterests] = useState([]);
+
+ const toogleInterest = (id: number) => {
+ const newInterests = interests.map((interest) => {
+ if (interest.id === id) {
+ return { ...interest, isSelected: !interest.isSelected };
+ }
+ return interest;
+ });
+ setInterests(newInterests);
+ };
+
+ const onSubmit = async () => {
+ const selectedInterests = interests
+ .filter((interest) => interest.isSelected);
+ await profileRepository!.saveInterests(selectedInterests);
+ };
+
+ const setAllInterests = (interests: IOption[]) => {
+ setInterests(interests);
+ };
+
+ return { toogleInterest, interests, onSubmit, setAllInterests };
+};
diff --git a/mobile/src/profile/hooks/useGetUserInterests.ts b/mobile/src/profile/hooks/useGetUserInterests.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a14556c1acff6f3b1635389032299ca16a089afb
--- /dev/null
+++ b/mobile/src/profile/hooks/useGetUserInterests.ts
@@ -0,0 +1,12 @@
+import { useDataContext } from "../../common/contexts/data_context"
+import { IOption } from "../../common/domain/entities/option"
+import { useGet } from "../../hooks/useGet"
+
+export const useGetUserInterests = () => {
+ const { profileRepository } = useDataContext()
+ const callback = async () => {
+ return profileRepository!.getUserInterests();
+ }
+ const { data, requestStatus } = useGet(callback);
+ return { data, requestStatus };
+}
\ No newline at end of file
diff --git a/mobile/src/profile/hooks/useSelectInterests.ts b/mobile/src/profile/hooks/useSelectInterests.ts
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/mobile/src/profile/hooks/useSetUpProfile.ts b/mobile/src/profile/hooks/useSetUpProfile.ts
index 9acb88383871614d8500d1efbb94b3e4f5ccf8b1..bc04cd8a3c9f83941598d5807696d0194770c103 100644
--- a/mobile/src/profile/hooks/useSetUpProfile.ts
+++ b/mobile/src/profile/hooks/useSetUpProfile.ts
@@ -6,6 +6,7 @@ import { ApiRequestStatus } from "../../common/constants/api_request_states";
import { useDataContext } from "../../common/contexts/data_context";
import { useSetUp } from "../../common/contexts/set_up_context";
import { router } from "expo-router";
+import { useChangeInterests } from "./useChangeInterests";
export type SetUpProfileFormValues = {
interests: number[];
@@ -13,38 +14,34 @@ export type SetUpProfileFormValues = {
};
export const useSetUpProfile = () => {
- const { control, handleSubmit, setValue } = useForm();
- const { setFirstTime } = useSetUp();
- const { interests: allCategories, requestStatus } = useGetInterests();
- // TODO: Si se agregan mas campos que requieran datos de la API, debemos procurar que todos los request status esten en success
- const [interests, setInterests] = useState([]);
+ const { interests: allCategories, requestStatus: changeInterestsRequest } = useGetInterests();
+ const { interests, toogleInterest, onSubmit: onSubmitInterests, setAllInterests } = useChangeInterests();
+ const [requestStatus, setRequestStatus] = useState(ApiRequestStatus.LOADING);
+ // const { control, handleSubmit, setValue, getValues } = useForm();
+ const { setFirstTime } = useSetUp();
+
useEffect(() => {
- if (requestStatus === ApiRequestStatus.SUCCESS && allCategories && allCategories.length > 0) {
- setInterests([...allCategories]);
+ const requests = [changeInterestsRequest];
+ if (requests.every((request) => request === ApiRequestStatus.SUCCESS)) {
+ setAllInterests(allCategories!);
+ setRequestStatus(ApiRequestStatus.SUCCESS);
}
- }, [requestStatus]);
-
- const toogleInterest = (id: number) => {
- console.log("toogle");
- const newInterests = interests.map((interest) => {
- if (interest.id === id) {
- return { ...interest, isSelected: !interest.isSelected };
- }
- return interest;
- });
- setInterests(newInterests);
- };
+ }, [changeInterestsRequest]);
+
const onSubmit = async () => {
- setValue("interests", interests.filter((interest) => interest.isSelected).map((interest) => interest.id));
- await handleSubmit((data) => {
- //TODO: Implementar la logica de envio de datos
- //TODO: Verificar si se enviará la fecha de nacimiento y los intereses en el mismo request o por separado
- console.log(data);
- })();
- await setFirstTime();
- router.replace("(tabs)");
+/* await handleSubmit((data) => {
+
+ })(); */
+
+ try {
+ await onSubmitInterests();
+ await setFirstTime();
+ router.replace("/(tabs)");
+ } catch (error) {
+ console.log(error);
+ }
};
- return { control, onSubmit, toogleInterest, interests, requestStatus };
+ return { onSubmit, toogleInterest, interests, requestStatus };
};
diff --git a/mobile/src/profile/hooks/useUpdateInterests.ts b/mobile/src/profile/hooks/useUpdateInterests.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fdee8444c5bc4de5e9f41b846b3c60c8b25ee8e0
--- /dev/null
+++ b/mobile/src/profile/hooks/useUpdateInterests.ts
@@ -0,0 +1,51 @@
+import { useEffect, useState } from "react";
+import { useChangeInterests } from "./useChangeInterests";
+import { useGetUserInterests } from "./useGetUserInterests";
+import { ApiRequestStatus } from "../../common/constants/api_request_states";
+import { useGetInterests } from "./useGetInterests";
+import { router } from "expo-router";
+
+export const useUpdateInterests = () => {
+ const { data: userCategories, requestStatus: userInterestsRequest } =
+ useGetUserInterests();
+ const { interests: allCategories, requestStatus: changeInterestsRequest } =
+ useGetInterests();
+ const {
+ interests,
+ toogleInterest,
+ onSubmit: onSubmitInterests,
+ setAllInterests,
+ } = useChangeInterests();
+ const [requestStatus, setRequestStatus] = useState(
+ ApiRequestStatus.LOADING
+ );
+
+ useEffect(() => {
+ const requests = [changeInterestsRequest, userInterestsRequest];
+ if (requests.every((request) => request === ApiRequestStatus.SUCCESS)) {
+ setAllInterests(
+ allCategories!.map((category) => ({
+ ...category,
+ isSelected: userCategories!.some(
+ (userCategory) => userCategory.id === category.id
+ ),
+ }))
+ );
+ setRequestStatus(ApiRequestStatus.SUCCESS);
+ }
+ }, [changeInterestsRequest, userInterestsRequest]);
+
+ const onSubmit = async () => {
+ /* await handleSubmit((data) => {
+
+ })(); */
+
+ try {
+ await onSubmitInterests();
+ router.back();
+ } catch (error) {
+ console.log(error);
+ }
+ };
+ return { onSubmit, toogleInterest, interests, requestStatus };
+};
diff --git a/mobile/src/profile/infrastructure/datasources/dev/profile_datasource.ts b/mobile/src/profile/infrastructure/datasources/dev/profile_datasource.ts
index f7e598af23a97f74f462b8167a28d66fedbf5288..863a94fef02a15d1a708398ac6cb5fbb81bbe66d 100644
--- a/mobile/src/profile/infrastructure/datasources/dev/profile_datasource.ts
+++ b/mobile/src/profile/infrastructure/datasources/dev/profile_datasource.ts
@@ -1,6 +1,13 @@
import { IOption } from '../../../../common/domain/entities/option';
import { ProfileDataSource } from '../../../domain/datasources/profile_datasource';
export class ProfileDataSourceDev implements ProfileDataSource {
+ async getUserInterests(): Promise {
+ const interests = await this.getInterests();
+ interests[0].isSelected = true;
+ interests[1].isSelected = true;
+ interests[2].isSelected = true;
+ return interests;
+ }
async getInterests(): Promise {
return [
{ id: 1, name: 'Tecnología', isSelected: false },
diff --git a/mobile/src/profile/infrastructure/datasources/prod/profile_datasource.ts b/mobile/src/profile/infrastructure/datasources/prod/profile_datasource.ts
index eee7b181c9fb28d18f058986906113a78a0eb9ea..7384f5e73e5e6f898a62cad588776d6348853bdf 100644
--- a/mobile/src/profile/infrastructure/datasources/prod/profile_datasource.ts
+++ b/mobile/src/profile/infrastructure/datasources/prod/profile_datasource.ts
@@ -2,25 +2,65 @@ 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";
+import { CategoryModel } from "../../model/categorie_model";
+import { categoryModelToOption } from "../../utils/category";
export class ProfileDataSourceProd implements ProfileDataSource {
- async getInterests(): Promise {
- throw new Error('Method not implemented.');
+ private readonly lang: string;
+ constructor(lang: string) {
+ this.lang = lang;
+ }
+ async getUserInterests(): Promise {
+ const {data, status} = await axios.get(`${API_URL}/user/prefered-categories?lang=${this.lang}`);
+ if (status !== 200) {
+ throw new Error("Error getting user interests");
}
-
- async saveInterests(options: IOption[]): Promise {
- throw new Error('Method not implemented.');
+ const categories = data.map(categoryModelToOption);
+ return categories.map((category) => ({
+ ...category,
+ isSelected: true,
+ }));
+ }
+ async getInterests(): Promise {
+ //TODO: Implement this method
+ const { status, data } = await axios.get(
+ `${API_URL}/category?lang=${this.lang}`
+ );
+ if (status !== 200) {
+ throw new Error("Error getting interests");
}
+ return data.map(categoryModelToOption);
+ }
- 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);
+ async saveInterests(options: IOption[]): Promise {
+ const payload = {
+ idCategories: options.map((option) => option.id),
+ };
+ const { status } = await axios.patch(
+ `${API_URL}/user/update-prefered-categories`,
+ payload
+ );
+
+ if (status !== 200) {
+ throw new Error("Error updating interests");
}
+ }
+
+ 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/model/categorie_model.ts b/mobile/src/profile/infrastructure/model/categorie_model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c46975097a5439d552106a590f7e1dfd2bcc54a9
--- /dev/null
+++ b/mobile/src/profile/infrastructure/model/categorie_model.ts
@@ -0,0 +1,4 @@
+export interface CategoryModel {
+ idCategory: number;
+ name: string;
+}
diff --git a/mobile/src/profile/infrastructure/repositories/profile_repository.ts b/mobile/src/profile/infrastructure/repositories/profile_repository.ts
index 4dea398544246e0c303255c7fff907195e023e3c..8ca0c03334a4cab61fb81687396593a2d3ba08a0 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
){}
+ getUserInterests(): Promise{
+ return this.dataSource.getUserInterests();
+ }
async changePassword (oldPassword: string, newPassword: string): Promise {
return this.dataSource.changePassword(oldPassword, newPassword);
};
diff --git a/mobile/src/profile/infrastructure/utils/category.ts b/mobile/src/profile/infrastructure/utils/category.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2b51d315b5627bdb8245eb39326b9e6d7e6645e6
--- /dev/null
+++ b/mobile/src/profile/infrastructure/utils/category.ts
@@ -0,0 +1,8 @@
+import { IOption } from "../../../common/domain/entities/option";
+import { CategoryModel } from "../model/categorie_model";
+
+export const categoryModelToOption = (category: CategoryModel): IOption => ({
+ id: category.idCategory,
+ name: category.name,
+ isSelected: false,
+});
diff --git a/mobile/src/profile/screens/change_interests_screen.tsx b/mobile/src/profile/screens/change_interests_screen.tsx
index c08f54de835a14d60bef76b967a746322beb55c5..0f647bac691df27a9e6b7ebac19fa98fedd2426c 100644
--- a/mobile/src/profile/screens/change_interests_screen.tsx
+++ b/mobile/src/profile/screens/change_interests_screen.tsx
@@ -3,98 +3,30 @@ import { LIGHT_THEME } from "../../common/constants/theme";
import { ScrollView } from "react-native-gesture-handler";
import { useState } from "react";
import { MultipleOptionPicker } from "../components/multiple_option_pickeer";
+import { useUpdateInterests } from "../hooks/useUpdateInterests";
+import { ApiRequestStatus } from "../../common/constants/api_request_states";
+import { InterestSlide } from "../components/interest_slide";
+import { SlideControl } from "../../common/components/slide_control";
export const ChangeInterestsScreen = () => {
- const [options, setOptions] = useState( [
- {
- id: 1,
- name: "Arquitectura",
- isSelected: false,
- },
- {
- id: 2,
- name: "Ciencia",
- isSelected: false,
- },
- {
- id: 3,
- name: "Cultura",
- isSelected: false,
- },
- {
- id: 4,
- name: "Deportes",
- isSelected: false,
- },
- {
- id: 5,
- name: "Economía",
- isSelected: false,
- },
- {
- id: 6,
- name: "Educación",
- isSelected: false,
- },
- {
- id: 7,
- name: "Entretenimiento",
- isSelected: false,
- },
- {
- id: 8,
- name: "Gastronomía",
- isSelected: false,
- },
- {
- id: 9,
- name: "Historia",
- isSelected: false,
- },
- {
- id: 10,
- name: "Moda",
- isSelected: false,
- },
- {
- id: 11,
- name: "Música",
- isSelected: false,
- },
- {
- id: 12,
- name: "Política",
- isSelected: false,
- },
- {
- id: 13,
- name: "Salud",
- isSelected: false,
- },
- {
- id: 14,
- name: "Tecnología",
- isSelected: false,
- },
- ]);
+ const { toogleInterest: onToogleOption, interests: options, requestStatus, onSubmit } = useUpdateInterests();
+ if (requestStatus === ApiRequestStatus.LOADING) {
+ return Loading...;
+ }
- const onToogleOption = (optionId: number) => {
- setOptions(
- options.map((option) =>
- option.id === optionId
- ? { ...option, isSelected: !option.isSelected }
- : option
- )
- );
- };
+ if (requestStatus === ApiRequestStatus.ERROR) {
+ return Error;
+ }
+
+ const onFinish = () => {
+ onSubmit();
+ }
return (
-
- {`Selecciona las categorías que te interesan, puedes cambiarlos en la pestaña de cuenta > Cambiar intereses`}
-
-
+
+ {}} onPrevious={() => {}} isFirst isLast />
);
};
diff --git a/mobile/src/profile/screens/first_time_config_screen.tsx b/mobile/src/profile/screens/first_time_config_screen.tsx
index d5fa60225e0417b2ea131b2bb5250099dec110a8..16b7bf2184421373c60b54387b82cf01daaabd6c 100644
--- a/mobile/src/profile/screens/first_time_config_screen.tsx
+++ b/mobile/src/profile/screens/first_time_config_screen.tsx
@@ -15,15 +15,13 @@ import { useSlideControl } from "../hooks/useSlideControl";
import { router } from "expo-router";
export const FirstTimeComfigScreen = () => {
- const { onSubmit, toogleInterest, interests, control } = useSetUpProfile();
+ const { onSubmit, toogleInterest, interests } = useSetUpProfile();
const onFinishCallback = () => {
onSubmit();
};
- console.log('render');
const { onFinish, onNext, onPrevious, currentSlide } = useSlideControl(onFinishCallback);
const slides = [
,
- ,
];
return (
diff --git a/mobile/src/screens/state_selection/state_selection_page.tsx b/mobile/src/screens/state_selection/state_selection_page.tsx
index 358e2ab73c37f7e6b98548455ad796ee1ffdb58d..c46901e1061c92921716b1fd476c65cde50f3bb2 100644
--- a/mobile/src/screens/state_selection/state_selection_page.tsx
+++ b/mobile/src/screens/state_selection/state_selection_page.tsx
@@ -2,16 +2,24 @@ import { View, ActivityIndicator, Text } from "react-native";
import { pageStyles } from "../page_styles";
import { useGetStates } from "../../hooks/useGetStates";
import { ApiRequestStatus } from "../../common/constants/api_request_states";
-import { Caroussel } from "../../common/components/caroussel/caroussel";
+import {
+ Caroussel
+} from "../../common/components/caroussel/caroussel";
import { router } from "expo-router";
import { useAnimatedSelectedIndex } from "../../hooks/useAnimatedSelectedIndex";
import { AnimatedBackground } from "../../common/components/animated_background";
import { ErrorPage } from "../error_page/error_page";
+import { LinearGradient } from "expo-linear-gradient";
+import { LIGHT_THEME } from "../../common/constants/theme";
+import { useDataContext } from "../../common/contexts/data_context";
+import { useAuth } from "../../auth/contexts/auth_context";
+import { CARROUSEL_HEIGHT, CARROUSEL_WIDTH } from "../../common/constants/caroussel";
export const StateSelectionPage = () => {
const { data, requestStatus, refresh } = useGetStates();
const { selectedStateIndex, onIndexChange, backgroundImageAnimation } =
useAnimatedSelectedIndex(200, 200);
+ const { user } = useAuth();
if (requestStatus === ApiRequestStatus.LOADING) {
return (
@@ -22,9 +30,7 @@ export const StateSelectionPage = () => {
}
if (requestStatus === ApiRequestStatus.ERROR || !data) {
- return (
-
- );
+ return ;
}
const handleOnPress = (id: number) => {
@@ -32,16 +38,43 @@ export const StateSelectionPage = () => {
};
return (
-
-
-
+
+
+ {`Hola, ${user?.name} ${user?.lastName}!`}
+
+
+
+
+
+
);
};