Files
goodgo-platform/docs/explorations/from-desktop/FRONTEND_EXPLORATION_REPORT.md
Ho Ngoc Hai 08b96f9c2d 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>
2026-04-21 16:29:24 +07:00

16 KiB

GoodGo Platform AI - Next.js Frontend Exploration Report

1. Overall Directory Structure

Root Layout

/Users/velikho/Desktop/WORKING/goodgo-platform-ai/apps/web/
├── app/                      # Next.js App Router directory
├── components/               # Reusable React components
├── lib/                       # API clients, hooks, utilities, stores
├── i18n/                      # Internationalization config
├── messages/                  # Translation files
├── public/                    # Static assets
├── node_modules/              # Dependencies
└── package.json               # Project metadata & dependencies

Key Dependencies (from package.json)

  • Framework: Next.js 15.5.14, React 18.3.0
  • State Management: Zustand 5.0.12 (lightweight state), @tanstack/react-query 5.96.2 (server state)
  • Forms: react-hook-form 7.72.1, @hookform/resolvers 5.2.2, zod 4.3.6
  • Mapping: mapbox-gl 3.21.0, @types/mapbox-gl 3.5.0
  • Charts: recharts 3.8.1
  • UI: Tailwind CSS 3.4.0, class-variance-authority 0.7.1
  • Icons: lucide-react 1.7.0
  • Other: next-intl 4.9.0, next-themes 0.4.6, socket.io-client 4.8.3, html2canvas + jspdf

2. App Router Structure (Next.js 15 App Router)

Directory: /app/[locale]/

Routes are organized by locale (vi/en) with multiple layout groups:

app/[locale]/
├── (public)/                 # Public routes (no auth required)
│   ├── listings/
│   │   ├── page.tsx          # Listings search/browse page
│   │   └── [id]/page.tsx     # Individual listing detail page
│   ├── search/               # Advanced search interface
│   ├── khu-cong-nghiep/      # Industrial parks (Vietnamese)
│   ├── du-an/                # Projects
│   ├── bao-cao/              # Reports
│   ├── agents/[id]/          # Agent profiles
│   └── payment/return/       # Payment callbacks
├── (auth)/                   # Authentication routes
│   ├── login/page.tsx
│   ├── register/page.tsx
│   └── auth/callback/        # OAuth callbacks (Google, Zalo)
├── (dashboard)/              # Protected routes (auth required)
│   ├── dashboard/            # Main dashboard
│   ├── analytics/            # Market analytics
│   ├── industrial-parks/     # Industrial park management
│   ├── valuation/            # Valuation service
│   ├── reports/              # User's reports
│   └── ...
├── (admin)/                  # Admin routes
│   └── admin/
│       ├── users/
│       ├── kyc/
│       ├── moderation/
│       └── ...
├── auth/callback/            # Special auth callbacks
│   ├── zalo/page.tsx
│   └── google/page.tsx
└── [locale]/layout.tsx       # Root layout wrapping all routes

3. Components Directory Structure

Organized by Domain:

