Skip to main content

Overview

The DADDO analytics dashboard provides real-time insights into your business performance with KPI metrics, interactive charts powered by Recharts, top product analysis, and sales breakdowns by day and user.

Dashboard Data Fetching

Get Dashboard Action

The fetchDashboardData action (src/Redux/actions/Dash/getDash.js) retrieves all dashboard metrics:
export const fetchDashboardData =
  (startDate = null, endDate = null) =>
  async (dispatch) => {
    dispatch({ type: "DASHBOARD_REQUEST" });

    try {
      const noCacheHeaders = { "Cache-Control": "no-cache" };

      const query =
        startDate && endDate
          ? `?startDate=${encodeURIComponent(startDate)}&endDate=${encodeURIComponent(endDate)}`
          : "";

      const [salesByDayRes, salesByMonthRes, topProductsRes, salesByUserRes] =
        await Promise.all([
          api.get("/dash/sales/day", { headers: noCacheHeaders }),
          api.get("/dash/sales/month", { headers: noCacheHeaders }),
          api.get(`/dash/top-products${query}`, { headers: noCacheHeaders }),
          api.get("/dash/sales/user", { headers: noCacheHeaders }),
          api.get("/dash/sales/week", { headers: noCacheHeaders }),
          api.get("/dash/product-profit", { headers: noCacheHeaders }),
        ]);

      dispatch({
        type: "DASHBOARD_SUCCESS",
        payload: {
          salesByDay: salesByDayRes.data || [],
          salesByMonth: salesByMonthRes.data || [],
          topProducts: topProductsRes.data || [],
          salesByUser: salesByUserRes.data || [],
        },
      });
    } catch (error) {
      dispatch({
        type: "DASHBOARD_FAILURE",
        payload: error.response?.data?.error || error.message,
      });
    }
  };
All dashboard requests use no-cache headers to ensure real-time data accuracy.

Dashboard Component

The main dashboard (src/Views/DashBoard.jsx) organizes all metrics into a comprehensive view:
const DashboardSPA = () => {
  const dispatch = useDispatch();
  const navigate = useNavigate();

  const {
    salesByDay,
    topProducts,
    salesByUser: userSales,
    loading,
  } = useSelector(state => state.dashboard);

  useEffect(() => {
    dispatch(fetchDashboardData());
  }, [dispatch]);

  if (loading)
    return (
      <p className="text-white text-center mt-10">
        Cargando dashboard...
      </p>
    );

  // Calculate KPIs...
};

KPI Metrics

KPI Calculations

The dashboard calculates key performance indicators from the sales data:
const totalRevenue = userSales.reduce(
  (acc, s) => acc + Number(s.totalAmount || 0),
  0
);

const totalProductsSold = userSales.reduce(
  (acc, s) => acc + Number(s.numberOfProducts || 0),
  0
);

KPI Display

<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
  <KpiCard title="Ingresos totales" value={`$${totalRevenue}`} />
  <KpiCard title="Ventas realizadas" value={userSales.length} />
  <KpiCard title="Productos vendidos" value={totalProductsSold} />
</div>

KpiCard Component

The KpiCard component (src/components/dash/kpiCard.jsx) displays individual metrics:
const KpiCard = ({ title, value }) => (
  <div className="bg-gray-900 rounded-xl p-4 shadow-lg">
    <h3 className="text-gray-400 text-sm mb-2">{title}</h3>
    <p className="text-white text-2xl font-bold">{value}</p>
  </div>
);

Total Revenue

Sum of all confirmed sales amounts

Sales Count

Total number of sales transactions

Products Sold

Total quantity of all products sold

Active Products

Number of products in inventory

Sales by Day Chart

Recharts Integration

The SalesByDayChart component (src/components/dash/salesDayChart.jsx) uses Recharts for visualization:
import {
  LineChart,
  Line,
  CartesianGrid,
  XAxis,
  YAxis,
  Tooltip,
  ResponsiveContainer,
} from "recharts";

const SalesByDayChart = ({ data }) => (
  <div className="bg-gray-900 rounded-2xl p-4 h-80">
    <h2 className="text-white text-lg font-semibold mb-3">
      Ventas por día
    </h2>

    <ResponsiveContainer width="100%" height="100%">
      <LineChart data={data}>
        <CartesianGrid strokeDasharray="3 3" />
        <XAxis dataKey="date" />
        <YAxis />
        <Tooltip />
        <Line
          type="monotone"
          dataKey="totalSales"
          stroke="#8884d8"
          strokeWidth={2}
        />
      </LineChart>
    </ResponsiveContainer>
  </div>
);

Chart Usage

<SalesByDayChart data={salesByDay} />
Data Format:
[
  { date: "2024-01-15", totalSales: 1250.00 },
  { date: "2024-01-16", totalSales: 980.50 },
  { date: "2024-01-17", totalSales: 1450.75 }
]
The line chart automatically scales to fit all data points and provides hover tooltips for detailed information.

Top Products Grid

TopProductsGrid Component

The TopProductsGrid component (src/components/dash/topProducts.jsx) displays best-selling products:
const TopProductsGrid = ({ products }) => (
  <div className="bg-gray-900 rounded-2xl p-4">
    <h2 className="text-white text-lg font-semibold mb-4">
      Productos más vendidos
    </h2>
    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
      {products.map((product) => (
        <div key={product.id} className="bg-gray-800 rounded-lg p-4">
          <img 
            src={product.images?.[0]?.url || '/placeholder.png'}
            alt={product.name}
            className="w-full h-32 object-cover rounded-lg mb-3"
          />
          <h3 className="text-white font-semibold">{product.name}</h3>
          <p className="text-gray-400 text-sm">Vendidos: {product.totalSold}</p>
          <p className="text-purple-400 font-bold">${product.totalRevenue}</p>
        </div>
      ))}
    </div>
  </div>
);

Usage

<TopProductsGrid products={topProducts} />
  • Product Name: Display name of the product
  • Total Sold: Quantity sold in the selected period
  • Total Revenue: Revenue generated by this product
  • Product Image: First image from the product gallery

Sales by User Table

SalesByUserTable Component

