chore: cleanup root folder markdown files

- Deleted 36 old session/progress files (Oct 8-13)
- Deleted deprecated FIREBASE_SETUP.md
- Moved 4 planning documents to docs/planning/
  - PROJECT_PLAN.md → project-plan.md
  - PROJECT_STANDARDS.md → project-standards.md
  - TODO_ADMIN_FEATURES.md → todo-admin-features.md
  - IMPLEMENTATION_PLAN.md → implementation-plan.md
- Updated docs/README.md with new planning documents
- Root folder now only contains README.md
This commit is contained in:
dwindown
2025-10-13 09:37:03 +07:00
parent 89f881e7cf
commit 35e93b826a
41 changed files with 4 additions and 8105 deletions

View File

@@ -20,6 +20,10 @@ Step-by-step guides for common tasks:
Project planning and roadmap:
- [To-Do List](./planning/todo.md) - Upcoming tasks and features
- [Technical Q&A](./planning/tech-qa.md) - Technical decisions and answers
- [Project Plan](./planning/project-plan.md) - Original project plan and vision
- [Project Standards](./planning/project-standards.md) - Coding standards and conventions
- [Admin Features To-Do](./planning/todo-admin-features.md) - Admin-specific feature list
- [Implementation Plan](./planning/implementation-plan.md) - Implementation strategy
## 🚀 Quick Start

View File

@@ -0,0 +1,158 @@
# 🚀 TABUNGIN IMPLEMENTATION PLAN
**Date:** 2025-01-11
**Status:** In Progress
**Current Phase:** Admin Dashboard
---
## 📋 OVERVIEW
Tabungin is a personal finance SaaS with unique differentiators:
- 💰 Goals/Savings tracking with visual progress
- 👥 Team/Family collaboration on shared finances
- 🔑 API access for advanced users
- 💳 Flexible payment (manual + automatic)
---
## 🎯 PHASES
### Phase 1: Admin Dashboard (1 week) - CURRENT
- User management
- Dynamic plans management
- Payment methods with logos
- Payment verification
- App settings (replace .env editing)
### Phase 2: Team Feature (2-3 weeks)
- Team creation & invitations
- Shared wallets & goals
- Permission system
- Activity feed
### Phase 3: Goals Feature (2-3 weeks)
- Goal creation with images
- Multi-wallet allocation
- Progress tracking with donut charts
- Milestone notifications (25%, 50%, 75%, 100%)
- Exchange rate conversion
### Phase 4: Subscription (2 weeks)
- Manual payment flow
- Tripay integration
- Trial period (7 days)
- Grace period (3 days)
- Feature gating
- Coupon system
### Phase 5: API & Webhooks (2 weeks)
- API key generation
- Rate limiting
- Webhook system
- Usage tracking
---
## 💰 PRICING
| Feature | Free | Pro Monthly | Pro Yearly |
|---------|------|-------------|------------|
| Price | Rp 0 | Rp 49,000 | Rp 490,000 |
| Wallets | 5 | Unlimited | Unlimited |
| Goals | 3 | Unlimited | Unlimited |
| Team | ❌ | ✅ (10) | ✅ (10) |
| API | ❌ | ✅ 1000/hr | ✅ 1000/hr |
| Trial | - | 7 days | 7 days |
---
## 🗄️ DATABASE STRATEGY
**Zero Data Loss:**
- All new fields nullable or have defaults
- Additive migrations only
- No destructive changes
- Backward compatible
**New Models:**
- Plan, Subscription, Payment, PaymentMethod, Coupon
- Goal, GoalAllocation, GoalMilestone
- Team, TeamMember, TeamInvitation
- ApiKey, ApiKeyUsage, Webhook, WebhookDelivery
- AppConfig
**Modified:**
- User: add role, phone, suspendedAt
- Wallet: add teamId
---
## 🔐 SECURITY
- Admin routes: `/admin/*`
- JWT with role claim
- API keys hashed
- Internal DB URL in production
- Encrypted sensitive config
- Audit logging
---
## 📝 ADMIN SEEDER DATA
**Admin Account:**
- Email: (provide)
- Name: Dwindi Ramadhana
- Password: (provide or auto-generate)
**Default Plans:**
- Free: Rp 0, 5 wallets, 3 goals
- Pro Monthly: Rp 49,000, unlimited
- Pro Yearly: Rp 490,000, unlimited
**Payment Methods:**
- BCA, Mandiri, GoPay, OVO (placeholder data)
---
## ✅ PROGRESS
**Completed:**
- [x] Auth (email + Google OAuth)
- [x] OTP/2FA
- [x] Wallets & Transactions
- [x] Categories
- [x] Theme system
- [x] Filters & routing
**Current:**
- [ ] Phase 1: Admin Dashboard
- [x] Schema migration ✅
- [x] Seeder ✅
- [x] Backend ✅
- [x] Admin Guard
- [x] JWT Role Support
- [x] Plans CRUD
- [x] Payment Methods CRUD
- [x] Payments Verification
- [x] Users Management
- [x] App Config
- [ ] Frontend (IN PROGRESS - 50%)
- [x] Admin Layout
- [x] Dashboard
- [x] Plans Management (70%)
- [x] Users Management (90%)
- [ ] Payment Methods
- [ ] Payment Verification
- [ ] App Settings
**Next:**
- [ ] Phase 2: Team
- [ ] Phase 3: Goals
- [ ] Phase 4: Subscription
- [ ] Phase 5: API
---
**Last Updated:** 2025-01-11

