การบ้านจาก Dashboard Namnan • 5 sections × 5 ข้อ = 25 ข้อ
เรียนรู้ผ่าน Dashboard Namnan จริง — HTML, JavaScript, SQL, Python, DevOps
นี่คือ workshop การบ้าน สำหรับนักเรียนที่อยากเรียนเขียนโปรแกรม โดยใช้ Dashboard Namnan v11 (https://dashboard.namnan.co.th) เป็นโจทย์จริง
unzip dashboard-namnan-v11.zip| Section | หัวข้อ | ทักษะ |
|---|---|---|
| 1 | HTML / CSS | หน้าเว็บ, สี, layout |
| 2 | JavaScript | logic, function, async |
| 3 | SQL / MySQL | query, JOIN, GROUP BY |
| 4 | Python / FastAPI | API, backend |
| 5 | DevOps | nginx, systemd, cron |
เรียนรู้การสร้างกราฟ + วิเคราะห์ข้อมูลจาก MySQL โดยใช้ analytics.html + Chart.js เป็นโจทย์
frontend/analytics.html — หน้าวิเคราะห์ 6 กราฟ + 3 insightsfrontend/fb-ads.html — กราฟ CPC/CPM/CTR/ROASGET /orders?limit=10000ไฟล์ analytics.html มี monthlyChart (line chart) ใช้สีน้ำเงิน + เขียว
ใน analytics.html มี 6 กราฟ — ขาด Top 5 customers
renderTopCustomersChart() แสดง top 5 ลูกค้า (group by tracking, sum net_amount)ตอนนี้ analytics.html filter แค่ วันที่ — ขาด filter channel
analytics.html มี insight boxes เจ๋งๆ — แต่ไม่มีปุ่ม export
ใช้ข้อมูลจาก MySQL ตอบคำถามธุรกิจ
SELECT month, SUM(net_amount) FROM orders_history GROUP BY month ORDER BY 2 DESC LIMIT 1 → เดือนที่ดีสุดคือ 2024-02 (฿347K)เรียนรู้ function, array, async/await โดยใช้ frontend/api.js และ logic ใน HTML files
frontend/api.js — API client (7KB)frontend/expenses.html — มี switchTab, renderAdTab, renderBoxTab, renderProductTabfrontend/fb-ads.html — มี renderDailyChart, renderFunnelChartมี array ของ orders: [{amount: 100}, {amount: 200}, {amount: 50}]
sumAmount(orders) ที่รวม amount ทั้งหมด ใช้ Array.reduce()📂 เปิดไฟล์ expenses.html หรือ index.html → ใส่ function ใน <script>
ไฟล์ api.js มี DashboardAPI object — มี methods เช่น getExpenses, getOrders
getTopProducts(month, limit=10) ใน DashboardAPI📂 เปิด api.js → หา DashboardAPI = { ... } → เพิ่ม method ใหม่
วิธีใช้:
ใน expenses.html มี document.getElementById("monthInput").onchange = loadAll;
monthInput ให้ reload📂 หา document.getElementById("monthInput").onchange = loadAll; → เพิ่ม keydown listener
ใน loadAll() มี try/catch — แต่ไม่มี loading state
lastUpdate element ก่อน fetch และเปลี่ยนเป็น ✅ เมื่อสำเร็จ📂 เปิด expenses.html → หา async function loadAll()
ไฟล์ fb-ads.html ใช้ Chart.js — มี 2 charts (daily, funnel)
fb-ads.html — Pie chart แสดง % ของ ad spend แต่ละ campaign📂 หา renderDailyChart และ renderFunnelChart → เพิ่ม renderCampaignPieChart()
แล้วเพิ่ม <canvas id="pieChart"></canvas> ใน HTML
เรียนรู้ SQL ผ่าน MySQL จริง — มีตาราง orders, expenses, channels, products
orders — orders ปัจจุบัน (61 orders, July 2026)orders_history — orders เก่า (6,762 orders)expenses, expenses_history — รายจ่ายchannels — 8 channels (LINE, NIB, Web, FB, Shopee, Lazada, อื่นๆ, เฮียหนวด)products — 17 productsmysql -u namnan_dash -pNamnan2026! namnan_dashboard -e "SELECT ..."orders tableผลลัพธ์: total_revenue: 76,644, orders: 61
ผลลัพธ์: LINE (45/52,310), เฮียหนวด (14/21,836), อื่นๆ (2/2,498)
expenses และ expenses_history)ตรวจสอบผลลัพธ์:
เรียนรู้ Python ผ่าน FastAPI — สร้าง API endpoint จริง
backend/main.py — 25+ endpoints (13KB)backend/db.py — MySQL connectionbackend/auth.py — API key middlewarecd backend && python3 -m uvicorn api.main:app --reloadGET /hello/{name} ใน main.py ที่ return {"hello": name}ทดสอบ: curl http://localhost:8300/hello/World → {"ok":true,"hello":"World"}
GET /orders-by-channel รับ query param channel_id แล้ว return orders ของ channel นั้นget_top_customers(month, limit=10) ใน main.py return top customers by total spendPOST /create-expense รับ JSON body แล้ว INSERT ลง database/hello ต้อง login — เช็ค API key ก่อนใน auth.py:
เรียนรู้การ deploy เว็บจริง — nginx, systemd, cron, log
deploy/dashboard-api.service — systemd unitdeploy/dashboard.namnan.co.th.nginx.conf — nginx vhostdeploy/crontab.txt — cron jobsdeploy/cron_rebuild.sh — rebuild scriptdashboard.namnan.co.th.nginx.conf:
/api/ คืออะไร?dashboard-api.service:
python3 -m uvicorn api.main:app --host 127.0.0.1 --port 8300 --workers 2/var/backups/⚠️ ใน crontab ต้อง escape % เป็น \%
ผลลัพธ์: 73146
deploy.sh ที่:
เมื่อทำเสร็จ ให้ส่งงานผ่าน: