912 lines
38 KiB
TypeScript
912 lines
38 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { Button } from '../ui/button';
|
|
import { Badge } from '../ui/badge';
|
|
import { Card, CardContent } from '../ui/card';
|
|
import { ImageWithFallback } from '../figma/ImageWithFallback';
|
|
import { navigateTo } from '../Router';
|
|
import { BrandedTag } from '../about/BrandedTag';
|
|
import { PrimaryCTAButton } from '../PrimaryCTAButton';
|
|
import { StandardCTAButton } from '../StandardCTAButton';
|
|
import {
|
|
ArrowRight,
|
|
CheckCircle,
|
|
Settings,
|
|
Calendar,
|
|
Download,
|
|
Network,
|
|
Users,
|
|
Target,
|
|
Brain,
|
|
Eye,
|
|
TrendingUp,
|
|
BarChart3,
|
|
Award,
|
|
Lightbulb,
|
|
Shield,
|
|
ChevronDown,
|
|
ChevronUp,
|
|
ArrowLeft,
|
|
Star,
|
|
Zap,
|
|
Globe,
|
|
Crown,
|
|
Compass,
|
|
Users2,
|
|
Clock,
|
|
MessageCircle,
|
|
Building,
|
|
UserCheck,
|
|
Heart
|
|
} from 'lucide-react';
|
|
import { TestimonialsSection } from '../TestimonialsSection';
|
|
import { useGetServiceListQuery } from '../../redux/services/sercicesApi';
|
|
import { FullScreenLoader } from '../FullScreenLoader';
|
|
|
|
// Types based on API response
|
|
interface ServicePageData {
|
|
hero_section: {
|
|
id: string;
|
|
landing_page_type: string;
|
|
background_image_url: string;
|
|
background_image_alt_text: string;
|
|
headline: string;
|
|
subtext: string;
|
|
cta_text: string;
|
|
cta_destination: string;
|
|
};
|
|
overview: {
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
highlight_text: string;
|
|
overview_cards: Array<{
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
icon_url: string;
|
|
accessible_label: string;
|
|
}>;
|
|
};
|
|
audience_section: {
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
audience_cards: Array<{
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
icon_url: string;
|
|
accessible_label: string;
|
|
challenges: string[];
|
|
}>;
|
|
};
|
|
use_case_section: {
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
use_case_cards: Array<{
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
icon_url: string;
|
|
accessible_label: string;
|
|
highlight_text: string;
|
|
}>;
|
|
};
|
|
approach_section: {
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
approach_cards: Array<{
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
icon_url: string;
|
|
accessible_label: string;
|
|
bullets: string[];
|
|
}>;
|
|
outcomes: Array<{
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
icon_url: string;
|
|
accessible_label: string;
|
|
bullets: string[];
|
|
}>;
|
|
};
|
|
stats_section: {
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
stat_cards: Array<{
|
|
id: string;
|
|
value: string;
|
|
label: string;
|
|
icon_url: string;
|
|
accessible_label: string;
|
|
}>;
|
|
};
|
|
program_section: {
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
program_phases: Array<{
|
|
phase: {
|
|
id: string;
|
|
phase_number: number;
|
|
title: string;
|
|
duration: string;
|
|
};
|
|
activities: Array<{
|
|
id: string;
|
|
phase_id: string;
|
|
text: string;
|
|
}>;
|
|
outcomes: Array<{
|
|
id: string;
|
|
phase_id: string;
|
|
text: string;
|
|
}>;
|
|
}>;
|
|
};
|
|
impact_section: {
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
impact_stats: Array<{
|
|
id: string;
|
|
value: string;
|
|
description: string;
|
|
label: string;
|
|
icon_url: string;
|
|
accessible_label: string;
|
|
}>;
|
|
impact_benefits: Array<{
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
icon_url: string;
|
|
accessible_label: string;
|
|
}>;
|
|
};
|
|
testimonial_section: Array<{
|
|
id: string;
|
|
profile_xid: string;
|
|
name: string;
|
|
designation: string;
|
|
content: string;
|
|
video_url: string | null;
|
|
display_order: number;
|
|
}>;
|
|
cta_section: {
|
|
id: string;
|
|
background_image_url: string;
|
|
text: string;
|
|
cta_text: string;
|
|
cta_destination: string;
|
|
description: string;
|
|
landing_page_type: string;
|
|
service_type: string;
|
|
};
|
|
}
|
|
|
|
// Map API icons to Lucide icons
|
|
const getIconComponent = (iconUrl: string) => {
|
|
const iconMap: Record<string, any> = {
|
|
'/icons/pipeline.svg': TrendingUp,
|
|
'/icons/succession.svg': Users,
|
|
'/icons/capability.svg': Brain,
|
|
'/icons/hr.svg': Users2,
|
|
'/icons/management.svg': Crown,
|
|
'/icons/growth.svg': TrendingUp,
|
|
'/icons/gap.svg': Target,
|
|
'/icons/assessment.svg': BarChart3,
|
|
'/icons/development.svg': Brain,
|
|
'/icons/outcome.svg': Award,
|
|
'/icons/target.svg': Target,
|
|
'/icons/engagement.svg': Heart,
|
|
'/icons/leader.svg': Crown,
|
|
'/icons/productivity.svg': TrendingUp,
|
|
'/icons/performance.svg': TrendingUp,
|
|
};
|
|
|
|
const IconComponent = iconMap[iconUrl] || Target;
|
|
return IconComponent;
|
|
};
|
|
|
|
export function LeadershipDevelopment() {
|
|
const [expandedPhase, setExpandedPhase] = useState<number | null>(0);
|
|
|
|
const { data: apiResponse, isLoading, error } = useGetServiceListQuery({
|
|
service_type: 'leadership_development'
|
|
});
|
|
|
|
const apiData = apiResponse?.data as ServicePageData | undefined;
|
|
|
|
useEffect(() => {
|
|
window.scrollTo(0, 0);
|
|
}, []);
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center bg-white">
|
|
<FullScreenLoader text="Loading Leadership Development..." />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (error || !apiData) {
|
|
return (
|
|
<div className="flex items-center justify-center min-h-screen">
|
|
<div className="text-center">
|
|
<p className="text-red-600">Error loading content. Please try again later.</p>
|
|
<Button onClick={() => window.location.reload()} className="mt-4">Retry</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Transform data for UI
|
|
const targetAudience = apiData.audience_section?.audience_cards.map(card => ({
|
|
title: card.title,
|
|
description: card.description,
|
|
icon: getIconComponent(card.icon_url),
|
|
challenges: card.challenges || []
|
|
})) || [];
|
|
|
|
const useCases = apiData.use_case_section?.use_case_cards.map(card => ({
|
|
title: card.title,
|
|
description: card.description,
|
|
icon: getIconComponent(card.icon_url),
|
|
scenario: card.highlight_text
|
|
})) || [];
|
|
|
|
const programTimeline = apiData.program_section?.program_phases.map(phase => ({
|
|
phase: phase.phase.title,
|
|
duration: phase.phase.duration,
|
|
activities: phase.activities.map(activity => activity.text),
|
|
deliverables: phase.outcomes.map(outcome => outcome.text)
|
|
})) || [];
|
|
|
|
const expectedOutcomes = apiData.impact_section?.impact_benefits.map(benefit => ({
|
|
metric: apiData.impact_section?.impact_stats[0]?.value || '85%',
|
|
description: benefit.description,
|
|
icon: getIconComponent(benefit.icon_url),
|
|
category: benefit.title
|
|
})) || [];
|
|
|
|
const testimonials = apiData.testimonial_section?.map(testimonial => {
|
|
const designationParts = testimonial.designation.split(',');
|
|
const role = designationParts[0]?.trim() || '';
|
|
const company = designationParts[1]?.trim() || '';
|
|
|
|
return {
|
|
id: parseInt(testimonial.id) || 0,
|
|
name: testimonial.name,
|
|
role: role,
|
|
company: company,
|
|
avatar: `https://ui-avatars.com/api/?name=${encodeURIComponent(testimonial.name)}&background=04045B&color=fff&size=128`,
|
|
quote: testimonial.content,
|
|
rating: 5,
|
|
isVideo: !!testimonial.video_url,
|
|
videoThumbnail: testimonial.video_url ? `/images/testimonials/thumbnails/${testimonial.id}.jpg` : undefined,
|
|
videoUrl: testimonial.video_url || undefined
|
|
};
|
|
}) || [];
|
|
|
|
return (
|
|
<div style={{ backgroundColor: '#FFFFFF', fontFamily: 'var(--font-family-base)' }}>
|
|
{/* Hero Section */}
|
|
<section className="relative min-h-[85vh] flex flex-col">
|
|
<div className="absolute inset-0 z-0">
|
|
<div
|
|
className="w-full h-full bg-cover bg-center bg-no-repeat"
|
|
style={{
|
|
backgroundImage: `url('${apiData.hero_section.background_image_url}')`
|
|
}}
|
|
/>
|
|
<div className="absolute inset-0 bg-gradient-to-r from-black/85 via-black/75 to-black/65"></div>
|
|
</div>
|
|
|
|
<div className="relative z-10 flex-1 flex items-center">
|
|
<div className="w-full section-margin-x">
|
|
<div className="max-w-4xl">
|
|
<div className="mb-8">
|
|
<Button
|
|
variant="ghost"
|
|
onClick={() => navigateTo('/services')}
|
|
className="text-white hover:text-white hover:bg-white/10 p-2 -ml-2"
|
|
>
|
|
<ArrowLeft className="w-4 h-4 mr-2" />
|
|
Back to Services
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="mb-8">
|
|
<h1 className="text-h1-white">
|
|
{apiData.hero_section.headline}
|
|
</h1>
|
|
</div>
|
|
|
|
<p className="text-body-lg-white mb-8 max-w-3xl">
|
|
<strong>{apiData.hero_section.subtext}</strong>
|
|
</p>
|
|
|
|
<div className="flex justify-start">
|
|
<PrimaryCTAButton
|
|
text={apiData.hero_section.cta_text}
|
|
onClick={() => navigateTo(apiData.hero_section.cta_destination)}
|
|
ariaLabel={apiData.hero_section.cta_text}
|
|
className="primary-cta-button-blue cta-text-white"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* 1. What Is This Service */}
|
|
<section className="py-24 lg:py-32" style={{ backgroundColor: '#FFFFFF' }}>
|
|
<div className="section-margin-x">
|
|
<div className="max-w-6xl mx-auto">
|
|
<div className="text-center mb-12">
|
|
<BrandedTag text="What Is This Service?" />
|
|
<h2 className="text-h2 mb-8 text-[#26231A]">{apiData.overview.title}</h2>
|
|
<div className="max-w-4xl mx-auto space-y-6">
|
|
<p className="text-body-lg text-[#6F6F6F] leading-relaxed">
|
|
{apiData.overview.description}
|
|
</p>
|
|
<div className="bg-[#04045B]/5 border-l-4 border-[#04045B] p-6 rounded-lg">
|
|
<p className="text-body-lg text-[#26231A] leading-relaxed">
|
|
<span className="font-semibold text-[#04045B]">The Business Problem It Solves:</span> {apiData.overview.highlight_text}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
|
{apiData.overview.overview_cards.map((card, index) => {
|
|
const IconComponent = getIconComponent(card.icon_url);
|
|
return (
|
|
<div key={card.id} className="group bg-white border border-gray-200 rounded-xl p-8 hover:border-[#04045B]/20 hover:shadow-lg transition-all duration-300">
|
|
<div className="flex flex-col items-center text-center">
|
|
<div
|
|
className="w-16 h-16 rounded-xl flex items-center justify-center mb-6 group-hover:scale-105 transition-transform duration-300"
|
|
style={{ backgroundColor: '#04045B' }}
|
|
>
|
|
<IconComponent className="w-8 h-8 text-white" />
|
|
</div>
|
|
<h4 className="text-h4 mb-4 text-[#26231A] group-hover:text-[#04045B] transition-colors duration-300">
|
|
{card.title}
|
|
</h4>
|
|
<p className="text-body text-[#6F6F6F] leading-relaxed">
|
|
{card.description}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* 2. Who Is It For */}
|
|
<section className="py-24 lg:py-32" style={{ backgroundColor: '#F9F9F9' }}>
|
|
<div className="section-margin-x">
|
|
<div className="max-w-6xl mx-auto">
|
|
<div className="text-center mb-16">
|
|
<BrandedTag text="Who Is It For?" />
|
|
<h2 className="text-h2 mb-8">{apiData.audience_section.title}</h2>
|
|
<p className="text-body-lg text-muted max-w-3xl mx-auto">
|
|
{apiData.audience_section.description}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
|
{targetAudience.map((audience, index) => (
|
|
<Card key={index} className="h-full hover:shadow-lg transition-all duration-300">
|
|
<CardContent className="p-8">
|
|
<div className="flex items-center gap-4 mb-6">
|
|
<div
|
|
className="w-16 h-16 rounded-2xl flex items-center justify-center"
|
|
style={{ backgroundColor: 'var(--color-primary)' }}
|
|
>
|
|
<audience.icon className="w-8 h-8 text-white" />
|
|
</div>
|
|
</div>
|
|
<h3 className="text-h4 mb-4">{audience.title}</h3>
|
|
<p className="text-body text-muted mb-6">{audience.description}</p>
|
|
<div>
|
|
<h4 className="text-small font-semibold text-primary mb-3">Common Challenges:</h4>
|
|
<ul className="space-y-2">
|
|
{audience.challenges.map((challenge, challengeIndex) => (
|
|
<li key={challengeIndex} className="text-small text-muted flex items-start gap-2">
|
|
<div className="w-1 h-1 bg-primary rounded-full mt-2 flex-shrink-0"></div>
|
|
{challenge}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* 3. When to Use It */}
|
|
<section className="py-24 lg:py-32" style={{ backgroundColor: '#FFFFFF' }}>
|
|
<div className="section-margin-x">
|
|
<div className="max-w-6xl mx-auto">
|
|
<div className="text-center mb-16">
|
|
<BrandedTag text="When to Use It?" />
|
|
<h2 className="text-h2 mb-8">{apiData.use_case_section.title}</h2>
|
|
<p className="text-body-lg text-muted max-w-2xl mx-auto">
|
|
{apiData.use_case_section.description}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
{useCases.map((useCase, index) => (
|
|
<div
|
|
key={index}
|
|
className="bg-white rounded-xl border border-gray-200 p-6 hover:border-[#04045B] hover:shadow-lg transition-all duration-300"
|
|
>
|
|
<div className="flex items-start gap-4 mb-4">
|
|
<div
|
|
className="w-12 h-12 rounded-lg flex items-center justify-center flex-shrink-0"
|
|
style={{ backgroundColor: '#04045B' }}
|
|
>
|
|
<useCase.icon className="w-6 h-6 text-white" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<h3 className="text-h4 mb-2 text-[#26231A]">
|
|
{useCase.title}
|
|
</h3>
|
|
<p className="text-body text-muted">
|
|
{useCase.description}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-2 text-small text-[#04045B] bg-[#04045B]/5 px-3 py-2 rounded-lg">
|
|
<div className="w-2 h-2 rounded-full bg-[#F8C301]" />
|
|
<span className="font-medium">
|
|
{useCase.scenario}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* 4. Our Approach */}
|
|
<section className="py-24 lg:py-32" style={{ backgroundColor: '#F9F9F9' }}>
|
|
<div className="section-margin-x">
|
|
<div className="w-full">
|
|
<div className="max-w-6xl mx-auto">
|
|
<div className="text-center mb-16">
|
|
<BrandedTag text="Our Approach" />
|
|
<h2 className="text-h2 mb-8 text-[#26231A]">{apiData.approach_section.title}</h2>
|
|
<p className="text-body-lg text-[#6F6F6F] max-w-3xl mx-auto">
|
|
{apiData.approach_section.description}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Flowchart Container with Connecting Lines */}
|
|
<div className="relative mb-16 flex flex-col items-center">
|
|
{/* Desktop: Horizontal Flowchart */}
|
|
<div className="hidden lg:block w-full max-w-5xl">
|
|
<div className="relative">
|
|
{/* Row 1: First 3 approach cards from API */}
|
|
<div className="grid grid-cols-3 gap-8 mb-12 relative w-full">
|
|
{apiData.approach_section.approach_cards.slice(0, 3).map((card, idx) => {
|
|
const IconComponent = getIconComponent(card.icon_url);
|
|
return (
|
|
<div key={card.id} className={`bg-white border-2 ${idx === 1 ? 'border-[#F8C301]' : 'border-[#04045B]'} rounded-xl p-6 hover:shadow-lg transition-all duration-300 relative z-10`}>
|
|
<div className={`w-12 h-12 ${idx === 1 ? 'bg-[#F8C301]' : 'bg-[#04045B]'} rounded-lg flex items-center justify-center mb-4`}>
|
|
<IconComponent className="w-6 h-6 text-white" />
|
|
</div>
|
|
<h3 className="text-h4 text-[#26231A] mb-3">{card.title}</h3>
|
|
<p className="text-body text-[#6F6F6F] mb-4">{card.description}</p>
|
|
<div className="space-y-2">
|
|
{card.bullets.slice(0, 3).map((bullet, bulletIdx) => (
|
|
<div key={bulletIdx} className="text-small text-[#6F6F6F] bg-gray-50 px-3 py-2 rounded-lg">
|
|
{bullet}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
|
|
{/* Arrows between first 3 cards */}
|
|
{apiData.approach_section.approach_cards.length >= 2 && (
|
|
<div className="absolute top-1/2 left-[calc(33.33%-2rem)] -translate-y-1/2 z-0 flex items-center">
|
|
<div className="w-16 h-0.5 bg-[#F8C301]"></div>
|
|
<ArrowRight className="w-6 h-6 text-[#F8C301] -ml-1" />
|
|
</div>
|
|
)}
|
|
{apiData.approach_section.approach_cards.length >= 3 && (
|
|
<div className="absolute top-1/2 left-[calc(66.66%-2rem)] -translate-y-1/2 z-0 flex items-center">
|
|
<div className="w-16 h-0.5 bg-[#04045B]"></div>
|
|
<ArrowRight className="w-6 h-6 text-[#04045B] -ml-1" />
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Vertical Connector - Center Flow Down */}
|
|
<div className="flex justify-center mb-6">
|
|
<div className="flex flex-col items-center">
|
|
<div className="w-0.5 h-12 bg-[#F8C301]"></div>
|
|
<ArrowRight className="w-6 h-6 text-[#F8C301] rotate-90" />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Row 2: Next 2 approach cards (if available) */}
|
|
{apiData.approach_section.approach_cards.length >= 4 && (
|
|
<div className="grid grid-cols-2 gap-8 w-full max-w-3xl mx-auto mb-12 relative">
|
|
{apiData.approach_section.approach_cards.slice(3, 5).map((card, idx) => {
|
|
const IconComponent = getIconComponent(card.icon_url);
|
|
const isFirstOfPair = idx === 0;
|
|
return (
|
|
<div key={card.id} className={`bg-white border-2 ${isFirstOfPair ? 'border-[#F8C301]' : 'border-[#04045B]'} rounded-xl p-6 hover:shadow-lg transition-all duration-300 relative z-10`}>
|
|
<div className={`w-12 h-12 ${isFirstOfPair ? 'bg-[#F8C301]' : 'bg-[#04045B]'} rounded-lg flex items-center justify-center mb-4`}>
|
|
<IconComponent className="w-6 h-6 text-white" />
|
|
</div>
|
|
<h3 className="text-h4 text-[#26231A] mb-3">{card.title}</h3>
|
|
<p className="text-body text-[#6F6F6F] mb-4">{card.description}</p>
|
|
<div className="space-y-2">
|
|
{card.bullets.slice(0, 3).map((bullet, bulletIdx) => (
|
|
<div key={bulletIdx} className="text-small text-[#6F6F6F] bg-gray-50 px-3 py-2 rounded-lg">
|
|
{bullet}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
|
|
{/* Arrow between the two cards */}
|
|
{apiData.approach_section.approach_cards.length >= 5 && (
|
|
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-0 flex items-center">
|
|
<div className="w-16 h-0.5 bg-[#04045B]"></div>
|
|
<ArrowRight className="w-6 h-6 text-[#04045B] -ml-1" />
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
{/* Final Vertical Connector - Center Flow Down to Outcome */}
|
|
<div className="flex justify-center mb-6">
|
|
<div className="flex flex-col items-center">
|
|
<div className="w-0.5 h-12 bg-[#04045B]"></div>
|
|
<ArrowRight className="w-6 h-6 text-[#04045B] rotate-90" />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Row 3: Expected Outcome - Use API outcomes data */}
|
|
<div className="flex justify-center w-full">
|
|
<div className="bg-[#04045B] text-white rounded-xl p-8 w-full max-w-2xl border-4 border-[#F8C301] shadow-xl">
|
|
<div className="flex items-center gap-3 mb-4">
|
|
{apiData.approach_section.outcomes && apiData.approach_section.outcomes[0] && (() => {
|
|
const OutcomeIcon = getIconComponent(apiData.approach_section.outcomes[0].icon_url);
|
|
return <OutcomeIcon className="w-10 h-10 text-[#F8C301]" />;
|
|
})() || <TrendingUp className="w-10 h-10 text-[#F8C301]" />}
|
|
<h3 className="text-h4 text-white">
|
|
{apiData.approach_section.outcomes?.[0]?.title || "Expected Outcome"}
|
|
</h3>
|
|
</div>
|
|
<p className="text-body text-white mb-4">
|
|
{apiData.approach_section.outcomes?.[0]?.description || "Transformational executive leaders with strategic capability, executive presence, and proven business impact."}
|
|
</p>
|
|
<div className="space-y-2">
|
|
{apiData.approach_section.outcomes?.[0]?.bullets?.slice(0, 2).map((bullet, idx) => (
|
|
<div key={idx} className="flex items-center gap-2 text-[#F8C301]">
|
|
<CheckCircle className="w-6 h-6" />
|
|
<span className="text-body text-white">{bullet}</span>
|
|
</div>
|
|
)) || (
|
|
<>
|
|
<div className="flex items-center gap-2 text-[#F8C301]">
|
|
<CheckCircle className="w-6 h-6" />
|
|
<span className="text-body text-white">Enhanced Leadership Effectiveness</span>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Tablet & Mobile: Vertical Flowchart */}
|
|
<div className="lg:hidden space-y-8">
|
|
{/* Map all approach cards vertically */}
|
|
{apiData.approach_section.approach_cards.map((card, idx) => {
|
|
const IconComponent = getIconComponent(card.icon_url);
|
|
const isEven = idx % 2 === 0;
|
|
return (
|
|
<div key={card.id} className="relative">
|
|
<div className={`bg-white border-2 ${isEven ? 'border-[#04045B]' : 'border-[#F8C301]'} rounded-xl p-6 hover:shadow-lg transition-all duration-300`}>
|
|
<div className={`w-12 h-12 ${isEven ? 'bg-[#04045B]' : 'bg-[#F8C301]'} rounded-lg flex items-center justify-center mb-4`}>
|
|
<IconComponent className="w-6 h-6 text-white" />
|
|
</div>
|
|
<h3 className="text-h4 text-[#26231A] mb-3">{card.title}</h3>
|
|
<p className="text-body text-[#6F6F6F] mb-4">{card.description}</p>
|
|
<div className="space-y-2">
|
|
{card.bullets.map((bullet, bulletIdx) => (
|
|
<div key={bulletIdx} className="text-small text-[#6F6F6F] bg-gray-50 px-3 py-2 rounded-lg">
|
|
{bullet}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
{/* Connector Arrow */}
|
|
{idx < apiData.approach_section.approach_cards.length - 1 && (
|
|
<div className="flex justify-center my-4">
|
|
<ArrowRight className={`w-8 h-8 ${isEven ? 'text-[#F8C301]' : 'text-[#04045B]'} rotate-90`} />
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
})}
|
|
|
|
{/* Expected Outcome - Use API outcomes data */}
|
|
<div className="bg-[#04045B] text-white rounded-xl p-8 border-4 border-[#F8C301] shadow-xl">
|
|
<div className="flex items-center gap-3 mb-4">
|
|
{apiData.approach_section.outcomes && apiData.approach_section.outcomes[0] && (() => {
|
|
const OutcomeIcon = getIconComponent(apiData.approach_section.outcomes[0].icon_url);
|
|
return <OutcomeIcon className="w-10 h-10 text-[#F8C301]" />;
|
|
})() || <TrendingUp className="w-10 h-10 text-[#F8C301]" />}
|
|
<h3 className="text-h4 text-white">
|
|
{apiData.approach_section.outcomes?.[0]?.title || "Expected Outcome"}
|
|
</h3>
|
|
</div>
|
|
<p className="text-body text-white mb-4">
|
|
{apiData.approach_section.outcomes?.[0]?.description || "Transformational executive leaders with strategic capability, executive presence, and proven business impact."}
|
|
</p>
|
|
<div className="space-y-2">
|
|
{apiData.approach_section.outcomes?.[0]?.bullets?.slice(0, 2).map((bullet, idx) => (
|
|
<div key={idx} className="flex items-center gap-2 text-[#F8C301]">
|
|
<CheckCircle className="w-6 h-6" />
|
|
<span className="text-body text-white">{bullet}</span>
|
|
</div>
|
|
)) || (
|
|
<>
|
|
<div className="flex items-center gap-2 text-[#F8C301]">
|
|
<CheckCircle className="w-6 h-6" />
|
|
<span className="text-body text-white">Enhanced Leadership Effectiveness</span>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Framework Effectiveness - Stats Section */}
|
|
{apiData.stats_section && (
|
|
<div className="bg-gray-50 rounded-xl p-8">
|
|
<div className="text-center mb-8">
|
|
<h3 className="text-h3 text-[#26231A] mb-4">{apiData.stats_section.title}</h3>
|
|
<p className="text-body text-[#6F6F6F] max-w-2xl mx-auto">
|
|
{apiData.stats_section.description}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
{apiData.stats_section.stat_cards.map((stat) => {
|
|
const IconComponent = getIconComponent(stat.icon_url);
|
|
return (
|
|
<div key={stat.id} className="text-center bg-white rounded-lg p-6">
|
|
<div className="w-14 h-14 bg-[#04045B] rounded-lg flex items-center justify-center mx-auto mb-3">
|
|
<IconComponent className="w-7 h-7 text-white" />
|
|
</div>
|
|
<div className="text-h2 text-[#04045B] mb-2">{stat.value}</div>
|
|
<p className="text-body text-[#6F6F6F]">{stat.label}</p>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* 5. Sample Program Format */}
|
|
<section className="py-24 lg:py-32" style={{ backgroundColor: '#FFFFFF' }}>
|
|
<div className="section-margin-x">
|
|
<div className="max-w-6xl mx-auto">
|
|
<div className="text-center mb-16">
|
|
<BrandedTag text="Sample Program Format" />
|
|
<h2 className="text-h2 mb-8">{apiData.program_section.title}</h2>
|
|
<p className="text-body-lg text-muted max-w-3xl mx-auto">
|
|
{apiData.program_section.description}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="space-y-8">
|
|
{programTimeline.map((phase, index) => (
|
|
<Card
|
|
key={index}
|
|
className="border border-gray-200 hover:border-primary/20 transition-all duration-300 hover:shadow-lg"
|
|
>
|
|
<CardContent className="p-0">
|
|
<div
|
|
className="flex items-center justify-between p-6 cursor-pointer"
|
|
onClick={() => setExpandedPhase(expandedPhase === index ? null : index)}
|
|
>
|
|
<div className="flex items-start gap-4 flex-1">
|
|
<div
|
|
className="w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0"
|
|
style={{ backgroundColor: 'var(--color-primary)' }}
|
|
>
|
|
<span className="text-white font-semibold">{index + 1}</span>
|
|
</div>
|
|
<div className="flex-1">
|
|
<h3 className="text-h4 mb-2">{phase.phase}</h3>
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<Clock className="w-4 h-4 text-muted" />
|
|
<span className="text-small text-muted">{phase.duration}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="ml-4">
|
|
{expandedPhase === index ? (
|
|
<ChevronUp className="w-5 h-5 text-muted" />
|
|
) : (
|
|
<ChevronDown className="w-5 h-5 text-muted" />
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{expandedPhase === index && (
|
|
<div className="px-6 pb-6 border-t border-gray-100">
|
|
<div className="pt-6 grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
<div>
|
|
<h4 className="text-h4 mb-4">Key Activities</h4>
|
|
<ul className="space-y-3">
|
|
{phase.activities.map((activity, activityIndex) => (
|
|
<li key={activityIndex} className="flex items-start gap-3">
|
|
<CheckCircle className="w-4 h-4 text-primary flex-shrink-0 mt-1" />
|
|
<span className="text-body text-muted">{activity}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
<div>
|
|
<h4 className="text-h4 mb-4">Deliverables & Outcomes</h4>
|
|
<ul className="space-y-3">
|
|
{phase.deliverables.map((deliverable, deliverableIndex) => (
|
|
<li key={deliverableIndex} className="flex items-start gap-3">
|
|
<Star className="w-4 h-4 text-accent flex-shrink-0 mt-1" />
|
|
<span className="text-body text-muted">{deliverable}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* 6. Impact You Can Expect */}
|
|
<section className="py-24 lg:py-32" style={{ backgroundColor: '#F9F9F9' }}>
|
|
<div className="section-margin-x">
|
|
<div className="max-w-6xl mx-auto">
|
|
<div className="text-center mb-16">
|
|
<BrandedTag text="Impact You Can Expect" />
|
|
<h2 className="text-h2 mb-8">{apiData.impact_section.title}</h2>
|
|
<p className="text-body-lg text-muted max-w-3xl mx-auto">
|
|
{apiData.impact_section.description}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-12">
|
|
{apiData.impact_section.impact_stats.map((stat) => {
|
|
const IconComponent = getIconComponent(stat.icon_url);
|
|
return (
|
|
<Card key={stat.id} className="text-center bg-white hover:shadow-lg transition-all duration-300">
|
|
<CardContent className="p-8">
|
|
<div
|
|
className="w-16 h-16 rounded-2xl flex items-center justify-center mx-auto mb-6"
|
|
style={{ backgroundColor: 'var(--color-primary)' }}
|
|
>
|
|
<IconComponent className="w-8 h-8 text-white" />
|
|
</div>
|
|
<div className="text-5xl font-medium mb-4" style={{ color: 'var(--color-primary)' }}>
|
|
{stat.value}
|
|
</div>
|
|
<p className="text-body text-muted mb-2">{stat.description}</p>
|
|
<p className="text-small text-primary font-medium">{stat.label}</p>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
})}
|
|
</div>
|
|
|
|
<div className="bg-white p-8 rounded-2xl shadow-lg">
|
|
<h3 className="text-h3 mb-6 text-center">Additional Strategic Benefits</h3>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
{apiData.impact_section.impact_benefits.map((benefit) => {
|
|
const IconComponent = getIconComponent(benefit.icon_url);
|
|
return (
|
|
<div key={benefit.id} className="text-center">
|
|
<div className="w-12 h-12 bg-primary/10 rounded-lg flex items-center justify-center mx-auto mb-3">
|
|
<IconComponent className="w-6 h-6 text-primary" />
|
|
</div>
|
|
<h4 className="text-h4 mb-2">{benefit.title}</h4>
|
|
<p className="text-small text-muted">{benefit.description}</p>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* 7. Client Examples / Testimonials */}
|
|
<TestimonialsSection
|
|
title="What Our Leaders Say"
|
|
subtitle="Hear from executives and managers who have transformed their leadership approach through our comprehensive development programs."
|
|
tagText="SUCCESS STORIES"
|
|
customTestimonials={testimonials}
|
|
/>
|
|
|
|
{/* 8. CTA Section */}
|
|
{apiData.cta_section && (
|
|
<section className="relative h-[700px] overflow-hidden">
|
|
<div className="absolute inset-0">
|
|
<ImageWithFallback
|
|
src={apiData.cta_section.background_image_url}
|
|
alt={apiData.cta_section.text}
|
|
className="w-full h-full object-cover"
|
|
/>
|
|
<div className="absolute inset-0 bg-black/30" />
|
|
<div className="absolute inset-0 bg-gradient-to-r from-black/20 via-transparent to-black/60" />
|
|
</div>
|
|
|
|
<div className="relative h-full flex items-center justify-end section-margin-x">
|
|
<div
|
|
className="bg-opacity-95 backdrop-blur-sm rounded-lg p-16 max-w-2xl"
|
|
style={{ backgroundColor: 'var(--color-brand-primary)' }}
|
|
>
|
|
<BrandedTag text="Next Steps" variant="white" />
|
|
<h2 className="text-h2-white mb-8">
|
|
{apiData.cta_section.text}
|
|
<span className="italic" style={{ color: 'var(--color-brand-accent)' }}>
|
|
{" "}Get in touch{" "}
|
|
</span>
|
|
to drive exceptional strategic outcomes.
|
|
</h2>
|
|
<StandardCTAButton
|
|
text={apiData.cta_section.cta_text}
|
|
onClick={() => navigateTo(apiData.cta_section.cta_destination)}
|
|
ariaLabel={apiData.cta_section.cta_text}
|
|
/>
|
|
{apiData.cta_section.description && (
|
|
<p className="text-body-white mt-6 opacity-90">
|
|
{apiData.cta_section.description}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
)}
|
|
</div>
|
|
);
|
|
} |