Refine machine details layout and improve download feedback

This commit is contained in:
Esdras Renan 2025-10-19 00:52:42 -03:00
parent 5f7efa13e6
commit 1251468b77
6 changed files with 96 additions and 10 deletions

View file

@ -680,6 +680,50 @@ function formatAbsoluteDateTime(date?: Date | null) {
}).format(date)
}
function parseDateish(value: unknown): Date | null {
if (!value) return null
if (value instanceof Date && !Number.isNaN(value.getTime())) return value
if (typeof value === "number" && Number.isFinite(value)) {
const numeric = value > 1e12 ? value : value > 1e9 ? value * 1000 : value
const date = new Date(numeric)
return Number.isNaN(date.getTime()) ? null : date
}
if (typeof value === "string") {
const trimmed = value.trim()
if (!trimmed) return null
const numericValue = Number(trimmed)
if (Number.isFinite(numericValue)) {
const asMs = trimmed.length >= 13 ? numericValue : numericValue * 1000
const date = new Date(asMs)
if (!Number.isNaN(date.getTime())) return date
}
const date = new Date(trimmed)
if (!Number.isNaN(date.getTime())) return date
}
return null
}
function getMetricsTimestamp(metrics: MachineMetrics): Date | null {
if (!metrics || typeof metrics !== "object") return null
const data = metrics as Record<string, unknown>
const candidates = [
data["collectedAt"],
data["collected_at"],
data["collected_at_iso"],
data["collected_at_ms"],
data["timestamp"],
data["updatedAt"],
data["updated_at"],
data["createdAt"],
data["created_at"],
]
for (const candidate of candidates) {
const parsed = parseDateish(candidate)
if (parsed) return parsed
}
return null
}
function formatBytes(bytes?: number | null) {
if (!bytes || Number.isNaN(bytes)) return "—"
const units = ["B", "KB", "MB", "GB", "TB"]
@ -930,6 +974,8 @@ export function MachineDetails({ machine }: MachineDetailsProps) {
const { convexUserId } = useAuth()
const router = useRouter()
const effectiveStatus = machine ? resolveMachineStatus(machine) : "unknown"
const isActive = machine?.isActive ?? true
const isDeactivated = !isActive || effectiveStatus === "deactivated"
// Company name lookup (by slug)
const companyQueryArgs = convexUserId && machine ? { tenantId: machine.tenantId, viewerId: convexUserId as Id<"users"> } : undefined
const companies = useQuery(
@ -946,6 +992,7 @@ export function MachineDetails({ machine }: MachineDetailsProps) {
const machineAlertsHistory = alertsHistory ?? []
const metadata = machine?.inventory ?? null
const metrics = machine?.metrics ?? null
const metricsCapturedAt = useMemo(() => getMetricsTimestamp(metrics), [metrics])
const hardware = metadata?.hardware
const network = metadata?.network ?? null
const networkInterfaces = Array.isArray(network) ? network : null
@ -972,7 +1019,6 @@ export function MachineDetails({ machine }: MachineDetailsProps) {
? windowsBaseboardRaw
: null
const windowsSerialNumber = windowsBaseboard ? readString(toRecord(windowsBaseboard) ?? {}, "SerialNumber", "serialNumber") : undefined
const isActive = machine?.isActive ?? true
const windowsMemoryModules = useMemo(() => {
if (Array.isArray(windowsMemoryModulesRaw)) return windowsMemoryModulesRaw
if (windowsMemoryModulesRaw && typeof windowsMemoryModulesRaw === "object") return [windowsMemoryModulesRaw]
@ -1307,9 +1353,9 @@ export function MachineDetails({ machine }: MachineDetailsProps) {
return (
<Card className="border-slate-200">
<CardHeader>
<CardHeader className="gap-1">
<CardTitle>Detalhes</CardTitle>
<CardDescription>Resumo da máquina selecionada.</CardDescription>
<CardDescription>Resumo da máquina selecionada</CardDescription>
{machine ? (
<CardAction>
<div className="flex flex-col items-end gap-2 text-xs sm:text-sm">
@ -1318,7 +1364,7 @@ export function MachineDetails({ machine }: MachineDetailsProps) {
{companyName}
</div>
) : null}
<MachineStatusBadge status={effectiveStatus} />
{!isDeactivated ? <MachineStatusBadge status={effectiveStatus} /> : null}
{!isActive ? (
<Badge variant="outline" className="h-7 border-rose-200 bg-rose-50 px-3 font-semibold uppercase text-rose-700">
Máquina desativada
@ -1499,7 +1545,14 @@ export function MachineDetails({ machine }: MachineDetailsProps) {
</section>
<section className="space-y-2">
<h4 className="text-sm font-semibold">Métricas recentes</h4>
<div className="flex flex-wrap items-center gap-2">
<h4 className="text-sm font-semibold">Métricas recentes</h4>
{metricsCapturedAt ? (
<span className="text-xs font-medium text-muted-foreground">
Última atualização {formatRelativeTime(metricsCapturedAt)}
</span>
) : null}
</div>
<MetricsGrid metrics={metrics} hardware={hardware} disks={disks} />
</section>