專案

一般

配置概況

動作

Feature #1443

進行中

Feature #1442: [功能開發] CourseProfile 後台管理 API 與 FE 交接需求

[介面修改] CourseProfile 後台管理 UI

是由 陳國瑋 於 約 1 個月 前加入. 於 約 1 個月 前更新.

狀態:
Resolved
優先權:
Normal
被分派者:
開始日期:
2026-08-17
完成日期:
完成百分比:

0%

預估工時:

概述

目標

依父票 #1442 已完成的 CourseProfile 管理 API,新增後台「療程項目管理」UI。此票只處理 FE,不修改 API 或資料庫。

權限與選單

  • 僅 administrator role 可看到及操作。
  • 選單位置:Common Lists。
  • 選單名稱:療程項目管理。
  • 使用 migration 已建立的 SS3A functions:
    • course_profile_mgmt
    • course_profile_mgmt_list
    • course_profile_mgmt_create
    • course_profile_mgmt_edit
  • 不提供刪除功能或刪除按鈕。

UI 設計原則

  • Follow 現有後台其他列表頁設計與元件。
  • 沿用 SectionTitle、WrapperTable、Datatable、ActionButton、Switch 與既有搜尋表單元件。
  • Boolean 顯示文字使用「有/無」。
  • 搜尋欄位若不限制某旗標,request 不要帶該 property;不可用「全部」轉成 null 或空字串送出。
  • false 是有效搜尋值,不可用 truthy 判斷而漏傳。

列表頁

搜尋條件

  • 關鍵字:同時搜尋名稱與 description。
  • 是否啟用。
  • 日誌功能。
  • 滿意度調查。
  • 事後關懷卡。

四個 Boolean 篩選器的可選值只有「有/無」;未選擇代表不限制,API request 不帶該欄位。

列表欄位

  • Item ID
  • 名稱
  • 日誌功能(有/無)
  • 滿意度調查(有/無)
  • 事後關懷卡(有/無)
  • 狀態
  • 編輯操作

列表不顯示 Course/Booking 數量;數量只在狀態切換確認視窗顯示。

搜尋 API

POST /api/admin/course/profile/search

{
  "page": 1,
  "size": 10,
  "sidx": [],
  "sord": [],
  "keyword": "選填",
  "enabled": true,
  "hasDiary": true,
  "hasSatisfaction": false,
  "hasPostEventCard": true
}

只有使用者已選擇的 optional Boolean 才可放入 request。

新增頁

欄位:

  • 名稱:必填,最多 255 字元。
  • Description:選填。
  • 日誌功能:必填,有/無。
  • 滿意度調查:必填,有/無。
  • 事後關懷卡:必填,有/無。

建立前必須顯示確認視窗,列出名稱與三個建立後不可變更的旗標。取消時不得送出 request。

POST /api/admin/course/profile/create

{
  "name": "必填",
  "description": "選填",
  "hasDiary": true,
  "hasSatisfaction": false,
  "hasPostEventCard": false
}

注意事項:

  • 不傳 enabled,後端固定新建為 false。
  • 名稱會由後端 trim,且包含停用資料永久唯一。
  • 名稱重複時 API 回 HTTP 409,response 含 field: "name",須將錯誤顯示在名稱欄位。
  • 建立成功後回列表,資料顯示為停用。

編輯頁

先呼叫:

GET /api/admin/course/profile/info/{id}

顯示欄位:

  • 名稱:唯讀。
  • 日誌功能:唯讀。
  • 滿意度調查:唯讀。
  • 事後關懷卡:唯讀。
  • Description:可修改。
  • 是否啟用:可修改。

更新 API:

POST /api/admin/course/profile/update

{
  "id": "Pxxxxxxx",
  "description": "選填",
  "enabled": true
}

FE 不得傳 name 或三個功能旗標。

  • 只修改 description 時可直接送出 update。
  • enabled 有變更時,必須先取得 impact 並顯示確認視窗;管理員確認後才送出 update。
  • 管理員取消時不得送出 update,畫面狀態維持原值。

列表狀態切換

列表 Switch 不可先行改變畫面狀態。操作流程:

  1. 呼叫 GET /api/admin/course/profile/status/impact/{id}。
  2. 顯示確認視窗。
  3. 管理員確認後呼叫 status switch。
  4. 成功後重新取得列表或更新畫面狀態。
  5. 取消或 API 失敗時 Switch 回復原值。

Impact response:

{
  "id": "Pxxxxxxx",
  "name": "療程名稱",
  "enabled": true,
  "courseCount": 123,
  "bookingCount": 45
}

確認視窗必須顯示:

  • CourseProfile 名稱。
  • Course 歷史總數。
  • Booking 歷史總數。
  • 啟用/停用影響說明。

