Skip to content

Vue Composables

MYMO dùng 5 composables để quản lý state và business logic phía frontend. Tất cả composables dùng singleton pattern - state ở module scope, share giữa mọi components.

ts
// Singleton pattern
const config = ref<UserConfig | null>(null)  // module-level

export function useRunway() {
  // Mọi component gọi useRunway() đều share cùng config ref
  return { config, ... }
}

useAuth()

Authentication và session management.

State:

RefTypeMô tả
authenticatedRef<boolean>Trạng thái đăng nhập
userEmailRef<string>Email user hiện tại

Methods:

MethodSignatureMô tả
login(licenseKey: string) => Promise<void>Đăng nhập bằng license key
checkAuth() => booleanKiểm tra token còn valid
logout() => voidXóa token, reset state

useRunway()

Config management, runway calculations, currency formatting.

State:

RefTypeMô tả
configRef<UserConfig | null>Config hiện tại
loadingRef<boolean>Đang load config

Computed:

ComputedTypeMô tả
hasCompletedOnboardingbooleanConfig tồn tại = đã onboard
runwayDaysnumbertotal_cash / daily_burn_rate
doomDatestringNgày hết tiền (formatted)
status'safe' | 'warning' | 'danger'>= 180 safe, >= 90 warning, else danger
currencySymbolstringKý hiệu tiền tệ

Methods:

MethodSignatureMô tả
loadConfig() => Promise<void>Load config từ server
completeOnboarding(recurring, oneTime, totalCash) => Promise<void>Hoàn thành onboarding
resetOnboarding() => Promise<void>Xóa config
updateTotalCash(delta: number) => Promise<void>Cộng/trừ tài sản
formatAmount(n: number) => stringFormat số tiền + currency
setCurrency(currency: string) => Promise<void>Đổi đơn vị tiền
amountToDays(amount: number) => numberTiền → ngày
amountToHours(amount: number) => numberTiền → giờ

useTransactions()

Transaction CRUD và queries.

State:

RefTypeMô tả
transactionsRef<Transaction[]>Danh sách giao dịch

Methods:

MethodSignatureMô tả
loadTransactions() => Promise<void>Load 50 giao dịch gần nhất
createTransaction(amount, date, categoryId, note) => Promise<void>Tạo giao dịch
updateTransaction(id, amount, date, categoryId, note) => Promise<void>Cập nhật
deleteTransaction(id: number) => Promise<void>Xóa
getMonthTransactions(year, month) => Promise<TransactionWithCategory[]>Theo tháng
getMonthTierTotals(year, month) => Promise<{tier, total}[]>Tổng tier/tháng

useCategories()

Category CRUD.

State:

RefTypeMô tả
categoriesRef<Category[]>Danh sách danh mục

Methods:

MethodSignatureMô tả
loadCategories() => Promise<void>Load tất cả danh mục
findByName(name: string) => Category | nullTìm theo tên (case-insensitive)
createCategory(name, tier) => Promise<number>Tạo, trả về id
standardizeCategories() => Promise<void>AI chuẩn hóa tên

useRecurring()

Recurring expense management.

State:

RefTypeMô tả
recurringExpensesRef<RecurringWithCategory[]>Danh sách recurring

Methods:

MethodSignatureMô tả
loadRecurring() => Promise<void>Load recurring
catchUpRecurring() => Promise<void>Tạo transactions cho quá hạn
createRecurringExpense(name, amount, frequency, dayOfMonth, categoryId) => Promise<void>Tạo
updateRecurringExpense(id, fields) => Promise<void>Cập nhật
deleteRecurringExpense(id: number) => Promise<void>Xóa

Cross-Composable Dependencies

  • useRecurring imports useRunway (one-way dependency)
  • Sau khi mutate data ở composable A ảnh hưởng composable B → reload cả hai
  • Không tạo circular imports giữa composables (gây undefined exports)