import {Button, Card, CardContent, CardDescription, CardHeader, CardTitle} from '@plunk/ui'; import {BookOpen, CheckCircle2, Mail, MessageCircle, Shield, Users, Zap} from 'lucide-react'; import Link from 'next/link'; import {useMemo} from 'react'; import {LANDING_URI, WIKI_URI} from '../lib/constants'; import type {ProjectSetupState} from '../lib/hooks/useProjectSetupState'; import {useConfig} from '../lib/hooks/useConfig'; interface QuickStartStep { id: string; icon: React.ElementType; title: string; description: string; link: string; linkText: string; isCompleted: boolean; } interface QuickStartProps { setupState: ProjectSetupState | undefined; isLoading: boolean; } // Help resources that always appear function HelpResources() { return (

Need help?

); } export function QuickStart({setupState, isLoading}: QuickStartProps) { // Calculate days since last campaign using useMemo to avoid impure function during render // Must be called before any early returns to follow Rules of Hooks const daysSinceLastCampaign = useMemo(() => { if (!setupState || !setupState.lastCampaignSentAt) return null; const now = new Date(); const lastSent = new Date(setupState.lastCampaignSentAt); return Math.floor((now.getTime() - lastSent.getTime()) / (1000 * 60 * 60 * 24)); }, [setupState]); const {data: config} = useConfig(); const billingEnabled = config?.features.billing.enabled ?? false; if (isLoading || !setupState) { return ( Quick Start Get started with Plunk in minutes
{[1, 2, 3].map(i => (
))}
); } const hasContacts = setupState.contactCount > 0; const hasSentCampaign = setupState.lastCampaignSentAt !== null; const hasRecentCampaign = daysSinceLastCampaign !== null && daysSinceLastCampaign <= 30; // Build dynamic steps based on setup state with proper prioritization // Priority order: Domain → Contacts → Campaign → Workflow → Subscription const allSteps: QuickStartStep[] = []; // Priority 1: Domain verification (critical for deliverability) if (!setupState.hasVerifiedDomain) { allSteps.push({ id: 'domain', icon: Shield, title: 'Verify Your Domain', description: 'Essential for email deliverability and avoiding spam', link: '/settings?tab=domains', linkText: 'Add Domain', isCompleted: false, }); } // Priority 2: Add contacts (can't send without contacts) if (!hasContacts) { allSteps.push({ id: 'contacts', icon: Users, title: 'Add Your First Contacts', description: 'Import your subscriber list to start sending emails', link: '/contacts', linkText: 'Add Contacts', isCompleted: false, }); } // Priority 3: Send campaign (core functionality, show if they have contacts but never sent) if (hasContacts && !hasSentCampaign) { allSteps.push({ id: 'campaign', icon: Mail, title: 'Send Your First Campaign', description: 'Create and send your first email campaign', link: '/campaigns', linkText: 'Create Campaign', isCompleted: false, }); } // Priority 4: Set up automation (advanced feature, only show if no workflow and have contacts) if (hasContacts && !setupState.hasEnabledWorkflow) { allSteps.push({ id: 'workflows', icon: Zap, title: 'Set Up Automation', description: 'Create automated workflows to engage your audience', link: '/workflows', linkText: 'Create Workflow', isCompleted: false, }); } // Priority 5: Subscription (nice to have, lower priority) if (billingEnabled && !setupState.hasSubscription) { allSteps.push({ id: 'subscription', icon: Shield, title: 'Upgrade Your Plan', description: 'Remove Plunk branding and unlock more features', link: '/settings?tab=billing', linkText: 'Upgrade', isCompleted: false, }); } // Priority 6: Re-engagement (show if they've been inactive) if (hasSentCampaign && !hasRecentCampaign && daysSinceLastCampaign !== null && daysSinceLastCampaign > 30) { allSteps.push({ id: 'campaign-reengagement', icon: Mail, title: 'Re-engage Your Audience', description: `It's been ${daysSinceLastCampaign} days since your last campaign`, link: '/campaigns', linkText: 'Create Campaign', isCompleted: false, }); } // If core setup is complete and they're actively sending, show success message if (setupState.hasVerifiedDomain && hasContacts && hasSentCampaign && hasRecentCampaign) { return ( Quick Start Your project is fully set up

All set!

Your project is fully configured and you're actively engaging your audience. Keep up the great work!

); } // Show only the first 3 most important steps const visibleSteps = allSteps.slice(0, 3); return ( Quick Start {visibleSteps.length === 0 ? 'Your project is set up' : 'Get started with Plunk in minutes'}
{visibleSteps.map(step => { const Icon = step.icon; return (

{step.title}

{step.isCompleted && }

{step.description}

); })}
); }