feat(auth): Introduce 5-day grace period for email verification before lockout

This commit is contained in:
Mohan Ki
2026-07-27 19:16:17 +05:30
parent 4fe25f3de5
commit bd17947106
3 changed files with 71 additions and 30 deletions
+59 -26
View File
@@ -49,17 +49,25 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
</div>
<div className="p-4">
{user?.is_email_verified === false ? (
<button disabled className="flex items-center justify-center gap-2 w-full bg-gray-400 text-white font-bold py-3 px-4 rounded-xl shadow-sm mb-6 cursor-not-allowed opacity-70">
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" /></svg>
Verify Email to Create
</button>
) : (
<Link href="/dashboard/create" className="flex items-center justify-center gap-2 w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-3 px-4 rounded-xl transition-colors shadow-sm mb-6">
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" /></svg>
Create New QR Code
</Link>
)}
{(() => {
if (user?.is_email_verified === false) {
const daysSinceCreation = (new Date().getTime() - new Date(user.created_at).getTime()) / (1000 * 60 * 60 * 24);
if (daysSinceCreation > 5) {
return (
<button disabled className="flex items-center justify-center gap-2 w-full bg-gray-400 text-white font-bold py-3 px-4 rounded-xl shadow-sm mb-6 cursor-not-allowed opacity-70">
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" /></svg>
Verify Email to Create
</button>
);
}
}
return (
<Link href="/dashboard/create" className="flex items-center justify-center gap-2 w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-3 px-4 rounded-xl transition-colors shadow-sm mb-6">
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" /></svg>
Create New QR Code
</Link>
);
})()}
</div>
<nav className="flex-1 px-4 space-y-1 overflow-y-auto">
@@ -94,21 +102,46 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
{/* Main Content */}
<main className="flex-1 h-screen overflow-y-auto relative flex flex-col">
{user?.is_email_verified === false && (
<div className="bg-red-50 border-b border-red-200 px-6 py-3 flex items-center justify-between shadow-sm z-10">
<div className="flex items-center gap-3 text-red-800">
<svg className="w-6 h-6 text-red-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
<p className="font-medium text-sm">
Your account is currently restricted. Please verify your email address to unlock QR Code creation.
</p>
</div>
<Link href="/dashboard/profile" className="text-sm font-bold bg-white text-red-700 hover:bg-red-100 border border-red-300 px-4 py-1.5 rounded-lg transition-colors whitespace-nowrap">
Verify Now
</Link>
</div>
)}
{(() => {
if (user?.is_email_verified === false) {
const daysSinceCreation = (new Date().getTime() - new Date(user.created_at).getTime()) / (1000 * 60 * 60 * 24);
if (daysSinceCreation > 5) {
return (
<div className="bg-red-50 border-b border-red-200 px-6 py-3 flex items-center justify-between shadow-sm z-10">
<div className="flex items-center gap-3 text-red-800">
<svg className="w-6 h-6 text-red-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
<p className="font-medium text-sm">
Your account is currently restricted. Please verify your email address to unlock QR Code creation.
</p>
</div>
<Link href="/dashboard/profile" className="text-sm font-bold bg-white text-red-700 hover:bg-red-100 border border-red-300 px-4 py-1.5 rounded-lg transition-colors whitespace-nowrap">
Verify Now
</Link>
</div>
);
} else {
const daysLeft = Math.ceil(5 - daysSinceCreation);
return (
<div className="bg-yellow-50 border-b border-yellow-200 px-6 py-3 flex items-center justify-between shadow-sm z-10">
<div className="flex items-center gap-3 text-yellow-800">
<svg className="w-6 h-6 text-yellow-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<p className="font-medium text-sm">
Please verify your email address within {daysLeft} {daysLeft === 1 ? 'day' : 'days'} to prevent account restriction.
</p>
</div>
<Link href="/dashboard/profile" className="text-sm font-bold bg-white text-yellow-700 hover:bg-yellow-100 border border-yellow-300 px-4 py-1.5 rounded-lg transition-colors whitespace-nowrap">
Verify Now
</Link>
</div>
);
}
}
return null;
})()}
<div className="flex-1 overflow-y-auto">
{children}
</div>