Auth: poll machine session to reflect deactivation in real time; Desktop: refresh deactivation screen to match design system
This commit is contained in:
parent
01461d031b
commit
77f48652cd
2 changed files with 75 additions and 24 deletions
|
|
@ -1,40 +1,40 @@
|
||||||
import { RefreshCw, Mail } from "lucide-react"
|
import { ShieldAlert, Mail } from "lucide-react"
|
||||||
|
|
||||||
export function DeactivationScreen({ companyName }: { companyName?: string | null }) {
|
export function DeactivationScreen({ companyName }: { companyName?: string | null }) {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen grid place-items-center bg-slate-100 p-6">
|
<div className="min-h-screen grid place-items-center bg-gradient-to-b from-slate-50 via-slate-50 to-white p-6">
|
||||||
<div className="flex flex-col items-center gap-5 rounded-3xl border border-slate-200 bg-white px-8 py-10 shadow-xl">
|
<div className="flex w-full max-w-[720px] flex-col items-center gap-6 rounded-2xl border border-slate-200 bg-white px-8 py-10 shadow-sm">
|
||||||
<div className="flex flex-col items-center gap-3 text-center">
|
<div className="flex flex-col items-center gap-3 text-center">
|
||||||
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-neutral-900 text-white shadow-lg">
|
<span className="inline-flex items-center gap-2 rounded-full border border-rose-200 bg-rose-50 px-3 py-1 text-xs font-semibold text-rose-700">
|
||||||
<RefreshCw className="size-7 animate-pulse" />
|
<ShieldAlert className="size-4" /> Acesso bloqueado
|
||||||
</div>
|
</span>
|
||||||
<h1 className="text-2xl font-semibold text-neutral-900">Máquina desativada</h1>
|
<h1 className="text-2xl font-semibold text-neutral-900">Máquina desativada</h1>
|
||||||
<p className="max-w-sm text-sm text-neutral-600">
|
<p className="max-w-md text-sm text-neutral-600">
|
||||||
Esta máquina foi desativada temporariamente por um administrador da Rever. Enquanto estiver nessa situação,
|
Esta máquina foi desativada temporariamente pelos administradores. Enquanto isso, o acesso ao portal e o
|
||||||
o acesso ao portal e o envio de informações ficam bloqueados.
|
envio de informações ficam indisponíveis.
|
||||||
</p>
|
</p>
|
||||||
{companyName ? (
|
{companyName ? (
|
||||||
<span className="rounded-full bg-slate-100 px-3 py-1 text-xs font-semibold text-neutral-700">
|
<span className="rounded-full border border-slate-200 bg-slate-50 px-3 py-1 text-xs font-semibold text-neutral-700">
|
||||||
{companyName}
|
{companyName}
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full max-w-[360px] space-y-3 text-sm text-neutral-600">
|
|
||||||
<div className="rounded-2xl border border-slate-200 bg-slate-50 p-4">
|
<div className="w-full max-w-[520px] space-y-4">
|
||||||
<p className="font-medium text-neutral-800">Como proceder?</p>
|
<div className="rounded-xl border border-slate-200 bg-slate-50 p-4 text-sm text-neutral-700">
|
||||||
<ul className="mt-2 space-y-2 text-neutral-600">
|
<p className="font-medium text-neutral-800">Como regularizar</p>
|
||||||
<li>
|
<ul className="mt-2 list-disc space-y-1 pl-5 text-neutral-600">
|
||||||
<span className="font-semibold text-neutral-800">1.</span> Caso precise restaurar o acesso, entre em contato com a equipe de suporte da Rever.
|
<li>Entre em contato com o suporte da Rever e solicite a reativação.</li>
|
||||||
</li>
|
<li>Informe o nome do computador e seus dados de contato.</li>
|
||||||
<li>
|
|
||||||
<span className="font-semibold text-neutral-800">2.</span> Informe o identificador desta máquina e peça a reativação.
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col items-center gap-2 rounded-2xl border border-dashed border-neutral-300 bg-neutral-50 px-4 py-3 text-center text-xs text-neutral-500">
|
|
||||||
<Mail className="size-4" />
|
<a
|
||||||
suporte@rever.com.br
|
href="mailto:suporte@rever.com.br"
|
||||||
</div>
|
className="mx-auto inline-flex items-center gap-2 rounded-full border border-black bg-black px-4 py-2 text-sm font-semibold text-white transition hover:bg-black/90"
|
||||||
|
>
|
||||||
|
<Mail className="size-4" /> Falar com o suporte
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,57 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||||
}
|
}
|
||||||
}, [session?.user])
|
}, [session?.user])
|
||||||
|
|
||||||
|
// Poll machine session periodically to reflect admin changes (e.g., deactivation)
|
||||||
|
useEffect(() => {
|
||||||
|
const shouldPoll = Boolean(session?.user?.role === "machine") || Boolean(machineContext)
|
||||||
|
if (!shouldPoll) return
|
||||||
|
let cancelled = false
|
||||||
|
const tick = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/machines/session", { credentials: "include" })
|
||||||
|
if (!response.ok) return
|
||||||
|
const data = await response.json()
|
||||||
|
if (cancelled) return
|
||||||
|
const mc = data?.machine
|
||||||
|
if (mc && typeof mc === "object") {
|
||||||
|
setMachineContext((prev) => {
|
||||||
|
// only update when something changes to avoid re-renders
|
||||||
|
const next = {
|
||||||
|
machineId: mc.id,
|
||||||
|
tenantId: mc.tenantId,
|
||||||
|
persona: mc.persona ?? null,
|
||||||
|
assignedUserId: mc.assignedUserId ?? null,
|
||||||
|
assignedUserEmail: mc.assignedUserEmail ?? null,
|
||||||
|
assignedUserName: mc.assignedUserName ?? null,
|
||||||
|
assignedUserRole: mc.assignedUserRole ?? null,
|
||||||
|
companyId: mc.companyId ?? null,
|
||||||
|
isActive: (mc.isActive ?? true) as boolean,
|
||||||
|
} as MachineContext
|
||||||
|
return JSON.stringify(prev) === JSON.stringify(next) ? prev : next
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
/* ignore transient errors */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const id = setInterval(tick, 15000)
|
||||||
|
// Also refresh when tab gains focus
|
||||||
|
const onFocus = () => tick()
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
window.addEventListener("focus", onFocus)
|
||||||
|
document.addEventListener("visibilitychange", onFocus)
|
||||||
|
}
|
||||||
|
tick()
|
||||||
|
return () => {
|
||||||
|
cancelled = true
|
||||||
|
clearInterval(id)
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
window.removeEventListener("focus", onFocus)
|
||||||
|
document.removeEventListener("visibilitychange", onFocus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [session?.user?.role, machineContext])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!session?.user || session.user.role === "machine" || convexUserId) return
|
if (!session?.user || session.user.role === "machine" || convexUserId) return
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue