Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 2x 80x 80x 80x 80x 80x 80x 80x 76x 4x | import { AlertTriangle } from 'lucide-react'
import { formatUsageValue, usagePercent, usageTone } from '../utils/usage'
const TONES = {
green: { bar: 'bg-green-500', text: 'text-green-700' },
orange: { bar: 'bg-orange-500', text: 'text-orange-700' },
red: { bar: 'bg-red-500', text: 'text-red-700' },
neutral: { bar: 'bg-gray-300', text: 'text-gray-500' },
}
/**
* Affichage graphique d'un quota, partagé entre l'abonnement (variant "full")
* et le tableau des organisations de l'admin (variant "compact").
*
* Aucun hook de routing interne : l'action éventuelle (ex. « Upgrader ») est
* injectée par l'appelant via `action`.
*/
function QuotaBar({
label,
used,
limit,
type = 'count',
unit = '',
variant = 'full',
action = null,
className = '',
}) {
const percent = usagePercent(used, limit)
const tone = TONES[usageTone(percent)]
const width = percent == null ? 0 : Math.min(100, Math.max(0, percent))
const exceeded = percent != null && percent > 100
const usedText = formatUsageValue(used, type, limit)
const limitText = formatUsageValue(limit, type, limit)
if (variant === 'compact') {
return (
<div className={`flex items-center gap-2 whitespace-nowrap ${className}`}>
<span className="w-7 text-[11px] uppercase tracking-wide text-gray-400">{label}</span>
<div className="w-16 bg-gray-200 rounded-full h-1.5">
<div className={`h-1.5 rounded-full ${tone.bar}`} style={{ width: `${width}%` }} />
</div>
<span className={`text-[11px] font-medium ${tone.text}`}>
{usedText} / {limitText} {unit}
{exceeded && <span className="ml-1 font-semibold">dépassé</span>}
</span>
</div>
)
}
return (
<div className={`mb-4 ${className}`}>
<div className="flex items-center justify-between mb-1">
<span className="text-sm font-medium text-gray-700">{label}</span>
<span className={`text-sm font-medium ${tone.text}`}>
{usedText} / {limitText} {unit}
</span>
</div>
<div className="w-full bg-gray-200 rounded-full h-2.5">
<div
className={`h-2.5 rounded-full transition-all duration-300 ${tone.bar}`}
style={{ width: `${width}%` }}
/>
</div>
{percent != null && percent >= 90 && (
<div className="flex items-center gap-2 mt-1">
<AlertTriangle className={`w-4 h-4 ${tone.text}`} />
<span className={`text-xs ${tone.text}`}>
{exceeded ? 'Limite dépassée' : 'Vous approchez de votre limite'}
</span>
{action && <div className="ml-auto">{action}</div>}
</div>
)}
</div>
)
}
export default QuotaBar
|