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:
@@ -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
|
||||
|
||||
|
||||
158
docs/planning/implementation-plan.md
Normal file
158
docs/planning/implementation-plan.md
Normal 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
|
||||
81
docs/planning/project-plan.md
Normal file
81
docs/planning/project-plan.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Tabungin — Cross‑Platform Final Plan (v1)
|
||||
|
||||
_Last updated: 11 Aug 2025_
|
||||
|
||||
---
|
||||
|
||||
## 1) Executive summary
|
||||
**Goal:** Build a **simple but flexible** cross‑platform 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 startup‑scale 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 (self‑hosted on Coolify) — no reliance on 3rd‑party DB vendors.
|
||||
- **Auth:** OIDC via **Supabase Auth** (cost‑effective, quick to set up) with mapping to our own `users` table for vendor independence.
|
||||
- **Notifications:** In‑app 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** — type‑safe queries, smooth migrations.
|
||||
- **Database hosting:** Self‑hosted 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 (built‑in first), Excel (ExcelJS, later), PDF (Playwright for server‑side render, later).
|
||||
- **Jobs/queues:** **pg-boss** (Postgres‑based) — minimal extra infra.
|
||||
- **Object storage:** Not needed for v1 (direct downloads); S3‑compatible (e.g., Cloudflare R2) later.
|
||||
- **Error tracking:** Optional for v1; add Sentry when in public beta.
|
||||
- **Date/time & validation:** date‑fns (+TZ) and Zod.
|
||||
|
||||
---
|
||||
|
||||
## 4) Single‑Dev Lean Mode Workflow
|
||||
**Purpose:** Deliver a usable cross‑platform MVP quickly without committing to full “startup‑scale” 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.
|
||||
- In‑app 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 re‑architecture.
|
||||
|
||||
---
|
||||
|
||||
## 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 sprint‑ready tickets for Phase 1.
|
||||
3) Implement in Lean Mode, keeping deferred features behind flags for future expansion.
|
||||
|
||||
203
docs/planning/project-standards.md
Normal file
203
docs/planning/project-standards.md
Normal 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
|
||||
482
docs/planning/todo-admin-features.md
Normal file
482
docs/planning/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