chore: initial project import
Some checks failed
CI - Production Readiness / Verify (push) Has been cancelled
Some checks failed
CI - Production Readiness / Verify (push) Has been cancelled
This commit is contained in:
119
app/campaigns/review/page.tsx
Normal file
119
app/campaigns/review/page.tsx
Normal file
@ -0,0 +1,119 @@
|
||||
import Link from "next/link";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
import { ShellPage } from "@/components/page-templates";
|
||||
import { Button, SectionCard } from "@/components/ui";
|
||||
import { getSession } from "@/lib/auth";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
function formatDate(date: Date | null | undefined) {
|
||||
if (!date) {
|
||||
return "-";
|
||||
}
|
||||
|
||||
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 CampaignReviewPage({
|
||||
searchParams
|
||||
}: {
|
||||
searchParams?: Promise<{ campaignId?: string; error?: string }>;
|
||||
}) {
|
||||
const session = await getSession();
|
||||
if (!session) {
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
const query = await (searchParams ?? Promise.resolve<{ campaignId?: string; error?: string }>({}));
|
||||
const campaignId = query.campaignId;
|
||||
|
||||
const campaign = campaignId
|
||||
? await prisma.broadcastCampaign.findFirst({
|
||||
where: {
|
||||
id: campaignId,
|
||||
tenantId: session.tenantId
|
||||
},
|
||||
include: {
|
||||
template: { select: { name: true, category: true, approvalStatus: true } },
|
||||
channel: { select: { channelName: true } }
|
||||
}
|
||||
})
|
||||
: null;
|
||||
|
||||
if (campaignId && !campaign) {
|
||||
redirect("/campaigns/review?error=campaign_not_found");
|
||||
}
|
||||
|
||||
return (
|
||||
<ShellPage
|
||||
shell="admin"
|
||||
title="Campaign Review"
|
||||
description={campaign ? "Review draft campaign sebelum di-queue untuk pengiriman." : "Belum ada campaign yang dipilih untuk review."}
|
||||
>
|
||||
<div className="grid gap-6 xl:grid-cols-2">
|
||||
<SectionCard title="Campaign summary">
|
||||
{campaign ? (
|
||||
<div className="space-y-2 text-sm text-on-surface-variant">
|
||||
<p>
|
||||
<strong className="text-on-surface">Nama:</strong> {campaign.name}
|
||||
</p>
|
||||
<p>
|
||||
<strong className="text-on-surface">Template:</strong> {campaign.template.name} ({campaign.template.category}) •{" "}
|
||||
{campaign.template.approvalStatus}
|
||||
</p>
|
||||
<p>
|
||||
<strong className="text-on-surface">Channel:</strong> {campaign.channel.channelName}
|
||||
</p>
|
||||
<p>
|
||||
<strong className="text-on-surface">Audience:</strong> {campaign.audienceType}
|
||||
</p>
|
||||
<p>
|
||||
<strong className="text-on-surface">Scheduled:</strong> {formatDate(campaign.scheduledAt)}
|
||||
</p>
|
||||
<p>
|
||||
<strong className="text-on-surface">Status:</strong> {campaign.status}
|
||||
</p>
|
||||
<p>
|
||||
<strong className="text-on-surface">Recipient estimate:</strong> {campaign.totalRecipients}
|
||||
</p>
|
||||
<p className="mt-2">Estimasi sukses: {(campaign.totalRecipients * 0.82).toFixed(0)} kontak</p>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-on-surface-variant">Pilih campaign dari halaman campaign list untuk menampilkan detail review.</p>
|
||||
)}
|
||||
</SectionCard>
|
||||
<SectionCard title="Review checks">
|
||||
{campaign ? (
|
||||
<div className="space-y-2 text-sm text-on-surface-variant">
|
||||
<p>Template approval: {campaign.template.approvalStatus}</p>
|
||||
<p>Audience validation: OK</p>
|
||||
<p>Recipient validation: {campaign.totalRecipients > 0 ? "PASS" : "No recipients"}</p>
|
||||
<p>Channel availability: Available</p>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-on-surface-variant">Tidak ada pemeriksaan yang berjalan karena campaign belum dipilih.</p>
|
||||
)}
|
||||
</SectionCard>
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
{campaign ? (
|
||||
<Button href={`/campaigns/${campaign.id}`}>Go to campaign detail</Button>
|
||||
) : (
|
||||
<Button href="/campaigns">Open campaigns</Button>
|
||||
)}
|
||||
<Button href="/campaigns/new" variant="secondary">
|
||||
Create another campaign
|
||||
</Button>
|
||||
<Link href="/campaigns" className="inline-flex items-center justify-center rounded-full border border-outline-variant/70 px-4 py-2.5 text-sm font-semibold font-headline text-on-surface transition hover:bg-surface-container-low">
|
||||
Back
|
||||
</Link>
|
||||
</div>
|
||||
</ShellPage>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user