588 lines
19 KiB
Markdown
588 lines
19 KiB
Markdown
# Prompt: Move Announcement Pin Action Out of Create/Edit Form
|
|
|
|
## Objective
|
|
|
|
ปรับปรุงการจัดการฟังก์ชัน **ปักหมุดประกาศ** โดยนำตัวเลือกปักหมุดออกจากหน้าสร้างและหน้าแก้ไขประกาศ แล้วเปลี่ยนให้เป็น Action ที่ใช้งานหลังจากประกาศได้รับการเผยแพร่แล้ว
|
|
|
|
เป้าหมายคือ:
|
|
|
|
- ลดความซับซ้อนของแบบฟอร์มสร้างประกาศ
|
|
- แยกการจัดการเนื้อหาออกจากการจัดลำดับการแสดงผล
|
|
- ทำให้ Workflow ของประกาศชัดเจน
|
|
- จำกัดการปักหมุดตามสถานะและ Permission
|
|
- ใช้โครงสร้างเดิมของระบบให้มากที่สุด
|
|
|
|
---
|
|
|
|
# Existing Structure Review
|
|
|
|
ก่อนเริ่มแก้ไข ให้ตรวจสอบโครงสร้างเดิมที่เกี่ยวข้องทั้งหมด เช่น:
|
|
|
|
- Announcement database schema
|
|
- `is_pinned`, `pinned_at`, `pinned_by` หรือ Field ที่มีความหมายใกล้เคียง
|
|
- Create/Edit announcement form
|
|
- Announcement list
|
|
- Announcement detail
|
|
- Action menu
|
|
- API routes
|
|
- Server actions
|
|
- Query และ Sorting
|
|
- Permission
|
|
- Audit log
|
|
- Publish workflow
|
|
|
|
หากระบบมีโครงสร้างรองรับการปักหมุดอยู่แล้ว ให้ Reuse และปรับเฉพาะ UI/Workflow ตามความเหมาะสม
|
|
|
|
ใช้หลัก:
|
|
|
|
> Reuse > Extend > Refactor > Create New
|
|
|
|
ห้ามสร้าง Field, API หรือ Business Logic ซ้ำโดยไม่จำเป็น
|
|
|
|
---
|
|
|
|
# Scope
|
|
|
|
ดำเนินการดังนี้:
|
|
|
|
1. นำตัวเลือกปักหมุดออกจากหน้าสร้างประกาศ
|
|
2. นำตัวเลือกปักหมุดออกจากหน้าแก้ไขประกาศ
|
|
3. เพิ่ม Action ปักหมุดในหน้า Announcement List
|
|
4. เพิ่ม Action ปักหมุดในหน้า Announcement Detail หากเหมาะสม
|
|
5. จำกัด Action ตาม Status และ Permission
|
|
6. ปรับ Query การเรียงประกาศ
|
|
7. เพิ่ม Audit Log หากระบบรองรับ
|
|
8. ตรวจสอบ Regression ของ Workflow เดิม
|
|
|
|
---
|
|
|
|
# Create Announcement Form
|
|
|
|
นำ Section หรือ Field ต่อไปนี้ออกจากหน้าสร้างประกาศ:
|
|
|
|
```text
|
|
ปักหมุดประกาศ
|
|
ประกาศที่ปักหมุดจะแสดงด้านบนของรายการ
|
|
```
|
|
|
|
หน้าสร้างประกาศควรมีเฉพาะ:
|
|
|
|
- หัวข้อประกาศ
|
|
- รายละเอียดประกาศ
|
|
- วันเริ่มแสดง
|
|
- วันสิ้นสุดการแสดง
|
|
- ไฟล์แนบ
|
|
- ยกเลิก
|
|
- บันทึกร่าง
|
|
- ส่งตรวจสอบ
|
|
|
|
ห้ามส่งค่า `isPinned` หรือค่าที่เกี่ยวข้องจาก Create Form เว้นแต่โครงสร้าง API เดิมกำหนดเป็น Required ให้ปรับเป็นค่า Default ที่ปลอดภัย เช่น `false`
|
|
|
|
ประกาศใหม่ต้องมีค่าเริ่มต้น:
|
|
|
|
```text
|
|
is_pinned = false
|
|
```
|
|
|
|
---
|
|
|
|
# Edit Announcement Form
|
|
|
|
นำตัวเลือกปักหมุดออกจากหน้าแก้ไขประกาศเช่นเดียวกัน
|
|
|
|
หน้า Edit ใช้สำหรับแก้ไขเนื้อหาและช่วงเวลาการแสดงผลเท่านั้น
|
|
|
|
ห้ามให้การบันทึกหน้า Edit เปลี่ยนสถานะการปักหมุดโดยไม่ได้ตั้งใจ
|
|
|
|
---
|
|
|
|
# Announcement List
|
|
|
|
เพิ่มสถานะการปักหมุดให้มองเห็นได้ในรายการ เช่น:
|
|
|
|
- ไอคอน Pin ข้างชื่อประกาศ
|
|
- Badge `ปักหมุด`
|
|
- คอลัมน์การแสดงผล หากเหมาะกับ Layout เดิม
|
|
|
|
ตัวอย่าง:
|
|
|
|
```text
|
|
📌 ประกาศวันหยุดประจำปี
|
|
```
|
|
|
|
หรือ:
|
|
|
|
```text
|
|
[ปักหมุด] ประกาศวันหยุดประจำปี
|
|
```
|
|
|
|
หลีกเลี่ยงการเพิ่มคอลัมน์ใหม่ หากทำให้ตารางกว้างเกินไป ให้ใช้ไอคอนหรือ Badge ภายในคอลัมน์ชื่อประกาศแทน
|
|
|
|
---
|
|
|
|
# Action Menu
|
|
|
|
ใน Action Menu ของแต่ละประกาศ เพิ่มคำสั่งตามสถานะ:
|
|
|
|
หากยังไม่ปักหมุด:
|
|
|
|
```text
|
|
ปักหมุดประกาศ
|
|
```
|
|
|
|
หากปักหมุดอยู่แล้ว:
|
|
|
|
```text
|
|
ยกเลิกการปักหมุด
|
|
```
|
|
|
|
ใช้ไอคอนที่สื่อความหมาย เช่น:
|
|
|
|
- `Pin`
|
|
- `PinOff`
|
|
|
|
Action ต้องมี `aria-label` และข้อความภาษาไทยที่ชัดเจน
|
|
|
|
---
|
|
|
|
# Announcement Detail
|
|
|
|
หากหน้า Detail มีชุด Action อยู่แล้ว ให้เพิ่ม:
|
|
|
|
```text
|
|
ปักหมุดประกาศ
|
|
```
|
|
|
|
หรือ:
|
|
|
|
```text
|
|
ยกเลิกการปักหมุด
|
|
```
|
|
|
|
ไม่จำเป็นต้องเพิ่ม หากจะทำให้ Action ซ้ำซ้อนและหน้า List รองรับการใช้งานครบถ้วนแล้ว
|
|
|
|
ให้เลือกแนวทางที่สอดคล้องกับ Pattern ของระบบเดิม
|
|
|
|
---
|
|
|
|
# Status Rules
|
|
|
|
อนุญาตให้ปักหมุดเฉพาะประกาศที่มีสถานะ:
|
|
|
|
```text
|
|
Published
|
|
```
|
|
|
|
และควรอยู่ในเงื่อนไข:
|
|
|
|
- วันเริ่มแสดงมาถึงแล้ว หรือระบบอนุญาตให้ปักหมุดล่วงหน้าอย่างชัดเจน
|
|
- วันสิ้นสุดยังไม่ผ่านมา
|
|
- ไม่ถูก Archive
|
|
- ไม่ถูก Soft Delete
|
|
|
|
ห้ามปักหมุดประกาศสถานะ:
|
|
|
|
- Draft
|
|
- Pending Review
|
|
- Rejected
|
|
- Approved but not Published
|
|
- Inactive
|
|
- Archived
|
|
- Deleted
|
|
- Expired
|
|
|
|
หากระบบใช้ชื่อ Status ต่างจากนี้ ให้ Mapping กับ Enum เดิมของโปรเจกต์ ห้ามสร้าง Enum ซ้ำ
|
|
|
|
---
|
|
|
|
# Automatic Unpin Rules
|
|
|
|
ระบบต้องยกเลิกการปักหมุดอัตโนมัติ หรือไม่นำประกาศนั้นมาแสดงเป็นปักหมุด เมื่อ:
|
|
|
|
- ประกาศถูก Unpublish
|
|
- ประกาศถูก Archive
|
|
- ประกาศถูก Soft Delete
|
|
- ประกาศหมดอายุ
|
|
- วันสิ้นสุดการแสดงผลผ่านไปแล้ว
|
|
|
|
เลือกแนวทางให้สอดคล้องกับ Architecture เดิม:
|
|
|
|
1. อัปเดต `is_pinned = false` เมื่อสถานะเปลี่ยน
|
|
2. หรือ Filter ออกจาก Pinned Query โดยไม่เปลี่ยนข้อมูลเดิม
|
|
|
|
ควรเลือกวิธีที่ลดความเสี่ยงของข้อมูลไม่สอดคล้องกัน และอธิบายไว้ในรายงาน
|
|
|
|
---
|
|
|
|
# Multiple Pinned Announcements
|
|
|
|
รองรับการปักหมุดหลายประกาศ
|
|
|
|
ลำดับการแสดงผล:
|
|
|
|
1. ประกาศที่ปักหมุดก่อน
|
|
2. ภายในกลุ่มปักหมุด เรียงตาม `pinned_at DESC`
|
|
3. หากไม่มี `pinned_at` ให้ใช้ `published_at DESC`
|
|
4. ประกาศทั่วไปเรียงตามมาตรฐานเดิมของระบบ
|
|
|
|
ตัวอย่าง Query Logic:
|
|
|
|
```text
|
|
is_pinned DESC
|
|
pinned_at DESC
|
|
published_at DESC
|
|
created_at DESC
|
|
```
|
|
|
|
ให้ปรับตาม Field ที่มีอยู่จริงในระบบ
|
|
|
|
---
|
|
|
|
# Confirmation Dialog
|
|
|
|
ก่อนปักหมุด แสดง Dialog:
|
|
|
|
```text
|
|
ยืนยันการปักหมุดประกาศ
|
|
|
|
ประกาศนี้จะแสดงอยู่ด้านบนของรายการประกาศ
|
|
คุณต้องการดำเนินการต่อหรือไม่
|
|
```
|
|
|
|
ปุ่ม:
|
|
|
|
```text
|
|
ยกเลิก
|
|
ปักหมุดประกาศ
|
|
```
|
|
|
|
ก่อนยกเลิกการปักหมุด แสดง Dialog:
|
|
|
|
```text
|
|
ยืนยันการยกเลิกปักหมุด
|
|
|
|
ประกาศนี้จะกลับไปเรียงตามลำดับประกาศทั่วไป
|
|
คุณต้องการดำเนินการต่อหรือไม่
|
|
```
|
|
|
|
ปุ่ม:
|
|
|
|
```text
|
|
ยกเลิก
|
|
ยกเลิกการปักหมุด
|
|
```
|
|
|
|
หาก Pattern เดิมของระบบไม่ใช้ Confirm Dialog กับ Action ลักษณะนี้ สามารถใช้ Action ทันทีพร้อม Toast ได้ แต่ต้องรักษามาตรฐานเดียวกับ Feature อื่น
|
|
|
|
---
|
|
|
|
# Permission
|
|
|
|
ใช้ Permission-first Architecture เท่านั้น
|
|
|
|
เพิ่มหรือ Reuse Permission:
|
|
|
|
```text
|
|
announcement:pin
|
|
```
|
|
|
|
Permission นี้ครอบคลุม:
|
|
|
|
- ปักหมุดประกาศ
|
|
- ยกเลิกการปักหมุด
|
|
|
|
ทุก API หรือ Server Action ต้องตรวจสอบ Permission ฝั่ง Server
|
|
|
|
ห้ามตรวจสอบเฉพาะฝั่ง Client
|
|
|
|
ผู้ไม่มี Permission:
|
|
|
|
- ไม่เห็น Action
|
|
- เรียก API โดยตรงไม่ได้
|
|
- ได้รับ Response ที่เหมาะสม เช่น `403 Forbidden`
|
|
|
|
หากมี Permission เดิมที่มีความหมายตรงกัน ให้ Reuse และไม่สร้างซ้ำ
|
|
|
|
---
|
|
|
|
# API and Server Action
|
|
|
|
หากมี API เดิมรองรับ ให้ขยายของเดิม
|
|
|
|
หากไม่มี ให้เพิ่มเฉพาะ Endpoint หรือ Server Action ที่จำเป็น เช่น:
|
|
|
|
```text
|
|
POST /api/announcements/:id/pin
|
|
POST /api/announcements/:id/unpin
|
|
```
|
|
|
|
หรือใช้รูปแบบ Mutation ตาม Architecture เดิม
|
|
|
|
การปักหมุดต้องอัปเดต:
|
|
|
|
```text
|
|
is_pinned = true
|
|
pinned_at = current timestamp
|
|
pinned_by = current user
|
|
```
|
|
|
|
การยกเลิกปักหมุดต้องอัปเดต:
|
|
|
|
```text
|
|
is_pinned = false
|
|
pinned_at = null
|
|
pinned_by = null
|
|
```
|
|
|
|
หาก Schema เดิมไม่มี `pinned_at` หรือ `pinned_by` ให้ประเมินก่อนเพิ่ม โดยเพิ่มเฉพาะเมื่อจำเป็นต่อ Sorting และ Audit เท่านั้น
|
|
|
|
---
|
|
|
|
# Audit Log
|
|
|
|
หากระบบมี Audit Log อยู่แล้ว ให้บันทึก Action:
|
|
|
|
```text
|
|
ANNOUNCEMENT_PINNED
|
|
ANNOUNCEMENT_UNPINNED
|
|
```
|
|
|
|
ข้อมูลควรประกอบด้วย:
|
|
|
|
- Announcement ID
|
|
- Announcement title
|
|
- Actor
|
|
- Action
|
|
- Previous value
|
|
- New value
|
|
- Timestamp
|
|
|
|
ห้ามสร้างระบบ Audit ใหม่ หากมีโครงสร้างกลางอยู่แล้ว
|
|
|
|
---
|
|
|
|
# Toast Messages
|
|
|
|
ปักหมุดสำเร็จ:
|
|
|
|
```text
|
|
ปักหมุดประกาศเรียบร้อยแล้ว
|
|
```
|
|
|
|
ยกเลิกสำเร็จ:
|
|
|
|
```text
|
|
ยกเลิกการปักหมุดเรียบร้อยแล้ว
|
|
```
|
|
|
|
กรณีสถานะไม่รองรับ:
|
|
|
|
```text
|
|
สามารถปักหมุดได้เฉพาะประกาศที่เผยแพร่แล้วเท่านั้น
|
|
```
|
|
|
|
กรณีประกาศหมดอายุ:
|
|
|
|
```text
|
|
ไม่สามารถปักหมุดประกาศที่หมดอายุแล้วได้
|
|
```
|
|
|
|
กรณีไม่มีสิทธิ์:
|
|
|
|
```text
|
|
คุณไม่มีสิทธิ์จัดการการปักหมุดประกาศ
|
|
```
|
|
|
|
---
|
|
|
|
# Loading State
|
|
|
|
ขณะดำเนินการ:
|
|
|
|
- Disable Action ที่กำลังประมวลผล
|
|
- ป้องกันการกดซ้ำ
|
|
- แสดง Loading Indicator ตามมาตรฐานระบบ
|
|
- ไม่ปิดเมนูหรือ Dialog แบบทำให้ผู้ใช้ไม่ทราบผลลัพธ์
|
|
|
|
หลังสำเร็จ:
|
|
|
|
- Refresh หรือ Invalidate Query เฉพาะข้อมูลที่เกี่ยวข้อง
|
|
- ห้าม Reload ทั้งหน้าโดยไม่จำเป็น
|
|
|
|
---
|
|
|
|
# Accessibility
|
|
|
|
ตรวจสอบ:
|
|
|
|
- Action มีชื่อที่ Screen Reader เข้าใจได้
|
|
- ไอคอนไม่เป็นตัวสื่อความหมายเพียงอย่างเดียว
|
|
- Dialog Focus Management ถูกต้อง
|
|
- Keyboard Navigation ใช้งานได้
|
|
- Badge และสถานะไม่ใช้สีเพียงอย่างเดียว
|
|
|
|
---
|
|
|
|
# Responsive
|
|
|
|
หน้า List และ Action Menu ต้องใช้งานได้บน:
|
|
|
|
- Desktop
|
|
- Tablet
|
|
- Mobile
|
|
|
|
ห้ามให้ Badge หรือไอคอนปักหมุดทำให้ชื่อประกาศถูกบีบจนอ่านไม่ได้
|
|
|
|
---
|
|
|
|
# Business Logic Restrictions
|
|
|
|
ห้ามเปลี่ยน:
|
|
|
|
- Approval workflow
|
|
- Draft workflow
|
|
- Submit for review workflow
|
|
- Publish workflow
|
|
- Schedule publish workflow
|
|
- Versioning ของเนื้อหา
|
|
- File attachment logic
|
|
- Existing validation ที่ไม่เกี่ยวข้อง
|
|
- Existing permission ที่ไม่เกี่ยวข้อง
|
|
|
|
งานนี้ต้องเปลี่ยนเฉพาะ Workflow และ UI ของการปักหมุดประกาศ
|
|
|
|
---
|
|
|
|
# Testing
|
|
|
|
เพิ่มหรือปรับ Test Cases ให้ครอบคลุม:
|
|
|
|
## Functional
|
|
|
|
- Create announcement แล้ว `is_pinned` เป็น `false`
|
|
- หน้า Create ไม่มีตัวเลือกปักหมุด
|
|
- หน้า Edit ไม่มีตัวเลือกปักหมุด
|
|
- Published announcement สามารถปักหมุดได้
|
|
- Pinned announcement สามารถยกเลิกได้
|
|
- Draft ไม่สามารถปักหมุดได้
|
|
- Pending Review ไม่สามารถปักหมุดได้
|
|
- Archived ไม่สามารถปักหมุดได้
|
|
- Expired ไม่สามารถปักหมุดได้
|
|
- Unpublished announcement ไม่ถูกแสดงเป็นปักหมุด
|
|
- หลายประกาศปักหมุดเรียงถูกต้อง
|
|
|
|
## Permission
|
|
|
|
- มี `announcement:pin` เห็นและใช้ Action ได้
|
|
- ไม่มี Permission ไม่เห็น Action
|
|
- เรียก Server Action โดยไม่มี Permission ต้องถูกปฏิเสธ
|
|
|
|
## UI
|
|
|
|
- Badge หรือ Pin icon แสดงถูกต้อง
|
|
- Loading State ทำงาน
|
|
- Toast ถูกต้อง
|
|
- Confirm Dialog ถูกต้อง
|
|
- Mobile ใช้งานได้
|
|
|
|
## Regression
|
|
|
|
- Create Draft ยังทำงาน
|
|
- Submit Review ยังทำงาน
|
|
- Approve ยังทำงาน
|
|
- Publish ยังทำงาน
|
|
- Schedule Publish ยังทำงาน
|
|
- Edit Announcement ยังทำงาน
|
|
- Pagination/Search/Filter ยังทำงาน
|
|
|
|
---
|
|
|
|
# Deliverables
|
|
|
|
เมื่อดำเนินการเสร็จ ให้สร้างเอกสาร:
|
|
|
|
```text
|
|
docs/announcement-pin-action-enhancement-report.md
|
|
```
|
|
|
|
ประกอบด้วย:
|
|
|
|
## 1. Existing Structure Review
|
|
|
|
- โครงสร้างเดิมที่พบ
|
|
- Field เดิมที่ Reuse
|
|
- API/Action เดิมที่ Reuse
|
|
- Component เดิมที่ Reuse
|
|
- ส่วนที่ต้อง Refactor หรือ Extend
|
|
|
|
## 2. Files Changed
|
|
|
|
ระบุไฟล์ทั้งหมดที่แก้ไข
|
|
|
|
## 3. UI Changes
|
|
|
|
- สิ่งที่นำออกจาก Create/Edit
|
|
- Action ที่เพิ่มใน List/Detail
|
|
- Badge หรือสถานะที่เพิ่ม
|
|
|
|
## 4. Business Rules
|
|
|
|
- Status ที่ปักหมุดได้
|
|
- Automatic Unpin
|
|
- Sorting
|
|
- Multiple Pinned Announcements
|
|
|
|
## 5. Permission
|
|
|
|
- Permission ที่ใช้
|
|
- การตรวจสอบ Client/Server
|
|
|
|
## 6. Database and API Changes
|
|
|
|
- Field ที่เพิ่มหรือปรับ
|
|
- Migration
|
|
- Endpoint หรือ Server Action
|
|
|
|
## 7. Audit Log
|
|
|
|
Action ที่บันทึก
|
|
|
|
## 8. Testing Result
|
|
|
|
- Functional
|
|
- Permission
|
|
- Responsive
|
|
- Regression
|
|
|
|
## 9. Remaining Improvements
|
|
|
|
เช่น:
|
|
|
|
- Pin expiration
|
|
- Pin priority
|
|
- Scheduled pinning
|
|
- Limit maximum pinned announcements
|
|
- Drag-and-drop pinned ordering
|
|
|
|
---
|
|
|
|
# Success Criteria
|
|
|
|
งานถือว่าเสร็จเมื่อ:
|
|
|
|
- หน้าสร้างไม่มีตัวเลือกปักหมุด
|
|
- หน้าแก้ไขไม่มีตัวเลือกปักหมุด
|
|
- ปักหมุดจากหน้า List หรือ Detail ได้
|
|
- ปักหมุดได้เฉพาะประกาศที่เผยแพร่แล้ว
|
|
- Permission-first ทำงานครบ
|
|
- Server-side authorization ทำงาน
|
|
- Sorting ของประกาศปักหมุดถูกต้อง
|
|
- Automatic Unpin หรือ Filtering ทำงานถูกต้อง
|
|
- ไม่มีผลกระทบต่อ Approval/Publish Workflow
|
|
- TypeScript ไม่มี Error
|
|
- ESLint ผ่าน
|
|
- Build ผ่าน
|
|
- Tests ผ่าน
|
|
- ไม่มี Regression
|
|
- รายงานถูกสร้างเรียบร้อย
|