Compare commits
No commits in common. "d9868dd49f055a24de10a56a6d4581ab1b319200" and "4ce7d2ec07c280a53999ca11c5ab366b6fc8bfee" have entirely different histories.
d9868dd49f
...
4ce7d2ec07
@ -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 && (
|
||||
|
||||
@ -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);
|
||||
},
|
||||
};
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user