fix mobile profile flow and onboarding edge cases

This commit is contained in:
echo 2026-03-29 11:23:49 +02:00
parent 10b58245f5
commit 8275da687b
4 changed files with 51 additions and 60 deletions

View File

@ -24,7 +24,12 @@
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#ffffff"
},
"permissions": ["CAMERA", "POST_NOTIFICATIONS"]
"permissions": [
"CAMERA",
"POST_NOTIFICATIONS",
"android.permission.CAMERA"
],
"package": "com.anonymous.fitai"
},
"web": {
"favicon": "./assets/favicon.png"

View File

@ -1,11 +1,11 @@
module.exports = {
preset: 'react-native',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
moduleNameMapping: {
'^@/(.*)$': '<rootDir>/src/$1',
preset: "react-native",
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1",
},
transformIgnorePatterns: [
'node_modules/(?!(jest-)?react-native|@react-native|expo|@expo|@react-navigation)',
"node_modules/(?!(jest-)?react-native|@react-native|expo|@expo|@react-navigation)",
],
}
};

View File

@ -33,6 +33,7 @@ export default function TabLayout() {
const token = await getToken();
if (!token) {
log.warn("No token available for onboarding check");
setOnboardingChecked(true);
return;
}

View File

@ -16,8 +16,7 @@ import { Ionicons } from "@expo/vector-icons";
import { useTheme } from "../contexts/ThemeContext";
import { MinimalCard } from "../components/MinimalCard";
import { MinimalButton } from "../components/MinimalButton";
import { IconContainer } from "../components/IconContainer";
import { API_BASE_URL } from "../config/api";
import { fitnessProfileApi, type FitnessProfile } from "../api/fitnessProfile";
interface FitnessProfileData {
height?: number;
@ -110,40 +109,32 @@ export default function FitnessProfileScreen() {
try {
setFetchingProfile(true);
const token = await getToken();
const response = await fetch(
`${API_BASE_URL}/api/profile/fitness?userId=${userId}`,
{
headers: {
Authorization: `Bearer ${token}`,
},
},
);
if (!token || !userId) {
return;
}
if (response.ok) {
const data = await response.json();
if (data.profile) {
let activityLevel = data.profile.activityLevel || "";
const profile = await fitnessProfileApi.getFitnessProfile(token);
if (profile) {
let activityLevel = profile.activityLevel || "";
if (activityLevel === "light") activityLevel = "lightly_active";
if (activityLevel === "moderate") activityLevel = "moderately_active";
if (activityLevel === "active") activityLevel = "very_active";
setProfileData({
height: data.profile.height,
weight: data.profile.weight,
age: data.profile.age,
gender: data.profile.gender || "",
fitnessGoal: Array.isArray(data.profile.fitnessGoals)
? data.profile.fitnessGoals[0]
: typeof data.profile.fitnessGoals === "string"
? JSON.parse(data.profile.fitnessGoals)[0]
height: profile.height,
weight: profile.weight,
age: profile.age,
gender: profile.gender || "",
fitnessGoal: Array.isArray(profile.fitnessGoals)
? profile.fitnessGoals[0]
: "",
activityLevel: activityLevel,
medicalConditions: data.profile.medicalConditions || "",
allergies: data.profile.allergies || "",
injuries: data.profile.injuries || "",
medicalConditions: profile.medicalConditions || "",
allergies: profile.allergies || "",
injuries: profile.injuries || "",
});
}
}
} catch (error) {
console.error("Error fetching profile:", error);
} finally {
@ -155,37 +146,31 @@ export default function FitnessProfileScreen() {
try {
setLoading(true);
const token = await getToken();
if (!token || !userId) {
Alert.alert("Error", "Authentication required");
return;
}
const dataToSave = {
const dataToSave: Omit<FitnessProfile, "id"> = {
userId: userId,
height: profileData.height,
weight: profileData.weight,
age: profileData.age,
gender: profileData.gender || undefined,
gender: (profileData.gender as FitnessProfile["gender"]) || undefined,
fitnessGoals: profileData.fitnessGoal ? [profileData.fitnessGoal] : [],
activityLevel: profileData.activityLevel || undefined,
activityLevel:
(profileData.activityLevel as FitnessProfile["activityLevel"]) ||
undefined,
medicalConditions: profileData.medicalConditions,
allergies: profileData.allergies,
injuries: profileData.injuries,
};
const response = await fetch(`${API_BASE_URL}/api/profile/fitness`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(dataToSave),
});
await fitnessProfileApi.createFitnessProfile(dataToSave, token);
if (response.ok) {
Alert.alert("Success", "Fitness profile saved successfully!", [
{ text: "OK", onPress: () => router.back() },
]);
} else {
const error = await response.json();
Alert.alert("Error", error.error || "Failed to save profile");
}
} catch (error) {
console.error("Error saving profile:", error);
Alert.alert("Error", "Failed to save fitness profile");