feat: add AI service client and implement tenant AI management dashboards
This commit is contained in:
parent
85ecd9dac1
commit
0a672619ea
@ -42,6 +42,7 @@ import { formatDate } from "@/utils/format-date";
|
||||
import AuditLogs from "@/pages/tenant/AuditLogs";
|
||||
import TenantSettings from "@/pages/tenant/Settings";
|
||||
import TenantAIProviders from "@/pages/tenant/TenantAIProviders";
|
||||
import { TenantAIDashboard } from "@/pages/tenant/TenantAIDashboard";
|
||||
// import DepartmentsTable from "@/components/superadmin/DepartmentsTable";
|
||||
import DesignationsTable from "@/components/superadmin/DesignationsTable";
|
||||
|
||||
@ -59,7 +60,8 @@ type TabType =
|
||||
| "license"
|
||||
| "audit-logs"
|
||||
| "billing"
|
||||
| "ai-providers";
|
||||
| "ai-providers"
|
||||
| "ai-dashboard";
|
||||
|
||||
const tabs: Array<{ id: TabType; label: string; icon: ReactElement }> = [
|
||||
{ id: "overview", label: "Overview", icon: <FileText className="w-4 h-4" /> },
|
||||
@ -89,6 +91,7 @@ const tabs: Array<{ id: TabType; label: string; icon: ReactElement }> = [
|
||||
{ id: "modules", label: "Modules", icon: <Package className="w-4 h-4" /> },
|
||||
{ id: "settings", label: "Settings", icon: <Settings className="w-4 h-4" /> },
|
||||
{ id: "ai-providers", label: "AI Providers", icon: <Brain className="w-4 h-4" /> },
|
||||
{ id: "ai-dashboard", label: "AI Dashboard", icon: <Brain className="w-4 h-4" /> },
|
||||
{ id: "license", label: "License", icon: <FileText className="w-4 h-4" /> },
|
||||
{
|
||||
id: "audit-logs",
|
||||
@ -381,6 +384,9 @@ const TenantDetails = (): ReactElement => {
|
||||
{activeTab === "ai-providers" && id && (
|
||||
<TenantAIProviders customTenantId={id} hideLayout={true} />
|
||||
)}
|
||||
{activeTab === "ai-dashboard" && id && (
|
||||
<TenantAIDashboard customTenantId={id} hideLayout={true} />
|
||||
)}
|
||||
{activeTab === "license" && <LicenseTab tenant={tenant} />}
|
||||
{activeTab === "audit-logs" && id && (
|
||||
<AuditLogs customTenantId={id} hideLayout={true} />
|
||||
|
||||
@ -21,7 +21,15 @@ import { formatDate } from "@/utils/format-date";
|
||||
|
||||
type GroupBy = "day" | "week" | "month";
|
||||
|
||||
export const TenantAIDashboard = (): ReactElement => {
|
||||
interface TenantAIDashboardProps {
|
||||
customTenantId?: string;
|
||||
hideLayout?: boolean;
|
||||
}
|
||||
|
||||
export const TenantAIDashboard = ({
|
||||
customTenantId,
|
||||
hideLayout = false,
|
||||
}: TenantAIDashboardProps): ReactElement => {
|
||||
const [groupBy, setGroupBy] = useState<GroupBy | null>(null);
|
||||
const [startDate, setStartDate] = useState<string>("");
|
||||
const [endDate, setEndDate] = useState<string>("");
|
||||
@ -54,11 +62,14 @@ export const TenantAIDashboard = (): ReactElement => {
|
||||
) => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const data = await aiService.getCostSummary({
|
||||
const data = await aiService.getCostSummary(
|
||||
{
|
||||
group_by: group || undefined,
|
||||
start_date: group && start ? `${start}T00:00:00.000Z` : undefined,
|
||||
end_date: group && end ? `${end}T23:59:59.999Z` : undefined,
|
||||
});
|
||||
},
|
||||
customTenantId
|
||||
);
|
||||
setCosts(data);
|
||||
} catch (err: any) {
|
||||
showToast.error(
|
||||
@ -73,7 +84,7 @@ export const TenantAIDashboard = (): ReactElement => {
|
||||
if (!groupBy || (startDate && endDate)) {
|
||||
void fetchCostSummary(groupBy, startDate, endDate);
|
||||
}
|
||||
}, [groupBy, startDate, endDate]);
|
||||
}, [groupBy, startDate, endDate, customTenantId]);
|
||||
|
||||
const providerColumns: Column<any>[] = [
|
||||
{
|
||||
@ -170,15 +181,7 @@ export const TenantAIDashboard = (): ReactElement => {
|
||||
return `${Math.round(ms)}ms`;
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout
|
||||
currentPage="AI Services"
|
||||
pageHeader={{
|
||||
title: "AI Usage & Cost Dashboard",
|
||||
description:
|
||||
"Monitor AI completions, tokens, and billing analytics across all providers.",
|
||||
}}
|
||||
>
|
||||
const content = (
|
||||
<div className="space-y-6">
|
||||
{/* Top Controls Row */}
|
||||
|
||||
@ -296,6 +299,22 @@ export const TenantAIDashboard = (): ReactElement => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (hideLayout) {
|
||||
return content;
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout
|
||||
currentPage="AI Services"
|
||||
pageHeader={{
|
||||
title: "AI Usage & Cost Dashboard",
|
||||
description:
|
||||
"Monitor AI completions, tokens, and billing analytics across all providers.",
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
@ -84,12 +84,16 @@ class AIService {
|
||||
return unwrap<AICompletion>(response);
|
||||
}
|
||||
|
||||
async getCostSummary(params: {
|
||||
async getCostSummary(
|
||||
params: {
|
||||
group_by?: "day" | "week" | "month";
|
||||
start_date?: string;
|
||||
end_date?: string;
|
||||
} = {}): Promise<AICostSummary> {
|
||||
const response = await apiClient.get("/ai/costs", { params });
|
||||
} = {},
|
||||
tenantId?: string
|
||||
): Promise<AICostSummary> {
|
||||
const headers = tenantId ? { "x-tenant-id": tenantId } : undefined;
|
||||
const response = await apiClient.get("/ai/costs", { params, headers });
|
||||
return unwrap<AICostSummary>(response);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user