import { NEXT_PUBLIC_API_URL } from "@/config/api"; import { clientAuthFetch } from "@/app/utils/clientAuthFetch"; export const FEATURE_USAGE = { REPORT_MANAGEMENT: "REPORT_MANAGEMENT", TRUCK_ROUTING_SUMMARY: "TRUCK_ROUTING_SUMMARY", } as const; export const FEATURE_USAGE_ACTION = { PAGE_VIEW: "PAGE_VIEW", DOWNLOAD: "DOWNLOAD", PRINT: "PRINT", } as const; export type FeatureUsageSummaryRow = { userId: number; username: string; pageViews: number; downloads: number; prints: number; }; export type FeatureUsageSummaryPayload = { reportManagement: FeatureUsageSummaryRow[]; truckRoutingSummary: FeatureUsageSummaryRow[]; }; export type FeatureUsageSummaryFilters = { startDate?: string; endDate?: string; }; function toInt(v: unknown): number { if (v == null) return 0; if (typeof v === "number") return Number.isFinite(v) ? v : 0; const n = Number(v); return Number.isFinite(n) ? n : 0; } function normalizeRow(raw: Record): FeatureUsageSummaryRow { return { userId: toInt(raw.userId ?? raw.USER_ID), username: String(raw.username ?? raw.USERNAME ?? ""), pageViews: toInt(raw.pageViews ?? raw.PAGEVIEWS), downloads: toInt(raw.downloads ?? raw.DOWNLOADS), prints: toInt(raw.prints ?? raw.PRINTS), }; } /** Fire-and-forget client log; failures are ignored (console only). */ export function logFeatureUsage( featureCode: string, actionType: string, detail?: string | null, ): void { void (async () => { try { const res = await clientAuthFetch(`${NEXT_PUBLIC_API_URL}/feature-usage/log`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ featureCode, actionType, detail: detail == null || detail === "" ? null : detail, }), }); if (!res.ok) { console.warn("feature-usage log failed", res.status); } } catch (e) { console.warn("feature-usage log error", e); } })(); } export async function fetchFeatureUsageSummary( filters?: FeatureUsageSummaryFilters, ): Promise { const params = new URLSearchParams(); if (filters?.startDate) { params.set("startDate", filters.startDate); } if (filters?.endDate) { params.set("endDate", filters.endDate); } const query = params.toString(); const url = `${NEXT_PUBLIC_API_URL}/feature-usage/summary${query ? `?${query}` : ""}`; const res = await clientAuthFetch(url, { method: "GET", headers: { Accept: "application/json" }, }); if (!res.ok) { throw new Error(`feature-usage summary ${res.status}`); } const body = (await res.json()) as { data?: { reportManagement?: Record[]; truckRoutingSummary?: Record[]; }; }; const d = body.data; return { reportManagement: (d?.reportManagement ?? []).map((r) => normalizeRow(r)), truckRoutingSummary: (d?.truckRoutingSummary ?? []).map((r) => normalizeRow(r)), }; }