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:
468
docs/explorations/from-desktop/FRONTEND_EXPLORATION_REPORT.md
Normal file
468
docs/explorations/from-desktop/FRONTEND_EXPLORATION_REPORT.md
Normal file
@@ -0,0 +1,468 @@
|
||||
# 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`**
|
||||
```typescript
|
||||
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)
|
||||
```typescript
|
||||
// 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`
|
||||
```typescript
|
||||
// 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`):
|
||||
```typescript
|
||||
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:
|
||||
```typescript
|
||||
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]/` |
|
||||
|
||||
Reference in New Issue
Block a user