The SalesByUserTable component (src/components/dash/salesUserChart.jsx) shows sales performance per user:
const SalesByUserTable = ({ sales }) => (
  <div className="bg-gray-900 rounded-2xl p-4">
    <h2 className="text-white text-lg font-semibold mb-4">
      Ventas por usuario
    </h2>
    <div className="overflow-x-auto">
      <table className="w-full text-left">
        <thead>
          <tr className="text-gray-400 text-sm border-b border-gray-700">
            <th className="pb-3">Usuario</th>
            <th className="pb-3">Ventas</th>
            <th className="pb-3">Productos</th>
            <th className="pb-3">Total</th>
          </tr>
        </thead>
        <tbody>
          {sales.map((sale, idx) => (
            <tr key={idx} className="text-white border-b border-gray-800">
              <td className="py-3">{sale.userName}</td>
              <td className="py-3">{sale.salesCount}</td>
              <td className="py-3">{sale.numberOfProducts}</td>
              <td className="py-3 text-purple-400 font-bold">
                ${sale.totalAmount}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  </div>
);

Usage

<SalesByUserTable sales={userSales} />

User Name

Display name of the sales representative

Sales Count

Number of transactions completed

Products Sold

Total quantity of products sold

Total Amount

Total revenue generated by this user

Profitable Products

ProfitableProducts Component

The ProfitableProducts component (src/components/dash/profitableProducts.jsx) calculates profit margins:
const ProfitableProducts = ({ sales }) => {
  const calculateProfit = (product) => {
    const revenue = product.totalSales * product.price;
    const cost = product.totalSales * product.buyPrice;
    return revenue - cost;
  };

  const sortedProducts = [...sales].sort((a, b) => 
    calculateProfit(b) - calculateProfit(a)
  );

  return (
    <div className="bg-gray-900 rounded-2xl p-4">
      <h2 className="text-white text-lg font-semibold mb-4">
        Productos más rentables
      </h2>
      <div className="space-y-3">
        {sortedProducts.slice(0, 5).map((product) => (
          <div key={product.id} className="flex justify-between items-center">
            <div>
              <p className="text-white font-medium">{product.name}</p>
              <p className="text-gray-400 text-sm">
                Vendidos: {product.totalSales}
              </p>
            </div>
            <p className="text-green-400 font-bold">
              +${calculateProfit(product).toFixed(2)}
            </p>
          </div>
        ))}
      </div>
    </div>
  );
};

Usage

<ProfitableProducts sales={userSales} />
Profit calculation uses the difference between sale price and purchase price (buyPrice) multiplied by quantity sold.

Dashboard Layout

Grid Organization

The dashboard uses a responsive grid layout:
<div className="min-h-screen bg-black bg-opacity-75 p-5 space-y-10">
  {/* Header */}
  <div className="flex items-center justify-between">
    <button onClick={() => navigate("/")}>
      ← Inicio
    </button>
    <h1 className="text-xl font-semibold text-white">
      Dashboard
    </h1>
  </div>

  {/* KPIs */}
  <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
    <KpiCard title="Ingresos totales" value={`$${totalRevenue}`} />
    <KpiCard title="Ventas realizadas" value={userSales.length} />
    <KpiCard title="Productos vendidos" value={totalProductsSold} />
  </div>

  {/* Sales Chart */}
  <SalesByDayChart data={salesByDay} />

  {/* Top Products */}
  <TopProductsGrid products={topProducts} />

  {/* User Sales & Profitability */}
  <div className="grid md:grid-cols-2 gap-6">
    <SalesByUserTable sales={userSales} />
    <ProfitableProducts sales={userSales} />
  </div>
</div>

Date Range Filtering

The dashboard supports custom date ranges:
const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null);

const handleDateFilter = () => {
  dispatch(fetchDashboardData(startDate, endDate));
};
  • Filter top products by date range
  • Compare performance across time periods
  • Export filtered data
  • Reset to default (all time) view

API Endpoints

The dashboard fetches data from multiple endpoints:

/dash/sales/day

Daily sales aggregated by date

/dash/sales/month

Monthly sales totals

/dash/top-products

Best-selling products with optional date filters

/dash/sales/user

Sales broken down by user/employee

/dash/sales/week

Weekly sales trends

/dash/product-profit

Profit margins by product

Loading States

The dashboard handles loading gracefully:
if (loading)
  return (
    <p className="text-white text-center mt-10">
      Cargando dashboard...
    </p>
  );

Error Handling

Dashboard errors are caught and displayed to users:
dispatch({
  type: "DASHBOARD_FAILURE",
  payload: error.response?.data?.error || error.message,
});

Responsive Design

  • KPI cards stack vertically on mobile
  • Charts use ResponsiveContainer for auto-sizing
  • Tables scroll horizontally when needed
  • Grid layouts adapt to screen size
  • Touch-friendly interactive elements
  • Multi-column layouts for efficiency
  • Larger charts for better data visualization
  • Side-by-side comparisons
  • Expanded data tables
  • Interactive hover states

Best Practices

  • Review dashboard daily for business insights
  • Monitor KPI trends over time
  • Identify top-performing products
  • Track user sales performance
  • Use date filters for period comparisons
  • Compare current period to previous periods
  • Look for seasonal trends in sales
  • Identify underperforming products
  • Monitor profit margins closely
  • Track inventory turnover rates
  • Dashboard uses no-cache headers for fresh data
  • Parallel API requests for faster loading
  • Responsive charts optimize render performance
  • Efficient data aggregation on backend

Build docs developers (and LLMs) love