components/
├── listings/                 # Listing-related components
│   ├── listing-detail-client.tsx  (39KB - main detail component)
│   ├── listing-form-steps.tsx     (14KB - form wizard)
│   ├── ai-advice-cards.tsx        (9KB - AI recommendations)
│   ├── image-gallery.tsx
│   ├── image-lightbox.tsx
│   ├── image-upload.tsx
│   ├── inquiry-modal.tsx
│   ├── price-history-chart.tsx    (uses recharts)
│   ├── social-share.tsx
│   └── sparkline.tsx
│
├── neighborhood/             # Neighborhood analysis components
│   ├── neighborhood-poi-map.tsx        (11KB - POI map with Mapbox)
│   ├── neighborhood-radar-chart.tsx    (2KB - radar chart)
│   ├── neighborhood-score.tsx          (2KB - score display)
│   ├── types.ts                        # Shared types & config
│   └── index.ts                        # Barrel export
│
├── map/                      # Map components
│   ├── listing-map.tsx       (10KB - listings on Mapbox)
│   └── location-picker.tsx   (9KB - location selection)
│
├── charts/                   # Recharts-based charts
│   ├── price-area-chart.tsx  (2KB - trend visualization)
│   ├── price-trend-chart.tsx
│   ├── district-bar-chart.tsx
│   ├── district-heatmap.tsx  (9KB - with Mapbox)
│   └── agent-performance.tsx
│
├── design-system/            # Reusable UI primitives & patterns
│   ├── badge.tsx
│   ├── kpi-card.tsx          # Key performance indicator card
│   ├── stat-card.tsx         # Statistics card
│   ├── ticker-strip.tsx      # Horizontal ticker
│   ├── price-delta.tsx       # Price change indicator
│   ├── signal.tsx            # Up/down signal display
│   ├── numeric.tsx           # Formatted number display
│   ├── status-chip.tsx
│   ├── empty-state.tsx
│   ├── skeleton.tsx
│   ├── data-table.tsx        # @tanstack/react-table wrapper
│   ├── dashboard-layout.tsx
│   ├── density-provider.tsx  # Density/compact mode
│   └── index.ts
│
├── khu-cong-nghiep/          # Industrial park domain
├── du-an/                    # Project domain
├── agents/                   # Real estate agents
├── valuation/                # Valuation/AVM features
├── search/                   # Search interface
├── comparison/               # Property comparison
├── leads/                    # Lead management
├── inquiries/                # Inquiry management
├── reports/                  # Report generation
├── chuyen-nhuong/            # Transfer/ownership change
├── notifications/
├── auth/
├── providers/                # React context providers
│   ├── auth-provider.tsx
│   ├── query-provider.tsx    # React Query with error boundary
│   ├── theme-provider.tsx    # next-themes integration
│   ├── notifications-provider.tsx
│   └── web-vitals.tsx
├── seo/                      # SEO components
│   └── json-ld.tsx           # JSON-LD schema generation
├── subscription/
├── ui/                       # Base UI components (from shadcn/ui)
│   ├── badge.tsx
│   ├── button.tsx
│   ├── card.tsx
│   ├── dialog.tsx
│   └── ... (standard shadcn components)

4. Existing Neighborhood Components

Key Files:

  • components/neighborhood/types.ts

    • NeighborhoodCategory: score category with label, score (0-10), icon
    • POIItem: Point of Interest (school, hospital, etc.) with lat/lng
    • NeighborhoodScoreData: aggregated neighborhood data
    • POI_CATEGORY_CONFIG: config for 6 categories (school, hospital, transit, shopping, restaurant, park)
    • DEFAULT_CATEGORIES: default scoring categories
  • components/neighborhood/neighborhood-poi-map.tsx

    • Uses Mapbox GL with hardcoded SVG icons for 6 POI categories
    • Category filter toggles
    • Responsive map with custom markers
    • Integrated POI display
  • components/neighborhood/neighborhood-radar-chart.tsx

    • Recharts RadarChart component
    • 0-10 score scale
    • Badge display below chart
    • Responsive, themed
  • components/neighborhood/neighborhood-score.tsx

    • Small score display component
    • Used as quick reference

Integration in Listing Detail:

  • Dynamically imported in listing-detail-client.tsx
  • Used when neighborhood data is available from API
  • Part of the enrichment data pipeline

5. Mapbox GL Integration

Setup & Styling:

  • lib/mapbox-style.ts
    export const MAPBOX_STYLE_LIGHT = 'mapbox://styles/mapbox/streets-v12';
    export const MAPBOX_STYLE_DARK = 'mapbox://styles/mapbox/dark-v11';
    
    export function useMapboxStyle(): string {
      const { theme } = useTheme();
      return theme === 'dark' ? MAPBOX_STYLE_DARK : MAPBOX_STYLE_LIGHT;
    }
    

Map Components:

  1. components/map/listing-map.tsx (10KB)

    • Displays multiple listings as markers
    • Custom markers with price popup
    • Click handler for marker selection
    • Responsive sizing
    • City coordinate presets for auto-centering
  2. components/map/location-picker.tsx (9KB)

    • Interactive location selection
    • User-clickable map for address input
    • Reverse geocoding integration
  3. components/neighborhood/neighborhood-poi-map.tsx (11KB)

    • POI visualization with category filters
    • SVG marker icons (6 types)
    • Distance display
    • Category toggle buttons

