UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

1 lines 5.19 kB
{"version":3,"sources":["../src/hooks/useZendesk.ts"],"sourcesContent":["import { useCallback, useEffect, useState } from 'react';\n\nexport interface UseZendeskConfig {\n /** Chave do canal Zendesk (snippet). */\n zendeskKey: string;\n /**\n * Carrega o messenger apenas quando `true` (ex.: suporte é ZENDESK).\n * Default: `true`.\n */\n enabled?: boolean;\n}\n\nexport interface UseZendeskReturn {\n /** `true` quando o messenger (`window.zE`) está disponível para abrir. */\n ready: boolean;\n /** Abre o messenger do Zendesk. No-op enquanto não estiver pronto. */\n openChat: () => void;\n}\n\nconst SCRIPT_ID = 'ze-snippet';\nconst INITIAL_RETRY_MS = 2000;\nconst MAX_RETRY_MS = 30_000;\nconst POLL_MS = 500;\n\ntype ZE = (...args: unknown[]) => void;\n\nconst getZE = (): ZE | undefined =>\n (globalThis as unknown as Record<string, unknown>).zE as ZE | undefined;\n\n/**\n * Carrega o messenger do Zendesk de forma resiliente e isolada:\n * - injeta o snippet uma única vez (dedupe por id);\n * - se o script falhar (rede), re-injeta com backoff exponencial até carregar;\n * - sinaliza `ready` assim que `window.zE` fica disponível;\n * - `openChat` abre o messenger (no-op enquanto não estiver pronto).\n *\n * O loop de carregamento fica confinado a este hook — não bloqueia o restante\n * da página (form de login, Google, etc. funcionam independentemente).\n */\nexport const useZendesk = ({\n zendeskKey,\n enabled = true,\n}: UseZendeskConfig): UseZendeskReturn => {\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n if (!enabled || !zendeskKey) return;\n\n let cancelled = false;\n let attempt = 0;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n let pollTimer: ReturnType<typeof setInterval> | undefined;\n\n function confirmReady(): boolean {\n const zE = getZE();\n if (!zE) return false;\n zE('messenger:set', 'locale', 'pt-BR');\n if (!cancelled) setReady(true);\n return true;\n }\n\n function scheduleRetry() {\n if (cancelled) return;\n const delay = Math.min(INITIAL_RETRY_MS * 2 ** attempt, MAX_RETRY_MS);\n attempt += 1;\n retryTimer = setTimeout(inject, delay);\n }\n\n function handleScriptError() {\n if (cancelled) return;\n document.getElementById(SCRIPT_ID)?.remove();\n scheduleRetry();\n }\n\n function inject() {\n if (cancelled || confirmReady()) return;\n\n // Se o snippet já existe (ex.: injetado por outro ponto, como o\n // ZendeskWidget), não injeta de novo — mas adota o tratamento de erro\n // para manter o retry e não deixar `ready` travado caso ele falhe.\n const existing = document.getElementById(\n SCRIPT_ID\n ) as HTMLScriptElement | null;\n if (existing) {\n existing.addEventListener('error', handleScriptError, { once: true });\n return;\n }\n\n const script = document.createElement('script');\n script.id = SCRIPT_ID;\n script.src = `https://static.zdassets.com/ekr/snippet.js?key=${zendeskKey}`;\n script.async = true;\n script.addEventListener('error', handleScriptError, { once: true });\n document.body.appendChild(script);\n }\n\n inject();\n\n // Poll leve (sem rede) só para detectar quando o `zE` fica disponível.\n pollTimer = setInterval(() => {\n if (cancelled) return;\n if (confirmReady() && pollTimer) clearInterval(pollTimer);\n }, POLL_MS);\n\n return () => {\n cancelled = true;\n if (retryTimer) clearTimeout(retryTimer);\n if (pollTimer) clearInterval(pollTimer);\n };\n }, [zendeskKey, enabled]);\n\n const openChat = useCallback(() => {\n getZE()?.('messenger', 'open');\n }, []);\n\n return { ready, openChat };\n};\n"],"mappings":";AAAA,SAAS,aAAa,WAAW,gBAAgB;AAmBjD,IAAM,YAAY;AAClB,IAAM,mBAAmB;AACzB,IAAM,eAAe;AACrB,IAAM,UAAU;AAIhB,IAAM,QAAQ,MACX,WAAkD;AAY9C,IAAM,aAAa,CAAC;AAAA,EACzB;AAAA,EACA,UAAU;AACZ,MAA0C;AACxC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,KAAK;AAExC,YAAU,MAAM;AACd,QAAI,CAAC,WAAW,CAAC,WAAY;AAE7B,QAAI,YAAY;AAChB,QAAI,UAAU;AACd,QAAI;AACJ,QAAI;AAEJ,aAAS,eAAwB;AAC/B,YAAM,KAAK,MAAM;AACjB,UAAI,CAAC,GAAI,QAAO;AAChB,SAAG,iBAAiB,UAAU,OAAO;AACrC,UAAI,CAAC,UAAW,UAAS,IAAI;AAC7B,aAAO;AAAA,IACT;AAEA,aAAS,gBAAgB;AACvB,UAAI,UAAW;AACf,YAAM,QAAQ,KAAK,IAAI,mBAAmB,KAAK,SAAS,YAAY;AACpE,iBAAW;AACX,mBAAa,WAAW,QAAQ,KAAK;AAAA,IACvC;AAEA,aAAS,oBAAoB;AAC3B,UAAI,UAAW;AACf,eAAS,eAAe,SAAS,GAAG,OAAO;AAC3C,oBAAc;AAAA,IAChB;AAEA,aAAS,SAAS;AAChB,UAAI,aAAa,aAAa,EAAG;AAKjC,YAAM,WAAW,SAAS;AAAA,QACxB;AAAA,MACF;AACA,UAAI,UAAU;AACZ,iBAAS,iBAAiB,SAAS,mBAAmB,EAAE,MAAM,KAAK,CAAC;AACpE;AAAA,MACF;AAEA,YAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,aAAO,KAAK;AACZ,aAAO,MAAM,kDAAkD,UAAU;AACzE,aAAO,QAAQ;AACf,aAAO,iBAAiB,SAAS,mBAAmB,EAAE,MAAM,KAAK,CAAC;AAClE,eAAS,KAAK,YAAY,MAAM;AAAA,IAClC;AAEA,WAAO;AAGP,gBAAY,YAAY,MAAM;AAC5B,UAAI,UAAW;AACf,UAAI,aAAa,KAAK,UAAW,eAAc,SAAS;AAAA,IAC1D,GAAG,OAAO;AAEV,WAAO,MAAM;AACX,kBAAY;AACZ,UAAI,WAAY,cAAa,UAAU;AACvC,UAAI,UAAW,eAAc,SAAS;AAAA,IACxC;AAAA,EACF,GAAG,CAAC,YAAY,OAAO,CAAC;AAExB,QAAM,WAAW,YAAY,MAAM;AACjC,UAAM,IAAI,aAAa,MAAM;AAAA,EAC/B,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,OAAO,SAAS;AAC3B;","names":[]}