Expand production monitoring with full alert coverage for database connections, Redis memory/connections, container resources, disk usage, service health, and backup integrity. Add Alertmanager service with Slack routing for critical and warning alerts, and add automated backup verification to the pg-backup cron schedule. Update runbook with DR validation procedures and quarterly checklist. - Expand Prometheus alert rules from 4 to 24 alerts across 7 groups - Add Alertmanager container (prom/alertmanager:v0.27.0) with Slack routing - Configure inhibition rules (critical suppresses warning for same service) - Schedule automated backup verification at 04:00 UTC daily - Add Alertmanager datasource to Grafana provisioning - Update runbook with Section 9: DR Validation (automated + manual procedures) - Add SLACK_WEBHOOK_URL and Grafana vars to .env.example Co-Authored-By: Paperclip <noreply@paperclip.ing>
420 lines
12 KiB
Markdown
420 lines
12 KiB
Markdown
# GoodGo Platform - Codebase Exploration Summary
|
|
|
|
## 📋 Overview
|
|
|
|
This exploration provides a comprehensive analysis of the GoodGo Platform codebase to establish architectural patterns and best practices for building new Inquiry & Lead Management UI pages.
|
|
|
|
**Two detailed documents have been created:**
|
|
1. **`codebase_exploration.md`** - Full technical deep-dive with code samples
|
|
2. **`CODEBASE_QUICK_REFERENCE.md`** - Quick reference templates and checklists
|
|
|
|
---
|
|
|
|
## 🎯 Key Findings
|
|
|
|
### Architecture Overview
|
|
- **Frontend**: Next.js 15+ with App Router, TypeScript, Tailwind CSS
|
|
- **Backend**: NestJS with CQRS pattern, modular architecture
|
|
- **Communication**: REST API with JWT + CSRF protection
|
|
- **State Management**: Zustand + React Query
|
|
- **UI Components**: Radix UI-inspired compound components with Tailwind styling
|
|
- **i18n**: next-intl with Vietnamese (vi) and English (en)
|
|
- **Database**: Prisma ORM
|
|
|
|
### Authentication Flow
|
|
- **Cookies**: httpOnly JWT cookies (user management via `useAuthStore`)
|
|
- **CSRF**: Token-based via `XSRF-TOKEN` cookie
|
|
- **Authorization**: Role-based access (AGENT, ADMIN, USER roles)
|
|
- **Protected Routes**: `/dashboard` routes protected by JwtAuthGuard
|
|
|
|
---
|
|
|
|
## 📁 Directory Structure (Key Paths)
|
|
|
|
```
|
|
apps/web/
|
|
├── app/[locale]/
|
|
│ └── (dashboard)/ ← Place new pages here
|
|
│ ├── inquiries/ ← New: /inquiries, /inquiries/[id]
|
|
│ └── leads/ ← New: /leads, /leads/[id]
|
|
├── components/
|
|
│ ├── ui/ ← Reusable base components
|
|
│ ├── inquiries/ ← New: domain components
|
|
│ └── leads/ ← New: domain components
|
|
├── lib/
|
|
│ ├── api-client.ts ← Base fetch wrapper
|
|
│ ├── inquiries-api.ts ← New: API service
|
|
│ ├── leads-api.ts ← New: API service
|
|
│ ├── hooks/
|
|
│ │ ├── use-inquiries.ts ← New: React Query hooks
|
|
│ │ └── use-leads.ts ← New: React Query hooks
|
|
│ └── validations/ ← Zod schemas
|
|
└── messages/
|
|
├── vi.json ← Add inquiries/leads translations
|
|
└── en.json ← Add inquiries/leads translations
|
|
|
|
apps/api/src/modules/
|
|
├── inquiries/
|
|
│ ├── presentation/controllers/inquiries.controller.ts ✅ EXISTS
|
|
│ ├── presentation/dto/ ✅ EXISTS
|
|
│ └── domain/repositories/ ✅ EXISTS
|
|
└── leads/
|
|
├── presentation/controllers/leads.controller.ts ✅ EXISTS
|
|
├── presentation/dto/ ✅ EXISTS
|
|
└── domain/repositories/ ✅ EXISTS
|
|
```
|
|
|
|
---
|
|
|
|
## 🔌 Backend API Endpoints (Ready to Use)
|
|
|
|
### Inquiries Module
|
|
```
|
|
POST /api/v1/inquiries
|
|
GET /api/v1/inquiries/listing/{listingId}
|
|
GET /api/v1/inquiries/agent/me
|
|
PATCH /api/v1/inquiries/{id}/read
|
|
```
|
|
|
|
**Response Types:**
|
|
- `InquiryReadDto` - Single inquiry data
|
|
- `PaginatedResult<InquiryReadDto>` - List with pagination
|
|
|
|
### Leads Module
|
|
```
|
|
POST /api/v1/leads
|
|
GET /api/v1/leads
|
|
GET /api/v1/leads/stats
|
|
PATCH /api/v1/leads/{id}/status
|
|
DELETE /api/v1/leads/{id}
|
|
```
|
|
|
|
**Response Types:**
|
|
- `LeadReadDto` - Single lead data
|
|
- `PaginatedResult<LeadReadDto>` - List with pagination
|
|
- `LeadStatsData` - Statistics
|
|
|
|
---
|
|
|
|
## 🏗️ Patterns to Follow
|
|
|
|
### 1. Page Structure (Follow listings page pattern)
|
|
```typescript
|
|
'use client';
|
|
|
|
// Components + Hooks + Store
|
|
import { useTranslations } from 'next-intl';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { useState } from 'react';
|
|
|
|
// Layout: Header > Stats > Filters > Content
|
|
// Features: Stats cards, filter dropdowns, table/grid view, pagination
|
|
```
|
|
|
|
### 2. API Service (Use apiClient)
|
|
```typescript
|
|
// apps/web/lib/inquiries-api.ts
|
|
import { apiClient } from './api-client';
|
|
|
|
export const inquiriesApi = {
|
|
list: (params) => apiClient.get('/inquiries', params),
|
|
getById: (id) => apiClient.get(`/inquiries/${id}`),
|
|
markAsRead: (id) => apiClient.patch(`/inquiries/${id}/read`, {}),
|
|
};
|
|
```
|
|
|
|
### 3. React Query Hooks (Use key factory)
|
|
```typescript
|
|
// apps/web/lib/hooks/use-inquiries.ts
|
|
export const inquiriesKeys = {
|
|
all: ['inquiries'] as const,
|
|
list: (params) => ['inquiries', 'list', params] as const,
|
|
};
|
|
|
|
export function useInquiries(params = {}) {
|
|
return useQuery({
|
|
queryKey: inquiriesKeys.list(params),
|
|
queryFn: () => inquiriesApi.list(params),
|
|
});
|
|
}
|
|
```
|
|
|
|
### 4. Status Badge Component
|
|
```typescript
|
|
// apps/web/components/inquiries/inquiry-status-badge.tsx
|
|
// Map status enum to badge variant (success, warning, info, etc.)
|
|
```
|
|
|
|
### 5. Translations (Hierarchical JSON)
|
|
```json
|
|
{
|
|
"inquiries": {
|
|
"title": "Quản lý Liên hệ",
|
|
"status": { "new": "Mới", "read": "Đã xem" }
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 Component Library
|
|
|
|
### Base UI Components (Ready to Use)
|
|
- `Button` - Variants: default, outline, ghost, destructive
|
|
- `Card` - Compound: CardHeader, CardTitle, CardDescription, CardContent
|
|
- `Badge` - Variants: default, secondary, destructive, outline, success, warning, info
|
|
- `Table` - Compound: TableHeader, TableBody, TableRow, TableHead, TableCell
|
|
- `Select` - Native HTML with Tailwind styling
|
|
- `Input` - Text input with consistent styling
|
|
- `Textarea` - Text area with consistent styling
|
|
- `Dialog` - Modal dialog component
|
|
- `Tabs` - Tab navigation component
|
|
- `Label` - Form label component
|
|
|
|
### Styling Conventions
|
|
```typescript
|
|
// Grid layout (responsive)
|
|
className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3"
|
|
|
|
// Flex layout
|
|
className="flex items-center justify-between gap-3"
|
|
|
|
// Typography
|
|
className="text-2xl font-bold" // Heading
|
|
className="text-sm text-muted-foreground" // Secondary text
|
|
|
|
// Status indicators
|
|
className="text-green-600 bg-green-50" // Success
|
|
className="text-yellow-600 bg-yellow-50" // Warning
|
|
className="text-blue-600 bg-blue-50" // Info
|
|
```
|
|
|
|
### Theme Colors (CSS Variables)
|
|
- Primary: Green (#36A653)
|
|
- Secondary: Light gray-blue
|
|
- Accent: Light gray-blue
|
|
- Muted: Gray
|
|
- Destructive: Red
|
|
- Dark mode: Automatically inverted
|
|
|
|
---
|
|
|
|
## 🔄 Data Flow Example
|
|
|
|
```
|
|
User clicks filter
|
|
↓
|
|
setFilters(newFilters)
|
|
↓
|
|
queryKey changes
|
|
↓
|
|
React Query automatically fetches
|
|
↓
|
|
useQuery({ queryKey, queryFn: () => inquiriesApi.list(filters) })
|
|
↓
|
|
API call to /api/v1/inquiries?status=new&page=1
|
|
↓
|
|
useAuthStore provides JWT cookie + CSRF token
|
|
↓
|
|
Response: { items: [], total: 10, page: 1, limit: 20 }
|
|
↓
|
|
Component re-renders with new data
|
|
```
|
|
|
|
---
|
|
|
|
## ✅ Implementation Checklist
|
|
|
|
### Phase 1: Setup
|
|
- [ ] Create `inquiries-api.ts` in `apps/web/lib/`
|
|
- [ ] Create `leads-api.ts` in `apps/web/lib/`
|
|
- [ ] Define DTOs matching backend responses
|
|
- [ ] Test API endpoints with Postman/cURL
|
|
|
|
### Phase 2: Hooks & Queries
|
|
- [ ] Create `use-inquiries.ts` hook with React Query
|
|
- [ ] Create `use-leads.ts` hook with React Query
|
|
- [ ] Test data fetching with loading/error states
|
|
|
|
### Phase 3: Components
|
|
- [ ] Create `inquiry-status-badge.tsx` component
|
|
- [ ] Create `lead-status-badge.tsx` component
|
|
- [ ] Create filter bar / filter component
|
|
- [ ] Test components in isolation
|
|
|
|
### Phase 4: Pages
|
|
- [ ] Create `/inquiries/page.tsx` (list view)
|
|
- [ ] Create `/inquiries/[id]/page.tsx` (detail view - if needed)
|
|
- [ ] Create `/leads/page.tsx` (list view)
|
|
- [ ] Create `/leads/[id]/page.tsx` (detail view - if needed)
|
|
|
|
### Phase 5: i18n & Polish
|
|
- [ ] Add translations to `messages/vi.json`
|
|
- [ ] Add translations to `messages/en.json`
|
|
- [ ] Test all languages
|
|
- [ ] Test dark mode
|
|
- [ ] Test responsive design (mobile/tablet/desktop)
|
|
- [ ] Add loading skeletons
|
|
- [ ] Add error boundaries
|
|
- [ ] Add empty state messages
|
|
|
|
### Phase 6: Testing & QA
|
|
- [ ] Unit tests for components
|
|
- [ ] Integration tests for API calls
|
|
- [ ] E2E tests for user flows
|
|
- [ ] Performance testing (React Query caching)
|
|
- [ ] Accessibility testing (ARIA labels, keyboard nav)
|
|
|
|
---
|
|
|
|
## 📚 Reference Files
|
|
|
|
### Essential Reading
|
|
1. **Dashboard Layout** - `apps/web/app/[locale]/(dashboard)/layout.tsx`
|
|
- Responsive navigation patterns
|
|
- User info display
|
|
- Theme toggle
|
|
|
|
2. **Listings Page** - `apps/web/app/[locale]/(dashboard)/listings/page.tsx`
|
|
- Complete list view example
|
|
- Filter state management
|
|
- Grid/table view toggle
|
|
- Stats cards
|
|
- Pagination pattern
|
|
|
|
3. **Dashboard Page** - `apps/web/app/[locale]/(dashboard)/dashboard/page.tsx`
|
|
- Stats card component
|
|
- Chart integration
|
|
- Market data fetching
|
|
|
|
4. **API Client** - `apps/web/lib/api-client.ts`
|
|
- Request wrapper
|
|
- CSRF token handling
|
|
- Error handling
|
|
|
|
5. **Listings API** - `apps/web/lib/listings-api.ts`
|
|
- API service pattern
|
|
- Type definitions
|
|
- Search params handling
|
|
|
|
6. **Use Listings Hook** - `apps/web/lib/hooks/use-listings.ts`
|
|
- React Query pattern
|
|
- Key factory pattern
|
|
|
|
7. **Auth Store** - `apps/web/lib/auth-store.ts`
|
|
- Zustand pattern
|
|
- Async actions
|
|
- Error handling
|
|
|
|
8. **Comparison Store** - `apps/web/lib/comparison-store.ts`
|
|
- Zustand with persistence
|
|
- Complex state management
|
|
|
|
### Backend API Examples
|
|
- `apps/api/src/modules/inquiries/presentation/controllers/inquiries.controller.ts`
|
|
- `apps/api/src/modules/leads/presentation/controllers/leads.controller.ts`
|
|
- `apps/api/src/modules/listings/presentation/controllers/listings.controller.ts`
|
|
|
|
---
|
|
|
|
## 🛠️ Development Tips
|
|
|
|
### Local Testing
|
|
```bash
|
|
# Start frontend dev server
|
|
cd apps/web && npm run dev
|
|
|
|
# Start backend dev server (in another terminal)
|
|
cd apps/api && npm run dev
|
|
|
|
# API will be at http://localhost:3001/api/v1
|
|
# Frontend will be at http://localhost:3000
|
|
```
|
|
|
|
### API Testing
|
|
```bash
|
|
# Test inquiry list endpoint
|
|
curl -H "Authorization: Bearer {token}" \
|
|
http://localhost:3001/api/v1/inquiries/agent/me
|
|
|
|
# Test lead creation
|
|
curl -X POST \
|
|
-H "Content-Type: application/json" \
|
|
-H "Authorization: Bearer {token}" \
|
|
-d '{
|
|
"name": "John Doe",
|
|
"phone": "0912345678",
|
|
"source": "website",
|
|
"score": 80
|
|
}' \
|
|
http://localhost:3001/api/v1/leads
|
|
```
|
|
|
|
### React Query Debugging
|
|
```typescript
|
|
// Add this to see React Query state
|
|
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
|
|
|
// In provider:
|
|
<ReactQueryDevtools initialIsOpen={false} />
|
|
```
|
|
|
|
### i18n Testing
|
|
- Switch language in UI
|
|
- Verify all strings translate
|
|
- Test RTL (if adding Arabic)
|
|
|
|
---
|
|
|
|
## 🚨 Common Pitfalls to Avoid
|
|
|
|
1. **Forgetting `'use client'`** - Required for hooks (useQuery, useTranslations)
|
|
2. **Not using query key factory** - Makes cache invalidation hard
|
|
3. **Hardcoding API URLs** - Use environment variables (`NEXT_PUBLIC_API_URL`)
|
|
4. **Missing error states** - Always handle loading/error/empty states
|
|
5. **Not testing pagination** - Verify page params work correctly
|
|
6. **Forgetting translations** - Add to both vi.json and en.json
|
|
7. **Not handling 401/403 errors** - Redirect to login on auth errors
|
|
8. **Ignoring mobile responsive** - Test on all breakpoints (sm, md, lg)
|
|
9. **Not using semantic HTML** - Use proper heading hierarchy, ARIA labels
|
|
10. **Direct DOM manipulation** - Use React state/hooks instead of getElementById
|
|
|
|
---
|
|
|
|
## 📞 Contact & Questions
|
|
|
|
For implementation questions:
|
|
1. Check `codebase_exploration.md` for detailed explanations
|
|
2. Check `CODEBASE_QUICK_REFERENCE.md` for code templates
|
|
3. Reference existing pages (listings, dashboard)
|
|
4. Inspect backend DTOs for API response shapes
|
|
|
|
---
|
|
|
|
## 📄 Document Files
|
|
|
|
- **`codebase_exploration.md`** (29.8 KB)
|
|
- Complete technical deep-dive
|
|
- 10 major sections covering all aspects
|
|
- Code snippets and examples
|
|
- Architecture diagrams in text form
|
|
|
|
- **`CODEBASE_QUICK_REFERENCE.md`** (12 KB)
|
|
- Quick reference guide
|
|
- Template code snippets
|
|
- Checklists
|
|
- Key file references
|
|
- Development tips
|
|
|
|
- **`EXPLORATION_SUMMARY.md`** (This file)
|
|
- High-level overview
|
|
- Key findings summary
|
|
- Directory structure
|
|
- Implementation checklist
|
|
|
|
---
|
|
|
|
**Total Exploration:** 10 sections, 50+ code examples, 100+ file references
|
|
|
|
**Ready to start building!** 🚀
|