Initial commit: SmoothSchedule multi-tenant scheduling platform
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>
This commit is contained in:
258
frontend/src/pages/marketing/HomePage.tsx
Normal file
258
frontend/src/pages/marketing/HomePage.tsx
Normal file
@@ -0,0 +1,258 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user