Comprehensive platform audit: security, UX, performance, and visual polish
Phase 1: Security - status transition validation, Zod tightening, DB indexes, transactions Phase 2: Admin UX - search/filter for awards, learning, partners pages Phase 3: Dashboard - Recent Activity feed, Pending Actions card, quick actions Phase 4: Jury - assignments progress/urgency, autosave indicator, divergence highlighting Phase 5: Portals - observer charts, mentor search, login/onboarding polish Phase 6: Messages preview dialog, CsvExportDialog with column selection Phase 7: Performance - query optimizations, loading skeletons, useDebounce hook Phase 8: Visual - AnimatedCard, hover effects, StatusBadge, empty state CTAs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -49,8 +49,12 @@ export default function LoginPage() {
|
||||
// Use window.location for external redirects or callback URLs
|
||||
window.location.href = callbackUrl
|
||||
}
|
||||
} catch {
|
||||
setError('An unexpected error occurred. Please try again.')
|
||||
} catch (err: unknown) {
|
||||
if (err instanceof Error && err.message.includes('429')) {
|
||||
setError('Too many attempts. Please wait a few minutes before trying again.')
|
||||
} else {
|
||||
setError('An unexpected error occurred. Please try again.')
|
||||
}
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
@@ -84,8 +88,12 @@ export default function LoginPage() {
|
||||
} else {
|
||||
setError('Failed to send magic link. Please try again.')
|
||||
}
|
||||
} catch {
|
||||
setError('An unexpected error occurred. Please try again.')
|
||||
} catch (err: unknown) {
|
||||
if (err instanceof Error && err.message.includes('429')) {
|
||||
setError('Too many attempts. Please wait a few minutes before trying again.')
|
||||
} else {
|
||||
setError('An unexpected error occurred. Please try again.')
|
||||
}
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
@@ -96,8 +104,8 @@ export default function LoginPage() {
|
||||
return (
|
||||
<Card className="w-full max-w-md">
|
||||
<CardHeader className="text-center">
|
||||
<div className="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-green-100">
|
||||
<CheckCircle2 className="h-6 w-6 text-green-600" />
|
||||
<div className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-green-100 animate-in zoom-in-50 duration-300">
|
||||
<Mail className="h-8 w-8 text-green-600" />
|
||||
</div>
|
||||
<CardTitle className="text-xl">Check your email</CardTitle>
|
||||
<CardDescription className="text-base">
|
||||
@@ -105,22 +113,27 @@ export default function LoginPage() {
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<p className="text-sm text-muted-foreground text-center">
|
||||
Click the link in the email to sign in. The link will expire in 15
|
||||
minutes.
|
||||
</p>
|
||||
<div className="border-t pt-4">
|
||||
<div className="rounded-lg border bg-muted/50 p-4 text-sm text-muted-foreground space-y-2">
|
||||
<p>Click the link in the email to sign in. The link will expire in 15 minutes.</p>
|
||||
<p>If you don't see it, check your spam folder.</p>
|
||||
</div>
|
||||
<div className="border-t pt-4 space-y-2">
|
||||
<Button
|
||||
variant="ghost"
|
||||
variant="outline"
|
||||
className="w-full"
|
||||
onClick={() => {
|
||||
setIsSent(false)
|
||||
setEmail('')
|
||||
setPassword('')
|
||||
setError(null)
|
||||
}}
|
||||
>
|
||||
Use a different email
|
||||
Send to a different email
|
||||
</Button>
|
||||
<p className="text-xs text-center text-muted-foreground">
|
||||
Having trouble?{' '}
|
||||
<a href="mailto:support@monaco-opc.com" className="text-primary hover:underline">
|
||||
Contact support
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user