feat: implement user profile management (Fase 2)
- Add useProfile hook for managing user data - Add Profile page to view/edit user information - Add Settings layout with sidebar navigation - Add Settings pages: Profile, Password, Notifications, Account - Add user dropdown menu in Header with Profile/Settings links - Add protected routes for /settings/* pages - Implement profile update and password change functionality Completes Fase 2 of frontend missing features analysis from todo.md
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import api from '@/lib/api';
|
||||
import { showToast } from '@/components/ui/toast-utils';
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
email: string;
|
||||
full_name: string;
|
||||
is_active: boolean;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export function useProfile() {
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
// Fetch user profile
|
||||
const getProfile = useCallback(async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const response = await api.get('/auth/me');
|
||||
const userData = response.data;
|
||||
setUser(userData);
|
||||
return userData;
|
||||
} catch (err: any) {
|
||||
const message = err.response?.data?.detail || 'Failed to load profile';
|
||||
setError(message);
|
||||
showToast({
|
||||
title: 'Error loading profile',
|
||||
description: message,
|
||||
variant: 'destructive'
|
||||
});
|
||||
return null;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Update user profile
|
||||
const updateProfile = useCallback(async (data: Partial<User>) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const response = await api.put('/auth/me', data);
|
||||
const updatedUser = response.data;
|
||||
setUser(updatedUser);
|
||||
showToast({
|
||||
title: 'Profile updated',
|
||||
description: 'Your profile has been successfully updated'
|
||||
});
|
||||
return updatedUser;
|
||||
} catch (err: any) {
|
||||
const message = err.response?.data?.detail || 'Failed to update profile';
|
||||
setError(message);
|
||||
showToast({
|
||||
title: 'Update failed',
|
||||
description: message,
|
||||
variant: 'destructive'
|
||||
});
|
||||
throw err;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Change password
|
||||
const changePassword = useCallback(async (passwordData: {
|
||||
current_password: string;
|
||||
new_password: string;
|
||||
}) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
await api.post('/auth/change-password', passwordData);
|
||||
showToast({
|
||||
title: 'Password changed',
|
||||
description: 'Your password has been successfully updated'
|
||||
});
|
||||
return true;
|
||||
} catch (err: any) {
|
||||
const message = err.response?.data?.detail || 'Failed to change password';
|
||||
setError(message);
|
||||
showToast({
|
||||
title: 'Password change failed',
|
||||
description: message,
|
||||
variant: 'destructive'
|
||||
});
|
||||
throw err;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Load profile on mount
|
||||
useEffect(() => {
|
||||
getProfile();
|
||||
}, [getProfile]);
|
||||
|
||||
return {
|
||||
user,
|
||||
loading,
|
||||
error,
|
||||
getProfile,
|
||||
updateProfile,
|
||||
changePassword
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user