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:
parent
71757a1d59
commit
0c8d53c0b6
1 changed files with 36 additions and 7 deletions
|
|
@ -3137,7 +3137,7 @@ export function DeviceDetails({ device }: DeviceDetailsProps) {
|
||||||
const hasRemoteAccess = remoteAccessEntries.length > 0
|
const hasRemoteAccess = remoteAccessEntries.length > 0
|
||||||
|
|
||||||
const summaryChips = useMemo(() => {
|
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 osName = osNameDisplay || "Sistema desconhecido"
|
||||||
const osVersionRaw = device?.osVersion ?? windowsVersionLabel ?? ""
|
const osVersionRaw = device?.osVersion ?? windowsVersionLabel ?? ""
|
||||||
const osVersion = formatOsVersionDisplay(osNameDisplay, osVersionRaw)
|
const osVersion = formatOsVersionDisplay(osNameDisplay, osVersionRaw)
|
||||||
|
|
@ -3193,20 +3193,34 @@ export function DeviceDetails({ device }: DeviceDetailsProps) {
|
||||||
}
|
}
|
||||||
const statusLabels: Record<string, string> = {
|
const statusLabels: Record<string, string> = {
|
||||||
PENDING: "Pendente",
|
PENDING: "Pendente",
|
||||||
|
APPLYING: "Aplicando",
|
||||||
APPLIED: "Aplicado",
|
APPLIED: "Aplicado",
|
||||||
FAILED: "Falhou",
|
FAILED: "Falhou",
|
||||||
}
|
}
|
||||||
|
const statusBadgeVariants: Record<string, "default" | "success" | "warning" | "error"> = {
|
||||||
|
PENDING: "warning",
|
||||||
|
APPLYING: "warning",
|
||||||
|
APPLIED: "success",
|
||||||
|
FAILED: "error",
|
||||||
|
}
|
||||||
const currentPolicy = device?.usbPolicy ?? "ALLOW"
|
const currentPolicy = device?.usbPolicy ?? "ALLOW"
|
||||||
const policyLabel = policyLabels[currentPolicy] ?? currentPolicy
|
const policyLabel = policyLabels[currentPolicy] ?? currentPolicy
|
||||||
const statusLabel = device?.usbPolicyStatus ? ` (${statusLabels[device.usbPolicyStatus] ?? device.usbPolicyStatus})` : ""
|
|
||||||
const isPending = device?.usbPolicyStatus === "PENDING"
|
const isPending = device?.usbPolicyStatus === "PENDING"
|
||||||
|
const isApplying = device?.usbPolicyStatus === "APPLYING"
|
||||||
const isFailed = device?.usbPolicyStatus === "FAILED"
|
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({
|
chips.push({
|
||||||
key: "usb-policy",
|
key: "usb-policy",
|
||||||
label: "USB",
|
label: "USB",
|
||||||
value: `${policyLabel}${statusLabel}`,
|
value: policyLabel,
|
||||||
icon: <Usb className={`size-4 ${isFailed ? "text-red-500" : isPending ? "text-amber-500" : "text-neutral-500"}`} />,
|
icon: <Usb className={`size-4 ${isFailed ? "text-red-500" : isPending || isApplying ? "text-amber-500" : "text-neutral-500"}`} />,
|
||||||
tone: isFailed ? "warning" : isPending ? "warning" : undefined,
|
tone: isFailed ? "warning" : isPending || isApplying ? "warning" : undefined,
|
||||||
|
statusBadge,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return chips
|
return chips
|
||||||
|
|
@ -3917,6 +3931,7 @@ export function DeviceDetails({ device }: DeviceDetailsProps) {
|
||||||
value={chip.value}
|
value={chip.value}
|
||||||
icon={chip.icon}
|
icon={chip.icon}
|
||||||
tone={chip.tone}
|
tone={chip.tone}
|
||||||
|
statusBadge={chip.statusBadge}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</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 =
|
const toneClasses =
|
||||||
tone === "warning"
|
tone === "warning"
|
||||||
? "border-amber-200 bg-amber-50 text-amber-700"
|
? "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 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 (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn("flex items-center gap-3 rounded-xl border px-3 py-2 shadow-sm", toneClasses, clickableClasses)}
|
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}
|
{icon ? <span className="text-neutral-500">{icon}</span> : null}
|
||||||
<div className="min-w-0 leading-tight">
|
<div className="min-w-0 leading-tight">
|
||||||
<p className="text-xs uppercase text-neutral-500">{label}</p>
|
<p className="text-xs uppercase text-neutral-500">{label}</p>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
<p className="truncate text-sm font-semibold">{value}</p>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue