หน้าแดชบอร์ดและการวิเคราะห์ข้อมูล (Dashboard)

หน้า Dashboard คือหน้าแรกหลังเข้าสู่ระบบของฝั่ง Admin และเป็นจุดรวมข้อมูลสรุปจาก endpoint เดียว คือ GET /dashboard/
การเข้าถึงหน้า Dashboard
- route ที่ใช้จริงคือ
/และ/home - route นี้อยู่ใน
MainRoutes - หน้าใช้
MainCard permission={Permission.DASHBOARD_VIEW} - filter ด้านบนถูกครอบด้วย
Authorize permission={Permission.DASHBOARD_VIEW}
แหล่งข้อมูลของหน้า
- หน้าเรียก
useDashboardSummaryQuery - hook นี้เรียก
GetDashBoardSummary(params) - service layer ยิง
GET /dashboard/ - parameter ที่ส่งจริงมี 2 ค่า
workAreaIdmonthYear
ส่วนกรองข้อมูล (Filter)
ตัวกรองด้านบนของหน้าถูกส่งเข้า query โดยตรง
พื้นที่จะ map ไปเป็นworkAreaIdเดือน/ปีจะ map ไปเป็นmonthYear- ถ้าไม่เลือกค่าใหม่ ระบบจะใช้เดือนปัจจุบันจาก
dayjs().format('YYYY-MM') - แม้หน้า UI ส่ง filter ทั้ง 2 ค่าไปทุกครั้ง แต่ไม่ใช่ทุก widget จะใช้ filter ทั้งคู่จาก backend
การ์ดสถิติด้านบน (Stat Cards)
สี่การ์ดแรกของหน้า dashboard ใช้ field เหล่านี้จาก DashBoardSummary
| การ์ด | field ที่ใช้ |
|---|---|
| ลูกค้า | customerCount |
| รถบริษัท | companyVehicleCount |
| รถร่วม | partnerVehicleCount |
| ผู้ใช้งาน | userCount |
Widget กลุ่มงานปฏิบัติการ
รอบรถวิ่งวันนี้
- ใช้
todayTripRecord.dayPercentage - ใช้
todayTripRecord.nightPercentage - หน้า UI แสดงเป็น progress 2 ช่วง
06:00 - 17:5918:00 - 05:59
จำนวนเที่ยวรถรายสัปดาห์
- ใช้
weekTripRecord - แต่ละแท่งกราฟใช้ค่า
count - backend จัดข้อมูลตามสัปดาห์ปฏิทิน
จ. - อา.ของวันที่ปัจจุบัน - หน้า UI แสดง label ตาม
dayที่ service ส่งมา เช่นจ.,อ.,พ. - widget นี้ใช้
workAreaIdได้ แต่ไม่ใช้monthYear - backend จะใช้
driver.workAreaIdก่อน ถ้าไม่มีค่อย fallback ไปvehicle.workAreaId
จำนวนเที่ยวสูงสุด
- ใช้
driverTripCount - backend นับเฉพาะเที่ยวที่
isApproved = true - หน้า UI จะกรองคนที่มี
_count.tripRecordVehicles > 0 - จากนั้น sort จากมากไปน้อยก่อนแสดงผล
- ถ้ามีรถผูกกับนักขับ จะแสดง
vehicleCodeของคันแรก
จำนวนรถบริการ
- ใช้
vehicleTypeCount - หน้า UI จะกรองเฉพาะประเภทรถที่มีจำนวนรถมากกว่า 0
- แล้วคำนวณ
totalServiceVehicleCountเพื่อแสดงยอดรวมของ widget
Widget กลุ่มรายได้
รายได้นักขับ
- ใช้
driverIncomeRevenuePerMonth - แกน X แสดง
billingMonth - แกน Y แสดง
amount - backend สรุปย้อนหลัง 3 เดือน โดยยึดเดือนที่เลือกและย้อนหลังอีก 2 เดือน
- widget นี้ใช้ทั้ง
monthYearและworkAreaId
รายได้วางบิล
- ใช้
mainBillingRevenuePerMonth - หน้า UI แปลงค่าก่อน plot เป็น
Number((total * 0.99).toFixed(2)) - แต่ค่า
maxของแกน Y ยังอ้างจากtotalเดิมของ backend - backend สรุปย้อนหลัง 3 เดือน โดยยึดเดือนที่เลือกและย้อนหลังอีก 2 เดือน
- widget นี้ใช้ทั้ง
monthYearและworkAreaId
ยอดใบวางบิลลูกค้า
- ใช้
mainBilling - ยอดรวมด้านบนของ widget มาจาก
mainBilling.reduce((acc, v) => acc + v.totalAmount, 0) - รายการย่อยใช้
customerNameและtotalAmount
รายได้รถร่วม
- ใช้
partnerInvoiceRevenuePerMonth - กราฟ plot ค่า
totalตรงจาก backend - backend สรุปย้อนหลัง 3 เดือน โดยยึดเดือนที่เลือกและย้อนหลังอีก 2 เดือน
- widget นี้ใช้ทั้ง
monthYearและworkAreaId
ยอดใบแจ้งหนี้รถร่วม
- ใช้
partnerInvoice - ยอดรวมของ widget มาจาก
partnerInvoice.reduce((acc, v) => acc + v.totalAmount, 0) - รายการย่อยใช้
partnerNameและtotalAmount
Widget กลุ่ม KPI และข้อมูลสนับสนุน
กราฟเปรียบเทียบค่าดาวแดง (X-Ratio)
- ใช้
vehicleTypeRedstartXRatio - หน้า UI จะกรองเฉพาะรายการที่
vehicleCount > 0 - pie chart คำนวณ 2 ค่า
- สัดส่วน
ดาวแดง - สัดส่วน
ปกติ
- สัดส่วน
- backend ใช้ข้อมูลเติมน้ำมันในเดือนที่เลือกจาก
EnergyLog - widget นี้ใช้ทั้ง
monthYearและworkAreaId ดาวแดงหมายถึงรายการที่ค่าxRatioหลุดช่วงavgXRatio ± redStarThresholdของประเภทรถนั้น
กราฟแสดงค่า X-Ratio
- ใช้
monthlyVehicleTypeXRatio - หน้า UI ใช้
LineGraph - แกน X แสดง
vehicleTypeName - แกน Y แสดง
avgXRatio - backend ใช้ข้อมูลเติมน้ำมันในเดือนที่เลือกจาก
EnergyLog - widget นี้ใช้ทั้ง
monthYearและworkAreaId avgXRatioคือค่าเฉลี่ยของxRatioแยกตามประเภทรถxRatioคำนวณจาก(เลขไมล์ปัจจุบัน - เลขไมล์ครั้งก่อนหน้า) / ปริมาณน้ำมัน
ราคาน้ำมัน
- ใช้
fuelPrices - รายการตัวแรกถูกแสดงเป็นราคา
วันนี้ - รายการถัดไปใช้เป็นประวัติย้อนหลังในตาราง
- footer ระบุว่าอ้างอิงราคาตามประกาศ
PTTOR - widget นี้ไม่ใช้
monthYearและไม่ใช้workAreaId
เงื่อนไขการกรองของกราฟบนหน้า Dashboard
| กราฟ / Widget | field ที่ใช้ | เงื่อนไขเวลา | เงื่อนไขพื้นที่ | หมายเหตุ |
|---|---|---|---|---|
| รอบรถวิ่งวันนี้ | todayTripRecord.dayPercentage, todayTripRecord.nightPercentage | ใช้ข้อมูลของวันปัจจุบัน (อิงเวลา Bangkok) | ไม่ใช้ workAreaId | แบ่งกลางวัน 06:00 - 17:59 และกลางคืน 18:00 - 05:59 |
| จำนวนเที่ยวรถ | weekTripRecord | ใช้สัปดาห์ปฏิทิน จ. - อา. ของวันที่ปัจจุบัน | ใช้ workAreaId ผ่าน TripRecordVehicle โดยอิง driver.workAreaId ก่อน vehicle.workAreaId | backend นับเฉพาะเที่ยวที่ isApproved = true และหน้า UI แสดง label ตาม day จาก service |
| จำนวนเที่ยวสูงสุด | driverTripCount | ใช้เดือนที่เลือกใน monthYear (อิง Bangkok-based date object) | ใช้ workAreaId ที่ระดับ User | backend นับเฉพาะเที่ยวที่อนุมัติแล้ว และหน้า UI จะกรองเฉพาะคนที่จำนวนเที่ยวมากกว่า 0 ก่อนแสดง |
| จำนวนรถบริการ | vehicleTypeCount | ไม่ใช้ monthYear | ใช้ workAreaId ผ่าน Vehicle | หน้า UI กรองเฉพาะประเภทรถที่มีจำนวนรถมากกว่า 0 |
| รายได้นักขับ | driverIncomeRevenuePerMonth | ย้อนหลัง 3 เดือนอิงจาก monthYear | ใช้ workAreaId | แสดง billingMonth กับ amount |
| รายได้วางบิล | mainBillingRevenuePerMonth | ย้อนหลัง 3 เดือนอิงจาก monthYear | ใช้ workAreaId ผ่าน Customer | หน้า UI plot ค่า total * 0.99 |
| รายได้รถร่วม | partnerInvoiceRevenuePerMonth | ย้อนหลัง 3 เดือนอิงจาก monthYear | ใช้ workAreaId | plot ค่า total จาก backend ตรง ๆ |
| กราฟเปรียบเทียบค่าดาวแดง (X-Ratio) | vehicleTypeRedstartXRatio | ใช้เดือนที่เลือกใน monthYear | ใช้ workAreaId ผ่าน Vehicle | แสดงสัดส่วนดาวแดง/ปกติแยกตามประเภทรถ |
| กราฟแสดงค่า X-Ratio | monthlyVehicleTypeXRatio | ใช้เดือนที่เลือกใน monthYear | ใช้ workAreaId ผ่าน Vehicle | แสดงค่าเฉลี่ย avgXRatio ต่อประเภทรถ |
| ราคาน้ำมันดีเซล | fuelPrices | ไม่ใช้ monthYear | ไม่ใช้ workAreaId | ดึง 9 รายการล่าสุดจาก backend |
สิ่งที่ควรระวังเวลาอธิบายหน้า Dashboard
- ความแม่นยำของเวลา: ระบบได้เปลี่ยนมาใช้ Bangkok-based date-only objects ในการจัดการข้อมูล Dashboard ทั้งหมด เพื่อป้องกันปัญหา timezone ที่อาจทำให้ข้อมูลรายวันหรือรายเดือนคลาดเคลื่อน
- หน้า dashboard ใช้ข้อมูลสรุปจาก backend เป็นหลัก ไม่ได้ประกอบตัวเลขจากหลาย API ในหน้าเดียว
รายได้วางบิลมีการคูณ0.99ที่ชั้น UI จริงSummaryBillingTableของบิลลูกค้าและรถร่วมใช้totalAmountจาก backend ตรง ๆtodayTripRecordและfuelPricesไม่ได้กรองตามworkAreaIdweekTripRecordใช้workAreaIdแต่ไม่ใช้monthYear- กราฟ X-Ratio มี 2 ชุดข้อมูลคนละหน้าที่
vehicleTypeRedstartXRatioใช้กับกราฟ pie เปรียบเทียบดาวแดงmonthlyVehicleTypeXRatioใช้กับกราฟเส้นแสดงค่าเฉลี่ย X-Ratio
- การมองเห็น filter และหน้า dashboard ต้องผ่าน
dashboard:view
อ้างอิงโค้ด
atp30-tos-frontend/src/views/pages/home/index.tsxatp30-tos-frontend/src/hooks/useHome.tsatp30-tos-frontend/src/api/home.tsatp30-tos-frontend/src/types/home.tsatp30-tos-frontend/src/components/shared/Authorize.tsx