View File

@@ -0,0 +1,81 @@
# Tabungin — CrossPlatform Final Plan (v1)
_Last updated: 11 Aug 2025_
---
## 1) Executive summary
**Goal:** Build a **simple but flexible** crossplatform personal finance app (web, desktop via Tauri, Android via Tauri Mobile) with a freemium model. Core features: money wallets, transactions (incl. recurring), basic reports. Premium priorities (in order): **Assets**, **Exports**, **API/Webhooks**.
**Principles:** One backend for all clients; one shared UI + core logic; thin platform shells; OIDC-based login that works everywhere; data consistency within 10s across devices. Keep the stack lean to avoid unnecessary complexity or startupscale overhead.
---
## 2) Architecture overview
- **Clients:**
- Web SPA (client-side pages) / optional PWA
- Desktop app (Tauri) for Win/macOS/Linux
- Android app (Tauri Mobile); iOS later if needed
- **Shared packages:**
- `packages/core` — domain models, currency math, recurrence engine, validations (TS)
- `packages/ui` — React components/screens, theming, accessibility
- **Backend:** NestJS (Node + TypeScript). REST API with typed SDK. Jobs/queues for recurring txns, price updates, exports, and notifications.
- **Database:** PostgreSQL (selfhosted on Coolify) — no reliance on 3rdparty DB vendors.
- **Auth:** OIDC via **Supabase Auth** (costeffective, quick to set up) with mapping to our own `users` table for vendor independence.
- **Notifications:** Inapp center + Email; other channels (Web Push, Desktop OS, Android Push) can be added later.
---
## 3) Technology choices (finalized for v1)
- **Frontend:** React + Tailwind CSS.
- **Desktop/Mobile shell:** Tauri v2.
- **Backend framework:** **NestJS** — opinionated structure, modular, maintainable.
- **ORM & schema:** **Prisma** — typesafe queries, smooth migrations.
- **Database hosting:** Selfhosted PostgreSQL on Coolify.
- **Email delivery:** Elastic Email (API-based) with backend webhook support for bounces/complaints; fallback to SMTP if desired.
- **Charting library:** **Recharts**.
- **Export libraries:** CSV (builtin first), Excel (ExcelJS, later), PDF (Playwright for serverside render, later).
- **Jobs/queues:** **pg-boss** (Postgresbased) — minimal extra infra.
- **Object storage:** Not needed for v1 (direct downloads); S3compatible (e.g., Cloudflare R2) later.
- **Error tracking:** Optional for v1; add Sentry when in public beta.
- **Date/time & validation:** datefns (+TZ) and Zod.
---
## 4) SingleDev Lean Mode Workflow
**Purpose:** Deliver a usable crossplatform MVP quickly without committing to full “startupscale” complexity.
**Keep for v1:**
- Web SPA as the first client; desktop shell added once web is stable.
- NestJS backend + Prisma with Postgres on Coolify.
- Supabase Auth (OIDC) → local `users` table mapping.
- Inapp notifications.
- Elastic Email API for critical notices.
- CSV export (inline download).
- Simple recurring engine (pg-boss).
**Defer to later:**
- Mobile shell (after desktop parity).
- Push notifications (Web, Desktop OS, Android FCM).
- PDF/Excel exports.
- Object storage.
- Public API + webhooks.
- Sentry and advanced monitoring.
**Benefit:** Lower development overhead, fewer vendors, faster iteration. All deferred features are planned so they can be slotted in without rearchitecture.
---
## 5) Roadmap & acceptance criteria
- **Phase 1:** Web MVP (auth, wallets, transactions, recurrences, basic reports, CSV export, email notices).
- **Phase 2:** Desktop app (Tauri) with parity.
- **Phase 3:** Android app (Tauri Mobile) with local notifications.
- **Phase 4:** Premium features (Assets → Exports → API/Webhooks) + extra notification channels.
---
## 6) Next steps
1) Finalize Elastic Email API integration + webhook handling.
2) Prepare sprintready tickets for Phase 1.
3) Implement in Lean Mode, keeping deferred features behind flags for future expansion.

