Refactor password reset flow and improve ESLint integration

- Extracted password reset logic into `PasswordResetConfirmContent` wrapped in `Suspense` for cleaner and more modular component structure.
- Updated ESLint config to ignore generated files and added rules for stricter code quality (`eslint-comments`, `@typescript-eslint` adjustments).
- Automated insertion of `eslint-disable` in auto-generated TypeScript files through `generate-api-client.sh`.
- Replaced unsafe `any` type casts with safer `Record<string, unknown>` type assertions for TypeScript compliance.
- Added `lint:tests` script for pre-commit test coverage checks.
- Improved `useAuth` hooks and related type guards for better runtime safety and maintainability.
This commit is contained in:
Felipe Cardoso
2025-11-01 06:04:35 +01:00
parent a062daddc5
commit b8d3248a48
17 changed files with 171 additions and 86 deletions

View File

@@ -0,0 +1,78 @@
/**
* Password Reset Confirm Content Component
* Wrapped in Suspense boundary to handle useSearchParams()
*/
'use client';
import { useSearchParams, useRouter } from 'next/navigation';
import { useEffect, useRef } from 'react';
import { PasswordResetConfirmForm } from '@/components/auth/PasswordResetConfirmForm';
import { Alert } from '@/components/ui/alert';
import Link from 'next/link';
export default function PasswordResetConfirmContent() {
const searchParams = useSearchParams();
const router = useRouter();
const token = searchParams.get('token');
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
// Cleanup timeout on unmount
useEffect(() => {
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
};
}, []);
// Handle successful password reset
const handleSuccess = () => {
// Wait 3 seconds then redirect to login
timeoutRef.current = setTimeout(() => {
router.push('/login');
}, 3000);
};
// If no token in URL, show error
if (!token) {
return (
<div className="space-y-6">
<div className="text-center">
<h2 className="text-3xl font-bold tracking-tight">
Invalid Reset Link
</h2>
</div>
<Alert variant="destructive">
<p className="text-sm">
This password reset link is invalid or has expired. Please request a new
password reset.
</p>
</Alert>
<div className="text-center">
<Link
href="/password-reset"
className="text-sm text-primary underline-offset-4 hover:underline font-medium"
>
Request new reset link
</Link>
</div>
</div>
);
}
return (
<div className="space-y-6">
<div className="text-center">
<h2 className="text-3xl font-bold tracking-tight">Set new password</h2>
<p className="mt-2 text-sm text-muted-foreground">
Choose a strong password for your account
</p>
</div>
<PasswordResetConfirmForm token={token} onSuccess={handleSuccess} showLoginLink />
</div>
);
}

View File

@@ -3,76 +3,22 @@
* Users set a new password using the token from their email
*/
'use client';
import { useSearchParams, useRouter } from 'next/navigation';
import { useEffect, useRef } from 'react';
import { PasswordResetConfirmForm } from '@/components/auth/PasswordResetConfirmForm';
import { Alert } from '@/components/ui/alert';
import Link from 'next/link';
import { Suspense } from 'react';
import PasswordResetConfirmContent from './PasswordResetConfirmContent';
export default function PasswordResetConfirmPage() {
const searchParams = useSearchParams();
const router = useRouter();
const token = searchParams.get('token');
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
// Cleanup timeout on unmount
useEffect(() => {
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
};
}, []);
// Handle successful password reset
const handleSuccess = () => {
// Wait 3 seconds then redirect to login
timeoutRef.current = setTimeout(() => {
router.push('/login');
}, 3000);
};
// If no token in URL, show error
if (!token) {
return (
return (
<Suspense fallback={
<div className="space-y-6">
<div className="text-center">
<h2 className="text-3xl font-bold tracking-tight">
Invalid Reset Link
</h2>
</div>
<Alert variant="destructive">
<p className="text-sm">
This password reset link is invalid or has expired. Please request a new
password reset.
<h2 className="text-3xl font-bold tracking-tight">Set new password</h2>
<p className="mt-2 text-sm text-muted-foreground">
Loading...
</p>
</Alert>
<div className="text-center">
<Link
href="/password-reset"
className="text-sm text-primary underline-offset-4 hover:underline font-medium"
>
Request new reset link
</Link>
</div>
</div>
);
}
return (
<div className="space-y-6">
<div className="text-center">
<h2 className="text-3xl font-bold tracking-tight">Set new password</h2>
<p className="mt-2 text-sm text-muted-foreground">
Choose a strong password for your account
</p>
</div>
<PasswordResetConfirmForm token={token} onSuccess={handleSuccess} showLoginLink />
</div>
}>
<PasswordResetConfirmContent />
</Suspense>
);
}