TorbatYar/frontend/modules/communication/features/executiveDashboard.tsx
Mortezakoohjani 0d424c500a feat(platform): complete commercial runtime consolidation
Unify commercial runtime ownership across backend and frontend so platform, experience, and hospitality modules use the shared commercial source of truth.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-29 11:11:53 +03:30

97 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useQuery } from "@tanstack/react-query";
import Link from "next/link";
import { communicationApi } from "@/modules/communication/services/communication-api";
import { useAuth } from "@/hooks/useAuth";
import { useTenantId } from "@/hooks/useTenantId";
import {
useCommunicationCapabilities,
useCommunicationMonitoring,
} from "@/modules/communication/hooks/useCommunicationCapabilities";
import { CommunicationPageLoader, CommunicationPageError } from "@/modules/communication/pages/shared";
import { PageHeader, StatCard, Card, CardContent, Button, Badge } from "@/components/ds";
import { CommunicationBreadcrumbs } from "@/modules/communication/components/CommunicationBreadcrumbs";
export function ExecutiveDashboard() {
const { tenantId } = useTenantId();
const { isAuthenticated, loading: authLoading } = useAuth();
const caps = useCommunicationCapabilities();
const monitoring = useCommunicationMonitoring(tenantId);
const countsQ = useQuery({
queryKey: ["communication", tenantId, "exec-counts"],
queryFn: async () => {
const [providers, templates, messages] = await Promise.all([
communicationApi.providers.list(tenantId!),
communicationApi.templates.list(tenantId!),
communicationApi.messages.list(tenantId!, { limit: 500 }),
]);
return {
providers: providers.length,
templates: templates.length,
messages: messages.length,
delivered: messages.filter((m) => m.status === "delivered").length,
};
},
enabled: !!tenantId && isAuthenticated && !authLoading,
});
if (authLoading || !tenantId || countsQ.isLoading || caps.isLoading) {
return <CommunicationPageLoader />;
}
if (countsQ.error) return <CommunicationPageError error={countsQ.error} onRetry={() => countsQ.refetch()} />;
const c = countsQ.data!;
const stats = monitoring.data;
return (
<div className="space-y-6">
<CommunicationBreadcrumbs current="داشبورد اجرایی" />
<PageHeader
title="داشبورد اجرایی"
description="نمای کلی Torbat Communication — SMS Production Ready"
actions={
<Badge tone="success">v{caps.data?.version} · SMS MVP</Badge>
}
/>
<div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
<StatCard label="ارائه‌دهندگان" value={String(c.providers)} />
<StatCard label="قالب‌ها" value={String(c.templates)} />
<StatCard label="پیام‌ها" value={String(c.messages)} />
<StatCard label="تحویل‌شده" value={String(c.delivered)} />
</div>
{stats ? (
<div className="grid gap-4 sm:grid-cols-2">
<Card>
<CardContent className="p-4">
<p className="mb-2 text-sm font-semibold">صف پیام</p>
<pre className="text-xs text-[var(--muted)]">
{JSON.stringify(stats.queue_by_status, null, 2)}
</pre>
</CardContent>
</Card>
<Card>
<CardContent className="p-4">
<p className="mb-2 text-sm font-semibold">وضعیت پیامها</p>
<pre className="text-xs text-[var(--muted)]">
{JSON.stringify(stats.messages_by_status, null, 2)}
</pre>
</CardContent>
</Card>
</div>
) : null}
<Card>
<CardContent className="flex flex-wrap gap-2 p-4">
<Link href="/communication/sms/providers"><Button variant="outline">ارائهدهندگان</Button></Link>
<Link href="/communication/sms/send"><Button variant="outline">ارسال SMS</Button></Link>
<Link href="/communication/sms/messages"><Button variant="outline">تاریخچه</Button></Link>
<Link href="/communication/capabilities"><Button variant="outline">قابلیتها</Button></Link>
</CardContent>
</Card>
</div>
);
}
export default ExecutiveDashboard;