Files
whatsapp-inbox-platform/app/super-admin/channels/[channelId]/page.tsx
Wira Basalamah adde003fba
Some checks failed
CI - Production Readiness / Verify (push) Has been cancelled
chore: initial project import
2026-04-21 09:29:29 +07:00

97 lines
3.7 KiB
TypeScript

import Link from "next/link";
import { redirect } from "next/navigation";
import { ShellPage } from "@/components/page-templates";
import { SectionCard } from "@/components/ui";
import { getSession } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
function formatDate(date: Date | null) {
if (!date) {
return "Not synced";
}
return new Intl.DateTimeFormat("id-ID", {
day: "2-digit",
month: "short",
year: "numeric",
hour: "2-digit",
minute: "2-digit"
}).format(date);
}
export default async function SuperAdminChannelDetailPage({
params
}: {
params: Promise<{ channelId: string }>;
}) {
const session = await getSession();
if (!session || session.role !== "super_admin") {
redirect("/unauthorized");
}
const { channelId } = await params;
const channel = await prisma.channel.findUnique({
where: { id: channelId },
include: {
tenant: true,
conversations: {
where: {},
take: 5,
orderBy: { lastMessageAt: "desc" }
},
webhookEvents: {
orderBy: { createdAt: "desc" },
take: 8
}
}
});
if (!channel) {
redirect("/super-admin/channels?error=channel_not_found");
}
const failedWebhookCount = channel.webhookEvents.filter((item) => item.processStatus === "failed").length;
return (
<ShellPage shell="super-admin" title="Channel Detail" description="Phone status, webhook health, failure summary, dan reconnect action.">
<div className="grid gap-6 xl:grid-cols-2">
<SectionCard title="Channel info">
<p className="text-sm text-on-surface-variant">Tenant: {channel.tenant.name}</p>
<p className="text-sm text-on-surface-variant">Provider: {channel.provider}</p>
<p className="text-sm text-on-surface-variant">Channel name: {channel.channelName}</p>
<p className="text-sm text-on-surface-variant">WABA ID: {channel.wabaId ?? "-"}</p>
<p className="text-sm text-on-surface-variant">Phone Number ID: {channel.phoneNumberId ?? "-"}</p>
<p className="text-sm text-on-surface-variant">Display Number: {channel.displayPhoneNumber ?? "-"}</p>
<p className="text-sm text-on-surface-variant">Status: {channel.status}</p>
<p className="text-sm text-on-surface-variant">Webhook status: {channel.webhookStatus ?? "unknown"}</p>
<p className="text-sm text-on-surface-variant">Last sync: {formatDate(channel.lastSyncAt)}</p>
<div className="mt-4 flex gap-3">
<Link href={`/super-admin/tenants/${channel.tenantId}`} className="text-brand hover:underline">
Open tenant
</Link>
<Link href="/super-admin/channels" className="text-brand hover:underline">
Back to channels
</Link>
</div>
</SectionCard>
<SectionCard title="Health">
<p className="text-sm text-on-surface-variant">Webhook failures: {failedWebhookCount}</p>
<p className="text-sm text-on-surface-variant">Conversations tracked: {channel.conversations.length}</p>
<ul className="mt-2 space-y-2">
{channel.webhookEvents.map((event) => (
<li key={event.id} className="rounded-xl border border-line bg-surface-container p-3">
<p className="text-xs text-outline">{event.eventType}</p>
<p className="text-sm text-on-surface">Status: {event.processStatus}</p>
<p className="text-xs text-outline">Created: {formatDate(event.createdAt)}</p>
</li>
))}
{channel.webhookEvents.length === 0 ? <p className="text-sm text-on-surface-variant">No webhook events.</p> : null}
</ul>
</SectionCard>
</div>
</ShellPage>
);
}