Skip to content

Màn quản trị — Cài đặt giới hạn từ khóa theo cửa hàng

Tổng quan

Thiết kế UI cho màn quản trị mới sẽ làm trong #1-3 Mở rộng giới hạn từ khóa — Phase 2.

Sales / CS có thể điều chỉnh giới hạn từ khóa theo từng cửa hàng dưới quyền sở hữu của user, trong khoảng 8〜15. Thao tác trên UI thay thế cho việc INSERT bằng SQL của Phase 1.

MụcNội dung
Vị tríThêm 1 tab "Giới hạn từ khóa" vào page MappyUserDetail có sẵn (URL: /admin/users/:userId/details)
Guardauth:admin_api (đã có)
Bảng dữ liệumappy_keyword_limit_settings (scope_type='location')
AuditTích hợp ActivityLog

Phương châm tích hợp vào màn hình hiện có

Bám sát navigation admin của mappy đang có (không tạo route mới):

/admin/login

/admin/users                          [MappyUserList]   ← sidebar "MAPPY管理"
    ↓ (click loginId)
/admin/users/:userId/details          [MappyUserDetail] ← thêm 1 tab vào 2 tab đã có
    ├ Tab1: Thông tin tài khoản       (đã có · không sửa)
    ├ Tab2: Cài đặt thông báo         (đã có · không sửa)
    └ Tab3: Giới hạn từ khóa         ★ Mới ở Phase 2

File cần sửa

FileNội dung sửa
resources/js/mappy/views/admin/UserDetail.vueThêm tab 3. Mở rộng <v-tabs> từ 2 → 3
resources/js/mappy/views/admin/UserKeywordLimitTab.vue ★ MớiNội dung chính của màn (bảng shop + edit inline)
resources/js/mappy/include/selectors/StoreAndGroupSelector.vueKhông sửa (tab 1 vẫn dùng)
app/Http/Controllers/Mappy/Admin/LocationController.phpBổ sung max_keywords vào response của getUserLocationsAndGroups()
app/Http/Controllers/Mappy/Admin/KeywordLimitController.php ★ MớiImplement PATCH / DELETE endpoint
routes/mappy/api.phpThêm 2 dòng /admin/locations/{loc}/keyword-limit

Không cần thêm mục vào resources/js/mappy/_navigationAdmin.js. Tính năng nằm sâu trong "MAPPY管理" hiện có, không thêm top-level menu.

Mock màn hình

アカウント情報

user-standard-planプラン上限:8 件契約:2025-04-01 〜 2026-03-31(12ヶ月)所属店舗数:5
このユーザ配下の店舗ごとに 8〜15 件の範囲でキーワード上限を設定できます。
対象ユーザ配下の店舗一覧
店舗名プラン値現在の上限新しい上限メモ(課金根拠)有効期間操作
渋谷本店
location_id: 8801
815
2026-06-01
〜 無期限
新宿西口店
location_id: 8802
88
〜 無期限
池袋東口店
location_id: 8803
812
2026-05-15
〜 2026-12-31
横浜西口店
location_id: 8804
88
〜 無期限
川崎駅前店
location_id: 8805
810
2026-06-01
〜 無期限
上限の範囲は 8〜15 件。8 にすると override が解除され、プランデフォルト適用に戻ります。

呼び出し API(参考)

MethodPath役割
GET/api/mappy/admin/users/{user}/locations-and-groups店舗一覧取得(既存 API を拡張:resolved + override を含める)
PATCH/api/mappy/admin/locations/{loc}/keyword-limit店舗別上限を upsert(新設)
DELETE/api/mappy/admin/locations/{loc}/keyword-limitoverride 解除(新設)

Lưu ý: nằm dưới dạng 1 tab trong UserDetail. Tab Thông tin tài khoản / Cài đặt thông báo chỉ hiển thị dummy (giữ nguyên implement cũ, không sửa trong case này).

Thành phần màn hình

Phần header (kế thừa từ MappyUserDetail)

