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
This commit is contained in:
293
docs/features/maintenance-mode.md
Normal file
293
docs/features/maintenance-mode.md
Normal file
@@ -0,0 +1,293 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user