fix(machines): ensure machine details probe resolves
This commit is contained in:
parent
3fce36d4e5
commit
55316e51c6
2 changed files with 68 additions and 33 deletions
|
|
@ -1,6 +1,6 @@
|
|||
"use client"
|
||||
|
||||
import { useEffect, useMemo, useRef, useState } from "react"
|
||||
import { useEffect, useMemo, useState } from "react"
|
||||
import { useQuery } from "convex/react"
|
||||
import { useRouter } from "next/navigation"
|
||||
import { api } from "@/convex/_generated/api"
|
||||
|
|
@ -27,16 +27,14 @@ export function AdminMachineDetailsClient({ tenantId: _tenantId, machineId }: {
|
|||
const [fallback, setFallback] = useState<Record<string, unknown> | null | undefined>(undefined)
|
||||
const [loadError, setLoadError] = useState<string | null>(null)
|
||||
const [retryTick, setRetryTick] = useState(0)
|
||||
const timer = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
const shouldLoad = fallback === undefined && Boolean(machineId)
|
||||
|
||||
useEffect(() => {
|
||||
if (!shouldLoad) return
|
||||
(async () => {
|
||||
# immediate probe without delay
|
||||
|
||||
let cancelled = false
|
||||
|
||||
const probe = async () => {
|
||||
try {
|
||||
// 1) Tenta via Convex direto do browser (independe do servidor)
|
||||
const convexUrl = process.env.NEXT_PUBLIC_CONVEX_URL
|
||||
if (convexUrl) {
|
||||
try {
|
||||
|
|
@ -45,54 +43,90 @@ export function AdminMachineDetailsClient({ tenantId: _tenantId, machineId }: {
|
|||
id: machineId as Id<"machines">,
|
||||
includeMetadata: true,
|
||||
})) as Record<string, unknown> | null
|
||||
|
||||
if (cancelled) return
|
||||
|
||||
if (data) {
|
||||
setFallback(data)
|
||||
setLoadError(null)
|
||||
return
|
||||
}
|
||||
} catch {
|
||||
// continua para o plano B
|
||||
|
||||
if (data === null) {
|
||||
setFallback(null)
|
||||
setLoadError(null)
|
||||
return
|
||||
}
|
||||
} catch (err) {
|
||||
if (cancelled) return
|
||||
console.warn("[admin-machine-details] Convex probe failed, falling back to API route", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 2) Plano B: rota do servidor (útil em ambientes sem Convex público)
|
||||
try {
|
||||
const res = await fetch(`/api/admin/machines/${machineId}/details`, { credentials: "include" })
|
||||
const res = await fetch(`/api/admin/machines/${machineId}/details`, {
|
||||
credentials: "include",
|
||||
cache: "no-store",
|
||||
})
|
||||
|
||||
if (cancelled) return
|
||||
|
||||
let payload: Record<string, unknown> | null = null
|
||||
try {
|
||||
payload = (await res.json()) as Record<string, unknown> | null
|
||||
} catch {
|
||||
payload = null
|
||||
}
|
||||
|
||||
if (res.ok) {
|
||||
const data = (await res.json()) as Record<string, unknown>
|
||||
setFallback(data ?? null)
|
||||
setFallback(payload ?? null)
|
||||
setLoadError(null)
|
||||
return
|
||||
}
|
||||
|
||||
const message =
|
||||
typeof payload?.error === "string" && payload.error
|
||||
? payload.error
|
||||
: `Falha ao carregar (HTTP ${res.status})`
|
||||
|
||||
if (res.status === 404) {
|
||||
setFallback(null)
|
||||
setLoadError(null)
|
||||
} else {
|
||||
let message = `Falha ao carregar (HTTP ${res.status})`
|
||||
try {
|
||||
const payload = (await res.json()) as Record<string, unknown>
|
||||
if (typeof payload?.error === "string" && payload.error) {
|
||||
message = payload.error
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
if (res.status == 404) {
|
||||
setFallback(null)
|
||||
} else {
|
||||
setLoadError(message)
|
||||
}
|
||||
setLoadError(message)
|
||||
}
|
||||
} catch (err) {
|
||||
if (!cancelled) {
|
||||
console.error("[admin-machine-details] API fallback fetch failed", err)
|
||||
setLoadError("Erro de rede ao carregar os dados da máquina.")
|
||||
}
|
||||
} catch {
|
||||
setLoadError("Erro de rede ao carregar os dados da máquina.")
|
||||
}
|
||||
} catch (err) {
|
||||
if (!cancelled) {
|
||||
console.error("[admin-machine-details] Unexpected probe failure", err)
|
||||
setLoadError("Erro de rede ao carregar os dados da máquina.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
probe().catch((err) => {
|
||||
if (!cancelled) {
|
||||
console.error("[admin-machine-details] Probe promise rejected", err)
|
||||
setLoadError("Erro de rede ao carregar os dados da máquina.")
|
||||
}
|
||||
})
|
||||
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
}, [shouldLoad, machineId, retryTick])
|
||||
|
||||
// Timeout de proteção: se depois de X segundos ainda estiver carregando e sem fallback, mostra erro claro
|
||||
useEffect(() => {
|
||||
if (!shouldLoad) return
|
||||
const timeout = setTimeout(() => {
|
||||
setLoadError(
|
||||
"Tempo esgotado ao consultar os dados (Convex). Verifique sua conexão e tente novamente."
|
||||
setLoadError((error) =>
|
||||
error ?? "Tempo esgotado ao consultar os dados (Convex). Verifique sua conexão e tente novamente."
|
||||
)
|
||||
}, 10_000)
|
||||
return () => clearTimeout(timeout)
|
||||
|
|
@ -108,7 +142,7 @@ export function AdminMachineDetailsClient({ tenantId: _tenantId, machineId }: {
|
|||
|
||||
const onRetry = () => {
|
||||
setLoadError(null)
|
||||
setFallback(null)
|
||||
setFallback(undefined)
|
||||
setRetryTick((t) => t + 1)
|
||||
// força revalidação de RSC/convex subscription
|
||||
try {
|
||||
|
|
@ -159,4 +193,3 @@ export function AdminMachineDetailsClient({ tenantId: _tenantId, machineId }: {
|
|||
|
||||
return <MachineDetails machine={machine} />
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue