Luồng Social / Reels — Like · Bình luận · Chia sẻ · Thống kê
Domain: D-SOCIAL · WP: WP-SOC-ENGAGE-01 Surfaces: CON (Expo) + API (NestJS) Ngày: 2026-08-19 Status: IMP
Tài liệu này mô tả cách dữ liệu chạy khi người dùng thả tim, bình luận, lưu, chia sẻ trên Luồng (Social) và Reels (Video) — từ icon UI → REST → Postgres → số đếm trên màn hình.
1. Hai bề mặt, một bảng bài viết
Reels và bài tường không phải hai hệ thống. Cả hai đọc/ghi SocialPost (social_posts).
| Tab CON | Màn | Nguồn feed | Kind bài điển hình |
|---|---|---|---|
| Social | SocialFeedScreen · tab Luồng |
GET /social/posts/feed hoặc /posts/following |
STATUS · NEWS · PHOTO · VIDEO · REEL |
| Social | tab Video | Cùng list, lưới VideoExploreTile |
Có mediaUrls |
| Reels | ReelsFeedScreen |
GET /social/reels/feed hoặc /reels/following |
VIDEO / REEL (filter phía BE) |
Đăng từ CreatePostScreen → POST /social/posts (ảnh/video đã gỡ EXIF ở POST /upload/single, WP-MEDIA-STRIP-01).
flowchart LR
subgraph CON["App khách"]
Luong["Luồng SocialPostCard"]
Reels["Reels ReelPage"]
Sheet["CommentsSheet"]
end
subgraph API["NestJS /social"]
Feed["feed / following"]
Act["like save comment share"]
end
subgraph DB["Postgres"]
P["social_posts"]
L["post_likes"]
C["post_comments"]
S["post_shares"]
B["post_saves"]
end
Luong --> Feed
Reels --> Feed
Luong --> Act
Reels --> Act
Sheet --> Act
Feed --> P
Act --> L
Act --> C
Act --> S
Act --> B
Act --> P
2. Bộ đếm trên mỗi bài (SocialPost)
| Field | Ý nghĩa | Tăng khi | Giảm khi |
|---|---|---|---|
likeCount |
Số tim | POST .../like (lần đầu) |
Unlike (toggle lần 2) |
commentCount |
Số bình luận (kể cả reply) | POST .../comments |
Soft-delete comment (nếu có) |
shareCount |
Số lần chia sẻ đã ghi | POST .../share sau OS share sheet |
Không giảm |
saveCount |
Số bookmark | POST .../save |
Bỏ lưu |
viewCount |
Lượt xem chi tiết | GET /posts/:id hoặc /reels/:id |
Không |
Cờ theo viewer đang login:
| Flag | Nguồn |
|---|---|
liked |
Có dòng post_likes (postId, userId) |
saved |
Có dòng post_saves (postId, userId) |
Feed serialize (SocialService.serializePost) trả đủ 5 số + 2 cờ để UI không đoán.
3. Icon trên UI ↔ hành vi
3.1 Luồng (SocialPostCard)
Hàng action (trái → phải): tim → bình luận → chia sẻ · spacer · bookmark.
| Icon | Gesture | API | Cập nhật UI |
|---|---|---|---|
Tim (heart) |
Tap | POST /social/posts/:id/like |
Optimistic liked + likeCount ±1; sync res.liked |
| Bình luận | Tap | Mở CommentsSheet |
GET /posts/:id/comments · gửi POST .../comments |
| Chia sẻ | Tap | OS Share.share rồi POST /posts/:id/share { channel: "native" } |
shareCount từ response |
| Bookmark | Tap | POST /social/posts/:id/save |
saved + saveCount |
Số dưới icon: formatReelCount (1.2K / 1.2M).
3.2 Reels (ReelPage)
Rail phải: avatar+follow · tim · bình luận · bookmark · chia sẻ · đĩa nhạc.
| Gesture | Hành vi |
|---|---|
| Tap 1 lần video | Pause / play |
| Double-tap video | Tim + animation trái tim (DoubleTapHeart) → cùng like API |
| Tap tim | Toggle like |
| Tap bình luận | Sheet giống luồng (postId = id reel = id SocialPost) |
| Tap chia sẻ | Cùng sharePostToSheet |
3.3 Sheet bình luận
- List + reply (
parentId) - Tim trên từng comment:
POST /social/comments/:id/like→CommentLike+PostComment.likeCount - Gửi xong:
onCountChangecập nhật badge trên reel/card
4. REST (tag Swagger social)
Cùng postId dùng được cho bài tường và reel (alias /reels/:id/... gọi cùng service).
| Method | Path | Auth | Side effect |
|---|---|---|---|
| GET | /social/posts/feed |
optional JWT | List + liked/saved nếu có token |
| GET | /social/posts/following |
JWT | Chỉ author đang follow |
| GET | /social/reels/feed |
optional | Filter video/reel |
| GET | /social/reels/following |
JWT | |
| POST | /social/posts/:id/like |
JWT | Toggle PostLike; trả { liked, postId, likeCount } |
| POST | /social/posts/:id/save |
JWT | Toggle PostSave; { saved, postId, saveCount } |
| POST | /social/posts/:id/share |
JWT | WP-SOC-ENGAGE-01 · PostShare + shareCount++ |
| POST | /social/reels/:id/share |
JWT | Cùng share() |
| POST | /social/posts/:id/comments |
JWT | PostComment + commentCount++ + notif social.comment |
| GET | /social/posts/:id/comments |
optional | List + liked từng comment |
| POST | /social/comments/:id/like |
JWT | Toggle tim comment |
| POST | /social/follow/:userId |
JWT | Follow |
Like bài → notif social.like cho tác giả (không tự notif chính mình).
5. Luồng runtime (ví dụ: thả tim)
sequenceDiagram
participant U as User
participant FE as SocialPostCard / ReelPage
participant API as POST /posts/:id/like
participant DB as post_likes + social_posts
U->>FE: tap / double-tap tim
FE->>FE: optimistic liked + likeCount
FE->>API: JWT
API->>DB: tồn tại PostLike?
alt đã like
DB-->>API: xóa like, likeCount-1
API-->>FE: liked=false, likeCount
else chưa like
DB-->>API: tạo like, likeCount+1
API-->>FE: liked=true, likeCount
API-->>DB: AppNotification social.like
end
FE->>FE: set liked theo server (rollback nếu lỗi)
Chia sẻ
- Mở sheet hệ thống (Zalo / Messages / copy…).
- Nếu user không huỷ (
Share.dismissedAction) →SocialApi.share(postId, "native"). - BE ghi
post_shares.channel = nativevà tăngshareCount. - FE gán
shareCounts[id]=res.shareCount.
6. Thống kê — công thức & chỗ hiện
| Chỉ số | Công thức | Hiện ở |
|---|---|---|
| Tim bài | COUNT(post_likes) ≈ likeCount (denormalized) |
Card luồng · rail Reels |
| Bình luận | COUNT(post_comments WHERE deletedAt IS NULL) ≈ commentCount |
Card · rail · title sheet |
| Tim comment | comment.likeCount |
Trái tim nhỏ mỗi dòng |
| Chia sẻ | COUNT(post_shares) ≈ shareCount |
Card · rail Reels |
| Lưu | COUNT(post_saves) ≈ saveCount |
Bookmark Reels (+ card) |
| Xem | viewCount |
Overlay lưới explore / profile cell (viewCount ?? likeCount) |
| Followers | SocialProfile.followerCount |
SocialProfileScreen |
Lưu ý denormalize: số trên SocialPost.*Count tăng/giảm trong cùng transaction với bảng event. Không scan COUNT mỗi lần render feed.
Explore tile hiện viewCount ?? likeCount (play badge) — không phải lượt play realtime.
7. File đụng (WP-SOC-ENGAGE-01)
| Layer | File |
|---|---|
| BE | api/src/modules/social/social.controller.ts · social.service.ts |
| FE API | mobile/src/services/api.ts (SocialApi.share, counts) |
| Helper | mobile/src/features/social/sharePost.ts |
| UI | SocialPostCard · SocialFeedScreen · ReelPage · ReelsFeedScreen · CommentsSheet |
8. Cách kiểm tra nhanh
- Login CON → Social → Luồng → tim (icon đỏ, số +1) → tim lại (trừ).
- Bình luận → sheet → gửi → số comment trên card tăng; tim comment.
- Chia sẻ → chọn app hoặc copy → số share tăng (nếu huỷ sheet thì không ghi BE).
- Reels → double-tap video = tim; rail comment/share/save cùng
postId. - Swagger
/docstagsocial:POST /posts/{id}/share.
Restart API nếu process cũ chưa load route share bài tường.