ultisuite-client/components/ai/ai-spend-bar.tsx
R3D347HR4Y b95948f980 feat: refactor mail and account settings structure for improved navigation and layout
- Updated routing for mail settings to redirect to the new settings layout.
- Introduced new account layout and section components for better organization.
- Replaced hardcoded paths with constants for account and mail settings to enhance maintainability.
- Removed deprecated mail settings layout and integrated it into the new settings structure.
- Enhanced user experience by streamlining navigation between account and mail settings.
2026-06-16 11:32:58 +02:00

86 lines
2.7 KiB
TypeScript

"use client"
import Link from "next/link"
import {
aiQuotaUsedMonthPct,
formatAiCostEUR,
type AiQuota,
} from "@/lib/api/hooks/use-ai-queries"
import { ACCOUNT_SETTINGS_BASE_PATH } from "@/lib/compte-settings/settings-nav"
import { cn } from "@/lib/utils"
export function AiSpendBar({
quota,
compact = false,
className,
}: {
quota: AiQuota
compact?: boolean
className?: string
}) {
const pct = aiQuotaUsedMonthPct(quota)
const warnPct = quota.warn_threshold_pct || 80
const nearLimit = pct != null && pct >= warnPct
const isBYOK = !quota.billing_scope_org
if (isBYOK) {
const byokTotal = (quota.by_provider_keys ?? []).reduce(
(sum, k) => sum + k.cost_month_micro_eur,
quota.cost_used_month_micro_eur
)
return (
<div className={cn("space-y-1", className)}>
<div className="flex items-center justify-between gap-2 text-xs text-muted-foreground">
<span>Clé personnelle</span>
<span className="tabular-nums">{formatAiCostEUR(byokTotal)} / mois</span>
</div>
{!compact && (quota.by_provider_keys?.length ?? 0) > 0 ? (
<div className="space-y-0.5 pl-2 text-[10px] text-muted-foreground">
{quota.by_provider_keys!.slice(0, 3).map((k) => (
<div key={k.fingerprint} className="flex justify-between gap-2">
<span className="truncate">{k.label}</span>
<span className="tabular-nums shrink-0">{formatAiCostEUR(k.cost_month_micro_eur)}</span>
</div>
))}
</div>
) : null}
</div>
)
}
return (
<div className={cn("space-y-1", className)}>
<div className="flex items-center justify-between gap-2 text-xs text-muted-foreground">
<span className={cn(nearLimit && "text-amber-600 dark:text-amber-400")}>
IA {nearLimit ? "· proche du plafond" : ""}
</span>
<span className="tabular-nums">
{formatAiCostEUR(quota.cost_used_month_micro_eur)}
{quota.cost_limit_month_micro_eur
? ` / ${formatAiCostEUR(quota.cost_limit_month_micro_eur)}`
: ""}
</span>
</div>
{pct != null ? (
<div className="h-1.5 overflow-hidden rounded-full bg-muted">
<div
className={cn(
"h-full rounded-full transition-all",
nearLimit ? "bg-amber-500" : "bg-primary"
)}
style={{ width: `${pct}%` }}
/>
</div>
) : null}
{!compact ? (
<Link
href={`${ACCOUNT_SETTINGS_BASE_PATH}/usage-ia`}
className="text-[10px] text-muted-foreground underline-offset-2 hover:underline"
>
Détail de consommation
</Link>
) : null}
</div>
)
}