← Back to Works

The Deep Dive

Jodsub

เว็บแอปจด subscription และรายจ่ายประจำ เห็นยอด วันจ่าย และช่องทางที่เงินจะออกล่วงหน้า พร้อมเตือนก่อนถึงวันจ่าย

ปรับปรุงเนื้อหา

Year
2026
Category
Code
Tags
React, Supabase, PWA, Local-first, Web Push
Jodsub

Context

รายจ่ายประจำไม่ได้มาพร้อมกัน subscription แต่ละตัวตัดเงินคนละวัน ค่าน้ำ ค่าไฟ ค่าเช่าบ้านมีรอบของตัวเอง และแต่ละรายการออกจากคนละช่องทาง บัญชีธนาคาร กระเป๋าเงินดิจิทัล หรือเงินสด

Jodsub เป็น web app สำหรับจดรายการเหล่านี้ไว้ที่เดียว เห็นยอดรวม วันครบกำหนด และช่องทางที่เงินจะออก ก่อนถึงวันจ่ายจริง ใช้งานได้ที่ jodsub.panupongws.com

Problem

สิ่งที่ทำให้รายจ่ายประจำเป็นปัญหาไม่ใช่จำนวนเงิน แต่คือจังหวะ รายการถูกตัดในวันที่ไม่ได้นึกถึง จากช่องทางที่อาจมีเงินไม่พอ รู้อีกทีก็เมื่อเงินออกไปแล้ว

การแก้จึงไม่ใช่แค่จดให้ครบ แต่ต้องเห็นล่วงหน้าว่าอะไรจะครบกำหนดวันนี้ พรุ่งนี้ หรือในอีกกี่วัน และได้รับการเตือนก่อนถึงวันนั้น

Role

ออกแบบและพัฒนาทั้งหมด

Process

แอปสร้างขึ้นรอบหน่วยเล็กที่สุด คือรายการประจำหนึ่งรายการ ซึ่งต้องรู้สามอย่าง ยอด รอบการจ่าย และช่องทางที่เงินออก มุมมองที่เหลือต่อยอดจากสามอย่างนี้ ยอดรวมต่อเดือน รายการที่ใกล้ครบกำหนด หมวดหมู่รายจ่าย และงบประมาณรายเดือน

ลำดับการเริ่มใช้ไม่มีด่าน เปิดแล้วใช้ได้ทันทีแบบ guest ไม่ต้องสมัคร มีข้อมูลตัวอย่างให้ลองก่อน เมื่อสมัครบัญชีภายหลัง ข้อมูลที่จดไว้ตอนเป็น guest จะถูกย้ายเข้าบัญชีและแยกออกจากข้อมูล guest เดิม

Decisions

ข้อมูลอยู่ในเครื่องก่อน (local-first) แอปทำงานได้แม้ offline การเปลี่ยนแปลงถูกเก็บบน browser และ sync ขึ้น cloud เมื่อกลับมาออนไลน์ การจดรายจ่ายต้องทำได้ทุกเมื่อ ไม่ควรรอสัญญาณ

ช่องทางจ่ายเก็บแค่พอให้รู้ว่าเงินออกจากไหน ธนาคารใด กระเป๋าใด หรือเงินสด แอปจะไม่ขอและไม่เก็บหมายเลขบัตรหรือบัญชีเต็ม เพราะสิ่งที่ต้องรู้คือเงินจะออกจากไหน ไม่ใช่เลขบัญชี

เตือนก่อนถึงวันจ่ายผ่าน Web Push และแสดงสถานะครบกำหนดตรง ๆ ว่าวันนี้ พรุ่งนี้ หรือในอีกกี่วัน แทนการให้ผู้ใช้ไล่ดูวันที่เอง

งบประมาณรายเดือนทำหน้าที่เป็นเส้นเตือน แอปบอกเมื่อใกล้เต็มงบเดือนนี้ และบอกเมื่อจ่ายเกินงบเดือนนี้แล้ว

