chore: import codes

This commit is contained in:
2026-04-12 12:50:14 -04:00
parent 4bcb4898e8
commit 65ae3c6788
241 changed files with 48834 additions and 1 deletions
@@ -0,0 +1,189 @@
/**
* Password Strength Indicator Component
* Shows password strength and validation requirements
*/
'use client';
import { useState, useEffect } from 'react';
export default function PasswordStrengthIndicator({ password = '', showRequirements = true }) {
const [strength, setStrength] = useState(0);
const [requirements, setRequirements] = useState({
length: false,
maxLength: false,
uppercase: false,
lowercase: false,
number: false
});
useEffect(() => {
if (!password) {
setStrength(0);
setRequirements({
length: false,
uppercase: false,
lowercase: false,
number: false
});
return;
}
const newRequirements = {
length: password.length >= 8,
maxLength: password.length <= 128,
uppercase: /[A-Z]/.test(password),
lowercase: /[a-z]/.test(password),
number: /\d/.test(password)
};
setRequirements(newRequirements);
// Calculate strength based on both requirements and length
const requirementsMet = Object.values(newRequirements).filter(Boolean).length;
let strengthValue = requirementsMet;
// Adjust strength based on password length
if (password.length >= 12) {
strengthValue = Math.min(5, strengthValue + 1); // Bonus for long passwords
} else if (password.length >= 8 && password.length < 10) {
strengthValue = Math.max(1, strengthValue - 1); // Penalty for short passwords
} else if (password.length < 8) {
strengthValue = Math.max(0, strengthValue - 2); // Big penalty for very short passwords
}
// Ensure strength is between 0 and 5
strengthValue = Math.max(0, Math.min(5, strengthValue));
setStrength(strengthValue);
}, [password]);
const getStrengthColor = () => {
switch (strength) {
case 0:
case 1:
return 'bg-red-500';
case 2:
return 'bg-orange-500';
case 3:
return 'bg-yellow-500';
case 4:
return 'bg-blue-500';
case 5:
return 'bg-green-500';
default:
return 'bg-gray-500';
}
};
const getStrengthText = () => {
switch (strength) {
case 0:
return 'Très faible';
case 1:
return 'Faible';
case 2:
return 'Moyen';
case 3:
return 'Bon';
case 4:
return 'Très bon';
case 5:
return 'Excellent';
default:
return '';
}
};
const getStrengthTextColor = () => {
switch (strength) {
case 0:
case 1:
return 'text-red-700 dark:text-red-400';
case 2:
return 'text-orange-700 dark:text-orange-400';
case 3:
return 'text-yellow-700 dark:text-yellow-500';
case 4:
return 'text-blue-700 dark:text-blue-400';
case 5:
return 'text-green-700 dark:text-green-400';
default:
return 'text-neutral-600 dark:text-neutral-400';
}
};
if (!password && !showRequirements) {
return null;
}
return (
<div className="mt-2 space-y-2">
{/* Strength Bar */}
{password && (
<div className="space-y-1">
<div className="flex items-center justify-between">
<span className="text-xs text-neutral-600 dark:text-neutral-400">Force du mot de passe :</span>
<span className={`text-xs font-medium ${getStrengthTextColor()}`}>
{getStrengthText()}
</span>
</div>
<div className="w-full bg-neutral-200 dark:bg-neutral-700 rounded-full h-1.5">
<div
className={`h-1.5 rounded-full transition-all duration-300 ${getStrengthColor()}`}
style={{ width: `${(strength / 5) * 100}%` }}
/>
</div>
</div>
)}
{/* Requirements - Only show if not all requirements are met */}
{showRequirements && password && !Object.values(requirements).every(Boolean) && (
<div className="space-y-1">
<div className="space-y-1">
{!requirements.length && (
<div className="flex items-center space-x-2">
<div className="w-1.5 h-1.5 rounded-full flex-shrink-0 bg-red-500" />
<span className="text-xs text-red-700 dark:text-red-400">
Au moins 8 caractères
</span>
</div>
)}
{!requirements.maxLength && (
<div className="flex items-center space-x-2">
<div className="w-1.5 h-1.5 rounded-full flex-shrink-0 bg-red-500" />
<span className="text-xs text-red-700 dark:text-red-400">
Maximum 128 caractères
</span>
</div>
)}
{!requirements.uppercase && (
<div className="flex items-center space-x-2">
<div className="w-1.5 h-1.5 rounded-full flex-shrink-0 bg-red-500" />
<span className="text-xs text-red-700 dark:text-red-400">
Au moins une majuscule
</span>
</div>
)}
{!requirements.lowercase && (
<div className="flex items-center space-x-2">
<div className="w-1.5 h-1.5 rounded-full flex-shrink-0 bg-red-500" />
<span className="text-xs text-red-700 dark:text-red-400">
Au moins une minuscule
</span>
</div>
)}
{!requirements.number && (
<div className="flex items-center space-x-2">
<div className="w-1.5 h-1.5 rounded-full flex-shrink-0 bg-red-500" />
<span className="text-xs text-red-700 dark:text-red-400">
Au moins un chiffre
</span>
</div>
)}
</div>
</div>
)}
</div>
);
}