Files
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

96 lines
3.6 KiB
TypeScript

import { ShellPage } from "@/components/page-templates";
import { SectionCard } from "@/components/ui";
import { getSession } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { redirect } from "next/navigation";
function formatDate(value: Date | null | undefined) {
if (!value) {
return "-";
}
return new Intl.DateTimeFormat("id-ID", {
day: "2-digit",
month: "short",
year: "numeric"
}).format(value);
}
export default async function ImportContactsPage() {
const session = await getSession();
if (!session) {
redirect("/login");
}
if (session.role === "agent") {
redirect("/unauthorized");
}
const [channels, tags, sampleContacts] = await Promise.all([
prisma.channel.findMany({
where: { tenantId: session.tenantId },
select: { id: true, channelName: true, provider: true }
}),
prisma.tag.findMany({
where: { tenantId: session.tenantId },
orderBy: { name: "asc" }
}),
prisma.contact.findMany({
where: { tenantId: session.tenantId },
orderBy: { createdAt: "desc" },
take: 5,
select: { id: true, fullName: true, phoneNumber: true, createdAt: true }
})
]);
return (
<ShellPage shell="admin" title="Import Contacts" description="Upload CSV dan mapping ke field contact sesuai channel tenant.">
<div className="grid gap-6 xl:grid-cols-3">
<SectionCard title="Step 1" description="Upload CSV">
<p className="text-sm text-on-surface-variant">
Pilih file CSV dari browser dan pastikan header minimal: nama, no_telepon, email.
</p>
<div className="mt-3 rounded-xl border border-line bg-surface-container p-3">
<input type="file" className="w-full text-sm" />
</div>
</SectionCard>
<SectionCard title="Step 2" description="Field mapping">
<div className="space-y-2 text-sm text-on-surface-variant">
<p>Gunakan channel yang aktif:</p>
{channels.length === 0 ? (
<p className="text-sm text-warning">Tenant belum memiliki channel. Tambahkan channel dulu.</p>
) : (
<ul className="space-y-1">
{channels.map((channel) => (
<li key={channel.id} className="rounded-xl border border-line bg-surface-container p-3">
{channel.channelName} {channel.provider}
</li>
))}
</ul>
)}
</div>
</SectionCard>
<SectionCard title="Step 3" description="Validation preview">
<div className="space-y-2 text-sm">
<p className="text-on-surface-variant">Baris terakhir di tenant: {sampleContacts.length} contoh terbaru.</p>
{sampleContacts.length === 0 ? (
<p className="text-warning text-sm">Belum ada contact sebelumnya.</p>
) : (
<ul className="space-y-2">
{sampleContacts.map((contact) => (
<li key={contact.id} className="rounded-xl border border-line bg-surface-container p-3">
<p className="font-medium text-ink">{contact.fullName}</p>
<p className="text-xs text-outline">{contact.phoneNumber}</p>
<p className="text-xs text-outline">Created: {formatDate(contact.createdAt)}</p>
</li>
))}
</ul>
)}
<p className="text-xs text-on-surface-variant">Available tags: {tags.length > 0 ? tags.map((tag) => tag.name).join(", ") : "Belum ada tag."}</p>
</div>
</SectionCard>
</div>
</ShellPage>
);
}