diff --git a/src/app/(app)/dashboard2/page.tsx b/src/app/(app)/dashboard2/page.tsx
index 06f0933..8d81146 100644
--- a/src/app/(app)/dashboard2/page.tsx
+++ b/src/app/(app)/dashboard2/page.tsx
@@ -9,8 +9,6 @@ import {
ShoppingCart,
CalendarDays,
TrendingUp,
- Gauge,
- CheckCircle,
AlertCircle,
DollarSign,
} from "lucide-react";
@@ -19,7 +17,6 @@ import getPocketBase from "@/lib/pocketbase";
import { CHART, withAlpha } from "@/components/charts/palette";
import { DashboardCard } from "@/components/charts/dashboard-card";
import { BarChart } from "@/components/charts/bar-chart";
-import { RadialGauge } from "@/components/charts/radial-gauge";
import type { RepDashboardData } from "@/lib/server/rep-dashboard-service";
function weekLabel(iso: string): string {
@@ -114,8 +111,8 @@ export default function RepDashboardPage() {
- {/* Row 1: quotes-loaded KPIs + this month's money (6 cards) */}
-
{positive ? "+" : ""}
@@ -245,36 +224,6 @@ function RepKpiCard({
);
}
-function RepCurrencyKpiCard({
- label,
- value,
- icon: Icon,
- accentColor,
-}: {
- label: string;
- value: number;
- icon: React.ComponentType<{ className?: string; style?: React.CSSProperties }>;
- accentColor: string;
-}) {
- return (
-
-
-
- {formatZar(value)}
-
- This month
-
- );
-}
-
function RepList({
items,
emptyLabel,
diff --git a/src/lib/server/rep-dashboard-service.test.ts b/src/lib/server/rep-dashboard-service.test.ts
index e2c2b5e..5ff8f08 100644
--- a/src/lib/server/rep-dashboard-service.test.ts
+++ b/src/lib/server/rep-dashboard-service.test.ts
@@ -191,33 +191,32 @@ describe("getRepDashboardData", () => {
expect(data.outstandingOrders.items.map((i) => i.order_number).sort()).toEqual(["ORD1", "ORD2"]);
});
- it("sums selling/cost and computes markup % for this month's order items", async () => {
+ it("sums selling for this month and last month in a single query", async () => {
seed("quotes", []);
seed("orders", []);
seed("order_items", [
- { id: "i1", "order.customer.rep": REP_ID, created: "2026-08-05T00:00:00.000Z", quantity: 2, selling_price: 100, cost_price: 50 },
- { id: "i2", "order.customer.rep": REP_ID, created: "2026-08-10T00:00:00.000Z", quantity: 1, selling_price: 40, cost_price: 20 },
- { id: "i3", "order.customer.rep": REP_ID, created: "2026-07-31T00:00:00.000Z", quantity: 1, selling_price: 999, cost_price: 1 }, // last month, excluded
- { id: "i4", "order.customer.rep": OTHER_REP_ID, created: "2026-08-05T00:00:00.000Z", quantity: 1, selling_price: 999, cost_price: 1 }, // different rep
+ { id: "i1", "order.customer.rep": REP_ID, created: "2026-08-05T00:00:00.000Z", quantity: 2, selling_price: 100 },
+ { id: "i2", "order.customer.rep": REP_ID, created: "2026-08-10T00:00:00.000Z", quantity: 1, selling_price: 40 },
+ { id: "i3", "order.customer.rep": REP_ID, created: "2026-07-31T00:00:00.000Z", quantity: 1, selling_price: 999 }, // last month
+ { id: "i4", "order.customer.rep": OTHER_REP_ID, created: "2026-08-05T00:00:00.000Z", quantity: 1, selling_price: 999 }, // different rep
+ { id: "i5", "order.customer.rep": REP_ID, created: "2026-06-15T00:00:00.000Z", quantity: 1, selling_price: 500 }, // outside both months
]);
const data = await getRepDashboardData(REP_ID, NOW, pbMock as never);
- // selling = 2*100 + 1*40 = 240; cost = 2*50 + 1*20 = 120
- expect(data.monthRevenue.selling).toBe(240);
- expect(data.monthRevenue.cost).toBe(120);
- expect(data.monthRevenue.markupPct).toBe(100); // (240-120)/120 * 100
+ // this month = 2*100 + 1*40 = 240; last month = 1*999 = 999
+ expect(data.monthRevenue.sellingThisMonth).toBe(240);
+ expect(data.monthRevenue.sellingLastMonth).toBe(999);
});
- it("returns markupPct: null when there's no cost this month (no div-by-zero)", async () => {
+ it("returns zeroes when there are no order items this month or last", async () => {
seed("quotes", []);
seed("orders", []);
seed("order_items", []);
const data = await getRepDashboardData(REP_ID, NOW, pbMock as never);
- expect(data.monthRevenue.selling).toBe(0);
- expect(data.monthRevenue.cost).toBe(0);
- expect(data.monthRevenue.markupPct).toBeNull();
+ expect(data.monthRevenue.sellingThisMonth).toBe(0);
+ expect(data.monthRevenue.sellingLastMonth).toBe(0);
});
});
\ No newline at end of file
diff --git a/src/lib/server/rep-dashboard-service.ts b/src/lib/server/rep-dashboard-service.ts
index 131a964..5648544 100644
--- a/src/lib/server/rep-dashboard-service.ts
+++ b/src/lib/server/rep-dashboard-service.ts
@@ -31,9 +31,8 @@ export interface RepDashboardData {
items: { id: string; order_number: string; customer_name: string | null }[];
};
monthRevenue: {
- selling: number;
- cost: number;
- markupPct: number | null;
+ sellingThisMonth: number;
+ sellingLastMonth: number;
};
}
@@ -172,8 +171,10 @@ export async function getRepDashboardData(
},
),
pb.collection(getOrderItemsCollectionName()).getList(1, MONTH_ORDER_ITEM_LIMIT, {
- filter: `${orderRepFilter} && ${rangeFilter("created", thisMonthStart, nextMonthStart)}`,
- fields: "id,quantity,order_qty,selling_price,cost_price",
+ // Single query covers both months; classify each row by `created`
+ // in code so we don't pay a second round-trip just for the delta.
+ filter: `${orderRepFilter} && created >= "${lastMonthStart.toISOString()}" && created < "${nextMonthStart.toISOString()}"`,
+ fields: "id,created,quantity,order_qty,selling_price",
}),
]);
@@ -227,19 +228,26 @@ export async function getRepDashboardData(
};
/* ---------- monthRevenue ---------- */
- let selling = 0;
- let cost = 0;
+ let sellingThisMonth = 0;
+ let sellingLastMonth = 0;
+ const thisMonthStartMs = thisMonthStart.getTime();
for (const it of monthOrderItems.items as unknown as Array<{
+ created?: string;
quantity?: number | null;
order_qty?: number | null;
selling_price?: number | null;
- cost_price?: number | null;
}>) {
const qty = Number(it.quantity ?? it.order_qty ?? 0);
- selling += Number(it.selling_price ?? 0) * qty;
- cost += Number(it.cost_price ?? 0) * qty;
+ const lineTotal = Number(it.selling_price ?? 0) * qty;
+ // `created` is an ISO string — compare on its parsed timestamp so we
+ // don't tie this to a particular date-string format PB happens to use.
+ const createdMs = it.created ? new Date(it.created).getTime() : 0;
+ if (createdMs >= thisMonthStartMs) {
+ sellingThisMonth += lineTotal;
+ } else {
+ sellingLastMonth += lineTotal;
+ }
}
- const markupPct = cost > 0 ? ((selling - cost) / cost) * 100 : null;
return {
quotesLoaded: {
@@ -253,6 +261,6 @@ export async function getRepDashboardData(
quoteVolumeTrend,
outstandingQuotes,
outstandingOrders,
- monthRevenue: { selling, cost, markupPct },
+ monthRevenue: { sellingThisMonth, sellingLastMonth },
};
}
\ No newline at end of file