Files
Wdipl-react/components/DedicatedTeamPricing.tsx

281 lines
11 KiB
TypeScript

import { motion } from "framer-motion";
import { Check, Users, Clock, Sparkles } from "lucide-react";
import { GridPattern } from "./GridPattern";
import { Badge } from "./ui/badge";
interface PricingTier {
name: string;
price: string;
pricePerMonth: string;
description: string;
isPopular?: boolean;
teamSize: string;
projectManager: string;
uiuxDesigners: string;
frontendDevs: string;
backendDevs: string;
qaTesters: string;
leadTime: string;
minEngagement: string;
}
const pricingTiers: PricingTier[] = [
{
name: "Small",
price: "$7,500",
pricePerMonth: "/mo",
description: "Maintenance & updates",
teamSize: "3-5 Members",
projectManager: "Part-time (≤ 32 hrs/month)",
uiuxDesigners: "Part-time",
frontendDevs: "Shared",
backendDevs: "Shared",
qaTesters: "Part-time",
leadTime: "< 3 Days",
minEngagement: "1 Month"
},
{
name: "Medium",
price: "$12,000",
pricePerMonth: "/mo",
description: "Ongoing MVP development",
isPopular: true,
teamSize: "4-8 Members",
projectManager: "Shared (≤ 80 hrs/month)",
uiuxDesigners: "Shared",
frontendDevs: "Shared",
backendDevs: "Shared",
qaTesters: "Shared",
leadTime: "< 2 Weeks",
minEngagement: "2 Months"
},
{
name: "Large",
price: "$22,680",
pricePerMonth: "/mo",
description: "Long-term growth & GTM",
teamSize: "6-10 Members",
projectManager: "Dedicated full-time",
uiuxDesigners: "Full-time",
frontendDevs: "Full-time",
backendDevs: "Full-time",
qaTesters: "Full-time",
leadTime: "< 4 Weeks",
minEngagement: "3 Months"
}
];
const includedFeatures = [
{
left: "Access to WDI Code Library",
right: "Direct Communication"
},
{
left: "Time Zone Overlap: 3 Hours",
right: "Resource Replacement (within 1 week)"
},
{
left: "No Obligation Trial (conditional)",
right: "IPR & Code Ownership"
},
{
left: "Termination Notice: 1 Month",
right: "Performance Guarantee"
}
];
const comparisonRows = [
{ label: "Team Size", key: "teamSize" as keyof PricingTier },
{ label: "Project Manager", key: "projectManager" as keyof PricingTier },
{ label: "UI/UX Designers", key: "uiuxDesigners" as keyof PricingTier },
{ label: "Frontend Developers", key: "frontendDevs" as keyof PricingTier },
{ label: "Backend Developers", key: "backendDevs" as keyof PricingTier },
{ label: "QA Testers", key: "qaTesters" as keyof PricingTier },
{ label: "Lead Time to Start", key: "leadTime" as keyof PricingTier },
{ label: "Minimum Engagement Period", key: "minEngagement" as keyof PricingTier }
];
export const DedicatedTeamPricing = () => {
return (
<section className="relative py-20 bg-background overflow-hidden">
<GridPattern strokeDasharray="4 2" />
<div className="relative z-10 container mx-auto px-6 lg:px-8">
{/* Header */}
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }}
viewport={{ once: true }}
className="text-center mb-16"
>
<div className="inline-flex items-center gap-2 mb-4">
<Users className="w-6 h-6 text-accent" />
<h2 className="text-4xl lg:text-5xl font-semibold text-foreground font-manrope">
Dedicated Team Pricing
</h2>
</div>
<p className="text-muted-foreground text-lg max-w-2xl mx-auto font-manrope">
Scale your development with flexible team structures tailored to your project needs
</p>
</motion.div>
{/* Pricing Cards Row */}
<motion.div
initial={{ opacity: 0, y: 40 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.2 }}
viewport={{ once: true }}
className="grid md:grid-cols-3 gap-6 mb-12 max-w-6xl mx-auto"
>
{pricingTiers.map((tier, index) => (
<motion.div
key={tier.name}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: index * 0.1 }}
viewport={{ once: true }}
className={`relative bg-card/50 backdrop-blur-sm border rounded-[20px] p-6 transition-all duration-300 ${
tier.isPopular
? 'border-blue-500/50 shadow-xl shadow-blue-500/10 scale-105'
: 'border-border/50 hover:border-accent/30'
}`}
>
{tier.isPopular && (
<div className="absolute -top-4 left-1/2 -translate-x-1/2">
<Badge className="bg-blue-600 text-white px-4 py-1 rounded-full font-manrope">
Most Popular
</Badge>
</div>
)}
<div className="text-center mb-6">
<h3 className="text-2xl font-semibold text-foreground mb-2 font-manrope">
{tier.name}
</h3>
<div className="flex items-baseline justify-center mb-2">
<span className="text-4xl font-semibold text-foreground font-manrope">
{tier.price}
</span>
<span className="text-xl text-muted-foreground font-manrope">
{tier.pricePerMonth}
</span>
</div>
<p className="text-sm text-muted-foreground font-manrope">
{tier.description}
</p>
</div>
</motion.div>
))}
</motion.div>
{/* Comparison Table */}
<motion.div
initial={{ opacity: 0, y: 40 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.4 }}
viewport={{ once: true }}
className="max-w-6xl mx-auto mb-16"
>
<div className="bg-card/30 backdrop-blur-md border border-border/50 rounded-[20px] overflow-hidden">
<div className="overflow-x-auto">
<table className="w-full border-collapse font-manrope">
{/* Table Header - Hidden on mobile, shown on desktop */}
<thead className="hidden md:table-header-group">
<tr className="border-b border-border/50 bg-card/50">
<th className="p-6 text-left font-semibold text-foreground font-manrope"></th>
{pricingTiers.map((tier) => (
<th key={tier.name} className="p-6 text-center font-semibold text-foreground font-manrope">
{tier.name}
</th>
))}
</tr>
</thead>
{/* Table Body */}
<tbody>
{comparisonRows.map((row, rowIndex) => (
<motion.tr
key={row.label}
initial={{ opacity: 0, x: -20 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.5, delay: rowIndex * 0.05 }}
viewport={{ once: true }}
className="border-b border-border/30 last:border-b-0 hover:bg-card/50 transition-colors duration-200"
>
<td className="p-6 font-medium text-muted-foreground font-manrope align-top">
<div className="md:hidden mb-3">{row.label}</div>
<div className="hidden md:block">{row.label}</div>
{/* Mobile: Stack values vertically with tier name */}
<div className="grid grid-cols-1 md:hidden gap-3 mt-3">
{pricingTiers.map((tier) => (
<div key={tier.name} className="flex justify-between items-center bg-card/30 rounded-lg p-3">
<span className="text-sm text-muted-foreground font-manrope">{tier.name}:</span>
<span className="text-foreground font-manrope text-right">{tier[row.key]}</span>
</div>
))}
</div>
</td>
{/* Desktop: Show values in columns */}
{pricingTiers.map((tier) => (
<td key={tier.name} className="hidden md:table-cell p-6 text-center text-foreground font-manrope align-top">
{tier[row.key]}
</td>
))}
</motion.tr>
))}
</tbody>
</table>
</div>
</div>
</motion.div>
{/* Included in All Plans */}
<motion.div
initial={{ opacity: 0, y: 40 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.6 }}
viewport={{ once: true }}
className="max-w-4xl mx-auto"
>
<div className="bg-gradient-to-br from-accent/5 to-blue-500/5 backdrop-blur-sm border border-accent/20 rounded-[20px] p-8">
<div className="flex items-center gap-3 mb-6">
<div className="w-12 h-12 bg-accent/20 rounded-full flex items-center justify-center">
<Sparkles className="w-6 h-6 text-accent" />
</div>
<h3 className="text-2xl font-semibold text-foreground font-manrope">
Included in All Plans
</h3>
</div>
<div className="grid md:grid-cols-2 gap-6">
{includedFeatures.map((feature, index) => (
<div key={index} className="space-y-3">
<div className="flex items-start gap-3">
<div className="flex-shrink-0 w-5 h-5 bg-accent/20 rounded-full flex items-center justify-center mt-0.5">
<Check className="w-3 h-3 text-accent" />
</div>
<span className="text-foreground font-manrope leading-relaxed">
{feature.left}
</span>
</div>
<div className="flex items-start gap-3">
<div className="flex-shrink-0 w-5 h-5 bg-accent/20 rounded-full flex items-center justify-center mt-0.5">
<Check className="w-3 h-3 text-accent" />
</div>
<span className="text-foreground font-manrope leading-relaxed">
{feature.right}
</span>
</div>
</div>
))}
</div>
</div>
</motion.div>
</div>
</section>
);
};