Merge pull request 'feat(otp): mock phone OTP fallback while Twilio is down' (#17) from tanweer919/lynkeduppro-crm:feat/login-methods into goutamnextflow
This commit was merged in pull request #17.
This commit is contained in:
@@ -19,6 +19,12 @@ type Addr = { line1?: string; line2?: string; city?: string; state?: string; pos
|
|||||||
const STEPS = ["Account", "Verify", "Address"];
|
const STEPS = ["Account", "Verify", "Address"];
|
||||||
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
|
||||||
|
// Demo fallback for phone OTP while the Twilio sender is down. When on, the Verify
|
||||||
|
// step skips Supabase/Twilio and accepts a fixed code. Flip NEXT_PUBLIC_MOCK_OTP to
|
||||||
|
// "false" (or remove it) to restore real SMS verification — no other change needed.
|
||||||
|
const MOCK_OTP = process.env.NEXT_PUBLIC_MOCK_OTP === "true";
|
||||||
|
const DEMO_OTP = "123456";
|
||||||
|
|
||||||
export function RegisterFlow({ mode = "register" }: { mode?: "register" | "onboard" }) {
|
export function RegisterFlow({ mode = "register" }: { mode?: "register" | "onboard" }) {
|
||||||
// "onboard" = an already-authenticated OAuth (Google) user completing their CRM
|
// "onboard" = an already-authenticated OAuth (Google) user completing their CRM
|
||||||
// profile: email is skipped (Google-verified), the auth account already exists so
|
// profile: email is skipped (Google-verified), the auth account already exists so
|
||||||
@@ -390,6 +396,7 @@ function PhoneVerify({ cc, country, initialPhone, verified, onVerified }: {
|
|||||||
if (value.replace(/\D/g, "").length !== country.digits) { setState("invalid_mobile"); return; }
|
if (value.replace(/\D/g, "").length !== country.digits) { setState("invalid_mobile"); return; }
|
||||||
setState("sending");
|
setState("sending");
|
||||||
setOtpError("");
|
setOtpError("");
|
||||||
|
if (MOCK_OTP) { setState("sent"); return; } // demo: skip Twilio entirely
|
||||||
try {
|
try {
|
||||||
await addPhone(e164); // Supabase → Twilio sends the SMS OTP
|
await addPhone(e164); // Supabase → Twilio sends the SMS OTP
|
||||||
setState("sent");
|
setState("sent");
|
||||||
@@ -400,6 +407,11 @@ function PhoneVerify({ cc, country, initialPhone, verified, onVerified }: {
|
|||||||
|
|
||||||
async function submit(code: string) {
|
async function submit(code: string) {
|
||||||
setOtpError("");
|
setOtpError("");
|
||||||
|
if (MOCK_OTP) {
|
||||||
|
if (code === DEMO_OTP) onVerified();
|
||||||
|
else setOtpError(`Demo mode — enter ${DEMO_OTP} to verify.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await verifyPhone(e164, code); // confirm the OTP (phone_change)
|
await verifyPhone(e164, code); // confirm the OTP (phone_change)
|
||||||
onVerified();
|
onVerified();
|
||||||
@@ -436,13 +448,13 @@ function PhoneVerify({ cc, country, initialPhone, verified, onVerified }: {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="row between" style={{ marginTop: 12 }}>
|
<div className="row between" style={{ marginTop: 12 }}>
|
||||||
<span className="faint" style={{ fontSize: 12 }}>Standard SMS rates may apply.</span>
|
<span className="faint" style={{ fontSize: 12 }}>{MOCK_OTP ? "Demo verification (no SMS sent)." : "Standard SMS rates may apply."}</span>
|
||||||
<button className="btn btn-sm" style={{ width: "auto" }} disabled={state === "sending" || state === "sent"} onClick={send}>
|
<button className="btn btn-sm" style={{ width: "auto" }} disabled={state === "sending" || state === "sent"} onClick={send}>
|
||||||
{state === "sending" ? "Sending…" : state === "sent" ? "Sent" : "Send code"}
|
{state === "sending" ? "Sending…" : state === "sent" ? "Sent" : "Send code"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{state === "sent" && <p className="faint" style={{ fontSize: 12, marginTop: 10 }}>Code sent to {cc} {value} by SMS.</p>}
|
{state === "sent" && <p className="faint" style={{ fontSize: 12, marginTop: 10 }}>{MOCK_OTP ? `Demo mode — enter ${DEMO_OTP} to verify (SMS temporarily disabled).` : `Code sent to ${cc} ${value} by SMS.`}</p>}
|
||||||
{state === "invalid_mobile" && <div style={{ marginTop: 10 }}><FlashNote tone="error">Enter a valid {country.digits}-digit mobile number.</FlashNote></div>}
|
{state === "invalid_mobile" && <div style={{ marginTop: 10 }}><FlashNote tone="error">Enter a valid {country.digits}-digit mobile number.</FlashNote></div>}
|
||||||
{state === "send_error" && <div style={{ marginTop: 10 }}><FlashNote tone="error">Couldn't send the code. Check the number and try again.</FlashNote></div>}
|
{state === "send_error" && <div style={{ marginTop: 10 }}><FlashNote tone="error">Couldn't send the code. Check the number and try again.</FlashNote></div>}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user