@hook-sdk/template 0.13.0 → 0.14.0
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/index.cjs +117 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +117 -13
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1919,14 +1919,18 @@ var import_react11 = require("react");
|
|
|
1919
1919
|
var import_sdk4 = require("@hook-sdk/sdk");
|
|
1920
1920
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1921
1921
|
var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
|
|
1922
|
+
var MAX_CYCLES = 3;
|
|
1923
|
+
var SUPPORT_MAILTO = "mailto:suporte@usehook.net?subject=Pagamento%20pendente";
|
|
1922
1924
|
function PaymentReturnHandler({ children }) {
|
|
1923
1925
|
const { subscription } = (0, import_sdk4.useHook)();
|
|
1924
1926
|
const subRef = (0, import_react11.useRef)(subscription);
|
|
1925
1927
|
subRef.current = subscription;
|
|
1926
1928
|
const runIdRef = (0, import_react11.useRef)(0);
|
|
1929
|
+
const cyclesRef = (0, import_react11.useRef)(0);
|
|
1927
1930
|
const [state, setState] = (0, import_react11.useState)("idle");
|
|
1928
1931
|
const runPoll = (0, import_react11.useCallback)(() => {
|
|
1929
1932
|
const runId = ++runIdRef.current;
|
|
1933
|
+
cyclesRef.current += 1;
|
|
1930
1934
|
setState("confirming");
|
|
1931
1935
|
let attempts = 0;
|
|
1932
1936
|
const tick = async () => {
|
|
@@ -1942,12 +1946,17 @@ function PaymentReturnHandler({ children }) {
|
|
|
1942
1946
|
const cleanUrl = new URL(window.location.href);
|
|
1943
1947
|
cleanUrl.searchParams.delete("paymentReturn");
|
|
1944
1948
|
window.history.replaceState({}, "", cleanUrl.toString());
|
|
1949
|
+
cyclesRef.current = 0;
|
|
1945
1950
|
setState("idle");
|
|
1946
1951
|
return;
|
|
1947
1952
|
}
|
|
1948
1953
|
const delay = BACKOFF_MS[attempts - 1];
|
|
1949
1954
|
if (delay === void 0) {
|
|
1950
|
-
|
|
1955
|
+
if (cyclesRef.current >= MAX_CYCLES) {
|
|
1956
|
+
setState("timeout");
|
|
1957
|
+
} else {
|
|
1958
|
+
setState("waiting");
|
|
1959
|
+
}
|
|
1951
1960
|
return;
|
|
1952
1961
|
}
|
|
1953
1962
|
setTimeout(tick, delay);
|
|
@@ -1958,11 +1967,18 @@ function PaymentReturnHandler({ children }) {
|
|
|
1958
1967
|
if (typeof window === "undefined") return;
|
|
1959
1968
|
const url = new URL(window.location.href);
|
|
1960
1969
|
if (url.searchParams.get("paymentReturn") !== "1") return;
|
|
1970
|
+
cyclesRef.current = 0;
|
|
1961
1971
|
runPoll();
|
|
1962
1972
|
return () => {
|
|
1963
1973
|
runIdRef.current++;
|
|
1964
1974
|
};
|
|
1965
1975
|
}, [runPoll]);
|
|
1976
|
+
const goHome = (0, import_react11.useCallback)(() => {
|
|
1977
|
+
const cleanUrl = new URL(window.location.href);
|
|
1978
|
+
cleanUrl.searchParams.delete("paymentReturn");
|
|
1979
|
+
cleanUrl.pathname = "/app/home";
|
|
1980
|
+
window.location.href = cleanUrl.toString();
|
|
1981
|
+
}, []);
|
|
1966
1982
|
if (state === "confirming") {
|
|
1967
1983
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: "Confirmando pagamento\u2026" });
|
|
1968
1984
|
}
|
|
@@ -1972,6 +1988,45 @@ function PaymentReturnHandler({ children }) {
|
|
|
1972
1988
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", onClick: runPoll, style: buttonStyle, children: "Atualizar" })
|
|
1973
1989
|
] }) });
|
|
1974
1990
|
}
|
|
1991
|
+
if (state === "timeout") {
|
|
1992
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { role: "alert", "aria-live": "assertive", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { maxWidth: 360, textAlign: "center", lineHeight: 1.5 }, children: [
|
|
1993
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { marginBottom: 16 }, children: "Ainda n\xE3o conseguimos confirmar seu pagamento com o banco. Voc\xEA pode tentar de novo, voltar pro app, ou falar com a gente." }),
|
|
1994
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
1995
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1996
|
+
"button",
|
|
1997
|
+
{
|
|
1998
|
+
type: "button",
|
|
1999
|
+
onClick: () => {
|
|
2000
|
+
cyclesRef.current = 0;
|
|
2001
|
+
runPoll();
|
|
2002
|
+
},
|
|
2003
|
+
style: buttonStyle,
|
|
2004
|
+
"data-testid": "payment-timeout-retry",
|
|
2005
|
+
children: "Tentar de novo"
|
|
2006
|
+
}
|
|
2007
|
+
),
|
|
2008
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2009
|
+
"button",
|
|
2010
|
+
{
|
|
2011
|
+
type: "button",
|
|
2012
|
+
onClick: goHome,
|
|
2013
|
+
style: secondaryButtonStyle,
|
|
2014
|
+
"data-testid": "payment-timeout-home",
|
|
2015
|
+
children: "Voltar pro app"
|
|
2016
|
+
}
|
|
2017
|
+
),
|
|
2018
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2019
|
+
"a",
|
|
2020
|
+
{
|
|
2021
|
+
href: SUPPORT_MAILTO,
|
|
2022
|
+
style: linkStyle,
|
|
2023
|
+
"data-testid": "payment-timeout-support",
|
|
2024
|
+
children: "Falar com suporte"
|
|
2025
|
+
}
|
|
2026
|
+
)
|
|
2027
|
+
] })
|
|
2028
|
+
] }) });
|
|
2029
|
+
}
|
|
1975
2030
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, { children });
|
|
1976
2031
|
}
|
|
1977
2032
|
var overlayStyle2 = {
|
|
@@ -1996,6 +2051,19 @@ var buttonStyle = {
|
|
|
1996
2051
|
fontWeight: 600,
|
|
1997
2052
|
cursor: "pointer"
|
|
1998
2053
|
};
|
|
2054
|
+
var secondaryButtonStyle = {
|
|
2055
|
+
...buttonStyle,
|
|
2056
|
+
background: "transparent",
|
|
2057
|
+
color: "white",
|
|
2058
|
+
border: "1px solid rgba(255,255,255,0.5)"
|
|
2059
|
+
};
|
|
2060
|
+
var linkStyle = {
|
|
2061
|
+
color: "white",
|
|
2062
|
+
textDecoration: "underline",
|
|
2063
|
+
fontSize: "0.9rem",
|
|
2064
|
+
marginTop: 4,
|
|
2065
|
+
textAlign: "center"
|
|
2066
|
+
};
|
|
1999
2067
|
|
|
2000
2068
|
// src/AppRoot.tsx
|
|
2001
2069
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
@@ -2332,18 +2400,24 @@ function useLoginForm() {
|
|
|
2332
2400
|
const [password, setPassword] = (0, import_react14.useState)("");
|
|
2333
2401
|
const [submitting, setSubmitting] = (0, import_react14.useState)(false);
|
|
2334
2402
|
const [error, setError] = (0, import_react14.useState)(null);
|
|
2335
|
-
const
|
|
2403
|
+
const [touchedEmail, setTouchedEmail] = (0, import_react14.useState)(false);
|
|
2404
|
+
const [touchedPassword, setTouchedPassword] = (0, import_react14.useState)(false);
|
|
2405
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react14.useState)(false);
|
|
2406
|
+
const validateEmail = (0, import_react14.useMemo)(() => {
|
|
2336
2407
|
if (email.length === 0) return null;
|
|
2337
2408
|
if (!EMAIL_RE.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2338
2409
|
return null;
|
|
2339
2410
|
}, [email]);
|
|
2340
|
-
const
|
|
2411
|
+
const validatePassword = (0, import_react14.useMemo)(() => {
|
|
2341
2412
|
if (password.length === 0) return null;
|
|
2342
2413
|
if (password.length < MIN_PASSWORD) return `M\xEDnimo de ${MIN_PASSWORD} caracteres.`;
|
|
2343
2414
|
return null;
|
|
2344
2415
|
}, [password]);
|
|
2345
|
-
const
|
|
2416
|
+
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2417
|
+
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2418
|
+
const canSubmit = email.length > 0 && password.length >= MIN_PASSWORD && validateEmail === null && validatePassword === null && !submitting;
|
|
2346
2419
|
const submit = (0, import_react14.useCallback)(async () => {
|
|
2420
|
+
setFormSubmitAttempted(true);
|
|
2347
2421
|
if (!canSubmit) return false;
|
|
2348
2422
|
setSubmitting(true);
|
|
2349
2423
|
setError(null);
|
|
@@ -2361,9 +2435,12 @@ function useLoginForm() {
|
|
|
2361
2435
|
email,
|
|
2362
2436
|
setEmail,
|
|
2363
2437
|
emailError,
|
|
2438
|
+
markEmailTouched: () => setTouchedEmail(true),
|
|
2364
2439
|
password,
|
|
2365
2440
|
setPassword,
|
|
2366
2441
|
passwordError,
|
|
2442
|
+
markPasswordTouched: () => setTouchedPassword(true),
|
|
2443
|
+
formSubmitAttempted,
|
|
2367
2444
|
submit,
|
|
2368
2445
|
submitting,
|
|
2369
2446
|
canSubmit,
|
|
@@ -2384,23 +2461,31 @@ function useSignupForm() {
|
|
|
2384
2461
|
const [password, setPassword] = (0, import_react15.useState)("");
|
|
2385
2462
|
const [submitting, setSubmitting] = (0, import_react15.useState)(false);
|
|
2386
2463
|
const [error, setError] = (0, import_react15.useState)(null);
|
|
2387
|
-
const
|
|
2464
|
+
const [touchedName, setTouchedName] = (0, import_react15.useState)(false);
|
|
2465
|
+
const [touchedEmail, setTouchedEmail] = (0, import_react15.useState)(false);
|
|
2466
|
+
const [touchedPassword, setTouchedPassword] = (0, import_react15.useState)(false);
|
|
2467
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react15.useState)(false);
|
|
2468
|
+
const validateName = (0, import_react15.useMemo)(() => {
|
|
2388
2469
|
if (name.length === 0) return null;
|
|
2389
2470
|
if (name.trim().length < 2) return "Nome muito curto.";
|
|
2390
2471
|
return null;
|
|
2391
2472
|
}, [name]);
|
|
2392
|
-
const
|
|
2473
|
+
const validateEmail = (0, import_react15.useMemo)(() => {
|
|
2393
2474
|
if (email.length === 0) return null;
|
|
2394
2475
|
if (!EMAIL_RE2.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2395
2476
|
return null;
|
|
2396
2477
|
}, [email]);
|
|
2397
|
-
const
|
|
2478
|
+
const validatePassword = (0, import_react15.useMemo)(() => {
|
|
2398
2479
|
if (password.length === 0) return null;
|
|
2399
2480
|
if (password.length < MIN_PASSWORD2) return `M\xEDnimo de ${MIN_PASSWORD2} caracteres.`;
|
|
2400
2481
|
return null;
|
|
2401
2482
|
}, [password]);
|
|
2402
|
-
const
|
|
2483
|
+
const nameError = touchedName || formSubmitAttempted ? validateName : null;
|
|
2484
|
+
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2485
|
+
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2486
|
+
const canSubmit = name.trim().length >= 2 && email.length > 0 && password.length >= MIN_PASSWORD2 && validateName === null && validateEmail === null && validatePassword === null && !submitting;
|
|
2403
2487
|
const submit = (0, import_react15.useCallback)(async () => {
|
|
2488
|
+
setFormSubmitAttempted(true);
|
|
2404
2489
|
if (!canSubmit) return false;
|
|
2405
2490
|
setSubmitting(true);
|
|
2406
2491
|
setError(null);
|
|
@@ -2418,12 +2503,16 @@ function useSignupForm() {
|
|
|
2418
2503
|
name,
|
|
2419
2504
|
setName,
|
|
2420
2505
|
nameError,
|
|
2506
|
+
markNameTouched: () => setTouchedName(true),
|
|
2421
2507
|
email,
|
|
2422
2508
|
setEmail,
|
|
2423
2509
|
emailError,
|
|
2510
|
+
markEmailTouched: () => setTouchedEmail(true),
|
|
2424
2511
|
password,
|
|
2425
2512
|
setPassword,
|
|
2426
2513
|
passwordError,
|
|
2514
|
+
markPasswordTouched: () => setTouchedPassword(true),
|
|
2515
|
+
formSubmitAttempted,
|
|
2427
2516
|
submit,
|
|
2428
2517
|
submitting,
|
|
2429
2518
|
canSubmit,
|
|
@@ -2442,13 +2531,17 @@ function useForgotForm() {
|
|
|
2442
2531
|
const [submitting, setSubmitting] = (0, import_react16.useState)(false);
|
|
2443
2532
|
const [sent, setSent] = (0, import_react16.useState)(false);
|
|
2444
2533
|
const [error, setError] = (0, import_react16.useState)(null);
|
|
2445
|
-
const
|
|
2534
|
+
const [touchedEmail, setTouchedEmail] = (0, import_react16.useState)(false);
|
|
2535
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react16.useState)(false);
|
|
2536
|
+
const validateEmail = (0, import_react16.useMemo)(() => {
|
|
2446
2537
|
if (email.length === 0) return null;
|
|
2447
2538
|
if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2448
2539
|
return null;
|
|
2449
2540
|
}, [email]);
|
|
2450
|
-
const
|
|
2541
|
+
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2542
|
+
const canSubmit = email.length > 0 && validateEmail === null && !submitting;
|
|
2451
2543
|
const submit = (0, import_react16.useCallback)(async () => {
|
|
2544
|
+
setFormSubmitAttempted(true);
|
|
2452
2545
|
if (!canSubmit) return false;
|
|
2453
2546
|
setSubmitting(true);
|
|
2454
2547
|
setError(null);
|
|
@@ -2467,6 +2560,8 @@ function useForgotForm() {
|
|
|
2467
2560
|
email,
|
|
2468
2561
|
setEmail,
|
|
2469
2562
|
emailError,
|
|
2563
|
+
markEmailTouched: () => setTouchedEmail(true),
|
|
2564
|
+
formSubmitAttempted,
|
|
2470
2565
|
submit,
|
|
2471
2566
|
submitting,
|
|
2472
2567
|
canSubmit,
|
|
@@ -2487,24 +2582,30 @@ function useResetForm() {
|
|
|
2487
2582
|
const [submitting, setSubmitting] = (0, import_react17.useState)(false);
|
|
2488
2583
|
const [done, setDone] = (0, import_react17.useState)(false);
|
|
2489
2584
|
const [error, setError] = (0, import_react17.useState)(null);
|
|
2585
|
+
const [touchedPassword, setTouchedPassword] = (0, import_react17.useState)(false);
|
|
2586
|
+
const [touchedConfirm, setTouchedConfirm] = (0, import_react17.useState)(false);
|
|
2587
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react17.useState)(false);
|
|
2490
2588
|
(0, import_react17.useEffect)(() => {
|
|
2491
2589
|
if (typeof window === "undefined") return;
|
|
2492
2590
|
const params = new URLSearchParams(window.location.search);
|
|
2493
2591
|
const t = params.get("token");
|
|
2494
2592
|
setToken(t && t.length > 0 ? t : null);
|
|
2495
2593
|
}, []);
|
|
2496
|
-
const
|
|
2594
|
+
const validatePassword = (0, import_react17.useMemo)(() => {
|
|
2497
2595
|
if (password.length === 0) return null;
|
|
2498
2596
|
if (password.length < MIN_PASSWORD3) return `M\xEDnimo de ${MIN_PASSWORD3} caracteres.`;
|
|
2499
2597
|
return null;
|
|
2500
2598
|
}, [password]);
|
|
2501
|
-
const
|
|
2599
|
+
const validateConfirm = (0, import_react17.useMemo)(() => {
|
|
2502
2600
|
if (confirm.length === 0) return null;
|
|
2503
2601
|
if (confirm !== password) return "Senhas n\xE3o coincidem.";
|
|
2504
2602
|
return null;
|
|
2505
2603
|
}, [confirm, password]);
|
|
2506
|
-
const
|
|
2604
|
+
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2605
|
+
const confirmError = touchedConfirm || formSubmitAttempted ? validateConfirm : null;
|
|
2606
|
+
const canSubmit = token !== null && password.length >= MIN_PASSWORD3 && confirm === password && validatePassword === null && validateConfirm === null && !submitting && !done;
|
|
2507
2607
|
const submit = (0, import_react17.useCallback)(async () => {
|
|
2608
|
+
setFormSubmitAttempted(true);
|
|
2508
2609
|
if (!canSubmit || token === null) return;
|
|
2509
2610
|
setSubmitting(true);
|
|
2510
2611
|
setError(null);
|
|
@@ -2528,9 +2629,12 @@ function useResetForm() {
|
|
|
2528
2629
|
password,
|
|
2529
2630
|
setPassword,
|
|
2530
2631
|
passwordError,
|
|
2632
|
+
markPasswordTouched: () => setTouchedPassword(true),
|
|
2531
2633
|
confirm,
|
|
2532
2634
|
setConfirm,
|
|
2533
2635
|
confirmError,
|
|
2636
|
+
markConfirmTouched: () => setTouchedConfirm(true),
|
|
2637
|
+
formSubmitAttempted,
|
|
2534
2638
|
submit,
|
|
2535
2639
|
submitting,
|
|
2536
2640
|
canSubmit,
|