Agent ของ Truck
ภาพรวม (Overview)
แอปสำหรับบันทึกกะการทำงานและรายได้สำหรับคนขับรถบรรทุก ใช้ React 19 + Supabase มี 16 themes และรองรับ Telegram bot integration
บุคลิก (Personality)
- Role: overtime enthusiast
- ขยันขันแข็งกับ shift logs, รายละเอียดรายได้ และ edge cases ยอมทุ่มเวลา extra hours เพื่อให้ data model และ offline queue ถูกต้อง เคร่งครัดเรื่อง mutation-invalidation contracts
สแต็กเทคโนโลยี (Stack)
| Layer | Tech |
|---|---|
| Framework | React 19 + Vite 8 + TypeScript 6 |
| Routing | react-router-dom v7 |
| Data Fetching | tanstack/react-query v5 |
| Database | Supabase (Postgres) |
| Auth | Supabase Auth |
| Styling | Custom themes.css (16 themes) |
| Animations | motion (Framer Motion) — route transitions, modal exits, toast exits |
| Notifications | Telegram Bot API |
| Deployment | Vercel (SPA rewrite via git push) |
สถาปัตยกรรม (Architecture)
main.tsx → App.tsx (auth gate + session + theme)
→ AppRoutes.tsx (AnimatePresence > motion.div > Suspense > Routes route transitions)
→ lazy-loaded: DailyView, ShiftCalendar, History, IncomeView, ProfilePage, Changelog, AdminPanel, UserManagement, IncomeSettings
→ ErrorBoundary wrapper per route
→ Supabase (sb) + ReactQuery (monthly-logs, day-log, income, yearly-logs)
→ offlineQueue (localStorage mutation queue, auto-replay on reconnect)
→ AuthScreen (sign-in / request account via Telegram)แผนที่โครงสร้างโฟลเดอร์ (Directory Map)
| Directory | Responsibility |
|---|---|
src/lib/ | Supabase client (sb), offline mutation queue (offlineQueue) |
src/hooks/ | useOnlineStatus, useFocusTrap, usePendingSyncCount |
src/utils/ | calculateIncome(), shift helpers |
src/components/ | UI — 6 views + shared components |
src/components/daily/ | Daily logging (DateSlider, ShiftBadge, OdometerCard, CounterCard, LeaveCard) |
src/components/shifts/ | Monthly calendar (CalendarGrid, ShiftModal, ShiftSummary) |
src/components/history/ | Historical browsing |
src/components/income/ | Salary breakdown (HeroCard, SalaryBreakdown, TaxSummary) |
src/components/profile/ | Profile management modals |
src/components/skeletons/ | Loading skeletons (DailyView, ShiftCalendar, IncomeView) |
supabase/functions/ | Edge functions (approve-user, get-all-users, notify-telegram) |
รูปแบบหลัก (Key Patterns)
- Route transitions:
<AnimatePresence>(no mode) ><motion.div key={location.pathname}>><Suspense>><Routes>— fade+slide (0.2s, custom easing[0.16, 1, 0.3, 1]). Suspense อยู่ข้างใน motion.div เพื่อไม่ให้ lazy import discard animation tree - Modal exit animations:
<AnimatePresence>wrapping modals — backdrop fades out, content scales down (0.18s). CSSfadeIn/scaleInremoved from globals.css, motion handles enter+exit - Toast exit animation:
<AnimatePresence>in ToastContext — slide right + fade out (0.25s). CSSslideIn/slideOutremoved - Nav tab micro-interaction:
whileTap={{ scale: 0.9 }}on motion.div tab buttons - Auth gate: ตรวจสอบ Supabase session → แสดง ModalWrapper กับ AuthScreen overlay บนแอปหลัก (z-index 9999, ปิดไม่ได้)
- Toast:
useToast()จาก ToastContext — ห้ามใช้alert()หรือconsole.log() - Modal pattern: motion handles enter+exit — no more CSS animation classes on
.modal-backdrop/.modal-content - Admin gate: query DB
user_profiles.is_admin(ไม่ hardcode email) - Offline queue: เก็บ mutations ลง localStorage, replay เมื่อ reconnect ด้วย exponential backoff (ไม่มี service worker — ทำงานอิสระ)
- Focus trap:
useFocusTrap(active, ref, onClose?)ใน modals - Skeleton loaders: CSS skeleton ที่รองรับ theme สำหรับ 3 views
- Mutation invalidation contract: การ save ที่ mutates
logsต้อง invalidate ทั้งหมดของ:['monthly-logs', userId, year, month],['yearly-logs', userId, year],['income', userId, year, month] - Performance ref pattern:
formRefobject +useCallbackด้วย deps น้อยที่สุด เพื่อไม่ให้ memo'd children re-render
คำสั่ง (Commands)
| Command | What it does |
|---|---|
node node_modules/.bin/vite | Dev server |
node node_modules/vite/bin/vite.js build | Production build |
node node_modules/.bin/vitest run | Run tests (101 tests) |
node node_modules/.bin/eslint src/ | Lint |
node node_modules/.bin/prettier --write src/ | Format |
ทริกเกอร์ (Triggers)
"deploy"
git push — Vercel auto-deploys from git. ไม่ต้อง run vercel deploy ตรง ๆ.
"update .md"
- อ่าน project AGENTS.md + สถานะ KB ปัจจุบัน
- อัปเดต
projects/truck/status.mdด้วยการเปลี่ยนแปลงล่าสุด - อัปเดต
projects/truck/agent.md(architecture, patterns) - ถ้า project AGENTS.md มีข้อมูลเก่า ให้อัปเดตด้วย
"wrap-day"
- อ่าน diff, Changelog, STATUS.md
- เพิ่มสรุปภาษาไทยใน
src/components/Changelog.tsxเป็นรายการv{YYYY.MM.DD}ใหม่ - อัปเดต STATUS.md — Components / Data Flow / Constraints
git add+ commit"docs: wrap-day {YYYY-MM-DD}"- แตะเฉพาะ Changelog.tsx และ STATUS.md เท่านั้น
"cleanup"
- สแกน unused imports, ไฟล์ว่าง, dead exports
- ตรวจสอบสุขภาพ:
tsc --noEmit+ build - สแกนลึก: โฟลเดอร์ที่เหลือ,
vite.log,console.log, TODO/FIXME - นำผลมาเสนอให้ user เลือก
- อัปเดต STATUS.md + project AGENTS.md
- ห้าม cleanup
.env*,node_modules/,dist/,.git/, หรือ config จำเป็น
งานที่ต้องทำ (TODOs)
Environment Variables
VITE_SUPABASE_URLVITE_SUPABASE_ANON_KEYVITE_TELEGRAM_BOT_TOKENVITE_TELEGRAM_CHAT_ID
กฎ (Rules)
oldStringต้องสั้นและแม่นยำ — หลีกเลี่ยง code blocks ยาวใน edit- อ่านไฟล์เวอร์ชันล่าสุดเสมอก่อนแก้ไข
- Deploy =
git push— ไม่ต้อง run vercel deploy ตรง ๆ. Vercel auto-deploy จาก git.
สภาพแวดล้อม Termux (Termux Environment)
| Tool | Notes |
|---|---|
| Node.js | v22.14.0 (ARM64) — ใช้ nodeตรง ๆ ไฟล์ .bin/ เป็น shell scripts |
| Supabase CLI | CI เท่านั้น: supabase/setup-cli@v1 ใน GitHub Actions |
| cwebp | มีให้ใช้ — cwebp -q 80 input.jpg -o output.webp |
| sharp / ffmpeg | ไม่มีให้ใช้ |