# Kế hoạch triển khai: 11 Tính năng mới (Bổ sung Đa ngôn ngữ & Giao diện Sáng/Tối)

Kế hoạch này phác thảo các thay đổi về cơ sở dữ liệu (Prisma Schema), các API Endpoint ở Backend (NestJS), các Component và trang ở Frontend (React) để hiện thực hóa 11 tính năng mới theo yêu cầu của bạn.

---

## User Review Required

> [!IMPORTANT]
> - **Hệ thống đa ngôn ngữ (Tiếng Việt, Tiếng Anh, Tiếng Trung)**: Chúng tôi sẽ triển khai một hook dịch thuật tinh gọn `useTranslation` dạng từ điển lưu trữ cục bộ ở Frontend. Toàn bộ các tiêu đề, nhãn (labels), nút bấm, thông báo toast và văn bản tĩnh trong dự án sẽ được ánh xạ qua hook này dựa trên ngôn ngữ được lựa chọn. Lựa chọn ngôn ngữ sẽ được lưu trữ vào `localStorage` để giữ trạng thái sau khi tải lại trang.
> - **Cơ chế Giao diện Sáng / Tối (Light / Dark Theme)**: Hệ thống sẽ hỗ trợ 3 tùy chọn: Sáng (Light), Tối (Dark), và theo Hệ thống (System default, sử dụng `prefers-color-scheme` để tự động đổi màu theo hệ điều hành). Chúng tôi sẽ tích hợp các class tiện ích Tailwind CSS v4 (như `dark:bg-slate-900`, `dark:text-slate-100`, `dark:border-slate-800`) vào tất cả các component chính để giao diện đồng bộ hoàn hảo.
> - **Cơ chế lọc ảnh khiêu dâm & Làm mờ khuôn mặt**: Xử lý trực tiếp trên trình duyệt (Client-side) qua TensorFlow.js trước khi tải lên để đảm bảo tối ưu hiệu năng backend.
> - **Tài khoản Admin quản trị hệ thống bằng Secret Key**: Đọc `ADMIN_SECRET_KEY` từ `.env`. Ở Frontend, người dùng có thể kích hoạt quyền Admin tức thời bằng cách nhập chuỗi khóa này để được promote lên `isAdmin: true` trong Database.

---

## Open Questions

> [!WARNING]
> - Bạn có muốn lưu tùy chọn ngôn ngữ trực tiếp vào tài khoản User ở Database (để khi đăng nhập trên thiết bị khác thì tự động áp dụng ngôn ngữ đó) hay chỉ cần lưu ở `localStorage` trình duyệt là đủ?
> - Ngoài các ngôn ngữ Tiếng Việt, Tiếng Anh, Tiếng Trung, bạn có dự định mở rộng thêm ngôn ngữ nào khác trong tương lai không?

---

## Proposed Changes

### 1. Thay đổi Cơ sở dữ liệu (`backend/prisma/schema.prisma`)

Chúng ta sẽ bổ sung các Model mới để lưu trữ: Bộ lọc từ khóa, Cấu hình bộ lọc hình ảnh, Đánh giá Owner, và Mã chia sẻ hành trình.

#### [MODIFY] [schema.prisma](file:///home/locpham/travelplanning/backend/prisma/schema.prisma)
- Thêm model `WordFilter` để cấu hình bộ lọc từ khóa cấm.
- Thêm model `ModerationSetting` để lưu trạng thái cấu hình lọc của hệ thống.
- Thêm model `TourRating` để lưu đánh giá 5 sao cho Owner/Manager từ các thành viên.
- Thêm model `TourShare` để quản lý liên kết chia sẻ hành trình khẩn cấp.

