adds campaignX as upcoming feature

This commit is contained in:
Mayur Shinde
2026-06-12 16:54:10 +05:30
parent a2c77878ff
commit 46c8933ec7
3 changed files with 182 additions and 11 deletions
+7
View File
@@ -49,6 +49,7 @@ import CustomerEstimateWizard from './modules/estimateWizard/CustomerEstimateWiz
import EstimateWizardAdmin from './modules/estimateWizard/EstimateWizardAdmin';
import SocialAdsEngine from './modules/socialAdsEngine/SocialAdsEngine';
import PublicAdLanding from './modules/socialAdsEngine/PublicAdLanding';
import CampaignXComingSoon from './pages/CampaignXComingSoon';
// ... (existing imports)
const ProtectedRoute = ({ children, allowedRoles }) => {
@@ -93,6 +94,12 @@ function App() {
<SocialAdsEngine />
</ProtectedRoute>
} />
{/* CampaignX — placeholder teaser screen for the upcoming marketing module (Owner/Admin) */}
<Route path="/campaignx" element={
<ProtectedRoute allowedRoles={['OWNER', 'ADMIN']}>
<CampaignXComingSoon />
</ProtectedRoute>
} />
<Route
path="/chat-assistant"
element={
+31 -11
View File
@@ -6,7 +6,7 @@ import {
LayoutDashboard, Map, Calendar, LogOut, User, Home, MessageSquare,
ChevronLeft, ChevronRight, Sun, Moon, Trophy, Users, Briefcase,
FileText, Menu, X, Calculator, PlusCircle, ClipboardList, Zap, LayoutGrid, Settings, CloudLightning,
HardHat, ShieldCheck, Sparkles, Megaphone
HardHat, ShieldCheck, Sparkles, Megaphone, Rocket
} from 'lucide-react';
import PageTransition from './PageTransition';
@@ -160,6 +160,8 @@ const Layout = () => {
...commonItems,
{ to: "/estimate-wizard/admin", icon: Settings, label: "Wizard Admin" },
{ to: "/marketing", icon: Megaphone, label: "Ad Engine" },
{ type: "section", label: "Upcoming Features" },
{ to: "/campaignx", icon: Rocket, label: <span>Campaign<span className="text-amber-500">X</span></span> },
];
case 'ADMIN':
return [
@@ -183,6 +185,8 @@ const Layout = () => {
...commonItems,
{ to: "/estimate-wizard/admin", icon: Settings, label: "Wizard Admin" },
{ to: "/marketing", icon: Megaphone, label: "Ad Engine" },
{ type: "section", label: "Upcoming Features" },
{ to: "/campaignx", icon: Rocket, label: <span>Campaign<span className="text-amber-500">X</span></span> },
];
case 'CONTRACTOR':
case 'SUBCONTRACTOR':
@@ -288,16 +292,32 @@ const Layout = () => {
{/* 2. Navigation Items */}
<nav className="flex-1 px-3 py-6 space-y-1 overflow-y-auto custom-scrollbar" role="navigation">
{navItems.map((item) => (
<SidebarItem
key={item.to}
to={item.to}
icon={item.icon}
label={item.label}
isCollapsed={isCollapsed && !isMobileMenuOpen}
onClick={() => setIsMobileMenuOpen(false)}
/>
))}
{navItems.map((item, idx) => {
// Section header — a divider line followed by a small uppercase label.
if (item.type === 'section') {
const collapsed = isCollapsed && !isMobileMenuOpen;
return (
<div key={`section-${idx}`} className="pt-4 pb-1">
<div className="h-px bg-zinc-200 dark:bg-white/10 mb-2" />
{!collapsed && (
<span className="px-3 text-[10px] font-bold uppercase tracking-widest text-zinc-400 dark:text-zinc-500">
{item.label}
</span>
)}
</div>
);
}
return (
<SidebarItem
key={item.to}
to={item.to}
icon={item.icon}
label={item.label}
isCollapsed={isCollapsed && !isMobileMenuOpen}
onClick={() => setIsMobileMenuOpen(false)}
/>
);
})}
</nav>
{/* 3. User Profile & Footer */}
+144
View File
@@ -0,0 +1,144 @@
/**
* CampaignXComingSoon — placeholder / teaser screen for the upcoming CampaignX module.
*
* Rendered at /campaignx. This is intentionally a "coming soon" experience: a hero
* that explains what CampaignX is, followed by a vertical timeline of the upcoming
* features that will ship with the module. No real functionality is wired yet.
*/
import React from 'react';
import { motion } from 'framer-motion';
import {
Rocket, Sparkles, Target, BarChart3, Bot, Layers, Send, Clock,
} from 'lucide-react';
const UPCOMING = [
{
icon: Target,
title: 'Multi-Channel Campaign Orchestration',
desc: 'Design once and launch across email, SMS, social and ads from a single canvas — with audience targeting baked in.',
},
{
icon: Bot,
title: 'AI Campaign Copilot',
desc: 'Generate copy, subject lines and creative variants instantly, then let the assistant recommend the best-performing mix.',
},
{
icon: Layers,
title: 'Visual Journey Builder',
desc: 'Drag-and-drop branching journeys with triggers, delays and conditions to nurture every lead automatically.',
},
{
icon: Send,
title: 'Smart Send-Time Optimization',
desc: 'CampaignX learns when each contact is most likely to engage and schedules delivery for peak response.',
},
{
icon: BarChart3,
title: 'Real-Time Performance Analytics',
desc: 'Track opens, clicks, conversions and ROI live, with attribution that ties revenue back to every touchpoint.',
},
];
export default function CampaignXComingSoon() {
return (
<div className="min-h-full bg-zinc-50 dark:bg-[#09090b]">
<div className="max-w-4xl mx-auto px-4 sm:px-6 py-10 sm:py-16">
{/* --- Hero --- */}
<motion.div
initial={{ opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.4 }}
className="text-center"
>
<div className="inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-amber-500/10 text-amber-600 dark:text-amber-400 text-xs font-bold uppercase tracking-wider mb-6 ring-1 ring-amber-500/20">
<Clock size={13} />
Coming Soon
</div>
<div className="flex justify-center mb-6">
<div className="relative">
<div className="absolute inset-0 rounded-3xl bg-gradient-to-tr from-amber-400 to-orange-600 blur-2xl opacity-40" />
<div className="relative p-5 rounded-3xl bg-gradient-to-tr from-amber-400 to-orange-600 text-white shadow-xl shadow-amber-500/30">
<Rocket size={40} strokeWidth={2} />
</div>
</div>
</div>
<h1 className="text-3xl sm:text-5xl font-extrabold tracking-tight text-zinc-900 dark:text-white">
Campaign<span className="text-amber-500">X</span>
</h1>
<p className="mt-4 text-base sm:text-lg text-zinc-600 dark:text-zinc-400 max-w-2xl mx-auto leading-relaxed">
Your next-generation marketing command center. CampaignX brings every channel,
audience and automation into one intelligent workspace so you can launch
smarter campaigns and turn more leads into jobs.
</p>
<div className="mt-6 inline-flex items-center gap-2 text-sm text-zinc-400 dark:text-zinc-500">
<Sparkles size={15} className="text-amber-500" />
We're building something special. Stay tuned.
</div>
</motion.div>
{/* --- Upcoming features timeline --- */}
<motion.div
initial={{ opacity: 0, y: 16 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.4, delay: 0.15 }}
className="mt-14 sm:mt-20"
>
<h2 className="text-xs font-bold uppercase tracking-widest text-zinc-400 dark:text-zinc-500 mb-8 text-center">
What's coming to CampaignX
</h2>
{/* Vertical line + feature items */}
<div className="relative pl-8 sm:pl-10">
{/* The vertical line */}
<div className="absolute left-[11px] sm:left-[15px] top-2 bottom-2 w-px bg-gradient-to-b from-amber-400 via-amber-500/40 to-transparent" />
<div className="space-y-8">
{UPCOMING.map((feature, i) => {
const Icon = feature.icon;
return (
<motion.div
key={feature.title}
initial={{ opacity: 0, x: 12 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.35, delay: 0.2 + i * 0.08 }}
className="relative"
>
{/* Node on the line */}
<div className="absolute -left-8 sm:-left-10 top-0.5 flex items-center justify-center w-6 h-6 rounded-full bg-white dark:bg-zinc-900 ring-2 ring-amber-500 shadow-sm">
<Icon size={13} className="text-amber-500" />
</div>
<h3 className="text-base sm:text-lg font-bold text-zinc-900 dark:text-white">
{feature.title}
</h3>
<p className="mt-1 text-sm text-zinc-500 dark:text-zinc-400 leading-relaxed max-w-xl">
{feature.desc}
</p>
</motion.div>
);
})}
</div>
</div>
</motion.div>
{/* --- Footer note --- */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.4, delay: 0.6 }}
className="mt-16 text-center"
>
<div className="inline-block px-5 py-3 rounded-2xl bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-white/5 shadow-sm">
<p className="text-sm text-zinc-500 dark:text-zinc-400">
CampaignX is currently in active development it'll appear here the moment it's ready.
</p>
</div>
</motion.div>
</div>
</div>
);
}