- Reorganized admin settings into tabbed interface (General, Security, Payment Methods) - Vertical tabs on desktop, horizontal scrollable on mobile - Moved Payment Methods from separate menu to Settings tab - Fixed admin profile reuse and dashboard blocking - Fixed maintenance mode guard to use AppConfig model - Added admin auto-redirect after login (admins → /admin, users → /) - Reorganized documentation into docs/ folder structure - Created comprehensive README and documentation index - Added PWA and Web Push notifications to to-do list
20 KiB
20 KiB
Maintenance Mode - Visual Flow Diagram
🎯 Where Does the Maintenance Page Appear?
Answer: It appears AFTER successful login, when trying to access protected routes
📊 Complete User Journey
Scenario 1: Non-Logged-In User (Maintenance ON)
┌─────────────────────────────────────────────────────────────┐
│ User opens: http://localhost:5174 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ App.tsx checks: Is user logged in? │
│ Answer: NO │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Redirect to: /auth/login │
│ (Login page loads normally - @SkipMaintenance) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ User enters credentials and clicks Login │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ POST /auth/login (Works - @SkipMaintenance) │
│ Returns: { token: "...", user: {...} } │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Token saved to localStorage │
│ Redirect to: / │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Dashboard tries to load │
│ Makes API call: GET /api/users/me │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ MaintenanceGuard intercepts request │
│ - Checks: Is maintenance ON? YES │
│ - Checks: Is user admin? NO (role: 'user') │
│ - Returns: 503 Service Unavailable │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Axios interceptor catches 503 error │
│ Calls: setMaintenanceMode(true) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ ⚠️ MAINTENANCE PAGE DISPLAYED │
│ │
│ 🔧 Under Maintenance │
│ Your custom message here │
│ [Refresh Page] │
└─────────────────────────────────────────────────────────────┘
Scenario 2: Logged-In User (Maintenance Turns ON)
┌─────────────────────────────────────────────────────────────┐
│ User is already logged in, using the app normally │
│ Currently on: /wallets │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Admin enables maintenance mode in /admin/settings │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ User clicks on "Transactions" menu │
│ OR tries to create a new transaction │
│ OR any action that makes an API call │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ API call: POST /api/transactions │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ MaintenanceGuard intercepts │
│ - Maintenance is ON │
│ - User is not admin │
│ - Returns: 503 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Axios interceptor triggers │
│ setMaintenanceMode(true) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ ⚠️ MAINTENANCE PAGE REPLACES CURRENT VIEW │
│ │
│ 🔧 Under Maintenance │
│ System is being upgraded... │
│ [Refresh Page] │
└─────────────────────────────────────────────────────────────┘
Scenario 3: Admin User (Maintenance ON)
┌─────────────────────────────────────────────────────────────┐
│ Admin logs in at: /auth/login │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Redirected to: / │
│ Makes API call: GET /api/users/me │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ MaintenanceGuard intercepts │
│ - Maintenance is ON │
│ - Extracts JWT token │
│ - Checks role: 'admin' │
│ - Returns: 503 (Even for admin on main app!) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ ⚠️ MAINTENANCE PAGE SHOWN │
│ │
│ (Admin sees maintenance on main app) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Admin navigates to: /admin │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Makes API call: GET /api/admin/users/stats │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ MaintenanceGuard intercepts │
│ - Route has @SkipMaintenance decorator │
│ - Returns: ALLOW (200 OK) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ ✅ ADMIN PANEL WORKS NORMALLY │
│ │
│ Admin can: │
│ - View dashboard │
│ - Manage users │
│ - Disable maintenance mode │
└─────────────────────────────────────────────────────────────┘
🎨 Visual Representation
App Structure During Maintenance:
┌─────────────────────────────────────────────────────────────┐
│ TABUNGIN APP │
├─────────────────────────────────────────────────────────────┤
│ │
│ PUBLIC ROUTES (Always Work) │
│ ✅ /auth/login │
│ ✅ /auth/register │
│ ✅ /auth/otp │
│ ✅ /health │
│ │
├─────────────────────────────────────────────────────────────┤
│ │
│ ADMIN ROUTES (Work for Admins Only) │
│ ✅ /admin/* │
│ ✅ /api/admin/* │
│ │
├─────────────────────────────────────────────────────────────┤
│ │
│ MAIN APP ROUTES (BLOCKED - Shows Maintenance) │
│ ❌ / │
│ ❌ /wallets │
│ ❌ /transactions │
│ ❌ /api/users/me │
│ ❌ /api/wallets │
│ ❌ /api/transactions │
│ │
│ 👉 All show: MAINTENANCE PAGE │
│ │
└─────────────────────────────────────────────────────────────┘
🔍 Code Flow in App.tsx
export default function App() {
const [maintenanceMode, setMaintenanceMode] = useState(false)
const [maintenanceMessage, setMaintenanceMessage] = useState('')
useEffect(() => {
// Setup interceptor on app load
setupAxiosInterceptors((message) => {
setMaintenanceMessage(message)
setMaintenanceMode(true) // 👈 This triggers maintenance page
})
}, [])
// 👇 When maintenance mode is true, show maintenance page
if (maintenanceMode) {
return (
<ThemeProvider>
<MaintenancePage message={maintenanceMessage} />
</ThemeProvider>
)
}
// 👇 Otherwise, show normal app
return (
<BrowserRouter>
<ThemeProvider>
<LanguageProvider>
<AuthProvider>
<Routes>
{/* All routes here */}
</Routes>
</AuthProvider>
</LanguageProvider>
</ThemeProvider>
</BrowserRouter>
)
}
🎯 Key Points
1. Maintenance Page is NOT a Route
- It's not
/maintenanceor any URL - It's a state-based replacement of the entire app
- When
maintenanceModestate istrue, it replaces everything
2. Trigger is API Response
- Maintenance page appears when any API call returns 503
- The axios interceptor catches this and sets state
- This can happen on:
- Initial page load (GET /api/users/me)
- Any user action (creating transaction, loading wallets, etc.)
- Navigation between pages
3. Admin Panel is Separate
- Admin routes (
/admin/*) have@SkipMaintenance - API calls to
/api/admin/*bypass the guard - Admins can still manage the system
- But if admin tries to access main app (
/), they also see maintenance
4. Login Always Works
/auth/loginhas@SkipMaintenance- Users can still login during maintenance
- But after login, they immediately see maintenance page
📝 Summary
Where does maintenance page appear?
- ✅ After any API call that returns 503
- ✅ For regular users trying to access protected routes
- ✅ Even for admins trying to access main app (not admin panel)
- ✅ Replaces the entire app UI (not a specific route)
Where does it NOT appear?
- ❌ On login/register pages (before API calls)
- ❌ On admin panel routes (for admins)
- ❌ On health check endpoints
How to see it?
- Enable maintenance mode as admin
- Login as regular user (or stay logged in)
- Try to access any page or make any action
- Maintenance page will appear immediately