```prisma
model WordFilter {
  id          String   @id @default(uuid())
  word        String   @unique
  replacement String
  createdAt   DateTime @default(now())
}

model ModerationSetting {
  id        String  @id @default(uuid())
  blockNsfw Boolean @default(false)
  blurFaces Boolean @default(false)
}

model TourRating {
  id           String   @id @default(uuid())
  tourId       String
  targetUserId String   // Owner/Manager được đánh giá
  raterUserId  String   // Người dùng thực hiện đánh giá
  honesty      Int      @default(5)
  transparency Int      @default(5)
  enthusiasm   Int      @default(5)
  cheerfulness Int      @default(5)
  seriousness  Int      @default(5)
  planning     Int      @default(5)
  survival     Int      @default(5)
  averageScore Float    @default(5.0)
  comment      String?  @db.Text
  createdAt    DateTime @default(now())

  tour       Tour @relation(fields: [tourId], references: [id], onDelete: Cascade)
  targetUser User @relation("RatedUser", fields: [targetUserId], references: [id], onDelete: Cascade)
  raterUser  User @relation("RatingUser", fields: [raterUserId], references: [id], onDelete: Cascade)

  @@unique([tourId, targetUserId, raterUserId])
}

model TourShare {
  id        String   @id @default(uuid())
  tourId    String   @unique
  token     String   @unique @default(uuid())
  isEnabled Boolean  @default(true)
  createdAt DateTime @default(now())

  tour      Tour     @relation(fields: [tourId], references: [id], onDelete: Cascade)
}
```

---

### 2. Backend API (`backend/src/main.ts`)

#### [MODIFY] [main.ts](file:///home/locpham/travelplanning/backend/src/main.ts)
- Triển khai đầy đủ các endpoint như trong kế hoạch trước đó:
  - `DELETE /api/v1/public-photos/comments/:id`
  - Tích hợp bộ lọc từ khóa cấm ở các API tạo bài đăng/tin nhắn/bình luận.
  - API cài đặt bộ lọc ảnh và text của Admin (`/api/v1/admin/moderation`, `/api/v1/admin/word-filters`).
  - API Đánh giá Owner/Manager (`/api/v1/tours/:tourId/ratings`) và Leaderboard uy tín (`/api/v1/users/trusted`).
  - API kích hoạt Admin bằng secret key (`/api/v1/auth/promote-admin`).
  - API chia sẻ hành trình khẩn cấp (`/api/v1/tours/:tourId/share`, `/api/v1/tours/share/:token`).

---

### 3. Giao diện Frontend (`frontend/src/...`)

#### [NEW] [useTranslation.ts](file:///home/locpham/travelplanning/frontend/src/hooks/useTranslation.ts)
- Tạo hook `useTranslation` để quản lý đa ngôn ngữ:
  - Khai báo từ điển ngôn ngữ `translations` chứa các bản dịch Tiếng Việt (VI), Tiếng Anh (EN), Tiếng Trung (ZH).
  - Hỗ trợ hàm dịch `t(key: string)` và các hàm chuyển đổi ngôn ngữ, tự động đồng bộ giá trị với `localStorage.getItem('language')`.
  - Dịch các tiêu đề, thông báo, nhãn, nút bấm trong toàn bộ ứng dụng sang 3 ngôn ngữ tương ứng.

#### [NEW] [useTheme.ts](file:///home/locpham/travelplanning/frontend/src/hooks/useTheme.ts)
- Tạo hook `useTheme` để quản lý giao diện Sáng/Tối:
  - Quản lý trạng thái theme (`light`, `dark`, `system`).
  - Nếu chọn `system`, sử dụng `window.matchMedia('(prefers-color-scheme: dark)')` để lắng nghe thiết lập hệ điều hành của người dùng.
  - Thêm hoặc xóa class `dark` khỏi thẻ `<html>` hoặc `<body>` của ứng dụng.

#### [MODIFY] [index.css](file:///home/locpham/travelplanning/frontend/src/index.css)
- Bổ sung cấu hình màu sắc cơ bản cho dark mode: định nghĩa các màu nền và chữ chính cho chế độ tối để đảm bảo độ tương phản tốt nhất và đồng bộ thiết kế.

#### [MODIFY] [ExploreMap.tsx](file:///home/locpham/travelplanning/frontend/src/pages/ExploreMap.tsx), [MemberDashboard.tsx](file:///home/locpham/travelplanning/frontend/src/pages/MemberDashboard.tsx), [LandingPage.tsx](file:///home/locpham/travelplanning/frontend/src/pages/LandingPage.tsx)
- **Tích hợp Dark Mode**: Thêm các lớp CSS Tailwind như `dark:bg-slate-900`, `dark:text-slate-100`, `dark:border-slate-800` vào tất cả các card, danh sách và thanh điều hướng chính.
- **Thanh công cụ**: Thêm dropdown lựa chọn ngôn ngữ (Tiếng Việt, Tiếng Anh, Tiếng Trung) và nút chuyển đổi giao diện (Sáng/Tối/Hệ thống) ở Sidebar/Header cạnh nút Đăng xuất hoặc trong Menu Cài đặt của Admin.
- **Áp dụng Đa ngôn ngữ**: Thay thế toàn bộ text hiển thị tĩnh bằng hàm dịch `t('key')` (ví dụ: `t('explore')`, `t('logout')`, `t('trusted_members')`,...).

