Nasaq
Components

BusinessReports

Four ready made business reports, profitability by project, an employee KPI dashboard, a CRM pipeline with a chart and table toggle and support inbox statistics. Each is a section you drop into a page.

PreviewOpen ↗

Code

import { ProfitabilityReport } from "@fadymondy/nasaq/web";const money = { style: "currency", currency: "SAR", maximumFractionDigits: 0 } as const;export function Profit() {  return (    <ProfitabilityReport      format={money}      rows={[        { id: "p1", name: "Website rebuild", revenue: 120000, cost: 78000, hours: 410 },        { id: "p2", name: "Mobile app", revenue: 90000, cost: 96000, hours: 520 },      ]}    />  );}

Analytics · beta

Live examples and controls: BusinessReports in the lab.

Install

npx shadcn@latest add https://docs.nasaqui.com/r/business-reports.json

Four report sections built from the same parts (StatCard, SegmentBar, ProgressRing, FunnelSteps, TimeSeriesPanel, DataTable). They take plain data and formatting options, and know nothing about where the data came from.

  • ProfitabilityReport: revenue, cost, profit and margin, by project, client or service.
  • EmployeeKpiDashboard: a card per person with attainment against a target.
  • PipelineReport: the CRM pipeline stage by stage, as a funnel or a table.
  • SupportStatsReport: response and resolution times, satisfaction, SLA, volume and agents.

When to use

  • A report page in a back office, next to a ReportFilterBar.
  • You have the numbers already and want the layout, the tones and the wording.

When not to use

Import

import { ProfitabilityReport, EmployeeKpiDashboard, PipelineReport, SupportStatsReport } from "@fadymondy/nasaq/web";

Quick start

import { ProfitabilityReport } from "@fadymondy/nasaq/web";

const money = { style: "currency", currency: "SAR", maximumFractionDigits: 0 } as const;

export function Profit() {
  return (
    <ProfitabilityReport
      format={money}
      rows={[
        { id: "p1", name: "Website rebuild", revenue: 120000, cost: 78000, hours: 410 },
        { id: "p2", name: "Mobile app", revenue: 90000, cost: 96000, hours: 520 },
      ]}
    />
  );
}

Anatomy

ProfitabilityReport      data-slot="profitability-report": StatGrid, cost against profit bar, DataTable
EmployeeKpiDashboard     data-slot="employee-kpi-dashboard": StatGrid, a Card per person with ProgressRing
PipelineReport           data-slot="pipeline-report": StatGrid, Chart / Table toggle, FunnelSteps or DataTable
SupportStatsReport       data-slot="support-stats-report": StatGrid, TimeSeriesPanel, SegmentBar, agents DataTable

API

ProfitabilityReport

PropTypeDefaultDescription
rows{ id, name, revenue, cost, hours?, marginTrend? }[]requiredOne per project, client or service.
formatFormatNumberOptionsrequiredCurrency options for money.
subjectLabelstring"Project"Heading of the name column.
thinBelownumber0.15Margins below this read "Thin". Below zero reads "Loss".
rowActions(row) => DataTableRowAction[]noneRow menu: the ⋯ button, context-click, long press, Shift+F10.
loading error onRetryStates.
labelsPartial<BusinessReportsLabels>en / arText overrides.

EmployeeKpiDashboard

PropTypeDefaultDescription
employees{ id, name, role?, avatarSrc?, target, actual, metrics?, trend?, delta? }[]requiredmetrics are extra figures on the card.
formatFormatNumberOptionsplain numberFor target and actual.
measurestringnoneWhat the target measures, shown in the summary.
onTrackAtnumber0.8Share of the target that counts as On track.
actions(employee) => ContextMenuAction[]noneCard menu: the ⋯ button, context-click, long press, Shift+F10.

PipelineReport

PropTypeDefaultDescription
stages{ id, label, count, value, won? }[]requiredIn order, each with the deals that reached it (so counts fall down the list); "Pipeline value" is the first stage. The stage marked won (default the last) gives the win rate.
formatFormatNumberOptionsrequiredCurrency options.
view defaultView onViewChange"chart" | "table""chart"The toggle.
stageActions(stage) => DataTableRowAction[]noneMenu of a stage in the table view.

SupportStatsReport

PropTypeDescription
summary{ open, firstResponseMinutes, resolutionMinutes, csat, slaRate, deltas? }Times in minutes, rates as fractions. Short times show as minutes, long ones as hours.
volume previousVolumeTimeSeriesPoint[]Rows with date, created and resolved.
byStatusSegmentBarSegment[]The status mix.
agents{ id, name, assigned, resolved, firstResponseMinutes, csat, trend? }[]The agents table.
agentActions(agent) => DataTableRowAction[]Row menu.

Helpers

profitMargin, profitTotals, marginBand, attainment, kpiStatus, pipelineRows, winRate, median, slaRate. All pure.

Examples

A pipeline that opens as a table:

import { PipelineReport } from "@fadymondy/nasaq/web";

export const Pipeline = () => (
  <PipelineReport
    defaultView="table"
    format={{ style: "currency", currency: "SAR", notation: "compact" }}
    stages={[
      { id: "lead", label: "Leads", count: 240, value: 960000 },
      { id: "proposal", label: "Proposal", count: 80, value: 640000 },
      { id: "won", label: "Won", count: 24, value: 210000, won: true },
    ]}
  />
);

Employee cards with a menu:

import { EmployeeKpiDashboard } from "@fadymondy/nasaq/web";

export const Team = () => (
  <EmployeeKpiDashboard
    measure="Billable hours"
    employees={[{ id: "e1", name: "Sara", role: "Designer", target: 140, actual: 152 }]}
    actions={(e) => [{ id: "open", label: `Open ${e.name}`, onSelect: () => {} }]}
  />
);

Accessibility

Each report is a section; figures live in tables with headers, or in cards with a heading. Status is always text as well as colour: Loss, Thin, Healthy and Ahead, On track, Behind carry an icon and a word. Rings and small charts have text names, and the funnel writes the conversion between steps. The chart and table toggle is a labelled toggle group. Menus open from the ⋯ button, context-click, long press, Shift+F10 and the Menu key.

RTL & i18n

Layout follows the reading direction and the charts mirror. English and Arabic text ship built in; override with labels. Names and category labels come from you, localised. Numbers, currency, percentages and durations use Western digits and are bidi isolated.

Styling & tokens

Uses the Card, Badge, StatCard and chart tokens (--nq-success, --nq-warning, --nq-info). Target [data-slot="profitability-report"] and the other slots; extend with className.

Do / Don't

  • Do pass money as format with the currency, so every figure agrees.
  • Do give people and projects localised names.
  • Do offer actions for the things a reader does next (open the project, message the person).
  • Don't put the ring's meaning in colour only; keep the status word.
  • Don't feed times in seconds; the support report expects minutes.

Lab

https://docs.nasaqui.com/?path=/docs/components-analytics-pages-profitability--docs

On this page