# Báo Cáo Khám Phá Frontend Nền Tảng GoodGo ## apps/web (Next.js 15 với App Router) **Ngày:** 9 tháng 4, 2026 **Trạng thái:** Chưa có i18n (Không phát hiện cấu hình i18n nào) **Phiên bản Next.js:** 15.5.14 | **React:** 18.3.0 **Ngôn ngữ chính:** Tiếng Việt (vi_VN) --- ## 📁 Tổng Quan Cấu Trúc Thư Mục ``` apps/web/ ├── app/ # Next.js App Router (ứng dụng chính) │ ├── layout.tsx # Layout gốc với metadata & providers │ ├── globals.css # Style Tailwind toàn cục & biến theme │ ├── middleware.ts # Đã có sẵn (middleware định tuyến xác thực) │ ├── loading.tsx # Trạng thái tải gốc │ ├── error.tsx # Xử lý lỗi gốc │ ├── not-found.tsx # Trang 404 │ │ │ ├── (public)/ # Nhóm route công khai │ │ ├── layout.tsx # Layout công khai với header/footer │ │ ├── page.tsx # Trang đích (hero + danh sách nổi bật) │ │ ├── search/ # Trang kết quả tìm kiếm │ │ │ ├── page.tsx │ │ │ ├── layout.tsx │ │ │ ├── error.tsx │ │ │ ├── loading.tsx │ │ │ └── __tests__/ │ │ └── listings/[id]/ # Trang chi tiết tin đăng │ │ └── page.tsx │ │ │ ├── (auth)/ # Nhóm route xác thực │ │ ├── layout.tsx │ │ ├── login/page.tsx # Form đăng nhập │ │ ├── register/page.tsx # Form đăng ký │ │ ├── error.tsx │ │ ├── loading.tsx │ │ └── __tests__/ │ │ │ ├── (dashboard)/ # Nhóm route dashboard được bảo vệ │ │ ├── layout.tsx # Layout dashboard với thanh điều hướng bên │ │ ├── dashboard/page.tsx # Dashboard chính │ │ ├── listings/ │ │ │ ├── page.tsx # Danh sách tin đăng của người dùng │ │ │ ├── new/page.tsx # Tạo tin đăng (form nhiều bước) │ │ │ └── [id]/edit/page.tsx │ │ ├── analytics/page.tsx │ │ ├── profile/page.tsx # Cài đặt hồ sơ người dùng │ │ ├── subscription/page.tsx # Gói đăng ký │ │ ├── payments/page.tsx # Lịch sử thanh toán │ │ ├── valuation/page.tsx # Định giá bất động sản bằng AI │ │ ├── error.tsx │ │ ├── loading.tsx │ │ └── __tests__/ │ │ │ ├── (admin)/ # Nhóm route quản trị │ │ ├── layout.tsx │ │ ├── admin/page.tsx # Dashboard quản trị │ │ ├── admin/users/page.tsx │ │ ├── admin/kyc/page.tsx │ │ ├── admin/moderation/page.tsx │ │ ├── error.tsx │ │ └── loading.tsx │ │ │ ├── auth/ # Callback xác thực │ │ └── callback/ │ │ ├── google/page.tsx │ │ └── zalo/page.tsx │ │ │ ├── api/ # Route API │ │ └── health/route.ts │ │ │ ├── robots.ts │ └── sitemap.ts │ ├── components/ # Các component React tái sử dụng │ ├── providers/ # Context providers │ │ ├── auth-provider.tsx # Context xác thực & wrapper store │ │ ├── query-provider.tsx # Provider TanStack React Query │ │ └── theme-provider.tsx # Provider chế độ tối/sáng │ │ │ ├── ui/ # Các component UI cơ sở không có style │ │ ├── button.tsx # Biến thể button dựa trên CVA │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── card.tsx │ │ ├── dialog.tsx # Hộp thoại modal │ │ ├── tabs.tsx │ │ ├── select.tsx # Component select tùy chỉnh │ │ ├── badge.tsx │ │ ├── textarea.tsx │ │ ├── table.tsx │ │ └── __tests__/ # Test component │ │ │ ├── auth/ │ │ └── oauth-buttons.tsx # Nút OAuth Google & Zalo │ │ │ ├── search/ │ │ ├── filter-bar.tsx # Bộ lọc tìm kiếm (loại giao dịch, bất động sản, khoảng giá) │ │ ├── property-card.tsx # Thẻ danh sách bất động sản │ │ └── search-results.tsx # Container kết quả tìm kiếm │ │ │ ├── listings/ │ │ ├── listing-form-steps.tsx # Form tạo/chỉnh sửa nhiều bước │ │ ├── image-upload.tsx # Component tải ảnh lên │ │ ├── image-gallery.tsx # Trình xem thư viện ảnh │ │ └── listing-status-badge.tsx # Badge hiển thị trạng thái │ │ │ ├── map/ │ │ └── listing-map.tsx # Tích hợp Mapbox GL │ │ │ ├── valuation/ │ │ ├── valuation-form.tsx │ │ ├── valuation-results.tsx │ │ ├── valuation-history.tsx │ │ └── ai-estimate-button.tsx │ │ │ └── charts/ │ ├── price-trend-chart.tsx │ ├── agent-performance.tsx │ └── district-heatmap.tsx │ ├── lib/ # Tiện ích và hooks │ ├── utils.ts # cn() - clsx + tailwind-merge │ ├── auth-store.ts # Quản lý trạng thái xác thực Zustand │ ├── api-client.ts # Wrapper Axios/fetch │ ├── query-client.ts # Cấu hình TanStack React Query │ │ │ ├── hooks/ │ │ ├── use-listings.ts │ │ ├── use-analytics.ts │ │ ├── use-valuation.ts │ │ ├── use-payments.ts │ │ └── use-subscription.ts │ │ │ ├── validations/ # Schema Zod │ │ ├── auth.ts # Schema đăng nhập/đăng ký │ │ ├── listings.ts # Schema tin đăng nhiều bước │ │ └── valuation.ts │ │ │ ├── *-api.ts # Các API client │ │ ├── auth-api.ts │ │ ├── listings-api.ts │ │ ├── profile-api.ts │ │ ├── payment-api.ts │ │ ├── subscription-api.ts │ │ ├── analytics-api.ts │ │ ├── valuation-api.ts │ │ └── admin-api.ts │ │ │ └── __tests__/ # Unit test (Vitest + React Testing Library) │ ├── auth-store.spec.ts │ ├── auth-validations.spec.ts │ ├── listing-validations.spec.ts │ └── utils.spec.ts │ ├── public/ # Tài nguyên tĩnh │ └── [images, icons, etc.] │ ├── .next/ # Đầu ra build (được tạo tự động) ├── node_modules/ │ └── Tệp Cấu Hình: ├── package.json # Phụ thuộc & scripts ├── next.config.js # Cấu hình Next.js (Sentry, CSP, headers) ├── tailwind.config.ts # Cấu hình Tailwind CSS ├── postcss.config.js # Cấu hình PostCSS (Tailwind + Autoprefixer) ├── tsconfig.json # Cấu hình TypeScript (kế thừa base) ├── vitest.config.ts # Cấu hình framework kiểm thử ├── vitest.setup.ts # Thiết lập kiểm thử ├── middleware.ts # Middleware định tuyến xác thực ├── sentry.*.config.ts # Theo dõi lỗi Sentry (3 tệp) ├── instrumentation.ts # Instrumentation phía server └── global.d.ts # Định nghĩa TypeScript toàn cục ``` --- ## 📦 Phụ Thuộc Package.json ### Phụ Thuộc Production: ```json { "@hookform/resolvers": "^5.2.2", // Resolver xác thực form "@sentry/nextjs": "^10.47.0", // Theo dõi lỗi "@tanstack/react-query": "^5.96.2", // Lấy dữ liệu & bộ nhớ đệm "class-variance-authority": "^0.7.1", // Tiện ích biến thể component "clsx": "^2.1.1", // Tiện ích tên class "lucide-react": "^1.7.0", // Thư viện icon "mapbox-gl": "^3.21.0", // Thư viện bản đồ "next": "^14.2.0", // Framework "react": "^18.3.0", "react-dom": "^18.3.0", "react-hook-form": "^7.72.1", // Quản lý trạng thái form "recharts": "^3.8.1", // Thư viện biểu đồ "tailwind-merge": "^3.5.0", // Giải quyết xung đột Tailwind "zod": "^4.3.6", // Xác thực schema "zustand": "^5.0.12" // Quản lý trạng thái nhẹ } ``` ### Phụ Thuộc Dev (bao gồm kiểm thử): ```json { "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", "@vitejs/plugin-react": "^4.7.0", "vitest": "^4.1.3", "tailwindcss": "^3.4.0", "tailwindcss-animate": "^1.0.7", "msw": "^2.13.2", // Mock Service Worker "typescript": "^6.0.2" } ``` --- ## 🎯 Layout Gốc (app/layout.tsx) ### Triển Khai Hiện Tại: - **Ngôn ngữ HTML:** `lang="vi"` (Tiếng Việt được mã hóa cứng) - **Cấu trúc Metadata:** Tiêu đề & mô tả bằng tiếng Việt - **OpenGraph:** Locale đặt là `vi_VN` - **Providers xếp chồng:** `ThemeProvider → QueryProvider → AuthProvider` - **Khả năng tiếp cận:** Bao gồm liên kết bỏ qua đến nội dung chính (đã tuân thủ A11y) - **Màu theme:** `#15803d` (xanh lá chính) ### Metadata Hiện Tại: ```javascript title: 'GoodGo — Nền tảng Bất động sản Việt Nam' description: 'GoodGo — nền tảng bất động sản thông minh tại Việt Nam...' openGraph: { locale: 'vi_VN', ... } ``` --- ## 🔐 Middleware (middleware.ts) ### Định Tuyến Xác Thực Hiện Tại: ```typescript - Public paths: /login, /register, /search, /auth/callback, / (root) - Protected paths: Anything else requires 'goodgo_authenticated' cookie - Auth-only paths: /login, /register (redirects to /dashboard if authenticated) - Redirect param: Adds ?redirect=[original-path] on unauthorized access ``` **Các Điểm Nhập Quan Trọng Cần Cập Nhật Cho i18n:** - Cần phát hiện tiền tố locale (ví dụ: `/en/dashboard`, `/vi/dashboard`) - Phát hiện locale qua cookie/header --- ## 🎨 Cấu Hình Tailwind ### Thiết Lập Theme (tailwind.config.ts): ```typescript - Dark mode: 'class' based - Content paths: ./app/**, ./components/**, ./lib/** - Colors: HSL-based CSS variables (--primary, --secondary, etc.) - Border radius: Customizable via --radius CSS variable - Animation plugin: tailwindcss-animate ``` ### Style Toàn Cục (app/globals.css): - **Biến CSS:** Bảng màu chế độ sáng + chế độ tối - **Màu chính:** HSL(142.1, 76.2%, 36.3%) — xanh lá - **Tất cả component:** Dùng @apply border-border để nhất quán - **Nền gốc:** Áp dụng biến HSL --- ## 🗣️ Nội Dung Văn Bản & Các Điểm i18n ### Vị Trí Văn Bản Tiếng Việt Được Mã Hóa Cứng: #### Layout & Điều Hướng: - `app/(public)/layout.tsx` — Nav header: "Trang chủ", "Tìm kiếm", "Đăng nhập", "Đăng ký" - `app/(dashboard)/layout.tsx` — Các mục nav dashboard (8 mục + nhãn chuyển đổi theme) - Footer trong layout công khai — Tiêu đề phần, liên kết #### Trang: - `app/(public)/page.tsx` — Trang đích (hero, thanh tìm kiếm, quận huyện, thống kê, CTA) - `app/(auth)/login/page.tsx` — Nhãn form, thông báo lỗi (đối tượng OAUTH_ERROR_MESSAGES) - `app/(auth)/register/page.tsx` — Cấu trúc form tương tự #### Component: - `components/search/filter-bar.tsx` — Nhãn bộ lọc (PRICE_RANGES), tên thành phố - `components/search/property-card.tsx` — Badge thông tin bất động sản, nhãn hướng - `components/listings/listing-form-steps.tsx` — Nhãn form, thông báo xác thực - `components/ui/label.tsx` — Nhãn form trong toàn bộ ứng dụng #### Thông Báo Lỗi API & Xác Thực Zod: - `lib/validations/listings.ts` — Thông báo lỗi Zod (tiếng Việt) - `lib/validations/auth.ts` — Thông báo xác thực xác thực - `components/auth/oauth-buttons.tsx` — Văn bản nút ("Google", "Zalo") --- ## 🧩 Các Component Quan Trọng Cần Dịch ### Form (Xác thực form + nhãn): 1. **Form Đăng Nhập** (`app/(auth)/login/page.tsx`) - Nhãn nhập số điện thoại, nhãn mật khẩu, lỗi - Nhãn nút OAuth - Văn bản liên kết: "Chưa có tài khoản? Đăng ký" 2. **Form Đăng Ký** (`app/(auth)/register/page.tsx`) - Cấu trúc tương tự form đăng nhập 3. **Tạo Tin Đăng** (`components/listings/listing-form-steps.tsx`) - Form nhiều bước với nhãn cho: - Loại giao dịch (Bán/Cho thuê) - Loại bất động sản (Căn hộ/Nhà riêng/v.v.) - Vị trí (địa chỉ, phường, quận, thành phố) - Chi tiết (diện tích, phòng ngủ, phòng tắm, hướng) - Giá cả 4. **Bộ Lọc Tìm Kiếm** (`components/search/filter-bar.tsx`) - Select Giao dịch/Loại BĐS/Giá/Diện tích - Tùy chọn thành phố (13 thành phố Việt Nam) ### Component UI: - **Nút:** Nhãn văn bản ("Đăng nhập", "Tìm kiếm", "Gửi", v.v.) - **Badge:** Nhãn cho loại bất động sản, trạng thái, hướng - **Nhãn input:** Trên tất cả các form - **Thông báo lỗi:** Văn bản cảnh báo ### Điều Hướng: - **Header công khai:** 4 mục nav chính + menu người dùng - **Nav dashboard:** 8 phần chính + chuyển đổi theme - **Footer:** 4 cột liên kết + bản quyền --- ## ♿ Khả Năng Tiếp Cận (Trạng Thái Hiện Tại - WCAG 2.1 AA) ### Đã Triển Khai ✅: - Liên kết bỏ qua đến nội dung chính (ẩn, hiện khi focus) - HTML ngữ nghĩa: `
`, `