Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Niurka77/tf-app/llms.txt

Use this file to discover all available pages before exploring further.

At its core, TF-App exists to give real estate teams precise control over two interconnected concerns: tracking property sales from initial lead through to closed deal, and computing the commissions each agent earns from those transactions. The current release ships the UI scaffolding and authentication layer; the sections below explain the intended data model and show exactly how to connect the frontend to a backend API that drives both features.

Sales Control

Sales tracking in TF-App covers the full lifecycle of a real estate transaction. Each sale record is expected to capture:
  • Property details — address, type (residential, commercial), and listing price
  • Buyer and seller records — linked contact identities, typically matched by DNI
  • Deal status — a progression such as prospecto → negociación → contrato → cerrado
  • Agent assignment — which team member owns the deal at each stage
  • Close date — the date the transaction was finalised, used as the reference point for commission calculation
This information gives managers a live pipeline view and lets agents see exactly which deals they are responsible for at any given moment.

Commission Management

Commissions in TF-App are computed on a per-agent, per-closed-deal basis. A typical commission model for real estate looks like:
  • A percentage rate agreed upon at contract time (e.g. 3% of the sale price)
  • Applied only to closed deals — status cerrado — within a billing period
  • Summed across all closed deals to produce an agent’s monthly commission total
  • Optionally split between a listing agent and a buyer’s agent when both are tracked
For example, a property sold at 150,000witha3150,000 with a 3% commission rate generates a 4,500 commission entry attributed to the responsible agent. Your backend calculates this figure and TF-App renders it in the dashboard.
The commission and sales data features represent the primary backend integration points for TF-App. The current release ships the UI scaffolding, navigation structure, and authentication layer. Rendering live sales and commission data requires connecting the dashboard views to a REST or GraphQL API that your team provides.

Integrating with a Backend

Use the standard fetch() API — already in use for the login flow — to pull sales data from your backend and hydrate the dashboard. The Authorization header carries the token stored in localStorage after login:
fetch('/api/sales', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer <token>',
    'Content-Type': 'application/json'
  }
})
  .then(res => res.json())
  .then(data => renderSalesTable(data))
  .catch(err => {
    showMessage('Error de Datos', 'No se pudo cargar la información de ventas.');
  });
For commissions, a similar call to /api/commissions (filtered by agent ID or date range) follows the same pattern:
fetch('/api/commissions?agentId=42&month=2025-06', {
  method: 'GET',
  headers: { 'Authorization': `Bearer ${localStorage.getItem('authToken')}` }
})
  .then(res => res.json())
  .then(data => renderCommissionSummary(data));
After a successful login, store the token returned by your API in localStorage with localStorage.setItem('authToken', data.token). Every subsequent fetch() call on the dashboard and commission pages can then read it with localStorage.getItem('authToken'), keeping the user’s session alive across views without re-authenticating.

Rendering Sales Data

Once the API response arrives, use vanilla JS DOM manipulation to inject sales records into the dashboard view. Here is a complete example that creates a styled card for each sale and appends it to a container element:
function renderSalesTable(sales) {
  const container = document.getElementById('sales-list');
  container.innerHTML = ''; // Clear any previous content

  if (!sales || sales.length === 0) {
    container.innerHTML = '<p class="text-gray-500 text-sm">No hay ventas registradas.</p>';
    return;
  }

  sales.forEach(sale => {
    const card = document.createElement('div');
    card.className = 'flex justify-between items-center bg-green-50 rounded-lg p-3 text-sm';

    card.innerHTML = `
      <div>
        <p class="font-bold text-green-800">${sale.property}</p>
        <p class="text-green-600">${sale.buyer} · ${sale.date}</p>
      </div>
      <div class="text-right">
        <p class="font-bold text-green-700">$${sale.price.toLocaleString()}</p>
        <span class="text-xs px-2 py-1 rounded-full bg-green-200 text-green-800">${sale.status}</span>
      </div>
    `;

    container.appendChild(card);
  });
}
A matching renderCommissionSummary function follows the same pattern, reading commission.agent, commission.amount, and commission.period from each record in the API response and rendering them into a dedicated section on the dashboard.
function renderCommissionSummary(commissions) {
  const container = document.getElementById('commission-list');
  container.innerHTML = '';

  commissions.forEach(entry => {
    const row = document.createElement('div');
    row.className = 'flex justify-between text-sm text-green-800 border-b border-green-100 py-2';
    row.innerHTML = `
      <span>${entry.agent}</span>
      <span class="font-bold">$${entry.amount.toLocaleString()}</span>
      <span class="text-green-500">${entry.period}</span>
    `;
    container.appendChild(row);
  });
}
Both functions are self-contained and can be called directly from the DOMContentLoaded listener in dashboard.html’s script block after the fetch() calls resolve.

Build docs developers (and LLMs) love