ข้อมูลเป็นของผู้ใช้ สำรองเป็นไฟล์ ส่งออก และกู้คืนได้เอง ไม่ผูกอยู่กับบัญชีเพียงทางเดียว

Technical Decisions

React เป็นตัวหลักฝั่งหน้าบ้าน ติดตั้งเป็น PWA ได้ ทำงานผ่าน Service Worker และอัปเดตตัวเองเมื่อมีเวอร์ชันใหม่

Supabase ทำสองหน้าที่ ยืนยันตัวตนและเป็น cloud ที่ข้อมูล sync ไป เมื่อเข้าสู่ระบบด้วยบัญชีเดียวกันบนอุปกรณ์อื่น รายการทั้งหมดตามไปด้วย

ลำดับคือเครื่องก่อน cloud ทีหลัง ข้อมูลเขียนลงที่เก็บของ browser ก่อนเสมอ แล้วจึง sync ส่วนการเตือนผ่าน Web Push ผูกกับบัญชี จึงต้องเข้าสู่ระบบก่อนเปิดใช้

หัวใจของการเตือนคือการรู้ว่ารายการประจำแต่ละตัวจะครบกำหนดครั้งถัดไปเมื่อไร และเหลืออีกกี่วัน ตัวอย่างย่อของหลักการ:

// ตัวอย่างย่อ: วันครบกำหนดถัดไปของรายการรายเดือน และเหลืออีกกี่วัน
type Recurring = { dayOfMonth: number };

export function nextDue(item: Recurring, now: Date) {
  const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const due = new Date(today.getFullYear(), today.getMonth(), item.dayOfMonth);
  if (due < today) due.setMonth(due.getMonth() + 1);

  const daysLeft = Math.round((due.getTime() - today.getTime()) / 86_400_000);
  return { due, daysLeft }; // 0 = วันนี้, 1 = พรุ่งนี้
}

จาก daysLeft จึงได้สถานะที่แสดงบนหน้าจอ 0 คือครบกำหนดวันนี้ 1 คือพรุ่งนี้ มากกว่านั้นคือครบกำหนดในอีกกี่วัน

ตัวอย่างนี้ย่อเพื่ออธิบายลำดับการคำนวณ ไม่ใช่การจัดการปฏิทินครบทุกกรณี สำหรับวันที่ 29–31 ต้องกำหนดให้ชัดว่าเดือนที่มีวันไม่ครบจะใช้วันใด และทดสอบการข้ามเดือน ข้ามปี และเขตเวลาก่อนนำแนวคิดไปใช้ในระบบจริง

Result

Jodsub ใช้งานได้จริงที่ jodsub.panupongws.com เปิดใช้ได้ทันทีโดยไม่ต้องสมัคร ทำงาน offline ได้ ติดตั้งเป็นแอปบนเครื่องได้ผ่าน PWA และเมื่อสมัครบัญชีจะ sync ข้ามอุปกรณ์ผ่าน Supabase

สิ่งที่ผู้ใช้เห็นก่อนถึงวันจ่ายคือสามอย่างที่ชื่อแอปบอกไว้ จดครบ เห็นก่อน จ่ายทัน

Reflection

local-first แลกความเรียบง่ายของสถาปัตยกรรมกับความแน่นอนว่าจดได้เสมอ มีสองที่เก็บข้อมูลที่ต้องให้ตรงกัน แต่ผู้ใช้ไม่ต้องรอสัญญาณเพื่อจดรายการเดียว

การไม่เก็บหมายเลขบัตรหรือบัญชีเต็มทำให้แอปไม่รู้ยอดจริงในบัญชี รู้แค่ว่าเงินจะออกจากไหน แต่ก็ไม่มีข้อมูลการเงินที่อ่อนไหวให้ต้องดูแล ความเป็นส่วนตัวตรงนี้เป็นการเลือก ไม่ใช่ข้อจำกัด

