- Update Docker Compose configs for Redis, Typesense, and MinIO services - Update GitHub Actions deploy workflow with improved caching and steps - Extend .env.example with Stringee, Zalo OA, and FCM config keys - Update audit documentation with latest findings and recommendations - Update CHANGELOG and README with recent feature additions Co-Authored-By: Paperclip <noreply@paperclip.ing>
421 lines
12 KiB
Markdown
421 lines
12 KiB
Markdown
# Agent Public Profile Page — Complete Implementation Guide
|
|
|
|
**Last Updated:** April 11, 2026
|
|
**Status:** 📋 Exploration Complete — Ready for Implementation
|
|
**Scope:** `/agents/[id]` public profile page for GoodGo platform
|
|
|
|
---
|
|
|
|
## 📚 Documentation Index
|
|
|
|
This exploration package contains 3 comprehensive documents:
|
|
|
|
### 1. **AGENT_PROFILE_EXPLORATION.md** (21 KB)
|
|
**Comprehensive technical analysis of the entire codebase**
|
|
|
|
Contains:
|
|
- ✅ Web app structure & routing analysis
|
|
- ✅ Existing agent-related code inventory
|
|
- ✅ API endpoint design proposals
|
|
- ✅ UI component library overview
|
|
- ✅ Styling patterns & Tailwind setup
|
|
- ✅ State management & data fetching patterns
|
|
- ✅ SEO & structured data patterns
|
|
- ✅ Type definitions & interfaces
|
|
- ✅ Implementation checklist
|
|
- ✅ Key files reference guide
|
|
|
|
**Read this first** to understand the full architecture.
|
|
|
|
---
|
|
|
|
### 2. **AGENT_PROFILE_QUICK_REFERENCE.md** (10 KB)
|
|
**Quick-start guide for developers**
|
|
|
|
Contains:
|
|
- ✅ URL patterns & routing
|
|
- ✅ Backend API specification
|
|
- ✅ Frontend architecture diagram
|
|
- ✅ Data flow visualization
|
|
- ✅ Component composition guide
|
|
- ✅ API endpoints reference
|
|
- ✅ UI mockups & layouts
|
|
- ✅ Copy-paste code templates
|
|
- ✅ SEO & schema references
|
|
- ✅ 5-phase implementation timeline
|
|
- ✅ Example response structures
|
|
- ✅ Key files checklist
|
|
|
|
**Use this during development** as a handy reference.
|
|
|
|
---
|
|
|
|
### 3. **AGENT_PROFILE_CODE_EXAMPLES.md** (20 KB)
|
|
**Ready-to-use code templates for all components**
|
|
|
|
Contains:
|
|
- ✅ Backend query handler (CQRS pattern)
|
|
- ✅ Backend DTO definitions
|
|
- ✅ Backend controller endpoint
|
|
- ✅ Repository interface updates
|
|
- ✅ Prisma implementation
|
|
- ✅ Frontend API client (agents-api.ts)
|
|
- ✅ Frontend server fetch (agents-server.ts)
|
|
- ✅ Server component (page.tsx)
|
|
- ✅ Agent header component
|
|
- ✅ Agent listings section component
|
|
- ✅ Agent reviews section component
|
|
- ✅ Tailwind styling patterns
|
|
- ✅ Testing checklist
|
|
|
|
**Copy & paste these** into your actual files and customize.
|
|
|
|
---
|
|
|
|
## 🎯 Quick Start (5 Minutes)
|
|
|
|
1. **Read** `AGENT_PROFILE_QUICK_REFERENCE.md` sections:
|
|
- 🎯 Implementation Overview
|
|
- 📦 Backend Setup
|
|
- 🎨 Frontend Architecture
|
|
|
|
2. **Review** `AGENT_PROFILE_CODE_EXAMPLES.md`:
|
|
- Backend files structure
|
|
- Frontend files structure
|
|
|
|
3. **Plan** implementation in 5 phases (see quick reference)
|
|
|
|
---
|
|
|
|
## 🏗️ Architecture Summary
|
|
|
|
### Backend (NestJS)
|
|
```
|
|
New Endpoint: GET /api/v1/agents/:agentId/profile
|
|
│
|
|
├── Query: GetAgentProfileQuery
|
|
├── Handler: GetAgentProfileHandler
|
|
├── DTO: AgentPublicProfileDto
|
|
├── Repository: IAgentRepository.getPublicProfile()
|
|
└── Implementation: PrismaAgentRepository
|
|
```
|
|
|
|
### Frontend (Next.js 15)
|
|
```
|
|
Route: /agents/[id]
|
|
│
|
|
├── Page Component: [id]/page.tsx (Server)
|
|
│ ├── Metadata generation (SEO)
|
|
│ └── JSON-LD structured data
|
|
│
|
|
└── Client Component: AgentDetailClient
|
|
├── AgentHeader (profile info)
|
|
├── AgentReviewsSection (reviews & ratings)
|
|
└── AgentListingsSection (properties)
|
|
```
|
|
|
|
### Data Flow
|
|
```
|
|
1. GET /agents/[id]
|
|
2. Server fetches agent profile (ISR: 1 hour cache)
|
|
3. Generates SEO metadata
|
|
4. Renders with JSON-LD structured data
|
|
5. Client component fetches:
|
|
- Agent's listings (parallel)
|
|
- Agent's reviews (parallel)
|
|
6. Display agent profile with interactive sections
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 Implementation Phases
|
|
|
|
### Phase 1: Backend (1-2 hours)
|
|
- [ ] Create `get-agent-profile/` query handler
|
|
- [ ] Create `agent-public-profile.dto.ts`
|
|
- [ ] Update `agent.repository.ts` interface
|
|
- [ ] Implement `prisma-agent.repository.ts`
|
|
- [ ] Add endpoint to `agents.controller.ts`
|
|
- [ ] Test with Postman/curl
|
|
|
|
### Phase 2: Frontend Setup (1 hour)
|
|
- [ ] Create `lib/agents-api.ts`
|
|
- [ ] Create `lib/agents-server.ts`
|
|
- [ ] Create `/agents/[id]/` directory
|
|
- [ ] Create `/agents/[id]/page.tsx` (stub)
|
|
|
|
### Phase 3: UI Components (2-3 hours)
|
|
- [ ] Create `components/agents/` directory
|
|
- [ ] Create `agent-detail-client.tsx`
|
|
- [ ] Create `agent-header.tsx`
|
|
- [ ] Create `agent-reviews-section.tsx`
|
|
- [ ] Create `agent-listings-section.tsx`
|
|
|
|
### Phase 4: SEO & Polish (1 hour)
|
|
- [ ] Implement `generateMetadata()`
|
|
- [ ] Add JSON-LD schemas
|
|
- [ ] Mobile responsive testing
|
|
- [ ] Dark mode testing
|
|
|
|
### Phase 5: Testing & QA (1 hour)
|
|
- [ ] Manual e2e testing
|
|
- [ ] 404 handling
|
|
- [ ] ISR revalidation
|
|
- [ ] Pagination (reviews/listings)
|
|
- [ ] SEO audit (Lighthouse)
|
|
|
|
**Total Estimated Time:** 6-8 hours
|
|
|
|
---
|
|
|
|
## 🔗 Key API Endpoints
|
|
|
|
### Backend (New)
|
|
```http
|
|
GET /agents/:agentId/profile
|
|
# Returns: AgentPublicProfileDto
|
|
# Status: 200 (success), 404 (not found)
|
|
```
|
|
|
|
### Backend (Existing, Reused)
|
|
```http
|
|
GET /listings?agentId=:id&status=ACTIVE
|
|
# Get agent's active listings
|
|
|
|
GET /reviews?targetType=AGENT&targetId=:id
|
|
# Get agent reviews with pagination
|
|
|
|
GET /reviews/stats?targetType=AGENT&targetId=:id
|
|
# Get aggregate rating statistics
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 Frontend Routes
|
|
|
|
```
|
|
/ # Landing page
|
|
/agents/[id] # Agent profile (NEW)
|
|
/en/agents/[id] # English locale (NEW)
|
|
/vi/agents/[id] # Vietnamese locale (NEW)
|
|
/listings/[id] # Listing detail (EXISTING)
|
|
/search # Search page (EXISTING)
|
|
/pricing # Pricing page (EXISTING)
|
|
```
|
|
|
|
---
|
|
|
|
## 📦 Files to Create/Modify
|
|
|
|
### Backend
|
|
| File | Action | Lines |
|
|
|------|--------|-------|
|
|
| `agents/application/queries/get-agent-profile/get-agent-profile.query.ts` | CREATE | 5 |
|
|
| `agents/application/queries/get-agent-profile/get-agent-profile.handler.ts` | CREATE | 30 |
|
|
| `agents/presentation/dto/agent-public-profile.dto.ts` | CREATE | 30 |
|
|
| `agents/presentation/controllers/agents.controller.ts` | MODIFY | +20 |
|
|
| `agents/domain/repositories/agent.repository.ts` | MODIFY | +1 method |
|
|
| `agents/infrastructure/repositories/prisma-agent.repository.ts` | MODIFY | +35 |
|
|
|
|
### Frontend
|
|
| File | Action | Lines |
|
|
|------|--------|-------|
|
|
| `lib/agents-api.ts` | CREATE | 40 |
|
|
| `lib/agents-server.ts` | CREATE | 15 |
|
|
| `app/[locale]/(public)/agents/[id]/page.tsx` | CREATE | 120 |
|
|
| `components/agents/agent-detail-client.tsx` | CREATE | 30 |
|
|
| `components/agents/agent-header.tsx` | CREATE | 120 |
|
|
| `components/agents/agent-listings-section.tsx` | CREATE | 70 |
|
|
| `components/agents/agent-reviews-section.tsx` | CREATE | 100 |
|
|
|
|
**Total New Lines:** ~595
|
|
**Files Created:** 10
|
|
**Files Modified:** 3
|
|
|
|
---
|
|
|
|
## 🧪 Validation Checklist
|
|
|
|
### API Validation
|
|
- [ ] Endpoint returns 200 for valid agent
|
|
- [ ] Endpoint returns 404 for invalid agent
|
|
- [ ] Response includes all required fields
|
|
- [ ] Dates are ISO 8601 formatted
|
|
- [ ] Numbers have correct precision
|
|
|
|
### Frontend Validation
|
|
- [ ] Page loads without errors
|
|
- [ ] Metadata generates correctly
|
|
- [ ] JSON-LD validates on structured.data.org
|
|
- [ ] Mobile responsive (320px, 768px, 1024px)
|
|
- [ ] Dark mode works correctly
|
|
- [ ] ISR revalidation works
|
|
|
|
### SEO Validation
|
|
- [ ] Title tag is unique and descriptive
|
|
- [ ] Meta description is complete
|
|
- [ ] OG image displays correctly
|
|
- [ ] Canonical URL is correct
|
|
- [ ] Breadcrumb schema is valid
|
|
- [ ] LocalBusiness schema is valid
|
|
|
|
### Performance Validation
|
|
- [ ] First Contentful Paint < 2s
|
|
- [ ] Largest Contentful Paint < 2.5s
|
|
- [ ] Cumulative Layout Shift < 0.1
|
|
- [ ] Lighthouse score > 80
|
|
|
|
---
|
|
|
|
## 📊 Data Structure Reference
|
|
|
|
### Agent Public Profile Response
|
|
```typescript
|
|
{
|
|
id: string; // "clu1x2y3z4a5b6c7d8e9f0"
|
|
fullName: string; // "Nguyễn Văn A"
|
|
avatarUrl: string | null; // "https://..."
|
|
licenseNumber: string | null; // "DA123456"
|
|
agency: string | null; // "GoodGo Agency"
|
|
qualityScore: number; // 4.8
|
|
bio: string | null; // Agent description
|
|
serviceAreas: string[]; // ["quan-1", "quan-7"]
|
|
isVerified: boolean; // true
|
|
totalListings: number; // 45
|
|
activeListings: number; // 32
|
|
avgReviewRating: number; // 4.7
|
|
totalReviews: number; // 120
|
|
createdAt: string; // ISO 8601
|
|
updatedAt: string; // ISO 8601
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🔍 Key Design Decisions
|
|
|
|
1. **Routing:** Agent profiles under `(public)` group, same as listings
|
|
2. **Pattern:** Follow listing detail page pattern exactly (copy/paste approach)
|
|
3. **Data Fetching:** Server-side with ISR (1 hour revalidation)
|
|
4. **State:** Client-side useState for reviews/listings (no Zustand)
|
|
5. **Components:** Split into Page (server) + Client (interactive)
|
|
6. **SEO:** LocalBusiness JSON-LD schema for agent
|
|
7. **Styling:** Reuse existing UI components & Tailwind tokens
|
|
8. **Reviews:** Leverage existing /reviews endpoints (already public)
|
|
|
|
---
|
|
|
|
## 🚀 Getting Started
|
|
|
|
### Step 1: Read the Docs
|
|
- [ ] Read `AGENT_PROFILE_QUICK_REFERENCE.md` (10 min)
|
|
- [ ] Skim `AGENT_PROFILE_EXPLORATION.md` (20 min)
|
|
|
|
### Step 2: Backend Implementation
|
|
- [ ] Copy code from `AGENT_PROFILE_CODE_EXAMPLES.md` (Phase 1)
|
|
- [ ] Adapt to your codebase
|
|
- [ ] Test with Postman
|
|
|
|
### Step 3: Frontend Implementation
|
|
- [ ] Create directory structure
|
|
- [ ] Copy components from code examples (Phase 2-3)
|
|
- [ ] Wire up data fetching
|
|
- [ ] Add SEO metadata
|
|
|
|
### Step 4: Testing
|
|
- [ ] Manual testing
|
|
- [ ] Lighthouse audit
|
|
- [ ] E2E test (agent profile page)
|
|
|
|
---
|
|
|
|
## 💡 Implementation Tips
|
|
|
|
1. **Copy the listing detail page structure** — Agent page should be ~90% similar
|
|
2. **Reuse PropertyCard component** — For displaying agent's listings
|
|
3. **Use existing review endpoints** — Already public and don't need auth
|
|
4. **Follow i18n patterns** — Agent name/bio may need translation
|
|
5. **Test 404 handling** — When agent doesn't exist
|
|
6. **Cache agent profile** — 1 hour ISR matches listing pattern
|
|
|
|
---
|
|
|
|
## 📖 Reference Files in Codebase
|
|
|
|
### Pattern to Copy
|
|
- ✅ `app/[locale]/(public)/listings/[id]/page.tsx` — Page structure
|
|
- ✅ `components/search/property-card.tsx` — Card pattern
|
|
- ✅ `lib/listings-api.ts` — API client pattern
|
|
- ✅ `lib/listings-server.ts` — Server fetch pattern
|
|
- ✅ `components/seo/json-ld.tsx` — JSON-LD pattern
|
|
|
|
### Endpoints to Use
|
|
- ✅ `GET /listings?agentId=:id` — Existing
|
|
- ✅ `GET /reviews?targetType=AGENT` — Existing
|
|
- ✅ `GET /reviews/stats?targetType=AGENT` — Existing
|
|
|
|
### Components to Reuse
|
|
- ✅ `Card`, `CardContent` — Layout
|
|
- ✅ `Badge` — Status/stats display
|
|
- ✅ `Button` — CTAs
|
|
- ✅ `Image` — Avatar & property photos
|
|
- ✅ `PropertyCard` — Listings display
|
|
|
|
---
|
|
|
|
## ❓ FAQ
|
|
|
|
**Q: How long does this take to implement?**
|
|
A: 6-8 hours total (1-2h backend, 1h setup, 2-3h UI, 1h SEO, 1h testing)
|
|
|
|
**Q: Do I need to create new backend endpoints?**
|
|
A: Yes, 1 new endpoint: `GET /agents/:agentId/profile`. Reviews/listings endpoints already exist.
|
|
|
|
**Q: Can I reuse components from the listing page?**
|
|
A: Yes! PropertyCard, metadata generation, JSON-LD structure can all be adapted.
|
|
|
|
**Q: How do I handle pagination for listings/reviews?**
|
|
A: Use the same pagination as listing detail page (`limit`, `offset`, `page`)
|
|
|
|
**Q: What about internationalization?**
|
|
A: Agent fullName/bio come from database; use existing i18n patterns in codebase
|
|
|
|
**Q: How is SEO handled?**
|
|
A: Server-side metadata generation + LocalBusiness JSON-LD schema
|
|
|
|
---
|
|
|
|
## 📞 Support
|
|
|
|
If you have questions during implementation:
|
|
|
|
1. **Check the exploration document** — Most answers are there
|
|
2. **Review code examples** — All patterns are shown
|
|
3. **Look at existing pages** — Listing detail page is the best reference
|
|
4. **Follow the CQRS pattern** — Used throughout the API
|
|
|
|
---
|
|
|
|
## ✅ Completion Checklist
|
|
|
|
- [ ] Read all 3 documentation files
|
|
- [ ] Understand the data flow
|
|
- [ ] Plan your implementation (5 phases)
|
|
- [ ] Create directory structure
|
|
- [ ] Implement backend endpoint
|
|
- [ ] Implement frontend API client
|
|
- [ ] Create page component
|
|
- [ ] Create client components
|
|
- [ ] Add SEO metadata
|
|
- [ ] Add JSON-LD schemas
|
|
- [ ] Test manually
|
|
- [ ] Run Lighthouse audit
|
|
- [ ] Deploy & monitor
|
|
|
|
---
|
|
|
|
**Status:** 🟢 Ready to build!
|
|
|
|
Good luck with your implementation. Follow the patterns in the codebase, and you'll have a professional agent profile page up and running in a day.
|
|
|