Pattern:

  • Maps created as client components ('use client')
  • Mapbox GL CSS imported per file
  • Theme-aware style selection via useMapboxStyle()
  • Responsive containers

6. API Client Setup

Main Client: lib/api-client.ts (127 lines)

// Core features:
- Base URL from environment: process.env.NEXT_PUBLIC_API_URL
- CSRF token handling from cookies
- Automatic 401 refresh-and-retry (except auth endpoints)
- Concurrent refresh coalescing
- Type-safe request/response with generics
- Credentials: include for cookies

// API methods:
apiClient.get<T>(endpoint, headers?)
apiClient.post<T>(endpoint, body?, headers?)
apiClient.patch<T>(endpoint, body?, headers?)
apiClient.delete<T>(endpoint, headers?)

Domain-Specific API Clients (in lib/):

  • listings-api.ts - Listing CRUD, search, recommendations
  • analytics-api.ts - Market reports, heatmaps, price trends
  • agents-api.ts - Agent profiles & stats
  • valuation-api.ts - AVM (Automated Valuation Model) estimates
  • khu-cong-nghiep-api.ts - Industrial park data
  • du-an-api.ts - Project data
  • inquiries-api.ts - Inquiry management
  • leads-api.ts - Lead data
  • reports-api.ts - Report generation
  • admin-api.ts - Admin operations
  • auth-api.ts - Auth endpoints
  • payment-api.ts - Payment processing

Each API module:

  • Defines request/response interfaces
  • Uses apiClient helper for HTTP calls
  • May have both client and server implementations

7. Hooks & React Query Integration

React Query Setup: lib/query-client.ts

// Creates QueryClient singleton
// Provider in components/providers/query-provider.tsx
// Includes QueryErrorResetBoundary error handling

Custom Hooks: lib/hooks/

use-analytics.ts        - Market reports, heatmaps, trends
use-khu-cong-nghiep.ts  - Industrial parks
use-du-an.ts            - Projects
use-listings.ts         - Listings data
use-valuation.ts        - AVM valuations
use-inquiries.ts        - Inquiries
use-leads.ts            - Leads
use-reports.ts          - Reports
use-saved-searches.ts   - Saved search queries
use-socket-notifications.ts - Real-time notifications

Hook Pattern (example from use-analytics.ts):

export const analyticsKeys = {
  all: ['analytics'] as const,
  marketReport: (city, period) => [...],
  // ...
};

export function useMarketReport(city: string, period: string) {
  return useQuery({
    queryKey: analyticsKeys.marketReport(city, period),
    queryFn: () => analyticsApi.getMarketReport(city, period),
  });
}

8. Chart Components

Using Recharts:

  1. components/charts/price-area-chart.tsx

    • AreaChart with gradient fills
    • Up/down signal coloring
    • Formatted Y-axis (tr/k notation for Vietnamese)
    • Responsive container
  2. components/charts/district-heatmap.tsx (9KB)

    • District-level visualization
    • Possibly Mapbox layer integration
  3. components/charts/price-trend-chart.tsx

    • Historical price trends
    • Multi-period comparison
  4. components/charts/district-bar-chart.tsx

    • Bar chart for district comparisons
  5. components/charts/agent-performance.tsx (6KB)

    • Agent metrics visualization
  6. components/listings/price-history-chart.tsx (2KB)

    • Listing-specific price history
    • Small inline chart

Recharts Pattern:

  • ResponsiveContainer for responsive sizing
  • Custom CSS variable colors (--color-signal-up, --signal-down, etc.)
  • Tooltip with custom styling
  • Dark/light theme support via CSS variables

9. Listing Detail Page Structure

Route: app/[locale]/(public)/listings/[id]/page.tsx

  • Server component (RSC) for metadata generation
  • Uses generateMetadata() for SEO (Open Graph, canonical URLs)
  • Fetches listing via fetchListingById()
  • Returns <ListingDetailClient> for interactivity

