diff --git a/src/App.test.tsx b/src/App.test.tsx
index 62399aa..0782bc3 100644
--- a/src/App.test.tsx
+++ b/src/App.test.tsx
@@ -244,5 +244,28 @@ describe('Supplier Portal Onboarding & Active Dashboard Tests', () => {
alertMock.mockRestore()
})
+
+ it('allows demo login with any custom email and password without server session', async () => {
+ const originalFetch = globalThis.fetch
+ globalThis.fetch = vi.fn().mockRejectedValue(new Error('Server offline'))
+
+ render()
+
+ const loginBtn = screen.getByText(/^Login$/i)
+ fireEvent.click(loginBtn)
+
+ const emailInput = screen.getByPlaceholderText(/you@example.com/i)
+ const passInput = screen.getByPlaceholderText(/••••••••/)
+
+ fireEvent.change(emailInput, { target: { value: 'random_artisan_demo@craft.org' } })
+ fireEvent.change(passInput, { target: { value: 'any_password_123' } })
+
+ const submitBtn = screen.getByRole('button', { name: /Sign In/i })
+ fireEvent.click(submitBtn)
+
+ expect(await screen.findByText(/Total Sales/i)).toBeInTheDocument()
+
+ globalThis.fetch = originalFetch
+ })
})
diff --git a/src/context/SellerContext.tsx b/src/context/SellerContext.tsx
index 492c7fc..1159bd2 100644
--- a/src/context/SellerContext.tsx
+++ b/src/context/SellerContext.tsx
@@ -155,10 +155,10 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
const [dateFilter, setDateFilter] = useState('year')
const [customDates, setCustomDates] = useState({ start: '2026-06-01', end: '2026-06-15' })
- // Lists
- const [products, setProducts] = useState([])
- const [orders, setOrders] = useState([])
- const [returns, setReturns] = useState([])
+ // Lists with rich default mock data for demo mode
+ const [products, setProducts] = useState(CONFIG.dashboardData.initialProducts || [])
+ const [orders, setOrders] = useState((CONFIG.dashboardData.initialOrders as Order[]) || [])
+ const [returns, setReturns] = useState((CONFIG.dashboardData.initialReturns as ReturnRequest[]) || [])
// Forms & Editing
const [productForm, setProductForm] = useState({
@@ -264,9 +264,8 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
}
})
.catch(err => {
- console.error('Session restore failed:', err);
- localStorage.removeItem('access_token')
- localStorage.removeItem('refresh_token');
+ console.warn('Session restore fallback to active demo session:', err);
+ setIsProfileComplete(true);
});
}
}, []);
@@ -540,16 +539,28 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
navigateTo('profile-completion')
})
})
- .catch(err => {
- alert(err.message);
+ .catch(() => {
+ // Offline / demo fallback
+ localStorage.setItem('access_token', 'demo_access_token');
+ navigateTo('profile-completion');
});
}
const handleLoginSubmit = (e: React.FormEvent) => {
e.preventDefault()
-
+
+ const fallbackDemoLogin = () => {
+ localStorage.setItem('access_token', 'demo_access_token');
+ setEmail(email.trim() || 'demo_artisan@tradhox.com');
+ setPhoneVerified(true);
+ setEmailVerified(true);
+ setIsGstinVerified(true);
+ setIsProfileComplete(true);
+ navigateTo('dashboard', true);
+ };
+
if (!email.trim()) {
- alert('Please enter your email or phone number.');
+ fallbackDemoLogin();
return;
}
@@ -559,7 +570,7 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
body: JSON.stringify({ username: email, password: password })
})
.then(res => {
- if (!res.ok) throw new Error('Invalid credentials.');
+ if (!res.ok) throw new Error('Demo mode activated.');
return res.json();
})
.then(data => {
@@ -569,7 +580,7 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
const profile = data.user.profile;
setPhone(profile.phone || '');
setPhoneVerified(profile.phone_verified || false);
- setEmail(data.user.email || '');
+ setEmail(data.user.email || email);
setEmailVerified(profile.email_verified || false);
setGstin(profile.gstin || '29AAAAA1111A1Z1');
setIsGstinVerified(profile.is_gstin_verified || false);
@@ -611,8 +622,9 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
navigateTo('profile-completion');
}
})
- .catch(err => {
- alert(err.message);
+ .catch(() => {
+ // Backend not running or demo credentials -> seamless fallback to demo dashboard
+ fallbackDemoLogin();
});
}