#### [MODIFY] [ItineraryTimeline.tsx](file:///home/locpham/travelplanning/frontend/src/components/ItineraryTimeline.tsx)
- Bổ sung click vào địa điểm để xem trên bản đồ (gọi `onNavigate`).
- Áp dụng các lớp Tailwind chế độ tối (`dark:bg-slate-900`, `dark:border-slate-800`, `dark:text-gray-100`) để các thẻ chặng và chi tiết điểm dừng hiển thị hoàn hảo ở Dark Mode.
- Thay các đoạn text tĩnh bằng đa ngôn ngữ.

#### [MODIFY] [TourDetailPage.tsx](file:///home/locpham/travelplanning/frontend/src/pages/TourDetailPage.tsx)
- Thêm nút "Xuất PDF" (không kèm chi phí) sử dụng `html2pdf.js` từ CDN.
- Tích hợp Đánh giá ban tổ chức 5 sao.
- Tích hợp Đa ngôn ngữ và Dark Mode vào toàn bộ trang chi tiết hành trình.

#### [MODIFY] [PublicPhotoModal.tsx](file:///home/locpham/travelplanning/frontend/src/components/PublicPhotoModal.tsx)
- Cho phép xóa bình luận nếu thỏa mãn điều kiện quyền hạn.
- Tích hợp Đa ngôn ngữ và Dark Mode.

#### [MODIFY] [CoordinateSelectModal.tsx](file:///home/locpham/travelplanning/frontend/src/components/CoordinateSelectModal.tsx)
- Ẩn liên kết Leaflet bằng `attributionControl={false}`.
- Bổ sung ô tìm kiếm địa điểm tích hợp Nominatim API.
- Tích hợp Dark Mode (bảng kết quả tìm kiếm và các khung modal chuyển sang màu tối phù hợp).

#### [NEW] [ShareJourneyPage.tsx](file:///home/locpham/travelplanning/frontend/src/pages/ShareJourneyPage.tsx)
- Giao diện chia sẻ khẩn cấp, tích hợp Đa ngôn ngữ và hỗ trợ cả 2 chế độ Sáng / Tối.

#### [MODIFY] [App.tsx](file:///home/locpham/travelplanning/frontend/src/App.tsx)
- Cập nhật logic route `/journey/:token`.
- Bao bọc ứng dụng để khởi chạy ngôn ngữ và theme mặc định dựa trên cấu hình hệ thống / localStorage khi ứng dụng khởi chạy.

---

## Verification Plan

### Automated Tests
- Chạy biên dịch toàn bộ hệ thống để phát hiện lỗi TypeScript:
  - Backend: `npm run build -w backend`
  - Frontend: `npm run build -w frontend` hoặc chạy bộ kiểm tra TypeScript: `npx tsc --noEmit` ở thư mục frontend.

### Manual Verification
1. **Kiểm tra Đa ngôn ngữ**:
   - Chuyển đổi ngôn ngữ sang Tiếng Anh / Tiếng Trung.
   - Xác nhận tất cả tiêu đề, nhãn, nút bấm, thông báo toast cập nhật sang ngôn ngữ mới.
2. **Kiểm tra Dark Mode**:
   - Thay đổi cài đặt sang "Tối". Xác nhận toàn bộ giao diện (kể cả các card trắng ở dashboard, timeline, map modal) chuyển thành màu tối.
   - Thay đổi cài đặt sang "Hệ thống". Đổi cấu hình hệ điều hành từ Light sang Dark và ngược lại để xác nhận trang web đổi giao diện tương ứng theo thời gian thực.
3. **Kiểm tra click địa điểm xem bản đồ**: Xác nhận click vào địa điểm timeline tự động nhảy sang tab bản đồ và hiển thị lộ trình.
4. **Kiểm tra xuất PDF**: Xác nhận xuất lịch trình ra file PDF không chứa thông tin chi phí.
5. **Kiểm tra xóa bình luận công khai, lọc ảnh & text, chia sẻ khẩn cấp, admin secret key**.