Thành phầnVai trò
BreadcrumbQuản trị / MAPPY管理 (danh sách user) / loginId user
Chip thông tin userPlan / giới hạn plan / kỳ hợp đồng / số shop sở hữu
Tab barThông tin tài khoản / Cài đặt thông báo / Giới hạn từ khóa (kèm badge số override)

Toolbar trong tab "Giới hạn từ khóa"

Thành phầnVai trò
Mô tả"Có thể đặt giới hạn từ khóa 8〜15 cho từng cửa hàng dưới user này…"
Toggle audit logHiển thị inline 5 thay đổi gần nhất
Nút lưu hàng loạtChỉ active khi có thay đổi, kèm badge số dòng đã đổi

Bảng danh sách cửa hàng

CộtNội dungCó thể sửa
Tên cửa hàngTên + location_idKhông (link tới chi tiết shop)
Plan valueGiá trị mặc định từ user.plan.maxKeywordsKhông
Giới hạn hiện tạiGiá trị resolved (badge màu thể hiện trạng thái)Không
Giới hạn mớiStepper input 8〜15
MemoGhi chú sales / cơ sở tính phí (255 ký tự)
Hiệu lựceffective_from 〜 effective_toKhông (tự set)
Thao tácNút "Gỡ" → xoá override

Quy tắc màu badge

Trạng tháiMàuÝ nghĩa
Chỉ plan valueXámKhông có override, max_keywords = NULL
Đang overrideVàngVượt plan value nhưng dưới 15
Tối đaXanh láĐặt 15 (giới hạn hệ thống)

Filter

  • Tìm kiếm tên cửa hàng incremental
  • Select: tất cả / có override / chỉ plan value

Flow thao tác

Case 1: Nâng 1 cửa hàng từ 8 → 15

Case 2: Gỡ override (trở về plan value)

BướcThao tácKết quả
1Nhấn nút "Gỡ" trên dòng đóInput về 8 (plan default), dòng được highlight "changed"
2Nhấn nút lưu hàng loạtGọi DELETE /api/mappy/admin/locations/{loc}/keyword-limit
3API soft-delete bản ghiSet effective_to = CURDATE() - 1 day
4Ghi ActivityLog"Shop XYZ: 12 → 8, by xxx"

Case 3: Sửa hàng loạt

Edit nhiều input → nút lưu hàng loạt hiện "(N dòng)" → 1 transaction PATCH tất cả.

Validation

MụcQuy tắcHiển thị lỗi
max_keywordsSố nguyên, 8 ≤ N ≤ 15Viền ô đỏ + tooltip lý do
memo0〜255 ký tựVượt → disable nút lưu
effective_toNULL hoặc ≥ effective_fromBackend trả 400
override = plan valueKhông warning, UI hiểu là DELETE

Tích hợp ActivityLog

Khi PATCH / DELETE thành công, tự ghi vào ActivityLog. Cấu trúc:

json
{
  "action": "keyword_limit.updated",
  "actor_id": 42,
  "target_type": "gbp_location",
  "target_id": 8801,
  "before": { "max_keywords": 8,  "memo": null },
  "after":  { "max_keywords": 15, "memo": "Sales #4521 / +¥9,800/tháng" },
  "created_at": "2026-06-01 14:32:00"
}

Thông tin này là nguồn cho việc tích hợp nền tảng tính phí (case tiếp theo) mở rộng payload.

Responsive

WidthHành vi
PC (≥768px)Hiển thị toàn bộ cột, không scroll ngang
Mobile (<768px)Ẩn cột memo & effective, ưu tiên core (tên shop / sửa limit / lưu)

Phân quyền

RoleXemSửaGỡ
admin
cs_operator✅ (chỉ 8〜12)
sales_viewer

Cài đặt max_keywords > 12 chỉ admin được làm (cần xác nhận sales / billing).

Accessibility

  • Stepper là tổ hợp <button> + <input type="number"> (thao tác bàn phím được)
  • Dòng changed không chỉ đổi nền mà còn có aria-label cho screen reader
  • Không trap focus (do là inline edit, không phải modal)

Liên kết