# 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
