Skip to main content

Overview

Transactions are the core of BudgetView’s financial tracking. Every income and expense is recorded as a transaction, linked to a specific wallet and category.
Important: You must select a specific wallet (not “Global”) to create new transactions.

Creating a Transaction

The transaction form is located on the left side of the Transacciones page.
1

Select a Specific Wallet

Use the wallet selector in the header to choose a wallet.
If you’re in “Global” mode, you’ll see a warning alert. Switch to a specific wallet to enable transaction creation.
if (!billeteraId || billeteraId === GLOBAL_WALLET_ID) {
  setFormError("Selecciona una billetera específica desde el encabezado para registrar transacciones.")
  return
}
2

Choose Transaction Type

Click either:
  • Gasto (Expense) - Red button
  • Ingreso (Income) - Green button
The category list updates automatically based on your selection.
const filteredCategories = React.useMemo(() => {
  return categories.filter((cat) => cat.tipo === formTipo)
}, [categories, formTipo])
3

Enter Amount

Type the transaction amount. You can choose between:
Enter amount in US dollars. This is stored directly in the database.
let monto = rawAmount
if (amountCurrency === "VES") {
  if (!bcvRate || bcvRate <= 0) {
    setFormError("Necesitamos la tasa BCV para convertir tu monto.")
    return
  }
  monto = rawAmount / bcvRate
}
Validation rules:
  • Must be greater than 0
  • Accepts decimal values (e.g., 15.50)
  • Maximum 2 decimal places
4

Select Transaction Date

Click the date picker to choose when the transaction occurred.
  • Default: Today’s date
  • You can select past or future dates
  • Time is automatically set to 12:00 PM
const fechaSeleccionada = new Date(formFecha)
fechaSeleccionada.setHours(12, 0, 0, 0)
5

Choose a Category

Select from categories that match your transaction type:
  • Gasto categories: Food, Transport, Entertainment, etc.
  • Ingreso categories: Salary, Freelance, Investments, etc.
If you don’t have any categories of the selected type, create them first in the Categories section.
6

Add Description (Optional)

Add notes to help you remember transaction details:
  • Maximum 280 characters
  • Examples: “Grocery shopping at Trader Joe’s”, “Monthly rent payment”
  • Stored as null if left blank
const descripcionValue = formDescripcion.trim() ? formDescripcion.trim() : null
7

Save Transaction

Click Guardar Transacción to create the transaction.The system:
  1. Validates all required fields
  2. Converts VES to USD if needed
  3. Inserts the transaction into the database
  4. Broadcasts an update event to refresh wallet balances
const transactionData = {
  monto,
  tipo: formTipo,
  descripcion: descripcionValue,
  categoria_id: formCategoriaId,
  usuario_id: user.id,
  billetera_id: billeteraId,
  fecha_transaccion: fechaSeleccionada.toISOString(),
}

const { error: insertError } = await supabase.from("transacciones").insert(transactionData)

Transaction History

The right side of the page displays your transaction history.

Understanding Transaction Cards

Each transaction shows:

Category & Date

  • Category name (or “Sin categoría” if none)
  • Transaction date formatted as: “15 ene 2024”

Type Badge

  • Gasto: Red badge
  • Ingreso: Green badge

Amount

  • Shows USD amount with +/- prefix
  • VES equivalent below (if BCV rate available)
  • Red for expenses, green for income

Description

Optional notes you addedLimited to 2 lines with ellipsis if too long

Visual Indicators

const isGasto = transaction.tipo === "gasto"

// Icon color
const iconColor = isGasto
  ? "bg-red-500 text-white dark:bg-red-500/80"
  : "bg-emerald-500 text-white dark:bg-emerald-500/80"

// Badge color
const badgeColor = isGasto
  ? "bg-red-100 text-red-700 dark:bg-red-500/20 dark:text-red-300"
  : "bg-emerald-100 text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-300"

// Amount color
const amountColor = isGasto
  ? "text-red-600 dark:text-red-400"
  : "text-emerald-600 dark:text-emerald-400"

Filtering Transactions

Use the period filter buttons to view specific timeframes:
Shows transactions from the past week.
case "7days": {
  const sevenDaysAgo = new Date(now)
  sevenDaysAgo.setDate(now.getDate() - 7)
  filtered = transactions.filter((t) => new Date(t.fecha_transaccion) >= sevenDaysAgo)
  break
}

Editing a Transaction

1

Click the Edit Icon

Click the pen icon (✏️) on any transaction card.
2

Update Fields

The edit dialog appears with pre-filled data:Editable fields:
  • Transaction type (Gasto/Ingreso)
  • Amount (USD only in edit mode)
  • Date (date input, format: YYYY-MM-DD)
  • Category (filtered by type)
  • Description
Changing the type (Gasto ↔ Ingreso) resets the category selection since categories are type-specific.
React.useEffect(() => {
  if (!editingTransaction) return
  const isValidCategory = editFilteredCategories.some((cat) => cat.id === editCategoriaId)
  if (!isValidCategory) {
    setEditCategoriaId("")
  }
}, [editFilteredCategories, editCategoriaId, editingTransaction])
3

Save Changes

Click Guardar cambios to update the transaction.
const { error: updateError } = await supabase
  .from("transacciones")
  .update({
    monto: parsedAmount,
    tipo: editTipo,
    categoria_id: editCategoriaId,
    descripcion: descripcionValue,
    fecha_transaccion: fechaIso,
  })
  .eq("id", editingTransaction.id)
The transaction list refreshes automatically, and wallet balances update.

Currency Conversion in Action

BudgetView supports dual-currency input and display:

Input Conversion

When you switch currency while entering an amount:
const handleCurrencyChange = React.useCallback(
  (value: "USD" | "VES") => {
    if (value === amountCurrency) return

    const parsed = parseFloat(formMonto)
    if (Number.isNaN(parsed) || parsed <= 0 || !bcvRate || bcvRate <= 0) {
      setAmountCurrency(value)
      return
    }

    const convertedValue = value === "USD" ? parsed / bcvRate : parsed * bcvRate
    setFormMonto(convertedValue.toFixed(2))
    setAmountCurrency(value)
  },
  [amountCurrency, formMonto, bcvRate]
)
Example:
  • Enter 100 in USD field
  • Switch to VES
  • Amount automatically converts to 3,650.00 (assuming rate of 36.50)

Display Conversion

All saved transactions show VES equivalents:
const formatBcvAmount = React.useCallback(
  (usdAmount: number) => {
    if (!bcvRate || usdAmount === 0) {
      return null
    }
    return formatCurrency(usdAmount * bcvRate, "VES")
  },
  [bcvRate]
)
VES amounts are calculated in real-time. They update when the BCV rate changes, but the stored USD amount remains constant.

Global Wallet Mode

When you select “Global” in the wallet picker:

What You Can Do

  • ✅ View transactions from ALL wallets
  • ✅ Filter by period
  • ✅ Edit existing transactions

What You Can’t Do

  • ❌ Create new transactions
  • ❌ The form is disabled
You’ll see a warning alert:
{isGlobalWallet && !globalAlertDismissed && (
  <Alert variant="warning" className="flex items-start gap-3">
    <AlertTriangle className="size-4 mt-0.5" aria-hidden />
    <div className="flex-1 space-y-1">
      <AlertTitle>Modo global activo</AlertTitle>
      <AlertDescription>
        Estás en modo <span className="font-semibold">Global</span>. Selecciona una billetera específica en el encabezado para registrar nuevas transacciones.
      </AlertDescription>
    </div>
    <Button onClick={() => setGlobalAlertDismissed(true)}>
      <X className="size-4" />
    </Button>
  </Alert>
)}

Form Shortcuts

Clear Button

Click Limpiar campos to reset the entire form:
const resetFormState = React.useCallback(() => {
  setFormMonto("")
  setFormTipo("gasto")
  setFormCategoriaId("")
  setFormDescripcion("")
  setFormError(null)
  setAmountError(null)
  setAmountCurrency("USD")
  setFormFecha(new Date())
}, [])

Keyboard Navigation

  • Tab: Move between form fields
  • Enter: Submit the form (when focused on submit button)
  • Escape: Close edit dialog

Best Practices

Don’t wait to record transactions. Enter them right after they occur to maintain accuracy.Use the mobile-friendly interface to add transactions on the go.
Choose specific categories instead of generic ones:
  • ✅ “Groceries” instead of “Shopping”
  • ✅ “Gas” instead of “Car”
  • ✅ “Netflix” instead of “Subscription”
Include details that will help you remember the transaction later:
  • “Weekly grocery run - Whole Foods”
  • “Electric bill - January 2024”
  • “Birthday gift for Mom”
Use the “Last 7 Days” filter to review recent spending and catch any errors.
  • Use USD if you think in dollars or need precise historical records
  • Use VES if you’re paying in bolívares and want to see the exact amount charged
The system stores everything in USD, so your data remains consistent regardless of exchange rate fluctuations.

Troubleshooting

Possible causes:
  1. Global wallet selected: Switch to a specific wallet
  2. Missing amount: Enter a value greater than 0
  3. No category selected: Choose a category from the dropdown
  4. Session expired: Refresh the page to log in again
Error messages:
  • “Selecciona una billetera específica desde el encabezado”
  • “El monto debe ser un número mayor a 0”
  • “Debes seleccionar una categoría”
Cause: BCV rate hasn’t loaded yet or the API is unavailable.Solution:
  • Wait a few seconds for the rate to load
  • Use USD input instead
  • Check internet connection
You’ll see: “La tasa BCV no está disponible en este momento.”
Possible causes:
  • Wrong period filter (transaction date outside selected range)
  • Wrong wallet selected
  • Transaction failed to save
Solution:
  1. Try the “This Month” or “Last 7 Days” filter
  2. Check the wallet selector
  3. Look for error messages
  4. Refresh the page
This is by design. When you change the type in the edit dialog:
  1. Category dropdown updates to show only categories of the new type
  2. Your previously selected category is cleared if it doesn’t match
  3. You must select a new category
This prevents invalid combinations (e.g., “Salary” category with “Gasto” type).
Check these:
  • Current BCV rate shown at top of page
  • Your input currency (USD vs VES)
  • Whether you switched currencies mid-entry
Remember: The BCV rate changes daily. A transaction entered yesterday may show a different VES equivalent today if you’re viewing it with today’s rate.

Creating Wallets

Learn how to create and organize wallets for your transactions

Setting Budgets

Set spending limits by category to track against your transactions

Currency Conversion

Deep dive into USD/VES conversion mechanics

Exporting Data

Export your transaction history for analysis

Build docs developers (and LLMs) love