chore: update project documentation, audit reports, and initialize IDE configuration files
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 29s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m42s
Deploy / Build Web Image (push) Failing after 27s
Deploy / Build AI Services Image (push) Failing after 29s
E2E Tests / Playwright E2E (push) Failing after 43s
Deploy / Build API Image (push) Failing after 1m31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 6s
Security Scanning / Trivy Scan — API Image (push) Failing after 5m35s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 3m45s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Security Scanning / Trivy Scan — Web Image (push) Failing after 13m51s
Security Scanning / Trivy Filesystem Scan (push) Failing after 14m46s
Security Scanning / Security Gate (push) Has been cancelled
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 29s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m42s
Deploy / Build Web Image (push) Failing after 27s
Deploy / Build AI Services Image (push) Failing after 29s
E2E Tests / Playwright E2E (push) Failing after 43s
Deploy / Build API Image (push) Failing after 1m31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 6s
Security Scanning / Trivy Scan — API Image (push) Failing after 5m35s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 3m45s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Security Scanning / Trivy Scan — Web Image (push) Failing after 13m51s
Security Scanning / Trivy Filesystem Scan (push) Failing after 14m46s
Security Scanning / Security Gate (push) Has been cancelled
This commit is contained in:
@@ -1,116 +1,116 @@
|
||||
# GoodGo Platform Frontend Exploration Report
|
||||
## apps/web (Next.js 15 with App Router)
|
||||
# Báo Cáo Khám Phá Frontend Nền Tảng GoodGo
|
||||
## apps/web (Next.js 15 với App Router)
|
||||
|
||||
**Date:** April 9, 2026
|
||||
**Status:** Pre-i18n (No existing i18n setup detected)
|
||||
**Next.js Version:** 15.5.14 | **React:** 18.3.0
|
||||
**Primary Language:** Vietnamese (vi_VN)
|
||||
**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)
|
||||
|
||||
---
|
||||
|
||||
## 📁 Directory Structure Overview
|
||||
## 📁 Tổng Quan Cấu Trúc Thư Mục
|
||||
|
||||
```
|
||||
apps/web/
|
||||
├── app/ # Next.js App Router (main application)
|
||||
│ ├── layout.tsx # Root layout with metadata & providers
|
||||
│ ├── globals.css # Global Tailwind styles & theme variables
|
||||
│ ├── middleware.ts # Already exists (auth routing middleware)
|
||||
│ ├── loading.tsx # Root loading state
|
||||
│ ├── error.tsx # Root error boundary
|
||||
│ ├── not-found.tsx # 404 page
|
||||
├── 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)/ # Public route group
|
||||
│ │ ├── layout.tsx # Public layout with header/footer
|
||||
│ │ ├── page.tsx # Landing page (hero + featured listings)
|
||||
│ │ ├── search/ # Search results page
|
||||
│ ├── (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]/ # Listing detail page
|
||||
│ │ └── listings/[id]/ # Trang chi tiết tin đăng
|
||||
│ │ └── page.tsx
|
||||
│ │
|
||||
│ ├── (auth)/ # Auth route group
|
||||
│ ├── (auth)/ # Nhóm route xác thực
|
||||
│ │ ├── layout.tsx
|
||||
│ │ ├── login/page.tsx # Login form
|
||||
│ │ ├── register/page.tsx # Registration form
|
||||
│ │ ├── login/page.tsx # Form đăng nhập
|
||||
│ │ ├── register/page.tsx # Form đăng ký
|
||||
│ │ ├── error.tsx
|
||||
│ │ ├── loading.tsx
|
||||
│ │ └── __tests__/
|
||||
│ │
|
||||
│ ├── (dashboard)/ # Protected dashboard route group
|
||||
│ │ ├── layout.tsx # Dashboard layout with sidebar nav
|
||||
│ │ ├── dashboard/page.tsx # Main dashboard
|
||||
│ ├── (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 # User listings list
|
||||
│ │ │ ├── new/page.tsx # Create listing (multi-step form)
|
||||
│ │ │ ├── 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 # User profile settings
|
||||
│ │ ├── subscription/page.tsx # Subscription plans
|
||||
│ │ ├── payments/page.tsx # Payment history
|
||||
│ │ ├── valuation/page.tsx # AI property valuation
|
||||
│ │ ├── 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)/ # Admin route group
|
||||
│ ├── (admin)/ # Nhóm route quản trị
|
||||
│ │ ├── layout.tsx
|
||||
│ │ ├── admin/page.tsx # Admin dashboard
|
||||
│ │ ├── admin/page.tsx # Dashboard quản trị
|
||||
│ │ ├── admin/users/page.tsx
|
||||
│ │ ├── admin/kyc/page.tsx
|
||||
│ │ ├── admin/moderation/page.tsx
|
||||
│ │ ├── error.tsx
|
||||
│ │ └── loading.tsx
|
||||
│ │
|
||||
│ ├── auth/ # Auth callbacks
|
||||
│ ├── auth/ # Callback xác thực
|
||||
│ │ └── callback/
|
||||
│ │ ├── google/page.tsx
|
||||
│ │ └── zalo/page.tsx
|
||||
│ │
|
||||
│ ├── api/ # API routes
|
||||
│ ├── api/ # Route API
|
||||
│ │ └── health/route.ts
|
||||
│ │
|
||||
│ ├── robots.ts
|
||||
│ └── sitemap.ts
|
||||
│
|
||||
├── components/ # Reusable React components
|
||||
├── components/ # Các component React tái sử dụng
|
||||
│ ├── providers/ # Context providers
|
||||
│ │ ├── auth-provider.tsx # Auth context & store wrapper
|
||||
│ │ ├── query-provider.tsx # TanStack React Query provider
|
||||
│ │ └── theme-provider.tsx # Dark/light mode provider
|
||||
│ │ ├── 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/ # Unstyled base UI components
|
||||
│ │ ├── button.tsx # CVA-based button variants
|
||||
│ ├── 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 # Modal dialog
|
||||
│ │ ├── dialog.tsx # Hộp thoại modal
|
||||
│ │ ├── tabs.tsx
|
||||
│ │ ├── select.tsx # Custom select component
|
||||
│ │ ├── select.tsx # Component select tùy chỉnh
|
||||
│ │ ├── badge.tsx
|
||||
│ │ ├── textarea.tsx
|
||||
│ │ ├── table.tsx
|
||||
│ │ └── __tests__/ # Component tests
|
||||
│ │ └── __tests__/ # Test component
|
||||
│ │
|
||||
│ ├── auth/
|
||||
│ │ └── oauth-buttons.tsx # Google & Zalo OAuth buttons
|
||||
│ │ └── oauth-buttons.tsx # Nút OAuth Google & Zalo
|
||||
│ │
|
||||
│ ├── search/
|
||||
│ │ ├── filter-bar.tsx # Search filters (transaction, property, price range)
|
||||
│ │ ├── property-card.tsx # Property listing card
|
||||
│ │ └── search-results.tsx # Results container
|
||||
│ │ ├── 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 # Multi-step create/edit form
|
||||
│ │ ├── image-upload.tsx # Image upload component
|
||||
│ │ ├── image-gallery.tsx # Image gallery viewer
|
||||
│ │ └── listing-status-badge.tsx # Status display badge
|
||||
│ │ ├── 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 # Mapbox GL integration
|
||||
│ │ └── listing-map.tsx # Tích hợp Mapbox GL
|
||||
│ │
|
||||
│ ├── valuation/
|
||||
│ │ ├── valuation-form.tsx
|
||||
@@ -123,11 +123,11 @@ apps/web/
|
||||
│ ├── agent-performance.tsx
|
||||
│ └── district-heatmap.tsx
|
||||
│
|
||||
├── lib/ # Utilities and hooks
|
||||
├── lib/ # Tiện ích và hooks
|
||||
│ ├── utils.ts # cn() - clsx + tailwind-merge
|
||||
│ ├── auth-store.ts # Zustand auth state management
|
||||
│ ├── api-client.ts # Axios/fetch wrapper
|
||||
│ ├── query-client.ts # TanStack React Query config
|
||||
│ ├── 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
|
||||
@@ -136,12 +136,12 @@ apps/web/
|
||||
│ │ ├── use-payments.ts
|
||||
│ │ └── use-subscription.ts
|
||||
│ │
|
||||
│ ├── validations/ # Zod schemas
|
||||
│ │ ├── auth.ts # Login/register schemas
|
||||
│ │ ├── listings.ts # Multi-step listing schemas
|
||||
│ ├── validations/ # Schema Zod
|
||||
│ │ ├── auth.ts # Schema đăng nhập/đăng ký
|
||||
│ │ ├── listings.ts # Schema tin đăng nhiều bước
|
||||
│ │ └── valuation.ts
|
||||
│ │
|
||||
│ ├── *-api.ts # API clients
|
||||
│ ├── *-api.ts # Các API client
|
||||
│ │ ├── auth-api.ts
|
||||
│ │ ├── listings-api.ts
|
||||
│ │ ├── profile-api.ts
|
||||
@@ -151,58 +151,58 @@ apps/web/
|
||||
│ │ ├── valuation-api.ts
|
||||
│ │ └── admin-api.ts
|
||||
│ │
|
||||
│ └── __tests__/ # Unit tests (Vitest + React Testing Library)
|
||||
│ └── __tests__/ # Unit test (Vitest + React Testing Library)
|
||||
│ ├── auth-store.spec.ts
|
||||
│ ├── auth-validations.spec.ts
|
||||
│ ├── listing-validations.spec.ts
|
||||
│ └── utils.spec.ts
|
||||
│
|
||||
├── public/ # Static assets
|
||||
├── public/ # Tài nguyên tĩnh
|
||||
│ └── [images, icons, etc.]
|
||||
│
|
||||
├── .next/ # Build output (generated)
|
||||
├── .next/ # Đầu ra build (được tạo tự động)
|
||||
├── node_modules/
|
||||
│
|
||||
└── Configuration Files:
|
||||
├── package.json # Dependencies & scripts
|
||||
├── next.config.js # Next.js config (Sentry, CSP, headers)
|
||||
├── tailwind.config.ts # Tailwind CSS config
|
||||
├── postcss.config.js # PostCSS config (Tailwind + Autoprefixer)
|
||||
├── tsconfig.json # TypeScript config (extends base)
|
||||
├── vitest.config.ts # Testing framework config
|
||||
├── vitest.setup.ts # Test setup
|
||||
├── middleware.ts # Auth routing middleware
|
||||
├── sentry.*.config.ts # Sentry error tracking (3 files)
|
||||
├── instrumentation.ts # Server instrumentation
|
||||
└── global.d.ts # Global TypeScript definitions
|
||||
└── 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
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📦 Package.json Dependencies
|
||||
## 📦 Phụ Thuộc Package.json
|
||||
|
||||
### Production Dependencies:
|
||||
### Phụ Thuộc Production:
|
||||
```json
|
||||
{
|
||||
"@hookform/resolvers": "^5.2.2", // Form validation resolver
|
||||
"@sentry/nextjs": "^10.47.0", // Error tracking
|
||||
"@tanstack/react-query": "^5.96.2", // Data fetching & caching
|
||||
"class-variance-authority": "^0.7.1", // Component variant utilities
|
||||
"clsx": "^2.1.1", // Class name utility
|
||||
"lucide-react": "^1.7.0", // Icon library
|
||||
"mapbox-gl": "^3.21.0", // Map library
|
||||
"@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", // Form state management
|
||||
"recharts": "^3.8.1", // Chart library
|
||||
"tailwind-merge": "^3.5.0", // Merge Tailwind conflicts
|
||||
"zod": "^4.3.6", // Schema validation
|
||||
"zustand": "^5.0.12" // Lightweight state management
|
||||
"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ẹ
|
||||
}
|
||||
```
|
||||
|
||||
### Dev Dependencies (including testing):
|
||||
### Phụ Thuộc Dev (bao gồm kiểm thử):
|
||||
```json
|
||||
{
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
@@ -219,17 +219,17 @@ apps/web/
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Root Layout (app/layout.tsx)
|
||||
## 🎯 Layout Gốc (app/layout.tsx)
|
||||
|
||||
### Current Implementation:
|
||||
- **HTML language:** `lang="vi"` (Vietnamese hardcoded)
|
||||
- **Metadata structure:** Vietnamese title & description
|
||||
- **OpenGraph:** Locale set to `vi_VN`
|
||||
- **Providers stacked:** `ThemeProvider → QueryProvider → AuthProvider`
|
||||
- **Accessibility:** Includes skip-to-main-content link (already A11y compliant)
|
||||
- **Theme color:** `#15803d` (primary green)
|
||||
### 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)
|
||||
|
||||
### Current Metadata:
|
||||
### 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...'
|
||||
@@ -240,7 +240,7 @@ openGraph: { locale: 'vi_VN', ... }
|
||||
|
||||
## 🔐 Middleware (middleware.ts)
|
||||
|
||||
### Current Auth Routing:
|
||||
### Đị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
|
||||
@@ -248,15 +248,15 @@ openGraph: { locale: 'vi_VN', ... }
|
||||
- Redirect param: Adds ?redirect=[original-path] on unauthorized access
|
||||
```
|
||||
|
||||
**Key Entry Points to Update for i18n:**
|
||||
- Locale prefix detection needed (e.g., `/en/dashboard`, `/vi/dashboard`)
|
||||
- Cookie/header locale detection
|
||||
**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
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Tailwind Configuration
|
||||
## 🎨 Cấu Hình Tailwind
|
||||
|
||||
### Theme Setup (tailwind.config.ts):
|
||||
### Thiết Lập Theme (tailwind.config.ts):
|
||||
```typescript
|
||||
- Dark mode: 'class' based
|
||||
- Content paths: ./app/**, ./components/**, ./lib/**
|
||||
@@ -265,146 +265,146 @@ openGraph: { locale: 'vi_VN', ... }
|
||||
- Animation plugin: tailwindcss-animate
|
||||
```
|
||||
|
||||
### Global Styles (app/globals.css):
|
||||
- **CSS Variables:** Light mode + dark mode color schemes
|
||||
- **Primary color:** HSL(142.1, 76.2%, 36.3%) — green
|
||||
- **All components:** Use @apply border-border for consistency
|
||||
- **Root background:** HSL variables applied
|
||||
### 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
|
||||
|
||||
---
|
||||
|
||||
## 🗣️ Text Content & i18n Points
|
||||
## 🗣️ Nội Dung Văn Bản & Các Điểm i18n
|
||||
|
||||
### Hardcoded Vietnamese Text Locations:
|
||||
### Vị Trí Văn Bản Tiếng Việt Được Mã Hóa Cứng:
|
||||
|
||||
#### Layout & Navigation:
|
||||
- `app/(public)/layout.tsx` — Header nav: "Trang chủ", "Tìm kiếm", "Đăng nhập", "Đăng ký"
|
||||
- `app/(dashboard)/layout.tsx` — Dashboard nav items (8 items + theme toggle label)
|
||||
- Footer in public layout — Section headings, links
|
||||
#### 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
|
||||
|
||||
#### Pages:
|
||||
- `app/(public)/page.tsx` — Landing page (hero, search bar, districts, stats, CTA)
|
||||
- `app/(auth)/login/page.tsx` — Form labels, error messages (OAUTH_ERROR_MESSAGES object)
|
||||
- `app/(auth)/register/page.tsx` — Similar form structure
|
||||
#### 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ự
|
||||
|
||||
#### Components:
|
||||
- `components/search/filter-bar.tsx` — Filter labels (PRICE_RANGES), city names
|
||||
- `components/search/property-card.tsx` — Property info badges, direction labels
|
||||
- `components/listings/listing-form-steps.tsx` — Form labels, validation messages
|
||||
- `components/ui/label.tsx` — Form labels across app
|
||||
#### 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
|
||||
|
||||
#### API Error Messages & Zod Validation:
|
||||
- `lib/validations/listings.ts` — Zod error messages (Vietnamese)
|
||||
- `lib/validations/auth.ts` — Auth validation messages
|
||||
- `components/auth/oauth-buttons.tsx` — Button text ("Google", "Zalo")
|
||||
#### 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")
|
||||
|
||||
---
|
||||
|
||||
## 🧩 Key Components Requiring Translation
|
||||
## 🧩 Các Component Quan Trọng Cần Dịch
|
||||
|
||||
### Forms (Form validation + labels):
|
||||
1. **Login Form** (`app/(auth)/login/page.tsx`)
|
||||
- Phone input label, password label, errors
|
||||
- OAuth button labels
|
||||
- Link text: "Chưa có tài khoản? Đăng ký"
|
||||
### 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. **Register Form** (`app/(auth)/register/page.tsx`)
|
||||
- Similar structure to login
|
||||
2. **Form Đăng Ký** (`app/(auth)/register/page.tsx`)
|
||||
- Cấu trúc tương tự form đăng nhập
|
||||
|
||||
3. **Listing Creation** (`components/listings/listing-form-steps.tsx`)
|
||||
- Multi-step form with labels for:
|
||||
- Transaction type (Bán/Cho thuê)
|
||||
- Property type (Căn hộ/Nhà riêng/etc)
|
||||
- Location (address, ward, district, city)
|
||||
- Details (area, bedrooms, bathrooms, direction)
|
||||
- Pricing
|
||||
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. **Search Filter** (`components/search/filter-bar.tsx`)
|
||||
- Transaction/Property/Price/Area selects
|
||||
- City options (13 Vietnamese cities)
|
||||
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)
|
||||
|
||||
### UI Components:
|
||||
- **Buttons:** Text labels ("Đăng nhập", "Tìm kiếm", "Gửi", etc.)
|
||||
- **Badge:** Labels for property types, statuses, directions
|
||||
- **Input labels:** Across all forms
|
||||
- **Error messages:** Alert text
|
||||
### 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
|
||||
|
||||
### Navigation:
|
||||
- **Public header:** 4 main nav items + user menu
|
||||
- **Dashboard nav:** 8 main sections + theme toggle
|
||||
- **Footer:** 4 columns of links + copyright
|
||||
### Đ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
|
||||
|
||||
---
|
||||
|
||||
## ♿ Accessibility (Current State - WCAG 2.1 AA)
|
||||
## ♿ Khả Năng Tiếp Cận (Trạng Thái Hiện Tại - WCAG 2.1 AA)
|
||||
|
||||
### Already Implemented ✅:
|
||||
- Skip-to-main-content link (hidden, appears on focus)
|
||||
- Semantic HTML: `<header>`, `<nav>`, `<main>`, `<footer>`
|
||||
- `aria-label` on navigation items
|
||||
- `aria-label` on property cards (for screen readers)
|
||||
- `role="alert"` on error messages
|
||||
- `aria-invalid` on form inputs
|
||||
- Form labels linked with `htmlFor`
|
||||
- Image alt text on property images
|
||||
- `aria-hidden="true"` on decorative elements
|
||||
### Đã Triển Khai ✅:
|
||||
- Liên kết bỏ qua đến nội dung chính (ẩn, hiện khi focus)
|
||||
- HTML ngữ nghĩa: `<header>`, `<nav>`, `<main>`, `<footer>`
|
||||
- `aria-label` trên các mục điều hướng
|
||||
- `aria-label` trên thẻ bất động sản (cho trình đọc màn hình)
|
||||
- `role="alert"` trên thông báo lỗi
|
||||
- `aria-invalid` trên các input form
|
||||
- Nhãn form liên kết với `htmlFor`
|
||||
- Văn bản alt trên ảnh bất động sản
|
||||
- `aria-hidden="true"` trên các phần tử trang trí
|
||||
|
||||
### Accessibility Gaps to Fix 🔧:
|
||||
1. **Color contrast:** Need to verify against WCAG AA standards
|
||||
2. **Focus indicators:** Ensure visible focus states on all interactive elements
|
||||
3. **Dialog/Modal:** Need proper focus management in dialogs
|
||||
4. **Forms:** Ensure field grouping with `<fieldset>` where applicable
|
||||
5. **Error handling:** Some error messages lack clear labels
|
||||
6. **Loading states:** Spinner needs `aria-busy` or `aria-label`
|
||||
7. **Tables:** Data tables need proper headers (`<th>`, `scope`)
|
||||
8. **Links:** "Xem tất cả" links should have context or aria-labels
|
||||
9. **Icon-only buttons:** Need proper `aria-label`
|
||||
10. **Text alternatives:** Ensure all meaningful icons have descriptive labels
|
||||
### Lỗ Hổng Khả Năng Tiếp Cận Cần Khắc Phục 🔧:
|
||||
1. **Độ tương phản màu sắc:** Cần kiểm tra theo chuẩn WCAG AA
|
||||
2. **Chỉ báo focus:** Đảm bảo trạng thái focus hiển thị rõ trên tất cả phần tử tương tác
|
||||
3. **Dialog/Modal:** Cần quản lý focus đúng cách trong dialog
|
||||
4. **Form:** Đảm bảo nhóm trường với `<fieldset>` khi cần
|
||||
5. **Xử lý lỗi:** Một số thông báo lỗi thiếu nhãn rõ ràng
|
||||
6. **Trạng thái tải:** Spinner cần `aria-busy` hoặc `aria-label`
|
||||
7. **Bảng:** Bảng dữ liệu cần header đúng cách (`<th>`, `scope`)
|
||||
8. **Liên kết:** Liên kết "Xem tất cả" nên có ngữ cảnh hoặc aria-label
|
||||
9. **Nút chỉ có icon:** Cần `aria-label` phù hợp
|
||||
10. **Văn bản thay thế:** Đảm bảo tất cả icon có ý nghĩa đều có nhãn mô tả
|
||||
|
||||
### ARIA Implementation Points:
|
||||
- Dropdown navigation (if complex)
|
||||
- Tab interfaces (recharts/charts)
|
||||
- File upload components
|
||||
- Date/time inputs (if added)
|
||||
### Các Điểm Triển Khai ARIA:
|
||||
- Điều hướng dropdown (nếu phức tạp)
|
||||
- Giao diện Tab (recharts/biểu đồ)
|
||||
- Component tải tệp
|
||||
- Input ngày/giờ (nếu được thêm vào)
|
||||
|
||||
---
|
||||
|
||||
## 🔗 Current Locale Setup
|
||||
## 🔗 Thiết Lập Locale Hiện Tại
|
||||
|
||||
### Status: **NO EXISTING i18n**
|
||||
- No `next-intl` package
|
||||
- No translation files (JSON/YAML)
|
||||
- No locale routes (`/en/*`, `/vi/*`)
|
||||
- No i18n middleware
|
||||
- **Language is hardcoded to Vietnamese everywhere**
|
||||
### Trạng thái: **CHƯA CÓ i18n**
|
||||
- Không có package `next-intl`
|
||||
- Không có tệp dịch (JSON/YAML)
|
||||
- Không có route theo locale (`/en/*`, `/vi/*`)
|
||||
- Không có middleware i18n
|
||||
- **Ngôn ngữ được mã hóa cứng thành tiếng Việt ở khắp nơi**
|
||||
|
||||
### Where i18n Will Be Integrated:
|
||||
1. **Middleware:** Detect locale from URL, cookie, or `Accept-Language` header
|
||||
2. **Layout wrapper:** `[locale]/layout.tsx` folder structure
|
||||
3. **Message providers:** `next-intl` Provider in root layout
|
||||
4. **API responses:** May need to internationalize error messages from backend
|
||||
### Nơi i18n Sẽ Được Tích Hợp:
|
||||
1. **Middleware:** Phát hiện locale từ URL, cookie, hoặc header `Accept-Language`
|
||||
2. **Wrapper layout:** Cấu trúc thư mục `[locale]/layout.tsx`
|
||||
3. **Message providers:** Provider `next-intl` trong layout gốc
|
||||
4. **Phản hồi API:** Có thể cần quốc tế hóa thông báo lỗi từ backend
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Security Configuration
|
||||
## 🔒 Cấu Hình Bảo Mật
|
||||
|
||||
### Next.js Config Security Headers:
|
||||
### Security Headers Cấu Hình Next.js:
|
||||
- `X-Content-Type-Options: nosniff`
|
||||
- `X-Frame-Options: DENY`
|
||||
- `X-XSS-Protection: 1; mode=block`
|
||||
- `Content-Security-Policy` with Mapbox domains whitelisted
|
||||
- `Permissions-Policy` restricting camera/microphone/geolocation
|
||||
- `Content-Security-Policy` với các domain Mapbox được đưa vào danh sách trắng
|
||||
- `Permissions-Policy` hạn chế camera/microphone/geolocation
|
||||
|
||||
### Auth Middleware:
|
||||
- Cookie-based auth check (`goodgo_authenticated`)
|
||||
- Protected routes redirect to `/login?redirect=...`
|
||||
- Public route protection in middleware
|
||||
### Middleware Xác Thực:
|
||||
- Kiểm tra xác thực dựa trên cookie (`goodgo_authenticated`)
|
||||
- Các route được bảo vệ chuyển hướng đến `/login?redirect=...`
|
||||
- Bảo vệ route công khai trong middleware
|
||||
|
||||
---
|
||||
|
||||
## 📊 Key Data Structures & Enums
|
||||
## 📊 Cấu Trúc Dữ Liệu & Enum Quan Trọng
|
||||
|
||||
### Transaction Types:
|
||||
### Loại Giao Dịch:
|
||||
```typescript
|
||||
const TRANSACTION_TYPES = [
|
||||
{ value: 'SALE', label: 'Bán' },
|
||||
@@ -412,7 +412,7 @@ const TRANSACTION_TYPES = [
|
||||
];
|
||||
```
|
||||
|
||||
### Property Types:
|
||||
### Loại Bất Động Sản:
|
||||
```typescript
|
||||
const PROPERTY_TYPES = [
|
||||
{ value: 'APARTMENT', label: 'Căn hộ' },
|
||||
@@ -424,25 +424,25 @@ const PROPERTY_TYPES = [
|
||||
];
|
||||
```
|
||||
|
||||
### Listing Statuses:
|
||||
### Trạng Thái Tin Đăng:
|
||||
```typescript
|
||||
const LISTING_STATUSES = {
|
||||
DRAFT, PENDING_REVIEW, ACTIVE, RESERVED, SOLD, RENTED, EXPIRED, REJECTED
|
||||
};
|
||||
```
|
||||
|
||||
### Directions:
|
||||
### Hướng:
|
||||
```typescript
|
||||
const DIRECTIONS = [
|
||||
{ value: 'NORTH', label: 'Bắc' },
|
||||
{ value: 'SOUTH', label: 'Nam' },
|
||||
{ value: 'EAST', label: 'Đông' },
|
||||
{ value: 'WEST', label: 'Tây' },
|
||||
// ... and diagonal combinations
|
||||
// ... và các tổ hợp đường chéo
|
||||
];
|
||||
```
|
||||
|
||||
### Cities (13 total):
|
||||
### Thành Phố (13 tổng):
|
||||
```typescript
|
||||
Hồ Chí Minh, Hà Nội, Đà Nẵng, Nha Trang, Cần Thơ, Hải Phòng,
|
||||
Bình Dương, Đồng Nai, Long An, Bà Rịa - Vũng Tàu, [+ more]
|
||||
@@ -450,85 +450,85 @@ Bình Dương, Đồng Nai, Long An, Bà Rịa - Vũng Tàu, [+ more]
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing Setup
|
||||
## 🧪 Thiết Lập Kiểm Thử
|
||||
|
||||
### Test Framework: Vitest + React Testing Library
|
||||
- **Config file:** `vitest.config.ts`
|
||||
- **Setup file:** `vitest.setup.ts`
|
||||
- **Test files:** Located alongside source (`__tests__` folders)
|
||||
### Framework Kiểm Thử: Vitest + React Testing Library
|
||||
- **Tệp cấu hình:** `vitest.config.ts`
|
||||
- **Tệp thiết lập:** `vitest.setup.ts`
|
||||
- **Tệp test:** Đặt cạnh source (`__tests__` folders)
|
||||
|
||||
### Current Test Coverage:
|
||||
- Component tests for UI library
|
||||
- Auth store tests
|
||||
- Validation schema tests
|
||||
- Utility function tests
|
||||
### Phạm Vi Test Hiện Tại:
|
||||
- Test component cho thư viện UI
|
||||
- Test auth store
|
||||
- Test schema xác thực
|
||||
- Test hàm tiện ích
|
||||
|
||||
### Testing Best Practices for i18n:
|
||||
- Mock i18n provider in test setup
|
||||
- Test both locale variants
|
||||
- Verify translations render correctly
|
||||
### Thực Hành Tốt Nhất Khi Kiểm Thử i18n:
|
||||
- Mock provider i18n trong thiết lập test
|
||||
- Kiểm thử cả hai biến thể locale
|
||||
- Xác minh các bản dịch hiển thị đúng
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Implementation Readiness
|
||||
## 🚀 Mức Độ Sẵn Sàng Triển Khai
|
||||
|
||||
### Ready for i18n Implementation:
|
||||
✅ Centralized validation messages (Zod schemas)
|
||||
✅ Enum/constant-based UI text (TRANSACTION_TYPES, PROPERTY_TYPES, etc.)
|
||||
✅ Component library with consistent patterns
|
||||
✅ TypeScript for type safety
|
||||
✅ Middleware support for locale routing
|
||||
### Sẵn Sàng Cho Triển Khai i18n:
|
||||
✅ Thông báo xác thực tập trung (schema Zod)
|
||||
✅ Văn bản UI dựa trên enum/hằng số (TRANSACTION_TYPES, PROPERTY_TYPES, v.v.)
|
||||
✅ Thư viện component với các pattern nhất quán
|
||||
✅ TypeScript để đảm bảo type safety
|
||||
✅ Hỗ trợ middleware cho định tuyến theo locale
|
||||
|
||||
### Minor Refactoring Needed:
|
||||
⚠️ Extract some hardcoded strings from components
|
||||
⚠️ Move form error messages to message files
|
||||
⚠️ Centralize page metadata for i18n
|
||||
### Cần Tái Cấu Trúc Nhỏ:
|
||||
⚠️ Trích xuất một số chuỗi được mã hóa cứng ra khỏi component
|
||||
⚠️ Chuyển thông báo lỗi form sang tệp message
|
||||
⚠️ Tập trung hóa metadata trang cho i18n
|
||||
|
||||
---
|
||||
|
||||
## 📝 Summary: i18n & A11y Implementation Points
|
||||
## 📝 Tóm Tắt: Các Điểm Triển Khai i18n & A11y
|
||||
|
||||
| Area | Current State | Needs Work |
|
||||
|------|---------------|-----------|
|
||||
| **Locale Support** | Hardcoded to Vietnamese | Implement next-intl with routing |
|
||||
| **Translation Keys** | Scattered throughout code | Centralize in message files |
|
||||
| **Validation Messages** | In Zod schemas (Vietnamese) | Extract to i18n messages |
|
||||
| **Component Text** | Hardcoded strings | Use i18n hook |
|
||||
| **Metadata/SEO** | Hardcoded Vietnamese | Generate for each locale |
|
||||
| **Color Contrast** | Likely AA compliant | Audit and verify |
|
||||
| **Focus Management** | Partial (buttons/links ok) | Add to modals & dropdowns |
|
||||
| **ARIA Labels** | Good coverage | Complete missing labels |
|
||||
| **Error Messages** | Most have aria-invalid | Add more context to some |
|
||||
| **Loading States** | Spinner exists | Add aria-busy, better labels |
|
||||
| **Tables** | Basic structure | Add proper header semantics |
|
||||
| Khu Vực | Trạng Thái Hiện Tại | Cần Làm |
|
||||
|---------|---------------------|---------|
|
||||
| **Hỗ Trợ Locale** | Mã hóa cứng thành tiếng Việt | Triển khai next-intl với định tuyến |
|
||||
| **Khóa Dịch** | Rải rác trong code | Tập trung vào tệp message |
|
||||
| **Thông Báo Xác Thực** | Trong schema Zod (tiếng Việt) | Trích xuất sang message i18n |
|
||||
| **Văn Bản Component** | Chuỗi mã hóa cứng | Dùng hook i18n |
|
||||
| **Metadata/SEO** | Tiếng Việt mã hóa cứng | Tạo cho từng locale |
|
||||
| **Độ Tương Phản Màu** | Có thể đạt AA | Kiểm tra và xác minh |
|
||||
| **Quản Lý Focus** | Một phần (nút/liên kết ổn) | Thêm vào modal & dropdown |
|
||||
| **Nhãn ARIA** | Phạm vi tốt | Hoàn thiện nhãn còn thiếu |
|
||||
| **Thông Báo Lỗi** | Hầu hết có aria-invalid | Thêm ngữ cảnh cho một số trường hợp |
|
||||
| **Trạng Thái Tải** | Spinner tồn tại | Thêm aria-busy, nhãn tốt hơn |
|
||||
| **Bảng** | Cấu trúc cơ bản | Thêm ngữ nghĩa header đúng cách |
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ File Count Summary
|
||||
## 🗂️ Tóm Tắt Số Lượng Tệp
|
||||
|
||||
- **App routes:** ~15 page files
|
||||
- **Components:** ~35 component files
|
||||
- **Lib utilities:** ~20 files (hooks, APIs, validations)
|
||||
- **Tests:** ~15 test files
|
||||
- **Config files:** ~8 configuration files
|
||||
- **Total TypeScript/TSX files:** ~90+
|
||||
- **Route ứng dụng:** ~15 tệp trang
|
||||
- **Component:** ~35 tệp component
|
||||
- **Tiện ích lib:** ~20 tệp (hooks, API, xác thực)
|
||||
- **Test:** ~15 tệp test
|
||||
- **Tệp cấu hình:** ~8 tệp cấu hình
|
||||
- **Tổng tệp TypeScript/TSX:** ~90+
|
||||
|
||||
---
|
||||
|
||||
## Next Steps for Implementation
|
||||
## Các Bước Tiếp Theo Để Triển Khai
|
||||
|
||||
1. **Install i18n:** Add `next-intl` to dependencies
|
||||
2. **Create message files:** Set up `messages/en.json` and `messages/vi.json`
|
||||
3. **Refactor middleware:** Add locale detection & routing
|
||||
4. **Update root layout:** Wrap with i18n provider
|
||||
5. **Update all components:** Replace hardcoded strings with `useTranslations()`
|
||||
6. **Test both locales:** Ensure all pages render correctly
|
||||
7. **A11y audit:** Use axe DevTools to identify remaining issues
|
||||
8. **Focus management:** Add focus trapping in modals
|
||||
9. **Testing:** Update test setup for i18n mocking
|
||||
1. **Cài đặt i18n:** Thêm `next-intl` vào dependencies
|
||||
2. **Tạo tệp message:** Thiết lập `messages/en.json` và `messages/vi.json`
|
||||
3. **Tái cấu trúc middleware:** Thêm phát hiện locale & định tuyến
|
||||
4. **Cập nhật layout gốc:** Bọc với provider i18n
|
||||
5. **Cập nhật tất cả component:** Thay thế chuỗi mã hóa cứng bằng `useTranslations()`
|
||||
6. **Kiểm thử cả hai locale:** Đảm bảo tất cả trang hiển thị đúng
|
||||
7. **Kiểm tra A11y:** Dùng axe DevTools để xác định các vấn đề còn lại
|
||||
8. **Quản lý focus:** Thêm focus trapping trong modal
|
||||
9. **Kiểm thử:** Cập nhật thiết lập test cho mock i18n
|
||||
|
||||
---
|
||||
|
||||
**Report Generated:** April 9, 2026
|
||||
**Exploration Scope:** Thorough
|
||||
**Confidence:** High
|
||||
**Báo Cáo Được Tạo:** 9 tháng 4, 2026
|
||||
**Phạm Vi Khám Phá:** Toàn diện
|
||||
**Độ Tin Cậy:** Cao
|
||||
|
||||
Reference in New Issue
Block a user