提示文字語意:

  • 啟用:啟用後會出現在新建 Course 與 Booking 的選單。
  • 停用:停用後不再出現在新建 Course 與 Booking 的選單;既有 Course、Booking 及歷史流程不受影響。

Status switch API:

POST /api/admin/course/profile/status/switch

{
  "id": "Pxxxxxxx",
  "newStatus": false
}

API 清單

  • POST /api/admin/course/profile/search
  • GET /api/admin/course/profile/info/{id}
  • POST /api/admin/course/profile/create
  • POST /api/admin/course/profile/update
  • GET /api/admin/course/profile/status/impact/{id}
  • POST /api/admin/course/profile/status/switch

Backend branch:feature/redmine-1442-course-profile-admin

Backend commits:3cb9c49、d9d2a0b、438da92、6520c0c

API 測試報告:test_report/20260817_redmine_1442_course_profile_admin.md

驗收條件

  • 非 administrator 看不到選單,且不能進入功能頁。
  • 列表、搜尋、分頁、排序 follow 現有後台設計。
  • keyword 可搜尋名稱與 description。
  • 未選 Boolean 時不帶 property;選「無」時正確傳 false。
  • 新增前顯示確認視窗;新資料固定停用。
  • 編輯頁名稱與三旗標不可修改。
  • 列表與編輯頁修改 enabled 前都顯示 impact 確認視窗。
  • 確認視窗顯示 Course/Booking 數量與影響說明。
  • 取消操作不得改變資料或 Switch 畫面狀態。
  • 名稱重複錯誤能對應到名稱欄位。
  • 不出現 delete 操作。

環境注意事項

截至 2026-08-17,公開 staging API hm-api.line2me.tw 回 HTTP 503。開始串接前請先確認父票分支已部署且 staging API 恢復。

是由 陳國瑋 於 約 1 個月 前更新

  • 被分派者 設定為 鍾正剛

是由 鍾正剛 於 約 1 個月 前更新

開發完成(FE)

branch: feature/issue-1443-course-profile-admin-ui(自 main 開,未合併)
commits: 048b3de 實作、cc7965b code review 修正

一、實作內容

頁面位於 react/admin/app/common/course-profile/,對應 migration 的 function_url。

  • 列表:關鍵字(名稱/說明)+ 是否啟用、日誌功能、滿意度調查、事後關懷卡四個篩選;欄位為 Item ID、名稱、三旗標(有/無)、狀態、編輯;沿用既有 SectionTitle/WrapperTable/Datatable/ActionButton/Switch,未提供任何刪除功能。
  • 搜尋 request:未選擇的 Boolean 不會出現在 request 中,選「無」會送出真正的 false。此段邏輯(helper.js 的 buildSearchPayload)另外寫了驗證,並以「故意改成 truthy 判斷」反向確認驗證確實會失敗。
  • 新增:送出前二次確認名稱與三個不可變更旗標,取消不送 request;payload 不含 enabled。
  • 編輯:名稱與三旗標唯讀且不進入 payload,update 只送 {id, description, enabled};enabled 未變更直接送出,有變更則先取 impact 確認。
  • 狀態切換:Switch 畫面狀態完全由查詢結果決定,不先行改變;流程為 impact → 確認視窗 → switch → refetch,取消或失敗皆不改變畫面。
  • 確認視窗顯示 CourseProfile 名稱、Course 歷史總數、Booking 歷史總數,以及啟用/停用的影響說明。
  • 名稱重複(HTTP 409,body field: "name")顯示於名稱欄位,不跳共用錯誤視窗。

二、與票面規格的補充說明

驗收條件的「非 administrator 不能進入功能頁」,現行 admin 專案沒有任何 page 層級的權限守衛,既有模組都只靠選單隱藏加後端 403。本次在本模組內加了一個 guard:讀取後端回傳的選單樹,比對不到對應的 function url 就顯示 403 區塊。

刻意未沿用既有的 src/components/auth/not-allowed,因為該元件會 redirect('/signin'),會把已登入但無此權限的管理員直接登出。

此 guard 僅作用於本模組,未改動其他模組;若日後要全站套用再抽共用元件。

三、驗證範圍

  • yarn lint:0 error。
  • 三條新路由於 dev server 均編譯成功。
  • 搜尋 payload 組裝邏輯:16 項檢查全數通過。
  • 未執行:六支 API 的實際串接驗證,需 administrator token,待人工於瀏覽器登入後確認。

四、與本票無關的既有問題

react/admin 的 yarn build 目前失敗:

static/chunks/0e02fca3-*.js from Terser
invalid unicode code point at line 1 column 562193

已在乾淨的 main(未含本次變更)重現,錯誤與位移完全相同,確認為既有問題、非本次造成。目前此專案無法產出 production build,建議另開票處理。

是由 鍾正剛 於 約 1 個月 前更新

  • 狀態 從 New 變更為 Resolved
動作

匯出至 Atom PDF