docs: consolidate exploration & audit reports under docs/ (TEC-3094)
- Move 8 stray .md (+5 .txt) from ~/Desktop into docs/explorations/from-desktop/ - Reorganize 27 .md/.txt at workspace root: - audit reports -> docs/audits/ - exploration reports -> docs/explorations/ - design system -> docs/design-system/ - Keep only README/CHANGELOG/CONTRIBUTING/CLAUDE at repo root - Refresh docs/README.md as canonical index with links to all groups - Note: pre-existing docs/audits/AUDIT_INDEX.md and AUDIT_SUMMARY.md were overwritten by the newer root-level versions during the move Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
536
docs/explorations/UI_MAPPING_QUICK_GUIDE.md
Normal file
536
docs/explorations/UI_MAPPING_QUICK_GUIDE.md
Normal file
@@ -0,0 +1,536 @@
|
||||
# UI Mapping Quick Guide — GoodGo API Fields
|
||||
|
||||
A fast reference for wiring UI mockups to real API data. All fields with their actual types and endpoints.
|
||||
|
||||
---
|
||||
|
||||
## 🏠 Property/Listing Display
|
||||
|
||||
### Card View (Search Results)
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ [Featured Badge] 2 hrs ago │ ← listing.featuredUntil | createdAt
|
||||
├─────────────────────────────────┤
|
||||
│ $2.5B [SALE] [ACTIVE] │ ← priceVND | transactionType | status
|
||||
│ 75 m² • 2BR • 1BA • Q1, HCMC │ ← areaM2 | bedrooms | bathrooms | district
|
||||
├─────────────────────────────────┤
|
||||
│ 👁️ 342 ❤️ 28 💬 12 │ ← viewCount | saveCount | inquiryCount
|
||||
├─────────────────────────────────┤
|
||||
│ Agent: John | ⭐ 4.8 │ ← agent.user.fullName | agent.qualityScore
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
**API Fields**:
|
||||
- Price: `listing.priceVND` → format as VND
|
||||
- Type/Status: `listing.transactionType`, `listing.status`
|
||||
- Area: `property.areaM2`
|
||||
- Bedrooms: `property.bedrooms` (null = studio)
|
||||
- Bathrooms: `property.bathrooms`
|
||||
- District: `property.district`
|
||||
- Metrics: `listing.viewCount`, `listing.saveCount`, `listing.inquiryCount`
|
||||
- Agent: `listing.agent.user.fullName`, `listing.agent.qualityScore`
|
||||
|
||||
**Endpoint**: `GET /search` or search index
|
||||
|
||||
---
|
||||
|
||||
### Detail Page (Hero Section)
|
||||
```
|
||||
Main Image Carousel
|
||||
┌────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ Apartment in District 1 for $2.5B │
|
||||
│ 75 m² | 2BR 1BA | ACTIVE │
|
||||
│ │
|
||||
│ ⭐ 4.8 (234 views) | 28 saves | 12 inquiries │
|
||||
│ │
|
||||
│ [Agent: John] [Verified] [License: xxx] │
|
||||
└────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**API Fields** (from Listing + Property):
|
||||
- Title: `property.title`
|
||||
- Price: `listing.priceVND`
|
||||
- Area: `property.areaM2`
|
||||
- Beds/Baths: `property.bedrooms`, `property.bathrooms`
|
||||
- Status: `listing.status`
|
||||
- Views: `listing.viewCount`
|
||||
- Saves: `listing.saveCount`
|
||||
- Inquiries: `listing.inquiryCount`
|
||||
- Agent Name: `listing.agent.user.fullName`
|
||||
- Agent Verified: `listing.agent.isVerified`
|
||||
- License: `listing.agent.licenseNumber`
|
||||
|
||||
**Endpoint**: Individual listing API or detail endpoint
|
||||
|
||||
---
|
||||
|
||||
### Property Details Panel
|
||||
```
|
||||
LOCATION
|
||||
├─ Address: 123 Nguyen Hue, District 1, HCMC
|
||||
├─ Lat/Lng: 10.7769, 106.7009
|
||||
├─ Metro Distance: 450m
|
||||
└─ Project: [Project Name if applicable]
|
||||
|
||||
PHYSICAL
|
||||
├─ Type: APARTMENT
|
||||
├─ Area: 75 m²
|
||||
├─ Usable Area: 70 m²
|
||||
├─ Bedrooms: 2 (or Studio if -1)
|
||||
├─ Bathrooms: 1
|
||||
├─ Floors: 25 total, Unit on Floor 12
|
||||
├─ Direction: NORTHEAST
|
||||
├─ Year Built: 2020
|
||||
└─ Legal: Sở hữu lâu dài
|
||||
|
||||
AMENITIES
|
||||
├─ Furnishing: FULLY_FURNISHED
|
||||
├─ Condition: LIKE_NEW
|
||||
├─ Parking: 1 slot
|
||||
├─ Maintenance Fee: 2.5M/month
|
||||
├─ Pet Friendly: Yes
|
||||
├─ Views: Street, Park
|
||||
└─ Suitable For: Young couples, Families
|
||||
```
|
||||
|
||||
**API Fields** (all from `property`):
|
||||
- Address: `address`, `ward`, `district`, `city`
|
||||
- Coordinates: `location.lat`, `location.lng`
|
||||
- Metro: `metroDistanceM`
|
||||
- Project: `projectName`, `projectDevelopmentId`
|
||||
- Type: `propertyType`
|
||||
- Sizes: `areaM2`, `usableAreaM2`
|
||||
- Rooms: `bedrooms`, `bathrooms`
|
||||
- Levels: `floor`, `totalFloors`
|
||||
- Direction: `direction`
|
||||
- Year: `yearBuilt`
|
||||
- Legal: `legalStatus`
|
||||
- Furnishing: `furnishing`
|
||||
- Condition: `propertyCondition`
|
||||
- Parking: `parkingSlots`
|
||||
- Fee: `maintenanceFeeVND`
|
||||
- Pet: `petFriendly`
|
||||
- Views: `viewType[]`
|
||||
- Suitable: `suitableFor[]`
|
||||
|
||||
---
|
||||
|
||||
## 📊 Analytics & Market Data
|
||||
|
||||
### Market Snapshot Widget
|
||||
```
|
||||
HCMC Market Overview (Last Updated: 2 hours ago)
|
||||
┌─────────────────────────────┐
|
||||
│ Active Listings 2,345 │ ← activeCount
|
||||
│ Avg Price $2.8B │ ← avgPrice (format)
|
||||
│ Median Price $2.5B │ ← medianPrice (format)
|
||||
│ Price/m² $35M │ ← avgPricePerM2
|
||||
│ Avg Days on Mkt 45d │ ← daysOnMarket
|
||||
│ New (24h) 12 │ ← newListings24h
|
||||
│ │
|
||||
│ Price Change (24h) +2% │ ← priceChangePct.d1
|
||||
│ Price Change (7d) +5% │ ← priceChangePct.d7
|
||||
│ Price Change (30d) +12% │ ← priceChangePct.d30
|
||||
└─────────────────────────────┘
|
||||
Cache: Next update in 25 min ← nextRefreshAt
|
||||
```
|
||||
|
||||
**Endpoint**: `GET /analytics/market-snapshot?city=HCMC`
|
||||
|
||||
**Response Fields** (`MarketSnapshotDto`):
|
||||
- `activeCount`
|
||||
- `avgPrice` → convert string to number for display
|
||||
- `medianPrice`
|
||||
- `avgPricePerM2`
|
||||
- `daysOnMarket`
|
||||
- `newListings24h`
|
||||
- `priceChangePct.d1/d7/d30` → percentage values
|
||||
- `nextRefreshAt` → show "Updates in X mins"
|
||||
|
||||
---
|
||||
|
||||
### Price Trend Chart (Line)
|
||||
```
|
||||
Price Over Time (Q1 2026 - Q2 2026)
|
||||
|
||||
$4B ┌─────╮
|
||||
│ │
|
||||
$3B │ ╰──────
|
||||
│
|
||||
$2B └──────────
|
||||
Q1 Q2 Q3
|
||||
```
|
||||
|
||||
**Endpoint**: `GET /analytics/price-trend?district=Quận%201&city=HCMC&propertyType=APARTMENT`
|
||||
|
||||
**Response Fields** (`PriceTrendDto`):
|
||||
- `trend[]`:
|
||||
- `period` → x-axis label (e.g., "Q1 2026")
|
||||
- `medianPrice` → y-axis value (parse from string)
|
||||
- `avgPriceM2` → optional secondary axis
|
||||
- `totalListings` → tooltip data
|
||||
|
||||
---
|
||||
|
||||
### Heatmap (District Color Intensity)
|
||||
```
|
||||
[District] [Price/m²] [Listings] [Median Price]
|
||||
├─ D1 $45M 234 $2.8B
|
||||
├─ D2 $38M 412 $2.2B
|
||||
└─ D3 $28M 567 $1.8B
|
||||
|
||||
→ Use avgPriceM2 for color intensity
|
||||
```
|
||||
|
||||
**Endpoint**: `GET /analytics/heatmap?city=HCMC&period=2026-04`
|
||||
|
||||
**Response Fields** (`HeatmapDto`):
|
||||
- `dataPoints[]`:
|
||||
- `district` → overlay label
|
||||
- `avgPriceM2` → color intensity (higher = redder)
|
||||
- `totalListings` → hover tooltip
|
||||
- `medianPrice` → detail view
|
||||
|
||||
---
|
||||
|
||||
### District Stats Table
|
||||
```
|
||||
District Median Price Price/m² Listings Days Market YoY Change
|
||||
├─ D1 $2.8B $45M 234 42d +12%
|
||||
├─ D2 $2.2B $38M 412 48d +8%
|
||||
└─ D3 $1.8B $28M 567 52d +5%
|
||||
```
|
||||
|
||||
**Endpoint**: `GET /analytics/district-stats?city=HCMC&period=2026-04`
|
||||
|
||||
**Response Fields** (`DistrictStatsDto`):
|
||||
- `districts[]`:
|
||||
- `district` → row label
|
||||
- `medianPrice` → format as VND
|
||||
- `avgPriceM2`
|
||||
- `totalListings`
|
||||
- `daysOnMarket`
|
||||
- `yoyChange` → percentage
|
||||
|
||||
---
|
||||
|
||||
### Trending Areas Widget
|
||||
```
|
||||
🔥 Trending (Last 30 Days)
|
||||
┌────────────────────────────────────┐
|
||||
│ 1. District 1 │ ← scoreRank
|
||||
│ 📊 12 new | 45 inquiries │ ← listings | inquiries
|
||||
│ 👁️ 234 views | ↑5% price │ ← views | priceChangePct
|
||||
│ │
|
||||
│ 2. District 5 │
|
||||
│ 📊 8 new | 32 inquiries │
|
||||
│ 👁️ 156 views | ↑2% price │
|
||||
│ │
|
||||
│ 3. District 9 │
|
||||
│ 📊 15 new | 28 inquiries │
|
||||
│ 👁️ 189 views | ↓1% price │
|
||||
└────────────────────────────────────┘
|
||||
Score = inquiries×0.6 + views×0.3 + listings×0.1
|
||||
```
|
||||
|
||||
**Endpoint**: `GET /analytics/trending-areas?period=30&limit=10&level=district`
|
||||
|
||||
**Response Fields** (`TrendingAreasDto`):
|
||||
- `areas[]`:
|
||||
- `scoreRank` → ranking number
|
||||
- `name` → district name (e.g., "Quận 1")
|
||||
- `listings` → new listings count
|
||||
- `inquiries`
|
||||
- `views`
|
||||
- `priceChangePct` → YoY change or null
|
||||
|
||||
---
|
||||
|
||||
## 💰 Valuations (AVM)
|
||||
|
||||
### Quick Estimate Card
|
||||
```
|
||||
PROPERTY VALUATION (by Coordinates)
|
||||
|
||||
Estimated Value: $2.5B
|
||||
Confidence: 82% (Good)
|
||||
Price/m²: $33.3M
|
||||
Model: AVM v2 Ensemble
|
||||
|
||||
Comparable Sales (5 nearby):
|
||||
├─ 234B (apt, 75m²) - 450m away
|
||||
├─ 231B (apt, 78m²) - 520m away
|
||||
└─ 238B (apt, 72m²) - 380m away
|
||||
```
|
||||
|
||||
**Endpoint**: `GET /analytics/valuation?propertyId=prop-123` OR `POST /analytics/valuation`
|
||||
|
||||
**GET Response** (`ValuationDto`):
|
||||
- `estimatedPrice` → format as VND
|
||||
- `confidence` → 0.0-1.0, convert to percentage
|
||||
- `pricePerM2`
|
||||
- `modelVersion`
|
||||
- `comparables[]`:
|
||||
- `priceVND`
|
||||
- `areaM2`
|
||||
- `distanceMeters` → convert to distance label
|
||||
|
||||
**POST Request**:
|
||||
```json
|
||||
{
|
||||
"propertyType": "APARTMENT",
|
||||
"area": 75,
|
||||
"district": "Quận 1",
|
||||
"city": "Hồ Chí Minh",
|
||||
"bedrooms": 2,
|
||||
"bathrooms": 1,
|
||||
"yearBuilt": 2020,
|
||||
"useV2": true,
|
||||
"distanceToHospitalKm": 0.5,
|
||||
"distanceToParkKm": 1.2,
|
||||
"hasElevator": true,
|
||||
"hasParking": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Valuation History Chart
|
||||
```
|
||||
Estimated Value Over 12 Months
|
||||
|
||||
$2.8B ┌─────╮
|
||||
│ │
|
||||
$2.5B │ ╰──────
|
||||
│
|
||||
$2.2B └──────────
|
||||
Apr Aug Dec
|
||||
```
|
||||
|
||||
**Endpoint**: `GET /analytics/valuation/history/prop-123?limit=50`
|
||||
|
||||
**Response Fields**:
|
||||
- `history[]`:
|
||||
- `valuedAt` → x-axis timestamp
|
||||
- `estimatedPrice` → y-axis value (parse)
|
||||
- `confidence` → tooltip
|
||||
- `pricePerM2` → tooltip
|
||||
- `modelVersion` → metadata
|
||||
|
||||
---
|
||||
|
||||
### Property Comparison Table
|
||||
```
|
||||
Property A Property B Property C
|
||||
Value $2.5B $2.2B $2.8B
|
||||
Conf 85% 78% 92%
|
||||
/m² $33.3M $31.4M $35M
|
||||
Model v2 Ensemble v2 Ensemble v1 Standard
|
||||
|
||||
[Comparables shown for each]
|
||||
```
|
||||
|
||||
**Endpoint**: `POST /analytics/valuation/compare`
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"propertyIds": ["prop-a", "prop-b", "prop-c"]
|
||||
}
|
||||
```
|
||||
|
||||
**Response Fields**:
|
||||
- `comparisons[]`:
|
||||
- `propertyId`
|
||||
- `address`, `district`, `areaM2`
|
||||
- `valuation` (same as ValuationDto above)
|
||||
|
||||
---
|
||||
|
||||
## 🌟 Neighborhood & POIs
|
||||
|
||||
### Neighborhood Score Card
|
||||
```
|
||||
NEIGHBORHOOD SCORE
|
||||
|
||||
Overall: 78/100 ⭐⭐⭐⭐
|
||||
|
||||
├─ Education 85/100
|
||||
├─ Healthcare 92/100
|
||||
├─ Transport 78/100
|
||||
├─ Shopping 85/100
|
||||
├─ Greenery 65/100
|
||||
└─ Safety 72/100
|
||||
|
||||
POI Summary:
|
||||
├─ 3 Schools
|
||||
├─ 5 Hospitals
|
||||
├─ 2 Transit Stations
|
||||
├─ 8 Shopping Centers
|
||||
├─ 2 Parks
|
||||
└─ 12 Restaurants
|
||||
```
|
||||
|
||||
**Endpoint**: `GET /analytics/neighborhoods/Quận%201/score?city=HCMC` (PUBLIC)
|
||||
|
||||
**Response Fields** (`NeighborhoodScoreResult`):
|
||||
- `totalScore` → 0-100
|
||||
- `educationScore`, `healthcareScore`, `transportScore`, etc. → each 0-100
|
||||
- `poiCounts` → map of category→count
|
||||
- `calculatedAt` → timestamp
|
||||
|
||||
---
|
||||
|
||||
### Nearby POIs Map
|
||||
```
|
||||
Center: (10.7769, 106.7009)
|
||||
|
||||
POI Markers (within 2km):
|
||||
|
||||
🏫 School (450m)
|
||||
Name: Saigon Star International School
|
||||
Address: 123 Nguyen Hue, D1
|
||||
|
||||
🏥 Hospital (890m)
|
||||
Name: Vinmec Hospital
|
||||
Address: 458 Ly Thuong Kiet, D1
|
||||
|
||||
🛍️ Mall (1.2km)
|
||||
Name: The Landmark 81
|
||||
|
||||
🚇 Metro (680m)
|
||||
Name: Ben Thanh Station
|
||||
```
|
||||
|
||||
**Endpoint**: `GET /analytics/pois/nearby?lat=10.7769&lng=106.7009&radius=2000&limit=30` (PUBLIC)
|
||||
|
||||
**Response Fields** (`NearbyPOIsResultDto`):
|
||||
- `center`: `{lat, lng}`
|
||||
- `pois[]`:
|
||||
- `name`
|
||||
- `type` → SCHOOL, HOSPITAL, METRO_STATION, MALL, PARK, RESTAURANT, etc.
|
||||
- `category` → school | hospital | transit | shopping | restaurant | park
|
||||
- `lat`, `lng` → for map markers
|
||||
- `distance` → meters from center
|
||||
- `address`
|
||||
|
||||
---
|
||||
|
||||
## 👨💼 Agent Profile
|
||||
|
||||
### Agent Card
|
||||
```
|
||||
┌─────────────────────────────┐
|
||||
│ [Avatar] John Doe │
|
||||
│ ⭐ 4.8/5 │ ← qualityScore
|
||||
│ [Verified] [Licensed] │ ← isVerified | licenseNumber exists
|
||||
│ │
|
||||
│ License: RE-12345 │ ← licenseNumber
|
||||
│ Agency: Saigon Realty │ ← agency
|
||||
│ Response Time: 2.5 hours │ ← responseTimeAvg (seconds→hours)
|
||||
│ Deals: 42 completed │ ← totalDeals
|
||||
│ │
|
||||
│ Service Areas: │
|
||||
│ District 1, 3, 7, Binh Thanh│ ← serviceAreas[]
|
||||
│ │
|
||||
│ Bio: "10+ years experience" │ ← bio
|
||||
│ │
|
||||
│ [Message] [View Listings] │
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
**API Fields** (Agent + User):
|
||||
- Avatar: `user.avatarUrl`
|
||||
- Name: `user.fullName`
|
||||
- Rating: `qualityScore` → convert 0-100 to 0-5 stars
|
||||
- Verified Badge: `isVerified`
|
||||
- License: `licenseNumber` (display if exists)
|
||||
- Agency: `agency`
|
||||
- Response Time: `responseTimeAvg` (seconds) → format as "X.X hours"
|
||||
- Deals: `totalDeals`
|
||||
- Service Areas: `serviceAreas[]` → join with comma
|
||||
|
||||
---
|
||||
|
||||
## 📋 Listing Management
|
||||
|
||||
### Listing Status Flow
|
||||
```
|
||||
DRAFT
|
||||
↓
|
||||
PENDING_REVIEW ← re-moderation if edited while ACTIVE
|
||||
↓
|
||||
ACTIVE ← publishedAt timestamp
|
||||
↓
|
||||
RESERVED ← buyer offer
|
||||
↓
|
||||
SOLD/RENTED ← transaction complete
|
||||
|
||||
Alternative: REJECTED → DRAFT (can re-submit)
|
||||
Alternative: EXPIRED → DRAFT (can re-list)
|
||||
```
|
||||
|
||||
**Status Colors**:
|
||||
- DRAFT: Gray
|
||||
- PENDING_REVIEW: Yellow
|
||||
- ACTIVE: Green
|
||||
- RESERVED: Blue
|
||||
- SOLD: Dark Gray
|
||||
- RENTED: Dark Gray
|
||||
- EXPIRED: Orange
|
||||
- REJECTED: Red
|
||||
|
||||
---
|
||||
|
||||
### Listing Engagement Metrics
|
||||
```
|
||||
VIEWS 342 ← listing.viewCount
|
||||
SAVES 28 ← listing.saveCount
|
||||
INQUIRIES 12 ← listing.inquiryCount
|
||||
```
|
||||
|
||||
**Engagement Targets**:
|
||||
- Views → increased each time listing is viewed
|
||||
- Saves → increased when user bookmarks
|
||||
- Inquiries → increased when buyer sends inquiry
|
||||
|
||||
---
|
||||
|
||||
## 💡 Common Conversions
|
||||
|
||||
### Price Formatting
|
||||
```typescript
|
||||
// Input: priceVND = "2500000000" (string)
|
||||
const formatted = new Intl.NumberFormat('vi-VN', {
|
||||
style: 'currency',
|
||||
currency: 'VND'
|
||||
}).format(Number(priceVND));
|
||||
// Output: "2.500.000.000 ₫" or "$2.5B"
|
||||
```
|
||||
|
||||
### Confidence to Stars
|
||||
```typescript
|
||||
// Input: confidence = 0.82 (0.0-1.0)
|
||||
const stars = Math.round(confidence * 5); // 0-5 stars
|
||||
const label = confidence > 0.8 ? "High" : confidence > 0.6 ? "Good" : "Low";
|
||||
```
|
||||
|
||||
### Response Time
|
||||
```typescript
|
||||
// Input: responseTimeAvg = 9000 (seconds)
|
||||
const hours = (responseTimeAvg / 3600).toFixed(1);
|
||||
// Output: "2.5 hours"
|
||||
```
|
||||
|
||||
### Distance Display
|
||||
```typescript
|
||||
// Input: distanceMeters = 890
|
||||
const label = distanceMeters < 1000
|
||||
? `${distanceMeters}m`
|
||||
: `${(distanceMeters/1000).toFixed(1)}km`;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: April 2026
|
||||
Reference in New Issue
Block a user