ปฏิทินวางแผนแคมเปญ
ภาพรวม
Campaign Planner คือมุมมองปฏิทินรายเดือนที่รวมแคมเปญทั้งหมดมาจัดเรียงตามวัน สำหรับผู้ดูแลระบบและทีมการตลาดที่ต้องวางแผนว่าจะส่งแคมเปญวันไหน วันไหนส่งถี่เกินไป และมีแคมเปญร่างค้างอยู่หรือไม่
ฟีเจอร์นี้เป็นแบบ อ่านอย่างเดียว ทั้งหมด ไม่มีการสร้าง แก้ไข หรือลบแคมเปญจากหน้านี้ และไม่มีชั้นบริการของตัวเอง แต่ใช้ข้อมูลชุดเดียวกับหน้าจัดการแคมเปญ ทุกรายการบนปฏิทินเป็นลิงก์กลับไปยังหน้าดูรายละเอียดของแคมเปญนั้น
พูดอีกอย่างคือ Planner ทำหน้าที่เป็น "ทางเข้าอีกทางหนึ่ง" สู่ข้อมูลเดียวกัน โดยจัดเรียงตามเวลาแทนที่จะเป็นตาราง
ด้านบนของหน้ามีการ์ดสรุปของเดือนที่กำลังดูอยู่ แสดงจำนวนแคมเปญรวมและแยกตามสถานะ 4 แบบ ได้แก่ ส่งแล้ว (Sent) ตั้งเวลาไว้ (Scheduled) ยกเลิก (Cancelled) และร่าง (Draft)
Business Flow
- ผู้ใช้เปิดหน้า
/campaign-plannerระบบตรวจสิทธิ์การดูข้อมูลแคมเปญก่อน จากนั้นตั้งค่า breadcrumb และเมนูด้านข้างให้ทำงานสอดคล้องกัน - ระบบเริ่มต้นที่เดือนปัจจุบัน แล้วคำนวณช่วงวันที่ที่ต้องดึงข้อมูลเป็น ต้นเดือนย้อนหลัง 7 วัน ถึงปลายเดือนล่วงหน้า 7 วัน เพื่อให้ช่องปฏิทินแถวแรกและแถวสุดท้ายที่คาบเกี่ยวกับเดือนข้างเคียงมีข้อมูลครบ
- ระบบดึงข้อมูลแยกกัน 4 คำขอตามสถานะ เพื่อให้แต่ละสถานะมี cache ของตัวเอง
- แคมเปญที่ส่งแล้วและที่ตั้งเวลาไว้ เรียงตามวันที่เริ่มจากเก่าไปใหม่
- แคมเปญร่างและที่ยกเลิก เรียงตามวันที่แก้ไขล่าสุดจากใหม่ไปเก่า
- ผลลัพธ์ทั้งสี่ชุดถูกรวมเข้าด้วยกัน แล้วจัดกลุ่มตามวันที่ โดยเลือกฟิลด์วันที่ตามสถานะ คือแคมเปญที่ส่งแล้วและที่ตั้งเวลาไว้ใช้วันที่เริ่ม ส่วนแคมเปญร่างและที่ยกเลิกใช้วันที่แก้ไขล่าสุด แคมเปญที่ไม่มีวันที่จะถูกข้ามไป
- ภายในแต่ละวัน รายการจะเรียงตามลำดับความสำคัญของสถานะก่อน (ตั้งเวลาไว้ ส่งแล้ว ร่าง ยกเลิก ตามลำดับ) แล้วจึงเรียงตามวันเวลา
- การ์ดสรุปด้านบนนับเฉพาะแคมเปญที่อยู่ในเดือนที่กำลังดูจริง ไม่รวมช่วง 7 วันที่ดึงมาเผื่อ
- ระหว่างที่ข้อมูลยังโหลดไม่เสร็จ การ์ดสรุปจะแสดงเครื่องหมายขีดแทนตัวเลข และพื้นที่ปฏิทินจะแสดงสัญลักษณ์กำลังโหลด
- เมื่อข้อมูลพร้อม ระบบแสดงปฏิทินแบบเต็มหน้าจอพร้อมคำอธิบายสีของทั้ง 4 สถานะไว้ด้านบน
- แต่ละช่องวันแสดงแคมเปญได้สูงสุด 3 รายการ แต่ละรายการเป็นจุดสีคู่กับชื่อแคมเปญ และคลิกเพื่อเปิดหน้าดูรายละเอียดได้
- เมื่อผู้ใช้นำเมาส์ไปวางบนรายการ ระบบแสดงกล่องข้อมูลย่อ ประกอบด้วยป้ายสถานะ ชื่อแคมเปญ กลุ่มผู้รับ (หรือ "เพื่อนทั้งหมดบน OA" หากไม่ได้ระบุกลุ่ม) จำนวนผู้รับ และบรรทัดวันเวลาที่เปลี่ยนคำอธิบายตามสถานะ เช่น ส่งเมื่อ ตั้งเวลาไว้ ยกเลิกเมื่อ หรือแก้ไขเมื่อ
- หากวันใดมีเกิน 3 รายการ จะมีปุ่มแสดงจำนวนที่เหลือ กดแล้วเปิดกล่องรายการเต็มของวันนั้น พร้อมหัวข้อบอกวันและจำนวนรวม แต่ละแถวเป็นลิงก์ไปหน้าดูรายละเอียดเช่นกัน
- เมื่อผู้ใช้เปลี่ยนเดือนบนปฏิทิน ช่วงวันที่จะถูกคำนวณใหม่และดึงข้อมูลของเดือนใหม่โดยอัตโนมัติ
หน้าจอและองค์ประกอบหลัก
หน้าและตัวควบคุมหลัก
หน้า /campaign-planner เป็นเพียงชั้นบางที่ตั้งค่า breadcrumb เมนูด้านข้าง และการตรวจสิทธิ์ ส่วนตรรกะทั้งหมดอยู่ที่ container (src/components/campaign-planner/campaign-planner.container.tsx) ซึ่งรับผิดชอบการดึงข้อมูลทั้ง 4 สถานะ การรวมและจัดกลุ่มข้อมูลตามวัน การคำนวณสถิติประจำเดือน และการแสดงการ์ดสรุป
Container ยังรองรับรูปแบบข้อมูลตอบกลับได้สองแบบ ทั้งแบบที่เป็นอาร์เรย์โดยตรงและแบบที่ห่อไว้ในอ็อบเจ็กต์ เนื่องจากรูปแบบที่ API ตอบกลับให้หน้านี้กับหน้ารายการไม่เหมือนกัน
ปฏิทิน
คอมโพเนนต์ปฏิทินรับผิดชอบการวาดช่องวัน คำอธิบายสี กล่องข้อมูลย่อเมื่อวางเมาส์ และปุ่มดูรายการที่เหลือ รวมถึงการแจ้งกลับเมื่อผู้ใช้เปลี่ยนเดือน
กล่องข้อมูลย่อและรายการรายวัน
กล่องข้อมูลย่อ (tooltip) และกล่องรายการเต็มของวัน (popover) เป็นคอมโพเนนต์แยกกัน แต่ใช้ป้ายสถานะร่วมกัน ทำให้สีและไอคอนของสถานะสอดคล้องกันทั้งหน้า
ป้ายสถานะ
คอมโพเนนต์ป้ายสถานะกำหนดสีและไอคอนของทั้ง 4 สถานะไว้ที่จุดเดียว โดยสีที่ใช้คือเขียวสำหรับส่งแล้ว น้ำเงินสำหรับตั้งเวลาไว้ แดงสำหรับยกเลิก และเทาสำหรับร่าง ส่วนข้อความบนป้ายไม่ได้ถูกกำหนดตายตัวไว้ในค่าคงที่ แต่ถูกดึงจากระบบแปลภาษาตอนแสดงผล เพื่อให้สลับภาษาได้ถูกต้อง
ปลายทาง API ที่เรียกใช้
ฟีเจอร์นี้เรียกใช้เฉพาะ GET /campaign ของหน้าจัดการแคมเปญ โดยยิง 4 ครั้งต่อการเปลี่ยนเดือนหนึ่งครั้ง แต่ละครั้งระบุสถานะที่ต้องการ ช่วงวันที่ ลำดับการเรียง และจำกัดผลลัพธ์ที่ 500 รายการ
จุดเชื่อมต่อกับฟีเจอร์อื่น
- จัดการแคมเปญ — เป็น dependency หลักและทางเดียวของฟีเจอร์นี้ ทั้งการดึงข้อมูล ค่าคงที่ของสถานะ โครงสร้างข้อมูล และปลายทางของลิงก์ทุกจุด
- สิทธิ์การเข้าถึง — ใช้สิทธิ์ดูข้อมูลของหน้าจัดการแคมเปญ ไม่มีสิทธิ์แยกของ Planner เอง โดยโมดูล
campaignฝั่งเซิร์ฟเวอร์จะเปิดทั้งหน้าจัดการแคมเปญและหน้าปฏิทินพร้อมกัน ส่วนเมนูด้านข้างใช้คีย์ของตัวเองในการไฮไลต์เมนูที่กำลังใช้งาน - องค์ประกอบร่วม — ใช้ส่วนหัวมาตรฐานของหน้าและคอมโพเนนต์ลิงก์กลางที่รองรับการ build แบบ static export
- ข้อสังเกตเรื่องรูปแบบวันที่และตัวเลข — การจัดรูปแบบวันที่และตัวเลขในหน้านี้ถูกกำหนดเป็น locale แบบอังกฤษไว้ตายตัว จึงไม่เปลี่ยนตามภาษาที่ผู้ใช้เลือก
รายละเอียดฝั่ง Backend (CMS API)
ไม่มีโมดูล backend ของตัวเอง
ฝั่ง cms-api ไม่มีโมดูลหรือ endpoint สำหรับปฏิทินวางแผนแคมเปญโดยเฉพาะ หน้านี้ใช้ GET /api/campaign ตัวเดียวกับหน้าจัดการแคมเปญทั้งหมด เพียงแต่ยิงหลายครั้งด้วยเงื่อนไขต่างกัน สิ่งที่ปฏิทินทำจึงเป็นการจัดเรียงและจัดกลุ่มข้อมูลฝั่งหน้าเว็บล้วน ๆ
ข้อนี้มีนัยเชิงปฏิบัติหลายอย่าง
- ไม่มีการกรองตามช่วงวันที่ที่ backend คำนวณให้ — หน้าเว็บเป็นผู้ส่งช่วงวันที่และเงื่อนไขการเรียงลำดับเข้าไปเอง การเปลี่ยนกฎการแสดงผลของปฏิทินจึงไม่ต้องแก้ backend
- การยิง 4 คำขอต่อการเปลี่ยนเดือนหนึ่งครั้งเป็นการออกแบบฝั่งหน้าเว็บ ไม่ใช่ข้อจำกัดของ API — API เดียวกันรับพารามิเตอร์สถานะได้ตามปกติ
- ขีดจำกัด 500 รายการต่อคำขอเป็นค่าที่หน้าเว็บกำหนด ถ้าเดือนใดมีแคมเปญเกินจำนวนนี้ในสถานะเดียวกัน รายการส่วนเกินจะไม่ปรากฏบนปฏิทินโดยไม่มีการแจ้งเตือน
สิทธิ์ที่บังคับจริง
เพราะใช้ endpoint เดียวกัน สิทธิ์ที่บังคับจึงเป็นชุดเดียวกับหน้าจัดการแคมเปญทุกประการ
- ต้องผ่าน ModuleGate ของโมดูล
campaignซึ่งบังคับใช้จริง ถ้าองค์กรถูกปิดโมดูลแคมเปญไว้ หน้าปฏิทินจะดึงข้อมูลไม่ได้เลยเช่นเดียวกับหน้ารายการ - ต้องมี token ที่ระบุ LINE OA แล้ว ข้อมูลบนปฏิทินจึงถูกจำกัดขอบเขตอยู่ที่ channel ที่เลือกโดยอัตโนมัติ
- ไม่มีสิทธิ์แยกสำหรับปฏิทิน และไม่มีทางที่ผู้ใช้จะเห็นแคมเปญบนปฏิทินแต่เปิดหน้ารายละเอียดไม่ได้
ทำไมรูปแบบข้อมูลตอบกลับจึงมีสองแบบ
ข้อสังเกตที่ว่า container ต้องรองรับผลลัพธ์ทั้งแบบอาร์เรย์ตรงและแบบห่อในอ็อบเจ็กต์ มีที่มาจากฝั่ง backend: GET /api/campaign ตอบกลับเป็นโครงสร้างที่มีทั้งรายการข้อมูล จำนวนรวมตามเงื่อนไข และจำนวนรวมทั้งหมด ไม่ได้ตอบเป็นอาร์เรย์เปล่า การเขียนโค้ดให้รองรับทั้งสองแบบจึงเป็นการเผื่อไว้ ไม่ใช่เพราะ backend ตอบไม่คงเส้นคงวา
ข้อมูลบางฟิลด์ถูกประกอบขึ้นที่ backend
repository ฝั่ง backend จะแทรกข้อมูลกลุ่มเป้าหมายเข้าไปในผลลัพธ์ของแต่ละแคมเปญให้เลย ปฏิทินจึงแสดงชื่อกลุ่มผู้รับและจำนวนผู้รับในกล่องข้อมูลย่อได้โดยไม่ต้องยิงคำขอเพิ่ม