Fix magic OTP on dev, fix portal login flash of login form

- loginOTP.cfm/sendOTP.cfm: Use magic OTP code (123456) on dev instead of random
- portal/login.html: Hide login card until auth check completes to prevent flash of login form when redirecting to business selection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
John Mizerek 2026-01-31 14:19:36 -08:00
parent c5a332b04e
commit 498ebb6c0e
3 changed files with 29 additions and 7 deletions

View file

@ -76,8 +76,12 @@ try {
}, { datasource: "payfrit" });
}
// Generate and save OTP
// Generate OTP (use magic code on dev for easy testing)
otp = generateOTP();
if (structKeyExists(application, "MAGIC_OTP_ENABLED") && application.MAGIC_OTP_ENABLED
&& structKeyExists(application, "MAGIC_OTP_CODE") && len(application.MAGIC_OTP_CODE)) {
otp = application.MAGIC_OTP_CODE;
}
queryExecute("
UPDATE Users
SET MobileVerifyCode = :otp

View file

@ -81,6 +81,10 @@ try {
", { phone: { value: phone, cfsqltype: "cf_sql_varchar" } }, { datasource: "payfrit" });
otp = generateOTP();
if (structKeyExists(application, "MAGIC_OTP_ENABLED") && application.MAGIC_OTP_ENABLED
&& structKeyExists(application, "MAGIC_OTP_CODE") && len(application.MAGIC_OTP_CODE)) {
otp = application.MAGIC_OTP_CODE;
}
userUUID = "";
if (qIncomplete.recordCount > 0) {

View file

@ -167,6 +167,14 @@
border-color: var(--primary);
}
.login-card {
visibility: hidden;
}
.login-card.ready {
visibility: visible;
}
.step {
display: none;
}
@ -186,7 +194,7 @@
</div>
<!-- Step 1: Login -->
<div class="step active" id="step-login">
<div class="step" id="step-login">
<form class="login-form" id="loginForm">
<div class="login-error" id="loginError"></div>
@ -239,27 +247,31 @@
businesses: [],
init() {
// Check if already logged in
const card = document.querySelector('.login-card');
const savedToken = localStorage.getItem('payfrit_portal_token');
const savedBusiness = localStorage.getItem('payfrit_portal_business');
const savedUserId = localStorage.getItem('payfrit_portal_userid');
if (savedToken && savedBusiness) {
// Already logged in with a business - redirect to portal
// Already logged in with a business - redirect to portal (stay hidden)
this.verifyAndRedirect(savedToken, savedBusiness);
return;
}
if (savedToken && savedUserId) {
// Has token but no business selected (switching businesses)
// Skip login form, go directly to business selection
// Has token but no business selected - skip login, show business selection
this.userToken = savedToken;
this.userId = parseInt(savedUserId);
this.showStep('business');
card.classList.add('ready');
this.loadBusinessesAndShow();
return;
}
// Setup form handlers
// No saved session - show login form
this.showStep('login');
card.classList.add('ready');
document.getElementById('loginForm').addEventListener('submit', (e) => {
e.preventDefault();
this.login();
@ -331,6 +343,7 @@
// Load user's businesses
await this.loadBusinesses();
const card = document.querySelector('.login-card');
if (this.businesses.length === 0) {
// No businesses - go directly to wizard
this.startNewRestaurant();
@ -340,6 +353,7 @@
} else {
// Multiple businesses - show selection
this.showStep('business');
card.classList.add('ready');
}
} else {
const friendlyErrors = {