View File

@@ -0,0 +1,203 @@
# Tabungin Project Standards
## 🌐 Multilingual Support (COMPLETED)
### Languages Supported:
-**English (EN)** - Full translation
-**Indonesian (ID)** - Full translation (Default)
### Implementation:
- **Location:** `/apps/web/src/locales/`
- `en.ts` - English translations
- `id.ts` - Indonesian translations
- **Context:** `LanguageContext.tsx` - Language state management
- **Component:** `LanguageToggle.tsx` - Language switcher UI
- **Usage:** `const { t } = useLanguage()` then `t.section.key`
### Translation Structure:
```typescript
{
nav: { ... },
overview: { ... },
wallets: { ... },
transactions: { ... },
profile: { ... },
walletDialog: { ... },
transactionDialog: { ... },
dateRange: { ... }
}
```
### Rules:
1.**ALL user-facing text MUST use translations** - No hardcoded strings
2.**Both EN and ID must have identical keys** - Type-safe with TypeScript
3.**Toast messages use translations** - `toast.success(t.section.key)`
4.**Error messages use translations** - Consistent UX
---
## 🎨 UI Component Library (COMPLETED)
### Framework: **shadcn/ui**
- Built on Radix UI primitives
- Tailwind CSS styling
- Fully customizable components
### Components Used:
- ✅ Button, Input, Label, Badge
- ✅ Card, Alert, Separator, Tabs
- ✅ Dialog, Drawer (Responsive)
- ✅ Select, Popover, Calendar
- ✅ Sidebar, Breadcrumb
- ✅ Toast (Sonner)
### Styling Convention:
- **Tailwind CSS** for all styling
- **Dark mode support** via `useTheme` hook
- **Responsive design** with `md:`, `lg:` breakpoints
---
## 📱 Mobile UI/UX Optimization (COMPLETED ✅)
### Status:
-**Profile Page** - Fully optimized
-**Overview Page** - Fully optimized
-**Wallets Page** - Fully optimized
-**Transactions Page** - Fully optimized
-**Responsive Dialogs** - Desktop (Dialog) / Mobile (Drawer)
### Mobile Standards:
#### 1. Touch Target Sizes
- **Buttons:** `h-11` (44px) on mobile, `h-10` on desktop
- **Inputs:** `h-11` (44px) on mobile, `h-10` on desktop
- **Minimum width:** `min-w-[100px]` for buttons
- **Padding:** `px-6` on mobile, `px-4` on desktop
#### 2. Typography
- **Inputs/Labels:** `text-base` (16px) on mobile to prevent iOS zoom
- **Desktop:** `text-sm` (14px) for compact layout
- **Responsive:** `text-base md:text-sm`
#### 3. Spacing
- **Form fields:** `space-y-3` on mobile, `space-y-2` on desktop
- **Touch targets:** Minimum 8px gap between tappable elements
- **Padding:** More generous on mobile (`p-6` vs `p-4`)
#### 4. Responsive Patterns
```tsx
// Button sizing
<Button className="h-11 md:h-9 px-6 md:px-4 text-base md:text-sm">
// Input sizing
<Input className="h-11 md:h-9 text-base md:text-sm" />
// Label sizing
<Label className="text-base md:text-sm">
// Spacing
<div className="space-y-3 md:space-y-2">
```
#### 5. Responsive Dialog/Drawer
- **Desktop (≥768px):** Uses `Dialog` (modal)
- **Mobile (<768px):** Uses `Drawer` (bottom sheet)
- **Component:** `ResponsiveDialog` wrapper
- **Usage:** Replace `Dialog` with `ResponsiveDialog`
---
## 🏗️ Architecture Standards
### Frontend Structure:
```
/apps/web/src/
├── components/
│ ├── dialogs/ # Form dialogs (Wallet, Transaction)
│ ├── layout/ # Layout components (Sidebar, Dashboard)
│ ├── pages/ # Page components (Overview, Profile, etc.)
│ └── ui/ # shadcn components
├── contexts/ # React contexts (Auth, Language, Theme)
├── hooks/ # Custom hooks
├── locales/ # Translation files (en.ts, id.ts)
└── lib/ # Utilities
```
### Backend Structure:
```
/apps/api/src/
├── auth/ # Authentication module
├── users/ # User management
├── wallets/ # Wallet CRUD
├── transactions/ # Transaction CRUD
├── otp/ # OTP verification (Email, WhatsApp, TOTP)
└── prisma/ # Database client
```
---
## 📋 Development Checklist for New Pages
When creating a new page, ensure:
### ✅ Multilingual
- [ ] All text uses `t.section.key` from translations
- [ ] Both `en.ts` and `id.ts` have matching keys
- [ ] Toast messages are translated
- [ ] Error messages are translated
### ✅ UI Components
- [ ] Uses shadcn/ui components
- [ ] Follows existing design patterns
- [ ] Dark mode compatible
### ✅ Mobile Optimization
- [ ] Buttons: `h-11 md:h-9 px-6 md:px-4 text-base md:text-sm`
- [ ] Inputs: `h-11 md:h-9 text-base md:text-sm`
- [ ] Labels: `text-base md:text-sm`
- [ ] Spacing: `space-y-3 md:space-y-2`
- [ ] Dialogs use `ResponsiveDialog` component
- [ ] Touch targets meet 44px minimum
- [ ] Tested on mobile viewport
### ✅ Code Quality
- [ ] TypeScript strict mode passing
- [ ] No lint errors/warnings
- [ ] Follows existing patterns
- [ ] Proper error handling
---
## 🎯 Next Steps
### Completed:
1. Profile page mobile optimization
2. Overview page mobile optimization
3. Wallets page mobile optimization
4. Transactions page mobile optimization
5. WhatsApp number validation
6. Language toggle moved to header
7. Responsive Dialog/Drawer system
### Future Enhancements:
- [ ] Add more languages (if needed)
- [ ] Improve loading states
- [ ] Add skeleton loaders
- [ ] Optimize performance
- [ ] Add E2E tests
---
## 📝 Notes
- **Default Language:** Indonesian (ID)
- **Theme:** Light/Dark mode support
- **Responsive Breakpoint:** 768px (md)
- **Touch Target Standard:** 44px (Apple HIG & Material Design)
- **Font Size (Mobile):** 16px minimum to prevent iOS zoom
---
**Last Updated:** October 12, 2025
**Status:** Mobile optimization in progress

View 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**