Add status badge to USB policy chip in device details

- Replace parentheses text with styled badge
- Use color-coded badges: success (green), warning (amber), error (red)
- Add APPLYING status support
- Match badge style with custom fields counter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
esdrasrenan 2025-12-06 23:52:56 -03:00
parent 71757a1d59
commit 0c8d53c0b6

View file

@ -3137,7 +3137,7 @@ export function DeviceDetails({ device }: DeviceDetailsProps) {
const hasRemoteAccess = remoteAccessEntries.length > 0
const summaryChips = useMemo(() => {
const chips: Array<{ key: string; label: string; value: string; icon: ReactNode; tone?: "warning" | "muted"; onClick?: () => void }> = []
const chips: Array<{ key: string; label: string; value: string; icon: ReactNode; tone?: "warning" | "muted"; onClick?: () => void; statusBadge?: { text: string; variant: "default" | "success" | "warning" | "error" } }> = []
const osName = osNameDisplay || "Sistema desconhecido"
const osVersionRaw = device?.osVersion ?? windowsVersionLabel ?? ""
const osVersion = formatOsVersionDisplay(osNameDisplay, osVersionRaw)
@ -3193,20 +3193,34 @@ export function DeviceDetails({ device }: DeviceDetailsProps) {
}
const statusLabels: Record<string, string> = {
PENDING: "Pendente",
APPLYING: "Aplicando",
APPLIED: "Aplicado",
FAILED: "Falhou",
}
const statusBadgeVariants: Record<string, "default" | "success" | "warning" | "error"> = {
PENDING: "warning",
APPLYING: "warning",
APPLIED: "success",
FAILED: "error",
}
const currentPolicy = device?.usbPolicy ?? "ALLOW"
const policyLabel = policyLabels[currentPolicy] ?? currentPolicy
const statusLabel = device?.usbPolicyStatus ? ` (${statusLabels[device.usbPolicyStatus] ?? device.usbPolicyStatus})` : ""
const isPending = device?.usbPolicyStatus === "PENDING"
const isApplying = device?.usbPolicyStatus === "APPLYING"
const isFailed = device?.usbPolicyStatus === "FAILED"
const statusBadge = device?.usbPolicyStatus
? {
text: statusLabels[device.usbPolicyStatus] ?? device.usbPolicyStatus,
variant: statusBadgeVariants[device.usbPolicyStatus] ?? "default" as const,
}
: undefined
chips.push({
key: "usb-policy",
label: "USB",
value: `${policyLabel}${statusLabel}`,
icon: <Usb className={`size-4 ${isFailed ? "text-red-500" : isPending ? "text-amber-500" : "text-neutral-500"}`} />,
tone: isFailed ? "warning" : isPending ? "warning" : undefined,
value: policyLabel,
icon: <Usb className={`size-4 ${isFailed ? "text-red-500" : isPending || isApplying ? "text-amber-500" : "text-neutral-500"}`} />,
tone: isFailed ? "warning" : isPending || isApplying ? "warning" : undefined,
statusBadge,
})
}
return chips
@ -3917,6 +3931,7 @@ export function DeviceDetails({ device }: DeviceDetailsProps) {
value={chip.value}
icon={chip.icon}
tone={chip.tone}
statusBadge={chip.statusBadge}
/>
))}
</div>
@ -6176,7 +6191,7 @@ function DetailLine({ label, value, classNameValue, layout = "spread" }: DetailL
)
}
function InfoChip({ label, value, icon, tone = "default", onClick }: { label: string; value: string; icon?: ReactNode; tone?: "default" | "warning" | "muted"; onClick?: () => void }) {
function InfoChip({ label, value, icon, tone = "default", onClick, statusBadge }: { label: string; value: string; icon?: ReactNode; tone?: "default" | "warning" | "muted"; onClick?: () => void; statusBadge?: { text: string; variant: "default" | "success" | "warning" | "error" } }) {
const toneClasses =
tone === "warning"
? "border-amber-200 bg-amber-50 text-amber-700"
@ -6186,6 +6201,13 @@ function InfoChip({ label, value, icon, tone = "default", onClick }: { label: st
const clickableClasses = onClick ? "cursor-pointer hover:ring-2 hover:ring-blue-200 transition-all" : ""
const badgeVariantClasses = {
default: "border-slate-200 bg-slate-100 text-slate-600",
success: "border-emerald-200 bg-emerald-50 text-emerald-700",
warning: "border-amber-200 bg-amber-50 text-amber-700",
error: "border-red-200 bg-red-50 text-red-700",
}
return (
<div
className={cn("flex items-center gap-3 rounded-xl border px-3 py-2 shadow-sm", toneClasses, clickableClasses)}
@ -6197,7 +6219,14 @@ function InfoChip({ label, value, icon, tone = "default", onClick }: { label: st
{icon ? <span className="text-neutral-500">{icon}</span> : null}
<div className="min-w-0 leading-tight">
<p className="text-xs uppercase text-neutral-500">{label}</p>
<p className="truncate text-sm font-semibold">{value}</p>
<div className="flex items-center gap-2">
<p className="truncate text-sm font-semibold">{value}</p>
{statusBadge && (
<span className={cn("inline-flex rounded-full border px-2 py-0.5 text-[11px] font-semibold", badgeVariantClasses[statusBadge.variant])}>
{statusBadge.text}
</span>
)}
</div>
</div>
</div>
)