di usage in website

This commit is contained in:
2026-01-06 19:36:03 +01:00
parent 589b55a87e
commit e589c30bf8
191 changed files with 6367 additions and 4253 deletions

View File

@@ -3,6 +3,7 @@
import { useState, useEffect, FormEvent, type ChangeEvent } from 'react';
import { useRouter } from 'next/navigation';
import { useAuth } from '@/lib/auth/AuthContext';
import { useForgotPassword } from '@/hooks/auth/useForgotPassword';
import Link from 'next/link';
import { motion } from 'framer-motion';
import {
@@ -33,7 +34,6 @@ export default function ForgotPasswordPage() {
const router = useRouter();
const { session } = useAuth();
const [loading, setLoading] = useState(false);
const [errors, setErrors] = useState<FormErrors>({});
const [success, setSuccess] = useState<SuccessState | null>(null);
const [formData, setFormData] = useState({
@@ -60,34 +60,40 @@ export default function ForgotPasswordPage() {
return Object.keys(newErrors).length === 0;
};
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
if (loading) return;
if (!validateForm()) return;
setLoading(true);
setErrors({});
setSuccess(null);
try {
const { ServiceFactory } = await import('@/lib/services/ServiceFactory');
const serviceFactory = new ServiceFactory(process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3001');
const authService = serviceFactory.createAuthService();
const result = await authService.forgotPassword({ email: formData.email });
// Use forgot password mutation hook
const forgotPasswordMutation = useForgotPassword({
onSuccess: (result) => {
setSuccess({
message: result.message,
magicLink: result.magicLink,
});
} catch (error) {
},
onError: (error) => {
setErrors({
submit: error instanceof Error ? error.message : 'Failed to send reset link. Please try again.',
submit: error.message || 'Failed to send reset link. Please try again.',
});
setLoading(false);
},
});
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
if (forgotPasswordMutation.isPending) return;
if (!validateForm()) return;
setErrors({});
setSuccess(null);
try {
await forgotPasswordMutation.mutateAsync({ email: formData.email });
} catch (error) {
// Error handling is done in the mutation's onError callback
}
};
// Loading state from mutation
const loading = forgotPasswordMutation.isPending;
return (
<main className="min-h-screen bg-deep-graphite flex items-center justify-center px-4 py-12">
{/* Background Pattern */}

View File

@@ -20,6 +20,7 @@ import Button from '@/components/ui/Button';
import Input from '@/components/ui/Input';
import Heading from '@/components/ui/Heading';
import { useAuth } from '@/lib/auth/AuthContext';
import { useLogin } from '@/hooks/auth/useLogin';
import AuthWorkflowMockup from '@/components/auth/AuthWorkflowMockup';
import UserRolesPreview from '@/components/auth/UserRolesPreview';
import { EnhancedFormError, FormErrorSummary } from '@/components/errors/EnhancedFormError';
@@ -37,6 +38,21 @@ export default function LoginPage() {
const [showErrorDetails, setShowErrorDetails] = useState(false);
const [hasInsufficientPermissions, setHasInsufficientPermissions] = useState(false);
// Use login mutation hook
const loginMutation = useLogin({
onSuccess: async () => {
// Refresh session in context so header updates immediately
await refreshSession();
router.push(returnTo);
},
onError: (error) => {
// Show error details toggle in development
if (process.env.NODE_ENV === 'development') {
setShowErrorDetails(true);
}
},
});
// Check if user is already authenticated
useEffect(() => {
console.log('[LoginPage] useEffect running', {
@@ -84,10 +100,6 @@ export default function LoginPage() {
validate: validateLoginForm,
component: 'LoginPage',
onSubmit: async (values) => {
const { ServiceFactory } = await import('@/lib/services/ServiceFactory');
const serviceFactory = new ServiceFactory(process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3001');
const authService = serviceFactory.createAuthService();
// Log the attempt for debugging
logErrorWithContext(
{ message: 'Login attempt', values: { ...values, password: '[REDACTED]' } },
@@ -98,21 +110,14 @@ export default function LoginPage() {
}
);
await authService.login({
await loginMutation.mutateAsync({
email: values.email,
password: values.password,
rememberMe: values.rememberMe,
});
// Refresh session in context so header updates immediately
await refreshSession();
router.push(returnTo);
},
onError: (error, values) => {
// Show error details toggle in development
if (process.env.NODE_ENV === 'development') {
setShowErrorDetails(true);
}
// Error handling is done in the mutation's onError callback
},
onSuccess: () => {
// Reset error details on success

View File

@@ -20,6 +20,7 @@ import Button from '@/components/ui/Button';
import Input from '@/components/ui/Input';
import Heading from '@/components/ui/Heading';
import { useAuth } from '@/lib/auth/AuthContext';
import { useResetPassword } from '@/hooks/auth/useResetPassword';
interface FormErrors {
newPassword?: string;
@@ -52,7 +53,6 @@ export default function ResetPasswordPage() {
const searchParams = useSearchParams();
const { session } = useAuth();
const [loading, setLoading] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const [errors, setErrors] = useState<FormErrors>({});
@@ -112,34 +112,40 @@ export default function ResetPasswordPage() {
return Object.keys(newErrors).length === 0;
};
// Use reset password mutation hook
const resetPasswordMutation = useResetPassword({
onSuccess: (result) => {
setSuccess(result.message);
},
onError: (error) => {
setErrors({
submit: error.message || 'Failed to reset password. Please try again.',
});
},
});
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
if (loading) return;
if (resetPasswordMutation.isPending) return;
if (!validateForm()) return;
setLoading(true);
setErrors({});
setSuccess(null);
try {
const { ServiceFactory } = await import('@/lib/services/ServiceFactory');
const serviceFactory = new ServiceFactory(process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3001');
const authService = serviceFactory.createAuthService();
const result = await authService.resetPassword({
await resetPasswordMutation.mutateAsync({
token,
newPassword: formData.newPassword,
});
setSuccess(result.message);
} catch (error) {
setErrors({
submit: error instanceof Error ? error.message : 'Failed to reset password. Please try again.',
});
setLoading(false);
// Error handling is done in the mutation's onError callback
}
};
// Loading state from mutation
const loading = resetPasswordMutation.isPending;
return (
<main className="min-h-screen bg-deep-graphite flex items-center justify-center px-4 py-12">
{/* Background Pattern */}

View File

@@ -28,6 +28,7 @@ import Button from '@/components/ui/Button';
import Input from '@/components/ui/Input';
import Heading from '@/components/ui/Heading';
import { useAuth } from '@/lib/auth/AuthContext';
import { useSignup } from '@/hooks/auth/useSignup';
interface FormErrors {
firstName?: string;
@@ -94,7 +95,6 @@ export default function SignupPage() {
const { refreshSession, session } = useAuth();
const returnTo = searchParams.get('returnTo') ?? '/onboarding';
const [loading, setLoading] = useState(false);
const [checkingAuth, setCheckingAuth] = useState(true);
const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
@@ -198,29 +198,9 @@ export default function SignupPage() {
return Object.keys(newErrors).length === 0;
};
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
if (loading) return;
if (!validateForm()) return;
setLoading(true);
setErrors({});
try {
const { ServiceFactory } = await import('@/lib/services/ServiceFactory');
const serviceFactory = new ServiceFactory(process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3001');
const authService = serviceFactory.createAuthService();
// Combine first and last name into display name
const displayName = `${formData.firstName} ${formData.lastName}`.trim();
await authService.signup({
email: formData.email,
password: formData.password,
displayName,
});
// Use signup mutation hook
const signupMutation = useSignup({
onSuccess: async () => {
// Refresh session in context so header updates immediately
try {
await refreshSession();
@@ -229,14 +209,39 @@ export default function SignupPage() {
}
// Always redirect to dashboard after signup
router.push('/dashboard');
} catch (error) {
},
onError: (error) => {
setErrors({
submit: error instanceof Error ? error.message : 'Signup failed. Please try again.',
submit: error.message || 'Signup failed. Please try again.',
});
setLoading(false);
},
});
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
if (signupMutation.isPending) return;
if (!validateForm()) return;
setErrors({});
try {
// Combine first and last name into display name
const displayName = `${formData.firstName} ${formData.lastName}`.trim();
await signupMutation.mutateAsync({
email: formData.email,
password: formData.password,
displayName,
});
} catch (error) {
// Error handling is done in the mutation's onError callback
}
};
// Loading state from mutation
const loading = signupMutation.isPending;
// Show loading while checking auth
if (checkingAuth) {
return (