Files
tabungin/docs/features/maintenance-mode.md
dwindown 89f881e7cf feat: reorganize admin settings with tabbed interface and documentation
- 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
2025-10-13 09:28:12 +07:00

294 lines
20 KiB
Markdown

# 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**
```typescript
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 `/maintenance` or any URL
- It's a **state-based replacement** of the entire app
- When `maintenanceMode` state is `true`, 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/login` has `@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?**
1. Enable maintenance mode as admin
2. Login as regular user (or stay logged in)
3. Try to access any page or make any action
4. Maintenance page will appear immediately