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:
482
TODO_ADMIN_FEATURES.md
Normal file
482
TODO_ADMIN_FEATURES.md
Normal file
@@ -0,0 +1,482 @@
|
||||
# Admin Features TODO List
|
||||
|
||||
## 🔴 HIGH PRIORITY - Backend Implementation Required
|
||||
|
||||
### 1. Suspended User Implementation
|
||||
**Status:** ⚠️ UI Only - Backend Logic Missing
|
||||
|
||||
**Current State:**
|
||||
- ✅ UI: Suspend/Unsuspend buttons in Admin Users page
|
||||
- ✅ API: Endpoints exist (`/api/admin/users/:id/suspend`, `/api/admin/users/:id/unsuspend`)
|
||||
- ❌ **Missing:** Middleware to block suspended users from accessing the app
|
||||
|
||||
**Required Implementation:**
|
||||
```typescript
|
||||
// apps/api/src/auth/auth.guard.ts
|
||||
// Add check for suspendedAt field
|
||||
if (user.suspendedAt) {
|
||||
throw new UnauthorizedException('Your account has been suspended. Reason: ' + user.suspendedReason);
|
||||
}
|
||||
```
|
||||
|
||||
**Tasks:**
|
||||
- [ ] Add suspended user check in AuthGuard
|
||||
- [ ] Return proper error message with suspension reason
|
||||
- [ ] Test: Suspended user cannot login
|
||||
- [ ] Test: Suspended user's active sessions are invalidated
|
||||
- [ ] Frontend: Show suspension message on login attempt
|
||||
|
||||
---
|
||||
|
||||
### 2. Pro Features Implementation
|
||||
**Status:** ⚠️ UI Only - No Pro Features Defined
|
||||
|
||||
**Current State:**
|
||||
- ✅ UI: Grant Pro Access dialog in Admin Users page
|
||||
- ✅ API: Endpoint exists (`/api/admin/users/:id/grant-pro`)
|
||||
- ✅ Database: Subscription model exists
|
||||
- ❌ **Missing:** Actual pro features and restrictions
|
||||
|
||||
**Required Implementation:**
|
||||
|
||||
**A. Define Pro Features:**
|
||||
```typescript
|
||||
// Pro Features List:
|
||||
1. Unlimited wallets (Free: max 5)
|
||||
2. Unlimited transactions (Free: max 100/month)
|
||||
3. Advanced analytics & reports
|
||||
4. Export data (CSV, PDF)
|
||||
5. Multiple currencies
|
||||
6. Recurring transactions
|
||||
7. Budget planning
|
||||
8. Custom categories (Free: limited to default)
|
||||
9. API access
|
||||
10. Priority support
|
||||
```
|
||||
|
||||
**B. Create Pro Guard:**
|
||||
```typescript
|
||||
// apps/api/src/subscription/guards/pro.guard.ts
|
||||
@Injectable()
|
||||
export class ProGuard implements CanActivate {
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const request = context.switchToHttp().getRequest();
|
||||
const user = request.user;
|
||||
|
||||
// Check if user has active pro subscription
|
||||
const subscription = await this.prisma.subscription.findUnique({
|
||||
where: { userId: user.id },
|
||||
});
|
||||
|
||||
if (!subscription || subscription.status !== 'active') {
|
||||
throw new ForbiddenException('This feature requires Pro subscription');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**C. Apply Restrictions:**
|
||||
```typescript
|
||||
// Example: Limit wallets for free users
|
||||
// apps/api/src/wallets/wallets.service.ts
|
||||
async create(userId: string, data: CreateWalletDto) {
|
||||
const subscription = await this.getSubscription(userId);
|
||||
|
||||
if (!subscription || subscription.status !== 'active') {
|
||||
// Free user - check limits
|
||||
const walletCount = await this.prisma.wallet.count({
|
||||
where: { userId, deletedAt: null }
|
||||
});
|
||||
|
||||
if (walletCount >= 5) {
|
||||
throw new ForbiddenException('Free users can only create up to 5 wallets. Upgrade to Pro for unlimited wallets.');
|
||||
}
|
||||
}
|
||||
|
||||
// Create wallet...
|
||||
}
|
||||
```
|
||||
|
||||
**Tasks:**
|
||||
- [ ] Define all Pro features and free limits
|
||||
- [ ] Create ProGuard decorator
|
||||
- [ ] Apply wallet limit (5 for free users)
|
||||
- [ ] Apply transaction limit (100/month for free users)
|
||||
- [ ] Add Pro badge in frontend for Pro users
|
||||
- [ ] Show upgrade prompt when hitting limits
|
||||
- [ ] Create pricing page
|
||||
- [ ] Add "Upgrade to Pro" button in app
|
||||
|
||||
---
|
||||
|
||||
### 3. Maintenance Mode Implementation
|
||||
**Status:** ⚠️ UI Only - Backend Logic Missing
|
||||
|
||||
**Current State:**
|
||||
- ✅ UI: Toggle in Admin Settings page
|
||||
- ✅ Database: `Config` table with `maintenanceMode` key
|
||||
- ❌ **Missing:** Middleware to block users during maintenance
|
||||
|
||||
**Required Implementation:**
|
||||
|
||||
**A. Create Maintenance Middleware:**
|
||||
```typescript
|
||||
// apps/api/src/common/middleware/maintenance.middleware.ts
|
||||
@Injectable()
|
||||
export class MaintenanceMiddleware implements NestMiddleware {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async use(req: Request, res: Response, next: NextFunction) {
|
||||
// Skip for admin users
|
||||
if (req.user?.role === 'admin') {
|
||||
return next();
|
||||
}
|
||||
|
||||
// Check maintenance mode
|
||||
const config = await this.prisma.config.findUnique({
|
||||
where: { key: 'maintenanceMode' }
|
||||
});
|
||||
|
||||
if (config?.value === 'true') {
|
||||
throw new ServiceUnavailableException({
|
||||
message: 'System is under maintenance. Please try again later.',
|
||||
maintenanceMode: true
|
||||
});
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**B. Apply Globally:**
|
||||
```typescript
|
||||
// apps/api/src/main.ts
|
||||
app.use(new MaintenanceMiddleware(prisma));
|
||||
```
|
||||
|
||||
**C. Frontend Handling:**
|
||||
```typescript
|
||||
// apps/web/src/App.tsx
|
||||
// Show maintenance page when API returns 503
|
||||
if (error.response?.status === 503 && error.response?.data?.maintenanceMode) {
|
||||
return <MaintenancePage />;
|
||||
}
|
||||
```
|
||||
|
||||
**Tasks:**
|
||||
- [ ] Create MaintenanceMiddleware
|
||||
- [ ] Apply middleware globally (except admin routes)
|
||||
- [ ] Create MaintenancePage component
|
||||
- [ ] Test: Regular users blocked during maintenance
|
||||
- [ ] Test: Admin users can still access
|
||||
- [ ] Add maintenance message customization in settings
|
||||
|
||||
---
|
||||
|
||||
### 4. New User Registration Toggle Implementation
|
||||
**Status:** ⚠️ UI Only - Backend Logic Missing
|
||||
|
||||
**Current State:**
|
||||
- ✅ UI: Toggle in Admin Settings page
|
||||
- ✅ Database: `Config` table with `allowRegistration` key
|
||||
- ❌ **Missing:** Check in registration endpoint
|
||||
|
||||
**Required Implementation:**
|
||||
|
||||
**A. Add Check in Auth Service:**
|
||||
```typescript
|
||||
// apps/api/src/auth/auth.service.ts
|
||||
async register(email: string, password: string) {
|
||||
// Check if registration is allowed
|
||||
const config = await this.prisma.config.findUnique({
|
||||
where: { key: 'allowRegistration' }
|
||||
});
|
||||
|
||||
if (config?.value === 'false') {
|
||||
throw new ForbiddenException('New user registration is currently disabled. Please contact administrator.');
|
||||
}
|
||||
|
||||
// Continue with registration...
|
||||
}
|
||||
```
|
||||
|
||||
**B. Frontend Handling:**
|
||||
```typescript
|
||||
// apps/web/src/pages/Register.tsx
|
||||
// Show message if registration is disabled
|
||||
if (error.response?.data?.message?.includes('registration is currently disabled')) {
|
||||
return (
|
||||
<Alert>
|
||||
<AlertTitle>Registration Disabled</AlertTitle>
|
||||
<AlertDescription>
|
||||
New user registration is currently disabled. Please contact the administrator.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**Tasks:**
|
||||
- [ ] Add registration check in auth.service.ts
|
||||
- [ ] Update register endpoint
|
||||
- [ ] Frontend: Show disabled message
|
||||
- [ ] Test: Registration blocked when disabled
|
||||
- [ ] Test: Admin can still create users manually
|
||||
|
||||
---
|
||||
|
||||
### 5. Email Verification Requirement Implementation
|
||||
**Status:** ⚠️ UI Only - Backend Logic Missing
|
||||
|
||||
**Current State:**
|
||||
- ✅ UI: Toggle in Admin Settings page
|
||||
- ✅ Database: `Config` table with `requireEmailVerification` key
|
||||
- ✅ Database: `User.emailVerified` field exists
|
||||
- ❌ **Missing:** Enforcement in AuthGuard
|
||||
|
||||
**Required Implementation:**
|
||||
|
||||
**A. Add Check in AuthGuard:**
|
||||
```typescript
|
||||
// apps/api/src/auth/auth.guard.ts
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
// ... existing auth checks ...
|
||||
|
||||
// Check if email verification is required
|
||||
const config = await this.prisma.config.findUnique({
|
||||
where: { key: 'requireEmailVerification' }
|
||||
});
|
||||
|
||||
if (config?.value === 'true' && !user.emailVerified) {
|
||||
throw new UnauthorizedException({
|
||||
message: 'Please verify your email address to continue.',
|
||||
emailVerificationRequired: true,
|
||||
email: user.email
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
**B. Resend Verification Email:**
|
||||
```typescript
|
||||
// apps/api/src/auth/auth.controller.ts
|
||||
@Post('resend-verification')
|
||||
async resendVerification(@Body() body: { email: string }) {
|
||||
return this.authService.resendVerificationEmail(body.email);
|
||||
}
|
||||
```
|
||||
|
||||
**C. Frontend Handling:**
|
||||
```typescript
|
||||
// apps/web/src/components/EmailVerificationRequired.tsx
|
||||
// Show verification required page with resend button
|
||||
```
|
||||
|
||||
**Tasks:**
|
||||
- [ ] Add email verification check in AuthGuard
|
||||
- [ ] Create resend verification endpoint
|
||||
- [ ] Create EmailVerificationRequired component
|
||||
- [ ] Test: Unverified users blocked when required
|
||||
- [ ] Test: Resend verification email works
|
||||
- [ ] Add email verification link in emails
|
||||
|
||||
---
|
||||
|
||||
### 6. Manual Payment Verification Implementation
|
||||
**Status:** ⚠️ UI Only - Backend Logic Missing
|
||||
|
||||
**Current State:**
|
||||
- ✅ UI: Toggle in Admin Settings page
|
||||
- ✅ Database: `Config` table with `requireManualPaymentVerification` key
|
||||
- ✅ Database: `Payment.status` field exists
|
||||
- ❌ **Missing:** Payment verification workflow
|
||||
|
||||
**Required Implementation:**
|
||||
|
||||
**A. Payment Verification Endpoint:**
|
||||
```typescript
|
||||
// apps/api/src/admin/admin-payments.controller.ts
|
||||
@Post(':id/verify')
|
||||
async verifyPayment(
|
||||
@Param('id') id: string,
|
||||
@Body() body: { approved: boolean; notes?: string }
|
||||
) {
|
||||
return this.service.verifyPayment(id, body.approved, body.notes);
|
||||
}
|
||||
```
|
||||
|
||||
**B. Payment Verification Service:**
|
||||
```typescript
|
||||
// apps/api/src/admin/admin-payments.service.ts
|
||||
async verifyPayment(paymentId: string, approved: boolean, notes?: string) {
|
||||
const payment = await this.prisma.payment.findUnique({
|
||||
where: { id: paymentId },
|
||||
include: { user: true }
|
||||
});
|
||||
|
||||
if (approved) {
|
||||
// Approve payment
|
||||
await this.prisma.payment.update({
|
||||
where: { id: paymentId },
|
||||
data: {
|
||||
status: 'completed',
|
||||
verifiedAt: new Date(),
|
||||
verificationNotes: notes
|
||||
}
|
||||
});
|
||||
|
||||
// Activate subscription
|
||||
await this.activateSubscription(payment.userId, payment.planId);
|
||||
|
||||
// Send confirmation email
|
||||
await this.emailService.sendPaymentApproved(payment.user.email);
|
||||
} else {
|
||||
// Reject payment
|
||||
await this.prisma.payment.update({
|
||||
where: { id: paymentId },
|
||||
data: {
|
||||
status: 'failed',
|
||||
verifiedAt: new Date(),
|
||||
verificationNotes: notes
|
||||
}
|
||||
});
|
||||
|
||||
// Send rejection email
|
||||
await this.emailService.sendPaymentRejected(payment.user.email, notes);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**C. Payment Status Check:**
|
||||
```typescript
|
||||
// apps/api/src/payments/payments.service.ts
|
||||
async create(userId: string, data: CreatePaymentDto) {
|
||||
const config = await this.prisma.config.findUnique({
|
||||
where: { key: 'requireManualPaymentVerification' }
|
||||
});
|
||||
|
||||
const status = config?.value === 'true' ? 'pending' : 'completed';
|
||||
|
||||
const payment = await this.prisma.payment.create({
|
||||
data: {
|
||||
...data,
|
||||
userId,
|
||||
status
|
||||
}
|
||||
});
|
||||
|
||||
if (status === 'completed') {
|
||||
// Auto-activate subscription
|
||||
await this.activateSubscription(userId, data.planId);
|
||||
} else {
|
||||
// Notify admin of pending payment
|
||||
await this.notifyAdminNewPayment(payment);
|
||||
}
|
||||
|
||||
return payment;
|
||||
}
|
||||
```
|
||||
|
||||
**D. Admin UI for Verification:**
|
||||
```typescript
|
||||
// apps/web/src/components/admin/pages/AdminPayments.tsx
|
||||
// Add Verify/Reject buttons for pending payments
|
||||
<Button onClick={() => openVerifyDialog(payment.id)}>
|
||||
Verify Payment
|
||||
</Button>
|
||||
```
|
||||
|
||||
**Tasks:**
|
||||
- [ ] Create payment verification endpoints
|
||||
- [ ] Add verification logic in service
|
||||
- [ ] Create admin verification UI
|
||||
- [ ] Send email notifications (approved/rejected)
|
||||
- [ ] Test: Manual verification workflow
|
||||
- [ ] Test: Auto-approval when disabled
|
||||
- [ ] Add payment receipt upload
|
||||
|
||||
---
|
||||
|
||||
## 🟡 MEDIUM PRIORITY - UI Translation to English
|
||||
|
||||
### Admin Dashboard Pages to Translate:
|
||||
|
||||
#### 1. Dashboard (AdminDashboard.tsx)
|
||||
**Current:** Mixed Indonesian/English
|
||||
**Tasks:**
|
||||
- [ ] Convert all headings to English
|
||||
- [ ] Convert all labels to English
|
||||
- [ ] Convert all button text to English
|
||||
- [ ] Convert all chart labels to English
|
||||
- [ ] Convert all toast messages to English
|
||||
|
||||
#### 2. Plans (AdminPlans.tsx)
|
||||
**Current:** Mixed Indonesian/English
|
||||
**Tasks:**
|
||||
- [ ] Convert page title and description
|
||||
- [ ] Convert form labels
|
||||
- [ ] Convert button text
|
||||
- [ ] Convert table headers
|
||||
- [ ] Convert dialog text
|
||||
- [ ] Convert toast messages
|
||||
|
||||
#### 3. Payment Methods (AdminPaymentMethods.tsx)
|
||||
**Current:** Mixed Indonesian/English
|
||||
**Tasks:**
|
||||
- [ ] Convert page title and description
|
||||
- [ ] Convert form labels
|
||||
- [ ] Convert button text
|
||||
- [ ] Convert table headers
|
||||
- [ ] Convert dialog text
|
||||
- [ ] Convert toast messages
|
||||
|
||||
#### 4. Payments (AdminPayments.tsx)
|
||||
**Current:** Mixed Indonesian/English
|
||||
**Tasks:**
|
||||
- [ ] Convert page title and description
|
||||
- [ ] Convert filter labels
|
||||
- [ ] Convert table headers
|
||||
- [ ] Convert status badges
|
||||
- [ ] Convert dialog text
|
||||
- [ ] Convert toast messages
|
||||
|
||||
#### 5. Settings (AdminSettings.tsx)
|
||||
**Current:** Mixed Indonesian/English
|
||||
**Tasks:**
|
||||
- [ ] Convert page title and description
|
||||
- [ ] Convert section titles
|
||||
- [ ] Convert toggle labels
|
||||
- [ ] Convert button text
|
||||
- [ ] Convert toast messages
|
||||
- [ ] Convert help text
|
||||
|
||||
---
|
||||
|
||||
## 📋 Summary
|
||||
|
||||
### Backend Implementation Priority:
|
||||
1. **Suspended User** - Critical security feature
|
||||
2. **Email Verification** - Important for user management
|
||||
3. **Maintenance Mode** - Important for system updates
|
||||
4. **Registration Toggle** - Important for user management
|
||||
5. **Pro Features** - Business logic (most complex)
|
||||
6. **Manual Payment Verification** - Business logic
|
||||
|
||||
### Frontend Translation Priority:
|
||||
1. **Dashboard** - Most visible page
|
||||
2. **Settings** - Admin configuration
|
||||
3. **Payments** - Business critical
|
||||
4. **Plans** - Business critical
|
||||
5. **Payment Methods** - Business critical
|
||||
|
||||
### Estimated Time:
|
||||
- Backend Implementation: **3-5 days**
|
||||
- Frontend Translation: **2-3 hours**
|
||||
- Testing: **1-2 days**
|
||||
|
||||
**Total: ~1 week for complete implementation**
|
||||
Reference in New Issue
Block a user