# Kế hoạch: Tái thiết kế giao diện xem ảnh và bình luận trên Mobile (PublicPhotoModal) Thiết kế lại giao diện mobile của modal xem ảnh công khai để trải nghiệm cuộn trang tự nhiên hơn, tương tự như Instagram/Twitter — ảnh chiếm toàn bộ chiều rộng màn hình từ trên xuống, thông tin người đăng và các nút được bố cục rõ ràng, sau đó cuộn xuống xem bình luận một cách liền mạch. --- ## Phân tích hiện trạng Cấu trúc hiện tại của modal trên mobile (`flex flex-col`): 1. **Container (90vh, overflow-hidden)** — toàn bộ nội dung bị "kẹt" trong 90vh 2. Phần ảnh (`h-[45vh]`) — cố định, không thể co giãn 3. Phần "Mobile Uploader" strip — cố định (`shrink-0`) 4. Phần comment panel (`flex-1 min-h-0`) — chỉ phần danh sách comment cuộn bên trong **Vấn đề**: Ảnh bị giới hạn ở `h-[45vh]`, có padding `p-4` từ container ngoài nên không chạm mép màn hình. Nút like nằm ở góc trên trái (gần nút X), người đăng nằm ở vùng riêng giữa ảnh và comment, không cuộn cùng content. --- ## Thay đổi đề xuất ### [MODIFY] [PublicPhotoModal.tsx](file:///home/locpham/travelplanning/frontend/src/components/PublicPhotoModal.tsx) #### 1. Outer wrapper — Bỏ padding và căn giữa **Hiện tại** (line 358): ```
``` **Thay thành** — trên mobile modal full screen, không padding, không căn giữa. Desktop giữ nguyên layout cũ: ```
``` #### 2. Container modal — Mobile: full screen cuộn tự nhiên; Desktop: giữ nguyên **Hiện tại** (line 366): ```
``` **Thay thành**: - Mobile: `fixed inset-0 overflow-y-auto flex flex-col bg-slate-900` — toàn màn hình, cuộn tự nhiên theo trang - Desktop: `relative w-full max-w-5xl h-[85vh] overflow-hidden flex flex-row rounded-[32px]` ```
``` #### 3. Nút X — Fixed ở góc trên phải (hiện tại đúng, cần giữ nguyên) Nút X hiện đang dùng `fixed` — **giữ nguyên**, chỉ điều chỉnh `top` để tính safe-area: ``` className="fixed top-[calc(1rem+env(safe-area-inset-top,0px))] right-4 z-50 ..." ``` #### 4. Phần ảnh (Left Side Photo) — Mobile: full width, không giới hạn chiều cao, aspect ratio tự nhiên **Hiện tại** (line 377): ```
``` **Thay thành** — Trên mobile: ảnh full width, chiều cao theo tỷ lệ ảnh (aspect-ratio), không giới hạn, chạm mép trên màn hình (không có padding trên): ```
``` Với ảnh bên trong: ``` ``` #### 5. Nút Like — Di chuyển từ góc trên trái sang góc dưới phải của vùng ảnh **Hiện tại**: `absolute top-[...] left-4` — góc trên bên trái. **Thay thành**: `absolute bottom-4 right-4` — góc dưới bên phải của ảnh, không bị che bởi thanh địa chỉ và không xung đột với nút X: ``` className="absolute bottom-4 right-4 z-40 ..." ``` #### 6. Thông tin người đăng — Di chuyển thành overlay góc trên trái trên ảnh Hiện tại "Mobile Uploader strip" là một block riêng biệt giữa ảnh và comment (`block md:hidden p-6 ...`). **Thay thành**: Overlay trực tiếp trên ảnh ở góc **trên bên trái**, nằm trong vùng ảnh, có safe-area padding: ```html
{photo.uploader?.name || 'Ẩn danh'}
``` #### 7. "Mobile Uploader strip" block — Xóa block cũ Block `{/* Mobile Only: Uploader details & divider */}` ở lines 597–623 sẽ được **xóa** vì thông tin người đăng đã được hiển thị trực tiếp trên ảnh ở bước 6. Nếu `isAuthorized && photo.originalUrl` (nút Tải ảnh gốc): sẽ được giữ lại nhưng chuyển vào trong phần metadata/overlay của ảnh hoặc đặt trước phần comments. #### 8. Phần Comments — Cuộn cùng với nội dung (không bị kẹt trong flex) Trên mobile, toàn bộ trang cuộn — phần comment không cần `overflow-y-auto` riêng nữa (vì parent đã cuộn): **Hiện tại** (line 626): ```
``` **Thay thành**: ```
``` Danh sách bình luận (line 640): ```
``` → Trên mobile không giới hạn `overflow-y-auto`: ```
``` #### 9. Comment Input — Sticky ở cuối trang trên mobile Thay vì nằm cố định cuối flex column, ô nhập bình luận sẽ sticky ở bottom: ```
``` --- ## Tóm tắt layout cuối cùng trên mobile ``` ┌─────────────────────────────────────────────┐ ← màn hình (fixed inset-0) │ [X nút đóng] (góc trên phải, fixed/z-50) │─────────────────────────────────────────────│ │ │ │ [Người đăng] (overlay TL) │ │ │ ← Vùng ảnh (full width, │ ẢNH │ height theo tỷ lệ) │ │ │ [❤ Like + số] │ │─────────────────────────────────────────────│ │ 📷 Timeline ảnh (nếu có nhiều ảnh) │ ← Cuộn cùng trang │─────────────────────────────────────────────│ │ Tiêu đề, mô tả, ngày chụp, địa điểm │ ← Info overlay panel │─────────────────────────────────────────────│ │ [Tải ảnh gốc] (nếu là chủ sở hữu) │ │─────────────────────────────────────────────│ │ 💬 Comment 1 │ ← Cuộn cùng trang │ 💬 Comment 2 │ │ 💬 Comment 3 │ │ ... │ │─────────────────────────────────────────────│ │ [Viết bình luận...] [▶ Gửi] (sticky bottom)│ └─────────────────────────────────────────────┘ ``` --- ## Verification Plan ### Automated Tests - `npm run build -w frontend` — không có lỗi compilation. ### Manual Verification 1. Mở app trên Chrome mobile (Android) → modal mở full screen, ảnh chạm top, không có padding. 2. Nút X hiển thị góc trên phải, luôn visible. 3. Tên người đăng hiển thị overlay góc trên trái, không nhầm với người bình luận. 4. Nút like hiển thị góc dưới phải của ảnh. 5. Vuốt lên → ảnh và bình luận cuộn cùng nhau một cách liền mạch. 6. Ô bình luận sticky ở dưới cùng. 7. Trên desktop (≥768px) layout 2 cột giữ nguyên hoàn toàn. 8. Safe area insets hoạt động đúng trên iPhone (notch/Dynamic Island) dùng Safari.