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:
357
docs/explorations/from-desktop/FRONTEND_QUICK_REFERENCE.txt
Normal file
357
docs/explorations/from-desktop/FRONTEND_QUICK_REFERENCE.txt
Normal file
@@ -0,0 +1,357 @@
|
||||
╔════════════════════════════════════════════════════════════════════════════╗
|
||||
║ GOODGO PLATFORM AI - NEXT.JS FRONTEND QUICK REFERENCE ║
|
||||
╚════════════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
1. PROJECT STRUCTURE
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
/apps/web/
|
||||
├─ app/[locale]/ ← Next.js 15 App Router (public, auth, dashboard, admin)
|
||||
├─ components/ ← React components (listings, neighborhood, map, charts, design-system)
|
||||
├─ lib/ ← API clients, hooks, stores, utilities
|
||||
├─ i18n/ & messages/ ← Internationalization (vi/en)
|
||||
└─ public/ ← Static assets
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
2. CORE TECHNOLOGIES
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Framework: Next.js 15.5.14 (App Router)
|
||||
Runtime: React 18.3.0
|
||||
Styling: Tailwind CSS 3.4.0 + CVA 0.7.1
|
||||
Forms: react-hook-form 7.72.1 + Zod 4.3.6
|
||||
State: Zustand 5.0.12 (client) + React Query 5.96.2 (server)
|
||||
Mapping: Mapbox GL 3.21.0
|
||||
Charts: Recharts 3.8.1
|
||||
Icons: lucide-react 1.7.0
|
||||
i18n: next-intl 4.9.0
|
||||
Theme: next-themes 0.4.6
|
||||
Real-time: socket.io-client 4.8.3
|
||||
PDF Export: html2canvas 1.4.1 + jspdf 4.2.1
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
3. NEIGHBORHOOD FEATURES
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
COMPONENTS:
|
||||
✓ NeighborhoodPOIMap (11 KB, Mapbox GL + 6 POI categories)
|
||||
✓ NeighborhoodRadarChart (2 KB, Recharts radar, 0-10 scores, 6 categories)
|
||||
✓ NeighborhoodScore (2 KB, compact score display)
|
||||
|
||||
TYPES & CONFIG:
|
||||
✓ NeighborhoodCategory (label, score 0-10, icon)
|
||||
✓ POIItem (id, name, category, lat/lng, distance)
|
||||
✓ POICategory (school, hospital, transit, shopping, restaurant, park)
|
||||
✓ NeighborhoodScoreData (overall score, categories, POIs, center)
|
||||
|
||||
INTEGRATION:
|
||||
✓ Dynamically loaded in listing-detail-client.tsx
|
||||
✓ Part of enrichment data pipeline (API response)
|
||||
✓ Maps imported with SSR disabled for performance
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
4. MAPBOX GL USAGE
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
COMPONENTS:
|
||||
• listing-map.tsx Multiple listings + click handlers
|
||||
• location-picker.tsx Interactive location selection
|
||||
• neighborhood-poi-map.tsx POI visualization with filters
|
||||
|
||||
STYLING:
|
||||
• Light: mapbox://styles/mapbox/streets-v12
|
||||
• Dark: mapbox://styles/mapbox/dark-v11
|
||||
• Theme-aware via useMapboxStyle() hook
|
||||
|
||||
PATTERN:
|
||||
'use client' ← Must be client component
|
||||
import 'mapbox-gl/dist/mapbox-gl.css'
|
||||
const style = useMapboxStyle() ← Get theme-aware style
|
||||
new mapboxgl.Map({ style }) ← Create map instance
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
5. CHART COMPONENTS (RECHARTS)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✓ price-area-chart.tsx Trend visualization (up/down coloring)
|
||||
✓ price-trend-chart.tsx Historical trends
|
||||
✓ district-bar-chart.tsx District comparisons
|
||||
✓ district-heatmap.tsx Heat visualization (9 KB)
|
||||
✓ agent-performance.tsx Agent metrics (6 KB)
|
||||
✓ neighborhood-radar-chart.tsx Radar chart (0-10 scores)
|
||||
|
||||
PATTERN:
|
||||
ResponsiveContainer ← Responsive sizing
|
||||
CSS variables for theming ← --color-signal-up, --color-signal-down
|
||||
Custom Tooltip styling ← Themed backgrounds
|
||||
Vietnamese number formatting ← tr/k notation
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
6. API CLIENT PATTERN
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
BASE CLIENT (lib/api-client.ts):
|
||||
apiClient.get<T>(endpoint, headers?)
|
||||
apiClient.post<T>(endpoint, body?, headers?)
|
||||
apiClient.patch<T>(endpoint, body?, headers?)
|
||||
apiClient.delete<T>(endpoint, headers?)
|
||||
|
||||
FEATURES:
|
||||
✓ CSRF token handling (from cookies)
|
||||
✓ Automatic 401 refresh-and-retry (except auth endpoints)
|
||||
✓ Concurrent refresh coalescing
|
||||
✓ Type-safe with generics
|
||||
✓ Base URL from NEXT_PUBLIC_API_URL env var
|
||||
|
||||
DOMAIN-SPECIFIC CLIENTS (lib/*-api.ts):
|
||||
listings-api.ts | Listing CRUD, search
|
||||
analytics-api.ts | Market reports, heatmaps, trends
|
||||
neighborhood-api.ts | Neighborhood scoring (if exists)
|
||||
valuation-api.ts | AVM estimates
|
||||
agents-api.ts | Agent profiles
|
||||
khu-cong-nghiep-api | Industrial parks
|
||||
du-an-api.ts | Projects
|
||||
inquiries-api.ts | Inquiries
|
||||
leads-api.ts | Leads
|
||||
admin-api.ts | Admin operations
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
7. REACT QUERY HOOKS (lib/hooks/)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
PATTERN:
|
||||
const analyticsKeys = {
|
||||
all: ['analytics'] as const,
|
||||
marketReport: (city, period) => ['analytics', 'market-report', city, period] as const,
|
||||
};
|
||||
|
||||
export function useMarketReport(city: string, period: string) {
|
||||
return useQuery({
|
||||
queryKey: analyticsKeys.marketReport(city, period),
|
||||
queryFn: () => analyticsApi.getMarketReport(city, period),
|
||||
});
|
||||
}
|
||||
|
||||
AVAILABLE HOOKS:
|
||||
use-analytics.ts useMarketReport, useHeatmap, usePriceTrend, etc.
|
||||
use-listings.ts useListings, useListing
|
||||
use-khu-cong-nghiep.ts useIndustrialParks
|
||||
use-du-an.ts useProjects
|
||||
use-valuation.ts useValuation
|
||||
use-inquiries.ts useInquiries
|
||||
use-leads.ts useLeads
|
||||
use-reports.ts useReports
|
||||
use-saved-searches.ts useSavedSearches
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
8. LISTING DETAIL PAGE FLOW
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
ROUTE: /[locale]/(public)/listings/[id]/page.tsx
|
||||
|
||||
1. SERVER COMPONENT (RSC)
|
||||
├─ generateMetadata() ← SEO: OG, canonical, schema
|
||||
└─ fetchListingById(id) ← Data fetching
|
||||
|
||||
2. CLIENT COMPONENT (listing-detail-client.tsx - 39 KB)
|
||||
├─ ImageGallery ← Media slideshow
|
||||
├─ KPI Strip ← Trader-style metrics
|
||||
├─ Core Details ← Address, bedrooms, etc.
|
||||
├─ PriceHistoryChart ← Recharts trend
|
||||
├─ Neighborhood Section
|
||||
│ ├─ NeighborhoodRadarChart ← (dynamic import, SSR: false)
|
||||
│ └─ NeighborhoodPOIMap ← (dynamic import, SSR: false)
|
||||
├─ AiAdviceCards ← Personas
|
||||
├─ SimilarListings ← Recommendations
|
||||
├─ AgentCard ← Quality score
|
||||
└─ CTA Section ← Inquiry, comparison, estimate
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
9. STATE MANAGEMENT LAYERS
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
LAYER 1: REACT QUERY (Server State)
|
||||
Purpose: Fetch & cache API data
|
||||
Provider: QueryProvider (components/providers/query-provider.tsx)
|
||||
Error Handle: QueryErrorResetBoundary + custom error boundary
|
||||
Usage: useQuery, useMutation hooks
|
||||
|
||||
LAYER 2: ZUSTAND (Client State)
|
||||
Purpose: UI state, preferences
|
||||
Examples: auth-store, comparison-store, preferences-store
|
||||
Persistence: localStorage integration
|
||||
Usage: Direct store access or hooks
|
||||
|
||||
LAYER 3: CONTEXT (Global Features)
|
||||
Theme: ThemeProvider (next-themes)
|
||||
Notifications: NotificationsProvider
|
||||
Auth: AuthProvider
|
||||
Query: QueryProvider
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
10. DESIGN SYSTEM COMPONENTS
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
FINANCIAL METRICS:
|
||||
✓ kpi-card.tsx Key performance indicator
|
||||
✓ stat-card.tsx Statistics display
|
||||
✓ ticker-strip.tsx Horizontal ticker/marquee
|
||||
✓ price-delta.tsx Price change with signal
|
||||
✓ signal.tsx Up/down indicator
|
||||
✓ numeric.tsx Formatted number display
|
||||
|
||||
DATA DISPLAY:
|
||||
✓ data-table.tsx @tanstack/react-table wrapper
|
||||
✓ empty-state.tsx Empty data fallback
|
||||
✓ skeleton.tsx Loading skeleton
|
||||
✓ status-chip.tsx Status badge
|
||||
|
||||
LAYOUT:
|
||||
✓ dashboard-layout.tsx Dashboard structure
|
||||
✓ density-provider.tsx Compact/dense mode toggle
|
||||
✓ divider.tsx Visual separator
|
||||
|
||||
UI PRIMITIVES (from shadcn/ui via design-system/):
|
||||
✓ badge.tsx, button.tsx, card.tsx, dialog.tsx, etc.
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
11. INTERNATIONALIZATION (i18n)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
SETUP:
|
||||
Library: next-intl 4.9.0
|
||||
Locales: vi (Vietnamese), en (English)
|
||||
Route param: [locale] prefix
|
||||
Translations: /messages/ directory
|
||||
|
||||
USAGE:
|
||||
const t = useTranslations();
|
||||
<span>{t('key.path')}</span>
|
||||
|
||||
ROUTES:
|
||||
/vi/listings/[id] ← Vietnamese
|
||||
/en/listings/[id] ← English
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
12. PERFORMANCE OPTIMIZATIONS
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
CODE SPLITTING:
|
||||
dynamic(() => import(...), { ssr: false }) ← Heavy components (maps, charts)
|
||||
|
||||
LAZY LOADING:
|
||||
loading: () => <Fallback /> ← Show UI while loading
|
||||
|
||||
IMAGE OPTIMIZATION:
|
||||
next/image ← Built-in optimization
|
||||
|
||||
CACHING:
|
||||
React Query query keys ← Automatic deduplication & refetch intervals
|
||||
|
||||
CSS-IN-JS:
|
||||
Tailwind + CVA ← Static + composable variants
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
13. KEY FILE PATHS REFERENCE
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
NEIGHBORHOOD:
|
||||
lib/components/neighborhood/ Components
|
||||
lib/components/neighborhood/types.ts Type definitions
|
||||
lib/components/neighborhood/neighborhood-poi-map.tsx Mapbox POI layer
|
||||
lib/components/neighborhood/neighborhood-radar-chart.tsx Radar scores
|
||||
|
||||
MAPPING:
|
||||
lib/mapbox-style.ts Theme-aware styles
|
||||
lib/components/map/listing-map.tsx Listings on map
|
||||
lib/components/map/location-picker.tsx Location selection
|
||||
|
||||
CHARTS:
|
||||
lib/components/charts/ Chart components
|
||||
lib/components/charts/price-area-chart.tsx Area trend chart
|
||||
|
||||
API & STATE:
|
||||
lib/api-client.ts Base HTTP client
|
||||
lib/listings-api.ts Listings endpoints
|
||||
lib/analytics-api.ts Analytics endpoints
|
||||
lib/hooks/use-analytics.ts Analytics React Query hooks
|
||||
|
||||
LISTING DETAIL:
|
||||
app/[locale]/(public)/listings/[id]/page.tsx Server component
|
||||
lib/components/listings/listing-detail-client.tsx Client component (39 KB)
|
||||
|
||||
PROVIDERS:
|
||||
lib/components/providers/query-provider.tsx React Query setup
|
||||
lib/components/providers/theme-provider.tsx Theme management
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
14. CODING PATTERNS
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
COMPONENT FILE HEADER:
|
||||
'use client' ← Client component marker
|
||||
import ... ← External imports
|
||||
import ... ← Internal imports
|
||||
|
||||
interface ComponentProps { ... } ← Props interface
|
||||
|
||||
export function Component({ ... }: ComponentProps) {
|
||||
// implementation
|
||||
}
|
||||
|
||||
API CLIENT USAGE:
|
||||
const data = await apiClient.get<Type>('/endpoint');
|
||||
const result = await apiClient.post<Type>('/endpoint', body);
|
||||
|
||||
REACT QUERY HOOK:
|
||||
export function useData(param: string) {
|
||||
return useQuery({
|
||||
queryKey: ['key', param],
|
||||
queryFn: () => api.getData(param),
|
||||
enabled: !!param, ← Conditional queries
|
||||
});
|
||||
}
|
||||
|
||||
COMPONENT IMPORTS:
|
||||
import dynamic from 'next/dynamic';
|
||||
const Map = dynamic(() => import('...').then(m => m.Component), {
|
||||
ssr: false,
|
||||
loading: () => <LoadingState />
|
||||
});
|
||||
|
||||
ZUSTAND STORE:
|
||||
import { create } from 'zustand';
|
||||
const useStore = create((set) => ({
|
||||
value: null,
|
||||
setValue: (v) => set({ value: v }),
|
||||
}));
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
15. DEBUGGING & DEVELOPMENT TIPS
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
ENV VARS:
|
||||
NEXT_PUBLIC_API_URL ← Backend API base URL
|
||||
NEXT_PUBLIC_SITE_URL ← Frontend base URL
|
||||
MAPBOX_ACCESS_TOKEN ← Mapbox API key
|
||||
|
||||
SCRIPTS:
|
||||
npm run dev ← Start dev server (port 3000)
|
||||
npm run build ← Production build
|
||||
npm run lint ← ESLint
|
||||
npm test ← Vitest
|
||||
npm run typecheck ← TypeScript check
|
||||
|
||||
HOT TIPS:
|
||||
• Dynamic imports reduce bundle size for heavy components
|
||||
• React Query keys are the foundation of caching strategy
|
||||
• Use CSS variables for theming (see design-system/)
|
||||
• Barrel exports (index.ts) for cleaner imports
|
||||
• Zustand for simple state, React Query for server state
|
||||
• Always check enabled condition in useQuery() for dependent queries
|
||||
|
||||
╔════════════════════════════════════════════════════════════════════════════╗
|
||||
║ Report Generated: April 2026 ║
|
||||
║ Base Path: /Users/velikho/Desktop/WORKING/goodgo-platform-ai/apps/web ║
|
||||
╚════════════════════════════════════════════════════════════════════════════╝
|
||||
Reference in New Issue
Block a user