Compare commits

..

No commits in common. "d9868dd49f055a24de10a56a6d4581ab1b319200" and "4ce7d2ec07c280a53999ca11c5ab366b6fc8bfee" have entirely different histories.

4 changed files with 12 additions and 98 deletions

View File

@ -6,13 +6,13 @@
'use client';
import { useState, useEffect } from 'react';
import { useState } from 'react';
import { useAuth } from '@/lib/context/auth-context';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { updateUser, changePassword } from '@/lib/api';
import { updateUser } from '@/lib/api';
// Password update schema
const passwordSchema = z
@ -44,7 +44,7 @@ const profileSchema = z.object({
type ProfileFormData = z.infer<typeof profileSchema>;
export default function ProfilePage() {
const { user, refreshUser, loading } = useAuth();
const { user, refreshUser } = useAuth();
const queryClient = useQueryClient();
const [activeTab, setActiveTab] = useState<'profile' | 'password'>('profile');
const [successMessage, setSuccessMessage] = useState('');
@ -63,37 +63,8 @@ export default function ProfilePage() {
// Password form
const passwordForm = useForm<PasswordFormData>({
resolver: zodResolver(passwordSchema),
defaultValues: {
currentPassword: '',
newPassword: '',
confirmPassword: '',
},
});
// Update form values when user data loads
useEffect(() => {
if (user) {
profileForm.reset({
firstName: user.firstName,
lastName: user.lastName,
email: user.email,
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [user]);
// Reset password form when switching to password tab
useEffect(() => {
if (activeTab === 'password') {
passwordForm.reset({
currentPassword: '',
newPassword: '',
confirmPassword: '',
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeTab]);
// Update profile mutation
const updateProfileMutation = useMutation({
mutationFn: (data: ProfileFormData) => {
@ -113,22 +84,17 @@ export default function ProfilePage() {
},
});
// Update password mutation
// Update password mutation (you'll need to add this endpoint)
const updatePasswordMutation = useMutation({
mutationFn: async (data: PasswordFormData) => {
return changePassword({
currentPassword: data.currentPassword,
newPassword: data.newPassword,
});
// TODO: Add password update endpoint
// return updatePassword(data);
return Promise.resolve({ success: true });
},
onSuccess: () => {
setSuccessMessage('Password updated successfully!');
setErrorMessage('');
passwordForm.reset({
currentPassword: '',
newPassword: '',
confirmPassword: '',
});
passwordForm.reset();
setTimeout(() => setSuccessMessage(''), 3000);
},
onError: (error: any) => {
@ -145,35 +111,6 @@ export default function ProfilePage() {
updatePasswordMutation.mutate(data);
};
// Show loading state while user data is being fetched
if (loading) {
return (
<div className="flex items-center justify-center min-h-screen">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
<p className="text-gray-600">Loading profile...</p>
</div>
</div>
);
}
// Show error if user is not found after loading
if (!loading && !user) {
return (
<div className="flex items-center justify-center min-h-screen">
<div className="text-center">
<p className="text-red-600 mb-4">Unable to load user profile</p>
<button
onClick={() => window.location.reload()}
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
>
Retry
</button>
</div>
</div>
);
}
return (
<div className="max-w-4xl mx-auto space-y-6">
{/* Header */}
@ -351,7 +288,6 @@ export default function ProfilePage() {
{...passwordForm.register('currentPassword')}
type="password"
id="currentPassword"
autoComplete="current-password"
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
{passwordForm.formState.errors.currentPassword && (
@ -373,7 +309,6 @@ export default function ProfilePage() {
{...passwordForm.register('newPassword')}
type="password"
id="newPassword"
autoComplete="new-password"
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
{passwordForm.formState.errors.newPassword && (
@ -399,7 +334,6 @@ export default function ProfilePage() {
{...passwordForm.register('confirmPassword')}
type="password"
id="confirmPassword"
autoComplete="new-password"
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
{passwordForm.formState.errors.confirmPassword && (

View File

@ -103,7 +103,7 @@ export const usersApi = {
/**
* Change password
*/
async changePassword(data: ChangePasswordRequest): Promise<{ message: string }> {
return apiClient.patch<{ message: string }>('/api/v1/users/me/password', data);
async changePassword(data: ChangePasswordRequest): Promise<void> {
return apiClient.post<void>('/api/v1/users/change-password', data);
},
};

View File

@ -53,16 +53,8 @@ export {
type CsvBookingStatsResponse,
} from './bookings';
// Users (7 endpoints)
export {
listUsers,
getUser,
createUser,
updateUser,
deleteUser,
restoreUser,
changePassword,
} from './users';
// Users (6 endpoints)
export { listUsers, getUser, createUser, updateUser, deleteUser, restoreUser } from './users';
// Organizations (4 endpoints)
export {

View File

@ -78,15 +78,3 @@ export async function deleteUser(id: string): Promise<SuccessResponse> {
export async function restoreUser(id: string): Promise<UserResponse> {
return post<UserResponse>(`/api/v1/users/${id}/restore`);
}
/**
* Change own password
* PATCH /api/v1/users/me/password
* Requires: Authentication
*/
export async function changePassword(data: {
currentPassword: string;
newPassword: string;
}): Promise<{ message: string }> {
return patch<{ message: string }>('/api/v1/users/me/password', data);
}