feat: remove backend link and support passwordless login and registration
All checks were successful
Beta CI/CD Pipeline / build-and-test (push) Successful in 1m21s
Beta CI/CD Pipeline / deploy-beta (push) Successful in 25s

This commit is contained in:
vickytechkey 2026-09-10 20:05:12 +05:30
parent b3557d0698
commit 2a8f575e1c
6 changed files with 59 additions and 37 deletions

View file

@ -267,5 +267,34 @@ describe('Supplier Portal Onboarding & Active Dashboard Tests', () => {
globalThis.fetch = originalFetch
})
it('allows login directly without entering any password', async () => {
render(<App />)
const loginBtn = screen.getByText(/^Login$/i)
fireEvent.click(loginBtn)
const submitBtn = screen.getByRole('button', { name: /Sign In/i })
fireEvent.click(submitBtn)
expect(await screen.findByText(/Total Sales/i)).toBeInTheDocument()
})
it('allows signup without entering any password', async () => {
render(<App />)
const getStartedBtn = screen.getByText(/^Get started$/i)
fireEvent.click(getStartedBtn)
fireEvent.change(screen.getByPlaceholderText(/Enter your email/i), { target: { value: 'artisan_nopass@tradhox.com' } })
fireEvent.change(screen.getByPlaceholderText(/9876543210/i), { target: { value: '9876543210' } })
fireEvent.click(screen.getByLabelText(/I agree to the/i))
const alertMock = vi.spyOn(window, 'alert').mockImplementation(() => {})
fireEvent.click(screen.getByRole('button', { name: /Create Account/i }))
expect(await screen.findByText(/Welcome to Tradhox/i)).toBeInTheDocument()
alertMock.mockRestore()
})
})

View file

@ -150,10 +150,9 @@ export default function AuthForms() {
<input
id="r-pass"
type={showSignupPass ? 'text' : 'password'}
placeholder="Create a password"
placeholder="Create a password (optional)"
value={password}
onChange={e => setPassword(e.target.value)}
required
style={{ width: '100%', border: '1px solid #D1CAC7', borderRadius: '8px', height: '42px', padding: '0 40px 0 14px', fontSize: '0.9rem', outline: 'none' }}
/>
<button
@ -174,10 +173,9 @@ export default function AuthForms() {
<input
id="r-confirm"
type="password"
placeholder="Repeat your password"
placeholder="Repeat your password (optional)"
value={confirmPassword}
onChange={e => setConfirmPassword(e.target.value)}
required
style={{ width: '100%', border: '1px solid #D1CAC7', borderRadius: '8px', height: '42px', padding: '0 14px', fontSize: '0.9rem', outline: 'none' }}
/>
</div>

View file

@ -211,7 +211,6 @@ export default function LoginPage() {
placeholder="you@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
style={{ borderColor: '#D1CAC7', borderRadius: '8px', height: '42px', fontSize: '0.9rem' }}
/>
<span className="icon is-left has-text-grey">
@ -237,7 +236,6 @@ export default function LoginPage() {
placeholder="••••••••"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
style={{ borderColor: '#D1CAC7', borderRadius: '8px', height: '42px', fontSize: '0.9rem' }}
/>
<span className="icon is-left has-text-grey">

View file

@ -1,9 +1,4 @@
const getApiBaseUrl = () => {
if (import.meta.env.DEV) {
return 'http://127.0.0.1:8000'; // Or your local backend port
}
// Use relative path in production.
// CloudFront will proxy /api/* requests to the EC2 backend automatically!
return '';
};

View file

@ -479,26 +479,22 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
const handleRegisterSubmit = (e: React.FormEvent) => {
e.preventDefault()
// Email Validation
// Email Validation (if provided)
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
if (email.trim() && !emailRegex.test(email)) {
alert('Please enter a valid email address.');
return;
}
// Phone Validation
// Phone Validation (if provided)
const phoneRegex = /^[6-9]\d{9}$/;
if (!phoneRegex.test(phone)) {
if (phone.trim() && !phoneRegex.test(phone)) {
alert('Please enter a valid 10-digit mobile number starting with 6, 7, 8, or 9.');
return;
}
// Password Validation
if (password.length < 8) {
alert('Password must be at least 8 characters long.');
return;
}
if (password !== confirmPassword) {
// Password Validation: If password is provided and confirm password doesn't match
if (password && confirmPassword && password !== confirmPassword) {
alert('Passwords do not match.');
return;
}
@ -509,15 +505,26 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
return;
}
const completeRegistration = () => {
localStorage.setItem('access_token', 'demo_access_token');
navigateTo('profile-completion');
};
// If no password is provided, proceed directly to onboarding
if (!password) {
completeRegistration();
return;
}
apiFetch(`${CONFIG.apiBaseUrl}/api/auth/register/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: email,
email: email,
phone: phone,
username: email || 'demo_artisan@tradhox.com',
email: email || 'demo_artisan@tradhox.com',
phone: phone || '9876543210',
password: password,
confirm_password: confirmPassword,
confirm_password: confirmPassword || password,
policy_accepted: policyAccepted
})
})
@ -530,7 +537,7 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
apiFetch(`${CONFIG.apiBaseUrl}/api/auth/login/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: email, password: password })
body: JSON.stringify({ username: email || 'demo_artisan@tradhox.com', password: password })
})
.then(res => {
if (!res.ok) throw new Error('Auto-login failed.');
@ -541,11 +548,13 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
if (data.refresh_token) localStorage.setItem('refresh_token', data.refresh_token);
navigateTo('profile-completion')
})
.catch(() => {
completeRegistration();
})
})
.catch(() => {
// Offline / demo fallback
localStorage.setItem('access_token', 'demo_access_token');
navigateTo('profile-completion');
completeRegistration();
});
}
@ -562,7 +571,8 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
navigateTo('dashboard', true);
};
if (!email.trim()) {
// Allow login without password directly
if (!password) {
fallbackDemoLogin();
return;
}

View file

@ -6,12 +6,4 @@ export default defineConfig({
plugins: [
react(),
],
server: {
proxy: {
'/api': {
target: 'http://127.0.0.1:8000',
changeOrigin: true,
},
},
},
})