This commit includes: - Django backend with multi-tenancy (django-tenants) - React + TypeScript frontend with Vite - Platform administration API with role-based access control - Authentication system with token-based auth - Quick login dev tools for testing different user roles - CORS and CSRF configuration for local development - Docker development environment setup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
259 lines
9.6 KiB
TypeScript
259 lines
9.6 KiB
TypeScript
import React from 'react';
|
|
import { Link } from 'react-router-dom';
|
|
import { useTranslation } from 'react-i18next';
|
|
import {
|
|
Calendar,
|
|
Users,
|
|
CreditCard,
|
|
Building2,
|
|
Palette,
|
|
BarChart3,
|
|
Plug,
|
|
UserCircle,
|
|
ArrowRight,
|
|
} from 'lucide-react';
|
|
import Hero from '../../components/marketing/Hero';
|
|
import FeatureCard from '../../components/marketing/FeatureCard';
|
|
import HowItWorks from '../../components/marketing/HowItWorks';
|
|
import StatsSection from '../../components/marketing/StatsSection';
|
|
import TestimonialCard from '../../components/marketing/TestimonialCard';
|
|
import CTASection from '../../components/marketing/CTASection';
|
|
|
|
const HomePage: React.FC = () => {
|
|
const { t } = useTranslation();
|
|
|
|
const features = [
|
|
{
|
|
icon: Calendar,
|
|
titleKey: 'marketing.features.scheduling.title',
|
|
descriptionKey: 'marketing.features.scheduling.description',
|
|
color: 'brand',
|
|
},
|
|
{
|
|
icon: Users,
|
|
titleKey: 'marketing.features.resources.title',
|
|
descriptionKey: 'marketing.features.resources.description',
|
|
color: 'green',
|
|
},
|
|
{
|
|
icon: UserCircle,
|
|
titleKey: 'marketing.features.customers.title',
|
|
descriptionKey: 'marketing.features.customers.description',
|
|
color: 'purple',
|
|
},
|
|
{
|
|
icon: CreditCard,
|
|
titleKey: 'marketing.features.payments.title',
|
|
descriptionKey: 'marketing.features.payments.description',
|
|
color: 'orange',
|
|
},
|
|
{
|
|
icon: Building2,
|
|
titleKey: 'marketing.features.multiTenant.title',
|
|
descriptionKey: 'marketing.features.multiTenant.description',
|
|
color: 'pink',
|
|
},
|
|
{
|
|
icon: Palette,
|
|
titleKey: 'marketing.features.whiteLabel.title',
|
|
descriptionKey: 'marketing.features.whiteLabel.description',
|
|
color: 'cyan',
|
|
},
|
|
];
|
|
|
|
const testimonials = [
|
|
{
|
|
quote: "SmoothSchedule transformed how we manage appointments. Our no-show rate dropped by 40% with automated reminders.",
|
|
author: "Sarah Johnson",
|
|
role: "Owner",
|
|
company: "Luxe Salon",
|
|
rating: 5,
|
|
},
|
|
{
|
|
quote: "The white-label feature is perfect for our multi-location business. Each location has its own branded booking experience.",
|
|
author: "Michael Chen",
|
|
role: "CEO",
|
|
company: "FitLife Studios",
|
|
rating: 5,
|
|
},
|
|
{
|
|
quote: "Setup was incredibly easy. We were up and running in under an hour, and our clients love the self-service booking.",
|
|
author: "Emily Rodriguez",
|
|
role: "Manager",
|
|
company: "Peak Performance Therapy",
|
|
rating: 5,
|
|
},
|
|
];
|
|
|
|
return (
|
|
<div>
|
|
{/* Hero Section */}
|
|
<Hero />
|
|
|
|
{/* Features Section */}
|
|
<section className="py-20 lg:py-28 bg-white dark:bg-gray-900">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
{/* Header */}
|
|
<div className="text-center mb-16">
|
|
<h2 className="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
|
{t('marketing.features.title')}
|
|
</h2>
|
|
<p className="text-lg text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
|
|
{t('marketing.features.subtitle')}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Feature Grid */}
|
|
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6 lg:gap-8">
|
|
{features.map((feature) => (
|
|
<FeatureCard
|
|
key={feature.titleKey}
|
|
icon={feature.icon}
|
|
title={t(feature.titleKey)}
|
|
description={t(feature.descriptionKey)}
|
|
iconColor={feature.color}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
{/* View All Features Link */}
|
|
<div className="text-center mt-12">
|
|
<Link
|
|
to="/features"
|
|
className="inline-flex items-center gap-2 text-brand-600 dark:text-brand-400 font-medium hover:text-brand-700 dark:hover:text-brand-300 transition-colors"
|
|
>
|
|
{t('common.viewAll')} {t('marketing.nav.features').toLowerCase()}
|
|
<ArrowRight className="h-4 w-4" />
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* How It Works Section */}
|
|
<HowItWorks />
|
|
|
|
{/* Stats Section */}
|
|
<StatsSection />
|
|
|
|
{/* Testimonials Section */}
|
|
<section className="py-20 lg:py-28 bg-gray-50 dark:bg-gray-800/50">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
{/* Header */}
|
|
<div className="text-center mb-16">
|
|
<h2 className="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
|
{t('marketing.testimonials.title')}
|
|
</h2>
|
|
<p className="text-lg text-gray-600 dark:text-gray-400">
|
|
{t('marketing.testimonials.subtitle')}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Testimonials Grid */}
|
|
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6 lg:gap-8">
|
|
{testimonials.map((testimonial, index) => (
|
|
<TestimonialCard key={index} {...testimonial} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Pricing Preview Section */}
|
|
<section className="py-20 lg:py-28 bg-white dark:bg-gray-900">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
{/* Header */}
|
|
<div className="text-center mb-16">
|
|
<h2 className="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
|
{t('marketing.pricing.title')}
|
|
</h2>
|
|
<p className="text-lg text-gray-600 dark:text-gray-400">
|
|
{t('marketing.pricing.subtitle')}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Pricing Cards Preview */}
|
|
<div className="grid md:grid-cols-3 gap-6 lg:gap-8 max-w-5xl mx-auto">
|
|
{/* Free */}
|
|
<div className="p-6 bg-white dark:bg-gray-800 rounded-2xl border border-gray-200 dark:border-gray-700">
|
|
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
|
|
{t('marketing.pricing.tiers.free.name')}
|
|
</h3>
|
|
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">
|
|
{t('marketing.pricing.tiers.free.description')}
|
|
</p>
|
|
<div className="mb-6">
|
|
<span className="text-4xl font-bold text-gray-900 dark:text-white">$0</span>
|
|
<span className="text-gray-500 dark:text-gray-400">{t('marketing.pricing.perMonth')}</span>
|
|
</div>
|
|
<Link
|
|
to="/signup"
|
|
className="block w-full py-3 px-4 text-center text-sm font-medium text-brand-600 bg-brand-50 dark:bg-brand-900/30 rounded-lg hover:bg-brand-100 dark:hover:bg-brand-900/50 transition-colors"
|
|
>
|
|
{t('marketing.pricing.getStarted')}
|
|
</Link>
|
|
</div>
|
|
|
|
{/* Professional - Highlighted */}
|
|
<div className="relative p-6 bg-brand-600 rounded-2xl shadow-xl shadow-brand-600/20">
|
|
<div className="absolute -top-3 left-1/2 -translate-x-1/2 px-3 py-1 bg-brand-500 text-white text-xs font-semibold rounded-full">
|
|
{t('marketing.pricing.mostPopular')}
|
|
</div>
|
|
<h3 className="text-lg font-semibold text-white mb-2">
|
|
{t('marketing.pricing.tiers.professional.name')}
|
|
</h3>
|
|
<p className="text-sm text-brand-100 mb-4">
|
|
{t('marketing.pricing.tiers.professional.description')}
|
|
</p>
|
|
<div className="mb-6">
|
|
<span className="text-4xl font-bold text-white">$29</span>
|
|
<span className="text-brand-200">{t('marketing.pricing.perMonth')}</span>
|
|
</div>
|
|
<Link
|
|
to="/signup"
|
|
className="block w-full py-3 px-4 text-center text-sm font-medium text-brand-600 bg-white rounded-lg hover:bg-brand-50 transition-colors"
|
|
>
|
|
{t('marketing.pricing.getStarted')}
|
|
</Link>
|
|
</div>
|
|
|
|
{/* Business */}
|
|
<div className="p-6 bg-white dark:bg-gray-800 rounded-2xl border border-gray-200 dark:border-gray-700">
|
|
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
|
|
{t('marketing.pricing.tiers.business.name')}
|
|
</h3>
|
|
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">
|
|
{t('marketing.pricing.tiers.business.description')}
|
|
</p>
|
|
<div className="mb-6">
|
|
<span className="text-4xl font-bold text-gray-900 dark:text-white">$79</span>
|
|
<span className="text-gray-500 dark:text-gray-400">{t('marketing.pricing.perMonth')}</span>
|
|
</div>
|
|
<Link
|
|
to="/signup"
|
|
className="block w-full py-3 px-4 text-center text-sm font-medium text-brand-600 bg-brand-50 dark:bg-brand-900/30 rounded-lg hover:bg-brand-100 dark:hover:bg-brand-900/50 transition-colors"
|
|
>
|
|
{t('marketing.pricing.getStarted')}
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
|
|
{/* View Full Pricing Link */}
|
|
<div className="text-center mt-10">
|
|
<Link
|
|
to="/pricing"
|
|
className="inline-flex items-center gap-2 text-brand-600 dark:text-brand-400 font-medium hover:text-brand-700 dark:hover:text-brand-300 transition-colors"
|
|
>
|
|
View full pricing details
|
|
<ArrowRight className="h-4 w-4" />
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Final CTA */}
|
|
<CTASection />
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default HomePage;
|