ให้ใช้แบบ guest ก่อนแล้วค่อยย้ายเข้าบัญชี ทำให้ด่านแรกหายไป แต่ก็ต้องแยกข้อมูล guest ออกจากบัญชีให้ถูกต้องเมื่อถึงเวลา ซึ่งแอปทำให้เห็นเป็นขั้นตอนตรง ๆ แทนที่จะซ่อนไว้

จากหน้าแนะนำสู่สมุดรายจ่าย

แดชบอร์ด Jodsub ในโหมดเดโม แสดงป้ายข้อมูลตัวอย่างชั่วคราวและกระดานรายจ่ายประจำ
หน้าแดชบอร์ดในโหมดเดโมที่เปิดตรวจวันที่ 14 ตุลาคม 2569 จำนวนเงินและรายการในภาพเป็นข้อมูลตัวอย่างของแอป ไม่ใช่ข้อมูลการเงินของผู้ใช้จริง

เส้นทางเริ่มต้นต้องตอบได้ว่าผู้ใช้เห็นประโยชน์ก่อนสมัครอย่างไร หน้าแนะนำมีทางเข้าเดโมพร้อมข้อมูลตัวอย่างแยกจากรายการที่จดเอง ผู้ใช้จึงสำรวจยอด วันจ่าย และช่องทางจ่ายได้ก่อนตัดสินใจเริ่มสมุดของตัวเอง

ใช้ปฏิทินตรวจคิวรายจ่าย

ปฏิทิน Jodsub เดือนตุลาคม 2569 ในโหมดข้อมูลตัวอย่าง
เปลี่ยนจากแดชบอร์ดไปปฏิทินในเดโมเดียวกัน เพื่อดูการเรียงรายจ่ายตามเดือนและวันกำหนด

ยอดรวมตอบว่าเตรียมเงินเท่าไร ส่วนปฏิทินตอบว่าเมื่อไร สองมุมมองต้องอ้างรายการชุดเดียวกัน เมื่อลองใช้งาน ควรตรวจทั้งรายการที่ใกล้ครบกำหนดและรายการที่อยู่คนละเดือน ไม่ดูเฉพาะยอดรวมหน้าแรก

สิ่งที่ตรวจในรอบนี้และวิธีลองต่อ

การตรวจหน้าเว็บวันที่ 14 ตุลาคม 2569 เปิดหน้าแนะนำ เข้าเดโม และเปลี่ยนจากแดชบอร์ดไปปฏิทินได้ หน้าทั้งสองแสดงสถานะข้อมูลตัวอย่างชัดเจน รอบนี้ไม่ได้เข้าสู่บัญชีจริงหรือส่งการแจ้งเตือนจริง จึงไม่ใช้ภาพเดโมเป็นหลักฐานของการซิงก์หรือการส่งแจ้งเตือน

ลองทำซ้ำได้โดยเปิดเว็บแล้วเลือก “เข้าเดโม” ตรวจป้ายสถานะเดโมก่อน จากนั้นเปิดปฏิทินและเทียบรายการกับแดชบอร์ด หากต้องการทดลองแก้รายการ ให้ทำภายในเดโมและออกจากเดโมเมื่อจบ

ข้อคิดจากการออกแบบข้อมูลนี้

ข้อมูลที่ไม่ต้องเก็บคือข้อมูลที่ไม่ต้องนำมาดูแล การระบุช่องทางจ่ายแบบชื่อหรือคำใบ้ช่วยวางแผนได้โดยไม่เชื่อมบัญชีธนาคาร ส่วนการเปิดให้ลองก่อนช่วยแยกการเรียนรู้เครื่องมือออกจากขั้นตอนสร้างบัญชี

การทำงานในเครื่องและการซิงก์มีข้อแลกเปลี่ยนต่างกัน คำอธิบายต่อผู้ใช้ควรบอกว่าตอนนี้กำลังใช้ข้อมูลชุดไหนและอยู่ในโหมดใด แทนการปล่อยให้ผู้ใช้เดาเองจากหน้าจอที่ดูคล้ายกัน