Profile saving works

This commit is contained in:
AG
2025-11-20 22:56:38 +02:00
parent 17ae81d5d9
commit 84417847fd
6 changed files with 39 additions and 11 deletions

View File

@@ -69,6 +69,10 @@ function App() {
setLanguage(lang);
};
const handleUserUpdate = (updatedUser: User) => {
setCurrentUser(updatedUser);
};
const handleStartSession = (plan?: WorkoutPlan) => {
if (!currentUser) return;
@@ -179,6 +183,7 @@ function App() {
onLogout={handleLogout}
lang={language}
onLanguageChange={handleLanguageChange}
onUserUpdate={handleUserUpdate}
/>
)}
</div>

View File

@@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';
import { User, Language, ExerciseDef, ExerciseType } from '../types';
import { createUser, changePassword, updateUserProfile, getCurrentUserProfile, getUsers, deleteUser, toggleBlockUser, adminResetPassword } from '../services/auth';
import { createUser, changePassword, updateUserProfile, getCurrentUserProfile, getUsers, deleteUser, toggleBlockUser, adminResetPassword, getMe } from '../services/auth';
import { getExercises, saveExercise } from '../services/storage';
import { User as UserIcon, LogOut, Save, Shield, UserPlus, Lock, Calendar, Ruler, Scale, PersonStanding, Globe, ChevronDown, ChevronUp, Trash2, Ban, KeyRound, Dumbbell, Archive, ArchiveRestore, Pencil, X, Plus, Percent } from 'lucide-react';
import { t } from '../services/i18n';
@@ -12,9 +12,10 @@ interface ProfileProps {
onLogout: () => void;
lang: Language;
onLanguageChange: (lang: Language) => void;
onUserUpdate?: (user: User) => void;
}
const Profile: React.FC<ProfileProps> = ({ user, onLogout, lang, onLanguageChange }) => {
const Profile: React.FC<ProfileProps> = ({ user, onLogout, lang, onLanguageChange, onUserUpdate }) => {
// Profile Data
const [weight, setWeight] = useState<string>('');
const [height, setHeight] = useState<string>('');
@@ -51,19 +52,20 @@ const Profile: React.FC<ProfileProps> = ({ user, onLogout, lang, onLanguageChang
useEffect(() => {
const p = getCurrentUserProfile(user.id);
if (p) {
if (p.weight) setWeight(p.weight.toString());
if (p.height) setHeight(p.height.toString());
if (p.gender) setGender(p.gender);
if (p.birthDate) setBirthDate(new Date(p.birthDate).toISOString().split('T')[0]);
// Load profile data from user object (comes from /auth/me endpoint)
if (user.profile) {
if (user.profile.weight) setWeight(user.profile.weight.toString());
if (user.profile.height) setHeight(user.profile.height.toString());
if (user.profile.gender) setGender(user.profile.gender);
if (user.profile.birthDate) setBirthDate(new Date(user.profile.birthDate).toISOString().split('T')[0]);
}
if (user.role === 'ADMIN') {
refreshUserList();
}
refreshExercises();
}, [user.id, user.role]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [user.id, user.role, JSON.stringify(user.profile)]);
const refreshUserList = () => {
setAllUsers(getUsers());
@@ -89,12 +91,17 @@ const Profile: React.FC<ProfileProps> = ({ user, onLogout, lang, onLanguageChang
weight: parseFloat(weight) || undefined,
height: parseFloat(height) || undefined,
gender: gender as any,
birthDate: birthDate ? new Date(birthDate).getTime() : undefined,
birthDate: birthDate ? new Date(birthDate).toISOString() : undefined,
language: lang
});
if (res.success) {
showSnackbar(t('profile_saved', lang) || 'Profile saved successfully', 'success');
// Refetch user data to update the profile in the app state
const userRes = await getMe();
if (userRes.success && userRes.user && onUserUpdate) {
onUserUpdate(userRes.user);
}
} else {
showSnackbar(res.error || 'Failed to save profile', 'error');
}

Binary file not shown.

View File

@@ -105,6 +105,13 @@ router.patch('/profile', async (req, res) => {
if (!token) return res.status(401).json({ error: 'Unauthorized' });
const { userId, profile } = req.body;
console.log('DEBUG: Updating profile for', userId, profile);
// Convert birthDate from timestamp to Date object if needed
if (profile.birthDate) {
// Handle both number (timestamp) and string (ISO)
profile.birthDate = new Date(profile.birthDate);
}
// Verify token
const decoded = jwt.verify(token, JWT_SECRET) as any;

View File

@@ -34,5 +34,14 @@ export const api = {
});
if (!res.ok) throw new Error(await res.text());
return res.json();
},
patch: async (endpoint: string, data: any) => {
const res = await fetch(`${API_URL}${endpoint}`, {
method: 'PATCH',
headers: headers(),
body: JSON.stringify(data)
});
if (!res.ok) throw new Error(await res.text());
return res.json();
}
};

View File

@@ -68,7 +68,7 @@ export interface UserProfile {
weight?: number;
height?: number;
gender?: 'MALE' | 'FEMALE' | 'OTHER';
birthDate?: number; // timestamp
birthDate?: number | string; // timestamp or ISO string
language?: Language;
}