cre-sync/components/TourSimulation.tsx
BusyBee3333 4e6467ffb0 Add CRESync CRM application with Setup page
- Build complete Next.js CRM for commercial real estate
- Add authentication with JWT sessions and role-based access
- Add GoHighLevel API integration for contacts, conversations, opportunities
- Add AI-powered Control Center with tool calling
- Add Setup page with onboarding checklist (/setup)
- Add sidebar navigation with Setup menu item
- Fix type errors in onboarding API, GHL services, and control center tools
- Add Prisma schema with SQLite for local development
- Add UI components with clay morphism design system

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 17:30:55 -05:00

72 lines
3.0 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import { Button } from './Button';
import { MousePointer2, Loader2, Check } from 'lucide-react';
interface Props {
type: string;
onComplete: () => void;
}
export const TourSimulation: React.FC<Props> = ({ type, onComplete }) => {
const [step, setStep] = useState(0);
const getSteps = () => {
if (type === 'UPLOAD') return ['Navigating to Contacts...', 'Clicking Import CSV...', 'Mapping Fields...', 'Import Confirmed!'];
if (type === 'SMS_DIY') return ['Opening Settings...', 'Buying Phone Number...', 'Verifying A2P Brand...', 'SMS Active!'];
if (type === 'EMAIL_DIY') return ['Opening Domain Settings...', 'Adding DNS Records...', 'Verifying DKIM/SPF...', 'Email Warmup Started!'];
if (type === 'CAMPAIGN_DIY') return ['Selecting Audience...', 'Choosing Template...', 'Setting Schedule...', 'Campaign Launched!'];
if (type === 'LEAD_STORE') return ['Accessing Lead Database...', 'Filtering by Criteria...', 'Selecting 50 Leads...', 'Leads Acquired!'];
return ['Processing...'];
};
const steps = getSteps();
useEffect(() => {
if (step < steps.length) {
const timer = setTimeout(() => {
setStep(prev => prev + 1);
}, 1500); // 1.5s per step
return () => clearTimeout(timer);
} else {
const timer = setTimeout(() => {
onComplete();
}, 1000);
return () => clearTimeout(timer);
}
}, [step, steps.length, onComplete]);
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-white/80 backdrop-blur-md animate-fadeIn">
<div className="text-center p-8">
<div className="relative w-24 h-24 mx-auto mb-6 bg-indigo-50 rounded-full flex items-center justify-center shadow-lg">
{step < steps.length ? (
<MousePointer2 className="text-indigo-600 animate-bounce" size={40} />
) : (
<Check className="text-green-600 scale-125 transition-transform" size={40} />
)}
</div>
<h2 className="text-3xl font-bold text-gray-800 mb-4">
{step < steps.length ? 'Guided Tour in Progress' : 'Setup Complete!'}
</h2>
<div className="space-y-3 min-h-[160px]">
{steps.map((text, index) => (
<div
key={index}
className={`transition-all duration-500 flex items-center justify-center gap-2
${index === step ? 'text-indigo-600 font-bold scale-110 opacity-100' : ''}
${index < step ? 'text-green-500 opacity-50' : ''}
${index > step ? 'text-gray-300 opacity-30 blur-[1px]' : ''}
`}
>
{index < step && <Check size={16} />}
{index === step && <Loader2 size={16} className="animate-spin" />}
{text}
</div>
))}
</div>
</div>
</div>
);
};