JUNOHUB-test/src/app/dashboard/storefront-chat/page.tsx
2026-04-02 14:31:35 +05:00

112 lines
4.7 KiB
TypeScript

"use server"
import { prisma } from "@/lib/prisma"
import { auth } from "@/auth.vendor"
import { redirect } from "next/navigation"
export default async function StorefrontChatInboxPage() {
const session = await auth()
if (!session?.user?.id) {
redirect("/login")
}
const p = prisma as any
const stores = await prisma.store.findMany({
where: { userId: session.user.id, onboardingComplete: true },
select: { id: true, businessName: true, shopifyDomain: true, isActive: true }
})
const store = stores.find((s) => s.isActive) ?? stores[0]
if (!store) {
redirect("/onboarding")
}
const conversations = await p.storefrontChatConversation.findMany({
where: { storeId: store.id },
orderBy: { updatedAt: "desc" },
take: 25,
select: { id: true, visitorId: true, customerEmail: true, updatedAt: true }
})
const conversationIds = conversations.map((c: { id: string }) => c.id)
const messages = await p.storefrontChatMessage.findMany({
where: conversationIds.length ? { conversationId: { in: conversationIds } } : undefined,
orderBy: { createdAt: "desc" },
take: 200,
select: {
id: true,
content: true,
createdAt: true,
senderType: true,
conversation: {
select: {
visitorId: true,
customerEmail: true
}
}
}
})
const sorted = [...messages].sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime())
return (
<div className="flex flex-col gap-4 p-1">
<div className="flex items-start justify-between gap-4">
<div className="min-w-0">
<h1 className="text-xl font-black text-white">Storefront Chat Inbox</h1>
<p className="text-sm text-slate-400 mt-1 truncate">
{store.businessName} · {store.shopifyDomain}
</p>
</div>
<div className="shrink-0 text-right">
<p className="text-sm font-black text-white">{conversations.length} visitors</p>
<p className="text-xs text-slate-500 mt-1">{sorted.length} messages</p>
</div>
</div>
{sorted.length === 0 ? (
<div className="bg-white/5 border border-white/10 rounded-2xl p-6 text-slate-300">
<p className="font-black">No storefront chat messages yet.</p>
<p className="text-sm text-slate-400 mt-2">When customers send a message from the widget, it will show here.</p>
</div>
) : (
<div className="bg-white/5 border border-white/10 rounded-2xl overflow-hidden">
<div className="p-4 border-b border-white/10 flex items-center justify-between">
<p className="text-sm font-black text-white">Recent activity</p>
<p className="text-xs text-slate-400">Read-only</p>
</div>
<div className="max-h-[70vh] overflow-y-auto p-4 space-y-3">
{sorted.map((m) => (
<div key={m.id} className="flex flex-col gap-2">
<div className="flex items-center justify-between gap-4">
<div className="min-w-0">
<p className="text-xs font-black uppercase tracking-widest text-slate-400 truncate">
{m.senderType === "CUSTOMER" ? "CUSTOMER" : m.senderType}
{" · "}
{m.conversation?.visitorId || "visitor"}
</p>
{m.conversation?.customerEmail ? (
<p className="text-[11px] text-slate-500 truncate">{m.conversation.customerEmail}</p>
) : null}
</div>
<p className="text-[11px] text-slate-500 shrink-0">
{new Date(m.createdAt).toLocaleString()}
</p>
</div>
<div className="whitespace-pre-wrap text-sm text-white/90 bg-black/20 border border-white/10 rounded-2xl px-4 py-3">
{m.content}
</div>
</div>
))}
</div>
</div>
)}
</div>
)
}