Admin AI Tools page: unified design system styling, provider selector with OpenAI turd emoji, free-text model input with exact ID warning
This commit is contained in:
@@ -1,26 +1,5 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getCampaignAnalytics } from "@/actions/harvest-reach/campaigns";
|
||||
import CommunicationsPage from "@/components/admin/CommunicationsPage";
|
||||
|
||||
export default async function AnalyticsPage() {
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser || !adminUser.can_manage_messages) redirect("/admin/pickup");
|
||||
|
||||
const effectiveBrandId = adminUser.brand_id ?? "64294306-5f42-463d-a5e8-2ad6c81a96de";
|
||||
const analytics = await getCampaignAnalytics(effectiveBrandId);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-stone-100 px-6 py-10">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<CommunicationsPage
|
||||
campaigns={[]}
|
||||
templates={[]}
|
||||
activeTab="analytics"
|
||||
brandId={effectiveBrandId}
|
||||
initialAnalytics={analytics}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
export default function AnalyticsPage() {
|
||||
redirect("/admin/communications");
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { redirect } from "next/navigation";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getCommunicationCampaigns, getCampaignById } from "@/actions/communications/campaigns";
|
||||
import { getCommunicationTemplates } from "@/actions/communications/templates";
|
||||
import { getHarvestReachSegments } from "@/actions/harvest-reach/segments";
|
||||
import CommunicationsPage from "@/components/admin/CommunicationsPage";
|
||||
|
||||
export default async function CampaignEditPage({
|
||||
@@ -10,36 +11,30 @@ export default async function CampaignEditPage({
|
||||
params: Promise<{ id: string }>;
|
||||
}) {
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser) redirect("/admin");
|
||||
if (!adminUser.can_manage_messages) redirect("/admin/pickup");
|
||||
if (!adminUser || !adminUser.can_manage_messages) {
|
||||
redirect("/admin/pickup");
|
||||
}
|
||||
|
||||
const { id } = await params;
|
||||
const isNew = id === "new";
|
||||
const effectiveBrandId = adminUser.brand_id ?? "64294306-5f42-463d-a5e8-2ad6c81a96de";
|
||||
|
||||
const [campaignsResult, templatesResult] = await Promise.all([
|
||||
const [campaignsResult, templatesResult, segmentsResult] = await Promise.all([
|
||||
getCommunicationCampaigns(effectiveBrandId),
|
||||
getCommunicationTemplates(effectiveBrandId),
|
||||
getHarvestReachSegments(effectiveBrandId),
|
||||
]);
|
||||
|
||||
const campaign = isNew ? undefined : id ? await getCampaignById(id) : undefined;
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-stone-100 px-6 py-10">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl font-bold text-stone-950">Harvest Reach</h1>
|
||||
</div>
|
||||
|
||||
<CommunicationsPage
|
||||
campaigns={campaignsResult.success ? campaignsResult.campaigns : []}
|
||||
templates={templatesResult.success ? templatesResult.templates : []}
|
||||
activeTab="campaigns"
|
||||
brandId={adminUser.brand_id ?? "64294306-5f42-463d-a5e8-2ad6c81a96de"}
|
||||
editCampaign={campaign}
|
||||
editMode={isNew ? "new" : "edit"}
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
<CommunicationsPage
|
||||
campaigns={campaignsResult.success ? campaignsResult.campaigns : []}
|
||||
templates={templatesResult.success ? templatesResult.templates : []}
|
||||
brandId={effectiveBrandId}
|
||||
initialSegments={segmentsResult.success ? segmentsResult.segments : []}
|
||||
editCampaign={campaign}
|
||||
editMode={isNew ? "new" : "edit"}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,37 +1,31 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getHarvestReachCampaigns } from "@/actions/harvest-reach/campaigns";
|
||||
import { getCommunicationCampaigns } from "@/actions/communications/campaigns";
|
||||
import { getCommunicationTemplates } from "@/actions/communications/templates";
|
||||
import { getHarvestReachSegments } from "@/actions/harvest-reach/segments";
|
||||
import CommunicationsPage from "@/components/admin/CommunicationsPage";
|
||||
|
||||
export default async function ComposePage() {
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser || !adminUser.can_manage_messages) redirect("/admin/pickup");
|
||||
if (!adminUser || !adminUser.can_manage_messages) {
|
||||
redirect("/admin/pickup");
|
||||
}
|
||||
|
||||
const effectiveBrandId = adminUser.brand_id ?? "64294306-5f42-463d-a5e8-2ad6c81a96de";
|
||||
|
||||
const [campaignsResult, templatesResult, segmentsResult] = await Promise.all([
|
||||
getHarvestReachCampaigns(effectiveBrandId),
|
||||
getCommunicationCampaigns(effectiveBrandId),
|
||||
getCommunicationTemplates(effectiveBrandId),
|
||||
getHarvestReachSegments(effectiveBrandId),
|
||||
]);
|
||||
|
||||
const campaigns = campaignsResult.success ? campaignsResult.campaigns : [];
|
||||
const templates = templatesResult.success ? templatesResult.templates : [];
|
||||
const segments = segmentsResult.success ? segmentsResult.segments : [];
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-stone-100 px-6 py-10">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<CommunicationsPage
|
||||
campaigns={campaigns}
|
||||
templates={templates}
|
||||
activeTab="compose"
|
||||
brandId={effectiveBrandId}
|
||||
initialSegments={segments}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<CommunicationsPage
|
||||
campaigns={campaignsResult.success ? campaignsResult.campaigns : []}
|
||||
templates={templatesResult.success ? templatesResult.templates : []}
|
||||
brandId={effectiveBrandId}
|
||||
initialSegments={segmentsResult.success ? segmentsResult.segments : []}
|
||||
editMode="new"
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,42 +1,5 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getCommunicationCampaigns } from "@/actions/communications/campaigns";
|
||||
import { getCommunicationTemplates } from "@/actions/communications/templates";
|
||||
import { getContacts } from "@/actions/communications/contacts";
|
||||
import CommunicationsPage from "@/components/admin/CommunicationsPage";
|
||||
|
||||
export default async function ContactsPage() {
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser) redirect("/admin");
|
||||
if (!adminUser.can_manage_messages) redirect("/admin/pickup");
|
||||
|
||||
const brandId = adminUser.brand_id ?? "64294306-5f42-463d-a5e8-2ad6c81a96de";
|
||||
|
||||
const [campaignsResult, templatesResult, contactsResult] = await Promise.all([
|
||||
getCommunicationCampaigns(brandId),
|
||||
getCommunicationTemplates(brandId),
|
||||
getContacts({ brandId, limit: 50 }),
|
||||
]);
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-stone-100 px-6 py-10">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl font-bold text-stone-950">Harvest Reach</h1>
|
||||
<p className="mt-2 text-stone-500">
|
||||
Manage email campaigns, templates, contacts, and message history.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<CommunicationsPage
|
||||
campaigns={campaignsResult.success ? campaignsResult.campaigns : []}
|
||||
templates={templatesResult.success ? templatesResult.templates : []}
|
||||
activeTab="contacts"
|
||||
brandId={brandId}
|
||||
initialContacts={contactsResult.success ? contactsResult.contacts : []}
|
||||
initialContactTotal={contactsResult.success ? contactsResult.total : 0}
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
export default function ContactsPage() {
|
||||
redirect("/admin/communications");
|
||||
}
|
||||
@@ -1,41 +1,5 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getCommunicationCampaigns } from "@/actions/communications/campaigns";
|
||||
import { getCommunicationTemplates } from "@/actions/communications/templates";
|
||||
import { getMessageLogs } from "@/actions/communications/send";
|
||||
import CommunicationsPage from "@/components/admin/CommunicationsPage";
|
||||
|
||||
export default async function LogsPage() {
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser) redirect("/admin");
|
||||
if (!adminUser.can_manage_messages) redirect("/admin/pickup");
|
||||
|
||||
const brandId = adminUser.brand_id ?? "64294306-5f42-463d-a5e8-2ad6c81a96de";
|
||||
|
||||
const [campaignsResult, templatesResult, logsResult] = await Promise.all([
|
||||
getCommunicationCampaigns(brandId),
|
||||
getCommunicationTemplates(brandId),
|
||||
getMessageLogs({ brandId, limit: 200 }),
|
||||
]);
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-stone-100 px-6 py-10">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl font-bold text-stone-950">Harvest Reach</h1>
|
||||
<p className="mt-2 text-stone-500">
|
||||
Manage email campaigns, templates, and message history.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<CommunicationsPage
|
||||
campaigns={campaignsResult.success ? campaignsResult.campaigns : []}
|
||||
templates={templatesResult.success ? templatesResult.templates : []}
|
||||
activeTab="logs"
|
||||
brandId={brandId}
|
||||
initialLogs={logsResult.success ? logsResult.logs : []}
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
export default function LogsPage() {
|
||||
redirect("/admin/communications");
|
||||
}
|
||||
@@ -8,9 +8,11 @@ import CommunicationsPage from "@/components/admin/CommunicationsPage";
|
||||
|
||||
export default async function CommunicationsRootPage() {
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser || !adminUser.can_manage_messages) redirect("/admin/pickup");
|
||||
if (!adminUser || !adminUser.can_manage_messages) {
|
||||
redirect("/admin/pickup");
|
||||
}
|
||||
|
||||
const effectiveBrandId = adminUser.brand_id ?? "64294306-5f42-463d-a5e8-2ad6c81a96de";
|
||||
const effectiveBrandId = adminUser!.brand_id ?? "64294306-5f42-463d-a5e8-2ad6c81a96de";
|
||||
|
||||
const [campaignsResult, templatesResult, segmentsResult, analyticsResult] = await Promise.all([
|
||||
getCommunicationCampaigns(effectiveBrandId),
|
||||
@@ -20,31 +22,12 @@ export default async function CommunicationsRootPage() {
|
||||
]);
|
||||
|
||||
return (
|
||||
<main className="min-h-screen px-6 py-10">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
{/* Breadcrumb */}
|
||||
<nav className="flex items-center gap-2 text-xs text-stone-500 mb-6">
|
||||
<a href="/admin" className="hover:text-stone-600 transition-colors">Admin</a>
|
||||
<span>/</span>
|
||||
<span className="text-stone-600">Harvest Reach</span>
|
||||
</nav>
|
||||
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl font-bold text-stone-950">Harvest Reach</h1>
|
||||
<p className="mt-2 text-stone-500">
|
||||
Manage email campaigns, templates, and message history.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<CommunicationsPage
|
||||
campaigns={campaignsResult.success ? campaignsResult.campaigns : []}
|
||||
templates={templatesResult.success ? templatesResult.templates : []}
|
||||
activeTab="campaigns"
|
||||
brandId={effectiveBrandId}
|
||||
initialSegments={segmentsResult.success ? segmentsResult.segments : []}
|
||||
initialAnalytics={analyticsResult}
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
<CommunicationsPage
|
||||
campaigns={campaignsResult.success ? campaignsResult.campaigns : []}
|
||||
templates={templatesResult.success ? templatesResult.templates : []}
|
||||
brandId={effectiveBrandId}
|
||||
initialSegments={segmentsResult.success ? segmentsResult.segments : []}
|
||||
initialAnalytics={analyticsResult}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,27 +1,5 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getHarvestReachSegments } from "@/actions/harvest-reach/segments";
|
||||
import CommunicationsPage from "@/components/admin/CommunicationsPage";
|
||||
|
||||
export default async function SegmentsPage() {
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser || !adminUser.can_manage_messages) redirect("/admin/pickup");
|
||||
|
||||
const effectiveBrandId = adminUser.brand_id ?? "64294306-5f42-463d-a5e8-2ad6c81a96de";
|
||||
const segmentsResult = await getHarvestReachSegments(effectiveBrandId);
|
||||
const segments = segmentsResult.success ? segmentsResult.segments : [];
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-stone-100 px-6 py-10">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<CommunicationsPage
|
||||
campaigns={[]}
|
||||
templates={[]}
|
||||
activeTab="segments"
|
||||
brandId={effectiveBrandId}
|
||||
initialSegments={segments}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
export default function SegmentsPage() {
|
||||
redirect("/admin/communications");
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getCommunicationCampaigns } from "@/actions/communications/campaigns";
|
||||
import { getCommunicationTemplates } from "@/actions/communications/templates";
|
||||
import { getCommunicationSettings } from "@/actions/communications/settings";
|
||||
import CommunicationsPage from "@/components/admin/CommunicationsPage";
|
||||
import CommunicationSettingsForm from "@/components/admin/CommunicationSettingsForm";
|
||||
|
||||
export default async function SettingsPage() {
|
||||
const adminUser = await getAdminUser();
|
||||
@@ -11,31 +9,41 @@ export default async function SettingsPage() {
|
||||
if (!adminUser.can_manage_messages) redirect("/admin/pickup");
|
||||
|
||||
const brandId = adminUser.brand_id ?? "64294306-5f42-463d-a5e8-2ad6c81a96de";
|
||||
|
||||
const [campaignsResult, templatesResult, settingsResult] = await Promise.all([
|
||||
getCommunicationCampaigns(brandId),
|
||||
getCommunicationTemplates(brandId),
|
||||
getCommunicationSettings(brandId),
|
||||
]);
|
||||
const settingsResult = await getCommunicationSettings(brandId);
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-stone-100 px-6 py-10">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl font-bold text-stone-950">Harvest Reach</h1>
|
||||
<p className="mt-2 text-stone-500">
|
||||
Manage email campaigns, templates, and message history.
|
||||
</p>
|
||||
<div className="min-h-screen bg-[var(--admin-bg)]">
|
||||
<div className="px-4 sm:px-6 md:px-8 pt-4 sm:pt-6">
|
||||
{/* Back button */}
|
||||
<a
|
||||
href="/admin/communications"
|
||||
className="inline-flex items-center gap-2 text-sm text-stone-500 hover:text-stone-700 mb-4"
|
||||
>
|
||||
<svg className="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="m15 18-6-6 6-6"/>
|
||||
</svg>
|
||||
Back to Harvest Reach
|
||||
</a>
|
||||
|
||||
{/* Header */}
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-xl bg-emerald-600">
|
||||
<svg className="h-5 w-5 text-white" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/>
|
||||
<circle cx="12" cy="12" r="3"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-xl sm:text-2xl font-black text-[var(--admin-text-primary)] tracking-tight">Harvest Reach Settings</h1>
|
||||
<p className="text-xs text-[var(--admin-text-muted)]">Configure email and SMS integration</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<CommunicationsPage
|
||||
campaigns={campaignsResult.success ? campaignsResult.campaigns : []}
|
||||
templates={templatesResult.success ? templatesResult.templates : []}
|
||||
activeTab="settings"
|
||||
brandId={brandId}
|
||||
initialSettings={settingsResult}
|
||||
/>
|
||||
{/* Settings Form */}
|
||||
<div className="rounded-2xl border border-[var(--admin-border)] bg-white p-4 sm:p-6">
|
||||
<CommunicationSettingsForm settings={settingsResult} brandId={brandId} />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getCommunicationTemplates, getTemplateById } from "@/actions/communications/templates";
|
||||
import { getCommunicationCampaigns } from "@/actions/communications/campaigns";
|
||||
import { getHarvestReachSegments } from "@/actions/harvest-reach/segments";
|
||||
import CommunicationsPage from "@/components/admin/CommunicationsPage";
|
||||
|
||||
export default async function TemplateEditPage({
|
||||
@@ -9,31 +11,30 @@ export default async function TemplateEditPage({
|
||||
params: Promise<{ id: string }>;
|
||||
}) {
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser) redirect("/admin");
|
||||
if (!adminUser.can_manage_messages) redirect("/admin/pickup");
|
||||
if (!adminUser || !adminUser.can_manage_messages) {
|
||||
redirect("/admin/pickup");
|
||||
}
|
||||
|
||||
const { id } = await params;
|
||||
const isNew = id === "new";
|
||||
const effectiveBrandId = adminUser.brand_id ?? "64294306-5f42-463d-a5e8-2ad6c81a96de";
|
||||
|
||||
const [campaignsResult, templatesResult, segmentsResult] = await Promise.all([
|
||||
getCommunicationCampaigns(effectiveBrandId),
|
||||
getCommunicationTemplates(effectiveBrandId),
|
||||
getHarvestReachSegments(effectiveBrandId),
|
||||
]);
|
||||
|
||||
const templatesResult = await getCommunicationTemplates();
|
||||
const template = isNew ? undefined : id ? await getTemplateById(id) : undefined;
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-stone-100 px-6 py-10">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl font-bold text-stone-950">Harvest Reach</h1>
|
||||
</div>
|
||||
|
||||
<CommunicationsPage
|
||||
campaigns={[]}
|
||||
templates={templatesResult.success ? templatesResult.templates : []}
|
||||
activeTab="templates"
|
||||
brandId={adminUser.brand_id ?? "64294306-5f42-463d-a5e8-2ad6c81a96de"}
|
||||
editTemplate={template}
|
||||
editMode={isNew ? "new" : "edit"}
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
<CommunicationsPage
|
||||
campaigns={campaignsResult.success ? campaignsResult.campaigns : []}
|
||||
templates={templatesResult.success ? templatesResult.templates : []}
|
||||
brandId={effectiveBrandId}
|
||||
initialSegments={segmentsResult.success ? segmentsResult.segments : []}
|
||||
editTemplate={template}
|
||||
editMode={isNew ? "new" : "edit"}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,36 +1,5 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getCommunicationCampaigns } from "@/actions/communications/campaigns";
|
||||
import { getCommunicationTemplates } from "@/actions/communications/templates";
|
||||
import CommunicationsPage from "@/components/admin/CommunicationsPage";
|
||||
|
||||
export default async function TemplatesPage() {
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser) redirect("/admin");
|
||||
if (!adminUser.can_manage_messages) redirect("/admin/pickup");
|
||||
|
||||
const [campaignsResult, templatesResult] = await Promise.all([
|
||||
getCommunicationCampaigns(adminUser.brand_id ?? undefined),
|
||||
getCommunicationTemplates(adminUser.brand_id ?? undefined),
|
||||
]);
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-stone-100 px-6 py-10">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl font-bold text-stone-950">Harvest Reach</h1>
|
||||
<p className="mt-2 text-stone-500">
|
||||
Manage email campaigns, templates, and message history.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<CommunicationsPage
|
||||
campaigns={campaignsResult.success ? campaignsResult.campaigns : []}
|
||||
templates={templatesResult.success ? templatesResult.templates : []}
|
||||
activeTab="templates"
|
||||
brandId={adminUser.brand_id ?? "64294306-5f42-463d-a5e8-2ad6c81a96de"}
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
export default function TemplatesPage() {
|
||||
redirect("/admin/communications");
|
||||
}
|
||||
Reference in New Issue
Block a user