Client Component: components/listings/listing-detail-client.tsx (39KB)

Core Sections:

  1. Image Gallery - <ImageGallery>
  2. KPI Strip - Trader-style metrics (price, m², DOM, etc.)
  3. Core Details - Address, bedrooms, furnishing, etc.
  4. Price History Chart - <PriceHistoryChart>
  5. Neighborhood Section - Dynamically loaded:
    • <NeighborhoodRadarChart> (6 categories, 0-10 scores)
    • <NeighborhoodPOIMap> (POI layer)
  6. AI Advice Cards - <AiAdviceCards> with personas
  7. Similar Listings - Recommendations
  8. Agent Card - Agent quality score & info
  9. Call-to-Action - Inquiry modal, comparison, AI estimate

Key Data Types:

export interface ListingDetail {
  id: string;
  status: ListingStatus;
  transactionType: 'SALE' | 'RENT';
  priceVND: string;
  property: { title, address, bedrooms, areaM2, media[], ... };
  valuationEstimate?: { value, confidence, ... };
  neighborhoodScore?: NeighborhoodScoreData;
  agentQualityScore?: AgentQualityScore;
  similarListings?: ListingSimilarItem[];
  // ...
}

Dynamic Imports (performance):

  • NeighborhoodRadarChart - SSR disabled
  • NeighborhoodPOIMap - SSR disabled + loading fallback

10. State Management Patterns

React Query (Server State):

  • Used for API data fetching & caching
  • Query keys follow convention pattern
  • Error boundaries handle failures
  • Automatic refetch intervals for live data

Zustand Stores (Client State):

  • Examples: auth-store.ts, comparison-store.ts, preferences-store.ts
  • Lightweight, minimal boilerplate
  • Integrated with localStorage where needed

Context (Theme, Notifications):

  • ThemeProvider (via next-themes)
  • QueryProvider (React Query)
  • NotificationsProvider
  • AuthProvider

11. Key File Patterns & Conventions

Naming:

  • Pages: page.tsx in route directories
  • Layouts: layout.tsx
  • Components: PascalCase with domain prefix (e.g., NeighborhoodPOIMap)
  • API modules: *-api.ts for client-side, *-server.ts for server-side
  • Hooks: use-* pattern
  • Types: inline in files or types.ts per domain

File Organization:

  • Domain-based (listings/, neighborhood/, khu-cong-nghiep/)
  • Shared utilities in /lib and /components/design-system
  • Barrel exports with index.ts for easy importing

Code Structure:

  • 'use client' at top of client components
  • TypeScript strict mode
  • Props interfaces above component functions
  • Sub-components extracted for readability
  • Helpers defined near top-level components

12. Performance & SEO

SEO:

  • Server-side metadata generation with generateMetadata()
  • JSON-LD schema generation (components/seo/json-ld.tsx)
  • Open Graph + canonical URLs
  • Multi-language support (vi/en)

Performance:

  • Dynamic imports with code splitting (e.g., maps, heavy charts)
  • Lazy-loading fallbacks
  • Image optimization (Next.js Image component)
  • CSS-in-JS via Tailwind + CVA
  • Responsive containers for charts/maps

Internationalization:

  • next-intl for translations
  • Route segments by locale: [locale]/
  • Translations in /messages directory

Summary Table

Aspect Technology Key Files
Mapping Mapbox GL 3.21.0 components/map/, lib/mapbox-style.ts
Charts Recharts 3.8.1 components/charts/, components/neighborhood/neighborhood-radar-chart.tsx
API Client Fetch + CSRF lib/api-client.ts, lib/*-api.ts
State (Server) React Query 5.96.2 lib/query-client.ts, lib/hooks/
State (Client) Zustand 5.0.12 lib/*-store.ts
Forms react-hook-form + Zod lib/validations/
UI Tailwind + CVA components/design-system/, components/ui/
Routing Next.js App Router app/[locale]/
i18n next-intl /messages/, route [locale]/