forlogic-core 2.4.7 → 2.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/services/userProfileApi.d.ts +5 -5
- package/dist/components/modules/ModuleAccessGuard.d.ts +20 -1
- package/dist/contexts/ModuleContext.d.ts +18 -2
- package/dist/index.esm.js +1 -1
- package/dist/index.js +1 -1
- package/dist/providers/CoreProviders.d.ts +17 -1
- package/dist/sign/index.esm.js +1 -1
- package/dist/sign/index.js +1 -1
- package/dist/sign/services/signService.d.ts +9 -1
- package/docs/design-system/patterns/core-providers.md +105 -0
- package/docs/design-system/patterns/module-access.md +72 -0
- package/package.json +1 -1
|
@@ -51,6 +51,22 @@ export interface CoreProvidersProps {
|
|
|
51
51
|
* // ex: "https://api.qualiex.com/api/inovacao/v1"
|
|
52
52
|
*/
|
|
53
53
|
associationsBaseUrl?: string;
|
|
54
|
+
/**
|
|
55
|
+
* Schema Postgres onde a tabela `sign_documents` vive neste projeto.
|
|
56
|
+
* Quando informado, é propagado no payload de `create_and_send` (edge
|
|
57
|
+
* function `d4sign`) como query param da callback URL e usado pelo front
|
|
58
|
+
* para ler/realtime no schema correto.
|
|
59
|
+
*
|
|
60
|
+
* Default `'common'` (Admin).
|
|
61
|
+
*
|
|
62
|
+
* @example signDocumentsSchema="educacao"
|
|
63
|
+
*/
|
|
64
|
+
signDocumentsSchema?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Nome da tabela usada para tracking do envelope D4Sign.
|
|
67
|
+
* Default `'sign_documents'`.
|
|
68
|
+
*/
|
|
69
|
+
signDocumentsTable?: string;
|
|
54
70
|
/**
|
|
55
71
|
* Props opcionais para o ModuleAccessGuard.
|
|
56
72
|
* Permite configurar módulos contratados, callbacks e URLs.
|
|
@@ -132,4 +148,4 @@ export declare function getSecurityMode(): 'legacy' | 'strict';
|
|
|
132
148
|
* }
|
|
133
149
|
* ```
|
|
134
150
|
*/
|
|
135
|
-
export declare function CoreProviders({ children, queryClient, moduleAlias, associationsBaseUrl, moduleAccessGuardProps, appTranslations, clarityProjectId, clarityMode, backend, securityMode, }: CoreProvidersProps): import("react/jsx-runtime").JSX.Element;
|
|
151
|
+
export declare function CoreProviders({ children, queryClient, moduleAlias, associationsBaseUrl, signDocumentsSchema, signDocumentsTable, moduleAccessGuardProps, appTranslations, clarityProjectId, clarityMode, backend, securityMode, }: CoreProvidersProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/sign/index.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsxs as e,jsx as n}from"react/jsx-runtime";import{useState as a,useEffect as i,useCallback as s,useRef as t,useMemo as r}from"react";import{useAuth as o,getSupabaseClient as l,Alert as c,AlertTitle as d,AlertDescription as m,toast as u,Card as g,CardContent as h,Button as p,CardHeader as f,CardTitle as v,Label as _,Input as w,Select as x,SelectTrigger as N,SelectValue as b,SelectContent as y,SelectItem as D,Badge as k,Separator as A}from"forlogic-core";import{Loader2 as E,CheckCircle2 as S,Download as C,RefreshCw as M,Upload as I,CheckCircle as j,AlertCircle as L,AlertTriangle as T,Send as R,ExternalLink as P,Circle as $}from"lucide-react";import{useTranslation as U}from"react-i18next";import G from"i18next";function V(){const{alias:e}=o(),[n,t]=a(null),[r,c]=a(!0);i(()=>{if(!e)return void c(!1);let n=!1;return(async()=>{c(!0);try{const a=l(),{data:i,error:s}=await a.schema("common").from("sign_configs").select("*").eq("alias",e).is("deleted_at",null).maybeSingle();n||t(i)}catch(a){n||t(null)}finally{n||c(!1)}})(),()=>{n=!0}},[e]);return{config:n,isLoading:r,saveConfig:s(async(n,a)=>{if(!e)throw new Error("Alias not available");const i=l(),{data:s,error:r}=await i.schema("common").from("sign_configs").upsert({alias:e,api_key:n,environment:a,updated_at:(new Date).toISOString()},{onConflict:"alias"}).select().maybeSingle();if(r)throw r;return t(s),s},[e])}}async function F(e,n,a){const i=l(),{data:s,error:t}=await i.functions.invoke(e,{body:{action:n,data:a}});if(t){const n=t.context;if(n&&"function"==typeof n.json){const a=await n.json().catch(()=>null),i=a?.error||a?.message||t.message;throw new Error(i||`Erro na requisição: ${e}`)}throw new Error(t.message||`Erro na requisição: ${e}`)}return s}const q={createEnvelopeWithSigner:async e=>F("d4sign"===e.provider?"d4sign":"clicksign","d4sign"===e.provider?"create_and_send":"create_envelope_with_signer",{content_base64:e.contentBase64,filename:e.filename,signer_email:e.signerEmail,signer_name:e.signerName}),getSignedDocument:async e=>F("d4sign"===e.provider?"d4sign":"clicksign","get_signed_document",{envelope_id:e.envelopeId,document_id:e.documentId}),async getD4SignDocumentRecord(e){const n=l(),{data:a,error:i}=await n.schema("common").from("sign_documents").select("status, download_url, signed_at").eq("envelope_id",e).maybeSingle();if(i)throw new Error(i.message);return a??null}};let J=null;function B(){return window.Clicksign?Promise.resolve():J||(J=new Promise((e,n)=>{const a=document.createElement("script");a.src="https://cdn-public-library.clicksign.com/embedded/embedded.min-2.1.0.js",a.onload=()=>e(),a.onerror=()=>n(new Error("Falha ao carregar script do Clicksign")),document.head.appendChild(a)}),J)}const Q="clicksign-container";function W({signerId:s,environment:r="sandbox",onSign:o,onError:l,onClose:c}){const{t:d}=U(),m=t(null),[u,g]=a(!0),[h,p]=a(null);return i(()=>{let e=!1;return m.current&&(m.current.unmount(),m.current=null),p(null),g(!0),B().then(()=>{if(e)return;const n=new window.Clicksign(s);n.endpoint="production"===r?"https://app.clicksign.com":"https://sandbox.clicksign.com",n.origin=window.origin,n.mount(Q),n.on("loaded",function(){g(!1)}),n.on("signed",function(){o?.()}),n.on("resized",function(e){const n=e,a=document.getElementById(Q);a&&n?.data?.height&&(a.style.height=n.data.height+"px")}),n.on("error",function(e){g(!1),l?.(e instanceof Error?e:new Error(d("sign_widget_error")))}),n.on("closed",function(){c?.()}),m.current=n}).catch(n=>{e||(p("Falha ao carregar o script de assinatura."),g(!1),l?.(n))}),()=>{e=!0,m.current&&(m.current.unmount(),m.current=null)}},[s,r]),e("div",{className:"relative h-full",children:[u&&n("div",{className:"absolute inset-0 flex items-center justify-center",children:e("div",{className:"flex items-center gap-2 text-muted-foreground",children:[n(E,{className:"h-5 w-5 animate-spin"}),n("span",{className:"text-sm",children:"Carregando documento..."})]})}),h&&n("div",{className:"absolute inset-0 flex items-center justify-center",children:n("p",{className:"text-sm text-destructive",children:h})}),n("div",{id:Q,style:{height:"600px"}})]})}function Z({documentKey:r,signerEmail:o,signerName:l,keySigner:u,environment:g,onSign:h,onError:p}){const f=t(null),[v,_]=a("loading"),[w,x]=a(null),N="production"===g?"https://secure.d4sign.com.br/embed/viewblob":"https://sandbox.d4sign.com.br/embed/viewblob",b=(()=>{const e=new URLSearchParams({email:o,display_name:l||"",disable_preview:"0"});return u&&e.set("key_signer",u),`${N}/${r}?${e.toString()}`})(),y=s(e=>"signed"===e.data?(_("ready"),void h?.()):"wrong-data"===e.data?(_("error"),x(G.t("sign_incorrect_data")),void p?.(new Error(G.t("sign_incorrect_data")))):void 0,[h,p]);i(()=>(window.addEventListener("message",y,!1),()=>{window.removeEventListener("message",y,!1)}),[y]);const D=s(()=>{"loading"===v&&_("ready")},[v]);return"error"===v?e(c,{variant:"danger",className:"my-4",children:[n(d,{children:G.t("sign_doc_load_error")}),n(m,{children:w||"Ocorreu um erro inesperado ao carregar o documento para assinatura. Tente novamente."})]}):e("div",{className:"relative h-full",children:["loading"===v&&n("div",{className:"absolute inset-0 flex items-center justify-center",children:e("div",{className:"flex items-center gap-2 text-muted-foreground",children:[n(E,{className:"h-5 w-5 animate-spin"}),n("span",{className:"text-sm",children:"Carregando documento..."})]})}),n("iframe",{ref:f,id:"d4sign-container",src:b,width:"100%",style:{height:"600px",border:0},allow:"geolocation",onLoad:D})]})}function z({file:r,onDocumentSigned:c,onError:d,showEventLog:m=!1}){const{user:f,alias:v}=o(),{config:_,isLoading:w}=V(),{t:x}=U(),[N,b]=a(null),[y,D]=a(!1),[k,A]=a(null),[j,L]=a("sandbox"),[T,R]=a("clicksign"),[P,$]=a(null),[F,J]=a(null),[B,Q]=a(!1),[z,K]=a(0),[Y,O]=a(!1),[H,X]=a([]),ee=t(null),ne=t(null),ae=s(e=>{m&&X(n=>[...n,`[${(new Date).toLocaleTimeString()}] ${e}`])},[m]),ie=s(async e=>{if(b(e),A(null),$(null),J(null),ae(`Arquivo selecionado: ${e.name}`),v&&f){D(!0);try{const n=_?.provider??"clicksign";R(n),ae(`Provedor resolvido: ${n}`);const a=new FileReader,i=await new Promise((n,i)=>{a.onload=()=>{const e=a.result;n(e)},a.onerror=i,a.readAsDataURL(e)});ae(`Criando envelope para assinatura via ${n}...`);const s=await q.createEnvelopeWithSigner({alias:v,contentBase64:i,filename:e.name,signerEmail:f.email||"",signerName:f.name||"",provider:n});ae(`Envelope criado: ${s.envelope_id}`),$({envelope_id:s.envelope_id,document_id:s.document_id,signer_email:s.signer_email,key_signer:s.signer_id}),L(s.environment),R(s.provider||n),"d4sign"===n?(ae("Documento enviado para D4Sign. Abrindo widget de assinatura..."),await new Promise(e=>setTimeout(e,2e3)),A(s.document_id),u.success(x("sign_doc_sent","Documento enviado! Assine abaixo."))):s.signer_id?(ae(`Signer ID obtido: ${s.signer_id}. Aguardando processamento (3s)...`),await new Promise(e=>setTimeout(e,3e3)),A(s.signer_id),u.success(x("sign_doc_sent","Documento enviado! Assine abaixo."))):(ae(G.t("sign_signer_unavailable")),u.error(x("sign_access_error","Não foi possível obter o acesso para assinatura. Tente novamente.")),d?.(new Error(x("sign_signer_unavailable"))))}catch(n){const e=n instanceof Error?n:new Error(x("sign_process_error",x("sign_doc_process_error"))),a=e.message||"";a.includes("MONTHLY_LIMIT_REACHED")?(ae(G.t("sign_monthly_limit")),u.error(x("sign_monthly_limit","Limite mensal de assinaturas atingido. Entre em contato com o administrador para ampliar seu plano."))):(ae(`Erro: ${a}`),u.error(a)),d?.(e)}finally{D(!1)}}},[v,f,ae,d,_]);i(()=>{r&&v&&f&&!w&&r!==ne.current&&(ne.current=r,ie(r))},[r,v,f,w,ie]);const se=t(null),te=s(()=>{if(se.current){try{l().removeChannel(se.current)}catch{}se.current=null}},[]);i(()=>()=>te(),[te]);const re=s(e=>!!e&&("signed"===e.status&&e.download_url?(ae(G.t("sign_doc_available")),J(e.download_url),Q(!1),O(!1),te(),!0):("cancelled"===e.status||"failed"===e.status)&&(ae(`Assinatura ${"cancelled"===e.status?"cancelada":"falhou"}.`),Q(!1),O(!0),te(),!0)),[ae,te]),oe=s(async()=>{if(!P||!v)return;if(Q(!0),K(0),O(!1),ae("Buscando documento assinado..."),"d4sign"===T){try{const e=await q.getD4SignDocumentRecord(P.envelope_id);if(re(e))return}catch(e){ae(`Erro na verificação inicial: ${e instanceof Error?e.message:x("unknown_error")}`)}te();const n=l().channel(`sign:${P.envelope_id}`).on("postgres_changes",{event:"UPDATE",schema:"common",table:"sign_documents",filter:`envelope_id=eq.${P.envelope_id}`},e=>{ae(`Webhook recebido: status=${e.new.status}`),re(e.new)}).subscribe();se.current=n,ae("Aguardando confirmação do D4Sign via webhook...");return void setTimeout(()=>{se.current!==n||F||(ae(G.t("sign_fetch_failed")),Q(!1),O(!0))},3e5)}for(let n=1;n<=6;n++){K(n),ae(`Tentativa ${n}/6...`);try{const e=await q.getSignedDocument({alias:v,envelopeId:P.envelope_id,documentId:P.document_id,provider:T});if(e.download_url)return ae(G.t("sign_doc_available")),J(e.download_url),void Q(!1)}catch(e){ae(`Erro na tentativa ${n}: ${e instanceof Error?e.message:x("unknown_error")}`)}n<6&&(ae("Aguardando 10 segundos para próxima tentativa..."),await new Promise(e=>setTimeout(e,1e4)))}ae(G.t("sign_fetch_failed")),Q(!1),O(!0)},[P,v,ae,T,x,re,te,F]),le=s(async()=>{ae("Documento assinado com sucesso!"),u.success(x("sign_signed_success","Documento assinado com sucesso!")),A(null),P&&v&&(c?.({success:!0,provider:T,envelope_id:P.envelope_id,document_id:P.document_id,signer_id:k||"",environment:j}),await oe())},[ae,c,P,k,v,j,T,oe]);if(!v)return n(g,{className:"border-amber-200 bg-amber-50",children:n(h,{className:"flex items-start gap-3 py-6",children:e("div",{children:[n("p",{className:"font-medium text-amber-800",children:x("sign_auth_required","Autenticação necessária")}),n("p",{className:"text-sm text-amber-700 mt-1",children:x("sign_login_required","Faça login para utilizar a assinatura digital.")})]})})});const ce="d4sign"===T?"D4Sign":"Clicksign",de=()=>m&&H.length>0?n("div",{className:"bg-muted p-3 rounded-md text-xs font-mono space-y-1 max-h-40 overflow-auto",children:H.map((e,a)=>n("div",{children:e},a))}):null;return P&&!k&&(F||B||Y)?e("div",{className:"space-y-4",children:[n(g,{className:"border-green-200 bg-green-50",children:e(h,{className:"flex flex-col items-center gap-4 py-8",children:[n(S,{className:"h-12 w-12 text-green-600"}),e("div",{className:"text-center",children:[n("p",{className:"text-lg font-semibold text-green-800",children:x("sign_signed_success","Documento assinado com sucesso!")}),n("p",{className:"text-sm text-green-700 mt-1",children:N?.name})]}),B?e("div",{className:"flex flex-col items-center gap-2 text-sm text-muted-foreground",children:[e("div",{className:"flex items-center gap-2",children:[n(E,{className:"h-4 w-4 animate-spin"}),x("sign_preparing_doc","Preparando documento assinado...")," (",x("sign_attempt","tentativa")," ",z,"/6)"]}),n("p",{className:"text-xs text-muted-foreground",children:x("sign_waiting_provider",`Aguardando processamento pelo ${ce}...`)})]}):F?n(p,{asChild:!0,variant:"default",className:"gap-2",children:e("a",{href:F,target:"_blank",rel:"noopener noreferrer",children:[n(C,{className:"h-4 w-4"}),x("sign_download_signed","Baixar documento assinado")]})}):Y?e("div",{className:"text-center space-y-3",children:[e("div",{className:"space-y-1",children:[n("p",{className:"text-sm text-muted-foreground",children:x("sign_fetch_failed","Não foi possível obter o documento assinado após 1 minuto.")}),n("p",{className:"text-xs text-muted-foreground",children:x("sign_email_fallback","O documento será enviado para o seu e-mail assim que estiver disponível.")})]}),e(p,{variant:"secondary",className:"gap-2",onClick:oe,children:[n(M,{className:"h-4 w-4"}),x("sign_try_again","Tentar novamente")]})]}):null]})}),n(de,{})]}):k?e("div",{className:"space-y-4",children:["d4sign"===T?n(Z,{documentKey:k,signerEmail:P?.signer_email||f?.email||"",signerName:f?.name,keySigner:P?.key_signer,environment:j,onSign:le,onError:d}):n(W,{signerId:k,environment:j,onSign:le,onError:d}),n(de,{})]}):r&&(y||w)?n(g,{children:e(h,{className:"flex items-center justify-center gap-3 py-10",children:[n(E,{className:"h-6 w-6 animate-spin text-primary"}),n("p",{className:"font-medium",children:x("sign_sending_doc","Enviando documento para assinatura...")})]})}):e("div",{className:"space-y-4",children:[n("input",{ref:ee,type:"file",accept:"application/pdf",className:"hidden",onChange:e=>{const n=e.target.files?.[0];n&&"application/pdf"===n.type?ie(n):u.error(x("sign_select_pdf","Selecione um arquivo PDF"))}}),n(g,y?{children:e(h,{className:"flex items-center justify-center gap-3 py-10",children:[n(E,{className:"h-6 w-6 animate-spin text-primary"}),n("p",{className:"font-medium",children:x("sign_sending_doc","Enviando documento para assinatura...")})]})}:{className:"border-dashed border-2 cursor-pointer hover:bg-muted/50 transition-colors",onClick:()=>ee.current?.click(),children:e(h,{className:"flex flex-col items-center justify-center py-10 gap-3",children:[n(I,{className:"h-8 w-8 text-muted-foreground"}),e("div",{className:"text-center",children:[n("p",{className:"font-medium",children:x("sign_select_pdf","Selecione um arquivo PDF")}),n("p",{className:"text-sm text-muted-foreground",children:x("sign_click_to_select","Clique para escolher o documento para assinatura")})]})]})}),n(de,{})]})}function K({onSaved:s}){const{config:t,isLoading:r,saveConfig:o}=V(),{t:l}=U(),[c,d]=a(""),[m,k]=a("sandbox"),[A,S]=a(!1);i(()=>{!r&&t&&(d(t.api_key),k(t.environment))},[t,r]);return r?n("div",{className:"flex items-center justify-center py-8",children:n(E,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):e("div",{className:"space-y-4",children:[e("div",t?{className:"flex items-center gap-2 text-sm text-emerald-600",children:[n(j,{className:"h-4 w-4"}),n("span",{children:l("sign_configured",l("sign_configured_unit"))})]}:{className:"flex items-center gap-2 text-sm text-amber-600",children:[n(L,{className:"h-4 w-4"}),n("span",{children:l("sign_not_configured",l("sign_not_configured_unit"))})]}),e(g,{children:[n(f,{children:n(v,{className:"text-base",children:l("sign_digital_config")})}),n(h,{children:e("form",{onSubmit:async e=>{if(e.preventDefault(),c.trim()){S(!0);try{await o(c.trim(),m),u.success(l("sign_config_saved",l("sign_config_saved_success"))),s?.()}catch(n){u.error(l("sign_config_save_error",l("sign_config_save_err")))}finally{S(!1)}}else u.error(l("sign_api_key_required",l("sign_api_key_info")))},className:"space-y-4",children:[e("div",{className:"space-y-2",children:[n(_,{htmlFor:"sign-api-key",children:"API Key"}),n(w,{id:"sign-api-key",type:"password",placeholder:l("sign_api_key_placeholder",l("sign_api_key_input")),value:c,onChange:e=>d(e.target.value)})]}),e("div",{className:"space-y-2",children:[n(_,{children:l("sign_environment","Ambiente")}),e(x,{value:m,onValueChange:e=>k(e),children:[n(N,{children:n(b,{})}),e(y,{children:[n(D,{value:"sandbox",children:"Sandbox (Testes)"}),n(D,{value:"production",children:"Produção"})]})]})]}),e(p,{type:"submit",disabled:A,children:[A&&n(E,{className:"mr-2 h-4 w-4 animate-spin"}),t?l("sign_update_config",l("sign_update_config_btn")):l("sign_save_config",l("sign_save_config_btn"))]})]})})]})]})}const Y=[{id:"create",label:"Criar envelope no D4Sign (edge function d4sign / create_and_send)",status:"idle"},{id:"row",label:"Inserir linha em common.sign_documents (status=pending)",status:"idle"},{id:"webhook-reg",label:"Registrar webhook /documents/{uuid}/webhooks na D4Sign",status:"idle"},{id:"sign",label:"Aguardar assinatura no iframe embedded",status:"idle"},{id:"webhook-in",label:"Receber webhook (UPDATE em sign_documents detectado via polling 3s)",status:"idle"},{id:"download",label:"download_url salvo e disponível",status:"idle"}];function O(){return(new Date).toLocaleTimeString("pt-BR",{hour12:!1})}function H({step:a}){const i="done"===a.status?n(S,{className:"h-4 w-4 text-emerald-600 shrink-0"}):"running"===a.status?n(E,{className:"h-4 w-4 animate-spin text-primary shrink-0"}):"error"===a.status?n(T,{className:"h-4 w-4 text-destructive shrink-0"}):n($,{className:"h-4 w-4 text-muted-foreground shrink-0"});return e("div",{className:"flex items-start gap-2 text-sm",children:[n("div",{className:"pt-0.5",children:i}),e("div",{className:"flex-1",children:[e("div",{className:"flex items-center gap-2",children:[n("span",{className:"idle"===a.status?"text-muted-foreground":"",children:a.label}),a.at&&n("span",{className:"text-xs text-muted-foreground font-mono",children:a.at})]}),a.detail&&n("pre",{className:"mt-1 text-xs font-mono bg-muted/50 px-2 py-1 rounded whitespace-pre-wrap break-all",children:a.detail})]})]})}function X(){const{user:l,alias:u}=o(),{config:x,isLoading:N}=V(),b=import.meta.env?.VITE_SUPABASE_URL||"",y=b?`${b}/functions/v1/d4sign-webhook`:"",D=r(()=>{try{return new URL(b).host.split(".")[0]||""}catch{return""}},[b]),S=l?.userEmail||"",I=l?.userName||"",[j,L]=a(S),[$,U]=a(I),[G,F]=a(Y),[J,B]=a(null),[Q,W]=a("idle"),[z,K]=a([]),[X,ee]=a(null),[ne,ae]=a(!1),[ie,se]=a(!1),te=t(null),re=t(null);i(()=>{!j&&S&&L(S),!$&&I&&U(I)},[S,I,j,$]);const oe=s((e,n)=>{F(a=>a.map(a=>a.id===e?{...a,...n,at:n.at??a.at}:a))},[]),le=s((e,n)=>{K(a=>[{at:O(),type:e,payload:n},...a].slice(0,50))},[]),ce=s(async(e=!1)=>{if(!J?.envelope_id)return null;try{const n=await q.getD4SignDocumentRecord(J.envelope_id);return ee(n),e||le("snapshot.fetch",n),n}catch(n){return e||le("snapshot.error",n.message),null}},[J,le]),de=s(()=>{ce(!1)},[ce]);i(()=>{if(!J?.envelope_id)return;re.current=null,W("active");let e=null;const n=async()=>{const n=await ce(!0);if(!n)return;const a=re.current,i=n.status??null;null===a&&i?(le("poll.initial",n),oe("row",{status:"done",at:O(),detail:`status=${i}`})):a!==i&&(le("poll.change",n),oe("webhook-in",{status:"done",at:O(),detail:`status=${i}`}),"signed"===i&&(oe("sign",{status:"done",at:O()}),oe("download",{status:n.download_url?"done":"error",at:O(),detail:n.download_url||"download_url ausente no payload"})),"failed"!==i&&"cancelled"!==i||oe("webhook-in",{status:"error",at:O(),detail:`status=${i}`})),re.current=i,"signed"!==i&&"failed"!==i&&"cancelled"!==i||(e&&clearInterval(e),W("stopped"),te.current&&clearTimeout(te.current))};return n(),e=setInterval(()=>{n()},3e3),()=>{e&&clearInterval(e),W("stopped")}},[J,ce,le,oe]),i(()=>{if(J?.envelope_id)return te.current=setTimeout(()=>se(!0),3e5),()=>{te.current&&clearTimeout(te.current)}},[J]);const me=s(()=>{F(Y),B(null),K([]),ee(null),W("idle"),se(!1)},[]),ue=s(async()=>{if(u){me(),ae(!0),oe("create",{status:"running",at:O()});try{const e=await q.createEnvelopeWithSigner({alias:u,contentBase64:"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9MZW5ndGggNDQ+PnN0cmVhbQpCVAovRjEgMjQgVGYKMTAwIDcwMCBUZAooRDRTaWduIFdlYmhvb2sgVGVzdCkgVGoKRVQKZW5kc3RyZWFtCmVuZG9iagoyIDAgb2JqCjw8L1R5cGUvUGFnZS9QYXJlbnQgMSAwIFIvTWVkaWFCb3hbMCAwIDYxMiA3OTJdL0NvbnRlbnRzIDMgMCBSL1Jlc291cmNlczw8L0ZvbnQ8PC9GMTw8L1R5cGUvRm9udC9TdWJ0eXBlL1R5cGUxL0Jhc2VGb250L0hlbHZldGljYT4+Pj4+Pj4+CmVuZG9iagoxIDAgb2JqCjw8L1R5cGUvUGFnZXMvS2lkc1syIDAgUl0vQ291bnQgMT4+CmVuZG9iago0IDAgb2JqCjw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAxIDAgUj4+CmVuZG9iagp4cmVmCjAgNQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAyMzMgMDAwMDAgbiAKMDAwMDAwMDEwMSAwMDAwMCBuIAowMDAwMDAwMDE1IDAwMDAwIG4gCjAwMDAwMDAyODQgMDAwMDAgbiAKdHJhaWxlcgo8PC9TaXplIDUvUm9vdCA0IDAgUj4+CnN0YXJ0eHJlZgozMzQKJSVFT0Y=",filename:`d4sign-webhook-test-${Date.now()}.pdf`,signerEmail:j,signerName:$,provider:"d4sign"});oe("create",{status:"done",at:O(),detail:JSON.stringify(e,null,2)}),oe("webhook-reg",{status:"done",at:O(),detail:y||"(SUPABASE_URL não disponível)"}),oe("sign",{status:"running",at:O()}),B(e),le("envelope.created",e)}catch(e){oe("create",{status:"error",at:O(),detail:e.message}),le("envelope.error",e.message)}finally{ae(!1)}}},[u,j,$,le,me,oe,y]),ge=s(async()=>{if(J){await de();try{const e=await q.getSignedDocument({alias:u,envelopeId:J.envelope_id,documentId:J.document_id,provider:"d4sign"});le("d4sign.api.fetch",e)}catch(e){le("d4sign.api.error",e.message)}}},[u,J,le,de]),he="d4sign"===x?.provider;return e("div",{className:"space-y-4",children:[e(g,{children:[n(f,{className:"pb-3",children:n(v,{className:"text-sm",children:"Pré-flight"})}),e(h,{className:"space-y-2 text-sm",children:[e("div",{className:"flex items-center justify-between",children:[n("span",{children:"Alias logado"}),n(k,{variant:u?"default":"danger",children:u||"sem alias"})]}),e("div",{className:"flex items-center justify-between",children:[n("span",{children:"Provedor configurado"}),n(k,{variant:he?"default":"danger",children:N?"carregando…":x?.provider||"não configurado"})]}),e("div",{className:"flex items-center justify-between",children:[n("span",{children:"Ambiente"}),n(k,{variant:"outline",children:x?.environment||"—"})]}),e("div",{className:"flex items-center justify-between gap-2",children:[n("span",{children:"URL do webhook"}),n("code",{className:"text-xs font-mono text-muted-foreground truncate max-w-[60%]",children:y||"—"})]}),e("div",{className:"flex items-center justify-between",children:[n("span",{children:"Polling do snapshot"}),n(k,{variant:"active"===Q?"default":"outline",children:"active"===Q?"ativo (3s)":Q})]})]})]}),!he&&!N&&e(c,{variant:"danger",children:[n(T,{className:"h-4 w-4"}),n(d,{children:"Provedor não é D4Sign"}),e(m,{children:["Configure o provedor desta unidade como ",n("strong",{children:"d4sign"})," em /a/cs antes de rodar o teste."]})]}),e(g,{children:[n(f,{className:"pb-3",children:n(v,{className:"text-sm",children:"Disparo do envelope"})}),e(h,{className:"space-y-3",children:[e("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:[e("div",{className:"space-y-1",children:[n(_,{htmlFor:"d4-test-email",children:"E-mail do signatário"}),n(w,{id:"d4-test-email",type:"email",value:j,onChange:e=>L(e.target.value)})]}),e("div",{className:"space-y-1",children:[n(_,{htmlFor:"d4-test-name",children:"Nome do signatário"}),n(w,{id:"d4-test-name",value:$,onChange:e=>U(e.target.value)}),e("p",{className:"text-xs text-muted-foreground",children:["Use nome e sobrenome (ex.: ",n("em",{children:"Vinicius Silva"}),'). A D4Sign rejeita nomes incompletos com "Nome completo inválido".']})]})]}),e("div",{className:"flex flex-wrap gap-2",children:[e(p,{onClick:ue,disabled:ne||!he||!j||$.trim().split(/\s+/).length<2,children:[ne?n(E,{className:"h-4 w-4 mr-2 animate-spin"}):n(R,{className:"h-4 w-4 mr-2"}),"Gerar PDF e enviar para D4Sign"]}),n(p,{variant:"outline",onClick:me,disabled:ne,children:"Resetar teste"})]})]})]}),e(g,{children:[n(f,{className:"pb-3",children:n(v,{className:"text-sm",children:"Timeline"})}),e(h,{className:"space-y-3",children:[G.map(e=>n(H,{step:e},e.id)),ie&&e(c,{variant:"danger",children:[n(T,{className:"h-4 w-4"}),n(d,{children:"Timeout de 5 min"}),e(m,{className:"space-y-2",children:[n("p",{children:"Webhook ainda não chegou. Verifique manualmente o status e os logs."}),e(p,{size:"sm",variant:"outline",onClick:ge,children:[n(M,{className:"h-3.5 w-3.5 mr-2"}),"Verificar status manualmente"]})]})]})]})]}),J&&"d4sign"===x?.provider&&e(g,{children:[n(f,{className:"pb-3",children:n(v,{className:"text-sm",children:"Assinatura (iframe embedded)"})}),n(h,{children:n(Z,{documentKey:J.document_id,signerEmail:j,signerName:$,keySigner:J.signer_id,environment:J.environment||"sandbox",onSign:()=>oe("sign",{status:"done",at:O(),detail:"iframe postMessage=signed"}),onError:e=>oe("sign",{status:"error",at:O(),detail:e.message})})})]}),e("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e(g,{children:[e(f,{className:"pb-3 flex flex-row items-center justify-between",children:[n(v,{className:"text-sm",children:"Snapshot em common.sign_documents"}),e(p,{size:"sm",variant:"outline",onClick:de,disabled:!J,children:[n(M,{className:"h-3.5 w-3.5 mr-2"}),"Refetch"]})]}),e(h,{children:[n("pre",{className:"text-xs font-mono bg-muted/50 p-2 rounded max-h-72 overflow-auto",children:X?JSON.stringify(X,null,2):"— sem dados —"}),X?.download_url&&e(p,{size:"sm",className:"mt-2",onClick:()=>window.open(X.download_url,"_blank"),children:[n(C,{className:"h-3.5 w-3.5 mr-2"}),"Baixar PDF assinado"]})]})]}),e(g,{children:[e(f,{className:"pb-3 flex flex-row items-center justify-between",children:[n(v,{className:"text-sm",children:"Eventos do canal"}),D&&e("a",{href:`https://supabase.com/dashboard/project/${D}/functions/d4sign-webhook/logs`,target:"_blank",rel:"noreferrer",className:"text-xs text-primary hover:underline inline-flex items-center gap-1",children:["Logs do webhook ",n(P,{className:"h-3 w-3"})]})]}),n(h,{children:e("div",{className:"space-y-2 max-h-72 overflow-auto",children:[0===z.length&&n("p",{className:"text-xs text-muted-foreground",children:"— sem eventos —"}),z.map((a,i)=>e("div",{className:"text-xs",children:[e("div",{className:"flex items-center gap-2",children:[n("span",{className:"font-mono text-muted-foreground",children:a.at}),n(k,{variant:"outline",className:"text-[10px]",children:a.type})]}),n("pre",{className:"mt-1 font-mono bg-muted/50 p-2 rounded whitespace-pre-wrap break-all",children:"string"==typeof a.payload?a.payload:JSON.stringify(a.payload,null,2)}),n(A,{className:"mt-2"})]},i))]})})]})]})]})}export{X as D4SignWebhookTester,Z as D4SignWidget,z as DocumentSigner,K as SignConfigForm,W as SignWidget,B as loadClicksignScript,q as signService,V as useSignConfig};
|
|
1
|
+
import{jsxs as e,jsx as n}from"react/jsx-runtime";import{useState as a,useEffect as i,useCallback as s,useRef as t,useMemo as r}from"react";import{useAuth as o,getSupabaseClient as l,Alert as c,AlertTitle as d,AlertDescription as m,useModuleConfig as u,toast as g,Card as h,CardContent as p,Button as f,CardHeader as v,CardTitle as _,Label as w,Input as x,Select as N,SelectTrigger as b,SelectValue as y,SelectContent as D,SelectItem as k,Badge as A,Separator as S}from"forlogic-core";import{Loader2 as E,CheckCircle2 as C,Download as M,RefreshCw as I,Upload as T,CheckCircle as j,AlertCircle as L,AlertTriangle as R,Send as P,ExternalLink as $,Circle as U}from"lucide-react";import{useTranslation as G}from"react-i18next";import V from"i18next";function F(){const{alias:e}=o(),[n,t]=a(null),[r,c]=a(!0);i(()=>{if(!e)return void c(!1);let n=!1;return(async()=>{c(!0);try{const a=l(),{data:i,error:s}=await a.schema("common").from("sign_configs").select("*").eq("alias",e).is("deleted_at",null).maybeSingle();n||t(i)}catch(a){n||t(null)}finally{n||c(!1)}})(),()=>{n=!0}},[e]);return{config:n,isLoading:r,saveConfig:s(async(n,a)=>{if(!e)throw new Error("Alias not available");const i=l(),{data:s,error:r}=await i.schema("common").from("sign_configs").upsert({alias:e,api_key:n,environment:a,updated_at:(new Date).toISOString()},{onConflict:"alias"}).select().maybeSingle();if(r)throw r;return t(s),s},[e])}}async function q(e,n,a){const i=l(),{data:s,error:t}=await i.functions.invoke(e,{body:{action:n,data:a}});if(t){const n=t.context;if(n&&"function"==typeof n.json){const a=await n.json().catch(()=>null),i=a?.error||a?.message||t.message;throw new Error(i||`Erro na requisição: ${e}`)}throw new Error(t.message||`Erro na requisição: ${e}`)}return s}const J={createEnvelopeWithSigner:async e=>q("d4sign"===e.provider?"d4sign":"clicksign","d4sign"===e.provider?"create_and_send":"create_envelope_with_signer",{content_base64:e.contentBase64,filename:e.filename,signer_email:e.signerEmail,signer_name:e.signerName,target_schema:e.targetSchema,target_table:e.targetTable}),getSignedDocument:async e=>q("d4sign"===e.provider?"d4sign":"clicksign","get_signed_document",{envelope_id:e.envelopeId,document_id:e.documentId}),async getD4SignDocumentRecord(e,n="common",a="sign_documents"){const i=l(),{data:s,error:t}=await i.schema(n).from(a).select("status, download_url, signed_at").eq("envelope_id",e).maybeSingle();if(t)throw new Error(t.message);return s??null}};let B=null;function Q(){return window.Clicksign?Promise.resolve():B||(B=new Promise((e,n)=>{const a=document.createElement("script");a.src="https://cdn-public-library.clicksign.com/embedded/embedded.min-2.1.0.js",a.onload=()=>e(),a.onerror=()=>n(new Error("Falha ao carregar script do Clicksign")),document.head.appendChild(a)}),B)}const W="clicksign-container";function Z({signerId:s,environment:r="sandbox",onSign:o,onError:l,onClose:c}){const{t:d}=G(),m=t(null),[u,g]=a(!0),[h,p]=a(null);return i(()=>{let e=!1;return m.current&&(m.current.unmount(),m.current=null),p(null),g(!0),Q().then(()=>{if(e)return;const n=new window.Clicksign(s);n.endpoint="production"===r?"https://app.clicksign.com":"https://sandbox.clicksign.com",n.origin=window.origin,n.mount(W),n.on("loaded",function(){g(!1)}),n.on("signed",function(){o?.()}),n.on("resized",function(e){const n=e,a=document.getElementById(W);a&&n?.data?.height&&(a.style.height=n.data.height+"px")}),n.on("error",function(e){g(!1),l?.(e instanceof Error?e:new Error(d("sign_widget_error")))}),n.on("closed",function(){c?.()}),m.current=n}).catch(n=>{e||(p("Falha ao carregar o script de assinatura."),g(!1),l?.(n))}),()=>{e=!0,m.current&&(m.current.unmount(),m.current=null)}},[s,r]),e("div",{className:"relative h-full",children:[u&&n("div",{className:"absolute inset-0 flex items-center justify-center",children:e("div",{className:"flex items-center gap-2 text-muted-foreground",children:[n(E,{className:"h-5 w-5 animate-spin"}),n("span",{className:"text-sm",children:"Carregando documento..."})]})}),h&&n("div",{className:"absolute inset-0 flex items-center justify-center",children:n("p",{className:"text-sm text-destructive",children:h})}),n("div",{id:W,style:{height:"600px"}})]})}function z({documentKey:r,signerEmail:o,signerName:l,keySigner:u,environment:g,onSign:h,onError:p}){const f=t(null),[v,_]=a("loading"),[w,x]=a(null),N="production"===g?"https://secure.d4sign.com.br/embed/viewblob":"https://sandbox.d4sign.com.br/embed/viewblob",b=(()=>{const e=new URLSearchParams({email:o,display_name:l||"",disable_preview:"0"});return u&&e.set("key_signer",u),`${N}/${r}?${e.toString()}`})(),y=s(e=>"signed"===e.data?(_("ready"),void h?.()):"wrong-data"===e.data?(_("error"),x(V.t("sign_incorrect_data")),void p?.(new Error(V.t("sign_incorrect_data")))):void 0,[h,p]);i(()=>(window.addEventListener("message",y,!1),()=>{window.removeEventListener("message",y,!1)}),[y]);const D=s(()=>{"loading"===v&&_("ready")},[v]);return"error"===v?e(c,{variant:"danger",className:"my-4",children:[n(d,{children:V.t("sign_doc_load_error")}),n(m,{children:w||"Ocorreu um erro inesperado ao carregar o documento para assinatura. Tente novamente."})]}):e("div",{className:"relative h-full",children:["loading"===v&&n("div",{className:"absolute inset-0 flex items-center justify-center",children:e("div",{className:"flex items-center gap-2 text-muted-foreground",children:[n(E,{className:"h-5 w-5 animate-spin"}),n("span",{className:"text-sm",children:"Carregando documento..."})]})}),n("iframe",{ref:f,id:"d4sign-container",src:b,width:"100%",style:{height:"600px",border:0},allow:"geolocation",onLoad:D})]})}function K({file:r,onDocumentSigned:c,onError:d,showEventLog:m=!1}){const{user:v,alias:_}=o(),{signDocumentsSchema:w,signDocumentsTable:x}=u(),{config:N,isLoading:b}=F(),{t:y}=G(),[D,k]=a(null),[A,S]=a(!1),[j,L]=a(null),[R,P]=a("sandbox"),[$,U]=a("clicksign"),[q,B]=a(null),[Q,W]=a(null),[K,Y]=a(!1),[O,H]=a(0),[X,ee]=a(!1),[ne,ae]=a([]),ie=t(null),se=t(null),te=s(e=>{m&&ae(n=>[...n,`[${(new Date).toLocaleTimeString()}] ${e}`])},[m]),re=s(async e=>{if(k(e),L(null),B(null),W(null),te(`Arquivo selecionado: ${e.name}`),_&&v){S(!0);try{const n=N?.provider??"clicksign";U(n),te(`Provedor resolvido: ${n}`);const a=new FileReader,i=await new Promise((n,i)=>{a.onload=()=>{const e=a.result;n(e)},a.onerror=i,a.readAsDataURL(e)});te(`Criando envelope para assinatura via ${n}...`);const s=await J.createEnvelopeWithSigner({alias:_,contentBase64:i,filename:e.name,signerEmail:v.email||"",signerName:v.name||"",provider:n,targetSchema:w,targetTable:x});te(`Envelope criado: ${s.envelope_id}`),B({envelope_id:s.envelope_id,document_id:s.document_id,signer_email:s.signer_email,key_signer:s.signer_id}),P(s.environment),U(s.provider||n),"d4sign"===n?(te("Documento enviado para D4Sign. Abrindo widget de assinatura..."),await new Promise(e=>setTimeout(e,2e3)),L(s.document_id),g.success(y("sign_doc_sent","Documento enviado! Assine abaixo."))):s.signer_id?(te(`Signer ID obtido: ${s.signer_id}. Aguardando processamento (3s)...`),await new Promise(e=>setTimeout(e,3e3)),L(s.signer_id),g.success(y("sign_doc_sent","Documento enviado! Assine abaixo."))):(te(V.t("sign_signer_unavailable")),g.error(y("sign_access_error","Não foi possível obter o acesso para assinatura. Tente novamente.")),d?.(new Error(y("sign_signer_unavailable"))))}catch(n){const e=n instanceof Error?n:new Error(y("sign_process_error",y("sign_doc_process_error"))),a=e.message||"";a.includes("MONTHLY_LIMIT_REACHED")?(te(V.t("sign_monthly_limit")),g.error(y("sign_monthly_limit","Limite mensal de assinaturas atingido. Entre em contato com o administrador para ampliar seu plano."))):(te(`Erro: ${a}`),g.error(a)),d?.(e)}finally{S(!1)}}},[_,v,te,d,N,w,x,y]);i(()=>{r&&_&&v&&!b&&r!==se.current&&(se.current=r,re(r))},[r,_,v,b,re]);const oe=t(null),le=s(()=>{if(oe.current){try{l().removeChannel(oe.current)}catch{}oe.current=null}},[]);i(()=>()=>le(),[le]);const ce=s(e=>!!e&&("signed"===e.status&&e.download_url?(te(V.t("sign_doc_available")),W(e.download_url),Y(!1),ee(!1),le(),!0):("cancelled"===e.status||"failed"===e.status)&&(te(`Assinatura ${"cancelled"===e.status?"cancelada":"falhou"}.`),Y(!1),ee(!0),le(),!0)),[te,le]),de=s(async()=>{if(!q||!_)return;if(Y(!0),H(0),ee(!1),te("Buscando documento assinado..."),"d4sign"===$){try{const e=await J.getD4SignDocumentRecord(q.envelope_id,w,x);if(ce(e))return}catch(e){te(`Erro na verificação inicial: ${e instanceof Error?e.message:y("unknown_error")}`)}le();const n=l().channel(`sign:${q.envelope_id}`).on("postgres_changes",{event:"UPDATE",schema:w,table:x,filter:`envelope_id=eq.${q.envelope_id}`},e=>{te(`Webhook recebido: status=${e.new.status}`),ce(e.new)}).subscribe();oe.current=n,te("Aguardando confirmação do D4Sign via webhook...");return void setTimeout(()=>{oe.current!==n||Q||(te(V.t("sign_fetch_failed")),Y(!1),ee(!0))},3e5)}for(let n=1;n<=6;n++){H(n),te(`Tentativa ${n}/6...`);try{const e=await J.getSignedDocument({alias:_,envelopeId:q.envelope_id,documentId:q.document_id,provider:$});if(e.download_url)return te(V.t("sign_doc_available")),W(e.download_url),void Y(!1)}catch(e){te(`Erro na tentativa ${n}: ${e instanceof Error?e.message:y("unknown_error")}`)}n<6&&(te("Aguardando 10 segundos para próxima tentativa..."),await new Promise(e=>setTimeout(e,1e4)))}te(V.t("sign_fetch_failed")),Y(!1),ee(!0)},[q,_,te,$,y,ce,le,Q,w,x]),me=s(async()=>{te("Documento assinado com sucesso!"),g.success(y("sign_signed_success","Documento assinado com sucesso!")),L(null),q&&_&&(c?.({success:!0,provider:$,envelope_id:q.envelope_id,document_id:q.document_id,signer_id:j||"",environment:R}),await de())},[te,c,q,j,_,R,$,de]);if(!_)return n(h,{className:"border-amber-200 bg-amber-50",children:n(p,{className:"flex items-start gap-3 py-6",children:e("div",{children:[n("p",{className:"font-medium text-amber-800",children:y("sign_auth_required","Autenticação necessária")}),n("p",{className:"text-sm text-amber-700 mt-1",children:y("sign_login_required","Faça login para utilizar a assinatura digital.")})]})})});const ue="d4sign"===$?"D4Sign":"Clicksign",ge=()=>m&&ne.length>0?n("div",{className:"bg-muted p-3 rounded-md text-xs font-mono space-y-1 max-h-40 overflow-auto",children:ne.map((e,a)=>n("div",{children:e},a))}):null;return q&&!j&&(Q||K||X)?e("div",{className:"space-y-4",children:[n(h,{className:"border-green-200 bg-green-50",children:e(p,{className:"flex flex-col items-center gap-4 py-8",children:[n(C,{className:"h-12 w-12 text-green-600"}),e("div",{className:"text-center",children:[n("p",{className:"text-lg font-semibold text-green-800",children:y("sign_signed_success","Documento assinado com sucesso!")}),n("p",{className:"text-sm text-green-700 mt-1",children:D?.name})]}),K?e("div",{className:"flex flex-col items-center gap-2 text-sm text-muted-foreground",children:[e("div",{className:"flex items-center gap-2",children:[n(E,{className:"h-4 w-4 animate-spin"}),y("sign_preparing_doc","Preparando documento assinado...")," (",y("sign_attempt","tentativa")," ",O,"/6)"]}),n("p",{className:"text-xs text-muted-foreground",children:y("sign_waiting_provider",`Aguardando processamento pelo ${ue}...`)})]}):Q?n(f,{asChild:!0,variant:"default",className:"gap-2",children:e("a",{href:Q,target:"_blank",rel:"noopener noreferrer",children:[n(M,{className:"h-4 w-4"}),y("sign_download_signed","Baixar documento assinado")]})}):X?e("div",{className:"text-center space-y-3",children:[e("div",{className:"space-y-1",children:[n("p",{className:"text-sm text-muted-foreground",children:y("sign_fetch_failed","Não foi possível obter o documento assinado após 1 minuto.")}),n("p",{className:"text-xs text-muted-foreground",children:y("sign_email_fallback","O documento será enviado para o seu e-mail assim que estiver disponível.")})]}),e(f,{variant:"secondary",className:"gap-2",onClick:de,children:[n(I,{className:"h-4 w-4"}),y("sign_try_again","Tentar novamente")]})]}):null]})}),n(ge,{})]}):j?e("div",{className:"space-y-4",children:["d4sign"===$?n(z,{documentKey:j,signerEmail:q?.signer_email||v?.email||"",signerName:v?.name,keySigner:q?.key_signer,environment:R,onSign:me,onError:d}):n(Z,{signerId:j,environment:R,onSign:me,onError:d}),n(ge,{})]}):r&&(A||b)?n(h,{children:e(p,{className:"flex items-center justify-center gap-3 py-10",children:[n(E,{className:"h-6 w-6 animate-spin text-primary"}),n("p",{className:"font-medium",children:y("sign_sending_doc","Enviando documento para assinatura...")})]})}):e("div",{className:"space-y-4",children:[n("input",{ref:ie,type:"file",accept:"application/pdf",className:"hidden",onChange:e=>{const n=e.target.files?.[0];n&&"application/pdf"===n.type?re(n):g.error(y("sign_select_pdf","Selecione um arquivo PDF"))}}),n(h,A?{children:e(p,{className:"flex items-center justify-center gap-3 py-10",children:[n(E,{className:"h-6 w-6 animate-spin text-primary"}),n("p",{className:"font-medium",children:y("sign_sending_doc","Enviando documento para assinatura...")})]})}:{className:"border-dashed border-2 cursor-pointer hover:bg-muted/50 transition-colors",onClick:()=>ie.current?.click(),children:e(p,{className:"flex flex-col items-center justify-center py-10 gap-3",children:[n(T,{className:"h-8 w-8 text-muted-foreground"}),e("div",{className:"text-center",children:[n("p",{className:"font-medium",children:y("sign_select_pdf","Selecione um arquivo PDF")}),n("p",{className:"text-sm text-muted-foreground",children:y("sign_click_to_select","Clique para escolher o documento para assinatura")})]})]})}),n(ge,{})]})}function Y({onSaved:s}){const{config:t,isLoading:r,saveConfig:o}=F(),{t:l}=G(),[c,d]=a(""),[m,u]=a("sandbox"),[A,S]=a(!1);i(()=>{!r&&t&&(d(t.api_key),u(t.environment))},[t,r]);return r?n("div",{className:"flex items-center justify-center py-8",children:n(E,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):e("div",{className:"space-y-4",children:[e("div",t?{className:"flex items-center gap-2 text-sm text-emerald-600",children:[n(j,{className:"h-4 w-4"}),n("span",{children:l("sign_configured",l("sign_configured_unit"))})]}:{className:"flex items-center gap-2 text-sm text-amber-600",children:[n(L,{className:"h-4 w-4"}),n("span",{children:l("sign_not_configured",l("sign_not_configured_unit"))})]}),e(h,{children:[n(v,{children:n(_,{className:"text-base",children:l("sign_digital_config")})}),n(p,{children:e("form",{onSubmit:async e=>{if(e.preventDefault(),c.trim()){S(!0);try{await o(c.trim(),m),g.success(l("sign_config_saved",l("sign_config_saved_success"))),s?.()}catch(n){g.error(l("sign_config_save_error",l("sign_config_save_err")))}finally{S(!1)}}else g.error(l("sign_api_key_required",l("sign_api_key_info")))},className:"space-y-4",children:[e("div",{className:"space-y-2",children:[n(w,{htmlFor:"sign-api-key",children:"API Key"}),n(x,{id:"sign-api-key",type:"password",placeholder:l("sign_api_key_placeholder",l("sign_api_key_input")),value:c,onChange:e=>d(e.target.value)})]}),e("div",{className:"space-y-2",children:[n(w,{children:l("sign_environment","Ambiente")}),e(N,{value:m,onValueChange:e=>u(e),children:[n(b,{children:n(y,{})}),e(D,{children:[n(k,{value:"sandbox",children:"Sandbox (Testes)"}),n(k,{value:"production",children:"Produção"})]})]})]}),e(f,{type:"submit",disabled:A,children:[A&&n(E,{className:"mr-2 h-4 w-4 animate-spin"}),t?l("sign_update_config",l("sign_update_config_btn")):l("sign_save_config",l("sign_save_config_btn"))]})]})})]})]})}const O=[{id:"create",label:"Criar envelope no D4Sign (edge function d4sign / create_and_send)",status:"idle"},{id:"row",label:"Inserir linha em common.sign_documents (status=pending)",status:"idle"},{id:"webhook-reg",label:"Registrar webhook /documents/{uuid}/webhooks na D4Sign",status:"idle"},{id:"sign",label:"Aguardar assinatura no iframe embedded",status:"idle"},{id:"webhook-in",label:"Receber webhook (UPDATE em sign_documents detectado via polling 3s)",status:"idle"},{id:"download",label:"download_url salvo e disponível",status:"idle"}];function H(){return(new Date).toLocaleTimeString("pt-BR",{hour12:!1})}function X({step:a}){const i="done"===a.status?n(C,{className:"h-4 w-4 text-emerald-600 shrink-0"}):"running"===a.status?n(E,{className:"h-4 w-4 animate-spin text-primary shrink-0"}):"error"===a.status?n(R,{className:"h-4 w-4 text-destructive shrink-0"}):n(U,{className:"h-4 w-4 text-muted-foreground shrink-0"});return e("div",{className:"flex items-start gap-2 text-sm",children:[n("div",{className:"pt-0.5",children:i}),e("div",{className:"flex-1",children:[e("div",{className:"flex items-center gap-2",children:[n("span",{className:"idle"===a.status?"text-muted-foreground":"",children:a.label}),a.at&&n("span",{className:"text-xs text-muted-foreground font-mono",children:a.at})]}),a.detail&&n("pre",{className:"mt-1 text-xs font-mono bg-muted/50 px-2 py-1 rounded whitespace-pre-wrap break-all",children:a.detail})]})]})}function ee(){const{user:l,alias:g}=o(),{signDocumentsSchema:N,signDocumentsTable:b}=u(),{config:y,isLoading:D}=F(),k=import.meta.env?.VITE_SUPABASE_URL||"",C=k?`${k}/functions/v1/d4sign-webhook`:"",T=r(()=>{try{return new URL(k).host.split(".")[0]||""}catch{return""}},[k]),j=l?.userEmail||"",L=l?.userName||"",[U,G]=a(j),[V,q]=a(L),[B,Q]=a(O),[W,Z]=a(null),[K,Y]=a("idle"),[ee,ne]=a([]),[ae,ie]=a(null),[se,te]=a(!1),[re,oe]=a(!1),le=t(null),ce=t(null);i(()=>{!U&&j&&G(j),!V&&L&&q(L)},[j,L,U,V]);const de=s((e,n)=>{Q(a=>a.map(a=>a.id===e?{...a,...n,at:n.at??a.at}:a))},[]),me=s((e,n)=>{ne(a=>[{at:H(),type:e,payload:n},...a].slice(0,50))},[]),ue=s(async(e=!1)=>{if(!W?.envelope_id)return null;try{const n=await J.getD4SignDocumentRecord(W.envelope_id,N,b);return ie(n),e||me("snapshot.fetch",n),n}catch(n){return e||me("snapshot.error",n.message),null}},[W,me,N,b]),ge=s(()=>{ue(!1)},[ue]);i(()=>{if(!W?.envelope_id)return;ce.current=null,Y("active");let e=null;const n=async()=>{const n=await ue(!0);if(!n)return;const a=ce.current,i=n.status??null;null===a&&i?(me("poll.initial",n),de("row",{status:"done",at:H(),detail:`status=${i}`})):a!==i&&(me("poll.change",n),de("webhook-in",{status:"done",at:H(),detail:`status=${i}`}),"signed"===i&&(de("sign",{status:"done",at:H()}),de("download",{status:n.download_url?"done":"error",at:H(),detail:n.download_url||"download_url ausente no payload"})),"failed"!==i&&"cancelled"!==i||de("webhook-in",{status:"error",at:H(),detail:`status=${i}`})),ce.current=i,"signed"!==i&&"failed"!==i&&"cancelled"!==i||(e&&clearInterval(e),Y("stopped"),le.current&&clearTimeout(le.current))};return n(),e=setInterval(()=>{n()},3e3),()=>{e&&clearInterval(e),Y("stopped")}},[W,ue,me,de]),i(()=>{if(W?.envelope_id)return le.current=setTimeout(()=>oe(!0),3e5),()=>{le.current&&clearTimeout(le.current)}},[W]);const he=s(()=>{Q(O),Z(null),ne([]),ie(null),Y("idle"),oe(!1)},[]),pe=s(async()=>{if(g){he(),te(!0),de("create",{status:"running",at:H()});try{const e=await J.createEnvelopeWithSigner({alias:g,contentBase64:"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9MZW5ndGggNDQ+PnN0cmVhbQpCVAovRjEgMjQgVGYKMTAwIDcwMCBUZAooRDRTaWduIFdlYmhvb2sgVGVzdCkgVGoKRVQKZW5kc3RyZWFtCmVuZG9iagoyIDAgb2JqCjw8L1R5cGUvUGFnZS9QYXJlbnQgMSAwIFIvTWVkaWFCb3hbMCAwIDYxMiA3OTJdL0NvbnRlbnRzIDMgMCBSL1Jlc291cmNlczw8L0ZvbnQ8PC9GMTw8L1R5cGUvRm9udC9TdWJ0eXBlL1R5cGUxL0Jhc2VGb250L0hlbHZldGljYT4+Pj4+Pj4+CmVuZG9iagoxIDAgb2JqCjw8L1R5cGUvUGFnZXMvS2lkc1syIDAgUl0vQ291bnQgMT4+CmVuZG9iago0IDAgb2JqCjw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAxIDAgUj4+CmVuZG9iagp4cmVmCjAgNQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAyMzMgMDAwMDAgbiAKMDAwMDAwMDEwMSAwMDAwMCBuIAowMDAwMDAwMDE1IDAwMDAwIG4gCjAwMDAwMDAyODQgMDAwMDAgbiAKdHJhaWxlcgo8PC9TaXplIDUvUm9vdCA0IDAgUj4+CnN0YXJ0eHJlZgozMzQKJSVFT0Y=",filename:`d4sign-webhook-test-${Date.now()}.pdf`,signerEmail:U,signerName:V,provider:"d4sign",targetSchema:N,targetTable:b});de("create",{status:"done",at:H(),detail:JSON.stringify(e,null,2)}),de("webhook-reg",{status:"done",at:H(),detail:C||"(SUPABASE_URL não disponível)"}),de("sign",{status:"running",at:H()}),Z(e),me("envelope.created",e)}catch(e){de("create",{status:"error",at:H(),detail:e.message}),me("envelope.error",e.message)}finally{te(!1)}}},[g,U,V,me,he,de,C,N,b]),fe=s(async()=>{if(W){await ge();try{const e=await J.getSignedDocument({alias:g,envelopeId:W.envelope_id,documentId:W.document_id,provider:"d4sign"});me("d4sign.api.fetch",e)}catch(e){me("d4sign.api.error",e.message)}}},[g,W,me,ge]),ve="d4sign"===y?.provider;return e("div",{className:"space-y-4",children:[e(h,{children:[n(v,{className:"pb-3",children:n(_,{className:"text-sm",children:"Pré-flight"})}),e(p,{className:"space-y-2 text-sm",children:[e("div",{className:"flex items-center justify-between",children:[n("span",{children:"Alias logado"}),n(A,{variant:g?"default":"danger",children:g||"sem alias"})]}),e("div",{className:"flex items-center justify-between",children:[n("span",{children:"Provedor configurado"}),n(A,{variant:ve?"default":"danger",children:D?"carregando…":y?.provider||"não configurado"})]}),e("div",{className:"flex items-center justify-between",children:[n("span",{children:"Ambiente"}),n(A,{variant:"outline",children:y?.environment||"—"})]}),e("div",{className:"flex items-center justify-between gap-2",children:[n("span",{children:"URL do webhook"}),n("code",{className:"text-xs font-mono text-muted-foreground truncate max-w-[60%]",children:C||"—"})]}),e("div",{className:"flex items-center justify-between",children:[n("span",{children:"Polling do snapshot"}),n(A,{variant:"active"===K?"default":"outline",children:"active"===K?"ativo (3s)":K})]})]})]}),!ve&&!D&&e(c,{variant:"danger",children:[n(R,{className:"h-4 w-4"}),n(d,{children:"Provedor não é D4Sign"}),e(m,{children:["Configure o provedor desta unidade como ",n("strong",{children:"d4sign"})," em /a/cs antes de rodar o teste."]})]}),e(h,{children:[n(v,{className:"pb-3",children:n(_,{className:"text-sm",children:"Disparo do envelope"})}),e(p,{className:"space-y-3",children:[e("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:[e("div",{className:"space-y-1",children:[n(w,{htmlFor:"d4-test-email",children:"E-mail do signatário"}),n(x,{id:"d4-test-email",type:"email",value:U,onChange:e=>G(e.target.value)})]}),e("div",{className:"space-y-1",children:[n(w,{htmlFor:"d4-test-name",children:"Nome do signatário"}),n(x,{id:"d4-test-name",value:V,onChange:e=>q(e.target.value)}),e("p",{className:"text-xs text-muted-foreground",children:["Use nome e sobrenome (ex.: ",n("em",{children:"Vinicius Silva"}),'). A D4Sign rejeita nomes incompletos com "Nome completo inválido".']})]})]}),e("div",{className:"flex flex-wrap gap-2",children:[e(f,{onClick:pe,disabled:se||!ve||!U||V.trim().split(/\s+/).length<2,children:[se?n(E,{className:"h-4 w-4 mr-2 animate-spin"}):n(P,{className:"h-4 w-4 mr-2"}),"Gerar PDF e enviar para D4Sign"]}),n(f,{variant:"outline",onClick:he,disabled:se,children:"Resetar teste"})]})]})]}),e(h,{children:[n(v,{className:"pb-3",children:n(_,{className:"text-sm",children:"Timeline"})}),e(p,{className:"space-y-3",children:[B.map(e=>n(X,{step:e},e.id)),re&&e(c,{variant:"danger",children:[n(R,{className:"h-4 w-4"}),n(d,{children:"Timeout de 5 min"}),e(m,{className:"space-y-2",children:[n("p",{children:"Webhook ainda não chegou. Verifique manualmente o status e os logs."}),e(f,{size:"sm",variant:"outline",onClick:fe,children:[n(I,{className:"h-3.5 w-3.5 mr-2"}),"Verificar status manualmente"]})]})]})]})]}),W&&"d4sign"===y?.provider&&e(h,{children:[n(v,{className:"pb-3",children:n(_,{className:"text-sm",children:"Assinatura (iframe embedded)"})}),n(p,{children:n(z,{documentKey:W.document_id,signerEmail:U,signerName:V,keySigner:W.signer_id,environment:W.environment||"sandbox",onSign:()=>de("sign",{status:"done",at:H(),detail:"iframe postMessage=signed"}),onError:e=>de("sign",{status:"error",at:H(),detail:e.message})})})]}),e("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e(h,{children:[e(v,{className:"pb-3 flex flex-row items-center justify-between",children:[n(_,{className:"text-sm",children:"Snapshot em common.sign_documents"}),e(f,{size:"sm",variant:"outline",onClick:ge,disabled:!W,children:[n(I,{className:"h-3.5 w-3.5 mr-2"}),"Refetch"]})]}),e(p,{children:[n("pre",{className:"text-xs font-mono bg-muted/50 p-2 rounded max-h-72 overflow-auto",children:ae?JSON.stringify(ae,null,2):"— sem dados —"}),ae?.download_url&&e(f,{size:"sm",className:"mt-2",onClick:()=>window.open(ae.download_url,"_blank"),children:[n(M,{className:"h-3.5 w-3.5 mr-2"}),"Baixar PDF assinado"]})]})]}),e(h,{children:[e(v,{className:"pb-3 flex flex-row items-center justify-between",children:[n(_,{className:"text-sm",children:"Eventos do canal"}),T&&e("a",{href:`https://supabase.com/dashboard/project/${T}/functions/d4sign-webhook/logs`,target:"_blank",rel:"noreferrer",className:"text-xs text-primary hover:underline inline-flex items-center gap-1",children:["Logs do webhook ",n($,{className:"h-3 w-3"})]})]}),n(p,{children:e("div",{className:"space-y-2 max-h-72 overflow-auto",children:[0===ee.length&&n("p",{className:"text-xs text-muted-foreground",children:"— sem eventos —"}),ee.map((a,i)=>e("div",{className:"text-xs",children:[e("div",{className:"flex items-center gap-2",children:[n("span",{className:"font-mono text-muted-foreground",children:a.at}),n(A,{variant:"outline",className:"text-[10px]",children:a.type})]}),n("pre",{className:"mt-1 font-mono bg-muted/50 p-2 rounded whitespace-pre-wrap break-all",children:"string"==typeof a.payload?a.payload:JSON.stringify(a.payload,null,2)}),n(S,{className:"mt-2"})]},i))]})})]})]})]})}export{ee as D4SignWebhookTester,z as D4SignWidget,K as DocumentSigner,Y as SignConfigForm,Z as SignWidget,Q as loadClicksignScript,J as signService,F as useSignConfig};
|
package/dist/sign/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("react/jsx-runtime"),s=require("react"),n=require("forlogic-core"),a=require("lucide-react"),t=require("react-i18next"),i=require("i18next");function r(){const{alias:e}=n.useAuth(),[a,t]=s.useState(null),[i,r]=s.useState(!0);s.useEffect(()=>{if(!e)return void r(!1);let s=!1;return(async()=>{r(!0);try{const a=n.getSupabaseClient(),{data:i,error:r}=await a.schema("common").from("sign_configs").select("*").eq("alias",e).is("deleted_at",null).maybeSingle();s||t(i)}catch(a){s||t(null)}finally{s||r(!1)}})(),()=>{s=!0}},[e]);return{config:a,isLoading:i,saveConfig:s.useCallback(async(s,a)=>{if(!e)throw new Error("Alias not available");const i=n.getSupabaseClient(),{data:r,error:o}=await i.schema("common").from("sign_configs").upsert({alias:e,api_key:s,environment:a,updated_at:(new Date).toISOString()},{onConflict:"alias"}).select().maybeSingle();if(o)throw o;return t(r),r},[e])}}async function o(e,s,a){const t=n.getSupabaseClient(),{data:i,error:r}=await t.functions.invoke(e,{body:{action:s,data:a}});if(r){const s=r.context;if(s&&"function"==typeof s.json){const n=await s.json().catch(()=>null),a=n?.error||n?.message||r.message;throw new Error(a||`Erro na requisição: ${e}`)}throw new Error(r.message||`Erro na requisição: ${e}`)}return i}const l={createEnvelopeWithSigner:async e=>o("d4sign"===e.provider?"d4sign":"clicksign","d4sign"===e.provider?"create_and_send":"create_envelope_with_signer",{content_base64:e.contentBase64,filename:e.filename,signer_email:e.signerEmail,signer_name:e.signerName}),getSignedDocument:async e=>o("d4sign"===e.provider?"d4sign":"clicksign","get_signed_document",{envelope_id:e.envelopeId,document_id:e.documentId}),async getD4SignDocumentRecord(e){const s=n.getSupabaseClient(),{data:a,error:t}=await s.schema("common").from("sign_documents").select("status, download_url, signed_at").eq("envelope_id",e).maybeSingle();if(t)throw new Error(t.message);return a??null}};let c=null;function d(){return window.Clicksign?Promise.resolve():c||(c=new Promise((e,s)=>{const n=document.createElement("script");n.src="https://cdn-public-library.clicksign.com/embedded/embedded.min-2.1.0.js",n.onload=()=>e(),n.onerror=()=>s(new Error("Falha ao carregar script do Clicksign")),document.head.appendChild(n)}),c)}const u="clicksign-container";function m({signerId:n,environment:i="sandbox",onSign:r,onError:o,onClose:l}){const{t:c}=t.useTranslation(),m=s.useRef(null),[g,x]=s.useState(!0),[h,p]=s.useState(null);return s.useEffect(()=>{let e=!1;return m.current&&(m.current.unmount(),m.current=null),p(null),x(!0),d().then(()=>{if(e)return;const s=new window.Clicksign(n);s.endpoint="production"===i?"https://app.clicksign.com":"https://sandbox.clicksign.com",s.origin=window.origin,s.mount(u),s.on("loaded",function(){x(!1)}),s.on("signed",function(){r?.()}),s.on("resized",function(e){const s=e,n=document.getElementById(u);n&&s?.data?.height&&(n.style.height=s.data.height+"px")}),s.on("error",function(e){x(!1),o?.(e instanceof Error?e:new Error(c("sign_widget_error")))}),s.on("closed",function(){l?.()}),m.current=s}).catch(s=>{e||(p("Falha ao carregar o script de assinatura."),x(!1),o?.(s))}),()=>{e=!0,m.current&&(m.current.unmount(),m.current=null)}},[n,i]),e.jsxs("div",{className:"relative h-full",children:[g&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground",children:[e.jsx(a.Loader2,{className:"h-5 w-5 animate-spin"}),e.jsx("span",{className:"text-sm",children:"Carregando documento..."})]})}),h&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsx("p",{className:"text-sm text-destructive",children:h})}),e.jsx("div",{id:u,style:{height:"600px"}})]})}function g({documentKey:t,signerEmail:r,signerName:o,keySigner:l,environment:c,onSign:d,onError:u}){const m=s.useRef(null),[g,x]=s.useState("loading"),[h,p]=s.useState(null),f="production"===c?"https://secure.d4sign.com.br/embed/viewblob":"https://sandbox.d4sign.com.br/embed/viewblob",j=(()=>{const e=new URLSearchParams({email:r,display_name:o||"",disable_preview:"0"});return l&&e.set("key_signer",l),`${f}/${t}?${e.toString()}`})(),v=s.useCallback(e=>"signed"===e.data?(x("ready"),void d?.()):"wrong-data"===e.data?(x("error"),p(i.t("sign_incorrect_data")),void u?.(new Error(i.t("sign_incorrect_data")))):void 0,[d,u]);s.useEffect(()=>(window.addEventListener("message",v,!1),()=>{window.removeEventListener("message",v,!1)}),[v]);const _=s.useCallback(()=>{"loading"===g&&x("ready")},[g]);return"error"===g?e.jsxs(n.Alert,{variant:"danger",className:"my-4",children:[e.jsx(n.AlertTitle,{children:i.t("sign_doc_load_error")}),e.jsx(n.AlertDescription,{children:h||"Ocorreu um erro inesperado ao carregar o documento para assinatura. Tente novamente."})]}):e.jsxs("div",{className:"relative h-full",children:["loading"===g&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground",children:[e.jsx(a.Loader2,{className:"h-5 w-5 animate-spin"}),e.jsx("span",{className:"text-sm",children:"Carregando documento..."})]})}),e.jsx("iframe",{ref:m,id:"d4sign-container",src:j,width:"100%",style:{height:"600px",border:0},allow:"geolocation",onLoad:_})]})}const x=[{id:"create",label:"Criar envelope no D4Sign (edge function d4sign / create_and_send)",status:"idle"},{id:"row",label:"Inserir linha em common.sign_documents (status=pending)",status:"idle"},{id:"webhook-reg",label:"Registrar webhook /documents/{uuid}/webhooks na D4Sign",status:"idle"},{id:"sign",label:"Aguardar assinatura no iframe embedded",status:"idle"},{id:"webhook-in",label:"Receber webhook (UPDATE em sign_documents detectado via polling 3s)",status:"idle"},{id:"download",label:"download_url salvo e disponível",status:"idle"}];function h(){return(new Date).toLocaleTimeString("pt-BR",{hour12:!1})}function p({step:s}){const n="done"===s.status?e.jsx(a.CheckCircle2,{className:"h-4 w-4 text-emerald-600 shrink-0"}):"running"===s.status?e.jsx(a.Loader2,{className:"h-4 w-4 animate-spin text-primary shrink-0"}):"error"===s.status?e.jsx(a.AlertTriangle,{className:"h-4 w-4 text-destructive shrink-0"}):e.jsx(a.Circle,{className:"h-4 w-4 text-muted-foreground shrink-0"});return e.jsxs("div",{className:"flex items-start gap-2 text-sm",children:[e.jsx("div",{className:"pt-0.5",children:n}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"idle"===s.status?"text-muted-foreground":"",children:s.label}),s.at&&e.jsx("span",{className:"text-xs text-muted-foreground font-mono",children:s.at})]}),s.detail&&e.jsx("pre",{className:"mt-1 text-xs font-mono bg-muted/50 px-2 py-1 rounded whitespace-pre-wrap break-all",children:s.detail})]})]})}exports.D4SignWebhookTester=function(){const{user:t,alias:i}=n.useAuth(),{config:o,isLoading:c}=r(),d=s.useMemo(()=>{try{return new URL("").host.split(".")[0]||""}catch{return""}},[""]),u=t?.userEmail||"",m=t?.userName||"",[f,j]=s.useState(u),[v,_]=s.useState(m),[w,b]=s.useState(x),[N,C]=s.useState(null),[y,S]=s.useState("idle"),[k,D]=s.useState([]),[A,E]=s.useState(null),[T,L]=s.useState(!1),[M,I]=s.useState(!1),R=s.useRef(null),P=s.useRef(null);s.useEffect(()=>{!f&&u&&j(u),!v&&m&&_(m)},[u,m,f,v]);const B=s.useCallback((e,s)=>{b(n=>n.map(n=>n.id===e?{...n,...s,at:s.at??n.at}:n))},[]),$=s.useCallback((e,s)=>{D(n=>[{at:h(),type:e,payload:s},...n].slice(0,50))},[]),q=s.useCallback(async(e=!1)=>{if(!N?.envelope_id)return null;try{const s=await l.getD4SignDocumentRecord(N.envelope_id);return E(s),e||$("snapshot.fetch",s),s}catch(s){return e||$("snapshot.error",s.message),null}},[N,$]),U=s.useCallback(()=>{q(!1)},[q]);s.useEffect(()=>{if(!N?.envelope_id)return;P.current=null,S("active");let e=null;const s=async()=>{const s=await q(!0);if(!s)return;const n=P.current,a=s.status??null;null===n&&a?($("poll.initial",s),B("row",{status:"done",at:h(),detail:`status=${a}`})):n!==a&&($("poll.change",s),B("webhook-in",{status:"done",at:h(),detail:`status=${a}`}),"signed"===a&&(B("sign",{status:"done",at:h()}),B("download",{status:s.download_url?"done":"error",at:h(),detail:s.download_url||"download_url ausente no payload"})),"failed"!==a&&"cancelled"!==a||B("webhook-in",{status:"error",at:h(),detail:`status=${a}`})),P.current=a,"signed"!==a&&"failed"!==a&&"cancelled"!==a||(e&&clearInterval(e),S("stopped"),R.current&&clearTimeout(R.current))};return s(),e=setInterval(()=>{s()},3e3),()=>{e&&clearInterval(e),S("stopped")}},[N,q,$,B]),s.useEffect(()=>{if(N?.envelope_id)return R.current=setTimeout(()=>I(!0),3e5),()=>{R.current&&clearTimeout(R.current)}},[N]);const G=s.useCallback(()=>{b(x),C(null),D([]),E(null),S("idle"),I(!1)},[]),V=s.useCallback(async()=>{if(i){G(),L(!0),B("create",{status:"running",at:h()});try{const e=await l.createEnvelopeWithSigner({alias:i,contentBase64:"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9MZW5ndGggNDQ+PnN0cmVhbQpCVAovRjEgMjQgVGYKMTAwIDcwMCBUZAooRDRTaWduIFdlYmhvb2sgVGVzdCkgVGoKRVQKZW5kc3RyZWFtCmVuZG9iagoyIDAgb2JqCjw8L1R5cGUvUGFnZS9QYXJlbnQgMSAwIFIvTWVkaWFCb3hbMCAwIDYxMiA3OTJdL0NvbnRlbnRzIDMgMCBSL1Jlc291cmNlczw8L0ZvbnQ8PC9GMTw8L1R5cGUvRm9udC9TdWJ0eXBlL1R5cGUxL0Jhc2VGb250L0hlbHZldGljYT4+Pj4+Pj4+CmVuZG9iagoxIDAgb2JqCjw8L1R5cGUvUGFnZXMvS2lkc1syIDAgUl0vQ291bnQgMT4+CmVuZG9iago0IDAgb2JqCjw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAxIDAgUj4+CmVuZG9iagp4cmVmCjAgNQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAyMzMgMDAwMDAgbiAKMDAwMDAwMDEwMSAwMDAwMCBuIAowMDAwMDAwMDE1IDAwMDAwIG4gCjAwMDAwMDAyODQgMDAwMDAgbiAKdHJhaWxlcgo8PC9TaXplIDUvUm9vdCA0IDAgUj4+CnN0YXJ0eHJlZgozMzQKJSVFT0Y=",filename:`d4sign-webhook-test-${Date.now()}.pdf`,signerEmail:f,signerName:v,provider:"d4sign"});B("create",{status:"done",at:h(),detail:JSON.stringify(e,null,2)}),B("webhook-reg",{status:"done",at:h(),detail:"(SUPABASE_URL não disponível)"}),B("sign",{status:"running",at:h()}),C(e),$("envelope.created",e)}catch(e){B("create",{status:"error",at:h(),detail:e.message}),$("envelope.error",e.message)}finally{L(!1)}}},[i,f,v,$,G,B,""]),F=s.useCallback(async()=>{if(N){await U();try{const e=await l.getSignedDocument({alias:i,envelopeId:N.envelope_id,documentId:N.document_id,provider:"d4sign"});$("d4sign.api.fetch",e)}catch(e){$("d4sign.api.error",e.message)}}},[i,N,$,U]),W="d4sign"===o?.provider;return e.jsxs("div",{className:"space-y-4",children:[e.jsxs(n.Card,{children:[e.jsx(n.CardHeader,{className:"pb-3",children:e.jsx(n.CardTitle,{className:"text-sm",children:"Pré-flight"})}),e.jsxs(n.CardContent,{className:"space-y-2 text-sm",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{children:"Alias logado"}),e.jsx(n.Badge,{variant:i?"default":"danger",children:i||"sem alias"})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{children:"Provedor configurado"}),e.jsx(n.Badge,{variant:W?"default":"danger",children:c?"carregando…":o?.provider||"não configurado"})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{children:"Ambiente"}),e.jsx(n.Badge,{variant:"outline",children:o?.environment||"—"})]}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{children:"URL do webhook"}),e.jsx("code",{className:"text-xs font-mono text-muted-foreground truncate max-w-[60%]",children:"—"})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{children:"Polling do snapshot"}),e.jsx(n.Badge,{variant:"active"===y?"default":"outline",children:"active"===y?"ativo (3s)":y})]})]})]}),!W&&!c&&e.jsxs(n.Alert,{variant:"danger",children:[e.jsx(a.AlertTriangle,{className:"h-4 w-4"}),e.jsx(n.AlertTitle,{children:"Provedor não é D4Sign"}),e.jsxs(n.AlertDescription,{children:["Configure o provedor desta unidade como ",e.jsx("strong",{children:"d4sign"})," em /a/cs antes de rodar o teste."]})]}),e.jsxs(n.Card,{children:[e.jsx(n.CardHeader,{className:"pb-3",children:e.jsx(n.CardTitle,{className:"text-sm",children:"Disparo do envelope"})}),e.jsxs(n.CardContent,{className:"space-y-3",children:[e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(n.Label,{htmlFor:"d4-test-email",children:"E-mail do signatário"}),e.jsx(n.Input,{id:"d4-test-email",type:"email",value:f,onChange:e=>j(e.target.value)})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(n.Label,{htmlFor:"d4-test-name",children:"Nome do signatário"}),e.jsx(n.Input,{id:"d4-test-name",value:v,onChange:e=>_(e.target.value)}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Use nome e sobrenome (ex.: ",e.jsx("em",{children:"Vinicius Silva"}),'). A D4Sign rejeita nomes incompletos com "Nome completo inválido".']})]})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(n.Button,{onClick:V,disabled:T||!W||!f||v.trim().split(/\s+/).length<2,children:[T?e.jsx(a.Loader2,{className:"h-4 w-4 mr-2 animate-spin"}):e.jsx(a.Send,{className:"h-4 w-4 mr-2"}),"Gerar PDF e enviar para D4Sign"]}),e.jsx(n.Button,{variant:"outline",onClick:G,disabled:T,children:"Resetar teste"})]})]})]}),e.jsxs(n.Card,{children:[e.jsx(n.CardHeader,{className:"pb-3",children:e.jsx(n.CardTitle,{className:"text-sm",children:"Timeline"})}),e.jsxs(n.CardContent,{className:"space-y-3",children:[w.map(s=>e.jsx(p,{step:s},s.id)),M&&e.jsxs(n.Alert,{variant:"danger",children:[e.jsx(a.AlertTriangle,{className:"h-4 w-4"}),e.jsx(n.AlertTitle,{children:"Timeout de 5 min"}),e.jsxs(n.AlertDescription,{className:"space-y-2",children:[e.jsx("p",{children:"Webhook ainda não chegou. Verifique manualmente o status e os logs."}),e.jsxs(n.Button,{size:"sm",variant:"outline",onClick:F,children:[e.jsx(a.RefreshCw,{className:"h-3.5 w-3.5 mr-2"}),"Verificar status manualmente"]})]})]})]})]}),N&&"d4sign"===o?.provider&&e.jsxs(n.Card,{children:[e.jsx(n.CardHeader,{className:"pb-3",children:e.jsx(n.CardTitle,{className:"text-sm",children:"Assinatura (iframe embedded)"})}),e.jsx(n.CardContent,{children:e.jsx(g,{documentKey:N.document_id,signerEmail:f,signerName:v,keySigner:N.signer_id,environment:N.environment||"sandbox",onSign:()=>B("sign",{status:"done",at:h(),detail:"iframe postMessage=signed"}),onError:e=>B("sign",{status:"error",at:h(),detail:e.message})})})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs(n.Card,{children:[e.jsxs(n.CardHeader,{className:"pb-3 flex flex-row items-center justify-between",children:[e.jsx(n.CardTitle,{className:"text-sm",children:"Snapshot em common.sign_documents"}),e.jsxs(n.Button,{size:"sm",variant:"outline",onClick:U,disabled:!N,children:[e.jsx(a.RefreshCw,{className:"h-3.5 w-3.5 mr-2"}),"Refetch"]})]}),e.jsxs(n.CardContent,{children:[e.jsx("pre",{className:"text-xs font-mono bg-muted/50 p-2 rounded max-h-72 overflow-auto",children:A?JSON.stringify(A,null,2):"— sem dados —"}),A?.download_url&&e.jsxs(n.Button,{size:"sm",className:"mt-2",onClick:()=>window.open(A.download_url,"_blank"),children:[e.jsx(a.Download,{className:"h-3.5 w-3.5 mr-2"}),"Baixar PDF assinado"]})]})]}),e.jsxs(n.Card,{children:[e.jsxs(n.CardHeader,{className:"pb-3 flex flex-row items-center justify-between",children:[e.jsx(n.CardTitle,{className:"text-sm",children:"Eventos do canal"}),d&&e.jsxs("a",{href:`https://supabase.com/dashboard/project/${d}/functions/d4sign-webhook/logs`,target:"_blank",rel:"noreferrer",className:"text-xs text-primary hover:underline inline-flex items-center gap-1",children:["Logs do webhook ",e.jsx(a.ExternalLink,{className:"h-3 w-3"})]})]}),e.jsx(n.CardContent,{children:e.jsxs("div",{className:"space-y-2 max-h-72 overflow-auto",children:[0===k.length&&e.jsx("p",{className:"text-xs text-muted-foreground",children:"— sem eventos —"}),k.map((s,a)=>e.jsxs("div",{className:"text-xs",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-mono text-muted-foreground",children:s.at}),e.jsx(n.Badge,{variant:"outline",className:"text-[10px]",children:s.type})]}),e.jsx("pre",{className:"mt-1 font-mono bg-muted/50 p-2 rounded whitespace-pre-wrap break-all",children:"string"==typeof s.payload?s.payload:JSON.stringify(s.payload,null,2)}),e.jsx(n.Separator,{className:"mt-2"})]},a))]})})]})]})]})},exports.D4SignWidget=g,exports.DocumentSigner=function({file:o,onDocumentSigned:c,onError:d,showEventLog:u=!1}){const{user:x,alias:h}=n.useAuth(),{config:p,isLoading:f}=r(),{t:j}=t.useTranslation(),[v,_]=s.useState(null),[w,b]=s.useState(!1),[N,C]=s.useState(null),[y,S]=s.useState("sandbox"),[k,D]=s.useState("clicksign"),[A,E]=s.useState(null),[T,L]=s.useState(null),[M,I]=s.useState(!1),[R,P]=s.useState(0),[B,$]=s.useState(!1),[q,U]=s.useState([]),G=s.useRef(null),V=s.useRef(null),F=s.useCallback(e=>{u&&U(s=>[...s,`[${(new Date).toLocaleTimeString()}] ${e}`])},[u]),W=s.useCallback(async e=>{if(_(e),C(null),E(null),L(null),F(`Arquivo selecionado: ${e.name}`),h&&x){b(!0);try{const s=p?.provider??"clicksign";D(s),F(`Provedor resolvido: ${s}`);const a=new FileReader,t=await new Promise((s,n)=>{a.onload=()=>{const e=a.result;s(e)},a.onerror=n,a.readAsDataURL(e)});F(`Criando envelope para assinatura via ${s}...`);const r=await l.createEnvelopeWithSigner({alias:h,contentBase64:t,filename:e.name,signerEmail:x.email||"",signerName:x.name||"",provider:s});F(`Envelope criado: ${r.envelope_id}`),E({envelope_id:r.envelope_id,document_id:r.document_id,signer_email:r.signer_email,key_signer:r.signer_id}),S(r.environment),D(r.provider||s),"d4sign"===s?(F("Documento enviado para D4Sign. Abrindo widget de assinatura..."),await new Promise(e=>setTimeout(e,2e3)),C(r.document_id),n.toast.success(j("sign_doc_sent","Documento enviado! Assine abaixo."))):r.signer_id?(F(`Signer ID obtido: ${r.signer_id}. Aguardando processamento (3s)...`),await new Promise(e=>setTimeout(e,3e3)),C(r.signer_id),n.toast.success(j("sign_doc_sent","Documento enviado! Assine abaixo."))):(F(i.t("sign_signer_unavailable")),n.toast.error(j("sign_access_error","Não foi possível obter o acesso para assinatura. Tente novamente.")),d?.(new Error(j("sign_signer_unavailable"))))}catch(s){const e=s instanceof Error?s:new Error(j("sign_process_error",j("sign_doc_process_error"))),a=e.message||"";a.includes("MONTHLY_LIMIT_REACHED")?(F(i.t("sign_monthly_limit")),n.toast.error(j("sign_monthly_limit","Limite mensal de assinaturas atingido. Entre em contato com o administrador para ampliar seu plano."))):(F(`Erro: ${a}`),n.toast.error(a)),d?.(e)}finally{b(!1)}}},[h,x,F,d,p]);s.useEffect(()=>{o&&h&&x&&!f&&o!==V.current&&(V.current=o,W(o))},[o,h,x,f,W]);const J=s.useRef(null),Q=s.useCallback(()=>{if(J.current){try{n.getSupabaseClient().removeChannel(J.current)}catch{}J.current=null}},[]);s.useEffect(()=>()=>Q(),[Q]);const Z=s.useCallback(e=>!!e&&("signed"===e.status&&e.download_url?(F(i.t("sign_doc_available")),L(e.download_url),I(!1),$(!1),Q(),!0):("cancelled"===e.status||"failed"===e.status)&&(F(`Assinatura ${"cancelled"===e.status?"cancelada":"falhou"}.`),I(!1),$(!0),Q(),!0)),[F,Q]),z=s.useCallback(async()=>{if(!A||!h)return;if(I(!0),P(0),$(!1),F("Buscando documento assinado..."),"d4sign"===k){try{const e=await l.getD4SignDocumentRecord(A.envelope_id);if(Z(e))return}catch(e){F(`Erro na verificação inicial: ${e instanceof Error?e.message:j("unknown_error")}`)}Q();const s=n.getSupabaseClient().channel(`sign:${A.envelope_id}`).on("postgres_changes",{event:"UPDATE",schema:"common",table:"sign_documents",filter:`envelope_id=eq.${A.envelope_id}`},e=>{F(`Webhook recebido: status=${e.new.status}`),Z(e.new)}).subscribe();J.current=s,F("Aguardando confirmação do D4Sign via webhook...");return void setTimeout(()=>{J.current!==s||T||(F(i.t("sign_fetch_failed")),I(!1),$(!0))},3e5)}for(let s=1;s<=6;s++){P(s),F(`Tentativa ${s}/6...`);try{const e=await l.getSignedDocument({alias:h,envelopeId:A.envelope_id,documentId:A.document_id,provider:k});if(e.download_url)return F(i.t("sign_doc_available")),L(e.download_url),void I(!1)}catch(e){F(`Erro na tentativa ${s}: ${e instanceof Error?e.message:j("unknown_error")}`)}s<6&&(F("Aguardando 10 segundos para próxima tentativa..."),await new Promise(e=>setTimeout(e,1e4)))}F(i.t("sign_fetch_failed")),I(!1),$(!0)},[A,h,F,k,j,Z,Q,T]),H=s.useCallback(async()=>{F("Documento assinado com sucesso!"),n.toast.success(j("sign_signed_success","Documento assinado com sucesso!")),C(null),A&&h&&(c?.({success:!0,provider:k,envelope_id:A.envelope_id,document_id:A.document_id,signer_id:N||"",environment:y}),await z())},[F,c,A,N,h,y,k,z]);if(!h)return e.jsx(n.Card,{className:"border-amber-200 bg-amber-50",children:e.jsx(n.CardContent,{className:"flex items-start gap-3 py-6",children:e.jsxs("div",{children:[e.jsx("p",{className:"font-medium text-amber-800",children:j("sign_auth_required","Autenticação necessária")}),e.jsx("p",{className:"text-sm text-amber-700 mt-1",children:j("sign_login_required","Faça login para utilizar a assinatura digital.")})]})})});const K="d4sign"===k?"D4Sign":"Clicksign",Y=()=>u&&q.length>0?e.jsx("div",{className:"bg-muted p-3 rounded-md text-xs font-mono space-y-1 max-h-40 overflow-auto",children:q.map((s,n)=>e.jsx("div",{children:s},n))}):null;return A&&!N&&(T||M||B)?e.jsxs("div",{className:"space-y-4",children:[e.jsx(n.Card,{className:"border-green-200 bg-green-50",children:e.jsxs(n.CardContent,{className:"flex flex-col items-center gap-4 py-8",children:[e.jsx(a.CheckCircle2,{className:"h-12 w-12 text-green-600"}),e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"text-lg font-semibold text-green-800",children:j("sign_signed_success","Documento assinado com sucesso!")}),e.jsx("p",{className:"text-sm text-green-700 mt-1",children:v?.name})]}),M?e.jsxs("div",{className:"flex flex-col items-center gap-2 text-sm text-muted-foreground",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(a.Loader2,{className:"h-4 w-4 animate-spin"}),j("sign_preparing_doc","Preparando documento assinado...")," (",j("sign_attempt","tentativa")," ",R,"/6)"]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:j("sign_waiting_provider",`Aguardando processamento pelo ${K}...`)})]}):T?e.jsx(n.Button,{asChild:!0,variant:"default",className:"gap-2",children:e.jsxs("a",{href:T,target:"_blank",rel:"noopener noreferrer",children:[e.jsx(a.Download,{className:"h-4 w-4"}),j("sign_download_signed","Baixar documento assinado")]})}):B?e.jsxs("div",{className:"text-center space-y-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:j("sign_fetch_failed","Não foi possível obter o documento assinado após 1 minuto.")}),e.jsx("p",{className:"text-xs text-muted-foreground",children:j("sign_email_fallback","O documento será enviado para o seu e-mail assim que estiver disponível.")})]}),e.jsxs(n.Button,{variant:"secondary",className:"gap-2",onClick:z,children:[e.jsx(a.RefreshCw,{className:"h-4 w-4"}),j("sign_try_again","Tentar novamente")]})]}):null]})}),e.jsx(Y,{})]}):N?e.jsxs("div",{className:"space-y-4",children:["d4sign"===k?e.jsx(g,{documentKey:N,signerEmail:A?.signer_email||x?.email||"",signerName:x?.name,keySigner:A?.key_signer,environment:y,onSign:H,onError:d}):e.jsx(m,{signerId:N,environment:y,onSign:H,onError:d}),e.jsx(Y,{})]}):o&&(w||f)?e.jsx(n.Card,{children:e.jsxs(n.CardContent,{className:"flex items-center justify-center gap-3 py-10",children:[e.jsx(a.Loader2,{className:"h-6 w-6 animate-spin text-primary"}),e.jsx("p",{className:"font-medium",children:j("sign_sending_doc","Enviando documento para assinatura...")})]})}):e.jsxs("div",{className:"space-y-4",children:[e.jsx("input",{ref:G,type:"file",accept:"application/pdf",className:"hidden",onChange:e=>{const s=e.target.files?.[0];s&&"application/pdf"===s.type?W(s):n.toast.error(j("sign_select_pdf","Selecione um arquivo PDF"))}}),w?e.jsx(n.Card,{children:e.jsxs(n.CardContent,{className:"flex items-center justify-center gap-3 py-10",children:[e.jsx(a.Loader2,{className:"h-6 w-6 animate-spin text-primary"}),e.jsx("p",{className:"font-medium",children:j("sign_sending_doc","Enviando documento para assinatura...")})]})}):e.jsx(n.Card,{className:"border-dashed border-2 cursor-pointer hover:bg-muted/50 transition-colors",onClick:()=>G.current?.click(),children:e.jsxs(n.CardContent,{className:"flex flex-col items-center justify-center py-10 gap-3",children:[e.jsx(a.Upload,{className:"h-8 w-8 text-muted-foreground"}),e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"font-medium",children:j("sign_select_pdf","Selecione um arquivo PDF")}),e.jsx("p",{className:"text-sm text-muted-foreground",children:j("sign_click_to_select","Clique para escolher o documento para assinatura")})]})]})}),e.jsx(Y,{})]})},exports.SignConfigForm=function({onSaved:i}){const{config:o,isLoading:l,saveConfig:c}=r(),{t:d}=t.useTranslation(),[u,m]=s.useState(""),[g,x]=s.useState("sandbox"),[h,p]=s.useState(!1);return s.useEffect(()=>{!l&&o&&(m(o.api_key),x(o.environment))},[o,l]),l?e.jsx("div",{className:"flex items-center justify-center py-8",children:e.jsx(a.Loader2,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):e.jsxs("div",{className:"space-y-4",children:[o?e.jsxs("div",{className:"flex items-center gap-2 text-sm text-emerald-600",children:[e.jsx(a.CheckCircle,{className:"h-4 w-4"}),e.jsx("span",{children:d("sign_configured",d("sign_configured_unit"))})]}):e.jsxs("div",{className:"flex items-center gap-2 text-sm text-amber-600",children:[e.jsx(a.AlertCircle,{className:"h-4 w-4"}),e.jsx("span",{children:d("sign_not_configured",d("sign_not_configured_unit"))})]}),e.jsxs(n.Card,{children:[e.jsx(n.CardHeader,{children:e.jsx(n.CardTitle,{className:"text-base",children:d("sign_digital_config")})}),e.jsx(n.CardContent,{children:e.jsxs("form",{onSubmit:async e=>{if(e.preventDefault(),u.trim()){p(!0);try{await c(u.trim(),g),n.toast.success(d("sign_config_saved",d("sign_config_saved_success"))),i?.()}catch(s){n.toast.error(d("sign_config_save_error",d("sign_config_save_err")))}finally{p(!1)}}else n.toast.error(d("sign_api_key_required",d("sign_api_key_info")))},className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(n.Label,{htmlFor:"sign-api-key",children:"API Key"}),e.jsx(n.Input,{id:"sign-api-key",type:"password",placeholder:d("sign_api_key_placeholder",d("sign_api_key_input")),value:u,onChange:e=>m(e.target.value)})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(n.Label,{children:d("sign_environment","Ambiente")}),e.jsxs(n.Select,{value:g,onValueChange:e=>x(e),children:[e.jsx(n.SelectTrigger,{children:e.jsx(n.SelectValue,{})}),e.jsxs(n.SelectContent,{children:[e.jsx(n.SelectItem,{value:"sandbox",children:"Sandbox (Testes)"}),e.jsx(n.SelectItem,{value:"production",children:"Produção"})]})]})]}),e.jsxs(n.Button,{type:"submit",disabled:h,children:[h&&e.jsx(a.Loader2,{className:"mr-2 h-4 w-4 animate-spin"}),o?d("sign_update_config",d("sign_update_config_btn")):d("sign_save_config",d("sign_save_config_btn"))]})]})})]})]})},exports.SignWidget=m,exports.loadClicksignScript=d,exports.signService=l,exports.useSignConfig=r;
|
|
1
|
+
"use strict";var e=require("react/jsx-runtime"),s=require("react"),n=require("forlogic-core"),a=require("lucide-react"),t=require("react-i18next"),i=require("i18next");function r(){const{alias:e}=n.useAuth(),[a,t]=s.useState(null),[i,r]=s.useState(!0);s.useEffect(()=>{if(!e)return void r(!1);let s=!1;return(async()=>{r(!0);try{const a=n.getSupabaseClient(),{data:i,error:r}=await a.schema("common").from("sign_configs").select("*").eq("alias",e).is("deleted_at",null).maybeSingle();s||t(i)}catch(a){s||t(null)}finally{s||r(!1)}})(),()=>{s=!0}},[e]);return{config:a,isLoading:i,saveConfig:s.useCallback(async(s,a)=>{if(!e)throw new Error("Alias not available");const i=n.getSupabaseClient(),{data:r,error:o}=await i.schema("common").from("sign_configs").upsert({alias:e,api_key:s,environment:a,updated_at:(new Date).toISOString()},{onConflict:"alias"}).select().maybeSingle();if(o)throw o;return t(r),r},[e])}}async function o(e,s,a){const t=n.getSupabaseClient(),{data:i,error:r}=await t.functions.invoke(e,{body:{action:s,data:a}});if(r){const s=r.context;if(s&&"function"==typeof s.json){const n=await s.json().catch(()=>null),a=n?.error||n?.message||r.message;throw new Error(a||`Erro na requisição: ${e}`)}throw new Error(r.message||`Erro na requisição: ${e}`)}return i}const l={createEnvelopeWithSigner:async e=>o("d4sign"===e.provider?"d4sign":"clicksign","d4sign"===e.provider?"create_and_send":"create_envelope_with_signer",{content_base64:e.contentBase64,filename:e.filename,signer_email:e.signerEmail,signer_name:e.signerName,target_schema:e.targetSchema,target_table:e.targetTable}),getSignedDocument:async e=>o("d4sign"===e.provider?"d4sign":"clicksign","get_signed_document",{envelope_id:e.envelopeId,document_id:e.documentId}),async getD4SignDocumentRecord(e,s="common",a="sign_documents"){const t=n.getSupabaseClient(),{data:i,error:r}=await t.schema(s).from(a).select("status, download_url, signed_at").eq("envelope_id",e).maybeSingle();if(r)throw new Error(r.message);return i??null}};let c=null;function d(){return window.Clicksign?Promise.resolve():c||(c=new Promise((e,s)=>{const n=document.createElement("script");n.src="https://cdn-public-library.clicksign.com/embedded/embedded.min-2.1.0.js",n.onload=()=>e(),n.onerror=()=>s(new Error("Falha ao carregar script do Clicksign")),document.head.appendChild(n)}),c)}const u="clicksign-container";function m({signerId:n,environment:i="sandbox",onSign:r,onError:o,onClose:l}){const{t:c}=t.useTranslation(),m=s.useRef(null),[g,x]=s.useState(!0),[h,p]=s.useState(null);return s.useEffect(()=>{let e=!1;return m.current&&(m.current.unmount(),m.current=null),p(null),x(!0),d().then(()=>{if(e)return;const s=new window.Clicksign(n);s.endpoint="production"===i?"https://app.clicksign.com":"https://sandbox.clicksign.com",s.origin=window.origin,s.mount(u),s.on("loaded",function(){x(!1)}),s.on("signed",function(){r?.()}),s.on("resized",function(e){const s=e,n=document.getElementById(u);n&&s?.data?.height&&(n.style.height=s.data.height+"px")}),s.on("error",function(e){x(!1),o?.(e instanceof Error?e:new Error(c("sign_widget_error")))}),s.on("closed",function(){l?.()}),m.current=s}).catch(s=>{e||(p("Falha ao carregar o script de assinatura."),x(!1),o?.(s))}),()=>{e=!0,m.current&&(m.current.unmount(),m.current=null)}},[n,i]),e.jsxs("div",{className:"relative h-full",children:[g&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground",children:[e.jsx(a.Loader2,{className:"h-5 w-5 animate-spin"}),e.jsx("span",{className:"text-sm",children:"Carregando documento..."})]})}),h&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsx("p",{className:"text-sm text-destructive",children:h})}),e.jsx("div",{id:u,style:{height:"600px"}})]})}function g({documentKey:t,signerEmail:r,signerName:o,keySigner:l,environment:c,onSign:d,onError:u}){const m=s.useRef(null),[g,x]=s.useState("loading"),[h,p]=s.useState(null),f="production"===c?"https://secure.d4sign.com.br/embed/viewblob":"https://sandbox.d4sign.com.br/embed/viewblob",j=(()=>{const e=new URLSearchParams({email:r,display_name:o||"",disable_preview:"0"});return l&&e.set("key_signer",l),`${f}/${t}?${e.toString()}`})(),v=s.useCallback(e=>"signed"===e.data?(x("ready"),void d?.()):"wrong-data"===e.data?(x("error"),p(i.t("sign_incorrect_data")),void u?.(new Error(i.t("sign_incorrect_data")))):void 0,[d,u]);s.useEffect(()=>(window.addEventListener("message",v,!1),()=>{window.removeEventListener("message",v,!1)}),[v]);const _=s.useCallback(()=>{"loading"===g&&x("ready")},[g]);return"error"===g?e.jsxs(n.Alert,{variant:"danger",className:"my-4",children:[e.jsx(n.AlertTitle,{children:i.t("sign_doc_load_error")}),e.jsx(n.AlertDescription,{children:h||"Ocorreu um erro inesperado ao carregar o documento para assinatura. Tente novamente."})]}):e.jsxs("div",{className:"relative h-full",children:["loading"===g&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground",children:[e.jsx(a.Loader2,{className:"h-5 w-5 animate-spin"}),e.jsx("span",{className:"text-sm",children:"Carregando documento..."})]})}),e.jsx("iframe",{ref:m,id:"d4sign-container",src:j,width:"100%",style:{height:"600px",border:0},allow:"geolocation",onLoad:_})]})}const x=[{id:"create",label:"Criar envelope no D4Sign (edge function d4sign / create_and_send)",status:"idle"},{id:"row",label:"Inserir linha em common.sign_documents (status=pending)",status:"idle"},{id:"webhook-reg",label:"Registrar webhook /documents/{uuid}/webhooks na D4Sign",status:"idle"},{id:"sign",label:"Aguardar assinatura no iframe embedded",status:"idle"},{id:"webhook-in",label:"Receber webhook (UPDATE em sign_documents detectado via polling 3s)",status:"idle"},{id:"download",label:"download_url salvo e disponível",status:"idle"}];function h(){return(new Date).toLocaleTimeString("pt-BR",{hour12:!1})}function p({step:s}){const n="done"===s.status?e.jsx(a.CheckCircle2,{className:"h-4 w-4 text-emerald-600 shrink-0"}):"running"===s.status?e.jsx(a.Loader2,{className:"h-4 w-4 animate-spin text-primary shrink-0"}):"error"===s.status?e.jsx(a.AlertTriangle,{className:"h-4 w-4 text-destructive shrink-0"}):e.jsx(a.Circle,{className:"h-4 w-4 text-muted-foreground shrink-0"});return e.jsxs("div",{className:"flex items-start gap-2 text-sm",children:[e.jsx("div",{className:"pt-0.5",children:n}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"idle"===s.status?"text-muted-foreground":"",children:s.label}),s.at&&e.jsx("span",{className:"text-xs text-muted-foreground font-mono",children:s.at})]}),s.detail&&e.jsx("pre",{className:"mt-1 text-xs font-mono bg-muted/50 px-2 py-1 rounded whitespace-pre-wrap break-all",children:s.detail})]})]})}exports.D4SignWebhookTester=function(){const{user:t,alias:i}=n.useAuth(),{signDocumentsSchema:o,signDocumentsTable:c}=n.useModuleConfig(),{config:d,isLoading:u}=r(),m=s.useMemo(()=>{try{return new URL("").host.split(".")[0]||""}catch{return""}},[""]),f=t?.userEmail||"",j=t?.userName||"",[v,_]=s.useState(f),[w,b]=s.useState(j),[N,C]=s.useState(x),[y,S]=s.useState(null),[k,D]=s.useState("idle"),[A,E]=s.useState([]),[T,L]=s.useState(null),[M,I]=s.useState(!1),[R,P]=s.useState(!1),B=s.useRef(null),$=s.useRef(null);s.useEffect(()=>{!v&&f&&_(f),!w&&j&&b(j)},[f,j,v,w]);const q=s.useCallback((e,s)=>{C(n=>n.map(n=>n.id===e?{...n,...s,at:s.at??n.at}:n))},[]),U=s.useCallback((e,s)=>{E(n=>[{at:h(),type:e,payload:s},...n].slice(0,50))},[]),G=s.useCallback(async(e=!1)=>{if(!y?.envelope_id)return null;try{const s=await l.getD4SignDocumentRecord(y.envelope_id,o,c);return L(s),e||U("snapshot.fetch",s),s}catch(s){return e||U("snapshot.error",s.message),null}},[y,U,o,c]),V=s.useCallback(()=>{G(!1)},[G]);s.useEffect(()=>{if(!y?.envelope_id)return;$.current=null,D("active");let e=null;const s=async()=>{const s=await G(!0);if(!s)return;const n=$.current,a=s.status??null;null===n&&a?(U("poll.initial",s),q("row",{status:"done",at:h(),detail:`status=${a}`})):n!==a&&(U("poll.change",s),q("webhook-in",{status:"done",at:h(),detail:`status=${a}`}),"signed"===a&&(q("sign",{status:"done",at:h()}),q("download",{status:s.download_url?"done":"error",at:h(),detail:s.download_url||"download_url ausente no payload"})),"failed"!==a&&"cancelled"!==a||q("webhook-in",{status:"error",at:h(),detail:`status=${a}`})),$.current=a,"signed"!==a&&"failed"!==a&&"cancelled"!==a||(e&&clearInterval(e),D("stopped"),B.current&&clearTimeout(B.current))};return s(),e=setInterval(()=>{s()},3e3),()=>{e&&clearInterval(e),D("stopped")}},[y,G,U,q]),s.useEffect(()=>{if(y?.envelope_id)return B.current=setTimeout(()=>P(!0),3e5),()=>{B.current&&clearTimeout(B.current)}},[y]);const F=s.useCallback(()=>{C(x),S(null),E([]),L(null),D("idle"),P(!1)},[]),W=s.useCallback(async()=>{if(i){F(),I(!0),q("create",{status:"running",at:h()});try{const e=await l.createEnvelopeWithSigner({alias:i,contentBase64:"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9MZW5ndGggNDQ+PnN0cmVhbQpCVAovRjEgMjQgVGYKMTAwIDcwMCBUZAooRDRTaWduIFdlYmhvb2sgVGVzdCkgVGoKRVQKZW5kc3RyZWFtCmVuZG9iagoyIDAgb2JqCjw8L1R5cGUvUGFnZS9QYXJlbnQgMSAwIFIvTWVkaWFCb3hbMCAwIDYxMiA3OTJdL0NvbnRlbnRzIDMgMCBSL1Jlc291cmNlczw8L0ZvbnQ8PC9GMTw8L1R5cGUvRm9udC9TdWJ0eXBlL1R5cGUxL0Jhc2VGb250L0hlbHZldGljYT4+Pj4+Pj4+CmVuZG9iagoxIDAgb2JqCjw8L1R5cGUvUGFnZXMvS2lkc1syIDAgUl0vQ291bnQgMT4+CmVuZG9iago0IDAgb2JqCjw8L1R5cGUvQ2F0YWxvZy9QYWdlcyAxIDAgUj4+CmVuZG9iagp4cmVmCjAgNQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAyMzMgMDAwMDAgbiAKMDAwMDAwMDEwMSAwMDAwMCBuIAowMDAwMDAwMDE1IDAwMDAwIG4gCjAwMDAwMDAyODQgMDAwMDAgbiAKdHJhaWxlcgo8PC9TaXplIDUvUm9vdCA0IDAgUj4+CnN0YXJ0eHJlZgozMzQKJSVFT0Y=",filename:`d4sign-webhook-test-${Date.now()}.pdf`,signerEmail:v,signerName:w,provider:"d4sign",targetSchema:o,targetTable:c});q("create",{status:"done",at:h(),detail:JSON.stringify(e,null,2)}),q("webhook-reg",{status:"done",at:h(),detail:"(SUPABASE_URL não disponível)"}),q("sign",{status:"running",at:h()}),S(e),U("envelope.created",e)}catch(e){q("create",{status:"error",at:h(),detail:e.message}),U("envelope.error",e.message)}finally{I(!1)}}},[i,v,w,U,F,q,"",o,c]),J=s.useCallback(async()=>{if(y){await V();try{const e=await l.getSignedDocument({alias:i,envelopeId:y.envelope_id,documentId:y.document_id,provider:"d4sign"});U("d4sign.api.fetch",e)}catch(e){U("d4sign.api.error",e.message)}}},[i,y,U,V]),Q="d4sign"===d?.provider;return e.jsxs("div",{className:"space-y-4",children:[e.jsxs(n.Card,{children:[e.jsx(n.CardHeader,{className:"pb-3",children:e.jsx(n.CardTitle,{className:"text-sm",children:"Pré-flight"})}),e.jsxs(n.CardContent,{className:"space-y-2 text-sm",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{children:"Alias logado"}),e.jsx(n.Badge,{variant:i?"default":"danger",children:i||"sem alias"})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{children:"Provedor configurado"}),e.jsx(n.Badge,{variant:Q?"default":"danger",children:u?"carregando…":d?.provider||"não configurado"})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{children:"Ambiente"}),e.jsx(n.Badge,{variant:"outline",children:d?.environment||"—"})]}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{children:"URL do webhook"}),e.jsx("code",{className:"text-xs font-mono text-muted-foreground truncate max-w-[60%]",children:"—"})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{children:"Polling do snapshot"}),e.jsx(n.Badge,{variant:"active"===k?"default":"outline",children:"active"===k?"ativo (3s)":k})]})]})]}),!Q&&!u&&e.jsxs(n.Alert,{variant:"danger",children:[e.jsx(a.AlertTriangle,{className:"h-4 w-4"}),e.jsx(n.AlertTitle,{children:"Provedor não é D4Sign"}),e.jsxs(n.AlertDescription,{children:["Configure o provedor desta unidade como ",e.jsx("strong",{children:"d4sign"})," em /a/cs antes de rodar o teste."]})]}),e.jsxs(n.Card,{children:[e.jsx(n.CardHeader,{className:"pb-3",children:e.jsx(n.CardTitle,{className:"text-sm",children:"Disparo do envelope"})}),e.jsxs(n.CardContent,{className:"space-y-3",children:[e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(n.Label,{htmlFor:"d4-test-email",children:"E-mail do signatário"}),e.jsx(n.Input,{id:"d4-test-email",type:"email",value:v,onChange:e=>_(e.target.value)})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(n.Label,{htmlFor:"d4-test-name",children:"Nome do signatário"}),e.jsx(n.Input,{id:"d4-test-name",value:w,onChange:e=>b(e.target.value)}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Use nome e sobrenome (ex.: ",e.jsx("em",{children:"Vinicius Silva"}),'). A D4Sign rejeita nomes incompletos com "Nome completo inválido".']})]})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(n.Button,{onClick:W,disabled:M||!Q||!v||w.trim().split(/\s+/).length<2,children:[M?e.jsx(a.Loader2,{className:"h-4 w-4 mr-2 animate-spin"}):e.jsx(a.Send,{className:"h-4 w-4 mr-2"}),"Gerar PDF e enviar para D4Sign"]}),e.jsx(n.Button,{variant:"outline",onClick:F,disabled:M,children:"Resetar teste"})]})]})]}),e.jsxs(n.Card,{children:[e.jsx(n.CardHeader,{className:"pb-3",children:e.jsx(n.CardTitle,{className:"text-sm",children:"Timeline"})}),e.jsxs(n.CardContent,{className:"space-y-3",children:[N.map(s=>e.jsx(p,{step:s},s.id)),R&&e.jsxs(n.Alert,{variant:"danger",children:[e.jsx(a.AlertTriangle,{className:"h-4 w-4"}),e.jsx(n.AlertTitle,{children:"Timeout de 5 min"}),e.jsxs(n.AlertDescription,{className:"space-y-2",children:[e.jsx("p",{children:"Webhook ainda não chegou. Verifique manualmente o status e os logs."}),e.jsxs(n.Button,{size:"sm",variant:"outline",onClick:J,children:[e.jsx(a.RefreshCw,{className:"h-3.5 w-3.5 mr-2"}),"Verificar status manualmente"]})]})]})]})]}),y&&"d4sign"===d?.provider&&e.jsxs(n.Card,{children:[e.jsx(n.CardHeader,{className:"pb-3",children:e.jsx(n.CardTitle,{className:"text-sm",children:"Assinatura (iframe embedded)"})}),e.jsx(n.CardContent,{children:e.jsx(g,{documentKey:y.document_id,signerEmail:v,signerName:w,keySigner:y.signer_id,environment:y.environment||"sandbox",onSign:()=>q("sign",{status:"done",at:h(),detail:"iframe postMessage=signed"}),onError:e=>q("sign",{status:"error",at:h(),detail:e.message})})})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs(n.Card,{children:[e.jsxs(n.CardHeader,{className:"pb-3 flex flex-row items-center justify-between",children:[e.jsx(n.CardTitle,{className:"text-sm",children:"Snapshot em common.sign_documents"}),e.jsxs(n.Button,{size:"sm",variant:"outline",onClick:V,disabled:!y,children:[e.jsx(a.RefreshCw,{className:"h-3.5 w-3.5 mr-2"}),"Refetch"]})]}),e.jsxs(n.CardContent,{children:[e.jsx("pre",{className:"text-xs font-mono bg-muted/50 p-2 rounded max-h-72 overflow-auto",children:T?JSON.stringify(T,null,2):"— sem dados —"}),T?.download_url&&e.jsxs(n.Button,{size:"sm",className:"mt-2",onClick:()=>window.open(T.download_url,"_blank"),children:[e.jsx(a.Download,{className:"h-3.5 w-3.5 mr-2"}),"Baixar PDF assinado"]})]})]}),e.jsxs(n.Card,{children:[e.jsxs(n.CardHeader,{className:"pb-3 flex flex-row items-center justify-between",children:[e.jsx(n.CardTitle,{className:"text-sm",children:"Eventos do canal"}),m&&e.jsxs("a",{href:`https://supabase.com/dashboard/project/${m}/functions/d4sign-webhook/logs`,target:"_blank",rel:"noreferrer",className:"text-xs text-primary hover:underline inline-flex items-center gap-1",children:["Logs do webhook ",e.jsx(a.ExternalLink,{className:"h-3 w-3"})]})]}),e.jsx(n.CardContent,{children:e.jsxs("div",{className:"space-y-2 max-h-72 overflow-auto",children:[0===A.length&&e.jsx("p",{className:"text-xs text-muted-foreground",children:"— sem eventos —"}),A.map((s,a)=>e.jsxs("div",{className:"text-xs",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-mono text-muted-foreground",children:s.at}),e.jsx(n.Badge,{variant:"outline",className:"text-[10px]",children:s.type})]}),e.jsx("pre",{className:"mt-1 font-mono bg-muted/50 p-2 rounded whitespace-pre-wrap break-all",children:"string"==typeof s.payload?s.payload:JSON.stringify(s.payload,null,2)}),e.jsx(n.Separator,{className:"mt-2"})]},a))]})})]})]})]})},exports.D4SignWidget=g,exports.DocumentSigner=function({file:o,onDocumentSigned:c,onError:d,showEventLog:u=!1}){const{user:x,alias:h}=n.useAuth(),{signDocumentsSchema:p,signDocumentsTable:f}=n.useModuleConfig(),{config:j,isLoading:v}=r(),{t:_}=t.useTranslation(),[w,b]=s.useState(null),[N,C]=s.useState(!1),[y,S]=s.useState(null),[k,D]=s.useState("sandbox"),[A,E]=s.useState("clicksign"),[T,L]=s.useState(null),[M,I]=s.useState(null),[R,P]=s.useState(!1),[B,$]=s.useState(0),[q,U]=s.useState(!1),[G,V]=s.useState([]),F=s.useRef(null),W=s.useRef(null),J=s.useCallback(e=>{u&&V(s=>[...s,`[${(new Date).toLocaleTimeString()}] ${e}`])},[u]),Q=s.useCallback(async e=>{if(b(e),S(null),L(null),I(null),J(`Arquivo selecionado: ${e.name}`),h&&x){C(!0);try{const s=j?.provider??"clicksign";E(s),J(`Provedor resolvido: ${s}`);const a=new FileReader,t=await new Promise((s,n)=>{a.onload=()=>{const e=a.result;s(e)},a.onerror=n,a.readAsDataURL(e)});J(`Criando envelope para assinatura via ${s}...`);const r=await l.createEnvelopeWithSigner({alias:h,contentBase64:t,filename:e.name,signerEmail:x.email||"",signerName:x.name||"",provider:s,targetSchema:p,targetTable:f});J(`Envelope criado: ${r.envelope_id}`),L({envelope_id:r.envelope_id,document_id:r.document_id,signer_email:r.signer_email,key_signer:r.signer_id}),D(r.environment),E(r.provider||s),"d4sign"===s?(J("Documento enviado para D4Sign. Abrindo widget de assinatura..."),await new Promise(e=>setTimeout(e,2e3)),S(r.document_id),n.toast.success(_("sign_doc_sent","Documento enviado! Assine abaixo."))):r.signer_id?(J(`Signer ID obtido: ${r.signer_id}. Aguardando processamento (3s)...`),await new Promise(e=>setTimeout(e,3e3)),S(r.signer_id),n.toast.success(_("sign_doc_sent","Documento enviado! Assine abaixo."))):(J(i.t("sign_signer_unavailable")),n.toast.error(_("sign_access_error","Não foi possível obter o acesso para assinatura. Tente novamente.")),d?.(new Error(_("sign_signer_unavailable"))))}catch(s){const e=s instanceof Error?s:new Error(_("sign_process_error",_("sign_doc_process_error"))),a=e.message||"";a.includes("MONTHLY_LIMIT_REACHED")?(J(i.t("sign_monthly_limit")),n.toast.error(_("sign_monthly_limit","Limite mensal de assinaturas atingido. Entre em contato com o administrador para ampliar seu plano."))):(J(`Erro: ${a}`),n.toast.error(a)),d?.(e)}finally{C(!1)}}},[h,x,J,d,j,p,f,_]);s.useEffect(()=>{o&&h&&x&&!v&&o!==W.current&&(W.current=o,Q(o))},[o,h,x,v,Q]);const Z=s.useRef(null),z=s.useCallback(()=>{if(Z.current){try{n.getSupabaseClient().removeChannel(Z.current)}catch{}Z.current=null}},[]);s.useEffect(()=>()=>z(),[z]);const H=s.useCallback(e=>!!e&&("signed"===e.status&&e.download_url?(J(i.t("sign_doc_available")),I(e.download_url),P(!1),U(!1),z(),!0):("cancelled"===e.status||"failed"===e.status)&&(J(`Assinatura ${"cancelled"===e.status?"cancelada":"falhou"}.`),P(!1),U(!0),z(),!0)),[J,z]),K=s.useCallback(async()=>{if(!T||!h)return;if(P(!0),$(0),U(!1),J("Buscando documento assinado..."),"d4sign"===A){try{const e=await l.getD4SignDocumentRecord(T.envelope_id,p,f);if(H(e))return}catch(e){J(`Erro na verificação inicial: ${e instanceof Error?e.message:_("unknown_error")}`)}z();const s=n.getSupabaseClient().channel(`sign:${T.envelope_id}`).on("postgres_changes",{event:"UPDATE",schema:p,table:f,filter:`envelope_id=eq.${T.envelope_id}`},e=>{J(`Webhook recebido: status=${e.new.status}`),H(e.new)}).subscribe();Z.current=s,J("Aguardando confirmação do D4Sign via webhook...");return void setTimeout(()=>{Z.current!==s||M||(J(i.t("sign_fetch_failed")),P(!1),U(!0))},3e5)}for(let s=1;s<=6;s++){$(s),J(`Tentativa ${s}/6...`);try{const e=await l.getSignedDocument({alias:h,envelopeId:T.envelope_id,documentId:T.document_id,provider:A});if(e.download_url)return J(i.t("sign_doc_available")),I(e.download_url),void P(!1)}catch(e){J(`Erro na tentativa ${s}: ${e instanceof Error?e.message:_("unknown_error")}`)}s<6&&(J("Aguardando 10 segundos para próxima tentativa..."),await new Promise(e=>setTimeout(e,1e4)))}J(i.t("sign_fetch_failed")),P(!1),U(!0)},[T,h,J,A,_,H,z,M,p,f]),Y=s.useCallback(async()=>{J("Documento assinado com sucesso!"),n.toast.success(_("sign_signed_success","Documento assinado com sucesso!")),S(null),T&&h&&(c?.({success:!0,provider:A,envelope_id:T.envelope_id,document_id:T.document_id,signer_id:y||"",environment:k}),await K())},[J,c,T,y,h,k,A,K]);if(!h)return e.jsx(n.Card,{className:"border-amber-200 bg-amber-50",children:e.jsx(n.CardContent,{className:"flex items-start gap-3 py-6",children:e.jsxs("div",{children:[e.jsx("p",{className:"font-medium text-amber-800",children:_("sign_auth_required","Autenticação necessária")}),e.jsx("p",{className:"text-sm text-amber-700 mt-1",children:_("sign_login_required","Faça login para utilizar a assinatura digital.")})]})})});const O="d4sign"===A?"D4Sign":"Clicksign",X=()=>u&&G.length>0?e.jsx("div",{className:"bg-muted p-3 rounded-md text-xs font-mono space-y-1 max-h-40 overflow-auto",children:G.map((s,n)=>e.jsx("div",{children:s},n))}):null;return T&&!y&&(M||R||q)?e.jsxs("div",{className:"space-y-4",children:[e.jsx(n.Card,{className:"border-green-200 bg-green-50",children:e.jsxs(n.CardContent,{className:"flex flex-col items-center gap-4 py-8",children:[e.jsx(a.CheckCircle2,{className:"h-12 w-12 text-green-600"}),e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"text-lg font-semibold text-green-800",children:_("sign_signed_success","Documento assinado com sucesso!")}),e.jsx("p",{className:"text-sm text-green-700 mt-1",children:w?.name})]}),R?e.jsxs("div",{className:"flex flex-col items-center gap-2 text-sm text-muted-foreground",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(a.Loader2,{className:"h-4 w-4 animate-spin"}),_("sign_preparing_doc","Preparando documento assinado...")," (",_("sign_attempt","tentativa")," ",B,"/6)"]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:_("sign_waiting_provider",`Aguardando processamento pelo ${O}...`)})]}):M?e.jsx(n.Button,{asChild:!0,variant:"default",className:"gap-2",children:e.jsxs("a",{href:M,target:"_blank",rel:"noopener noreferrer",children:[e.jsx(a.Download,{className:"h-4 w-4"}),_("sign_download_signed","Baixar documento assinado")]})}):q?e.jsxs("div",{className:"text-center space-y-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:_("sign_fetch_failed","Não foi possível obter o documento assinado após 1 minuto.")}),e.jsx("p",{className:"text-xs text-muted-foreground",children:_("sign_email_fallback","O documento será enviado para o seu e-mail assim que estiver disponível.")})]}),e.jsxs(n.Button,{variant:"secondary",className:"gap-2",onClick:K,children:[e.jsx(a.RefreshCw,{className:"h-4 w-4"}),_("sign_try_again","Tentar novamente")]})]}):null]})}),e.jsx(X,{})]}):y?e.jsxs("div",{className:"space-y-4",children:["d4sign"===A?e.jsx(g,{documentKey:y,signerEmail:T?.signer_email||x?.email||"",signerName:x?.name,keySigner:T?.key_signer,environment:k,onSign:Y,onError:d}):e.jsx(m,{signerId:y,environment:k,onSign:Y,onError:d}),e.jsx(X,{})]}):o&&(N||v)?e.jsx(n.Card,{children:e.jsxs(n.CardContent,{className:"flex items-center justify-center gap-3 py-10",children:[e.jsx(a.Loader2,{className:"h-6 w-6 animate-spin text-primary"}),e.jsx("p",{className:"font-medium",children:_("sign_sending_doc","Enviando documento para assinatura...")})]})}):e.jsxs("div",{className:"space-y-4",children:[e.jsx("input",{ref:F,type:"file",accept:"application/pdf",className:"hidden",onChange:e=>{const s=e.target.files?.[0];s&&"application/pdf"===s.type?Q(s):n.toast.error(_("sign_select_pdf","Selecione um arquivo PDF"))}}),N?e.jsx(n.Card,{children:e.jsxs(n.CardContent,{className:"flex items-center justify-center gap-3 py-10",children:[e.jsx(a.Loader2,{className:"h-6 w-6 animate-spin text-primary"}),e.jsx("p",{className:"font-medium",children:_("sign_sending_doc","Enviando documento para assinatura...")})]})}):e.jsx(n.Card,{className:"border-dashed border-2 cursor-pointer hover:bg-muted/50 transition-colors",onClick:()=>F.current?.click(),children:e.jsxs(n.CardContent,{className:"flex flex-col items-center justify-center py-10 gap-3",children:[e.jsx(a.Upload,{className:"h-8 w-8 text-muted-foreground"}),e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"font-medium",children:_("sign_select_pdf","Selecione um arquivo PDF")}),e.jsx("p",{className:"text-sm text-muted-foreground",children:_("sign_click_to_select","Clique para escolher o documento para assinatura")})]})]})}),e.jsx(X,{})]})},exports.SignConfigForm=function({onSaved:i}){const{config:o,isLoading:l,saveConfig:c}=r(),{t:d}=t.useTranslation(),[u,m]=s.useState(""),[g,x]=s.useState("sandbox"),[h,p]=s.useState(!1);return s.useEffect(()=>{!l&&o&&(m(o.api_key),x(o.environment))},[o,l]),l?e.jsx("div",{className:"flex items-center justify-center py-8",children:e.jsx(a.Loader2,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):e.jsxs("div",{className:"space-y-4",children:[o?e.jsxs("div",{className:"flex items-center gap-2 text-sm text-emerald-600",children:[e.jsx(a.CheckCircle,{className:"h-4 w-4"}),e.jsx("span",{children:d("sign_configured",d("sign_configured_unit"))})]}):e.jsxs("div",{className:"flex items-center gap-2 text-sm text-amber-600",children:[e.jsx(a.AlertCircle,{className:"h-4 w-4"}),e.jsx("span",{children:d("sign_not_configured",d("sign_not_configured_unit"))})]}),e.jsxs(n.Card,{children:[e.jsx(n.CardHeader,{children:e.jsx(n.CardTitle,{className:"text-base",children:d("sign_digital_config")})}),e.jsx(n.CardContent,{children:e.jsxs("form",{onSubmit:async e=>{if(e.preventDefault(),u.trim()){p(!0);try{await c(u.trim(),g),n.toast.success(d("sign_config_saved",d("sign_config_saved_success"))),i?.()}catch(s){n.toast.error(d("sign_config_save_error",d("sign_config_save_err")))}finally{p(!1)}}else n.toast.error(d("sign_api_key_required",d("sign_api_key_info")))},className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(n.Label,{htmlFor:"sign-api-key",children:"API Key"}),e.jsx(n.Input,{id:"sign-api-key",type:"password",placeholder:d("sign_api_key_placeholder",d("sign_api_key_input")),value:u,onChange:e=>m(e.target.value)})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(n.Label,{children:d("sign_environment","Ambiente")}),e.jsxs(n.Select,{value:g,onValueChange:e=>x(e),children:[e.jsx(n.SelectTrigger,{children:e.jsx(n.SelectValue,{})}),e.jsxs(n.SelectContent,{children:[e.jsx(n.SelectItem,{value:"sandbox",children:"Sandbox (Testes)"}),e.jsx(n.SelectItem,{value:"production",children:"Produção"})]})]})]}),e.jsxs(n.Button,{type:"submit",disabled:h,children:[h&&e.jsx(a.Loader2,{className:"mr-2 h-4 w-4 animate-spin"}),o?d("sign_update_config",d("sign_update_config_btn")):d("sign_save_config",d("sign_save_config_btn"))]})]})})]})]})},exports.SignWidget=m,exports.loadClicksignScript=d,exports.signService=l,exports.useSignConfig=r;
|
|
@@ -7,6 +7,10 @@ export declare const signService: {
|
|
|
7
7
|
signerEmail: string;
|
|
8
8
|
signerName: string;
|
|
9
9
|
provider?: SignProvider;
|
|
10
|
+
/** Schema onde gravar a linha de tracking (default `'common'`). */
|
|
11
|
+
targetSchema?: string;
|
|
12
|
+
/** Tabela de tracking (default `'sign_documents'`). */
|
|
13
|
+
targetTable?: string;
|
|
10
14
|
}): Promise<SignEnvelopeResult>;
|
|
11
15
|
getSignedDocument(params: {
|
|
12
16
|
alias: string;
|
|
@@ -17,8 +21,12 @@ export declare const signService: {
|
|
|
17
21
|
/**
|
|
18
22
|
* D4Sign-only: reads the tracking row written by the d4sign-webhook edge function.
|
|
19
23
|
* Used both for one-shot fallback checks and as the source for the realtime subscription.
|
|
24
|
+
*
|
|
25
|
+
* @param schema Default `'common'`. Pass `'educacao'`, `'treinamentos'`, etc. when
|
|
26
|
+
* o projeto consumidor mantém a tabela no próprio schema.
|
|
27
|
+
* @param table Default `'sign_documents'`.
|
|
20
28
|
*/
|
|
21
|
-
getD4SignDocumentRecord(envelopeId: string): Promise<{
|
|
29
|
+
getD4SignDocumentRecord(envelopeId: string, schema?: string, table?: string): Promise<{
|
|
22
30
|
status: "pending" | "signed" | "cancelled" | "failed";
|
|
23
31
|
download_url: string | null;
|
|
24
32
|
signed_at: string | null;
|
|
@@ -36,6 +36,111 @@
|
|
|
36
36
|
| clarityProjectId | string | Não | Project ID do Microsoft Clarity. Sem ele, integração desativada. |
|
|
37
37
|
| clarityMode | 'auto' \| 'disabled' | Não | Opt-out do tracking Clarity. Default `'auto'`. |
|
|
38
38
|
| backend | 'supabase' \| 'dotnet' | Não | Backend ativo. Default `'supabase'`. Ver seção abaixo. |
|
|
39
|
+
| signDocumentsSchema | string | Não | Schema onde a tabela de tracking do D4Sign vive neste projeto. Default `'common'`. Ver seção abaixo. |
|
|
40
|
+
| signDocumentsTable | string | Não | Nome da tabela de tracking. Default `'sign_documents'`. |
|
|
41
|
+
|
|
42
|
+
## Tabela `sign_documents` por schema (D4Sign)
|
|
43
|
+
|
|
44
|
+
Por padrão, o webhook D4Sign grava o resultado em `common.sign_documents`. Projetos que mantêm a tabela no próprio schema (ex.: Educação) podem redirecionar via:
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
<CoreProviders
|
|
48
|
+
moduleAlias="educacao"
|
|
49
|
+
signDocumentsSchema="educacao"
|
|
50
|
+
// signDocumentsTable opcional — default 'sign_documents'
|
|
51
|
+
>
|
|
52
|
+
...
|
|
53
|
+
</CoreProviders>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
O que acontece:
|
|
57
|
+
|
|
58
|
+
1. `DocumentSigner` envia `target_schema` e `target_table` para a edge function `d4sign` no `create_and_send`.
|
|
59
|
+
2. A edge function `d4sign` insere a linha `pending` no schema/tabela alvo e registra o webhook do D4Sign com a URL `/functions/v1/d4sign-webhook?schema={schema}&table={table}`.
|
|
60
|
+
3. A edge function `d4sign-webhook` lê os query params, valida contra uma **allowlist** de schemas (`common`, `educacao`, `treinamentos`, `inovacao`, `public`) e faz o `UPDATE` no schema correto.
|
|
61
|
+
4. O front se inscreve no Realtime no mesmo schema/tabela.
|
|
62
|
+
|
|
63
|
+
**Requisitos no projeto consumidor:**
|
|
64
|
+
|
|
65
|
+
Cada projeto que redirecionar o destino precisa criar a tabela no seu próprio schema com **exatamente** o contrato abaixo — os nomes e tipos das colunas são consumidos pelas edge functions `d4sign` e `d4sign-webhook` e pelo `DocumentSigner`. Divergir quebra o fluxo.
|
|
66
|
+
|
|
67
|
+
### Contrato de campos
|
|
68
|
+
|
|
69
|
+
| Campo | Tipo | Obrigatório | Default | Preenchido por |
|
|
70
|
+
|---|---|---|---|---|
|
|
71
|
+
| `document_id` | `text` PK | sim | — | front (`DocumentSigner`, `crypto.randomUUID()`) |
|
|
72
|
+
| `alias` | `text` | sim | — | front |
|
|
73
|
+
| `provider` | `text` | sim | `'d4sign'` | front |
|
|
74
|
+
| `envelope_id` | `text` | sim | — | edge `d4sign` (UUID retornado pelo D4Sign) |
|
|
75
|
+
| `signer_email` | `text` | sim | — | front |
|
|
76
|
+
| `signer_name` | `text` | não | — | front |
|
|
77
|
+
| `filename` | `text` | não | — | front |
|
|
78
|
+
| `status` | `text` | sim | `'pending'` | webhook (`pending` → `signed` / `cancelled` / `failed`) |
|
|
79
|
+
| `signed_at` | `timestamptz` | não | — | webhook |
|
|
80
|
+
| `download_url` | `text` | não | — | webhook |
|
|
81
|
+
| `download_url_expires_at` | `timestamptz` | não | — | webhook (~50 min) |
|
|
82
|
+
| `raw_webhook_payload` | `jsonb` | não | — | webhook |
|
|
83
|
+
| `created_at` | `timestamptz` | sim | `now()` | DB |
|
|
84
|
+
| `updated_at` | `timestamptz` | sim | `now()` | trigger |
|
|
85
|
+
|
|
86
|
+
> **PK em `document_id`** (não `id` serial) — é a chave que o front usa para correlacionar o envelope com a row.
|
|
87
|
+
|
|
88
|
+
### Script SQL (substituir `{schema}`)
|
|
89
|
+
|
|
90
|
+
```sql
|
|
91
|
+
CREATE TABLE {schema}.sign_documents (
|
|
92
|
+
document_id text PRIMARY KEY,
|
|
93
|
+
alias text NOT NULL,
|
|
94
|
+
provider text NOT NULL DEFAULT 'd4sign',
|
|
95
|
+
envelope_id text NOT NULL,
|
|
96
|
+
signer_email text NOT NULL,
|
|
97
|
+
signer_name text,
|
|
98
|
+
filename text,
|
|
99
|
+
status text NOT NULL DEFAULT 'pending',
|
|
100
|
+
download_url text,
|
|
101
|
+
download_url_expires_at timestamptz,
|
|
102
|
+
raw_webhook_payload jsonb,
|
|
103
|
+
signed_at timestamptz,
|
|
104
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
105
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
CREATE INDEX sign_documents_alias_status_idx ON {schema}.sign_documents (alias, status);
|
|
109
|
+
CREATE INDEX sign_documents_envelope_idx ON {schema}.sign_documents (envelope_id);
|
|
110
|
+
|
|
111
|
+
GRANT SELECT ON {schema}.sign_documents TO authenticated;
|
|
112
|
+
GRANT ALL ON {schema}.sign_documents TO service_role;
|
|
113
|
+
|
|
114
|
+
ALTER TABLE {schema}.sign_documents ENABLE ROW LEVEL SECURITY;
|
|
115
|
+
|
|
116
|
+
CREATE POLICY "sign_documents_select_own_tenant"
|
|
117
|
+
ON {schema}.sign_documents
|
|
118
|
+
FOR SELECT
|
|
119
|
+
TO authenticated
|
|
120
|
+
USING (alias = ((SELECT auth.jwt()) ->> 'alias'));
|
|
121
|
+
|
|
122
|
+
CREATE OR REPLACE FUNCTION {schema}.sign_documents_set_updated_at()
|
|
123
|
+
RETURNS TRIGGER LANGUAGE plpgsql SET search_path = {schema}, public AS $$
|
|
124
|
+
BEGIN NEW.updated_at = now(); RETURN NEW; END;
|
|
125
|
+
$$;
|
|
126
|
+
|
|
127
|
+
CREATE TRIGGER sign_documents_updated_at
|
|
128
|
+
BEFORE UPDATE ON {schema}.sign_documents
|
|
129
|
+
FOR EACH ROW EXECUTE FUNCTION {schema}.sign_documents_set_updated_at();
|
|
130
|
+
|
|
131
|
+
-- Realtime — obrigatório, senão o DocumentSigner nunca recebe o evento de assinatura
|
|
132
|
+
ALTER TABLE {schema}.sign_documents REPLICA IDENTITY FULL;
|
|
133
|
+
ALTER PUBLICATION supabase_realtime ADD TABLE {schema}.sign_documents;
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Notas importantes
|
|
137
|
+
|
|
138
|
+
- **`sign_configs` continua em `common`** — o webhook lê de lá independentemente do schema alvo. Cada projeto que usa assinatura precisa ter `common.sign_configs` populado (via `/a/cs` no Admin).
|
|
139
|
+
- **`REPLICA IDENTITY FULL` + entrada na publication `supabase_realtime`** são obrigatórios. Sem isso, o `DocumentSigner` fica em loading eterno após assinar.
|
|
140
|
+
- **Schemas novos** precisam ser adicionados à constante `ALLOWED_SCHEMAS` em `supabase/functions/d4sign/index.ts` **e** `supabase/functions/d4sign-webhook/index.ts`, senão o webhook silenciosamente cai para `common` (proteção anti-SSRF).
|
|
141
|
+
|
|
142
|
+
**Retrocompatibilidade:** sem essas props, tudo continua apontando para `common.sign_documents` — Admin segue funcionando inalterado.
|
|
143
|
+
|
|
39
144
|
|
|
40
145
|
## Associações em outra base URL
|
|
41
146
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Module Access Guard
|
|
2
|
+
|
|
3
|
+
O `ModuleAccessGuard` envolve a aplicação e bloqueia o acesso de usuários sem
|
|
4
|
+
permissão no módulo (`moduleAlias`). É injetado automaticamente pelo
|
|
5
|
+
`CoreProviders` quando você passa `moduleAccessGuardProps` ou usa um dos shortcuts
|
|
6
|
+
abaixo.
|
|
7
|
+
|
|
8
|
+
## Props relacionadas
|
|
9
|
+
|
|
10
|
+
| Prop | Tipo | Default | Descrição |
|
|
11
|
+
|-------------------------|----------------------------|---------------|-----------|
|
|
12
|
+
| `bypassPaths` | `string[]` | `undefined` | Rotas que ignoram o guard. Suporta glob simples no final (`/public/*`). |
|
|
13
|
+
| `noAccessRedirectPath` | `string` | `undefined` | Path para onde usuários **autenticados e sem acesso** são redirecionados. |
|
|
14
|
+
| `noAccessRedirectMode` | `'always' \| 'never'` | `'always'` | Quando há `noAccessRedirectPath`, controla se o redirect dispara. |
|
|
15
|
+
| `accessDeniedRoutes` | `Record<string, ReactNode>`| `undefined` | Conteúdo customizado por rota dentro da tela de bloqueio. |
|
|
16
|
+
|
|
17
|
+
> O `noAccessRedirectPath` aceita path com ou sem o `:alias`. Se começar com `/`
|
|
18
|
+
> e a URL atual tiver um alias na primeira posição (`/inovacao/...`), o alias é
|
|
19
|
+
> prefixado automaticamente — você passa `/fe`, vira `/inovacao/fe`.
|
|
20
|
+
|
|
21
|
+
## Exemplo: rota pública `/fe` + redirect pós-login
|
|
22
|
+
|
|
23
|
+
Cenário do projeto Educação:
|
|
24
|
+
|
|
25
|
+
- `/fe` (área do aluno) deve ser pública.
|
|
26
|
+
- Usuários sem licença no módulo Educação caem por padrão na home privada
|
|
27
|
+
após o login do Qualiex — em vez de mostrar a tela de bloqueio, queremos
|
|
28
|
+
mandá-los para `/fe`.
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
<CoreProviders
|
|
32
|
+
backend="dotnet"
|
|
33
|
+
associationsBaseUrl={env.QUALIEX_API}
|
|
34
|
+
moduleAccessGuardProps={{
|
|
35
|
+
bypassPaths: ['/fe', '/fe/*'],
|
|
36
|
+
noAccessRedirectPath: '/fe',
|
|
37
|
+
noAccessRedirectMode: 'always',
|
|
38
|
+
}}
|
|
39
|
+
appTranslations={{ 'pt-BR': pt }}
|
|
40
|
+
>
|
|
41
|
+
...
|
|
42
|
+
</CoreProviders>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Tabela de comportamento
|
|
46
|
+
|
|
47
|
+
| Cenário | Resultado |
|
|
48
|
+
|-----------------------------------------------------------------|-----------|
|
|
49
|
+
| Usuário deslogado acessa `/fe` | Vê a página (precisa estar fora do `ProtectedRoute` no router do app) |
|
|
50
|
+
| Usuário deslogado acessa qualquer outra rota | Redirect para login pelo `ProtectedRoute` |
|
|
51
|
+
| Usuário logado **sem acesso** cai na home pós-login | Redirecionado para `/fe` |
|
|
52
|
+
| Usuário logado **sem acesso** digita `/turmas` na URL | Redirecionado para `/fe` (não vê mais a tela de bloqueio) |
|
|
53
|
+
| Usuário logado **com acesso** navega em qualquer rota privada | Tudo normal |
|
|
54
|
+
|
|
55
|
+
## Atenção
|
|
56
|
+
|
|
57
|
+
- **`bypassPaths` ≠ rota pública**. Ele só ignora o gating do módulo. Para
|
|
58
|
+
permitir acesso anônimo (sem login), a rota também precisa ficar fora do
|
|
59
|
+
`ProtectedRoute` no router do projeto consumidor.
|
|
60
|
+
- **`noAccessRedirectPath` não substitui auth**. Ele só dispara para usuários
|
|
61
|
+
já autenticados. Usuários deslogados continuam barrados pelo `ProtectedRoute`.
|
|
62
|
+
- O guard evita loops: se o destino do redirect for igual ao pathname atual,
|
|
63
|
+
os children são renderizados (combine com `bypassPaths` para liberar o destino).
|
|
64
|
+
|
|
65
|
+
## Combinações comuns
|
|
66
|
+
|
|
67
|
+
| Objetivo | Configuração |
|
|
68
|
+
|----------------------------------------------------------------|--------------|
|
|
69
|
+
| Liberar uma rota pública sem mexer no comportamento padrão | `bypassPaths: ['/publico/*']` |
|
|
70
|
+
| Mandar quem não tem licença para uma landing interna | `noAccessRedirectPath: '/sem-acesso'` |
|
|
71
|
+
| Liberar landing + redirecionar todo o resto para ela | `bypassPaths: ['/fe', '/fe/*']` + `noAccessRedirectPath: '/fe'` |
|
|
72
|
+
| Manter UI de bloqueio (comportamento legado) | Nenhuma das duas props |
|