first commit

This commit is contained in:
priyanshuvish
2025-08-28 13:14:51 +05:30
commit b9bf8ce99e
176 changed files with 51228 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
import svgPaths from "./svg-9nb29n5e63";
function Frame1597884903() {
return (
<div className="absolute font-['Inter:Regular',_sans-serif] font-normal inset-[22%_-4.71%_22%_20.59%] leading-[0] not-italic overflow-clip text-[#ffffff] text-[20px] text-left text-nowrap">
<div className="absolute left-0 top-0">
<p className="block leading-[28px] text-nowrap whitespace-pre">
Build Your Leadership Pipeline
</p>
</div>
<div className="absolute left-0 top-[22px]">
<p className="block leading-[28px] text-nowrap whitespace-pre">
Build Your Leadership Pipeline
</p>
</div>
</div>
);
}
function Frame18() {
return (
<div className="absolute bg-[#04045b] bottom-0 left-0 overflow-clip right-[85.29%] top-0">
<div
className="absolute flex h-[25.953px] items-center justify-center translate-x-[-50%] translate-y-[-50%] w-[25.953px]"
style={{ top: "calc(50% - 0.226px)", left: "calc(50% - 0.645px)" }}
>
<div className="flex-none rotate-[225deg] scale-y-[-100%]">
<div className="h-5 relative w-[16.717px]" data-name="Vector">
<svg
className="block size-full"
fill="none"
preserveAspectRatio="none"
viewBox="0 0 17 20"
>
<path
d={svgPaths.pac4fa00}
fill="var(--fill-0, white)"
id="Vector"
/>
</svg>
</div>
</div>
</div>
<div
className="absolute flex h-[38.935px] items-center justify-center translate-x-[-50%] translate-y-[-50%] w-[38.935px]"
style={{ top: "calc(50% + 35.775px)", left: "calc(50% - 35.646px)" }}
>
<div className="flex-none rotate-[225deg] scale-y-[-100%]">
<div className="h-[30px] relative w-[25.075px]" data-name="Vector">
<svg
className="block size-full"
fill="none"
preserveAspectRatio="none"
viewBox="0 0 26 30"
>
<path
d={svgPaths.p177af00}
fill="var(--fill-0, white)"
id="Vector"
/>
</svg>
</div>
</div>
</div>
</div>
);
}
export default function BuildYourLeadershipPipelineButton() {
return (
<div
className="relative size-full"
data-name="Build Your Leadership Pipeline (Button)"
>
<Frame1597884903 />
<Frame18 />
</div>
);
}

View File

@@ -0,0 +1,79 @@
import svgPaths from "./svg-sphymsws2o";
function Frame1597884903() {
return (
<div className="absolute bottom-[22%] font-['Inter:Regular',_sans-serif] font-normal leading-[0] left-[19.66%] not-italic overflow-clip right-0 text-[#ffffff] text-[20px] text-left text-nowrap top-[22%]">
<div className="absolute left-0 top-0">
<p className="block leading-[28px] text-nowrap whitespace-pre">
Build Your Leadership Pipeline
</p>
</div>
<div className="absolute left-0 top-[22px]">
<p className="block leading-[28px] text-nowrap whitespace-pre">
Build Your Leadership Pipeline
</p>
</div>
</div>
);
}
function Frame18() {
return (
<div className="absolute bg-[#04045b] bottom-0 left-0 overflow-clip right-[85.95%] top-0">
<div
className="absolute flex h-[25.953px] items-center justify-center translate-x-[-50%] translate-y-[-50%] w-[25.953px]"
style={{ top: "calc(50% - 0.226px)", left: "calc(50% - 0.645px)" }}
>
<div className="flex-none rotate-[225deg] scale-y-[-100%]">
<div className="h-5 relative w-[16.717px]" data-name="Vector">
<svg
className="block size-full"
fill="none"
preserveAspectRatio="none"
viewBox="0 0 17 20"
>
<path
d={svgPaths.pac4fa00}
fill="var(--fill-0, white)"
id="Vector"
/>
</svg>
</div>
</div>
</div>
<div
className="absolute flex h-[38.935px] items-center justify-center translate-x-[-50%] translate-y-[-50%] w-[38.935px]"
style={{ top: "calc(50% + 35.775px)", left: "calc(50% - 35.646px)" }}
>
<div className="flex-none rotate-[225deg] scale-y-[-100%]">
<div className="h-[30px] relative w-[25.075px]" data-name="Vector">
<svg
className="block size-full"
fill="none"
preserveAspectRatio="none"
viewBox="0 0 26 30"
>
<path
d={svgPaths.p177af00}
fill="var(--fill-0, white)"
id="Vector"
/>
</svg>
</div>
</div>
</div>
</div>
);
}
export default function BuildYourLeadershipPipelineButton() {
return (
<div
className="relative size-full"
data-name="Build Your Leadership Pipeline (Button)"
>
<Frame1597884903 />
<Frame18 />
</div>
);
}

View File

@@ -0,0 +1,79 @@
import svgPaths from "./svg-k5kyhbfrwc";
function Frame1597884903() {
return (
<div className="absolute bottom-[22%] font-['Source_Sans_Pro:Regular',_sans-serif] leading-[0] left-[21.61%] not-italic overflow-clip right-0 text-[#ffffff] text-[20px] text-left text-nowrap top-[22%]">
<div className="absolute left-0 top-0">
<p className="block leading-[28px] text-nowrap whitespace-pre">
Build Your Leadership Pipeline
</p>
</div>
<div className="absolute left-0 top-[22px]">
<p className="block leading-[28px] text-nowrap whitespace-pre">
Build Your Leadership Pipeline
</p>
</div>
</div>
);
}
function Frame18() {
return (
<div className="absolute bg-[#04045b] bottom-0 left-0 overflow-clip right-[84.57%] top-0">
<div
className="absolute flex h-[25.953px] items-center justify-center translate-x-[-50%] translate-y-[-50%] w-[25.953px]"
style={{ top: "calc(50% - 0.226px)", left: "calc(50% - 0.645px)" }}
>
<div className="flex-none rotate-[225deg] scale-y-[-100%]">
<div className="h-5 relative w-[16.717px]" data-name="Vector">
<svg
className="block size-full"
fill="none"
preserveAspectRatio="none"
viewBox="0 0 17 20"
>
<path
d={svgPaths.pac4fa00}
fill="var(--fill-0, white)"
id="Vector"
/>
</svg>
</div>
</div>
</div>
<div
className="absolute flex h-[38.935px] items-center justify-center translate-x-[-50%] translate-y-[-50%] w-[38.935px]"
style={{ top: "calc(50% + 35.775px)", left: "calc(50% - 35.645px)" }}
>
<div className="flex-none rotate-[225deg] scale-y-[-100%]">
<div className="h-[30px] relative w-[25.075px]" data-name="Vector">
<svg
className="block size-full"
fill="none"
preserveAspectRatio="none"
viewBox="0 0 26 30"
>
<path
d={svgPaths.p177af00}
fill="var(--fill-0, white)"
id="Vector"
/>
</svg>
</div>
</div>
</div>
</div>
);
}
export default function BuildYourLeadershipPipelineButton() {
return (
<div
className="relative size-full"
data-name="Build Your Leadership Pipeline (Button)"
>
<Frame1597884903 />
<Frame18 />
</div>
);
}

View File

@@ -0,0 +1,178 @@
function Frame1597884955() {
return (
<div className="box-border content-stretch flex flex-col gap-7 items-center justify-start leading-[0] not-italic p-0 relative shrink-0 text-center w-[652px]">
<div className="font-['Inter:Semi_Bold',_sans-serif] font-semibold relative shrink-0 text-[#26231a] text-[48px] tracking-[-0.96px] w-full">
<p className="block leading-[53px]">Our Approach</p>
</div>
<div className="font-['Inter:Regular',_sans-serif] font-normal relative shrink-0 text-[18px] text-[rgba(38,35,26,0.8)] w-full">
<p className="block leading-[24px]">
Programmatic journey over 612 weeks combining practical application with peer learning for maximum management
effectiveness.
</p>
</div>
</div>
);
}
function Component01() {
return (
<div className="absolute bg-[#ffffff] h-[234px] left-0 top-0 w-[1230px]" data-name="01">
<div
className="absolute font-['Inter:Regular',_sans-serif] font-normal leading-[0] not-italic text-[18px] text-[rgba(38,35,26,0.8)] text-left top-[186px] w-[652px]"
style={{ left: "calc(50% - 400px)" }}
>
<p className="block leading-[24px]">
Comprehensive assessment of current management skills and development needs
</p>
</div>
<div
className="absolute font-['Inter:Semi_Bold',_sans-serif] font-semibold leading-[0] not-italic text-[#26231a] text-[40px] text-center text-nowrap top-10 tracking-[-0.8px] translate-x-[-50%]"
style={{ left: "calc(50% - 577.5px)" }}
>
<p className="adjustLetterSpacing block leading-[53px] whitespace-pre">(01)</p>
</div>
<div
className="absolute font-['Inter:Semi_Bold',_sans-serif] font-semibold leading-[53px] not-italic text-[#26231a] text-[40px] text-left text-nowrap top-10 tracking-[-0.8px] whitespace-pre"
style={{ left: "calc(50% - 400px)" }}
>
<p className="adjustLetterSpacing block mb-0">{`Skills `}</p>
<p className="adjustLetterSpacing block">Assessment</p>
</div>
<div className="absolute h-0 left-0 top-0 w-[1230px]">
<div className="absolute bottom-0 left-0 right-0 top-[-1px]">
<svg className="block size-full" fill="none" preserveAspectRatio="none" viewBox="0 0 1230 1">
<line id="Line 62" stroke="var(--stroke-0, black)" x2="1230" y1="0.5" y2="0.5" />
</svg>
</div>
</div>
</div>
);
}
function Component02() {
return (
<div className="absolute bg-[#ffffff] h-[234px] left-0 top-[274px] w-[1230px]" data-name="02">
<div
className="absolute font-['Inter:Regular',_sans-serif] font-normal leading-[0] not-italic text-[#26231a] text-[18px] text-left top-[186px] w-[652px]"
style={{ left: "calc(50% - 399px)" }}
>
<p className="block leading-[24px]">
Customized curriculum design based on assessment results and operational context
</p>
</div>
<div
className="absolute font-['Inter:Semi_Bold',_sans-serif] font-semibold leading-[0] not-italic text-[#26231a] text-[40px] text-center text-nowrap top-10 tracking-[-0.8px] translate-x-[-50%]"
style={{ left: "calc(50% - 576.5px)" }}
>
<p className="adjustLetterSpacing block leading-[53px] whitespace-pre">(02)</p>
</div>
<div
className="absolute font-['Inter:Semi_Bold',_sans-serif] font-semibold leading-[53px] not-italic text-[#26231a] text-[40px] text-left text-nowrap top-10 tracking-[-0.8px] whitespace-pre"
style={{ left: "calc(50% - 399px)" }}
>
<p className="adjustLetterSpacing block mb-0">{`Program `}</p>
<p className="adjustLetterSpacing block">Design</p>
</div>
<div className="absolute h-0 left-[3px] top-0 w-[1230px]">
<div className="absolute bottom-0 left-0 right-0 top-[-1px]">
<svg className="block size-full" fill="none" preserveAspectRatio="none" viewBox="0 0 1230 1">
<line id="Line 62" stroke="var(--stroke-0, black)" x2="1230" y1="0.5" y2="0.5" />
</svg>
</div>
</div>
</div>
);
}
function Component03() {
return (
<div className="absolute bg-[#ffffff] h-[234px] left-0 top-[548px] w-[1230px]" data-name="03">
<div
className="absolute font-['Inter:Regular',_sans-serif] font-normal leading-[0] not-italic text-[18px] text-[rgba(38,35,26,0.8)] text-left top-[186px] w-[601px]"
style={{ left: "calc(50% - 398px)" }}
>
<p className="block leading-[24px]">
Hands-on workshops and peer learning sessions with real-world application
</p>
</div>
<div
className="absolute font-['Inter:Semi_Bold',_sans-serif] font-semibold leading-[0] not-italic text-[#26231a] text-[40px] text-center text-nowrap top-10 tracking-[-0.8px] translate-x-[-50%]"
style={{ left: "calc(50% - 576px)" }}
>
<p className="adjustLetterSpacing block leading-[53px] whitespace-pre">(03)</p>
</div>
<div
className="absolute font-['Inter:Semi_Bold',_sans-serif] font-semibold leading-[53px] not-italic text-[#26231a] text-[40px] text-left text-nowrap top-10 tracking-[-0.8px] whitespace-pre"
style={{ left: "calc(50% - 398px)" }}
>
<p className="adjustLetterSpacing block mb-0">{`Interactive `}</p>
<p className="adjustLetterSpacing block">Learning</p>
</div>
<div className="absolute h-0 left-1 top-0 w-[1230px]">
<div className="absolute bottom-0 left-0 right-0 top-[-1px]">
<svg className="block size-full" fill="none" preserveAspectRatio="none" viewBox="0 0 1230 1">
<line id="Line 62" stroke="var(--stroke-0, black)" x2="1230" y1="0.5" y2="0.5" />
</svg>
</div>
</div>
</div>
);
}
function Component04() {
return (
<div className="absolute bg-[#ffffff] h-[234px] left-0 top-[822px] w-[1230px]" data-name="04">
<div
className="absolute font-['Inter:Regular',_sans-serif] font-normal leading-[0] not-italic text-[18px] text-[rgba(38,35,26,0.8)] text-left top-[186px] w-[601px]"
style={{ left: "calc(50% - 398px)" }}
>
<p className="block leading-[24px]">
Ongoing support and progress tracking to ensure skills transfer and improvement
</p>
</div>
<div
className="absolute font-['Inter:Semi_Bold',_sans-serif] font-semibold leading-[0] not-italic text-[#26231a] text-[40px] text-center text-nowrap top-10 tracking-[-0.8px] translate-x-[-50%]"
style={{ left: "calc(50% - 575.5px)" }}
>
<p className="adjustLetterSpacing block leading-[53px] whitespace-pre">(04)</p>
</div>
<div
className="absolute font-['Inter:Semi_Bold',_sans-serif] font-semibold leading-[53px] not-italic text-[#26231a] text-[40px] text-left text-nowrap top-10 tracking-[-0.8px] whitespace-pre"
style={{ left: "calc(50% - 398px)" }}
>
<p className="adjustLetterSpacing block mb-0">{`Application & `}</p>
<p className="adjustLetterSpacing block">Review</p>
</div>
<div className="absolute h-0 left-1 top-0 w-[1230px]">
<div className="absolute bottom-0 left-0 right-0 top-[-1px]">
<svg className="block size-full" fill="none" preserveAspectRatio="none" viewBox="0 0 1230 1">
<line id="Line 62" stroke="var(--stroke-0, black)" x2="1230" y1="0.5" y2="0.5" />
</svg>
</div>
</div>
</div>
);
}
function Frame1597884956() {
return (
<div className="h-[1056px] relative shrink-0 w-full">
<Component01 />
<Component02 />
<Component03 />
<Component04 />
</div>
);
}
export default function OurApproachSection() {
return (
<div
className="box-border content-stretch flex flex-col gap-20 items-center justify-start p-0 relative size-full"
data-name="Our approach section"
>
<Frame1597884955 />
<Frame1597884956 />
</div>
);
}

View File

@@ -0,0 +1,4 @@
export default {
p177af00: "M24.7045 12.0426L12.5992 0L0.493934 12.0426C0.35111 12.1514 0.233321 12.2895 0.148542 12.4478C0.0637634 12.606 0.0139736 12.7806 0.00254296 12.9598C-0.00888768 13.1389 0.0183085 13.3185 0.0822895 13.4862C0.14627 13.6539 0.245543 13.806 0.373386 13.932C0.501229 14.058 0.654659 14.1551 0.823287 14.2167C0.991916 14.2783 1.17181 14.3029 1.35078 14.2889C1.52975 14.2749 1.70363 14.2226 1.86065 14.1356C2.01766 14.0486 2.15414 13.9288 2.26085 13.7845L11.3461 4.77444V28.7469C11.3461 29.0792 11.4781 29.398 11.7131 29.633C11.9481 29.868 12.2668 30 12.5992 30C12.9315 30 13.2503 29.868 13.4853 29.633C13.7203 29.398 13.8523 29.0792 13.8523 28.7469V4.77444L22.9375 13.7845C23.1735 14.0188 23.4929 14.1497 23.8254 14.1486C24.158 14.1474 24.4764 14.0142 24.7107 13.7782C24.945 13.5422 25.076 13.2228 25.0748 12.8903C25.0737 12.5578 24.9404 12.2393 24.7045 12.005V12.0426Z",
pac4fa00: "M16.4696 8.0284L8.39946 0L0.329289 8.0284C0.234073 8.10091 0.155547 8.19303 0.0990282 8.29852C0.042509 8.40402 0.00931573 8.52042 0.00169531 8.63986C-0.00592512 8.7593 0.0122057 8.87898 0.0548596 8.9908C0.0975136 9.10262 0.163695 9.20397 0.248924 9.28799C0.334153 9.37201 0.436439 9.43674 0.548858 9.47779C0.661277 9.51884 0.781204 9.53526 0.90052 9.52594C1.01984 9.51661 1.13576 9.48176 1.24043 9.42374C1.34511 9.36572 1.43609 9.28588 1.50723 9.18964L7.56404 3.18296V19.1646C7.56404 19.3861 7.65206 19.5986 7.80873 19.7553C7.9654 19.912 8.1779 20 8.39946 20C8.62103 20 8.83352 19.912 8.9902 19.7553C9.14687 19.5986 9.23488 19.3861 9.23488 19.1646V3.18296L15.2917 9.18964C15.449 9.34585 15.6619 9.43316 15.8836 9.43238C16.1053 9.43159 16.3176 9.34278 16.4738 9.18546C16.63 9.02815 16.7173 8.81523 16.7166 8.59354C16.7158 8.37185 16.627 8.15955 16.4696 8.00334V8.0284Z",
}

View File

@@ -0,0 +1,4 @@
export default {
p177af00: "M24.7045 12.0426L12.5992 0L0.493934 12.0426C0.35111 12.1514 0.233321 12.2895 0.148542 12.4478C0.0637634 12.606 0.0139736 12.7806 0.00254296 12.9598C-0.00888768 13.1389 0.0183085 13.3185 0.0822895 13.4862C0.14627 13.6539 0.245543 13.806 0.373386 13.932C0.501229 14.058 0.654659 14.1551 0.823287 14.2167C0.991916 14.2783 1.17181 14.3029 1.35078 14.2889C1.52975 14.2749 1.70363 14.2226 1.86065 14.1356C2.01766 14.0486 2.15414 13.9288 2.26085 13.7845L11.3461 4.77444V28.7469C11.3461 29.0792 11.4781 29.398 11.7131 29.633C11.9481 29.868 12.2668 30 12.5992 30C12.9315 30 13.2503 29.868 13.4853 29.633C13.7203 29.398 13.8523 29.0792 13.8523 28.7469V4.77444L22.9375 13.7845C23.1735 14.0188 23.4929 14.1497 23.8254 14.1486C24.158 14.1474 24.4764 14.0142 24.7107 13.7782C24.945 13.5422 25.076 13.2228 25.0748 12.8903C25.0737 12.5578 24.9404 12.2393 24.7045 12.005V12.0426Z",
pac4fa00: "M16.4696 8.0284L8.39946 0L0.329289 8.0284C0.234073 8.10091 0.155547 8.19303 0.0990282 8.29852C0.042509 8.40402 0.00931573 8.52042 0.00169531 8.63986C-0.00592512 8.7593 0.0122057 8.87898 0.0548596 8.9908C0.0975136 9.10262 0.163695 9.20397 0.248924 9.28799C0.334153 9.37201 0.436439 9.43674 0.548858 9.47779C0.661277 9.51884 0.781204 9.53526 0.90052 9.52594C1.01984 9.51661 1.13576 9.48176 1.24043 9.42374C1.34511 9.36572 1.43609 9.28588 1.50723 9.18964L7.56404 3.18296V19.1646C7.56404 19.3861 7.65206 19.5986 7.80873 19.7553C7.9654 19.912 8.1779 20 8.39946 20C8.62103 20 8.83352 19.912 8.9902 19.7553C9.14687 19.5986 9.23488 19.3861 9.23488 19.1646V3.18296L15.2917 9.18964C15.449 9.34585 15.6619 9.43316 15.8836 9.43238C16.1053 9.43159 16.3176 9.34278 16.4738 9.18546C16.63 9.02815 16.7173 8.81523 16.7166 8.59354C16.7158 8.37185 16.627 8.15955 16.4696 8.00334V8.0284Z",
}

View File

@@ -0,0 +1,4 @@
export default {
p177af00: "M24.7045 12.0426L12.5992 0L0.493934 12.0426C0.35111 12.1514 0.233321 12.2895 0.148542 12.4478C0.0637634 12.606 0.0139736 12.7806 0.00254296 12.9598C-0.00888768 13.1389 0.0183085 13.3185 0.0822895 13.4862C0.14627 13.6539 0.245543 13.806 0.373386 13.932C0.501229 14.058 0.654659 14.1551 0.823287 14.2167C0.991916 14.2783 1.17181 14.3029 1.35078 14.2889C1.52975 14.2749 1.70363 14.2226 1.86065 14.1356C2.01766 14.0486 2.15414 13.9288 2.26085 13.7845L11.3461 4.77444V28.7469C11.3461 29.0792 11.4781 29.398 11.7131 29.633C11.9481 29.868 12.2668 30 12.5992 30C12.9315 30 13.2503 29.868 13.4853 29.633C13.7203 29.398 13.8523 29.0792 13.8523 28.7469V4.77444L22.9375 13.7845C23.1735 14.0188 23.4929 14.1497 23.8254 14.1486C24.158 14.1474 24.4764 14.0142 24.7107 13.7782C24.945 13.5422 25.076 13.2228 25.0748 12.8903C25.0737 12.5578 24.9404 12.2393 24.7045 12.005V12.0426Z",
pac4fa00: "M16.4696 8.0284L8.39946 0L0.329289 8.0284C0.234073 8.10091 0.155547 8.19303 0.0990282 8.29852C0.042509 8.40402 0.00931573 8.52042 0.00169531 8.63986C-0.00592512 8.7593 0.0122057 8.87898 0.0548596 8.9908C0.0975136 9.10262 0.163695 9.20397 0.248924 9.28799C0.334153 9.37201 0.436439 9.43674 0.548858 9.47779C0.661277 9.51884 0.781204 9.53526 0.90052 9.52594C1.01984 9.51661 1.13576 9.48176 1.24043 9.42374C1.34511 9.36572 1.43609 9.28588 1.50723 9.18964L7.56404 3.18296V19.1646C7.56404 19.3861 7.65206 19.5986 7.80873 19.7553C7.9654 19.912 8.1779 20 8.39946 20C8.62103 20 8.83352 19.912 8.9902 19.7553C9.14687 19.5986 9.23488 19.3861 9.23488 19.1646V3.18296L15.2917 9.18964C15.449 9.34585 15.6619 9.43316 15.8836 9.43238C16.1053 9.43159 16.3176 9.34278 16.4738 9.18546C16.63 9.02815 16.7173 8.81523 16.7166 8.59354C16.7158 8.37185 16.627 8.15955 16.4696 8.00334V8.0284Z",
}

170
src/App.tsx Normal file
View File

@@ -0,0 +1,170 @@
import React from 'react';
import { Routes, Route } from "react-router-dom";
import { AuthProvider } from "./components/AuthContext";
import { CartProvider } from "./components/CartContext";
import { Navigation } from "./components/Navigation";
import HeroSection from "./components/HeroSection";
import { StatsSection } from "./components/StatsSection";
import { LogosSection } from "./components/LogosSection";
import { ServicesSection } from "./components/ServicesSection";
import { VirtualSpaceSection } from "./components/VirtualSpaceSection";
import { TestimonialsSection } from "./components/TestimonialsSection";
import { UpcomingWebinarsSection } from "./components/UpcomingWebinarsSection";
import { InsightsSection } from "./components/InsightsSection";
import { CTABannerSection } from "./components/CTABannerSection";
import { WhitepapersSection } from "./components/WhitepapersSection";
import { Footer } from "./components/Footer";
import { AIChatbot } from "./components/AIChatbot";
import { LeadershipJourneyPage } from "./components/LeadershipJourneyPage";
import { LeadershipDevelopment } from "./components/services/LeadershipDevelopment";
import { Consulting } from "./components/services/Consulting";
import { CultureCompetence } from "./components/services/CultureCompetence";
import { ExecutiveCoaching } from "./components/services/ExecutiveCoaching";
import { ManagementDevelopment } from "./components/services/ManagementDevelopment";
import { LearningFacility } from "./components/services/LearningFacility";
import { OurVision } from "./components/about/OurVision";
import { OurExpertise } from "./components/about/OurExpertise";
import { OurImpact } from "./components/about/OurImpact";
import { Contact } from "./components/Contact";
import { Cart } from "./components/Cart";
import { CorporateSignIn } from "./components/CorporateSignIn";
import { SelfLearnerSignIn } from "./components/SelfLearnerSignIn";
import { CorporateSignUp } from "./components/CorporateSignUp";
import { SelfLearnerSignUp } from "./components/SelfLearnerSignUp";
import { ProgrammeDetail } from "./components/ProgrammeDetail";
import { Articles } from "./components/Articles";
import { Blogs } from "./components/Blogs";
import { BlogDetail } from "./components/BlogDetail";
import { Webinars } from "./components/Webinars";
import { WebinarsPage } from "./components/WebinarsPage";
import WebinarsListing from "./components/WebinarsListing";
import WebinarDetail from "./components/WebinarDetail";
import { LearningOnline } from "./components/LearningOnline";
import { Terms } from "./components/Terms";
// import EnrollPlaceholder from "./components/EnrollPlaceholder";
// import ForgotPasswordPlaceholder from "./components/ForgotPasswordPlaceholder";
// import DashboardPlaceholder from "./components/DashboardPlaceholder";
// import CheckoutPlaceholder from "./components/CheckoutPlaceholder";
// import HomePage from "./components/HomePage";
export default function App() {
return (
<AuthProvider>
<CartProvider>
<div
className="min-h-screen main-content"
style={{ backgroundColor: '#FFFFFF' }}
>
<Routes>
{/* Home Page */}
<Route path="/" element={<HomePage />} />
{/* Leadership Journey */}
<Route path="/leadership-journey" element={<LeadershipJourneyPage />} />
{/* Services Pages */}
<Route path="/services/leadership-development" element={<LeadershipDevelopment />} />
<Route path="/services/consulting" element={<Consulting />} />
<Route path="/services/culture-competence" element={<CultureCompetence />} />
<Route path="/services/executive-coaching" element={<ExecutiveCoaching />} />
<Route path="/services/management-development" element={<ManagementDevelopment />} />
<Route path="/services/learning-facility" element={<LearningFacility />} />
{/* About Us Pages */}
<Route path="/about/our-vision" element={<OurVision />} />
<Route path="/about/our-expertise" element={<OurExpertise />} />
<Route path="/about/our-impact" element={<OurImpact />} />
{/* Learning Pages */}
<Route path="/learning/articles" element={<Articles />} />
<Route path="/learning/blogs" element={<Blogs />} />
<Route path="/learning/webcast" element={<Webinars />} />
{/* Webinars Pages */}
<Route path="/webinars" element={<WebinarsPage />} />
<Route path="/webinars-legacy" element={<WebinarsListing />} />
{/* Learning Online */}
<Route path="/learning-online" element={<LearningOnline />} />
{/* Terms & Conditions */}
<Route path="/terms" element={<Terms />} />
{/* Cart */}
<Route path="/cart" element={<Cart />} />
{/* Authentication Pages */}
<Route path="/corporate-login" element={<CorporateSignIn />} />
<Route path="/self-learner-signin" element={<SelfLearnerSignIn />} />
<Route path="/signin/self-learner" element={<SelfLearnerSignIn />} />
<Route path="/corporate-signup" element={<CorporateSignUp />} />
<Route path="/self-learner-signup" element={<SelfLearnerSignUp />} />
{/* Contact Page */}
<Route path="/contact" element={<Contact />} />
{/* Dynamic Routes */}
<Route path="/learning/articles/:slug" element={<BlogDetail />} />
<Route path="/learning/blogs/:slug" element={<BlogDetail />} />
{/* <Route path="/learning/webcast/:slug" element={<WebinarDetail />} />
<Route path="/webinar/:slug" element={<WebinarDetail />} /> */}
<Route path="/course/:slug" element={<ProgrammeDetail />} />
<Route path="/programme/:slug" element={<ProgrammeDetail />} />
{/* Placeholder Pages */}
{/* <Route path="/enroll" element={<EnrollPlaceholder />} />
<Route path="/forgot-password" element={<ForgotPasswordPlaceholder />} />
<Route path="/dashboard" element={<DashboardPlaceholder />} />
<Route path="/checkout" element={<CheckoutPlaceholder />} /> */}
{/* 404 Page */}
<Route path="*" element={<NotFound />} />
</Routes>
{/* Add AIChatbot to all pages */}
<AIChatbot />
</div>
</CartProvider>
</AuthProvider>
);
}
// Home Page Component (extracted from your default landing page)
function HomePage() {
return (
<>
<Navigation />
<HeroSection />
<StatsSection />
<LogosSection />
<ServicesSection />
<VirtualSpaceSection />
<TestimonialsSection />
<UpcomingWebinarsSection />
<InsightsSection />
<WhitepapersSection />
<CTABannerSection />
<Footer />
</>
);
}
// 404 Not Found Component
function NotFound() {
return (
<div className="min-h-screen flex items-center justify-center" style={{ backgroundColor: '#FFFFFF' }}>
<div className="text-center">
<h1 className="text-h2 mb-4">Page Not Found</h1>
<p className="text-body-lg text-muted mb-8">
The page you're looking for doesn't exist.
</p>
<button
onClick={() => window.location.href = '/'}
className="brand-button-system"
>
Back to Home
</button>
</div>
</div>
);
}

3
src/Attributions.md Normal file
View File

@@ -0,0 +1,3 @@
This Figma Make file includes components from [shadcn/ui](https://ui.shadcn.com/) used under [MIT license](https://github.com/shadcn-ui/ui/blob/main/LICENSE.md).
This Figma Make file includes photos from [Unsplash](https://unsplash.com) used under [license](https://unsplash.com/license).

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,485 @@
import React, { useState, useEffect, useRef } from 'react';
import { Button } from './ui/button';
import { Card, CardContent, CardHeader, CardTitle } from './ui/card';
import { Badge } from './ui/badge';
import {
MessageCircle,
X,
Send,
Bot,
User,
Minimize2,
Maximize2
} from 'lucide-react';
import { Input } from './ui/input';
import { ScrollArea } from './ui/scroll-area';
interface Message {
id: string;
type: 'user' | 'bot';
content: string;
timestamp: Date;
suggestions?: string[];
}
const initialMessage: Message = {
id: '1',
type: 'bot',
content: "Hi! I'm here to help you explore KLC's leadership programs and facilities. What are you looking for today?",
timestamp: new Date(),
suggestions: [
"Show me leadership programs",
"Book a facility tour",
"Upcoming webinars",
"Contact information"
]
};
const botResponses: Record<string, { content: string; suggestions?: string[] }> = {
"programs": {
content: "Great! We offer various leadership development programs including Executive Leadership, Strategic Management, and Team Building workshops. Would you like to explore specific programs or see our full catalog?",
suggestions: ["View all programs", "Executive programs", "Team building", "Custom corporate training"]
},
"leadership": {
content: "Our leadership programs are designed to transform leaders at every level. We offer Executive Leadership Development, Strategic Leadership, Team Leadership, and Management Excellence programs.",
suggestions: ["Executive Leadership", "Strategic Leadership", "Team Leadership", "Management Excellence"]
},
"facilities": {
content: "Our state-of-the-art facilities include modern conference rooms, training halls, and collaboration spaces. You can take a virtual tour or book a facility for your event.",
suggestions: ["Virtual tour", "Book conference room", "Training halls", "Facility pricing"]
},
"facility": {
content: "Our learning facility features cutting-edge technology, flexible meeting spaces, and comfortable learning environments. We can accommodate groups from 10 to 500 participants.",
suggestions: ["Book now", "View amenities", "Check availability", "Pricing information"]
},
"tour": {
content: "I'd be happy to arrange a facility tour for you! Our tours showcase our modern classrooms, breakout spaces, and technology capabilities. Would you like to schedule one?",
suggestions: ["Schedule tour", "Virtual tour", "Facility features", "Contact tour guide"]
},
"webinars": {
content: "We host regular webinars on leadership topics. You can view upcoming sessions, register for live events, or access our library of recorded sessions.",
suggestions: ["Upcoming webinars", "Recorded sessions", "Register for webinar", "Webinar schedule"]
},
"webinar": {
content: "Our webinars cover essential leadership topics like Strategic Thinking, Team Management, Change Leadership, and Executive Presence. Most are free to attend!",
suggestions: ["View schedule", "Register now", "Past recordings", "Webinar topics"]
},
"contact": {
content: "You can reach us at info@klc.edu.in or call +91 11 4567 8900. Our team is available Monday to Friday, 9 AM to 6 PM IST. You can also schedule a consultation.",
suggestions: ["Schedule consultation", "Email us", "Office locations", "Support hours"]
},
"executive": {
content: "Our Executive Leadership programs are designed for senior leaders and C-suite executives. These intensive programs focus on strategic thinking, organizational transformation, and executive presence.",
suggestions: ["Program details", "Enrollment", "Schedule", "Executive coaching"]
},
"strategic": {
content: "Strategic Leadership development helps leaders think systematically about complex challenges, make better decisions, and drive organizational change effectively.",
suggestions: ["Learn more", "Case studies", "Program schedule", "Apply now"]
},
"team": {
content: "Team Leadership programs focus on building high-performing teams, improving collaboration, and developing emotional intelligence for team leaders.",
suggestions: ["Team programs", "Workshop format", "Group discounts", "Custom training"]
},
"management": {
content: "Management Excellence programs cover essential management skills including performance management, delegation, communication, and conflict resolution.",
suggestions: ["Management training", "Skills assessment", "Corporate packages", "Schedule consultation"]
},
"pricing": {
content: "Our pricing varies by program type and group size. Individual programs start from ₹15,000, while corporate packages offer significant discounts for bulk enrollments.",
suggestions: ["Individual pricing", "Corporate packages", "Group discounts", "Payment options"]
},
"schedule": {
content: "We offer programs throughout the year with flexible scheduling options. Most programs are available in weekend, weekday, and intensive formats.",
suggestions: ["View calendar", "Weekend programs", "Weekday options", "Custom scheduling"]
},
"enrollment": {
content: "Enrollment is simple! You can register online, call us directly, or schedule a consultation to discuss the best program for your needs.",
suggestions: ["Register online", "Call us", "Schedule consultation", "Application process"]
},
"corporate": {
content: "Our corporate solutions include custom leadership development programs, executive coaching, and organizational development services tailored to your company's needs.",
suggestions: ["Custom programs", "Executive coaching", "Organizational development", "Corporate pricing"]
},
"coaching": {
content: "We offer one-on-one executive coaching with certified leadership coaches. Our coaching programs are customized to address specific leadership challenges and goals.",
suggestions: ["Coach profiles", "Coaching process", "Pricing", "Schedule session"]
},
"default": {
content: "I can help you with information about our programs, facilities, webinars, and more. What would you like to know?",
suggestions: ["Leadership programs", "Facility booking", "Webinars", "Contact us"]
}
};
export function AIChatbot() {
const [isVisible, setIsVisible] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const [isMinimized, setIsMinimized] = useState(false);
const [messages, setMessages] = useState<Message[]>([initialMessage]);
const [inputValue, setInputValue] = useState('');
const [isTyping, setIsTyping] = useState(false);
const messagesEndRef = useRef<HTMLDivElement>(null);
const inactivityTimerRef = useRef<NodeJS.Timeout>();
// Show chatbot after user activity
useEffect(() => {
const resetTimer = () => {
if (inactivityTimerRef.current) {
clearTimeout(inactivityTimerRef.current);
}
inactivityTimerRef.current = setTimeout(() => {
if (!isOpen) {
setIsVisible(true);
}
}, 8000); // Show after 8 seconds of activity
};
const events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart'];
const addEventListeners = () => {
events.forEach(event => {
document.addEventListener(event, resetTimer, true);
});
};
const removeEventListeners = () => {
events.forEach(event => {
document.removeEventListener(event, resetTimer, true);
});
};
addEventListeners();
resetTimer();
return () => {
removeEventListeners();
if (inactivityTimerRef.current) {
clearTimeout(inactivityTimerRef.current);
}
};
}, [isOpen]);
// Auto-scroll to bottom of messages
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);
const getBotResponse = (userMessage: string): { content: string; suggestions?: string[] } => {
const message = userMessage.toLowerCase();
// Enhanced keyword matching
if (message.includes('leadership') && (message.includes('program') || message.includes('course') || message.includes('training'))) {
return botResponses.leadership;
} else if (message.includes('executive') || message.includes('senior') || message.includes('c-suite')) {
return botResponses.executive;
} else if (message.includes('strategic') || message.includes('strategy')) {
return botResponses.strategic;
} else if (message.includes('team') || message.includes('collaboration')) {
return botResponses.team;
} else if (message.includes('management') || message.includes('manager')) {
return botResponses.management;
} else if (message.includes('program') || message.includes('course') || message.includes('training')) {
return botResponses.programs;
} else if (message.includes('facility') || message.includes('space') || message.includes('room')) {
return botResponses.facility;
} else if (message.includes('tour') || message.includes('visit')) {
return botResponses.tour;
} else if (message.includes('book') || message.includes('reserve') || message.includes('schedule')) {
return botResponses.facilities;
} else if (message.includes('webinar') || message.includes('session') || message.includes('online')) {
return botResponses.webinar;
} else if (message.includes('contact') || message.includes('phone') || message.includes('email') || message.includes('reach')) {
return botResponses.contact;
} else if (message.includes('price') || message.includes('cost') || message.includes('fee')) {
return botResponses.pricing;
} else if (message.includes('schedule') || message.includes('timing') || message.includes('when')) {
return botResponses.schedule;
} else if (message.includes('enroll') || message.includes('register') || message.includes('apply')) {
return botResponses.enrollment;
} else if (message.includes('corporate') || message.includes('company') || message.includes('organization')) {
return botResponses.corporate;
} else if (message.includes('coach') || message.includes('mentor') || message.includes('personal')) {
return botResponses.coaching;
} else {
return botResponses.default;
}
};
const handleSendMessage = async (content: string) => {
if (!content.trim()) return;
// Add user message
const userMessage: Message = {
id: Date.now().toString(),
type: 'user',
content: content.trim(),
timestamp: new Date()
};
setMessages(prev => [...prev, userMessage]);
setInputValue('');
setIsTyping(true);
// Simulate typing delay with realistic timing
setTimeout(() => {
const response = getBotResponse(content);
const botMessage: Message = {
id: (Date.now() + 1).toString(),
type: 'bot',
content: response.content,
timestamp: new Date(),
suggestions: response.suggestions
};
setMessages(prev => [...prev, botMessage]);
setIsTyping(false);
}, 800 + Math.random() * 600); // 800ms to 1.4s delay
};
const handleSuggestionClick = (suggestion: string) => {
handleSendMessage(suggestion);
};
const formatTime = (date: Date) => {
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
};
const handleKeyPress = (e: React.KeyboardEvent) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
handleSendMessage(inputValue);
}
};
if (!isVisible) return null;
return (
<>
{/* Chatbot Toggle Button */}
{!isOpen && (
<Button
onClick={() => setIsOpen(true)}
className="fixed bottom-6 right-6 w-16 h-16 rounded-full shadow-xl z-50 transition-all duration-300 hover:scale-110 chatbot-button"
style={{
backgroundColor: 'var(--color-primary)',
border: 'none'
}}
size="lg"
aria-label="Open KLC Assistant chat"
>
<MessageCircle className="w-6 h-6 text-white" />
</Button>
)}
{/* Chat Window */}
{isOpen && (
<Card className={`fixed bottom-6 right-6 w-80 md:w-96 shadow-2xl z-50 transition-all duration-300 border-0 ${
isMinimized ? 'h-16' : 'h-[500px]'
}`}>
{/* Header */}
<CardHeader
className="flex flex-row items-center justify-between space-y-0 pb-3 rounded-t-lg"
style={{ backgroundColor: 'var(--color-primary)' }}
>
<div className="flex items-center gap-3">
<div
className="w-10 h-10 rounded-full flex items-center justify-center"
style={{ backgroundColor: 'rgba(255, 255, 255, 0.2)' }}
>
<Bot className="w-5 h-5 text-white" />
</div>
<div>
<CardTitle className="text-base font-medium text-white" style={{ fontFamily: 'var(--font-family-base)' }}>
KLC Assistant
</CardTitle>
<div className="flex items-center gap-2 text-sm text-white opacity-90">
<div className="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
<span style={{ fontFamily: 'var(--font-family-base)' }}>Online & Ready to Help</span>
</div>
</div>
</div>
<div className="flex items-center gap-1">
<Button
variant="ghost"
size="sm"
onClick={() => setIsMinimized(!isMinimized)}
className="w-8 h-8 p-0 hover:bg-white/20 text-white"
aria-label={isMinimized ? "Maximize chat" : "Minimize chat"}
>
{isMinimized ? (
<Maximize2 className="w-4 h-4" />
) : (
<Minimize2 className="w-4 h-4" />
)}
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => setIsOpen(false)}
className="w-8 h-8 p-0 hover:bg-white/20 text-white"
aria-label="Close chat"
>
<X className="w-4 h-4" />
</Button>
</div>
</CardHeader>
{/* Chat Content */}
{!isMinimized && (
<CardContent className="p-0 flex flex-col h-[420px]">
{/* Messages */}
<ScrollArea className="flex-1 p-4">
<div className="space-y-4">
{messages.map((message) => (
<div key={message.id} className={`flex ${message.type === 'user' ? 'justify-end' : 'justify-start'}`}>
<div className={`flex items-start gap-3 max-w-[85%] ${message.type === 'user' ? 'flex-row-reverse' : ''}`}>
<div className={`w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${
message.type === 'user'
? 'text-white'
: 'bg-gray-100 text-gray-600'
}`}
style={message.type === 'user' ? { backgroundColor: 'var(--color-primary)' } : {}}
>
{message.type === 'user' ? (
<User className="w-4 h-4" />
) : (
<Bot className="w-4 h-4" />
)}
</div>
<div className="space-y-2">
<div className={`p-3 rounded-lg ${
message.type === 'user'
? 'text-white'
: 'bg-gray-50 text-gray-800'
}`}
style={message.type === 'user' ? { backgroundColor: 'var(--color-primary)' } : {}}
>
<p
className="text-sm leading-relaxed"
style={{ fontFamily: 'var(--font-family-base)' }}
>
{message.content}
</p>
</div>
{message.suggestions && (
<div className="flex flex-wrap gap-2">
{message.suggestions.map((suggestion, index) => (
<Badge
key={index}
variant="outline"
className="cursor-pointer transition-colors text-xs py-1 px-3 rounded-full font-normal border-gray-300 text-gray-700 hover:text-white"
style={{
fontFamily: 'var(--font-family-base)',
borderColor: 'var(--color-primary)'
}}
onClick={() => handleSuggestionClick(suggestion)}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = 'var(--color-primary)';
e.currentTarget.style.borderColor = 'var(--color-primary)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = 'transparent';
e.currentTarget.style.borderColor = 'var(--color-primary)';
}}
>
{suggestion}
</Badge>
))}
</div>
)}
<p
className="text-xs text-gray-500 px-1"
style={{ fontFamily: 'var(--font-family-base)' }}
>
{formatTime(message.timestamp)}
</p>
</div>
</div>
</div>
))}
{isTyping && (
<div className="flex justify-start">
<div className="flex items-start gap-3">
<div className="w-8 h-8 bg-gray-100 rounded-full flex items-center justify-center">
<Bot className="w-4 h-4 text-gray-600" />
</div>
<div className="bg-gray-50 p-3 rounded-lg">
<div className="flex gap-1">
<div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce"></div>
<div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '0.1s' }}></div>
<div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '0.2s' }}></div>
</div>
</div>
</div>
</div>
)}
<div ref={messagesEndRef} />
</div>
</ScrollArea>
{/* Input */}
<div className="border-t p-4 bg-white">
<form
onSubmit={(e) => {
e.preventDefault();
handleSendMessage(inputValue);
}}
className="flex gap-2"
role="form"
aria-label="Chat message form"
>
<Input
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="Type your message..."
className="flex-1 min-h-[44px] border-gray-200 focus:border-blue-500 focus:ring-blue-500"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)'
}}
disabled={isTyping}
aria-label="Chat message input"
/>
<Button
type="submit"
size="sm"
disabled={!inputValue.trim() || isTyping}
className="min-h-[44px] min-w-[44px] text-white transition-all duration-200"
style={{
backgroundColor: 'var(--color-primary)',
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)'
}}
onMouseEnter={(e) => {
if (!e.currentTarget.disabled) {
e.currentTarget.style.backgroundColor = '#030359';
}
}}
onMouseLeave={(e) => {
if (!e.currentTarget.disabled) {
e.currentTarget.style.backgroundColor = 'var(--color-primary)';
}
}}
>
<Send className="w-4 h-4" />
<span className="sr-only">Send message</span>
</Button>
</form>
{/* Quick Help Text */}
<p
className="text-xs text-gray-500 mt-2 text-center"
style={{ fontFamily: 'var(--font-family-base)' }}
>
Ask me about programs, facilities, or upcoming events
</p>
</div>
</CardContent>
)}
</Card>
)}
</>
);
}

View File

@@ -0,0 +1,244 @@
export function AboutSection() {
return (
<section
className="py-16 section-margin-x"
style={{ backgroundColor: 'var(--color-brand-bg-white)' }}
>
<div className="max-w-7xl mx-auto">
{/* Section Header with Branded Tag */}
<div className="text-center mb-16">
<div className="flex items-center justify-center gap-2 mb-6">
<div
className="w-2 h-2 rounded-full"
style={{ backgroundColor: 'var(--color-brand-accent)' }}
></div>
<span
className="text-sm font-semibold tracking-wider uppercase"
style={{
color: 'var(--color-brand-black)',
fontFamily: 'var(--font-family-brand)'
}}
>
WHO WE ARE
</span>
</div>
<h2
className="text-5xl font-semibold mb-6"
style={{
color: 'var(--color-brand-black)',
fontFamily: 'var(--font-family-brand)',
lineHeight: '1.1'
}}
>
About KLC
</h2>
<p
className="text-xl max-w-3xl mx-auto leading-relaxed"
style={{
color: 'var(--color-brand-gray-muted)',
fontFamily: 'var(--font-family-brand)'
}}
>
Transforming businesses through strategic expertise, innovative solutions, and lasting partnerships that drive sustainable growth.
</p>
</div>
{/* Three Column Layout */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-12 lg:gap-8">
{/* Our Vision */}
<div className="text-center lg:text-left">
<div
className="w-16 h-16 mx-auto lg:mx-0 mb-6 rounded-lg flex items-center justify-center"
style={{ backgroundColor: 'var(--color-brand-primary)' }}
>
<svg
width="32"
height="32"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1.5"
className="text-white"
>
<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/>
<circle cx="12" cy="12" r="3"/>
</svg>
</div>
<h3
className="text-2xl font-bold mb-4"
style={{
color: 'var(--color-brand-black)',
fontFamily: 'var(--font-family-brand)'
}}
>
Our Vision
</h3>
<p
className="text-base leading-relaxed mb-4"
style={{
color: 'var(--color-brand-gray-muted)',
fontFamily: 'var(--font-family-brand)'
}}
>
To be the leading catalyst for business transformation, empowering organizations to unlock their full potential through innovative strategies and cutting-edge solutions.
</p>
<p
className="text-base leading-relaxed"
style={{
color: 'var(--color-brand-gray-muted)',
fontFamily: 'var(--font-family-brand)'
}}
>
We envision a future where every business can thrive in an ever-evolving marketplace through strategic foresight and adaptive excellence.
</p>
</div>
{/* Our Impact */}
<div className="text-center lg:text-left">
<div
className="w-16 h-16 mx-auto lg:mx-0 mb-6 rounded-lg flex items-center justify-center"
style={{ backgroundColor: 'var(--color-brand-primary)' }}
>
<svg
width="32"
height="32"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1.5"
className="text-white"
>
<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/>
<path d="M3 3v5h5"/>
<path d="M12 7v5l4 2"/>
</svg>
</div>
<h3
className="text-2xl font-bold mb-4"
style={{
color: 'var(--color-brand-black)',
fontFamily: 'var(--font-family-brand)'
}}
>
Our Impact
</h3>
<p
className="text-base leading-relaxed mb-4"
style={{
color: 'var(--color-brand-gray-muted)',
fontFamily: 'var(--font-family-brand)'
}}
>
Over two decades of delivering measurable results for Fortune 500 companies and emerging businesses alike, driving over $2.5 billion in combined client value creation.
</p>
<p
className="text-base leading-relaxed"
style={{
color: 'var(--color-brand-gray-muted)',
fontFamily: 'var(--font-family-brand)'
}}
>
Our strategic interventions have transformed operational efficiency by an average of 40% and accelerated growth trajectories across diverse industries.
</p>
</div>
{/* Our Expertise */}
<div className="text-center lg:text-left">
<div
className="w-16 h-16 mx-auto lg:mx-0 mb-6 rounded-lg flex items-center justify-center"
style={{ backgroundColor: 'var(--color-brand-primary)' }}
>
<svg
width="32"
height="32"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1.5"
className="text-white"
>
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
<path d="M2 17l10 5 10-5"/>
<path d="M2 12l10 5 10-5"/>
</svg>
</div>
<h3
className="text-2xl font-bold mb-4"
style={{
color: 'var(--color-brand-black)',
fontFamily: 'var(--font-family-brand)'
}}
>
Our Expertise
</h3>
<p
className="text-base leading-relaxed mb-4"
style={{
color: 'var(--color-brand-gray-muted)',
fontFamily: 'var(--font-family-brand)'
}}
>
Deep domain knowledge spanning strategic consulting, digital transformation, operational excellence, and change management across multiple industry verticals.
</p>
<p
className="text-base leading-relaxed"
style={{
color: 'var(--color-brand-gray-muted)',
fontFamily: 'var(--font-family-brand)'
}}
>
Our multidisciplinary team combines analytical rigor with creative problem-solving to deliver solutions that are both innovative and pragmatic.
</p>
</div>
</div>
{/* CTA Section */}
<div className="text-center mt-16">
<button
className="brand-button"
style={{
backgroundColor: 'var(--color-brand-accent)',
color: 'var(--color-brand-black)',
border: 'none',
borderRadius: '10px',
padding: '1rem 2rem',
fontSize: '1.125rem',
fontWeight: '600',
fontFamily: 'var(--font-family-brand)',
cursor: 'pointer',
transition: 'all 0.3s ease',
display: 'inline-flex',
alignItems: 'center',
gap: '0.5rem'
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = 'var(--color-brand-primary)';
e.currentTarget.style.color = 'white';
e.currentTarget.style.transform = 'translateY(-2px)';
e.currentTarget.style.boxShadow = '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = 'var(--color-brand-accent)';
e.currentTarget.style.color = 'var(--color-brand-black)';
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.boxShadow = '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)';
}}
>
Learn More About Our Story
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
>
<path d="M5 12h14"/>
<path d="M12 5l7 7-7 7"/>
</svg>
</button>
</div>
</div>
</section>
);
}

743
src/components/Articles.tsx Normal file
View File

@@ -0,0 +1,743 @@
import React, { useState, useRef, useEffect } from 'react';
import { Button } from './ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from './ui/card';
import { Badge } from './ui/badge';
import { Input } from './ui/input';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
import { ImageWithFallback } from './figma/ImageWithFallback';
import { PrimaryCTAButton } from './PrimaryCTAButton';
import { navigateTo } from './Router';
import {
Search,
Calendar,
User,
ArrowRight,
BookOpen,
Filter,
Grid,
List,
SortAsc,
Clock,
Eye,
Star,
ChevronLeft,
ChevronRight,
X
} from 'lucide-react';
// Mock articles data
const articles = [
{
id: '1',
slug: 'future-of-leadership-development',
title: 'The Future of Leadership Development: Trends and Innovations',
excerpt: 'Explore emerging trends in leadership development and how organizations are adapting to create more effective leaders for tomorrow\'s challenges.',
content: 'Leadership development is evolving rapidly in response to changing workplace dynamics, technological advances, and new generations entering the workforce...',
author: 'Sarah Johnson',
authorTitle: 'Senior Leadership Consultant',
authorAvatar: 'https://images.unsplash.com/photo-1494790108755-2616b612b47c?w=150&h=150&fit=crop&crop=face',
date: '2024-02-20',
readTime: '8 min read',
category: 'Leadership Development',
tags: ['Future of Work', 'Leadership Trends', 'Innovation', 'Strategy'],
thumbnail: 'https://images.unsplash.com/photo-1552664730-d307ca884978?w=600&h=400&fit=crop',
featured: true,
views: '2.4k',
likes: 45
},
{
id: '2',
slug: 'emotional-intelligence-in-leadership',
title: 'Emotional Intelligence: The Key to Effective Leadership',
excerpt: 'Discover how emotional intelligence impacts leadership effectiveness and learn practical strategies to develop your EQ.',
content: 'Emotional intelligence has become increasingly recognized as a critical factor in leadership success...',
author: 'Dr. Michael Chen',
authorTitle: 'Executive Coach',
authorAvatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=150&h=150&fit=crop&crop=face',
date: '2024-02-18',
readTime: '6 min read',
category: 'Personal Development',
tags: ['Emotional Intelligence', 'Leadership Skills', 'Communication', 'Self-Awareness'],
thumbnail: 'https://images.unsplash.com/photo-1559027615-cd4628902d4a?w=600&h=400&fit=crop',
featured: true,
views: '1.8k',
likes: 32
},
{
id: '3',
slug: 'building-high-performing-teams',
title: 'Building High-Performing Teams: A Leader\'s Guide',
excerpt: 'Learn the essential strategies for creating and maintaining high-performing teams that deliver exceptional results.',
content: 'High-performing teams don\'t happen by accident. They require intentional leadership, clear purpose, and the right environment...',
author: 'Lisa Rodriguez',
authorTitle: 'Team Development Specialist',
authorAvatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=150&h=150&fit=crop&crop=face',
date: '2024-02-15',
readTime: '10 min read',
category: 'Team Development',
tags: ['Team Building', 'Performance', 'Collaboration', 'Leadership'],
thumbnail: 'https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=600&h=400&fit=crop',
featured: false,
views: '3.1k',
likes: 58
},
{
id: '4',
slug: 'digital-transformation-leadership',
title: 'Leading Digital Transformation: A Strategic Approach',
excerpt: 'Navigate the complexities of digital transformation with proven leadership strategies and best practices.',
content: 'Digital transformation is reshaping industries and organizations worldwide. Successful transformation requires strong leadership...',
author: 'David Park',
authorTitle: 'Digital Strategy Consultant',
authorAvatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=150&h=150&fit=crop&crop=face',
date: '2024-02-12',
readTime: '12 min read',
category: 'Digital Transformation',
tags: ['Digital Strategy', 'Change Management', 'Technology', 'Innovation'],
thumbnail: 'https://images.unsplash.com/photo-1560472355-536de3962603?w=600&h=400&fit=crop',
featured: false,
views: '2.7k',
likes: 41
},
{
id: '5',
slug: 'crisis-leadership-strategies',
title: 'Crisis Leadership: Navigating Uncertainty with Confidence',
excerpt: 'Master the art of crisis leadership and learn how to guide your organization through challenging times.',
content: 'Crisis situations test the mettle of leaders and reveal the true strength of an organization...',
author: 'Jennifer Adams',
authorTitle: 'Crisis Management Expert',
authorAvatar: 'https://images.unsplash.com/photo-1580489944761-15a19d654956?w=150&h=150&fit=crop&crop=face',
date: '2024-02-10',
readTime: '9 min read',
category: 'Crisis Management',
tags: ['Crisis Leadership', 'Risk Management', 'Decision Making', 'Communication'],
thumbnail: 'https://images.unsplash.com/photo-1584697964358-3e14ca57658b?w=600&h=400&fit=crop',
featured: false,
views: '1.9k',
likes: 35
},
{
id: '6',
slug: 'sustainable-leadership-practices',
title: 'Sustainable Leadership: Building for the Long Term',
excerpt: 'Explore sustainable leadership practices that create lasting value for organizations and stakeholders.',
content: 'Sustainable leadership goes beyond short-term gains to create lasting value for all stakeholders...',
author: 'Robert Kim',
authorTitle: 'Sustainability Consultant',
authorAvatar: 'https://images.unsplash.com/photo-1560250097-0b93528c311a?w=150&h=150&fit=crop&crop=face',
date: '2024-02-08',
readTime: '7 min read',
category: 'Strategy',
tags: ['Sustainability', 'ESG', 'Long-term Thinking', 'Stakeholder Value'],
thumbnail: 'https://images.unsplash.com/photo-1542601906990-b4d3fb778b09?w=600&h=400&fit=crop',
featured: false,
views: '1.5k',
likes: 28
}
];
export function Articles() {
const [searchTerm, setSearchTerm] = useState('');
const [selectedCategory, setSelectedCategory] = useState('All Categories');
const [selectedAuthor, setSelectedAuthor] = useState('All Authors');
const [selectedReadTime, setSelectedReadTime] = useState('All Read Times');
const [selectedDateRange, setSelectedDateRange] = useState('All Time');
const [selectedTopic, setSelectedTopic] = useState('All Topics');
const [sortBy, setSortBy] = useState('Most Recent');
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
const [currentPage, setCurrentPage] = useState(1);
const articlesPerPage = 6;
// Get unique values for filters
const categories = ['All Categories', ...Array.from(new Set(articles.map(article => article.category)))];
const authors = ['All Authors', ...Array.from(new Set(articles.map(article => article.author)))];
const readTimes = ['All Read Times', 'Under 5 min', '5-10 min', 'Over 10 min'];
const dateRanges = ['All Time', 'Last 7 days', 'Last 30 days', 'Last 3 months'];
const allTags = Array.from(new Set(articles.flatMap(article => article.tags)));
const sortOptions = [
{ value: 'Most Recent', label: 'Most Recent' },
{ value: 'oldest', label: 'Oldest First' },
{ value: 'title', label: 'Title A-Z' },
{ value: 'readTime', label: 'Read Time' },
{ value: 'popular', label: 'Most Popular' }
];
// Filter and sort articles
const filteredArticles = articles.filter(article => {
const matchesSearch = article.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
article.excerpt.toLowerCase().includes(searchTerm.toLowerCase()) ||
article.author.toLowerCase().includes(searchTerm.toLowerCase()) ||
article.tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase()));
const matchesCategory = selectedCategory === 'All Categories' || article.category === selectedCategory;
const matchesAuthor = selectedAuthor === 'All Authors' || article.author === selectedAuthor;
// Read time filter
const readTimeMinutes = parseInt(article.readTime);
const matchesReadTime = selectedReadTime === 'All Read Times' ||
(selectedReadTime === 'Under 5 min' && readTimeMinutes < 5) ||
(selectedReadTime === '5-10 min' && readTimeMinutes >= 5 && readTimeMinutes <= 10) ||
(selectedReadTime === 'Over 10 min' && readTimeMinutes > 10);
// Date range filter
const articleDate = new Date(article.date);
const now = new Date();
const matchesDateRange = selectedDateRange === 'All Time' ||
(selectedDateRange === 'Last 7 days' && (now.getTime() - articleDate.getTime()) <= 7 * 24 * 60 * 60 * 1000) ||
(selectedDateRange === 'Last 30 days' && (now.getTime() - articleDate.getTime()) <= 30 * 24 * 60 * 60 * 1000) ||
(selectedDateRange === 'Last 3 months' && (now.getTime() - articleDate.getTime()) <= 90 * 24 * 60 * 60 * 1000);
// Topic filter
const matchesTopic = selectedTopic === 'All Topics' ||
article.tags.includes(selectedTopic);
return matchesSearch && matchesCategory && matchesAuthor && matchesReadTime && matchesDateRange && matchesTopic;
}).sort((a, b) => {
switch (sortBy) {
case 'Most Recent':
return new Date(b.date).getTime() - new Date(a.date).getTime();
case 'oldest':
return new Date(a.date).getTime() - new Date(b.date).getTime();
case 'title':
return a.title.localeCompare(b.title);
case 'readTime':
return parseInt(a.readTime) - parseInt(b.readTime);
case 'popular':
return parseInt(b.views) - parseInt(a.views);
default:
return 0;
}
});
// Paginate results
const totalPages = Math.ceil(filteredArticles.length / articlesPerPage);
const startIndex = (currentPage - 1) * articlesPerPage;
const currentArticles = filteredArticles.slice(startIndex, startIndex + articlesPerPage);
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
};
const clearAllFilters = () => {
setSearchTerm('');
setSelectedCategory('All Categories');
setSelectedAuthor('All Authors');
setSelectedReadTime('All Read Times');
setSelectedDateRange('All Time');
setSelectedTopic('All Topics');
setSortBy('Most Recent');
};
const hasActiveFilters = searchTerm ||
selectedCategory !== 'All Categories' ||
selectedAuthor !== 'All Authors' ||
selectedReadTime !== 'All Read Times' ||
selectedDateRange !== 'All Time' ||
selectedTopic !== 'All Topics';
return (
<div style={{ backgroundColor: '#FFFFFF' }}>
{/* Hero Section */}
<section className="relative py-28 overflow-hidden">
<div className="absolute inset-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1481627834876-b7833e8f5570?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxhcnRpY2xlJTIwYmxvZyUyMGNvbnRlbnQlMjBrbm93bGVkZ2V8ZW58MXx8fHwxNzU1ODU0Mjg2fDA&ixlib=rb-4.1.0&q=80&w=1080"
alt="Knowledge and insights through articles and research"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-black/60" />
</div>
<div className="relative section-margin-x">
<div className="max-w-4xl mx-auto text-center">
<div className="branded-tag-system-white mb-6 justify-center">
<div className="dot"></div>
<span className="text">INSIGHTS & KNOWLEDGE</span>
</div>
<h1 className="text-h1-white mb-6">
Articles & Research
</h1>
<p className="text-body-lg-white mb-8 max-w-2xl mx-auto">
Discover cutting-edge insights, research findings, and expert perspectives on leadership development, management strategies, and organizational excellence.
</p>
</div>
</div>
{/* Statistics Strip */}
<div className="absolute bottom-0 left-0 right-0">
<div className="bg-black/80 backdrop-blur-sm px-8 py-6">
<div className="section-margin-x">
<div className="grid grid-cols-3 gap-8 text-center">
<div>
<div className="text-h2-white mb-2">{articles.length}+</div>
<div className="text-small-white">Expert Articles</div>
</div>
<div>
<div className="text-h2-white mb-2">{categories.length - 1}</div>
<div className="text-small-white">Categories</div>
</div>
<div>
<div className="text-h2-white mb-2">25,400</div>
<div className="text-small-white">Total Reads</div>
</div>
</div>
</div>
</div>
</div>
</section>
{/* Search and Controls Section */}
<section className="py-8" style={{ backgroundColor: '#FFFFFF' }}>
<div className="section-margin-x">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6">
{/* Search Bar */}
<div className="relative max-w-md flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
<Input
type="text"
placeholder="Search articles, authors, topics..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-10 pr-4 py-3 text-body rounded-lg border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all duration-200 w-full bg-gray-50"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
height: '48px'
}}
/>
</div>
{/* View Toggle and Sort */}
<div className="flex items-center gap-4">
<div className="flex items-center border border-gray-300 rounded-lg overflow-hidden">
<button
onClick={() => setViewMode('grid')}
className={`p-2 transition-colors ${
viewMode === 'grid'
? 'text-white'
: 'bg-white text-gray-600 hover:bg-gray-50'
}`}
style={{
backgroundColor: viewMode === 'grid' ? 'var(--color-primary)' : undefined
}}
aria-label="Grid view"
>
<Grid className="w-4 h-4" />
</button>
<button
onClick={() => setViewMode('list')}
className={`p-2 transition-colors ${
viewMode === 'list'
? 'text-white'
: 'bg-white text-gray-600 hover:bg-gray-50'
}`}
style={{
backgroundColor: viewMode === 'list' ? 'var(--color-primary)' : undefined
}}
aria-label="List view"
>
<List className="w-4 h-4" />
</button>
</div>
<Select value={sortBy} onValueChange={setSortBy}>
<SelectTrigger className="w-40 text-body">
<SelectValue placeholder="Sort by" />
</SelectTrigger>
<SelectContent>
{sortOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
</div>
</section>
{/* Main Content Section with Sidebar */}
<section className="pb-16" style={{ backgroundColor: '#FFFFFF' }}>
<div className="section-margin-x">
<div className="grid grid-cols-12 gap-8">
{/* Left Sidebar - Sticky Filters */}
<div className="col-span-12 lg:col-span-3">
<div className="sticky top-4">
<Card className="bg-white border border-gray-200 rounded-lg shadow-md overflow-hidden">
{/* Filter Header */}
<div className="bg-gray-50 px-4 py-3 border-b border-gray-200">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<div className="p-1.5 rounded-md" style={{ backgroundColor: 'rgba(4, 4, 91, 0.1)' }}>
<Filter className="w-3.5 h-3.5" style={{ color: 'var(--color-primary)' }} />
</div>
<h3 className="text-body font-semibold text-gray-800">
Filters
</h3>
</div>
{hasActiveFilters && (
<Button
variant="ghost"
size="sm"
onClick={clearAllFilters}
className="text-xs px-2 py-1 rounded-md transition-colors filter-clear-btn"
>
<X className="w-3 h-3 mr-1" />
Clear
</Button>
)}
</div>
</div>
{/* Filter Content */}
<div className="p-4">
<div className="space-y-4">
{/* Category Filter */}
<div className="filter-section">
<label className="block text-small mb-2 font-medium text-gray-700">
Category
</label>
<Select value={selectedCategory} onValueChange={setSelectedCategory}>
<SelectTrigger className="w-full text-small h-9 border-gray-300 hover:border-gray-400 transition-colors" style={{ '&:focus': { borderColor: 'var(--color-primary)' } }}>
<SelectValue placeholder="All Categories" />
</SelectTrigger>
<SelectContent>
{categories.map((category) => (
<SelectItem key={category} value={category} className="text-small">
{category}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{/* Author Filter */}
<div className="filter-section">
<label className="block text-small mb-2 font-medium text-gray-700">
Author
</label>
<Select value={selectedAuthor} onValueChange={setSelectedAuthor}>
<SelectTrigger className="w-full text-small h-9 border-gray-300 hover:border-gray-400 transition-colors" style={{ '&:focus': { borderColor: 'var(--color-primary)' } }}>
<SelectValue placeholder="All Authors" />
</SelectTrigger>
<SelectContent>
{authors.map((author) => (
<SelectItem key={author} value={author} className="text-small">
{author}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{/* Read Time Filter */}
<div className="filter-section">
<label className="block text-small mb-2 font-medium text-gray-700">
Read Time
</label>
<Select value={selectedReadTime} onValueChange={setSelectedReadTime}>
<SelectTrigger className="w-full text-small h-9 border-gray-300 hover:border-gray-400 transition-colors" style={{ '&:focus': { borderColor: 'var(--color-primary)' } }}>
<SelectValue placeholder="All Read Times" />
</SelectTrigger>
<SelectContent>
{readTimes.map((readTime) => (
<SelectItem key={readTime} value={readTime} className="text-small">
{readTime}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{/* Date Range Filter */}
<div className="filter-section">
<label className="block text-small mb-2 font-medium text-gray-700">
Date Range
</label>
<Select value={selectedDateRange} onValueChange={setSelectedDateRange}>
<SelectTrigger className="w-full text-small h-9 border-gray-300 hover:border-gray-400 transition-colors" style={{ '&:focus': { borderColor: 'var(--color-primary)' } }}>
<SelectValue placeholder="All Time" />
</SelectTrigger>
<SelectContent>
{dateRanges.map((dateRange) => (
<SelectItem key={dateRange} value={dateRange} className="text-small">
{dateRange}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{/* Topics Filter */}
<div className="filter-section">
<label className="block text-small mb-2 font-medium text-gray-700">
Topic
</label>
<Select value={selectedTopic} onValueChange={setSelectedTopic}>
<SelectTrigger className="w-full text-small h-9 border-gray-300 hover:border-gray-400 transition-colors" style={{ '&:focus': { borderColor: 'var(--color-primary)' } }}>
<SelectValue placeholder="All Topics" />
</SelectTrigger>
<SelectContent>
<SelectItem value="All Topics" className="text-small">
All Topics
</SelectItem>
{allTags.map((tag) => (
<SelectItem key={tag} value={tag} className="text-small">
{tag}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
</div>
</Card>
</div>
</div>
{/* Right Content Area - Scrollable Articles */}
<div className="col-span-12 lg:col-span-9">
<div className="mb-4 text-small text-muted">
Showing {currentArticles.length} of {filteredArticles.length} articles
</div>
{/* Articles Results */}
{currentArticles.length === 0 ? (
<div className="text-center py-12">
<p className="text-body-lg text-muted">
No articles found matching your criteria.
</p>
</div>
) : (
<>
{/* Grid View */}
{viewMode === 'grid' && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{currentArticles.map((article) => (
<Card
key={article.id}
className="overflow-hidden hover:shadow-lg transition-all duration-300 cursor-pointer group"
onClick={() => navigateTo(`/learning/articles/${article.slug}`)}
>
<div className="aspect-video w-full bg-gray-100 overflow-hidden relative">
<ImageWithFallback
src={article.thumbnail}
alt={article.title}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
/>
{article.featured && (
<div className="absolute top-4 right-4">
<Badge
variant="secondary"
className="bg-yellow-100 text-yellow-800 border-yellow-200"
>
Featured
</Badge>
</div>
)}
</div>
<CardContent className="p-6">
<div className="flex items-center gap-2 mb-3">
<Badge variant="outline" className="text-small">
{article.category}
</Badge>
<span className="text-small text-muted">{article.readTime}</span>
</div>
<h3 className="text-h4 mb-3 group-hover:text-blue-600 transition-colors line-clamp-2">
{article.title}
</h3>
<p className="text-small text-muted mb-4 line-clamp-3">
{article.excerpt}
</p>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<ImageWithFallback
src={article.authorAvatar}
alt={article.author}
className="w-6 h-6 rounded-full object-cover"
/>
<span className="text-small">{article.author}</span>
</div>
<div className="text-small text-muted">
{formatDate(article.date)}
</div>
</div>
</CardContent>
</Card>
))}
</div>
)}
{/* List View */}
{viewMode === 'list' && (
<div className="space-y-6">
{currentArticles.map((article) => (
<Card
key={article.id}
className="overflow-hidden hover:shadow-lg transition-all duration-300 cursor-pointer group"
onClick={() => navigateTo(`/learning/articles/${article.slug}`)}
>
<div className="flex flex-col md:flex-row">
<div className="md:w-80 h-48 md:h-auto bg-gray-100 overflow-hidden relative flex-shrink-0">
<ImageWithFallback
src={article.thumbnail}
alt={article.title}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
/>
{article.featured && (
<div className="absolute top-2 right-2">
<Badge
variant="secondary"
className="bg-yellow-100 text-yellow-800 border-yellow-200 text-xs"
>
Featured
</Badge>
</div>
)}
</div>
<div className="flex-1 p-6">
<div className="flex justify-between items-start">
<div className="flex-1">
<div className="flex items-center gap-2 mb-2">
<Badge variant="outline" className="text-small">
{article.category}
</Badge>
<span className="text-small text-muted">{article.readTime}</span>
<div className="flex items-center gap-1 text-small text-muted">
<Eye className="w-3 h-3" />
<span>{article.views}</span>
</div>
</div>
<h3 className="text-h4 mb-2 group-hover:text-blue-600 transition-colors">
{article.title}
</h3>
<p className="text-body text-muted mb-3">
{article.excerpt}
</p>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<ImageWithFallback
src={article.authorAvatar}
alt={article.author}
className="w-6 h-6 rounded-full object-cover"
/>
<div>
<span className="text-small font-medium">{article.author}</span>
<span className="text-small text-muted ml-1"> {article.authorTitle}</span>
</div>
</div>
<div className="text-small text-muted">
{formatDate(article.date)}
</div>
</div>
</div>
</div>
</div>
</div>
</Card>
))}
</div>
)}
{/* Pagination */}
{totalPages > 1 && (
<div className="flex items-center justify-center gap-4 mt-12">
<Button
variant="outline"
onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))}
disabled={currentPage === 1}
className="text-body"
>
<ChevronLeft className="w-4 h-4 mr-2" />
Previous
</Button>
<span className="text-body">
Page {currentPage} of {totalPages}
</span>
<Button
variant="outline"
onClick={() => setCurrentPage(prev => Math.min(prev + 1, totalPages))}
disabled={currentPage === totalPages}
className="text-body"
>
Next
<ChevronRight className="w-4 h-4 ml-2" />
</Button>
</div>
)}
</>
)}
</div>
</div>
</div>
</section>
{/* CTA Banner Section */}
<section className="relative h-[700px] overflow-hidden">
<div className="absolute inset-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1753613648191-4771cf76f034?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxvbmxpbmUlMjBsZWFybmluZyUyMGRpZ2l0YWwlMjBlZHVjYXRpb258ZW58MXx8fHwxNzU1ODU0Mjc1fDA&ixlib=rb-4.1.0&q=80&w=1080"
alt="Online learning and digital education environment"
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)'
}}
>
<div className="branded-tag-system-next-steps mb-6 justify-start">
<div className="dot"></div>
<span className="text">NEXT STEPS</span>
</div>
<h2 className="text-h2-white mb-8">
Ready to explore more insights?
<span
className="italic"
style={{ color: 'var(--color-brand-accent)' }}
>
{" "}Discover{" "}
</span>
our complete library of leadership resources.
</h2>
<PrimaryCTAButton
text="Browse All Resources"
onClick={() => navigateTo('/learning/articles')}
ariaLabel="Browse all leadership articles and resources"
className="cta-banner-yellow mb-6"
/>
<p className="text-body-white opacity-90">
Access cutting-edge research, expert insights, and practical guidance to accelerate your leadership journey and organizational success.
</p>
</div>
</div>
</section>
</div>
);
}

View File

@@ -0,0 +1,54 @@
import React, { createContext, useContext, useState, ReactNode } from 'react';
interface User {
name: string;
email: string;
corporateName: string;
avatar?: string;
}
interface AuthContextType {
user: User | null;
isAuthenticated: boolean;
signIn: (user: User) => void;
signOut: () => void;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
interface AuthProviderProps {
children: ReactNode;
}
export function AuthProvider({ children }: AuthProviderProps) {
const [user, setUser] = useState<User | null>(null);
const signIn = (userData: User) => {
setUser(userData);
};
const signOut = () => {
setUser(null);
};
const value: AuthContextType = {
user,
isAuthenticated: !!user,
signIn,
signOut,
};
return (
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
}

View File

@@ -0,0 +1,815 @@
import React, { useState, useEffect } from 'react';
import { Button } from './ui/button';
import { Card, CardContent } from './ui/card';
import { Badge } from './ui/badge';
import { Avatar, AvatarFallback, AvatarImage } from './ui/avatar';
import { navigateTo } from './Router';
import { ImageWithFallback } from './figma/ImageWithFallback';
import { CTABannerSection } from './CTABannerSection';
import { useCart } from './CartContext';
import {
Calendar,
Clock,
ArrowRight,
ChevronUp,
Share2,
Bookmark,
Twitter,
Facebook,
Linkedin,
Link,
Heart,
Eye,
BookOpen,
ArrowLeft,
Star,
MessageCircle,
Users,
TrendingUp,
Award
} from 'lucide-react';
interface BlogPost {
id: string;
title: string;
slug: string;
excerpt: string;
content: string;
author: string;
authorBio: string;
authorImage: string;
publishedDate: string;
updatedDate?: string;
readTime: string;
views: number;
likes: number;
category: string;
tags: string[];
image: string;
featured: boolean;
}
interface RelatedPost {
id: string;
title: string;
slug: string;
excerpt: string;
author: string;
publishedDate: string;
readTime: string;
category: string;
image: string;
}
interface BlogDetailProps {
params?: {
slug?: string;
};
}
// Articles data synced with Articles component for consistency
const articlesData = [
{
id: 1,
title: "The Future of Leadership Development: Trends and Innovations",
slug: "future-of-leadership-development",
excerpt: "Explore emerging trends in leadership development and how organizations are adapting to create more effective leaders for tomorrow's challenges.",
content: `
<p>Leadership development is evolving rapidly in response to changing workplace dynamics, technological advances, and new generations entering the workforce. Organizations worldwide are reimagining their approach to cultivating leadership talent.</p>
<h2>Emerging Trends in Leadership Development</h2>
<p>Several key trends are reshaping how we develop leaders:</p>
<ul>
<li><strong>Personalized Learning Paths:</strong> Customized development programs based on individual strengths, weaknesses, and career aspirations.</li>
<li><strong>Digital-First Delivery:</strong> Virtual reality simulations, AI-powered coaching, and mobile learning platforms.</li>
<li><strong>Continuous Feedback Culture:</strong> Real-time performance insights and ongoing mentorship relationships.</li>
<li><strong>Cross-Functional Exposure:</strong> Leaders developing broader business acumen through diverse role experiences.</li>
</ul>
<h2>Innovation in Leadership Development</h2>
<p>Organizations are experimenting with new methodologies and technologies to create more effective development experiences.</p>
<blockquote>
<p>"The future of leadership development lies in creating adaptive, resilient leaders who can thrive in uncertainty while driving innovation and human connection."</p>
<cite>— Sarah Johnson, Senior Leadership Consultant</cite>
</blockquote>
<h3>Technology-Enhanced Learning</h3>
<p>From virtual reality leadership scenarios to AI-powered coaching platforms, technology is creating immersive development experiences that accelerate learning and skill application.</p>
<p>The future belongs to leaders who embrace continuous learning, demonstrate emotional intelligence, and can navigate complexity with confidence and clarity.</p>
`,
author: "Sarah Johnson",
authorTitle: "Senior Leadership Consultant",
authorBio: "Sarah Johnson is a Senior Leadership Consultant with over 15 years of experience in organizational development and talent management. She specializes in designing innovative leadership programs for Fortune 500 companies.",
authorImage: "https://images.unsplash.com/photo-1494790108755-2616b612b47c?w=150&h=150&fit=crop",
publishedDate: "2024-02-20",
readTime: "8 min read",
category: "Leadership Development",
tags: ["Future of Work", "Leadership Trends", "Innovation", "Strategy"],
image: "https://images.unsplash.com/photo-1552664730-d307ca884978?w=1200&h=600&fit=crop",
featured: true,
views: 2400,
likes: 45
},
{
id: 2,
title: "Emotional Intelligence: The Key to Effective Leadership",
slug: "emotional-intelligence-in-leadership",
excerpt: "Discover how emotional intelligence impacts leadership effectiveness and learn practical strategies to develop your EQ.",
content: `
<p>Emotional intelligence has become increasingly recognized as a critical factor in leadership success. Research consistently shows that leaders with high emotional intelligence create more engaged teams, drive better business results, and build more resilient organizations.</p>
<h2>The Four Domains of Emotional Intelligence</h2>
<p>Daniel Goleman's framework identifies four key domains:</p>
<ul>
<li><strong>Self-Awareness:</strong> Understanding your emotions, strengths, and limitations.</li>
<li><strong>Self-Management:</strong> Effectively managing your emotions and behaviors.</li>
<li><strong>Social Awareness:</strong> Reading others' emotions and understanding group dynamics.</li>
<li><strong>Relationship Management:</strong> Influencing and managing relationships effectively.</li>
</ul>
<blockquote>
<p>"IQ gets you hired, but EQ gets you promoted. In leadership roles, emotional intelligence becomes the differentiator between good managers and great leaders."</p>
<cite>— Dr. Michael Chen, Executive Coach</cite>
</blockquote>
<h2>Developing Your Emotional Intelligence</h2>
<p>Unlike IQ, emotional intelligence can be developed throughout your career through deliberate practice, feedback, and reflection.</p>
<h3>Practical Strategies</h3>
<p>Start with mindfulness practices, seek feedback from trusted colleagues, and practice active listening in all your interactions. The investment in developing emotional intelligence pays dividends in leadership effectiveness.</p>
`,
author: "Dr. Michael Chen",
authorTitle: "Executive Coach",
authorBio: "Dr. Michael Chen is an Executive Coach and organizational psychologist with expertise in emotional intelligence and leadership development. He has coached hundreds of senior executives across various industries.",
authorImage: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=150&h=150&fit=crop",
publishedDate: "2024-02-18",
readTime: "6 min read",
category: "Personal Development",
tags: ["Emotional Intelligence", "Leadership Skills", "Communication", "Self-Awareness"],
image: "https://images.unsplash.com/photo-1559027615-cd4628902d4a?w=1200&h=600&fit=crop",
featured: true,
views: 1800,
likes: 32
},
{
id: 3,
title: "Building High-Performing Teams: A Leader's Guide",
slug: "building-high-performing-teams",
excerpt: "Learn the essential strategies for creating and maintaining high-performing teams that deliver exceptional results.",
content: `
<p>High-performing teams don't happen by accident. They require intentional leadership, clear purpose, and the right environment to thrive. Understanding the key elements that drive team performance is essential for any leader.</p>
<h2>Characteristics of High-Performing Teams</h2>
<p>Research identifies several common traits among exceptional teams:</p>
<ul>
<li><strong>Shared Purpose:</strong> Clear understanding of goals and how individual contributions matter.</li>
<li><strong>Psychological Safety:</strong> Environment where team members feel safe to take risks and share ideas.</li>
<li><strong>Diverse Perspectives:</strong> Variety of backgrounds, skills, and thinking styles.</li>
<li><strong>Effective Communication:</strong> Open, honest, and constructive dialogue.</li>
</ul>
<h2>Building Team Performance</h2>
<p>Creating high-performing teams requires deliberate effort in team formation, skill development, and culture building.</p>
<blockquote>
<p>"Great teams are not created by chance. They are the result of intentional leadership that focuses on both individual development and collective excellence."</p>
<cite>— Lisa Rodriguez, Team Development Specialist</cite>
</blockquote>
<p>The journey to high performance requires patience, consistency, and a commitment to continuous improvement at both individual and team levels.</p>
`,
author: "Lisa Rodriguez",
authorTitle: "Team Development Specialist",
authorBio: "Lisa Rodriguez is a Team Development Specialist with over 12 years of experience helping organizations build high-performing teams. She specializes in team dynamics, collaboration, and performance optimization.",
authorImage: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=150&h=150&fit=crop",
publishedDate: "2024-02-15",
readTime: "10 min read",
category: "Team Development",
tags: ["Team Building", "Performance", "Collaboration", "Leadership"],
image: "https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=1200&h=600&fit=crop",
featured: false,
views: 3100,
likes: 58
},
{
id: 4,
title: "Leading Digital Transformation: A Strategic Approach",
slug: "digital-transformation-leadership",
excerpt: "Navigate the complexities of digital transformation with proven leadership strategies and best practices.",
content: `
<p>Digital transformation is reshaping industries and organizations worldwide. Successful transformation requires strong leadership that can balance technological innovation with human-centered change management.</p>
<h2>The Leadership Challenge</h2>
<p>Digital transformation is as much about people and culture as it is about technology. Leaders must navigate resistance, build new capabilities, and maintain business performance during the transition.</p>
<h3>Key Success Factors</h3>
<ul>
<li><strong>Vision Clarity:</strong> Articulating a compelling future state that motivates change.</li>
<li><strong>Change Management:</strong> Supporting people through the transformation journey.</li>
<li><strong>Technology Integration:</strong> Selecting and implementing the right solutions.</li>
<li><strong>Cultural Evolution:</strong> Building a culture that embraces digital innovation.</li>
</ul>
<blockquote>
<p>"Digital transformation succeeds when leaders focus on transforming people and processes, not just implementing technology."</p>
<cite>— David Park, Digital Strategy Consultant</cite>
</blockquote>
<p>The most successful digital transformations are led by leaders who understand that technology enables transformation, but people make it happen.</p>
`,
author: "David Park",
authorTitle: "Digital Strategy Consultant",
authorBio: "David Park is a Digital Strategy Consultant with extensive experience in leading large-scale digital transformations across multiple industries. He specializes in technology strategy and organizational change.",
authorImage: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=150&h=150&fit=crop",
publishedDate: "2024-02-12",
readTime: "12 min read",
category: "Digital Transformation",
tags: ["Digital Strategy", "Change Management", "Technology", "Innovation"],
image: "https://images.unsplash.com/photo-1560472355-536de3962603?w=1200&h=600&fit=crop",
featured: false,
views: 2700,
likes: 41
},
{
id: 5,
title: "Crisis Leadership: Navigating Uncertainty with Confidence",
slug: "crisis-leadership-strategies",
excerpt: "Master the art of crisis leadership and learn how to guide your organization through challenging times.",
content: `
<p>Crisis situations test the mettle of leaders and reveal the true strength of an organization. Effective crisis leadership requires a unique combination of decisive action, clear communication, and emotional resilience.</p>
<h2>Principles of Crisis Leadership</h2>
<p>Successful crisis leaders follow key principles that help them navigate uncertainty:</p>
<ul>
<li><strong>Stay Calm Under Pressure:</strong> Maintaining composure to make clear-headed decisions.</li>
<li><strong>Communicate Transparently:</strong> Providing honest, frequent updates to all stakeholders.</li>
<li><strong>Act Decisively:</strong> Making tough decisions quickly with available information.</li>
<li><strong>Show Empathy:</strong> Understanding and addressing the human impact of the crisis.</li>
</ul>
<h2>Building Crisis Resilience</h2>
<p>The best time to prepare for a crisis is before it happens. Organizations need to build crisis response capabilities and leadership resilience proactively.</p>
<blockquote>
<p>"Crisis leadership is not about having all the answers—it's about maintaining trust and direction when everything seems uncertain."</p>
<cite>— Jennifer Adams, Crisis Management Expert</cite>
</blockquote>
<p>Leaders who excel in crisis situations combine strategic thinking with human compassion, creating stability in the midst of chaos.</p>
`,
author: "Jennifer Adams",
authorTitle: "Crisis Management Expert",
authorBio: "Jennifer Adams is a Crisis Management Expert with over 20 years of experience helping organizations navigate complex crises. She has advised government agencies and Fortune 500 companies on crisis preparedness and response.",
authorImage: "https://images.unsplash.com/photo-1580489944761-15a19d654956?w=150&h=150&fit=crop",
publishedDate: "2024-02-10",
readTime: "9 min read",
category: "Crisis Management",
tags: ["Crisis Leadership", "Risk Management", "Decision Making", "Communication"],
image: "https://images.unsplash.com/photo-1584697964358-3e14ca57658b?w=1200&h=600&fit=crop",
featured: false,
views: 1900,
likes: 35
},
{
id: 6,
title: "Sustainable Leadership: Building for the Long Term",
slug: "sustainable-leadership-practices",
excerpt: "Explore sustainable leadership practices that create lasting value for organizations and stakeholders.",
content: `
<p>Sustainable leadership goes beyond short-term gains to create lasting value for all stakeholders. It requires a long-term perspective that balances profit with purpose, growth with responsibility.</p>
<h2>The Sustainability Imperative</h2>
<p>Modern leaders must navigate increasing expectations for environmental and social responsibility while maintaining business performance.</p>
<h3>Key Elements of Sustainable Leadership</h3>
<ul>
<li><strong>Stakeholder Focus:</strong> Considering the needs of all stakeholders, not just shareholders.</li>
<li><strong>Environmental Stewardship:</strong> Making decisions that consider environmental impact.</li>
<li><strong>Social Responsibility:</strong> Contributing positively to communities and society.</li>
<li><strong>Economic Viability:</strong> Ensuring long-term business sustainability.</li>
</ul>
<blockquote>
<p>"Sustainable leadership is about creating value that endures beyond any individual leader's tenure, building organizations that thrive for generations."</p>
<cite>— Robert Kim, Sustainability Consultant</cite>
</blockquote>
<p>The future belongs to leaders who can balance multiple bottom lines—profit, people, and planet—while driving innovation and growth.</p>
`,
author: "Robert Kim",
authorTitle: "Sustainability Consultant",
authorBio: "Robert Kim is a Sustainability Consultant specializing in ESG strategy and sustainable business practices. He has helped numerous organizations integrate sustainability into their core business strategy.",
authorImage: "https://images.unsplash.com/photo-1560250097-0b93528c311a?w=150&h=150&fit=crop",
publishedDate: "2024-02-08",
readTime: "7 min read",
category: "Strategy",
tags: ["Sustainability", "ESG", "Long-term Thinking", "Stakeholder Value"],
image: "https://images.unsplash.com/photo-1542601906990-b4d3fb778b09?w=1200&h=600&fit=crop",
featured: false,
views: 1500,
likes: 28
}
];
// Function to get blog post by slug
const getBlogPostBySlug = (slug: string): BlogPost => {
const article = articlesData.find(article => article.slug === slug);
if (!article) {
return {
id: '1',
title: 'Article Not Found',
slug: 'not-found',
excerpt: `The requested article "${slug}" could not be found.`,
content: `
<p>We're sorry, but the article you're looking for could not be found. It may have been moved or removed.</p>
<p>Here are some available articles you can read:</p>
<ul>
<li><a href="/learning/articles/future-of-leadership-development">The Future of Leadership Development: Trends and Innovations</a></li>
<li><a href="/learning/articles/emotional-intelligence-in-leadership">Emotional Intelligence: The Key to Effective Leadership</a></li>
<li><a href="/learning/articles/building-high-performing-teams">Building High-Performing Teams: A Leader's Guide</a></li>
<li><a href="/learning/articles/digital-transformation-leadership">Leading Digital Transformation: A Strategic Approach</a></li>
<li><a href="/learning/articles/crisis-leadership-strategies">Crisis Leadership: Navigating Uncertainty with Confidence</a></li>
<li><a href="/learning/articles/sustainable-leadership-practices">Sustainable Leadership: Building for the Long Term</a></li>
</ul>
<p><a href="/learning/articles">Return to all articles</a></p>
`,
author: 'KLC Team',
authorBio: 'The Knowledge Leadership Centre team is dedicated to providing excellent leadership development resources.',
authorImage: 'https://images.unsplash.com/photo-1494790108755-2616b612b47c?w=150&h=150&fit=crop',
publishedDate: '2024-01-01',
updatedDate: '2024-01-01',
readTime: '1 min read',
views: 0,
likes: 0,
category: 'General',
tags: [],
image: 'https://images.unsplash.com/photo-1552664730-d307ca884978?w=1200&h=600&fit=crop',
featured: false
};
}
return {
id: article.id.toString(),
title: article.title,
slug: article.slug,
excerpt: article.excerpt,
content: article.content,
author: article.author,
authorBio: article.authorBio,
authorImage: article.authorImage,
publishedDate: article.publishedDate,
updatedDate: article.publishedDate,
readTime: article.readTime,
views: article.views,
likes: article.likes,
category: article.category,
tags: article.tags,
image: article.image,
featured: article.featured
};
};
const relatedPosts: RelatedPost[] = [
{
id: '2',
title: 'Emotional Intelligence: The Key to Effective Leadership',
slug: 'emotional-intelligence-in-leadership',
excerpt: 'Discover how emotional intelligence impacts leadership effectiveness and learn practical strategies to develop your EQ.',
author: 'Dr. Michael Chen',
publishedDate: '2024-02-18',
readTime: '6 min read',
category: 'Personal Development',
image: 'https://images.unsplash.com/photo-1559027615-cd4628902d4a?w=400&h=300&fit=crop'
},
{
id: '3',
title: 'Building High-Performing Teams: A Leader\'s Guide',
slug: 'building-high-performing-teams',
excerpt: 'Learn the essential strategies for creating and maintaining high-performing teams that deliver exceptional results.',
author: 'Lisa Rodriguez',
publishedDate: '2024-02-15',
readTime: '10 min read',
category: 'Team Development',
image: 'https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=400&h=300&fit=crop'
},
{
id: '4',
title: 'Leading Digital Transformation: A Strategic Approach',
slug: 'digital-transformation-leadership',
excerpt: 'Navigate the complexities of digital transformation with proven leadership strategies and best practices.',
author: 'David Park',
publishedDate: '2024-02-12',
readTime: '12 min read',
category: 'Digital Transformation',
image: 'https://images.unsplash.com/photo-1560472355-536de3962603?w=400&h=300&fit=crop'
}
];
export function BlogDetail({ params }: BlogDetailProps) {
const slug = params?.slug || '';
const [scrollProgress, setScrollProgress] = useState(0);
const [showBackToTop, setShowBackToTop] = useState(false);
const [isLiked, setIsLiked] = useState(false);
const [isBookmarked, setIsBookmarked] = useState(false);
const { addToCart } = useCart();
// Get blog post data based on slug
const blogPost = getBlogPostBySlug(slug);
useEffect(() => {
document.title = `${blogPost.title} | KLC Blog`;
window.scrollTo(0, 0);
const handleScroll = () => {
const winScroll = document.body.scrollTop || document.documentElement.scrollTop;
const height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
const scrolled = (winScroll / height) * 100;
setScrollProgress(scrolled);
setShowBackToTop(winScroll > 300);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, [blogPost.title]);
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
};
const handleShare = (platform: string) => {
const url = window.location.href;
const title = blogPost.title;
const shareUrls = {
twitter: `https://twitter.com/intent/tweet?text=${encodeURIComponent(title)}&url=${encodeURIComponent(url)}`,
facebook: `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`,
linkedin: `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`,
copy: url
};
if (platform === 'copy') {
navigator.clipboard.writeText(url);
alert('Link copied to clipboard!');
} else {
window.open(shareUrls[platform as keyof typeof shareUrls], '_blank', 'width=600,height=400');
}
};
const scrollToTop = () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
};
return (
<div className="min-h-screen" style={{ backgroundColor: '#FFFFFF' }}>
{/* Scroll Progress Bar */}
<div className="fixed top-0 left-0 w-full h-1 z-50" style={{ backgroundColor: 'rgba(0, 0, 0, 0.1)' }}>
<div
className="h-full transition-all duration-150"
style={{
width: `${scrollProgress}%`,
backgroundColor: '#04045B'
}}
/>
</div>
{/* Back to Top Button */}
{showBackToTop && (
<Button
onClick={scrollToTop}
size="icon"
className="fixed bottom-8 right-8 z-40 rounded-full shadow-lg"
style={{
backgroundColor: '#04045B',
color: 'white'
}}
>
<ChevronUp className="w-4 h-4" />
</Button>
)}
<main className="pt-20">
{/* Consistent Side Gutters - Breadcrumb Navigation */}
<div className="section-margin-x mb-8">
<div className="flex items-center gap-3 text-small" style={{ color: '#6F6F6F' }}>
<Button
variant="ghost"
size="sm"
onClick={() => navigateTo('/learning/articles')}
className="p-0 h-auto font-medium hover:bg-transparent transition-colors"
style={{ color: '#6F6F6F' }}
>
<ArrowLeft className="w-4 h-4 mr-2" />
Back to Articles
</Button>
<span className="text-[#E5E7EB]"></span>
<span>{blogPost.category}</span>
</div>
</div>
{/* Main Content Container with Consistent Gutters */}
<div className="section-margin-x">
{/* Reading Width Constraint for Better Readability */}
<div className="max-w-4xl mx-auto">
{/* Hero Header - Improved Spacing */}
<header className="mb-16">
{/* Category Badge */}
<div className="mb-8">
<Badge
className="mb-6 text-small px-4 py-2 font-medium border-none"
style={{
backgroundColor: 'rgba(4, 4, 91, 0.1)',
color: '#04045B'
}}
>
{blogPost.category}
</Badge>
{/* Improved Typography Hierarchy */}
<h1 className="text-h1 mb-6 leading-tight" style={{ color: '#26231A' }}>
{blogPost.title}
</h1>
{/* Constrained Width Excerpt for Better Readability */}
<div className="max-w-3xl">
<p className="text-body-lg leading-relaxed" style={{ color: '#6F6F6F' }}>
{blogPost.excerpt}
</p>
</div>
</div>
{/* Enhanced Meta Bar with Cleaner Spacing */}
<div
className="flex flex-col lg:flex-row items-start lg:items-center justify-between gap-6 p-6 rounded-xl border"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.02)', borderColor: 'rgba(0, 0, 0, 0.08)' }}
>
{/* Author Info with Improved Layout */}
<div className="flex items-center gap-4">
<Avatar className="w-14 h-14 ring-2 ring-white shadow-md">
<AvatarImage src={blogPost.authorImage} alt={blogPost.author} />
<AvatarFallback className="text-subhead font-medium">{blogPost.author.split(' ').map(n => n[0]).join('')}</AvatarFallback>
</Avatar>
<div>
<div className="text-subhead font-medium mb-1" style={{ color: '#26231A' }}>
{blogPost.author}
</div>
{/* Cleaner Meta Information with Subtle Dividers */}
<div className="flex items-center gap-4 text-small" style={{ color: '#6F6F6F' }}>
<span className="flex items-center gap-1.5">
<Calendar className="w-4 h-4" />
{formatDate(blogPost.publishedDate)}
</span>
<div className="w-1 h-1 rounded-full" style={{ backgroundColor: '#E5E7EB' }}></div>
<span className="flex items-center gap-1.5">
<Clock className="w-4 h-4" />
{blogPost.readTime}
</span>
<div className="w-1 h-1 rounded-full" style={{ backgroundColor: '#E5E7EB' }}></div>
<span className="flex items-center gap-1.5">
<Eye className="w-4 h-4" />
{blogPost.views.toLocaleString()}
</span>
</div>
</div>
</div>
{/* Action Buttons with Better Spacing */}
<div className="flex items-center gap-2">
<Button
variant="ghost"
size="sm"
onClick={() => setIsLiked(!isLiked)}
className={`transition-colors ${isLiked ? 'text-red-500' : 'text-[#6F6F6F]'}`}
>
<Heart className={`w-4 h-4 mr-2 ${isLiked ? 'fill-current' : ''}`} />
{blogPost.likes + (isLiked ? 1 : 0)}
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => setIsBookmarked(!isBookmarked)}
className={`transition-colors ${isBookmarked ? 'text-[#04045B]' : 'text-[#6F6F6F]'}`}
>
<Bookmark className={`w-4 h-4 ${isBookmarked ? 'fill-current' : ''}`} />
</Button>
{/* Share Options */}
<div className="flex items-center gap-1 ml-2 pl-2 border-l border-[#E5E7EB]">
<Button variant="ghost" size="sm" onClick={() => handleShare('twitter')} className="text-[#6F6F6F] hover:text-[#04045B]">
<Twitter className="w-4 h-4" />
</Button>
<Button variant="ghost" size="sm" onClick={() => handleShare('linkedin')} className="text-[#6F6F6F] hover:text-[#04045B]">
<Linkedin className="w-4 h-4" />
</Button>
<Button variant="ghost" size="sm" onClick={() => handleShare('copy')} className="text-[#6F6F6F] hover:text-[#04045B]">
<Link className="w-4 h-4" />
</Button>
</div>
</div>
</div>
{/* Featured Image with Better Aspect Ratio */}
<div className="aspect-[16/9] rounded-xl overflow-hidden mt-8 shadow-lg">
<ImageWithFallback
src={blogPost.image}
alt={blogPost.title}
className="w-full h-full object-cover"
/>
</div>
</header>
{/* Article Body with Enhanced Typography - Full Width */}
<article className="mb-20">
{/* Full Width Container - Uses complete available width */}
<div className="w-full">
<div
className="prose prose-xl max-w-none blog-article-content w-full"
style={{
/* Enhanced Typography Hierarchy using Design System */
'--tw-prose-body': '#26231A',
'--tw-prose-headings': '#26231A',
'--tw-prose-lead': '#26231A',
'--tw-prose-links': '#04045B',
'--tw-prose-bold': '#26231A',
'--tw-prose-counters': '#6F6F6F',
'--tw-prose-bullets': '#6F6F6F',
'--tw-prose-hr': 'rgba(0, 0, 0, 0.1)',
'--tw-prose-quotes': '#04045B',
'--tw-prose-quote-borders': '#04045B',
'--tw-prose-captions': '#6F6F6F',
'--tw-prose-code': '#04045B',
'--tw-prose-pre-code': '#26231A',
'--tw-prose-pre-bg': 'rgba(0, 0, 0, 0.05)',
'--tw-prose-th-borders': 'rgba(0, 0, 0, 0.15)',
'--tw-prose-td-borders': 'rgba(0, 0, 0, 0.1)',
/* Typography Scale using Design System Tokens */
fontSize: 'var(--font-body-lg)',
lineHeight: '1.75',
fontFamily: 'var(--font-family-base)',
color: '#26231A',
width: '100%'
}}
dangerouslySetInnerHTML={{ __html: blogPost.content }}
/>
</div>
</article>
{/* Enhanced Tag Pills with Hover States */}
<div className="mb-16">
<h3 className="text-subhead mb-6 font-medium" style={{ color: '#26231A' }}>
Topics covered in this article
</h3>
<div className="flex flex-wrap gap-3">
{blogPost.tags.map((tag) => (
<Badge
key={tag}
className="transition-all duration-200 text-body px-4 py-2 font-medium"
style={{
backgroundColor: 'rgba(4, 4, 91, 0.08)',
color: '#04045B',
border: '1px solid rgba(4, 4, 91, 0.15)'
}}
>
{tag}
</Badge>
))}
</div>
</div>
{/* Enhanced Author Bio Card */}
<Card className="mb-16 shadow-md border-0" style={{ backgroundColor: '#FFFFFF' }}>
<CardContent className="p-8">
<div className="flex items-start gap-6">
<Avatar className="w-20 h-20 ring-4 ring-white shadow-lg">
<AvatarImage src={blogPost.authorImage} alt={blogPost.author} />
<AvatarFallback className="text-lg font-medium">{blogPost.author.split(' ').map(n => n[0]).join('')}</AvatarFallback>
</Avatar>
<div className="flex-1">
<h4 className="text-h4 mb-3 font-semibold" style={{ color: '#26231A' }}>
About {blogPost.author}
</h4>
<p className="text-body leading-relaxed mb-6" style={{ color: '#6F6F6F' }}>
{blogPost.authorBio}
</p>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
{/* Related Articles Section with Balanced Grid Layout */}
<section className="py-20" style={{ backgroundColor: 'rgba(0, 0, 0, 0.02)' }}>
<div className="section-margin-x">
<div className="max-w-6xl mx-auto">
<div className="text-center mb-16">
<div className="branded-tag-system mb-6">
<div className="dot"></div>
<span className="text">Continue Learning</span>
</div>
<h2 className="text-h2 mb-6 font-bold" style={{ color: '#26231A' }}>
Explore More Leadership Insights
</h2>
<p className="text-body-lg max-w-2xl mx-auto" style={{ color: '#6F6F6F' }}>
Discover additional strategies and frameworks to enhance your leadership effectiveness
</p>
</div>
{/* Balanced Card Grid with Equal Spacing */}
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
{relatedPosts.map((post) => (
<Card
key={post.id}
className="overflow-hidden hover:shadow-xl transition-all duration-300 cursor-pointer group border-0"
onClick={() => navigateTo(`/learning/articles/${post.slug}`)}
style={{ backgroundColor: '#FFFFFF' }}
>
<div className="aspect-[16/10] w-full bg-gray-100 overflow-hidden relative">
<ImageWithFallback
src={post.image}
alt={post.title}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
/>
</div>
<CardContent className="p-6">
<div className="flex items-center justify-between mb-3">
<Badge
variant="outline"
className="text-small border-none"
style={{
backgroundColor: 'rgba(4, 4, 91, 0.1)',
color: '#04045B'
}}
>
{post.category}
</Badge>
<span className="text-small" style={{ color: '#6F6F6F' }}>
{post.readTime}
</span>
</div>
<h3
className="mb-3 group-hover:text-blue-600 transition-colors line-clamp-2"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
lineHeight: '1.3',
color: '#26231A',
fontFamily: 'var(--font-family-base)'
}}
>
{post.title}
</h3>
<p
className="mb-4 line-clamp-3"
style={{
fontSize: 'var(--font-body)',
lineHeight: '1.5',
color: '#6F6F6F',
fontFamily: 'var(--font-family-base)'
}}
>
{post.excerpt}
</p>
<div className="flex items-center justify-between pt-4 border-t" style={{ borderColor: 'rgba(0, 0, 0, 0.05)' }}>
<span className="text-small" style={{ color: '#6F6F6F' }}>
{post.author}
</span>
<span className="text-small" style={{ color: '#6F6F6F' }}>
{formatDate(post.publishedDate)}
</span>
</div>
</CardContent>
</Card>
))}
</div>
</div>
</div>
</section>
{/* CTA Section */}
<CTABannerSection />
</main>
</div>
);
}

483
src/components/Blogs.tsx Normal file
View File

@@ -0,0 +1,483 @@
import React, { useState } from 'react';
import { Button } from './ui/button';
import { Badge } from './ui/badge';
import { Calendar, Clock, User, ChevronLeft, ChevronRight, Search, Filter } from 'lucide-react';
import { Input } from './ui/input';
import { navigateTo } from './Router';
import { ImageWithFallback } from './figma/ImageWithFallback';
// Mock blog data
const blogPosts = [
{
id: '1',
slug: 'future-of-leadership-development',
title: 'The Future of Leadership Development: Trends and Innovations',
excerpt: 'Explore emerging trends in leadership development, from AI-powered coaching to virtual reality training experiences that are reshaping how leaders learn and grow.',
content: 'Full blog content would go here...',
author: 'Dr. Sarah Mitchell',
authorRole: 'Chief Learning Officer',
publishDate: '2024-02-15',
readTime: '8 min read',
category: 'Leadership',
tags: ['Leadership Development', 'Innovation', 'Future Trends', 'Technology'],
thumbnail: 'https://images.unsplash.com/photo-1552664730-d307ca884978?w=600&h=400&fit=crop',
featured: true
},
{
id: '2',
slug: 'building-emotional-intelligence',
title: 'Building Emotional Intelligence: A Leader\'s Guide to Self-Awareness',
excerpt: 'Discover practical strategies for developing emotional intelligence and how self-aware leaders create more engaged and productive teams.',
content: 'Full blog content would go here...',
author: 'Marcus Rodriguez',
authorRole: 'Leadership Coach',
publishDate: '2024-02-10',
readTime: '6 min read',
category: 'Personal Development',
tags: ['Emotional Intelligence', 'Self-Awareness', 'Team Building', 'Communication'],
thumbnail: 'https://images.unsplash.com/photo-1559027615-cd4628902d4a?w=600&h=400&fit=crop',
featured: false
},
{
id: '3',
slug: 'remote-leadership-strategies',
title: 'Remote Leadership Strategies: Managing Distributed Teams Effectively',
excerpt: 'Learn proven strategies for leading remote teams, maintaining culture, and driving performance in a distributed work environment.',
content: 'Full blog content would go here...',
author: 'Dr. Emily Chen',
authorRole: 'Remote Work Expert',
publishDate: '2024-02-05',
readTime: '10 min read',
category: 'Remote Work',
tags: ['Remote Leadership', 'Virtual Teams', 'Digital Communication', 'Performance Management'],
thumbnail: 'https://images.unsplash.com/photo-1600880292203-757bb62b4baf?w=600&h=400&fit=crop',
featured: true
},
{
id: '4',
slug: 'diversity-inclusion-leadership',
title: 'Diversity and Inclusion: Leading Change in Your Organization',
excerpt: 'A comprehensive guide to implementing meaningful diversity and inclusion initiatives that drive real organizational change.',
content: 'Full blog content would go here...',
author: 'Jennifer Adams',
authorRole: 'D&I Consultant',
publishDate: '2024-01-28',
readTime: '12 min read',
category: 'Diversity & Inclusion',
tags: ['Diversity', 'Inclusion', 'Organizational Change', 'Culture'],
thumbnail: 'https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=600&h=400&fit=crop',
featured: false
},
{
id: '5',
slug: 'agile-leadership-mindset',
title: 'Developing an Agile Leadership Mindset for Rapid Change',
excerpt: 'Explore how agile principles can transform your leadership approach and help organizations navigate uncertainty and rapid change.',
content: 'Full blog content would go here...',
author: 'David Park',
authorRole: 'Agile Coach',
publishDate: '2024-01-20',
readTime: '7 min read',
category: 'Agile Leadership',
tags: ['Agile', 'Change Management', 'Adaptability', 'Innovation'],
thumbnail: 'https://images.unsplash.com/photo-1552664730-d307ca884978?w=600&h=400&fit=crop',
featured: false
},
{
id: '6',
slug: 'coaching-vs-mentoring',
title: 'Coaching vs. Mentoring: Understanding the Difference and When to Use Each',
excerpt: 'Learn the key differences between coaching and mentoring, and discover when each approach is most effective for leadership development.',
content: 'Full blog content would go here...',
author: 'Lisa Thompson',
authorRole: 'Executive Coach',
publishDate: '2024-01-15',
readTime: '9 min read',
category: 'Coaching',
tags: ['Coaching', 'Mentoring', 'Leadership Development', 'Professional Growth'],
thumbnail: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=600&h=400&fit=crop',
featured: false
}
];
export function Blogs() {
const [searchTerm, setSearchTerm] = useState('');
const [selectedCategory, setSelectedCategory] = useState('All');
const [currentPage, setCurrentPage] = useState(1);
const postsPerPage = 6;
// Get unique categories
const categories = ['All', ...Array.from(new Set(blogPosts.map(post => post.category)))];
// Filter posts based on search and category
const filteredPosts = blogPosts.filter(post => {
const matchesSearch = post.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
post.excerpt.toLowerCase().includes(searchTerm.toLowerCase()) ||
post.author.toLowerCase().includes(searchTerm.toLowerCase());
const matchesCategory = selectedCategory === 'All' || post.category === selectedCategory;
return matchesSearch && matchesCategory;
});
// Paginate results
const totalPages = Math.ceil(filteredPosts.length / postsPerPage);
const currentPosts = filteredPosts.slice((currentPage - 1) * postsPerPage, currentPage * postsPerPage);
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
};
return (
<div style={{ backgroundColor: 'var(--color-bg-white)' }}>
{/* Header Section */}
<div className="py-12">
<div className="hero-margin-x">
<div className="text-center mb-12">
<div className="branded-tag-system mb-6">
<div className="dot"></div>
<span className="text">INSIGHTS & EXPERTISE</span>
</div>
<h1
className="mb-6"
style={{
fontSize: 'var(--font-h1)',
fontWeight: 'var(--font-weight-h1)',
lineHeight: 'var(--line-height-h1)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Leadership Insights Blog
</h1>
<p
className="max-w-3xl mx-auto"
style={{
fontSize: 'var(--font-body-lg)',
lineHeight: 'var(--line-height-body-lg)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Discover thought-provoking articles, expert insights, and practical strategies from leading voices in organizational development and leadership excellence.
</p>
</div>
{/* Search and Filter Section */}
<div className="mb-12">
<div className="flex flex-col lg:flex-row gap-6 items-center justify-between">
{/* Search Bar */}
<div className="relative flex-1 max-w-md">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
<Input
type="text"
placeholder="Search articles..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-10"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)'
}}
/>
</div>
{/* Category Filter */}
<div className="flex flex-wrap gap-2">
{categories.map((category) => (
<Button
key={category}
variant={selectedCategory === category ? "default" : "outline"}
onClick={() => {
setSelectedCategory(category);
setCurrentPage(1);
}}
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)',
backgroundColor: selectedCategory === category ? 'var(--color-primary)' : 'transparent',
borderColor: 'var(--color-primary)',
color: selectedCategory === category ? 'white' : 'var(--color-primary)'
}}
>
{category}
</Button>
))}
</div>
</div>
</div>
{/* Featured Posts Section */}
{searchTerm === '' && selectedCategory === 'All' && (
<div className="mb-16">
<h2
className="mb-8"
style={{
fontSize: 'var(--font-h2)',
fontWeight: 'var(--font-weight-h2)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Featured Articles
</h2>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
{blogPosts.filter(post => post.featured).slice(0, 2).map((post) => (
<article
key={post.id}
className="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden hover:shadow-lg transition-all duration-300 cursor-pointer"
onClick={() => navigateTo(`/learning/blogs/${post.slug}`)}
>
<div className="aspect-video w-full bg-gray-100">
<ImageWithFallback
src={post.thumbnail}
alt={post.title}
className="w-full h-full object-cover"
/>
</div>
<div className="p-6">
<div className="flex items-center gap-3 mb-4">
<Badge
variant="secondary"
style={{
backgroundColor: 'rgba(248, 195, 1, 0.1)',
color: 'var(--color-black)',
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
{post.category}
</Badge>
<Badge
variant="outline"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)',
borderColor: 'var(--color-primary)',
color: 'var(--color-primary)'
}}
>
Featured
</Badge>
</div>
<h3
className="mb-3 hover:text-blue-600 transition-colors"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
lineHeight: 'var(--line-height-h3)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{post.title}
</h3>
<p
className="mb-4"
style={{
fontSize: 'var(--font-body)',
lineHeight: 'var(--line-height-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
{post.excerpt}
</p>
<div className="flex items-center justify-between text-sm text-gray-500">
<div className="flex items-center gap-4">
<div className="flex items-center gap-1">
<User className="w-4 h-4" />
<span style={{ fontSize: 'var(--font-small)', fontFamily: 'var(--font-family-base)' }}>
{post.author}
</span>
</div>
<div className="flex items-center gap-1">
<Calendar className="w-4 h-4" />
<span style={{ fontSize: 'var(--font-small)', fontFamily: 'var(--font-family-base)' }}>
{formatDate(post.publishDate)}
</span>
</div>
</div>
<div className="flex items-center gap-1">
<Clock className="w-4 h-4" />
<span style={{ fontSize: 'var(--font-small)', fontFamily: 'var(--font-family-base)' }}>
{post.readTime}
</span>
</div>
</div>
</div>
</article>
))}
</div>
</div>
)}
{/* All Posts Grid */}
<div className="mb-12">
<h2
className="mb-8"
style={{
fontSize: 'var(--font-h2)',
fontWeight: 'var(--font-weight-h2)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{searchTerm || selectedCategory !== 'All' ? 'Search Results' : 'All Articles'}
</h2>
{currentPosts.length === 0 ? (
<div className="text-center py-12">
<p
style={{
fontSize: 'var(--font-body-lg)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
No articles found matching your criteria.
</p>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{currentPosts.map((post) => (
<article
key={post.id}
className="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden hover:shadow-lg transition-all duration-300 cursor-pointer group"
onClick={() => navigateTo(`/learning/blogs/${post.slug}`)}
>
<div className="aspect-video w-full bg-gray-100 overflow-hidden">
<ImageWithFallback
src={post.thumbnail}
alt={post.title}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
/>
</div>
<div className="p-6">
<div className="flex items-center gap-3 mb-3">
<Badge
variant="secondary"
style={{
backgroundColor: 'rgba(248, 195, 1, 0.1)',
color: 'var(--color-black)',
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
{post.category}
</Badge>
{post.featured && (
<Badge
variant="outline"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)',
borderColor: 'var(--color-primary)',
color: 'var(--color-primary)'
}}
>
Featured
</Badge>
)}
</div>
<h3
className="mb-3 group-hover:text-blue-600 transition-colors"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
lineHeight: 'var(--line-height-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{post.title}
</h3>
<p
className="mb-4"
style={{
fontSize: 'var(--font-small)',
lineHeight: 'var(--line-height-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
{post.excerpt}
</p>
<div className="flex items-center justify-between text-sm text-gray-500">
<div className="flex items-center gap-1">
<User className="w-4 h-4" />
<span style={{ fontSize: 'var(--font-small)', fontFamily: 'var(--font-family-base)' }}>
{post.author}
</span>
</div>
<div className="flex items-center gap-1">
<Clock className="w-4 h-4" />
<span style={{ fontSize: 'var(--font-small)', fontFamily: 'var(--font-family-base)' }}>
{post.readTime}
</span>
</div>
</div>
</div>
</article>
))}
</div>
)}
</div>
{/* Pagination */}
{totalPages > 1 && (
<div className="flex items-center justify-center gap-4">
<Button
variant="outline"
onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))}
disabled={currentPage === 1}
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
borderColor: 'var(--color-primary)'
}}
>
<ChevronLeft className="w-4 h-4 mr-2" />
Previous
</Button>
<span
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
Page {currentPage} of {totalPages}
</span>
<Button
variant="outline"
onClick={() => setCurrentPage(prev => Math.min(prev + 1, totalPages))}
disabled={currentPage === totalPages}
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
borderColor: 'var(--color-primary)'
}}
>
Next
<ChevronRight className="w-4 h-4 ml-2" />
</Button>
</div>
)}
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,991 @@
import React, { useState, useEffect } from 'react';
import { navigateTo } from './Router';
import { Button } from './ui/button';
import { Card, CardContent, CardHeader, CardTitle } from './ui/card';
import { Badge } from './ui/badge';
import { Input } from './ui/input';
import { Label } from './ui/label';
import { Textarea } from './ui/textarea';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
import { Calendar } from './ui/calendar';
import { Alert, AlertDescription } from './ui/alert';
import { Separator } from './ui/separator';
import { ImageWithFallback } from './figma/ImageWithFallback';
import {
Users,
MapPin,
Clock,
CheckCircle,
CreditCard,
Calendar as CalendarIcon,
Building,
Phone,
Mail,
User,
ArrowLeft,
ArrowRight,
Wifi,
Coffee,
Car,
Utensils,
Copy,
Download,
AlertCircle,
XCircle,
Zap,
Award,
Shield
} from 'lucide-react';
interface BookingFormData {
companyName: string;
contactName: string;
email: string;
phone: string;
role: string;
teamSize: string;
facilityZone: string;
additionalRequirements: string;
}
interface TimeSlot {
time: string;
available: boolean;
price: number;
}
interface BookingConfirmation {
referenceId: string;
facilityName: string;
date: string;
timeSlot: string;
totalAmount: number;
companyName: string;
contactName: string;
email: string;
phone: string;
}
const facilityData = {
id: 'executive-boardroom',
name: 'Executive Boardroom',
description: 'Premium boardroom designed for high-level meetings and strategic discussions with state-of-the-art technology.',
capacity: 20,
pricePerHour: 2500,
image: 'https://images.unsplash.com/photo-1560472354-b33ff0c44a43?w=800&h=600&fit=crop',
features: [
'4K video conferencing system',
'Premium leather seating',
'Climate controlled environment',
'Wireless presentation system',
'Premium catering options',
'Dedicated technical support'
],
amenities: [
{ icon: Wifi, name: 'High-Speed WiFi' },
{ icon: Coffee, name: 'Refreshment Station' },
{ icon: Car, name: 'Valet Parking' },
{ icon: Utensils, name: 'Premium Catering' }
]
};
const generateTimeSlots = (date: Date): TimeSlot[] => {
const slots: TimeSlot[] = [];
const isWeekend = date.getDay() === 0 || date.getDay() === 6;
if (isWeekend) {
return []; // No slots available on weekends
}
const startHour = 9;
const endHour = 18;
for (let hour = startHour; hour < endHour; hour++) {
const timeString = `${hour.toString().padStart(2, '0')}:00`;
const available = Math.random() > 0.3; // Random availability for demo
slots.push({
time: timeString,
available,
price: facilityData.pricePerHour
});
}
return slots;
};
const generateReferenceId = (): string => {
return 'KLC-' + Date.now().toString().slice(-8).toUpperCase();
};
export function BookFacility() {
const [currentStep, setCurrentStep] = useState<'booking' | 'confirmation' | 'payment-success' | 'payment-failed'>('booking');
const [selectedDate, setSelectedDate] = useState<Date | undefined>(new Date());
const [selectedTimeSlot, setSelectedTimeSlot] = useState<string>('');
const [timeSlots, setTimeSlots] = useState<TimeSlot[]>([]);
const [bookingForm, setBookingForm] = useState<BookingFormData>({
companyName: '',
contactName: '',
email: '',
phone: '',
role: '',
teamSize: '',
facilityZone: 'executive-wing',
additionalRequirements: ''
});
const [bookingConfirmation, setBookingConfirmation] = useState<BookingConfirmation | null>(null);
const [isSubmitting, setIsSubmitting] = useState(false);
useEffect(() => {
document.title = 'Book Facility - Kautilya Leadership Centre';
window.scrollTo(0, 0);
}, []);
useEffect(() => {
if (selectedDate) {
setTimeSlots(generateTimeSlots(selectedDate));
setSelectedTimeSlot(''); // Reset time slot when date changes
}
}, [selectedDate]);
const formatPrice = (price: number) => {
return new Intl.NumberFormat('en-IN', {
style: 'currency',
currency: 'INR',
maximumFractionDigits: 0
}).format(price);
};
const formatDate = (date: Date) => {
return date.toLocaleDateString('en-IN', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
};
const handleSubmitBooking = async (e: React.FormEvent) => {
e.preventDefault();
if (!selectedDate || !selectedTimeSlot) return;
setIsSubmitting(true);
// Simulate API call
setTimeout(() => {
const selectedSlot = timeSlots.find(slot => slot.time === selectedTimeSlot);
const confirmation: BookingConfirmation = {
referenceId: generateReferenceId(),
facilityName: facilityData.name,
date: formatDate(selectedDate),
timeSlot: selectedTimeSlot,
totalAmount: selectedSlot?.price || facilityData.pricePerHour,
companyName: bookingForm.companyName,
contactName: bookingForm.contactName,
email: bookingForm.email,
phone: bookingForm.phone
};
setBookingConfirmation(confirmation);
setCurrentStep('confirmation');
setIsSubmitting(false);
}, 2000);
};
const handlePayNow = () => {
// Simulate payment processing
setIsSubmitting(true);
setTimeout(() => {
const success = Math.random() > 0.2; // 80% success rate for demo
setCurrentStep(success ? 'payment-success' : 'payment-failed');
setIsSubmitting(false);
}, 3000);
};
const copyReferenceId = () => {
if (bookingConfirmation) {
navigator.clipboard.writeText(bookingConfirmation.referenceId);
}
};
const isFormValid = () => {
return (
bookingForm.companyName &&
bookingForm.contactName &&
bookingForm.email &&
bookingForm.phone &&
bookingForm.role &&
bookingForm.teamSize &&
selectedDate &&
selectedTimeSlot
);
};
const availableTimeSlots = timeSlots.filter(slot => slot.available);
if (currentStep === 'payment-success') {
return (
<div className="min-h-screen" style={{ backgroundColor: '#F7F7FD' }}>
<div className="pt-40 pb-16">
<div className="container mx-auto section-margin-x">
<div className="max-w-2xl mx-auto text-center">
<div
className="w-20 h-20 rounded-full flex items-center justify-center mx-auto mb-6"
style={{ backgroundColor: 'rgba(34, 197, 94, 0.1)' }}
>
<CheckCircle className="w-10 h-10 text-green-600" />
</div>
<h1 className="text-h2 mb-4">
Payment Successful!
</h1>
<p className="text-body-lg text-muted mb-8">
Your facility booking has been confirmed and payment processed successfully.
You'll receive a confirmation email shortly.
</p>
{bookingConfirmation && (
<Card className="mb-8 text-left" style={{ backgroundColor: 'var(--color-bg-white)' }}>
<CardHeader>
<CardTitle className="text-subhead">Booking Confirmed</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-2 gap-4 text-body">
<div>
<span className="text-muted">Reference ID:</span>
<div className="text-subhead">{bookingConfirmation.referenceId}</div>
</div>
<div>
<span className="text-muted">Amount Paid:</span>
<div className="text-subhead text-green-600">
{formatPrice(bookingConfirmation.totalAmount)}
</div>
</div>
</div>
</CardContent>
</Card>
)}
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<button
className="brand-button-system"
onClick={() => navigateTo('/')}
>
<Download className="w-5 h-5" />
Download Receipt
</button>
<Button
variant="outline"
size="lg"
onClick={() => navigateTo('/')}
className="text-body"
>
Return to Homepage
</Button>
</div>
</div>
</div>
</div>
</div>
);
}
if (currentStep === 'payment-failed') {
return (
<div className="min-h-screen" style={{ backgroundColor: '#F7F7FD' }}>
<div className="pt-40 pb-16">
<div className="container mx-auto section-margin-x">
<div className="max-w-2xl mx-auto text-center">
<div
className="w-20 h-20 rounded-full flex items-center justify-center mx-auto mb-6"
style={{ backgroundColor: 'rgba(239, 68, 68, 0.1)' }}
>
<XCircle className="w-10 h-10 text-red-600" />
</div>
<h1 className="text-h2 mb-4">
Payment Failed
</h1>
<p className="text-body-lg text-muted mb-8">
We encountered an issue processing your payment. Your booking is still reserved
for the next 30 minutes. Please try again or contact our support team.
</p>
<Alert className="mb-8 text-left">
<AlertCircle className="h-4 w-4" />
<AlertDescription className="text-body">
Your booking reference <strong>{bookingConfirmation?.referenceId}</strong> is
temporarily held. Please complete payment within 30 minutes to confirm your booking.
</AlertDescription>
</Alert>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Button
size="lg"
onClick={handlePayNow}
disabled={isSubmitting}
className="text-body"
style={{
backgroundColor: 'var(--color-primary)',
color: 'white'
}}
>
<CreditCard className="w-5 h-5 mr-2" />
{isSubmitting ? 'Processing...' : 'Try Payment Again'}
</Button>
<Button
variant="outline"
size="lg"
onClick={() => navigateTo('/contact')}
className="text-body"
>
Contact Support
</Button>
</div>
</div>
</div>
</div>
</div>
);
}
if (currentStep === 'confirmation') {
return (
<div className="min-h-screen" style={{ backgroundColor: '#F7F7FD' }}>
<div className="pt-40 pb-16">
<div className="container mx-auto section-margin-x">
<div className="max-w-4xl mx-auto">
{/* Confirmation Header */}
<div className="text-center mb-8">
<div
className="w-20 h-20 rounded-full flex items-center justify-center mx-auto mb-6"
style={{ backgroundColor: 'rgba(34, 197, 94, 0.1)' }}
>
<CheckCircle className="w-10 h-10 text-green-600" />
</div>
<h1 className="text-h2 mb-4">
Booking Request Submitted
</h1>
<p className="text-body-lg text-muted">
Your facility booking request has been received and is being processed.
</p>
</div>
{/* Confirmation Panel */}
{bookingConfirmation && (
<Card className="mb-8" style={{ backgroundColor: 'var(--color-bg-white)' }}>
<CardHeader>
<div className="flex items-center justify-between">
<CardTitle className="text-subhead">Booking Confirmation</CardTitle>
<Badge variant="outline" className="text-body px-4 py-2">
Pending Confirmation
</Badge>
</div>
</CardHeader>
<CardContent className="space-y-6">
{/* Reference ID */}
<div
className="rounded-lg p-4"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.03)' }}
>
<div className="flex items-center justify-between">
<div>
<span className="text-body text-muted">Reference ID</span>
<div className="text-subhead text-primary">
{bookingConfirmation.referenceId}
</div>
</div>
<Button
variant="outline"
size="sm"
onClick={copyReferenceId}
className="text-body"
>
<Copy className="w-4 h-4 mr-2" />
Copy
</Button>
</div>
</div>
{/* Booking Details */}
<div className="grid md:grid-cols-2 gap-6">
<div className="space-y-4">
<h3 className="text-subhead">Facility Details</h3>
<div className="space-y-3">
<div className="flex items-center gap-3">
<Building className="w-5 h-5 text-muted" />
<div>
<div className="text-body">{bookingConfirmation.facilityName}</div>
<div className="text-small text-muted">Executive Wing</div>
</div>
</div>
<div className="flex items-center gap-3">
<CalendarIcon className="w-5 h-5 text-muted" />
<div>
<div className="text-body">{bookingConfirmation.date}</div>
<div className="text-small text-muted">{bookingConfirmation.timeSlot}</div>
</div>
</div>
<div className="flex items-center gap-3">
<Users className="w-5 h-5 text-muted" />
<div>
<div className="text-body">Up to {facilityData.capacity} people</div>
<div className="text-small text-muted">Maximum capacity</div>
</div>
</div>
</div>
</div>
<div className="space-y-4">
<h3 className="text-subhead">Contact Information</h3>
<div className="space-y-3">
<div className="flex items-center gap-3">
<Building className="w-5 h-5 text-muted" />
<div>
<div className="text-body">{bookingConfirmation.companyName}</div>
<div className="text-small text-muted">Company</div>
</div>
</div>
<div className="flex items-center gap-3">
<User className="w-5 h-5 text-muted" />
<div>
<div className="text-body">{bookingConfirmation.contactName}</div>
<div className="text-small text-muted">Contact Person</div>
</div>
</div>
<div className="flex items-center gap-3">
<Mail className="w-5 h-5 text-muted" />
<div>
<div className="text-body">{bookingConfirmation.email}</div>
<div className="text-small text-muted">Email</div>
</div>
</div>
</div>
</div>
</div>
<Separator />
{/* Pricing */}
<div className="flex items-center justify-between text-subhead">
<span>Total Amount</span>
<span className="text-primary">
{formatPrice(bookingConfirmation.totalAmount)}
</span>
</div>
</CardContent>
</Card>
)}
{/* Action Buttons */}
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Button
size="lg"
onClick={handlePayNow}
disabled={isSubmitting}
className="text-body-lg"
style={{
backgroundColor: 'var(--color-primary)',
color: 'white'
}}
>
<CreditCard className="w-5 h-5 mr-2" />
{isSubmitting ? 'Processing Payment...' : 'Pay Now'}
</Button>
<Button
variant="outline"
size="lg"
onClick={() => navigateTo('/')}
className="text-body-lg"
>
Continue Browsing
</Button>
</div>
</div>
</div>
</div>
</div>
);
}
return (
<div className="min-h-screen" style={{ backgroundColor: '#F7F7FD' }}>
{/* Hero Section */}
<section className="relative h-[80vh] lg:h-[90vh] overflow-hidden pt-20" style={{ backgroundColor: 'var(--color-bg-white)' }}>
<div className="h-full flex items-center">
{/* Left Side - Content (60%) */}
<div className="relative w-full lg:w-[60%] h-full flex items-center justify-center p-8 lg:p-16 py-12 lg:py-16">
<div className="max-w-2xl space-y-8">
{/* Price Badge */}
<div className="space-y-2">
<Badge
className="text-body px-4 py-2"
style={{
backgroundColor: 'var(--color-primary)',
color: 'white',
border: 'none'
}}
>
₹2,500/hour
</Badge>
</div>
{/* Main Headline */}
<div className="space-y-6">
<h1 className="text-h1 text-primary leading-tight">
Book Executive
<br />
<span className="text-primary">Boardroom</span>
</h1>
</div>
{/* Description */}
<div className="space-y-6">
<p className="text-body-lg text-muted leading-relaxed max-w-xl">
Premium boardroom designed for high-level meetings and strategic discussions with
state-of-the-art technology.
</p>
</div>
{/* Facility Details */}
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<div className="flex items-center gap-2">
<Users className="w-5 h-5 text-muted" />
<span className="text-body">20 people</span>
</div>
<div className="flex items-center gap-2">
<MapPin className="w-5 h-5 text-muted" />
<span className="text-body">Executive Wing</span>
</div>
<div className="flex items-center gap-2">
<Clock className="w-5 h-5 text-muted" />
<span className="text-body">9 AM - 6 PM</span>
</div>
<div className="flex items-center gap-2">
<CheckCircle className="w-5 h-5 text-green-600" />
<span className="text-body">Available</span>
</div>
</div>
{/* Amenities */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
<div className="flex items-center gap-3">
<Wifi className="w-5 h-5 text-primary flex-shrink-0" />
<span className="text-body">High-Speed WiFi</span>
</div>
<div className="flex items-center gap-3">
<Coffee className="w-5 h-5 text-primary flex-shrink-0" />
<span className="text-body">Refreshment Station</span>
</div>
<div className="flex items-center gap-3">
<Car className="w-5 h-5 text-primary flex-shrink-0" />
<span className="text-body">Valet Parking</span>
</div>
<div className="flex items-center gap-3">
<Utensils className="w-5 h-5 text-primary flex-shrink-0" />
<span className="text-body">Premium Catering</span>
</div>
<div className="flex items-center gap-3">
<Zap className="w-5 h-5 text-primary flex-shrink-0" />
<span className="text-body">4K Video System</span>
</div>
<div className="flex items-center gap-3">
<Award className="w-5 h-5 text-primary flex-shrink-0" />
<span className="text-body">Premium Seating</span>
</div>
</div>
{/* CTA Button */}
<div className="pt-4">
<Button
onClick={() => {
const bookingSection = document.getElementById('booking-section');
if (bookingSection) {
bookingSection.scrollIntoView({ behavior: 'smooth' });
}
}}
className="group shadow-xl"
style={{
backgroundColor: 'var(--color-primary)',
color: 'white',
borderRadius: '9999px',
padding: '1rem 2rem'
}}
>
<span>Book This Boardroom</span>
<ArrowRight className="w-5 h-5 ml-2 group-hover:translate-x-1 transition-transform" />
</Button>
</div>
</div>
</div>
{/* Right Side - Luxury Interior Image (40%) */}
<div className="hidden lg:block relative w-[40%] h-full">
<div className="absolute inset-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1577791464704-3bbd2da56803?w=1080&h=800&fit=crop"
alt="Luxury executive boardroom with modern design"
className="w-full h-full object-cover"
/>
{/* Subtle overlay for depth */}
<div className="absolute inset-0 bg-gradient-to-l from-transparent via-transparent to-white/20"></div>
</div>
</div>
</div>
</section>
<div id="booking-section" className="py-8 lg:py-12">
<div className="container mx-auto section-margin-x">
<div className="max-w-6xl mx-auto">
{/* Back Button */}
<Button
variant="outline"
onClick={() => navigateTo('/learning-facility/virtual-tour')}
className="mb-6 text-body"
>
<ArrowLeft className="w-4 h-4 mr-2" />
Back to Virtual Tour
</Button>
{/* Facility Header Card */}
<Card className="mb-8" style={{ backgroundColor: 'var(--color-bg-white)' }}>
<CardContent className="p-6">
<div className="grid lg:grid-cols-3 gap-6">
<div className="lg:col-span-1">
<div className="aspect-video rounded-lg overflow-hidden">
<ImageWithFallback
src={facilityData.image}
alt={facilityData.name}
className="w-full h-full object-cover"
/>
</div>
</div>
<div className="lg:col-span-2">
<div className="flex items-start justify-between mb-4">
<div>
<h1 className="text-h3 mb-2">
Book {facilityData.name}
</h1>
<p className="text-body text-muted mb-4">
{facilityData.description}
</p>
</div>
<Badge variant="secondary" className="text-body px-4 py-2">
{formatPrice(facilityData.pricePerHour)}/hour
</Badge>
</div>
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<div className="flex items-center gap-2">
<Users className="w-5 h-5 text-muted" />
<span className="text-body">{facilityData.capacity} people</span>
</div>
<div className="flex items-center gap-2">
<MapPin className="w-5 h-5 text-muted" />
<span className="text-body">Executive Wing</span>
</div>
<div className="flex items-center gap-2">
<Clock className="w-5 h-5 text-muted" />
<span className="text-body">9 AM - 6 PM</span>
</div>
<div className="flex items-center gap-2">
<CheckCircle className="w-5 h-5 text-green-600" />
<span className="text-body">Available</span>
</div>
</div>
<div className="flex flex-wrap gap-2">
{facilityData.amenities.map((amenity, index) => (
<Badge key={index} variant="outline" className="text-small px-3 py-1">
<amenity.icon className="w-3 h-3 mr-1" />
{amenity.name}
</Badge>
))}
</div>
</div>
</div>
</CardContent>
</Card>
<div className="grid lg:grid-cols-3 gap-8">
{/* Booking Form */}
<div className="lg:col-span-2">
<form onSubmit={handleSubmitBooking} className="space-y-8">
{/* Company Information */}
<Card style={{ backgroundColor: 'var(--color-bg-white)' }}>
<CardHeader>
<CardTitle className="text-subhead">Company Information</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div>
<Label htmlFor="companyName" className="text-body">Company Name *</Label>
<Input
id="companyName"
value={bookingForm.companyName}
onChange={(e) => setBookingForm({...bookingForm, companyName: e.target.value})}
required
className="text-body min-h-[44px]"
placeholder="Enter company name"
/>
</div>
<div>
<Label htmlFor="contactName" className="text-body">Contact Person *</Label>
<Input
id="contactName"
value={bookingForm.contactName}
onChange={(e) => setBookingForm({...bookingForm, contactName: e.target.value})}
required
className="text-body min-h-[44px]"
placeholder="Enter contact name"
/>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<Label htmlFor="email" className="text-body">Email Address *</Label>
<Input
id="email"
type="email"
value={bookingForm.email}
onChange={(e) => setBookingForm({...bookingForm, email: e.target.value})}
required
className="text-body min-h-[44px]"
placeholder="Enter email address"
/>
</div>
<div>
<Label htmlFor="phone" className="text-body">Phone Number *</Label>
<Input
id="phone"
value={bookingForm.phone}
onChange={(e) => setBookingForm({...bookingForm, phone: e.target.value})}
required
className="text-body min-h-[44px]"
placeholder="Enter phone number"
/>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<Label htmlFor="role" className="text-body">Your Role *</Label>
<Select value={bookingForm.role} onValueChange={(value) => setBookingForm({...bookingForm, role: value})}>
<SelectTrigger className="text-body min-h-[44px]">
<SelectValue placeholder="Select your role" />
</SelectTrigger>
<SelectContent>
<SelectItem value="hr-director">HR Director</SelectItem>
<SelectItem value="learning-development">L&D Manager</SelectItem>
<SelectItem value="executive-assistant">Executive Assistant</SelectItem>
<SelectItem value="ceo-founder">CEO/Founder</SelectItem>
<SelectItem value="other">Other</SelectItem>
</SelectContent>
</Select>
</div>
<div>
<Label htmlFor="teamSize" className="text-body">Expected Team Size *</Label>
<Select value={bookingForm.teamSize} onValueChange={(value) => setBookingForm({...bookingForm, teamSize: value})}>
<SelectTrigger className="text-body min-h-[44px]">
<SelectValue placeholder="Select team size" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1-5">1-5 people</SelectItem>
<SelectItem value="6-10">6-10 people</SelectItem>
<SelectItem value="11-15">11-15 people</SelectItem>
<SelectItem value="16-20">16-20 people</SelectItem>
</SelectContent>
</Select>
</div>
</div>
<div>
<Label htmlFor="additionalRequirements" className="text-body">Additional Requirements</Label>
<Textarea
id="additionalRequirements"
value={bookingForm.additionalRequirements}
onChange={(e) => setBookingForm({...bookingForm, additionalRequirements: e.target.value})}
placeholder="Catering, special AV setup, accessibility needs..."
className="text-body min-h-[100px]"
/>
</div>
</CardContent>
</Card>
{/* Date and Time Selection */}
<Card style={{ backgroundColor: 'var(--color-bg-white)' }}>
<CardHeader>
<CardTitle className="text-subhead">Select Date & Time</CardTitle>
</CardHeader>
<CardContent className="space-y-6">
{/* Calendar Widget */}
<div>
<Label className="text-body mb-4 block">Select Date *</Label>
<div className="border rounded-lg p-4">
<Calendar
mode="single"
selected={selectedDate}
onSelect={setSelectedDate}
disabled={(date) =>
date < new Date() ||
date.getDay() === 0 ||
date.getDay() === 6
}
className="rounded-md"
/>
</div>
<p className="text-small text-muted mt-2">
Bookings available Monday to Friday only
</p>
</div>
{/* Time Slots */}
{selectedDate && (
<div>
<Label className="text-body mb-4 block">Available Time Slots *</Label>
{availableTimeSlots.length > 0 ? (
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
{availableTimeSlots.map((slot) => (
<Button
key={slot.time}
type="button"
variant={selectedTimeSlot === slot.time ? "default" : "outline"}
className="text-body justify-between p-4 h-auto"
onClick={() => setSelectedTimeSlot(slot.time)}
style={{
backgroundColor: selectedTimeSlot === slot.time ? 'var(--color-primary)' : 'transparent',
color: selectedTimeSlot === slot.time ? 'white' : 'var(--color-black)'
}}
>
<span>{slot.time}</span>
<span className="text-small">{formatPrice(slot.price)}</span>
</Button>
))}
</div>
) : (
<Alert>
<AlertCircle className="h-4 w-4" />
<AlertDescription className="text-body">
No time slots available for the selected date. Please choose a different date.
</AlertDescription>
</Alert>
)}
</div>
)}
</CardContent>
</Card>
{/* Submit Button */}
<Card style={{ backgroundColor: 'var(--color-bg-white)' }}>
<CardContent className="p-6">
<Button
type="submit"
size="lg"
className="w-full text-body-lg"
disabled={!isFormValid() || isSubmitting}
style={{
backgroundColor: 'var(--color-primary)',
color: 'white'
}}
>
{isSubmitting ? (
'Processing Booking...'
) : (
<>
Submit Booking Request
<ArrowRight className="w-5 h-5 ml-2" />
</>
)}
</Button>
<p className="text-small text-muted text-center mt-4">
By submitting, you agree to our booking terms and conditions
</p>
</CardContent>
</Card>
</form>
</div>
{/* Booking Summary Sidebar */}
<div className="lg:col-span-1">
<Card className="sticky top-24" style={{ backgroundColor: 'var(--color-bg-white)' }}>
<CardHeader>
<CardTitle className="text-subhead">Booking Summary</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-3">
<div className="flex justify-between text-body">
<span>Facility:</span>
<span className="text-subhead">{facilityData.name}</span>
</div>
{selectedDate && (
<div className="flex justify-between text-body">
<span>Date:</span>
<span className="text-subhead">
{selectedDate.toLocaleDateString('en-IN', {
month: 'short',
day: 'numeric'
})}
</span>
</div>
)}
{selectedTimeSlot && (
<div className="flex justify-between text-body">
<span>Time:</span>
<span className="text-subhead">{selectedTimeSlot}</span>
</div>
)}
<div className="flex justify-between text-body">
<span>Duration:</span>
<span className="text-subhead">1 hour</span>
</div>
{bookingForm.teamSize && (
<div className="flex justify-between text-body">
<span>Team Size:</span>
<span className="text-subhead">{bookingForm.teamSize}</span>
</div>
)}
</div>
<Separator />
<div className="space-y-3">
<div className="flex justify-between text-body">
<span>Base Rate:</span>
<span>{formatPrice(facilityData.pricePerHour)}</span>
</div>
<div className="flex justify-between text-body">
<span>Service Charge:</span>
<span>Included</span>
</div>
</div>
<Separator />
<div className="flex justify-between text-subhead">
<span>Total:</span>
<span className="text-primary">{formatPrice(facilityData.pricePerHour)}</span>
</div>
<div className="text-small text-muted">
<p> Payment due upon confirmation</p>
<p> Free cancellation up to 24 hours</p>
<p> Technical support included</p>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,69 @@
import { ArrowRight } from "lucide-react";
import { ImageWithFallback } from "./figma/ImageWithFallback";
import { BrandedTag } from "./about/BrandedTag";
import { PrimaryCTAButton } from "./PrimaryCTAButton";
import { navigateTo } from "./Router";
export function CTABannerSection() {
return (
<section className="relative h-[700px] overflow-hidden">
{/* Background Image */}
<div className="absolute inset-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2940&q=80"
alt="Professional team collaborating in modern office"
className="w-full h-full object-cover"
/>
{/* Subtle dark overlay for overall image */}
<div className="absolute inset-0 bg-black/30" />
{/* Gradient overlay for better text readability */}
<div className="absolute inset-0 bg-gradient-to-r from-black/20 via-transparent to-black/60" />
</div>
{/* Content Container */}
<div className="relative h-full flex items-center justify-end section-margin-x">
{/* CTA Content Block */}
<div
className="bg-opacity-95 backdrop-blur-sm rounded-lg p-16 max-w-2xl"
style={{
backgroundColor: 'var(--color-brand-primary)'
}}
>
{/* Branded Tag */}
<BrandedTag text="Next Steps" variant="white" />
{/* Main Headline */}
<h2
className="text-h2-white mb-8"
>
Ready to transform your leadership?
<span
className="italic"
style={{ color: 'var(--color-brand-accent)' }}
>
{" "}Get in touch{" "}
</span>
to start your development journey now.
</h2>
{/* CTA Button - Updated to redirect to contact page */}
<PrimaryCTAButton
text="Schedule a Consultation"
onClick={() => navigateTo('/contact?topic=consulting')}
ariaLabel="Schedule a consultation with our leadership experts"
className="cta-banner-yellow"
/>
{/* Supporting Text */}
<p
className="text-body-white mt-6 opacity-90"
>
Connect with our leadership experts to discuss your organization's specific development needs.
</p>
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,213 @@
import React from 'react';
import { Button } from './ui/button';
import { Eye, Calendar, ArrowRight, Building } from 'lucide-react';
import { navigateTo } from './Router';
interface CTAPopupModalProps {
isOpen: boolean;
onClose: () => void;
}
export function CTAPopupModal({ isOpen, onClose }: CTAPopupModalProps) {
console.log('CTAPopupModal render - isOpen:', isOpen); // Debug log
const handleVirtualTour = () => {
navigateTo('/services/learning-facility');
onClose();
// Add a small delay to ensure navigation completes before triggering tour
setTimeout(() => {
// Trigger virtual tour start if on facility page
const startTourBtn = document.querySelector('[data-tour-trigger]') as HTMLButtonElement;
if (startTourBtn) {
startTourBtn.click();
}
}, 100);
};
const handleBooking = () => {
console.log('Booking button clicked in modal'); // Debug log
// Use URL parameter approach for more reliable booking modal triggering
navigateTo('/services/learning-facility?autoBooking=true');
onClose();
// Also try the element-based approach as backup
const attemptBookingTrigger = (attempt = 1, maxAttempts = 5) => {
console.log(`Booking trigger attempt #${attempt}`); // Debug log
// Look for the booking trigger element
const bookingBtn = document.querySelector('[data-booking-trigger]') as HTMLButtonElement;
console.log('Found booking trigger:', bookingBtn); // Debug log
if (bookingBtn) {
console.log('Clicking booking trigger...'); // Debug log
bookingBtn.click();
return;
}
// If not found and we haven't reached max attempts, try again
if (attempt < maxAttempts) {
setTimeout(() => attemptBookingTrigger(attempt + 1, maxAttempts), 200);
} else {
console.log('Element-based approach failed, relying on URL parameter approach'); // Debug log
}
};
// Start the booking trigger attempts after initial navigation delay
setTimeout(() => attemptBookingTrigger(), 500);
};
const handleContactUs = () => {
navigateTo('/contact');
onClose();
};
// Simple modal implementation that bypasses Dialog component issues
if (!isOpen) {
return null;
}
return (
<div
style={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: 'rgba(0, 0, 0, 0.5)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
zIndex: 9999
}}
onClick={onClose}
>
<div
style={{
background: 'white',
padding: '2rem',
borderRadius: '8px',
maxWidth: '500px',
width: '90%',
maxHeight: '80vh',
overflow: 'auto'
}}
onClick={(e) => e.stopPropagation()}
>
{/* Header */}
<div className="text-center space-y-4 mb-6">
<div
className="w-20 h-20 rounded-2xl flex items-center justify-center mx-auto"
style={{ backgroundColor: 'rgba(4, 4, 91, 0.1)' }}
>
<Building className="w-10 h-10 text-primary" />
</div>
<h2 className="text-h3">
Explore Our Learning Facility
</h2>
<p className="text-body text-muted">
Discover our world-class learning environment. Take a virtual tour to see our facilities or book your space for an upcoming event.
</p>
</div>
{/* Content */}
<div className="py-6 space-y-4">
{/* Test Message */}
<div className="text-center p-4 bg-green-100 rounded-lg">
<p className="text-body text-green-800">
🎉 Simple Modal is working! This popup opened successfully.
</p>
</div>
{/* Virtual Tour Option */}
<div className="rounded-lg border p-6 space-y-4 hover:shadow-md transition-shadow">
<div className="flex items-center gap-3">
<div
className="w-12 h-12 rounded-lg flex items-center justify-center"
style={{ backgroundColor: 'rgba(4, 4, 91, 0.1)' }}
>
<Eye className="w-6 h-6 text-primary" />
</div>
<div>
<h4 className="text-h4 mb-1">Virtual Tour</h4>
<p className="text-body text-muted">
Explore our four distinct learning environments
</p>
</div>
</div>
<Button
onClick={handleVirtualTour}
className="w-full"
style={{
backgroundColor: 'var(--color-primary)',
color: 'white'
}}
>
<Eye className="w-5 h-5 mr-2" />
Start Virtual Tour
<ArrowRight className="w-5 h-5 ml-2" />
</Button>
</div>
{/* Booking Option */}
<div className="rounded-lg border p-6 space-y-4 hover:shadow-md transition-shadow">
<div className="flex items-center gap-3">
<div
className="w-12 h-12 rounded-lg flex items-center justify-center"
style={{ backgroundColor: 'rgba(248, 195, 1, 0.1)' }}
>
<Calendar className="w-6 h-6" style={{ color: '#F8C301' }} />
</div>
<div>
<h4 className="text-h4 mb-1">Book Facility</h4>
<p className="text-body text-muted">
Reserve our learning spaces for your next event
</p>
</div>
</div>
<Button
onClick={handleBooking}
variant="outline"
className="w-full"
style={{
borderColor: 'var(--color-primary)',
color: 'var(--color-primary)'
}}
>
<Calendar className="w-5 h-5 mr-2" />
Book Now
<ArrowRight className="w-5 h-5 ml-2" />
</Button>
</div>
{/* Contact Us Option */}
<div className="pt-4 border-t">
<p className="text-center text-small text-muted mb-3">
Need more information or have specific requirements?
</p>
<Button
onClick={handleContactUs}
variant="ghost"
className="w-full text-body"
style={{ color: 'var(--color-primary)' }}
>
Contact Us
</Button>
</div>
{/* Close Button */}
<div className="pt-4">
<Button
onClick={onClose}
variant="outline"
className="w-full"
>
Close
</Button>
</div>
</div>
</div>
</div>
);
}

493
src/components/Cart.tsx Normal file
View File

@@ -0,0 +1,493 @@
import React from 'react';
import { Button } from './ui/button';
import { Card, CardContent } from './ui/card';
import { Badge } from './ui/badge';
import { Separator } from './ui/separator';
import {
ShoppingBag,
Trash2,
Plus,
ArrowRight,
Shield,
CheckCircle,
Home,
ChevronRight
} from 'lucide-react';
import { motion } from 'motion/react';
import { navigateTo } from './Router';
import { ImageWithFallback } from './figma/ImageWithFallback';
import { useCart } from './CartContext';
export function Cart() {
const { cartItems, removeFromCart, getCartTotal } = useCart();
// Calculate pricing
const subtotal = getCartTotal();
const gstRate = 0.18; // 18% GST
const gstAmount = subtotal * gstRate;
const total = subtotal + gstAmount;
const handleProceedToPayment = () => {
// Navigate to checkout/payment page
navigateTo('/checkout');
};
const handleAddMoreProgrammes = () => {
navigateTo('/learning-online');
};
return (
<div style={{ backgroundColor: '#FFFFFF' }}>
{/* Breadcrumb Navigation */}
<div className="section-margin-x py-6 border-b border-gray-200">
<div className="flex items-center gap-2 text-sm">
<button
onClick={() => navigateTo('/')}
className="flex items-center gap-1 text-gray-600 hover:text-gray-900 transition-colors"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
<Home className="w-4 h-4" />
Home
</button>
<ChevronRight className="w-4 h-4 text-gray-400" />
<span
className="text-gray-900 font-medium"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Cart
</span>
</div>
</div>
{/* Main Cart Content */}
<div className="section-margin-x py-8">
{/* Page Header */}
<div className="flex items-center gap-3 mb-8">
<div className="w-10 h-10 rounded-lg bg-gray-100 flex items-center justify-center">
<ShoppingBag className="w-5 h-5 text-gray-700" />
</div>
<div>
<h1
style={{
fontSize: 'var(--font-h2)',
fontWeight: 'var(--font-weight-h2)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-h2)'
}}
>
Shopping Cart
</h1>
<p
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
marginTop: '0.25rem'
}}
>
Review your selected programmes before proceeding to payment
</p>
</div>
</div>
{cartItems.length === 0 ? (
/* Empty Cart State */
<div className="text-center py-16">
<div className="w-24 h-24 mx-auto mb-6 rounded-full bg-gray-100 flex items-center justify-center">
<ShoppingBag className="w-10 h-10 text-gray-400" />
</div>
<h2
className="mb-4"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Your cart is empty
</h2>
<p
className="mb-8 max-w-md mx-auto"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-body)'
}}
>
Browse our comprehensive leadership development programmes and add them to your cart.
</p>
<Button
onClick={handleAddMoreProgrammes}
className="inline-flex items-center gap-2 h-12 px-6 rounded-lg font-medium"
style={{
backgroundColor: 'var(--color-primary)',
color: 'white',
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500'
}}
>
Browse Programmes
<ArrowRight className="w-4 h-4" />
</Button>
</div>
) : (
/* Cart with Items */
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
{/* Left Column - Cart Items */}
<div className="lg:col-span-2">
{/* Cart Items Header */}
<div className="flex items-center justify-between mb-6">
<div className="flex items-center gap-3">
<h2
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Cart Items ({cartItems.length})
</h2>
<Badge
className="px-3 py-1 rounded-full"
style={{
backgroundColor: 'rgba(248, 195, 1, 0.15)',
color: 'var(--color-black)',
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
{cartItems.length} programme{cartItems.length !== 1 ? 's' : ''}
</Badge>
</div>
</div>
{/* Cart Items List */}
<div className="space-y-6">
{cartItems.map((item, index) => (
<motion.div
key={item.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.1 }}
>
<Card className="overflow-hidden hover:shadow-md transition-all duration-300">
<CardContent className="p-6">
<div className="flex items-start gap-6">
{/* Programme Thumbnail */}
<div className="w-24 h-16 rounded-lg overflow-hidden flex-shrink-0 bg-gray-100">
<ImageWithFallback
src={item.thumbnail}
alt={item.title}
className="w-full h-full object-cover"
/>
</div>
{/* Programme Details */}
<div className="flex-1 min-w-0">
{/* Programme Title */}
<h3
className="mb-3 line-clamp-2"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-h4)'
}}
>
{item.title}
</h3>
{/* Course Details Row */}
<div className="flex flex-wrap items-center gap-4 mb-4">
<div className="flex items-center gap-2">
<span
className="text-xs px-3 py-1 bg-gray-100 rounded-full"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Course ID: {item.category.toUpperCase().slice(0, 3)}-{item.id}
</span>
<span
className="text-xs px-3 py-1 rounded-full"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-primary)',
backgroundColor: 'rgba(4, 4, 91, 0.1)',
fontFamily: 'var(--font-family-base)'
}}
>
{item.level}
</span>
<span
className="text-xs px-3 py-1 bg-blue-50 text-blue-700 rounded-full"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Advanced
</span>
</div>
</div>
{/* Pricing Row */}
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<span
className="font-bold"
style={{
fontSize: 'var(--font-h4)',
color: 'var(--color-primary)',
fontFamily: 'var(--font-family-base)'
}}
>
{item.price}
</span>
{item.originalPrice && (
<span
className="line-through"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
{item.originalPrice}
</span>
)}
</div>
{/* Remove Button */}
<Button
variant="ghost"
size="sm"
onClick={() => removeFromCart(item.id)}
className="text-red-500 hover:text-red-700 hover:bg-red-50 p-2"
>
<Trash2 className="w-4 h-4" />
</Button>
</div>
</div>
</div>
</CardContent>
</Card>
</motion.div>
))}
</div>
{/* Add More Programmes Button */}
<div className="mt-8 pt-6 border-t border-gray-200">
<Button
variant="outline"
onClick={handleAddMoreProgrammes}
className="flex items-center gap-2 h-12 px-6 rounded-lg border-2 border-dashed border-gray-300 hover:border-gray-400 transition-all duration-300 w-full"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500'
}}
>
<Plus className="w-5 h-5" />
Add More Programmes
</Button>
</div>
</div>
{/* Right Column - Order Summary */}
<div className="lg:col-span-1">
<Card className="sticky top-4">
<CardContent className="p-6">
{/* Order Summary Header */}
<h3
className="mb-6"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Order Summary
</h3>
{/* Pricing Breakdown */}
<div className="space-y-4 mb-6">
{/* Subtotal */}
<div className="flex justify-between">
<span
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Subtotal
</span>
<span
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500'
}}
>
{subtotal.toLocaleString('en-IN')}
</span>
</div>
{/* GST */}
<div className="flex justify-between">
<div className="flex items-center gap-2">
<span
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
GST (18%)
</span>
<div className="w-4 h-4 rounded-full bg-gray-200 flex items-center justify-center cursor-help">
<span className="text-xs text-gray-600">i</span>
</div>
</div>
<span
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500'
}}
>
{gstAmount.toLocaleString('en-IN')}
</span>
</div>
<Separator />
{/* Total */}
<div className="flex justify-between">
<span
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Total
</span>
<span
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-primary)',
fontFamily: 'var(--font-family-base)'
}}
>
{total.toLocaleString('en-IN')}
</span>
</div>
</div>
{/* Proceed to Payment Button */}
<Button
onClick={handleProceedToPayment}
className="w-full flex items-center justify-center gap-2 h-14 rounded-lg font-semibold mb-6"
style={{
backgroundColor: 'var(--color-primary)',
color: 'white',
fontSize: 'var(--font-body-lg)',
fontFamily: 'var(--font-family-base)'
}}
>
Proceed to Payment
<ArrowRight className="w-5 h-5" />
</Button>
{/* Security Features */}
<div className="space-y-3 pt-4 border-t border-gray-200">
<div className="flex items-center gap-3 text-sm">
<CheckCircle className="w-4 h-4 text-green-600 flex-shrink-0" />
<span
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Secure payment processing
</span>
</div>
<div className="flex items-center gap-3 text-sm">
<CheckCircle className="w-4 h-4 text-green-600 flex-shrink-0" />
<span
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Instant course access
</span>
</div>
<div className="flex items-center gap-3 text-sm">
<CheckCircle className="w-4 h-4 text-green-600 flex-shrink-0" />
<span
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Certificate upon completion
</span>
</div>
</div>
{/* Security Note */}
<div className="flex items-start gap-2 mt-6 p-4 bg-gray-50 rounded-lg">
<Shield className="w-4 h-4 text-gray-600 mt-0.5 flex-shrink-0" />
<div>
<p
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-small)'
}}
>
<strong>Need help with payment?</strong><br />
Our AI assistant can guide you through the checkout process and answer questions about course enrollment. Click the chat icon to get started.
</p>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
)}
</div>
</div>
);
}

View File

@@ -0,0 +1,99 @@
import React, { createContext, useContext, useState, useEffect } from 'react';
import { CartItem } from './CartPopup';
interface CartContextType {
cartItems: CartItem[];
cartCount: number;
addToCart: (item: CartItem) => void;
removeFromCart: (itemId: string) => void;
clearCart: () => void;
getCartTotal: () => number;
}
const CartContext = createContext<CartContextType | undefined>(undefined);
export function CartProvider({ children }: { children: React.ReactNode }) {
const [cartItems, setCartItems] = useState<CartItem[]>([]);
// Load cart from localStorage on mount
useEffect(() => {
const savedCart = localStorage.getItem('klc-cart');
if (savedCart) {
try {
const parsedCart = JSON.parse(savedCart);
if (Array.isArray(parsedCart)) {
setCartItems(parsedCart);
}
} catch (error) {
console.error('Error loading cart from localStorage:', error);
}
}
}, []);
// Save cart to localStorage whenever it changes
useEffect(() => {
localStorage.setItem('klc-cart', JSON.stringify(cartItems));
}, [cartItems]);
// Parse price helper function
const parsePrice = (priceStr: string) => {
const cleanPrice = priceStr.replace(/[₹$,]/g, '');
const numValue = parseFloat(cleanPrice);
return isNaN(numValue) ? 0 : numValue;
};
const addToCart = (item: CartItem) => {
setCartItems(prevItems => {
// Check if item already exists
const existingItem = prevItems.find(cartItem => cartItem.id === item.id);
if (existingItem) {
// Item already in cart, don't add duplicate
return prevItems;
}
// Add new item
return [...prevItems, item];
});
};
const removeFromCart = (itemId: string) => {
setCartItems(prevItems => prevItems.filter(item => item.id !== itemId));
};
const clearCart = () => {
setCartItems([]);
};
const getCartTotal = () => {
return cartItems.reduce((total, item) => {
const price = parsePrice(item.price);
return total + price;
}, 0);
};
const cartCount = cartItems.length;
const value: CartContextType = {
cartItems,
cartCount,
addToCart,
removeFromCart,
clearCart,
getCartTotal
};
return (
<CartContext.Provider value={value}>
{children}
</CartContext.Provider>
);
}
export function useCart() {
const context = useContext(CartContext);
if (context === undefined) {
throw new Error('useCart must be used within a CartProvider');
}
return context;
}

View File

@@ -0,0 +1,574 @@
import React, { useState, useEffect } from 'react';
import { X, CheckCircle, ShoppingCart, Trash2, Shield, ArrowRight } from 'lucide-react';
import { motion, AnimatePresence } from 'motion/react';
import { Button } from './ui/button';
import { ImageWithFallback } from './figma/ImageWithFallback';
import { navigateTo } from './Router';
import { useCart } from './CartContext';
export interface CartItem {
id: string;
title: string;
thumbnail: string;
price: string;
originalPrice?: string;
category: string;
level: string;
}
interface CartPopupProps {
isOpen: boolean;
onClose: () => void;
cartItems: CartItem[]; // Legacy prop - no longer used but kept for backward compatibility
onRemoveItem: (itemId: string) => void; // Legacy prop - no longer used but kept for backward compatibility
recentlyAddedItem?: CartItem | null;
}
export function CartPopup({
isOpen,
onClose,
cartItems: legacyCartItems, // Renamed to avoid confusion
onRemoveItem: legacyOnRemoveItem, // Renamed to avoid confusion
recentlyAddedItem
}: CartPopupProps) {
const [showSuccess, setShowSuccess] = useState(false);
// Use global cart context instead of props
const { cartItems, removeFromCart, getCartTotal } = useCart();
useEffect(() => {
if (recentlyAddedItem && isOpen) {
setShowSuccess(true);
const timer = setTimeout(() => setShowSuccess(false), 3000);
return () => clearTimeout(timer);
}
}, [recentlyAddedItem, isOpen]);
// Prevent background scrolling when popup is open
useEffect(() => {
if (isOpen) {
// Save current scroll position
const scrollY = window.scrollY;
// Prevent scrolling
document.body.style.overflow = 'hidden';
document.body.style.position = 'fixed';
document.body.style.top = `-${scrollY}px`;
document.body.style.width = '100%';
return () => {
// Restore scrolling
document.body.style.overflow = '';
document.body.style.position = '';
document.body.style.top = '';
document.body.style.width = '';
// Restore scroll position
window.scrollTo(0, scrollY);
};
}
}, [isOpen]);
// Fixed price parsing function - handles both ₹ and $ formats
const parsePrice = (priceStr: string) => {
// Remove currency symbols and commas, then parse
const cleanPrice = priceStr.replace(/[₹$,]/g, '');
const numValue = parseFloat(cleanPrice);
return isNaN(numValue) ? 0 : numValue;
};
// Convert to rupees - improved handling
const convertToRupees = (priceStr: string) => {
const numValue = parsePrice(priceStr);
// If already in rupees, return as is
if (priceStr.includes('₹')) {
return `${numValue.toLocaleString('en-IN')}`;
}
// Convert from USD to INR
return `${(numValue * 83).toLocaleString('en-IN')}`;
};
// Use global cart total instead of calculating locally
const subtotal = getCartTotal();
const estimatedTotal = subtotal; // No taxes for now
const handleProceedToCheckout = () => {
// Navigate to checkout page (placeholder)
navigateTo('/checkout');
onClose();
};
const handleContinueShopping = () => {
onClose();
};
// Handle backdrop click - close popup only if clicking on backdrop
const handleBackdropClick = (e: React.MouseEvent) => {
if (e.target === e.currentTarget) {
onClose();
}
};
return (
<AnimatePresence>
{isOpen && (
<>
{/* Backdrop with higher z-index than navbar */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 bg-black/50 backdrop-blur-sm"
style={{ zIndex: 10001 }} // Higher than navbar (navbar typically uses z-50 which is 50)
onClick={handleBackdropClick}
/>
{/* Cart Popup with highest z-index */}
<motion.div
initial={{ x: '100%' }}
animate={{ x: 0 }}
exit={{ x: '100%' }}
transition={{ type: 'spring', damping: 30, stiffness: 300 }}
className="fixed top-0 right-0 h-full w-full max-w-lg bg-white shadow-2xl overflow-hidden flex flex-col"
style={{
zIndex: 10002, // Highest z-index to be above everything including navbar
fontFamily: 'var(--font-family-base)'
}}
>
{/* Header */}
<div className="flex items-center justify-between p-6 border-b border-gray-200 bg-white">
<div className="flex items-center gap-3">
<div className="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center">
<CheckCircle className="w-5 h-5 text-green-600" />
</div>
<div>
<h2
className="font-semibold"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Added to Cart
</h2>
<p
className="text-muted"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
{cartItems.length} programme{cartItems.length !== 1 ? 's' : ''} in your cart
</p>
</div>
</div>
<Button
variant="ghost"
size="sm"
onClick={onClose}
className="p-2 hover:bg-gray-100 rounded-full"
>
<X className="w-5 h-5" />
</Button>
</div>
{/* Success Message */}
<AnimatePresence>
{showSuccess && recentlyAddedItem && (
<motion.div
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
className="mx-6 mt-4 p-4 bg-green-50 border border-green-200 rounded-lg"
>
<div className="flex items-start gap-3">
<CheckCircle className="w-5 h-5 text-green-600 mt-0.5 flex-shrink-0" />
<div className="flex-1">
<p
className="font-medium text-green-800"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)'
}}
>
"{recentlyAddedItem.title}" added successfully!
</p>
<p
className="text-green-600 mt-1"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
You can continue browsing or proceed to checkout.
</p>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
{/* Cart Content - Scrollable */}
<div className="flex-1 overflow-y-auto">
{/* Cart Items */}
<div className="p-6">
<div className="flex items-center justify-between mb-4">
<h3
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Your Cart ({cartItems.length})
</h3>
<p
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500'
}}
>
Total: {subtotal.toLocaleString('en-IN')}
</p>
</div>
{/* Cart Items List */}
<div className="space-y-4">
{cartItems.map((item, index) => (
<motion.div
key={item.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.1 }}
className="flex items-start gap-4 p-4 border border-gray-200 rounded-lg hover:border-gray-300 transition-colors"
>
{/* Course Thumbnail */}
<div className="w-20 h-14 rounded-lg overflow-hidden flex-shrink-0">
<ImageWithFallback
src={item.thumbnail}
alt={item.title}
className="w-full h-full object-cover"
/>
</div>
{/* Course Details */}
<div className="flex-1 min-w-0">
<h4
className="font-medium line-clamp-2 mb-1"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{item.title}
</h4>
<div className="flex items-center gap-2 mb-2">
<span
className="text-xs px-2 py-1 bg-gray-100 rounded-md"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Programme
</span>
<span
className="text-xs px-2 py-1 rounded-md"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-primary)',
backgroundColor: 'rgba(4, 4, 91, 0.1)',
fontFamily: 'var(--font-family-base)'
}}
>
{item.level}
</span>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<span
className="font-semibold"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-primary)',
fontFamily: 'var(--font-family-base)'
}}
>
{convertToRupees(item.price)}
</span>
{item.originalPrice && (
<span
className="line-through"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
{convertToRupees(item.originalPrice)}
</span>
)}
</div>
<Button
variant="ghost"
size="sm"
onClick={() => removeFromCart(item.id)}
className="p-2 text-red-500 hover:text-red-700 hover:bg-red-50"
>
<Trash2 className="w-4 h-4" />
</Button>
</div>
</div>
</motion.div>
))}
</div>
{/* Cart Summary */}
{cartItems.length > 0 && (
<div className="mt-6 p-4 bg-gray-50 rounded-lg border">
<div className="flex items-center gap-2 mb-3">
<ShoppingCart className="w-5 h-5 text-gray-600" />
<h4
style={{
fontSize: 'var(--font-body)',
fontWeight: '600',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Cart Summary
</h4>
</div>
<div className="space-y-2">
<div className="flex justify-between">
<span
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Total Items:
</span>
<span
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500'
}}
>
{cartItems.length} programme{cartItems.length !== 1 ? 's' : ''}
</span>
</div>
<div className="flex justify-between">
<span
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Subtotal:
</span>
<span
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)',
fontWeight: '600'
}}
>
{subtotal.toLocaleString('en-IN')}
</span>
</div>
<div className="flex justify-between font-semibold pt-2 border-t border-gray-200">
<span
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)',
fontWeight: '600'
}}
>
Estimated Total:
</span>
<span
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-primary)',
fontFamily: 'var(--font-family-base)',
fontWeight: '700'
}}
>
{estimatedTotal.toLocaleString('en-IN')}
</span>
</div>
<p
className="text-center mt-2"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Final total calculated at checkout
</p>
</div>
</div>
)}
{/* Total Value Highlight Box */}
{cartItems.length > 0 && (
<div
className="mt-6 p-6 rounded-lg text-center"
style={{ backgroundColor: 'rgba(4, 4, 91, 0.05)' }}
>
<h4
className="mb-2"
style={{
fontSize: 'var(--font-body)',
fontWeight: '600',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Total Value
</h4>
<div
className="mb-2"
style={{
fontSize: '2rem',
fontWeight: '700',
color: 'var(--color-primary)',
fontFamily: 'var(--font-family-base)'
}}
>
{estimatedTotal.toLocaleString('en-IN')}
</div>
<p
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-primary)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500'
}}
>
{cartItems.length} programme{cartItems.length !== 1 ? 's' : ''} selected
</p>
</div>
)}
{/* Empty Cart Message */}
{cartItems.length === 0 && (
<div className="text-center py-8">
<ShoppingCart className="w-16 h-16 mx-auto text-gray-300 mb-4" />
<h3
className="mb-2"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Your cart is empty
</h3>
<p
className="mb-6"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Browse our courses and add programmes to get started.
</p>
<Button
onClick={handleContinueShopping}
className="bg-primary text-white hover:bg-primary/90"
style={{
backgroundColor: 'var(--color-primary)',
fontFamily: 'var(--font-family-base)'
}}
>
Browse Courses
</Button>
</div>
)}
</div>
</div>
{/* Footer Actions */}
{cartItems.length > 0 && (
<div className="border-t border-gray-200 p-6 bg-white">
{/* CTA Buttons */}
<div className="space-y-3 mb-4">
{/* Proceed to Checkout - Primary */}
<Button
onClick={handleProceedToCheckout}
className="w-full flex items-center justify-center gap-2 h-12 rounded-lg font-medium"
style={{
backgroundColor: 'var(--color-primary)',
color: 'white',
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
fontWeight: '600'
}}
>
<ShoppingCart className="w-5 h-5" />
Proceed to Checkout
</Button>
{/* Continue Shopping - Secondary */}
<Button
variant="outline"
onClick={handleContinueShopping}
className="w-full flex items-center justify-center gap-2 h-12 rounded-lg font-medium"
style={{
borderColor: 'var(--color-primary)',
color: 'var(--color-primary)',
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500',
borderWidth: '2px'
}}
>
Continue Shopping
<ArrowRight className="w-4 h-4" />
</Button>
</div>
{/* Security Footer */}
<div className="flex items-center justify-center gap-2 pt-3 border-t border-gray-100">
<Shield className="w-4 h-4 text-green-600" />
<p
className="text-center"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Secure checkout 30-day money-back guarantee
</p>
</div>
</div>
)}
</motion.div>
</>
)}
</AnimatePresence>
);
}

250
src/components/Chatbot.tsx Normal file
View File

@@ -0,0 +1,250 @@
import React, { useState, useRef, useEffect } from 'react';
import { MessageCircle, X, Send, User, Bot, Minimize2 } from 'lucide-react';
import { Button } from './ui/button';
import exampleImage from 'figma:asset/a28d79dd35b730f689b77dbb30452ca27bd25759.png';
interface Message {
id: string;
text: string;
sender: 'user' | 'bot';
timestamp: Date;
}
export function Chatbot() {
const [isOpen, setIsOpen] = useState(false);
const [messages, setMessages] = useState<Message[]>([
{
id: '1',
text: 'Hello! I\'m here to help you learn more about Kautilya Leadership Centre. How can I assist you today?',
sender: 'bot',
timestamp: new Date()
}
]);
const [inputValue, setInputValue] = useState('');
const [isTyping, setIsTyping] = useState(false);
const messagesEndRef = useRef<HTMLDivElement>(null);
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
useEffect(() => {
scrollToBottom();
}, [messages]);
const predefinedResponses: { [key: string]: string } = {
'hello': 'Hello! Welcome to Kautilya Leadership Centre. I\'m here to help you with information about our programs, services, and how we can support your leadership development journey.',
'programs': 'We offer comprehensive leadership development programs including executive coaching, team development, strategic leadership training, and virtual learning experiences. Would you like to know more about any specific program?',
'services': 'Our services include Leadership Development, Executive Coaching, Team Building, Strategic Planning, Organizational Development, and Virtual Learning Platforms. Each is designed to enhance leadership capabilities.',
'contact': 'You can reach us through our contact form on the website, or feel free to schedule a consultation. We\'d be happy to discuss how we can support your leadership development goals.',
'virtual': 'Our virtual learning platform offers flexible, interactive leadership development experiences. You can access courses, participate in live sessions, and connect with other leaders from anywhere.',
'coaching': 'Our executive coaching program provides personalized one-on-one guidance to help leaders develop their skills, overcome challenges, and achieve their professional goals.',
'team': 'Our team development services focus on building high-performing teams through collaborative workshops, communication training, and strategic alignment exercises.',
'webinar': 'Join our upcoming leadership webinars! We regularly host sessions covering various leadership topics. Check our webinars section for schedules and registration.',
'default': 'That\'s a great question! For detailed information about our specific programs and services, I\'d recommend exploring our website or contacting our team directly. Is there anything specific about leadership development I can help you with?'
};
const getBotResponse = (userMessage: string): string => {
const lowerMessage = userMessage.toLowerCase();
for (const [key, response] of Object.entries(predefinedResponses)) {
if (key !== 'default' && lowerMessage.includes(key)) {
return response;
}
}
return predefinedResponses.default;
};
const handleSendMessage = async () => {
if (!inputValue.trim()) return;
const userMessage: Message = {
id: Date.now().toString(),
text: inputValue,
sender: 'user',
timestamp: new Date()
};
setMessages(prev => [...prev, userMessage]);
setInputValue('');
setIsTyping(true);
// Simulate typing delay
setTimeout(() => {
const botMessage: Message = {
id: (Date.now() + 1).toString(),
text: getBotResponse(inputValue),
sender: 'bot',
timestamp: new Date()
};
setMessages(prev => [...prev, botMessage]);
setIsTyping(false);
}, 1500);
};
const handleKeyPress = (e: React.KeyboardEvent) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
handleSendMessage();
}
};
const formatTime = (date: Date) => {
return date.toLocaleTimeString('en-US', {
hour: '2-digit',
minute: '2-digit',
hour12: true
});
};
return (
<>
{/* Chatbot Toggle Button */}
<div className="fixed bottom-6 right-6 z-50">
<button
onClick={() => setIsOpen(!isOpen)}
className="w-16 h-16 rounded-full shadow-xl transition-all duration-300 hover:scale-105 focus:outline-none focus:ring-4 focus:ring-blue-300 chatbot-button"
style={{
backgroundColor: '#04045B',
boxShadow: '0 8px 32px rgba(4, 4, 91, 0.3)'
}}
aria-label="Open chat"
>
{isOpen ? (
<X className="w-7 h-7 text-white mx-auto" />
) : (
<MessageCircle className="w-7 h-7 text-white mx-auto" />
)}
</button>
</div>
{/* Chatbot Window */}
{isOpen && (
<div
className="fixed bottom-24 right-6 w-80 bg-white rounded-2xl shadow-2xl border-0 z-50 flex flex-col overflow-hidden"
style={{
height: '500px',
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 0 0 1px rgba(255, 255, 255, 0.1)'
}}
>
{/* Header with gradient background */}
<div
className="p-6 flex items-center justify-between relative"
style={{
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
borderRadius: '16px 16px 0 0'
}}
>
<div className="flex items-center space-x-3">
<div className="w-10 h-10 bg-white/20 backdrop-blur-sm rounded-full flex items-center justify-center">
<Bot className="w-6 h-6 text-white" />
</div>
<div>
<h3 className="text-white font-semibold text-lg">Welcome to KLC</h3>
<p className="text-white/80 text-sm">How can I help you today?</p>
</div>
</div>
<div className="flex items-center space-x-2">
<button
onClick={() => setIsOpen(false)}
className="text-white/70 hover:text-white transition-colors p-1"
>
<Minimize2 className="w-4 h-4" />
</button>
<button
onClick={() => setIsOpen(false)}
className="text-white/70 hover:text-white transition-colors p-1"
>
<X className="w-5 h-5" />
</button>
</div>
</div>
{/* Messages Container */}
<div className="flex-1 p-5 overflow-y-auto space-y-4" style={{ backgroundColor: '#f8fafc' }}>
{messages.map((message) => (
<div
key={message.id}
className={`flex ${message.sender === 'user' ? 'justify-end' : 'justify-start'}`}
>
<div className={`flex items-start space-x-3 max-w-[85%] ${message.sender === 'user' ? 'flex-row-reverse space-x-reverse' : ''}`}>
<div className={`w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${
message.sender === 'user'
? 'bg-gradient-to-r from-blue-500 to-purple-600'
: 'bg-gradient-to-r from-purple-500 to-pink-500'
}`}>
{message.sender === 'user' ? (
<User className="w-4 h-4 text-white" />
) : (
<Bot className="w-4 h-4 text-white" />
)}
</div>
<div>
<div className={`p-4 rounded-2xl ${
message.sender === 'user'
? 'bg-gradient-to-r from-blue-500 to-purple-600 text-white'
: 'bg-white text-gray-800 shadow-sm border border-gray-100'
}`}>
<p className="text-sm leading-relaxed">{message.text}</p>
</div>
<p className="text-xs text-gray-400 mt-2 px-2">
{formatTime(message.timestamp)}
</p>
</div>
</div>
</div>
))}
{/* Typing Indicator */}
{isTyping && (
<div className="flex justify-start">
<div className="flex items-start space-x-3">
<div className="w-8 h-8 rounded-full bg-gradient-to-r from-purple-500 to-pink-500 flex items-center justify-center">
<Bot className="w-4 h-4 text-white" />
</div>
<div className="bg-white p-4 rounded-2xl shadow-sm border border-gray-100">
<div className="flex space-x-1">
<div className="w-2 h-2 bg-purple-400 rounded-full animate-bounce"></div>
<div className="w-2 h-2 bg-purple-400 rounded-full animate-bounce" style={{ animationDelay: '0.1s' }}></div>
<div className="w-2 h-2 bg-purple-400 rounded-full animate-bounce" style={{ animationDelay: '0.2s' }}></div>
</div>
</div>
</div>
</div>
)}
<div ref={messagesEndRef} />
</div>
{/* Input Area */}
<div className="p-5 bg-white border-t border-gray-100">
<div className="flex space-x-3">
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="Type your message..."
className="flex-1 px-4 py-3 border border-gray-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent text-sm bg-gray-50"
style={{ fontFamily: 'var(--font-family-brand)' }}
/>
<button
onClick={handleSendMessage}
disabled={!inputValue.trim()}
className="px-4 py-3 rounded-xl text-white transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-purple-500"
style={{
background: inputValue.trim()
? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
: '#e5e7eb'
}}
>
<Send className="w-5 h-5" />
</button>
</div>
</div>
</div>
)}
</>
);
}

558
src/components/Contact.tsx Normal file
View File

@@ -0,0 +1,558 @@
import React, { useState, useEffect } from 'react';
import { MapPin, Phone, Mail, Clock, CheckCircle2, ArrowRight, Send, Calendar, Users } from 'lucide-react';
import { Button } from './ui/button';
import { Input } from './ui/input';
import { Textarea } from './ui/textarea';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
import { BrandedTag } from './about/BrandedTag';
import { PrimaryCTAButton } from './PrimaryCTAButton';
import { ImageWithFallback } from './figma/ImageWithFallback';
import { navigateTo } from './Router';
interface ContactProps {
topic?: string;
}
export function Contact({ topic }: ContactProps) {
const [formData, setFormData] = useState({
firstName: '',
lastName: '',
email: '',
phone: '',
company: '',
jobTitle: '',
subject: topic || '',
message: '',
source: ''
});
const [isSubmitted, setIsSubmitted] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
useEffect(() => {
console.log('Contact component mounted with topic:', topic);
// Set default subject based on topic parameter
if (topic) {
const subject = getTopicSubject(topic);
console.log('Setting form subject to:', subject);
setFormData(prev => ({
...prev,
subject: subject
}));
}
}, [topic]);
const getTopicSubject = (topicParam: string) => {
switch (topicParam) {
case 'leadership-pipeline':
return 'Leadership Pipeline Development';
case 'consulting':
return 'Consulting Services';
case 'executive-coaching':
return 'Executive Coaching';
case 'learning-facility':
return 'Learning Facility';
default:
return topicParam.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
}
};
const handleInputChange = (field: string, value: string) => {
setFormData(prev => ({
...prev,
[field]: value
}));
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setIsSubmitting(true);
// Simulate form submission
await new Promise(resolve => setTimeout(resolve, 2000));
setIsSubmitted(true);
setIsSubmitting(false);
};
if (isSubmitted) {
return (
<div className="min-h-screen" style={{ backgroundColor: '#F7F7FD' }}>
<div className="section-margin-x py-24">
<div className="max-w-2xl mx-auto text-center">
<div className="w-20 h-20 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-6">
<CheckCircle2 className="w-10 h-10 text-green-600" />
</div>
<h1 className="text-h2 mb-4">Thank You!</h1>
<p className="text-body-lg text-muted mb-8">
We've received your message and will get back to you within 24 hours.
Our leadership development experts are excited to help transform your organization.
</p>
<PrimaryCTAButton
text="Return to Home"
onClick={() => navigateTo('/')}
ariaLabel="Return to homepage"
/>
</div>
</div>
</div>
);
}
return (
<div className="min-h-screen" style={{ backgroundColor: '#F7F7FD' }}>
{/* Hero Section with CTA Banner Styling */}
<section className="relative h-[600px] overflow-hidden">
{/* Background Image */}
<div className="absolute inset-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1600880292203-757bb62b4baf?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2940&q=80"
alt="Professional business meeting and consultation"
className="w-full h-full object-cover"
/>
{/* 40% black overlay for better text readability */}
<div className="absolute inset-0 bg-black/70" />
</div>
{/* Content Container */}
<div className="relative h-full flex items-center justify-center section-margin-x">
{/* Hero Content Block */}
<div className="text-center max-w-4xl mx-auto">
{/* Branded Tag */}
<BrandedTag text="Get In Touch" variant="white" />
{/* Main Headline */}
<h1 className="text-h1-white mb-6">
Ready to transform your leadership?
<span
className="italic"
style={{ color: 'var(--color-brand-accent)' }}
>
{" "}Let's connect{" "}
</span>
</h1>
{/* Supporting Text */}
<p className="text-body-lg-white opacity-90 max-w-3xl mx-auto">
To start your development journey.
</p>
</div>
</div>
</section>
{/* Main Content Section */}
<div className="section-margin-x py-16">
<div className="max-w-7xl mx-auto">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-12">
{/* Contact Information - Enhanced Design */}
<div className="lg:col-span-1">
<div className="bg-white rounded-xl shadow-lg border border-gray-100 h-fit overflow-hidden">
{/* Contact Info Header */}
<div
className="p-8 text-white"
style={{ backgroundColor: 'var(--color-brand-primary)' }}
>
<h2 className="text-h3-white mb-2">Contact Information</h2>
<p className="text-body-white opacity-90">
We're here to help you on your leadership journey
</p>
</div>
{/* Contact Details */}
<div className="p-8 space-y-8">
{/* Office Location */}
<div className="flex items-start gap-4">
<div
className="w-12 h-12 rounded-lg flex items-center justify-center flex-shrink-0"
style={{ backgroundColor: 'rgba(248, 195, 1, 0.1)' }}
>
<MapPin className="w-6 h-6" style={{ color: 'var(--color-brand-primary)' }} />
</div>
<div>
<h3 className="text-h3 mb-2">Office Location</h3>
<p className="text-body text-muted">
123 Leadership Avenue<br />
Business District, New Delhi<br />
110001, India
</p>
</div>
</div>
{/* Phone */}
<div className="flex items-start gap-4">
<div
className="w-12 h-12 rounded-lg flex items-center justify-center flex-shrink-0"
style={{ backgroundColor: 'rgba(248, 195, 1, 0.1)' }}
>
<Phone className="w-6 h-6" style={{ color: 'var(--color-brand-primary)' }} />
</div>
<div>
<h3 className="text-h3 mb-2">Phone</h3>
<p className="text-body text-muted">
+91 11 4567 8900<br />
+91 98765 43210
</p>
</div>
</div>
{/* Email */}
<div className="flex items-start gap-4">
<div
className="w-12 h-12 rounded-lg flex items-center justify-center flex-shrink-0"
style={{ backgroundColor: 'rgba(248, 195, 1, 0.1)' }}
>
<Mail className="w-6 h-6" style={{ color: 'var(--color-brand-primary)' }} />
</div>
<div>
<h3 className="text-h3 mb-2">Email</h3>
<p className="text-body text-muted">
info@klc.edu<br />
leadership@klc.edu
</p>
</div>
</div>
{/* Business Hours */}
<div className="flex items-start gap-4">
<div
className="w-12 h-12 rounded-lg flex items-center justify-center flex-shrink-0"
style={{ backgroundColor: 'rgba(248, 195, 1, 0.1)' }}
>
<Clock className="w-6 h-6" style={{ color: 'var(--color-brand-primary)' }} />
</div>
<div>
<h3 className="text-h3 mb-2">Business Hours</h3>
<p className="text-body text-muted">
Monday - Friday: 9:00 AM - 6:00 PM<br />
Saturday: 10:00 AM - 4:00 PM<br />
Sunday: Closed
</p>
</div>
</div>
</div>
{/* Quick Actions */}
<div
className="p-8 border-t"
style={{ borderColor: 'var(--color-border)' }}
>
<h3 className="text-h3 mb-4">Quick Actions</h3>
<div className="space-y-3">
<Button
variant="outline"
className="w-full justify-start hover:bg-blue-50 hover:border-blue-200 transition-all duration-300"
onClick={() => navigateTo('/services/learning-facility')}
style={{
borderColor: 'var(--color-brand-primary)',
color: 'var(--color-brand-primary)'
}}
>
<Calendar className="w-4 h-4 mr-2" />
Schedule Facility Tour
</Button>
<Button
variant="outline"
className="w-full justify-start hover:bg-blue-50 hover:border-blue-200 transition-all duration-300"
onClick={() => navigateTo('/leadership-journey')}
style={{
borderColor: 'var(--color-brand-primary)',
color: 'var(--color-brand-primary)'
}}
>
<Users className="w-4 h-4 mr-2" />
Start Leadership Assessment
</Button>
</div>
</div>
</div>
</div>
{/* Contact Form - Enhanced Design */}
<div className="lg:col-span-2">
<div className="bg-white rounded-xl shadow-lg border border-gray-100">
{/* Form Header */}
<div className="p-8 border-b" style={{ borderColor: 'var(--color-border)' }}>
<div className="flex items-center gap-3 mb-2">
<div
className="w-10 h-10 rounded-lg flex items-center justify-center"
style={{ backgroundColor: 'rgba(248, 195, 1, 0.1)' }}
>
<Send className="w-5 h-5" style={{ color: 'var(--color-brand-primary)' }} />
</div>
<h2 className="text-h3">Send us a Message</h2>
</div>
<p className="text-body text-muted">
Fill out the form below and we'll get back to you within 24 hours.
</p>
</div>
{/* Form Content */}
<div className="p-8">
<form onSubmit={handleSubmit} className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="text-body font-medium mb-3 block" style={{ color: 'var(--color-black)' }}>
First Name *
</label>
<Input
type="text"
required
value={formData.firstName}
onChange={(e) => handleInputChange('firstName', e.target.value)}
placeholder="John"
className="w-full h-12 border-gray-200 focus:border-blue-500 focus:ring-blue-500"
style={{
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-body)'
}}
/>
</div>
<div>
<label className="text-body font-medium mb-3 block" style={{ color: 'var(--color-black)' }}>
Last Name *
</label>
<Input
type="text"
required
value={formData.lastName}
onChange={(e) => handleInputChange('lastName', e.target.value)}
placeholder="Doe"
className="w-full h-12 border-gray-200 focus:border-blue-500 focus:ring-blue-500"
style={{
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-body)'
}}
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="text-body font-medium mb-3 block" style={{ color: 'var(--color-black)' }}>
Email Address *
</label>
<Input
type="email"
required
value={formData.email}
onChange={(e) => handleInputChange('email', e.target.value)}
placeholder="john.doe@company.com"
className="w-full h-12 border-gray-200 focus:border-blue-500 focus:ring-blue-500"
style={{
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-body)'
}}
/>
</div>
<div>
<label className="text-body font-medium mb-3 block" style={{ color: 'var(--color-black)' }}>
Phone Number
</label>
<Input
type="tel"
value={formData.phone}
onChange={(e) => handleInputChange('phone', e.target.value)}
placeholder="+91 98765 43210"
className="w-full h-12 border-gray-200 focus:border-blue-500 focus:ring-blue-500"
style={{
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-body)'
}}
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="text-body font-medium mb-3 block" style={{ color: 'var(--color-black)' }}>
Company/Organization
</label>
<Input
type="text"
value={formData.company}
onChange={(e) => handleInputChange('company', e.target.value)}
placeholder="Company Name"
className="w-full h-12 border-gray-200 focus:border-blue-500 focus:ring-blue-500"
style={{
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-body)'
}}
/>
</div>
<div>
<label className="text-body font-medium mb-3 block" style={{ color: 'var(--color-black)' }}>
Job Title
</label>
<Input
type="text"
value={formData.jobTitle}
onChange={(e) => handleInputChange('jobTitle', e.target.value)}
placeholder="CEO, HR Director, etc."
className="w-full h-12 border-gray-200 focus:border-blue-500 focus:ring-blue-500"
style={{
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-body)'
}}
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="text-body font-medium mb-3 block" style={{ color: 'var(--color-black)' }}>
Subject/Interest Area *
</label>
<Select
value={formData.subject}
onValueChange={(value) => handleInputChange('subject', value)}
>
<SelectTrigger
className="w-full h-12 border-gray-200 focus:border-blue-500 focus:ring-blue-500"
style={{
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-body)'
}}
>
<SelectValue placeholder="Select a subject" />
</SelectTrigger>
<SelectContent>
<SelectItem value="Leadership Pipeline Development">Leadership Pipeline Development</SelectItem>
<SelectItem value="Executive Coaching">Executive Coaching</SelectItem>
<SelectItem value="Management Development">Management Development</SelectItem>
<SelectItem value="Culture Competence">Culture Competence</SelectItem>
<SelectItem value="Consulting Services">Consulting Services</SelectItem>
<SelectItem value="Learning Facility">Learning Facility Tour</SelectItem>
<SelectItem value="Online Courses">Online Learning Programs</SelectItem>
<SelectItem value="General Inquiry">General Inquiry</SelectItem>
</SelectContent>
</Select>
</div>
<div>
<label className="text-body font-medium mb-3 block" style={{ color: 'var(--color-black)' }}>
How did you hear about us?
</label>
<Select
value={formData.source}
onValueChange={(value) => handleInputChange('source', value)}
>
<SelectTrigger
className="w-full h-12 border-gray-200 focus:border-blue-500 focus:ring-blue-500"
style={{
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-body)'
}}
>
<SelectValue placeholder="Select an option" />
</SelectTrigger>
<SelectContent>
<SelectItem value="Website">Website</SelectItem>
<SelectItem value="Google Search">Google Search</SelectItem>
<SelectItem value="Social Media">Social Media</SelectItem>
<SelectItem value="Referral">Referral</SelectItem>
<SelectItem value="Event/Conference">Event/Conference</SelectItem>
<SelectItem value="LinkedIn">LinkedIn</SelectItem>
<SelectItem value="Email Marketing">Email Marketing</SelectItem>
<SelectItem value="Other">Other</SelectItem>
</SelectContent>
</Select>
</div>
</div>
<div>
<label className="text-body font-medium mb-3 block" style={{ color: 'var(--color-black)' }}>
Message *
</label>
<Textarea
required
value={formData.message}
onChange={(e) => handleInputChange('message', e.target.value)}
placeholder="Tell us about your leadership development needs, goals, or any specific questions you have..."
rows={6}
className="w-full border-gray-200 focus:border-blue-500 focus:ring-blue-500 resize-none"
style={{
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-body)'
}}
/>
</div>
<div className="pt-6 border-t" style={{ borderColor: 'var(--color-border)' }}>
<div className="flex flex-col sm:flex-row gap-4 justify-between items-start sm:items-center">
<div className="text-small text-muted">
* Required fields. We'll respond within 24 hours.
</div>
<PrimaryCTAButton
text={isSubmitting ? "Sending Message..." : "Send Message"}
onClick={() => {}}
ariaLabel="Send contact message"
disabled={isSubmitting}
className="w-full sm:w-auto"
/>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Enhanced CTA Section - Matching Landing Page Style */}
<section className="relative h-[800px] overflow-hidden">
{/* Background Image */}
<div className="absolute inset-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2940&q=80"
alt="Professional team collaborating in modern office"
className="w-full h-full object-cover"
/>
{/* Subtle dark overlay for overall image */}
<div className="absolute inset-0 bg-black/30" />
</div>
{/* Content Container */}
<div className="relative h-full flex items-center justify-end section-margin-x">
{/* CTA Content Block */}
<div
className="bg-opacity-95 backdrop-blur-sm rounded-lg p-16 max-w-2xl"
style={{
backgroundColor: 'var(--color-brand-primary)'
}}
>
{/* Branded Tag */}
<BrandedTag text="Next Steps" variant="white" />
{/* Main Headline */}
<h2 className="text-h2-white mb-8">
Ready to transform your leadership?
<span
className="italic"
style={{ color: 'var(--color-brand-accent)' }}
>
{" "}Get in touch{" "}
</span>
to start your development journey now.
</h2>
<PrimaryCTAButton
text="Schedule a Consultation"
onClick={() => navigateTo('/contact?topic=consulting')}
ariaLabel="Schedule a consultation with our leadership experts"
className="cta-banner-yellow"
/>
{/* Supporting Text */}
<p className="text-body-white opacity-90">
Connect with our leadership experts to discuss your organization's specific development needs.
</p>
</div>
</div>
</section>
</div>
);
}

View File

@@ -0,0 +1,527 @@
import React, { useState } from 'react';
import { Button } from './ui/button';
import { Input } from './ui/input';
import { Label } from './ui/label';
import { Card, CardContent } from './ui/card';
import { Checkbox } from './ui/checkbox';
import {
Users,
BarChart3,
Settings,
ArrowRight,
Eye,
EyeOff,
Building2,
BookOpen,
Target,
Award,
User
} from 'lucide-react';
import { navigateTo } from './Router';
export function CorporateSignIn() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [showPassword, setShowPassword] = useState(false);
const [rememberMe, setRememberMe] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const handleSignIn = async (e: React.FormEvent) => {
e.preventDefault();
setIsLoading(true);
// Simulate authentication
setTimeout(() => {
setIsLoading(false);
// Navigate to dashboard or success page
navigateTo('/dashboard');
}, 1500);
};
const transformationFeatures = [
{
icon: BookOpen,
title: 'World-Class Content',
description: 'Access premium leadership courses from industry experts'
},
{
icon: Users,
title: 'Global Community',
description: 'Join 25,000+ leaders from top organizations worldwide'
},
{
icon: Award,
title: 'Recognized Credentials',
description: 'Earn certificates valued by Fortune 500 companies'
},
{
icon: Target,
title: 'Personalized Path',
description: 'Get customized learning recommendations based on your goals'
}
];
const corporateFeatures = [
{
icon: Users,
title: 'Bulk Enrollment',
description: 'Enroll entire teams with volume discounts up to 30%'
},
{
icon: BarChart3,
title: 'Progress Analytics',
description: 'Real-time dashboards to track team learning outcomes'
},
{
icon: Settings,
title: 'Custom Programs',
description: 'Tailored leadership development aligned with your goals'
}
];
return (
<div style={{ backgroundColor: '#FFFFFF' }}>
{/* Main Content */}
<div className="section-margin-x py-16">
<div className="max-w-6xl mx-auto">
{/* Header Section */}
<div className="text-center mb-12">
<div className="mb-6">
<span
className="inline-flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium"
style={{
backgroundColor: 'rgba(248, 195, 1, 0.15)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
<Building2 className="w-4 h-4" />
Corporate Solutions
</span>
</div>
<h1
className="mb-6"
style={{
fontSize: 'var(--font-h2)',
fontWeight: 'var(--font-weight-h2)',
lineHeight: 'var(--line-height-h2)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Welcome Back, KLC Partner
</h1>
<p
className="mb-12 max-w-2xl mx-auto"
style={{
fontSize: 'var(--font-body-lg)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-body-lg)'
}}
>
Access your corporate dashboard to manage team enrollments, track learning
progress, and continue building your organization's leadership capabilities.
</p>
</div>
{/* Two Column Layout */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-start">
{/* Left Column - Content */}
<div>
{/* Leadership Transformation Section */}
<div className="mb-12">
<div className="mb-6">
<span
className="inline-flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium"
style={{
backgroundColor: 'rgba(248, 195, 1, 0.15)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
⭐ Join KLC Community
</span>
</div>
<h2
className="mb-4"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Start Your Leadership Transformation
</h2>
<p
className="mb-8"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-body)'
}}
>
Join thousands of professionals who have accelerated their careers through KLC's
proven leadership development programs. Your journey to becoming an exceptional leader starts here.
</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{transformationFeatures.map((feature, index) => (
<div key={index} className="flex items-start gap-3">
<div
className="w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0"
style={{ backgroundColor: 'var(--color-primary)' }}
>
<feature.icon className="w-4 h-4 text-white" />
</div>
<div className="flex-1">
<h3
className="font-medium mb-1"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{feature.title}
</h3>
<p
style={{
fontSize: '0.75rem',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: '1.3'
}}
>
{feature.description}
</p>
</div>
</div>
))}
</div>
</div>
{/* Corporate Dashboard Features */}
<div>
<h2
className="mb-8"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Corporate Dashboard Features
</h2>
<div className="space-y-6">
{corporateFeatures.map((feature, index) => (
<div key={index} className="flex items-start gap-4">
<div
className="w-12 h-12 rounded-lg flex items-center justify-center flex-shrink-0"
style={{ backgroundColor: 'var(--color-primary)' }}
>
<feature.icon className="w-6 h-6 text-white" />
</div>
<div className="flex-1">
<h3
className="font-medium mb-2"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{feature.title}
</h3>
<p
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-small)'
}}
>
{feature.description}
</p>
</div>
</div>
))}
</div>
{/* Existing Customer Note */}
<div
className="mt-8 p-4 rounded-lg border"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.02)' }}
>
<p
className="mb-2"
style={{
fontSize: 'var(--font-small)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Already have a corporate account?
</p>
<button
onClick={() => navigateTo('/corporate-login')}
className="text-blue-600 hover:text-blue-700 transition-colors"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Sign in to your dashboard
</button>
</div>
</div>
</div>
{/* Right Column - Sign In Form */}
<div>
<Card className="shadow-lg border-0">
<CardContent className="p-8">
{/* Form Header */}
<div className="text-center mb-8">
<h2
className="mb-2"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Sign In to Your Dashboard
</h2>
<p
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Manage your corporate learning programs
</p>
</div>
{/* Sign In Form */}
<form onSubmit={handleSignIn} className="space-y-6">
{/* Email Field */}
<div>
<Label
htmlFor="email"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Work Email *
</Label>
<Input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="your.work@company.com"
required
className="mt-2 h-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)'
}}
/>
</div>
{/* Password Field */}
<div>
<Label
htmlFor="password"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Password *
</Label>
<div className="relative mt-2">
<Input
id="password"
type={showPassword ? 'text' : 'password'}
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Enter your password"
required
className="h-12 pr-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)'
}}
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500 hover:text-gray-700"
>
{showPassword ? <EyeOff className="w-5 h-5" /> : <Eye className="w-5 h-5" />}
</button>
</div>
</div>
{/* Remember Me */}
<div className="flex items-center space-x-2">
<Checkbox
id="remember"
checked={rememberMe}
onCheckedChange={setRememberMe}
/>
<Label
htmlFor="remember"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Remember me
</Label>
</div>
{/* Sign In Button */}
<Button
type="submit"
disabled={isLoading}
className="w-full h-14 text-white font-medium flex items-center justify-center gap-2"
style={{
backgroundColor: 'var(--color-primary)',
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
borderRadius: '10px'
}}
>
{isLoading ? (
<div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
) : (
<>
Sign In
<ArrowRight className="w-5 h-5" />
</>
)}
</Button>
</form>
{/* Demo Credentials */}
<div
className="mt-8 p-4 rounded-lg border"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.02)' }}
>
<h4
className="mb-2 flex items-center gap-2"
style={{
fontSize: 'var(--font-small)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
<div className="w-4 h-4 rounded-full bg-gray-300 flex items-center justify-center">
<span className="text-xs text-gray-600">i</span>
</div>
Demo credentials:
</h4>
<div
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-small)'
}}
>
<p>Email: demo@company.com | Password: demo123</p>
<p>MFA Demo: mfa@company.com | Password: demo123 (Code: 123456)</p>
</div>
</div>
{/* Sign Up Link */}
<div className="text-center mt-8">
<button
onClick={() => navigateTo('/corporate-signup')}
className="text-blue-600 hover:text-blue-700 transition-colors"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
New to KLC? Sign up your company
</button>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
</div>
{/* Need Help Section - Separate Section Below */}
<div
className="section-margin-x py-12"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.02)' }}
>
<div className="max-w-4xl mx-auto text-center">
<h3
className="mb-4"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Need Help with Onboarding?
</h3>
<p
className="mb-6"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-body)'
}}
>
Our team is ready to help you set up your corporate learning program and answer any questions about our enterprise solutions.
</p>
<Button
variant="outline"
className="border-2 border-blue-600 text-blue-600 hover:bg-blue-600 hover:text-white"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500',
padding: '0.75rem 2rem',
borderRadius: '10px'
}}
>
Contact Sales Team
</Button>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,655 @@
import React, { useState } from 'react';
import { Button } from './ui/button';
import { Input } from './ui/input';
import { Label } from './ui/label';
import { Card, CardContent } from './ui/card';
import { Checkbox } from './ui/checkbox';
import {
Users,
BarChart3,
Settings,
ArrowRight,
Eye,
EyeOff,
Building2,
Globe,
User,
Mail,
Lock,
Phone,
BookOpen,
Target,
Award
} from 'lucide-react';
import { navigateTo } from './Router';
export function CorporateSignUp() {
const [formData, setFormData] = useState({
organisationName: '',
officialDomain: '',
contactName: '',
workEmail: '',
password: '',
phoneNumber: ''
});
const [showPassword, setShowPassword] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const handleInputChange = (field: string, value: string) => {
setFormData(prev => ({ ...prev, [field]: value }));
};
const handleSignUp = async (e: React.FormEvent) => {
e.preventDefault();
setIsLoading(true);
// Simulate registration
setTimeout(() => {
setIsLoading(false);
// Navigate to dashboard or success page
navigateTo('/dashboard');
}, 2000);
};
const transformationFeatures = [
{
icon: BookOpen,
title: 'World-Class Content',
description: 'Access premium leadership courses from industry experts'
},
{
icon: Users,
title: 'Global Community',
description: 'Join 25,000+ leaders from top organizations worldwide'
},
{
icon: Award,
title: 'Recognized Credentials',
description: 'Earn certificates valued by Fortune 500 companies'
},
{
icon: Target,
title: 'Personalized Path',
description: 'Get customized learning recommendations based on your goals'
}
];
const corporateFeatures = [
{
icon: Users,
title: 'Team Management',
description: 'Centralized dashboard to manage multiple learner accounts and progress tracking'
},
{
icon: BarChart3,
title: 'Advanced Analytics',
description: 'Comprehensive reporting and insights on team learning outcomes and ROI'
},
{
icon: Settings,
title: 'Custom Solutions',
description: 'Tailored programs designed specifically for your organization\'s goals'
}
];
return (
<div style={{ backgroundColor: '#FFFFFF' }}>
{/* Main Content */}
<div className="section-margin-x py-16">
<div className="max-w-6xl mx-auto">
{/* Header Section */}
<div className="text-center mb-12">
<div className="mb-6">
<span
className="inline-flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium"
style={{
backgroundColor: 'rgba(248, 195, 1, 0.15)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
<Building2 className="w-4 h-4" />
Corporate Registration
</span>
</div>
<h1
className="mb-6"
style={{
fontSize: 'var(--font-h2)',
fontWeight: 'var(--font-weight-h2)',
lineHeight: 'var(--line-height-h2)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Transform Your Organization's Leadership
</h1>
<p
className="mb-12 max-w-2xl mx-auto"
style={{
fontSize: 'var(--font-body-lg)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-body-lg)'
}}
>
Join thousands of organizations worldwide who trust KLC to develop their leaders.
Get started with enterprise-grade learning solutions and dedicated support.
</p>
</div>
{/* Two Column Layout */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-start">
{/* Left Column - Content */}
<div>
{/* Leadership Transformation Section */}
<div className="mb-12">
<div className="mb-6">
<span
className="inline-flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium"
style={{
backgroundColor: 'rgba(248, 195, 1, 0.15)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
⭐ Join KLC Community
</span>
</div>
<h2
className="mb-4"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Start Your Leadership Transformation
</h2>
<p
className="mb-8"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-body)'
}}
>
Join thousands of professionals who have accelerated their careers through KLC's
proven leadership development programs. Your journey to becoming an exceptional leader starts here.
</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{transformationFeatures.map((feature, index) => (
<div key={index} className="flex items-start gap-3">
<div
className="w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0"
style={{ backgroundColor: 'var(--color-primary)' }}
>
<feature.icon className="w-4 h-4 text-white" />
</div>
<div className="flex-1">
<h3
className="font-medium mb-1"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{feature.title}
</h3>
<p
style={{
fontSize: '0.75rem',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: '1.3'
}}
>
{feature.description}
</p>
</div>
</div>
))}
</div>
</div>
{/* What You'll Get with Corporate Access */}
<div>
<h2
className="mb-8"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
What You'll Get with Corporate Access
</h2>
<div className="space-y-6">
{corporateFeatures.map((feature, index) => (
<div key={index} className="flex items-start gap-4">
<div
className="w-12 h-12 rounded-lg flex items-center justify-center flex-shrink-0"
style={{ backgroundColor: 'var(--color-primary)' }}
>
<feature.icon className="w-6 h-6 text-white" />
</div>
<div className="flex-1">
<h3
className="font-medium mb-2"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{feature.title}
</h3>
<p
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-small)'
}}
>
{feature.description}
</p>
</div>
</div>
))}
</div>
{/* Existing Customer Note */}
<div
className="mt-8 p-4 rounded-lg border"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.02)' }}
>
<p
className="mb-2"
style={{
fontSize: 'var(--font-small)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Already have a corporate account?
</p>
<button
onClick={() => navigateTo('/corporate-login')}
className="text-blue-600 hover:text-blue-700 transition-colors"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Sign in to your dashboard
</button>
</div>
</div>
</div>
{/* Right Column - Sign Up Form */}
<div>
<Card className="shadow-lg border-0">
<CardContent className="p-8">
{/* Form Header */}
<div className="text-center mb-8">
<h2
className="mb-2"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Create Your KLC HR Account
</h2>
<p
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Get started with KLC's corporate leadership development programs
</p>
</div>
{/* Sign Up Form */}
<form onSubmit={handleSignUp} className="space-y-6">
{/* Organisation Name */}
<div>
<Label
htmlFor="organisationName"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Organisation Name *
</Label>
<div className="relative mt-2">
<div className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500">
<Building2 className="w-5 h-5" />
</div>
<Input
id="organisationName"
type="text"
value={formData.organisationName}
onChange={(e) => handleInputChange('organisationName', e.target.value)}
placeholder="Your Company Name"
required
className="h-12 pl-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
backgroundColor: '#F3F3F5'
}}
/>
</div>
</div>
{/* Official Domain */}
<div>
<Label
htmlFor="officialDomain"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Official Domain *
</Label>
<div className="relative mt-2">
<div className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500">
<Globe className="w-5 h-5" />
</div>
<Input
id="officialDomain"
type="text"
value={formData.officialDomain}
onChange={(e) => handleInputChange('officialDomain', e.target.value)}
placeholder="company.com"
required
className="h-12 pl-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
backgroundColor: '#F3F3F5'
}}
/>
</div>
</div>
{/* Contact Name */}
<div>
<Label
htmlFor="contactName"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Contact Name *
</Label>
<div className="relative mt-2">
<div className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500">
<User className="w-5 h-5" />
</div>
<Input
id="contactName"
type="text"
value={formData.contactName}
onChange={(e) => handleInputChange('contactName', e.target.value)}
placeholder="Your full name"
required
className="h-12 pl-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
backgroundColor: '#F3F3F5'
}}
/>
</div>
</div>
{/* Work Email */}
<div>
<Label
htmlFor="workEmail"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Work Email *
</Label>
<div className="relative mt-2">
<div className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500">
<Mail className="w-5 h-5" />
</div>
<Input
id="workEmail"
type="email"
value={formData.workEmail}
onChange={(e) => handleInputChange('workEmail', e.target.value)}
placeholder="you@company.com"
required
className="h-12 pl-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
backgroundColor: '#F3F3F5'
}}
/>
</div>
</div>
{/* Password */}
<div>
<Label
htmlFor="password"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Password *
</Label>
<div className="relative mt-2">
<div className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500">
<Lock className="w-5 h-5" />
</div>
<Input
id="password"
type={showPassword ? 'text' : 'password'}
value={formData.password}
onChange={(e) => handleInputChange('password', e.target.value)}
placeholder="Create a strong password"
required
className="h-12 pl-12 pr-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
backgroundColor: '#F3F3F5'
}}
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500 hover:text-gray-700"
>
{showPassword ? <EyeOff className="w-5 h-5" /> : <Eye className="w-5 h-5" />}
</button>
</div>
</div>
{/* Phone Number (Optional) */}
<div>
<Label
htmlFor="phoneNumber"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Phone Number (Optional)
</Label>
<div className="relative mt-2">
<div className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500">
<Phone className="w-5 h-5" />
</div>
<Input
id="phoneNumber"
type="tel"
value={formData.phoneNumber}
onChange={(e) => handleInputChange('phoneNumber', e.target.value)}
placeholder="+1 234 567 8900"
className="h-12 pl-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
backgroundColor: '#F3F3F5'
}}
/>
</div>
</div>
{/* Create Account Button */}
<Button
type="submit"
disabled={isLoading}
className="w-full h-14 text-white font-medium flex items-center justify-center gap-2"
style={{
backgroundColor: 'var(--color-primary)',
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
borderRadius: '10px'
}}
>
{isLoading ? (
<div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
) : (
<>
Create Account
<ArrowRight className="w-5 h-5" />
</>
)}
</Button>
</form>
{/* Terms Text */}
<div className="text-center mt-6">
<p
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-small)'
}}
>
By creating an account, you agree to our{' '}
<span className="text-blue-600 hover:text-blue-700 cursor-pointer">
Corporate Terms
</span>{' '}
and{' '}
<span className="text-blue-600 hover:text-blue-700 cursor-pointer">
Privacy Policy
</span>
</p>
</div>
{/* Sign In Link */}
<div className="text-center mt-6">
<button
onClick={() => navigateTo('/corporate-login')}
className="text-blue-600 hover:text-blue-700 transition-colors"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Already have an account? Sign in instead
</button>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
</div>
{/* Need Help Section - Separate Section Below */}
<div
className="section-margin-x py-12"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.02)' }}
>
<div className="max-w-4xl mx-auto text-center">
<h3
className="mb-4"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Need Help Getting Started?
</h3>
<p
className="mb-6"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-body)'
}}
>
Our team is ready to help you set up your corporate learning program and answer any questions about our enterprise solutions.
</p>
<Button
variant="outline"
className="border-2 border-blue-600 text-blue-600 hover:bg-blue-600 hover:text-white"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500',
padding: '0.75rem 2rem',
borderRadius: '10px'
}}
>
Contact Sales Team
</Button>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,280 @@
import React from 'react';
import { Button } from './ui/button';
import { Badge } from './ui/badge';
import {
Users,
Clock,
Star,
ArrowRight,
ShoppingCart
} from 'lucide-react';
import { motion } from 'motion/react';
import { navigateTo } from './Router';
import { ImageWithFallback } from './figma/ImageWithFallback';
import type { CartItem } from './CartPopup';
// Course type interface
export interface Course {
id: string;
title: string;
thumbnail: string;
duration: string;
level: string;
format: string;
rating: number;
participants: string;
category: string;
description: string;
price: string;
originalPrice?: string; // For showing discounted prices
}
interface CourseCardProps {
course: Course;
onClick?: () => void;
className?: string;
onAddToCart?: (item: CartItem) => void;
}
export function CourseCard({ course, onClick, className, onAddToCart }: CourseCardProps) {
const handleClick = () => {
if (onClick) {
onClick();
} else {
navigateTo(`/course/${course.id}`);
}
};
const handleAddToCart = (e: React.MouseEvent) => {
e.stopPropagation(); // Prevent card click when clicking Add to Cart
if (onAddToCart) {
const cartItem: CartItem = {
id: course.id,
title: course.title,
thumbnail: course.thumbnail,
price: course.price,
originalPrice: course.originalPrice,
category: course.category,
level: course.level
};
onAddToCart(cartItem);
}
};
return (
<motion.div
className={`flex-shrink-0 w-96 h-[560px] bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden hover:shadow-xl transition-all duration-300 cursor-pointer group flex flex-col ${className || ''}`}
onClick={handleClick}
>
{/* Course Image with Category Badge */}
<div className="relative aspect-[16/9] overflow-hidden flex-shrink-0">
<ImageWithFallback
src={course.thumbnail}
alt={course.title}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
/>
<div className="absolute top-4 left-4">
<Badge
variant="secondary"
className="px-3 py-1 font-medium"
style={{
backgroundColor: 'rgba(248, 195, 1, 0.95)',
color: 'var(--color-black)',
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)',
backdropFilter: 'blur(4px)'
}}
>
{course.category}
</Badge>
</div>
<div className="absolute top-4 right-4">
<Badge
variant="outline"
className="px-3 py-1 font-medium bg-white/90 backdrop-blur-sm"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)',
borderColor: 'var(--color-primary)',
color: 'var(--color-primary)'
}}
>
{course.level}
</Badge>
</div>
</div>
{/* Card Content - Reduced horizontal padding */}
<div className="p-5 flex flex-col flex-1">
{/* Course Title */}
<h3
className="mb-3 group-hover:text-blue-600 transition-colors leading-snug"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
lineHeight: '1.3',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{course.title}
</h3>
{/* Course Description - Limited to 2 lines with ellipsis */}
<p
className="mb-5 line-clamp-2 leading-relaxed"
style={{
fontSize: 'var(--font-body)',
lineHeight: '1.5',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
display: '-webkit-box',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
textOverflow: 'ellipsis'
}}
>
{course.description}
</p>
{/* Course Meta Information - Reduced bottom margin */}
<div className="flex items-center justify-between mb-5 pt-3 border-t border-gray-100">
<div className="flex items-center gap-5">
<div className="flex items-center gap-2">
<Clock className="w-4 h-4 text-gray-400" />
<span style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-gray-muted)',
fontWeight: '500'
}}>
{course.duration}
</span>
</div>
<div className="flex items-center gap-2">
<Users className="w-4 h-4 text-gray-400" />
<span style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-gray-muted)',
fontWeight: '500'
}}>
{course.participants}
</span>
</div>
</div>
<div className="flex items-center gap-1">
<Star className="w-4 h-4 fill-current text-yellow-400" />
<span
className="font-semibold"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{course.rating}
</span>
</div>
</div>
{/* Pricing Section - Reduced bottom margin */}
<div className="mb-5">
<div className="flex items-center justify-between">
<div className="flex items-baseline gap-3">
<span
className="font-bold"
style={{
fontSize: '1.75rem',
fontFamily: 'var(--font-family-base)',
color: '#04045B'
}}
>
{course.price}
</span>
{course.originalPrice && (
<span
className="line-through"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-gray-muted)'
}}
>
{course.originalPrice}
</span>
)}
</div>
{course.originalPrice && (
<div className="text-right">
<span
className="text-green-600 font-semibold text-sm"
style={{
fontFamily: 'var(--font-family-base)'
}}
>
Save {Math.round(((parseFloat(course.originalPrice.replace('$', '')) - parseFloat(course.price.replace('$', ''))) / parseFloat(course.originalPrice.replace('$', ''))) * 100)}%
</span>
</div>
)}
</div>
</div>
{/* Action Buttons - Horizontal Layout with reduced gap */}
<div className="flex flex-row gap-2 mt-auto">
{/* Add to Cart Button - Outline Blue */}
<Button
variant="outline"
onClick={handleAddToCart}
className="flex-1 flex items-center justify-center gap-2 h-11 rounded-lg transition-all duration-200 font-medium"
style={{
borderColor: '#04045B',
color: '#04045B',
backgroundColor: 'transparent',
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500',
borderWidth: '2px'
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = '#04045B';
e.currentTarget.style.color = 'white';
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = 'transparent';
e.currentTarget.style.color = '#04045B';
}}
>
<ShoppingCart className="w-4 h-4" />
Add to Cart
</Button>
{/* Learn More Button - Solid Blue */}
<Button
className="flex-1 flex items-center justify-center gap-2 h-11 rounded-lg transition-all duration-200 font-medium"
style={{
backgroundColor: '#04045B',
color: 'white',
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500',
border: 'none'
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = '#030359';
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = '#04045B';
}}
>
Learn More
<ArrowRight className="w-4 h-4" />
</Button>
</div>
</div>
</motion.div>
);
}

View File

@@ -0,0 +1,235 @@
import React from 'react';
import { Badge } from './ui/badge';
import { Card, CardContent, CardHeader, CardTitle } from './ui/card';
import { Button } from './ui/button';
import { ImageWithFallback } from './figma/ImageWithFallback';
import { navigateTo } from './Router';
import { CheckCircle, ArrowRight, Clock, Users, Star } from 'lucide-react';
// Service Card Component
export function ServiceCard({ service }) {
const IconComponent = service.icon;
return (
<Card className="border hover:shadow-lg transition-all duration-300 group h-full" style={{ backgroundColor: 'var(--color-bg-white)', borderColor: 'var(--color-border)' }}>
<CardHeader className="pb-4">
<div className="w-16 h-16 rounded-xl flex items-center justify-center mb-4 group-hover:scale-110 transition-transform" style={{ backgroundColor: 'var(--color-primary)' }}>
<IconComponent className="w-8 h-8 text-white" />
</div>
<CardTitle className="text-h4 mb-3">{service.title}</CardTitle>
<p className="text-body text-muted leading-relaxed">{service.description}</p>
</CardHeader>
<CardContent className="pt-0">
<div className="space-y-4">
<div>
<h4 className="text-subhead mb-3">Key Features:</h4>
<div className="space-y-2">
{service.features.map((feature, index) => (
<div key={index} className="flex items-start gap-2">
<CheckCircle className="w-4 h-4 text-green-600 mt-0.5 flex-shrink-0" />
<span className="text-small text-muted">{feature}</span>
</div>
))}
</div>
</div>
<div className="pt-4 border-t" style={{ borderColor: 'var(--color-border)' }}>
<p className="text-small text-primary">
<strong>Outcome:</strong> {service.outcome}
</p>
</div>
</div>
</CardContent>
</Card>
);
}
// Theme Card Component
export function ThemeCard({ theme }) {
const IconComponent = theme.icon;
return (
<Card className="border hover:shadow-md transition-all duration-300 text-center group" style={{ backgroundColor: 'var(--color-bg-white)', borderColor: 'var(--color-border)' }}>
<CardContent className="p-6">
<div className={`w-16 h-16 rounded-xl bg-gradient-to-r ${theme.color} flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform`}>
<IconComponent className="w-8 h-8 text-white" />
</div>
<h3 className="text-subhead mb-2">{theme.title}</h3>
<p className="text-small text-muted">{theme.description}</p>
</CardContent>
</Card>
);
}
// Program Card Component
export function ProgramCard({ program }) {
return (
<Card className="border hover:shadow-lg transition-all duration-300 h-full" style={{ backgroundColor: 'var(--color-bg-white)', borderColor: 'var(--color-border)' }}>
<CardHeader className="pb-4">
<div className="flex items-center gap-3 mb-4">
<Badge className="text-small px-3 py-1" style={{ backgroundColor: 'var(--color-primary)', color: 'white' }}>
{program.level}
</Badge>
<Badge variant="outline" className="text-small px-3 py-1">
{program.format}
</Badge>
</div>
<CardTitle className="text-h4 mb-3">{program.title}</CardTitle>
<p className="text-body text-muted leading-relaxed">{program.description}</p>
</CardHeader>
<CardContent className="pt-0">
<div className="space-y-4">
<div className="grid grid-cols-2 gap-4 text-small">
<div className="flex items-center gap-2">
<Clock className="w-4 h-4 text-primary" />
<span>{program.duration}</span>
</div>
<div className="flex items-center gap-2">
<Users className="w-4 h-4 text-primary" />
<span>{program.participants}</span>
</div>
</div>
<div>
<h4 className="text-subhead mb-3">Program Highlights:</h4>
<div className="space-y-2">
{program.highlights.map((highlight, index) => (
<div key={index} className="flex items-start gap-2">
<CheckCircle className="w-4 h-4 text-green-600 mt-0.5 flex-shrink-0" />
<span className="text-small text-muted">{highlight}</span>
</div>
))}
</div>
</div>
</div>
</CardContent>
</Card>
);
}
// Enhanced Feature Card Component for Platform Features
export function FeatureCard({ feature }) {
const IconComponent = feature.icon;
return (
<Card className="border border-gray-200 hover:border-primary/30 transition-all duration-300 shadow-sm hover:shadow-lg group h-full" style={{ backgroundColor: 'var(--color-bg-white)' }}>
<CardContent className="p-8">
{/* Feature Header */}
<div className="flex items-start gap-4 mb-6">
<div
className="w-14 h-14 rounded-xl flex items-center justify-center group-hover:scale-110 transition-transform duration-300 flex-shrink-0"
style={{ backgroundColor: 'rgba(4, 4, 91, 0.08)' }}
>
<IconComponent className="w-7 h-7 text-primary" />
</div>
<div className="flex-1">
<h3 className="text-h4 mb-3 text-black">{feature.title}</h3>
<p className="text-body text-muted leading-relaxed">{feature.description}</p>
</div>
</div>
{/* Feature List */}
<div className="space-y-3">
{feature.features.map((item, itemIndex) => (
<div key={itemIndex} className="flex items-center gap-3">
<div
className="w-5 h-5 rounded-full flex items-center justify-center flex-shrink-0"
style={{ backgroundColor: 'var(--color-accent)' }}
>
<CheckCircle className="w-3 h-3 text-white" />
</div>
<span className="text-body text-muted">{item}</span>
</div>
))}
</div>
</CardContent>
</Card>
);
}
// Case Study Card Component
export function CaseStudyCard({ caseStudy }) {
return (
<Card className="border hover:shadow-lg transition-all duration-300 overflow-hidden group" style={{ backgroundColor: 'var(--color-bg-white)', borderColor: 'var(--color-border)' }}>
<div className="relative h-48">
<ImageWithFallback
src={caseStudy.image}
alt={caseStudy.title}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
/>
<div className="absolute top-4 left-4">
<Badge className="text-small px-3 py-1" style={{ backgroundColor: 'var(--color-accent)', color: 'var(--color-black)' }}>
{caseStudy.industry}
</Badge>
</div>
</div>
<CardContent className="p-6">
<h3 className="text-h4 mb-3">{caseStudy.title}</h3>
<div className="space-y-4">
<div>
<h4 className="text-subhead mb-2">Challenge:</h4>
<p className="text-small text-muted">{caseStudy.challenge}</p>
</div>
<div>
<h4 className="text-subhead mb-2">Solution:</h4>
<p className="text-small text-muted">{caseStudy.solution}</p>
</div>
<div>
<h4 className="text-subhead mb-2">Results:</h4>
<div className="space-y-2">
{caseStudy.results.map((result, index) => (
<div key={index} className="flex items-start gap-2">
<Star className="w-4 h-4 text-yellow-500 mt-0.5 flex-shrink-0" />
<span className="text-small text-muted">{result}</span>
</div>
))}
</div>
</div>
<div className="flex items-center gap-4 pt-2 text-small">
<span className="flex items-center gap-1">
<Clock className="w-4 h-4 text-primary" />
{caseStudy.duration}
</span>
<span className="flex items-center gap-1">
<Users className="w-4 h-4 text-primary" />
{caseStudy.participants} participants
</span>
</div>
</div>
</CardContent>
</Card>
);
}
// Sticky Tabs Component
export function StickyTabs({ pillars, activeTab, onTabClick, isSticky }) {
return (
<div className={`bg-white border-b transition-all duration-300 ${isSticky ? 'fixed top-20 left-0 right-0 z-40 shadow-md' : 'relative'}`} style={{ borderColor: 'var(--color-border)' }}>
<nav className="section-margin-x mx-auto" aria-label="Section navigation">
{/* Mobile: compact dropdown */}
<div className="md:hidden py-3">
<label htmlFor="section-select" className="sr-only">Select section</label>
<select
id="section-select"
className="w-full border rounded-lg p-3 bg-white text-body focus-ring"
value={activeTab}
onChange={(e) => onTabClick(e.target.value)}
aria-controls="page-sections"
>
{pillars.map((pillar) => (
<option key={pillar.id} value={pillar.id}>{pillar.title}</option>
))}
</select>
</div>
</nav>
</div>
);
}

327
src/components/Footer.tsx Normal file
View File

@@ -0,0 +1,327 @@
import { Facebook, X, Linkedin, Instagram, User } from "lucide-react";
import { ImageWithFallback } from './figma/ImageWithFallback';
import { navigateTo } from './Router';
import klcLogo from 'figma:asset/e98caa8afd8d11246bbff1dde75bbaae6f6a0894.png';
export function Footer() {
return (
<footer
className="relative py-16"
style={{
backgroundColor: 'var(--color-brand-primary)',
color: 'white'
}}
>
{/* Main Footer Content */}
<div className="max-w-7xl mx-auto section-margin-x">
<div className="flex flex-col lg:flex-row lg:justify-between lg:items-start gap-12 lg:gap-8">
{/* Logo and Description Column */}
<div className="lg:flex-shrink-0 lg:w-80">
{/* Logo */}
<div className="flex items-center mb-6">
<img
src={klcLogo}
alt="Kautilya Leadership Centre"
className="h-16 w-auto object-contain"
style={{ filter: 'brightness(0) invert(1)' }}
/>
</div>
{/* Company Description */}
<p
className="text-sm leading-relaxed mb-8"
style={{ color: 'rgba(255, 255, 255, 0.85)' }}
>
Empowering leaders with transformative development opportunities for achieving excellence, growth, and lasting impact.
</p>
{/* Social Media Icons */}
<div className="flex space-x-4">
{[
{ icon: X, label: 'X' },
{ icon: Facebook, label: 'Facebook' },
{ icon: Linkedin, label: 'LinkedIn' },
{ icon: Instagram, label: 'Instagram' }
].map(({ icon: Icon, label }) => (
<a
key={label}
href="#"
className="w-8 h-8 rounded-full flex items-center justify-center transition-all duration-300 group"
style={{ backgroundColor: 'rgba(192, 192, 192, 0.1)' }}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = 'var(--color-brand-accent)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = 'rgba(192, 192, 192, 0.1)';
}}
aria-label={label}
>
<Icon
className="w-4 h-4 transition-colors duration-300"
style={{ color: 'rgba(255, 255, 255, 0.85)' }}
onMouseEnter={(e) => {
e.currentTarget.style.color = 'var(--color-brand-black)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.color = 'rgba(255, 255, 255, 0.85)';
}}
/>
</a>
))}
</div>
</div>
{/* Services */}
<div className="lg:w-auto lg:flex-shrink-0">
<h4
className="font-semibold mb-6 text-sm"
style={{ color: 'white' }}
>
Services
</h4>
<div className="space-y-3">
{[
{ text: 'Leadership Development', href: '/services/leadership-development', badge: null },
{ text: 'Executive Coaching', href: '/services/executive-coaching', badge: null },
{ text: 'Management Development', href: '/services/management-development', badge: null },
{ text: 'Consulting Services', href: '/services/consulting', badge: null },
{ text: 'Culture & Competence', href: '/services/culture-competence', badge: null },
{ text: 'Learning Facility', href: '/services/learning-facility', badge: 'Popular' }
].map((item) => (
<div key={item.text} className="flex items-center gap-2">
<button
onClick={() => navigateTo(item.href)}
className="text-sm transition-colors duration-300 cursor-pointer text-left"
style={{ color: 'rgba(255, 255, 255, 0.85)' }}
onMouseEnter={(e) => {
e.currentTarget.style.color = 'white';
}}
onMouseLeave={(e) => {
e.currentTarget.style.color = 'rgba(255, 255, 255, 0.85)';
}}
>
{item.text}
</button>
{item.badge && (
<span
className="px-2 py-0.5 text-xs rounded"
style={{
backgroundColor: 'var(--color-brand-accent)',
color: 'var(--color-brand-black)'
}}
>
{item.badge}
</span>
)}
</div>
))}
</div>
</div>
{/* Company */}
<div className="lg:w-auto lg:flex-shrink-0">
<h4
className="font-semibold mb-6 text-sm"
style={{ color: 'white' }}
>
About Us
</h4>
<div className="space-y-3">
{[
{ text: 'Our vision', href: '/about/our-vision' },
{ text: 'Our Impact', href: '/about/our-impact' },
{ text: 'Our Expertise', href: '/about/our-expertise' }
].map((link) => (
<button
key={link.text}
onClick={() => navigateTo(link.href)}
className="block text-sm transition-colors duration-300 cursor-pointer text-left"
style={{ color: 'rgba(255, 255, 255, 0.85)' }}
onMouseEnter={(e) => {
e.currentTarget.style.color = 'white';
}}
onMouseLeave={(e) => {
e.currentTarget.style.color = 'rgba(255, 255, 255, 0.85)';
}}
>
{link.text}
</button>
))}
</div>
</div>
{/* Explore */}
<div className="lg:w-auto lg:flex-shrink-0">
<h4
className="font-semibold mb-6 text-sm"
style={{ color: 'white' }}
>
Explore
</h4>
<div className="space-y-3">
{[
{ text: 'Learning facility', href: '/services/learning-facility' },
{ text: 'Online Courses', href: '/learning-online' },
{ text: 'Contact Us', href: '/contact' }
].map((link) => (
<button
key={link.text}
onClick={() => navigateTo(link.href)}
className="block text-sm transition-colors duration-300 cursor-pointer text-left"
style={{ color: 'rgba(255, 255, 255, 0.85)' }}
onMouseEnter={(e) => {
e.currentTarget.style.color = 'white';
}}
onMouseLeave={(e) => {
e.currentTarget.style.color = 'rgba(255, 255, 255, 0.85)';
}}
>
{link.text}
</button>
))}
</div>
</div>
{/* Resources */}
<div className="lg:w-auto lg:flex-shrink-0">
<h4
className="font-semibold mb-6 text-sm"
style={{ color: 'white' }}
>
Resources
</h4>
<div className="space-y-3">
{[
{ text: 'Blog article', href: '/learning/articles' },
{ text: 'Webcast', href: '/learning/webcast' }
].map((link) => (
<button
key={link.text}
onClick={() => navigateTo(link.href)}
className="block text-sm transition-colors duration-300 cursor-pointer text-left"
style={{ color: 'rgba(255, 255, 255, 0.85)' }}
onMouseEnter={(e) => {
e.currentTarget.style.color = 'white';
}}
onMouseLeave={(e) => {
e.currentTarget.style.color = 'rgba(255, 255, 255, 0.85)';
}}
>
{link.text}
</button>
))}
{/* Back To Top Button - Kept in Resources section */}
<div className="pt-12">
<button
onClick={() => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}}
className="flex items-center gap-2 text-sm transition-all duration-300 group"
style={{ color: 'rgba(255, 255, 255, 0.85)' }}
onMouseEnter={(e) => {
e.currentTarget.style.color = 'var(--color-brand-accent)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.color = 'rgba(255, 255, 255, 0.85)';
}}
aria-label="Back to top"
>
<svg
className="w-4 h-4 transition-transform duration-300 group-hover:-translate-y-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M5 10l7-7m0 0l7 7m-7-7v18"
/>
</svg>
<span className="transition-colors duration-300">
Back To Top
</span>
</button>
</div>
</div>
</div>
</div>
{/* Divider */}
<div
className="w-full h-px my-12"
style={{ backgroundColor: 'rgba(192, 192, 192, 0.2)' }}
/>
{/* Bottom Footer */}
<div className="flex flex-col lg:flex-row justify-between items-start lg:items-center space-y-6 lg:space-y-0">
{/* Copyright and Legal Links */}
<div className="flex flex-col lg:flex-row lg:items-center space-y-4 lg:space-y-0 lg:space-x-8">
<p
className="text-sm"
style={{ color: 'rgba(255, 255, 255, 0.85)' }}
>
Copyright 2025 Kautilya Leadership Centre
</p>
<div className="flex space-x-6">
<a
href="#"
className="text-sm transition-colors duration-300"
style={{ color: 'rgba(255, 255, 255, 0.85)' }}
onMouseEnter={(e) => {
e.currentTarget.style.color = 'var(--color-brand-accent)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.color = 'rgba(255, 255, 255, 0.85)';
}}
>
Privacy and Cookie Policy
</a>
<button
onClick={() => navigateTo('/terms')}
className="text-sm transition-colors duration-300 cursor-pointer text-left"
style={{ color: 'rgba(255, 255, 255, 0.85)' }}
onMouseEnter={(e) => {
e.currentTarget.style.color = 'var(--color-brand-accent)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.color = 'rgba(255, 255, 255, 0.85)';
}}
>
Terms of Service
</button>
</div>
</div>
{/* Contact Info */}
<div className="text-right">
<p
className="text-sm font-medium"
style={{ color: 'rgba(255, 255, 255, 0.85)' }}
>
Follow Our Leadership Journey
</p>
<p
className="text-xs"
style={{ color: 'rgba(255, 255, 255, 0.7)' }}
>
Discover leadership excellence with KLC
</p>
</div>
</div>
</div>
</footer>
);
}

View File

@@ -0,0 +1,304 @@
import React, { useState, useEffect, useCallback } from 'react';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import { navigateTo } from './Router';
import svgPaths from "../imports/svg-i1joeov37f";
interface SlideData {
id: number;
title: string;
description: string;
backgroundImage: string;
shortTitle: string;
}
export default function HeroSection() {
const [currentSlide, setCurrentSlide] = useState(0);
const [isAutoPlaying, setIsAutoPlaying] = useState(true);
const [progressValues, setProgressValues] = useState([0, 0, 0]);
const slides: SlideData[] = [
{
id: 1,
title: "Empowering Future-Ready\nLeaders",
description: "Build confidence, agility, and clarity for today's complex challenges.",
backgroundImage: "https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1920&q=80",
shortTitle: "Leadership Is Learned. We Teach It Right."
},
{
id: 2,
title: "Turn Managers into\nImpactful Leaders",
description: "Transform your management team into visionary leaders who inspire teams, drive innovation, and achieve exceptional business outcomes.",
backgroundImage: "https://images.unsplash.com/photo-1600880292203-757bb62b4baf?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1920&q=80",
shortTitle: "Turn Managers into Impactful Leaders"
},
{
id: 3,
title: "Struggling with\nManagerial Gaps?",
description: "Bridge the leadership gap in your organization with our proven methodologies that develop confident, capable leaders at every level.",
backgroundImage: "https://images.unsplash.com/photo-1542744173-8e7e53415bb0?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1920&q=80",
shortTitle: "Struggling with Managerial Gaps?"
}
];
const totalSlides = slides.length;
const slideDuration = 5000; // 5 seconds per slide
// Auto-advance slides
useEffect(() => {
if (!isAutoPlaying) return;
const interval = setInterval(() => {
setCurrentSlide((prev) => (prev + 1) % totalSlides);
}, slideDuration);
return () => clearInterval(interval);
}, [isAutoPlaying, totalSlides]);
// Progress bar animation
useEffect(() => {
if (!isAutoPlaying) return;
const interval = setInterval(() => {
setProgressValues(prev => {
const newProgress = [...prev];
newProgress[currentSlide] = Math.min(newProgress[currentSlide] + (100 / (slideDuration / 100)), 100);
// Reset progress when slide changes
if (newProgress[currentSlide] >= 100) {
newProgress[currentSlide] = 0;
// Reset other slides
newProgress.forEach((_, index) => {
if (index !== currentSlide) {
newProgress[index] = 0;
}
});
}
return newProgress;
});
}, 100);
return () => clearInterval(interval);
}, [currentSlide, isAutoPlaying]);
// Reset progress when manually changing slides
useEffect(() => {
setProgressValues(prev => {
const newProgress = [0, 0, 0];
newProgress[currentSlide] = 0;
return newProgress;
});
}, [currentSlide]);
const goToSlide = useCallback((slideIndex: number) => {
if (slideIndex !== currentSlide) {
setCurrentSlide(slideIndex);
setIsAutoPlaying(false);
// Resume auto-play after manual interaction
setTimeout(() => setIsAutoPlaying(true), 3000);
}
}, [currentSlide]);
const nextSlide = useCallback(() => {
const next = (currentSlide + 1) % totalSlides;
goToSlide(next);
}, [currentSlide, totalSlides, goToSlide]);
const prevSlide = useCallback(() => {
const prev = (currentSlide - 1 + totalSlides) % totalSlides;
goToSlide(prev);
}, [currentSlide, totalSlides, goToSlide]);
// Pause auto-play on hover
const handleMouseEnter = () => setIsAutoPlaying(false);
const handleMouseLeave = () => setIsAutoPlaying(true);
return (
<section
className="hero-section"
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
{/* Background Slides */}
{slides.map((slide, index) => (
<div
key={slide.id}
className={`hero-slide ${index === currentSlide ? 'active' : ''}`}
style={{
backgroundImage: `url('${slide.backgroundImage}')`
}}
>
<div className="hero-overlay" />
</div>
))}
{/* Hero Content */}
<div className="hero-content">
<div className="hero-text-section">
{/* Title */}
<h1 className="hero-title" style={{ whiteSpace: 'pre-line' }}>
{slides[currentSlide].title}
</h1>
{/* Description */}
<p className="hero-description">
{slides[currentSlide].description}
</p>
{/* Build Your Leadership Pipeline Button - Enhanced with Proper Navigation */}
<button
className="hero-slide-button group box-border content-stretch flex flex-row gap-2.5 items-center justify-start p-0 relative cursor-pointer overflow-hidden"
style={{
background: 'transparent',
border: 'none'
}}
onClick={() => {
console.log('Hero button clicked - navigating to contact page');
navigateTo('/contact?topic=leadership-pipeline');
}}
aria-label="Build Your Leadership Pipeline"
>
{/* Icon Container with Slide Animation */}
<div className="relative shrink-0 size-[50px] overflow-hidden">
{/* Background Rectangle - Consistent Blue Color */}
<div className="absolute inset-0 bg-[#04045B]" />
{/* Icon Layer - Sliding Animation */}
<div className="icon-layer absolute inset-0 w-full h-full">
{/* Primary Arrow - Slides out diagonally up-right */}
<div className="icon absolute inset-0 flex items-center justify-center transition-all duration-300 ease-in-out group-hover:translate-x-6 group-hover:-translate-y-6 group-hover:opacity-0">
<svg
className="block w-full h-full"
fill="none"
preserveAspectRatio="none"
viewBox="0 0 50 50"
>
<g clipPath="url(#clip0_95_1043_primary)">
<path d={svgPaths.p5b8d700} fill="white" />
<path d={svgPaths.p30b71a00} fill="white" />
</g>
<defs>
<clipPath id="clip0_95_1043_primary">
<rect fill="white" height="50" width="50" />
</clipPath>
</defs>
</svg>
</div>
{/* Secondary Arrow - Slides in from bottom-left */}
<div className="icon absolute inset-0 flex items-center justify-center opacity-0 -translate-x-6 translate-y-6 transition-all duration-300 ease-in-out group-hover:translate-x-0 group-hover:translate-y-0 group-hover:opacity-100">
<svg
className="block w-full h-full"
fill="none"
preserveAspectRatio="none"
viewBox="0 0 50 50"
>
<g clipPath="url(#clip0_95_1043_secondary)">
<path d={svgPaths.p5b8d700} fill="white" />
<path d={svgPaths.p30b71a00} fill="white" />
</g>
<defs>
<clipPath id="clip0_95_1043_secondary">
<rect fill="white" height="50" width="50" />
</clipPath>
</defs>
</svg>
</div>
</div>
</div>
{/* Text Section with Vertical Slide Animation */}
<div className="text-layer relative shrink-0 overflow-hidden flex items-center" style={{
height: '28px',
fontFamily: 'Inter, sans-serif',
fontSize: '20px',
fontWeight: '400',
lineHeight: '28px',
whiteSpace: 'nowrap',
color: '#ffffff'
}}>
{/* Primary Text - Slides up and out */}
<div
className="text-element absolute inset-0 flex items-center justify-start transition-all duration-300 ease-in-out group-hover:-translate-y-full group-hover:opacity-0"
style={{
color: '#ffffff !important',
textShadow: '0 1px 2px rgba(0, 0, 0, 0.4)',
fontFamily: 'Inter, sans-serif',
fontSize: '20px',
fontWeight: '400',
lineHeight: '28px'
}}
>
Build Your Leadership Pipeline
</div>
{/* Secondary Text - Slides in from bottom */}
<div
className="text-element absolute inset-0 flex items-center justify-start translate-y-full opacity-0 transition-all duration-300 ease-in-out group-hover:translate-y-0 group-hover:opacity-100"
style={{
color: '#ffffff !important',
textShadow: '0 1px 2px rgba(0, 0, 0, 0.4)',
fontFamily: 'Inter, sans-serif',
fontSize: '20px',
fontWeight: '400',
lineHeight: '28px'
}}
>
Build Your Leadership Pipeline
</div>
</div>
</button>
</div>
</div>
{/* Bottom Navigation */}
<div className="hero-navigation">
{/* Progress Section */}
<div className="hero-progress-container">
{slides.map((slide, index) => (
<div
key={slide.id}
className="hero-progress-item"
onClick={() => goToSlide(index)}
>
{/* Progress Bar */}
<div
className={`hero-progress-segment ${index === currentSlide ? 'active' : ''}`}
>
<div
className="hero-progress-fill"
style={{ width: index === currentSlide ? `${progressValues[index]}%` : '0%' }}
/>
</div>
{/* Progress Number */}
<div className={`hero-progress-number ${index === currentSlide ? 'active' : ''}`}>
{String(index + 1).padStart(2, '0')}
</div>
{/* Progress Text */}
<div className={`hero-progress-text ${index === currentSlide ? 'active' : ''}`}>
{slide.shortTitle}
</div>
</div>
))}
</div>
{/* Navigation Arrows */}
<div className="hero-controls">
<button
className="hero-nav-button"
onClick={prevSlide}
aria-label="Previous slide"
>
<ChevronLeft className="w-5 h-5" />
</button>
<button
className="hero-nav-button"
onClick={nextSlide}
aria-label="Next slide"
>
<ChevronRight className="w-5 h-5" />
</button>
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,235 @@
import { ArrowUpRight } from "lucide-react";
import { ImageWithFallback } from "./figma/ImageWithFallback";
import { BrandedTag } from "./about/BrandedTag";
import { PrimaryCTAButton } from "./PrimaryCTAButton";
import { navigateTo } from "./Router";
interface InsightCard {
id: number;
title: string;
description?: string;
date: string;
tags: string[];
image: string;
}
const insightCards: InsightCard[] = [
{
id: 1,
title: "The Evolving DNA of a Modern Leader",
description: "Explore how leadership traits are shifting in the age of AI, remote work, and hyper-connectivity.",
date: "25-05-2025",
tags: ["Adaptability", "Strategic foresight"],
image: "https://images.unsplash.com/photo-1522202176988-66273c2fd55f?auto=format&fit=crop&w=800&q=80"
},
{
id: 2,
title: "Strategic Leadership in Uncertain Times",
date: "25-05-2025",
tags: ["Strategy", "Decision Making"],
image: "https://images.unsplash.com/photo-1553877522-43269d4ea984?auto=format&fit=crop&w=800&q=80"
},
{
id: 3,
title: "Building High-Performance Teams",
date: "25-05-2025",
tags: ["Team Building", "Performance"],
image: "https://images.unsplash.com/photo-1559136555-9303baea8ebd?auto=format&fit=crop&w=800&q=80"
}
];
// Insight Tag Component
function InsightTag({ text }: { text: string }) {
return (
<span
className="px-3 py-1 text-sm font-medium rounded-full"
style={{
backgroundColor: 'var(--color-brand-accent)',
color: 'var(--color-brand-black)'
}}
>
{text}
</span>
);
}
// Arrow Icon Component
function ArrowIcon() {
return (
<div className="p-2 rounded-full transition-all duration-300 group-hover:bg-gray-100"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.05)' }}>
<ArrowUpRight className="w-4 h-4" style={{ color: 'var(--color-brand-black)' }} />
</div>
);
}
// Calendar Icon Component
function CalendarIcon() {
return (
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clipRule="evenodd" />
</svg>
);
}
// Explore All Button Component - Updated to redirect to articles page
function ExploreAllButton() {
return (
<PrimaryCTAButton
text="Explore All"
onClick={() => navigateTo('/learning/articles')}
ariaLabel="Explore all leadership insights and ideas"
className="explore-all-cta-override"
/>
);
}
// Large Insight Card Component
function LargeInsightCard({ card }: { card: InsightCard }) {
return (
<div className="relative h-[500px] rounded-xl overflow-hidden group cursor-pointer">
{/* Background Image */}
<div className="absolute inset-0 transition-transform duration-300 group-hover:scale-105">
<ImageWithFallback
src={card.image}
alt={card.title}
className="w-full h-full object-cover"
/>
</div>
{/* White Content Box */}
<div className="insight-card-white-box absolute bottom-6 left-6 right-6 bg-white rounded-xl p-6 shadow-lg transition-all duration-300 group-hover:shadow-xl">
{/* Top section with tags and arrow */}
<div className="insight-card-header flex items-start justify-between mb-4">
<div className="insight-card-tags flex gap-2">
{card.tags.map((tag, index) => (
<InsightTag key={index} text={tag} />
))}
</div>
<ArrowIcon />
</div>
{/* Bottom section with content and date */}
<div className="insight-card-footer">
<div className="insight-card-text-content mb-4">
<h3 className="insight-card-title text-xl font-bold mb-3 leading-tight"
style={{ color: 'var(--color-brand-black)' }}>
{card.title}
</h3>
{card.description && (
<p className="insight-card-description text-gray-600 text-sm leading-relaxed">
{card.description}
</p>
)}
</div>
<div className="insight-card-date flex items-center gap-2 text-gray-500">
<CalendarIcon />
<span className="insight-card-date-text text-sm font-medium">{card.date}</span>
</div>
</div>
</div>
</div>
);
}
// Small Insight Card Component
function SmallInsightCard({ card }: { card: InsightCard }) {
return (
<div className="relative h-[235px] rounded-xl overflow-hidden group cursor-pointer">
{/* Background Image */}
<div className="absolute inset-0 transition-transform duration-300 group-hover:scale-105">
<ImageWithFallback
src={card.image}
alt={card.title}
className="w-full h-full object-cover"
/>
</div>
{/* White Content Box */}
<div className="insight-card-white-box absolute bottom-4 left-4 right-4 bg-white rounded-xl p-4 shadow-lg transition-all duration-300 group-hover:shadow-xl">
{/* Top section with tags and arrow */}
<div className="insight-card-header flex items-start justify-between mb-3">
<div className="insight-card-tags flex gap-2">
{card.tags.map((tag, index) => (
<span
key={index}
className="px-2.5 py-1 text-xs font-medium rounded-full"
style={{
backgroundColor: 'var(--color-brand-accent)',
color: 'var(--color-brand-black)'
}}
>
{tag}
</span>
))}
</div>
<div className="p-1.5 rounded-full transition-all duration-300 group-hover:bg-gray-100"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.05)' }}>
<ArrowUpRight className="w-3.5 h-3.5" style={{ color: 'var(--color-brand-black)' }} />
</div>
</div>
{/* Bottom section with content and date */}
<div className="insight-card-footer">
<div className="insight-card-text-content mb-3">
<h3 className="insight-card-title text-base font-bold leading-tight"
style={{ color: 'var(--color-brand-black)' }}>
{card.title}
</h3>
</div>
<div className="insight-card-date flex items-center gap-2 text-gray-500">
<CalendarIcon />
<span className="insight-card-date-text text-sm font-medium">{card.date}</span>
</div>
</div>
</div>
</div>
);
}
export function InsightsSection() {
return (
<section
className="py-24"
style={{
backgroundColor: '#F7F7FD',
paddingTop: '8.75rem',
paddingBottom: '8.75rem'
}}
>
<div className="max-w-7xl mx-auto section-margin-x">
{/* Branded Tag */}
<BrandedTag text="Leadership Insights" />
<div className="insights-container">
{/* Header */}
<div className="insights-header flex flex-col lg:flex-row lg:items-center lg:justify-between mb-16 gap-8 text-center lg:text-left">
<h2
className="insights-title text-3xl md:text-4xl lg:text-5xl font-bold leading-tight"
style={{ color: 'var(--color-brand-black)' }}
>
Leadership Insights & Ideas
</h2>
<ExploreAllButton />
</div>
{/* Main Grid Layout */}
<div className="insights-grid grid grid-cols-1 lg:grid-cols-2 gap-4 md:gap-6 lg:gap-8">
{/* Large Card - Takes full height on left */}
<div className="lg:row-span-2">
<LargeInsightCard card={insightCards[0]} />
</div>
{/* Small Cards - Stack on right */}
<div className="flex flex-col gap-4 md:gap-6 lg:gap-8">
<SmallInsightCard card={insightCards[1]} />
<SmallInsightCard card={insightCards[2]} />
</div>
</div>
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,188 @@
import React, { useState } from 'react';
import { motion } from 'motion/react';
import { Building2, User, ArrowRight, ChevronLeft, Shield, Users, Target, BookOpen } from 'lucide-react';
import { Button } from './ui/button';
import { navigateTo } from './Router';
import { BrandedTag } from './about/BrandedTag';
interface JourneyOption {
id: string;
title: string;
description: string;
icon: React.ReactNode;
benefits: string[];
buttonText: string;
onClick: () => void;
}
export function LeadershipJourneyPage() {
const [hoveredOption, setHoveredOption] = useState<string | null>(null);
const journeyOptions: JourneyOption[] = [
{
id: 'corporate',
title: 'Corporate Login',
description: 'Access your organization\'s leadership development programs and track team progress.',
icon: <Building2 className="w-8 h-8" />,
benefits: [
'Team management and tracking',
'Enterprise-grade security',
'Customized learning paths',
'Advanced analytics and reporting'
],
buttonText: 'Access Corporate Portal',
onClick: () => navigateTo('/corporate-login')
},
{
id: 'self-learner',
title: 'Self Learner',
description: 'Begin your personal leadership journey with our comprehensive individual programs.',
icon: <User className="w-8 h-8" />,
benefits: [
'Personalized learning experience',
'Self-paced development',
'Individual progress tracking',
'Direct access to resources'
],
buttonText: 'Start Personal Journey',
onClick: () => navigateTo('/self-learner-signup')
}
];
return (
<div className="min-h-screen" style={{ backgroundColor: '#F7F7FD' }}>
{/* Header Section */}
<section className="py-20" style={{ backgroundColor: 'var(--color-brand-bg-white)' }}>
<div className="max-w-7xl mx-auto section-margin-x">
{/* Branded Tag */}
<motion.div
className="mb-6 text-center"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
<BrandedTag text="Choose Your Path" />
</motion.div>
{/* Main Heading */}
<motion.div
className="text-center mb-6"
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, delay: 0.2 }}
>
<h1
className="text-5xl font-bold leading-tight max-lg:text-4xl max-md:text-3xl mb-6"
style={{ color: 'var(--color-brand-black)' }}
>
Start Your Leadership Journey
</h1>
</motion.div>
</div>
</section>
{/* Journey Options Section */}
<section className="py-20">
<div className="max-w-7xl mx-auto section-margin-x">
<div className="grid md:grid-cols-2 gap-12">
{journeyOptions.map((option, index) => (
<motion.div
key={option.id}
className="relative"
initial={{ opacity: 0, y: 40 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, delay: 0.6 + index * 0.2 }}
onHoverStart={() => setHoveredOption(option.id)}
onHoverEnd={() => setHoveredOption(null)}
>
<div
className="bg-white rounded-2xl p-8 h-full shadow-lg border border-gray-100 transition-all duration-300 hover:shadow-2xl hover:-translate-y-2"
style={{
transform: hoveredOption === option.id ? 'translateY(-8px)' : 'translateY(0)',
boxShadow: hoveredOption === option.id
? '0 25px 50px -12px rgba(0, 0, 0, 0.15)'
: '0 10px 25px -5px rgba(0, 0, 0, 0.1)'
}}
>
{/* Icon Container */}
<div
className="w-16 h-16 rounded-xl flex items-center justify-center mb-6 transition-all duration-300"
style={{
backgroundColor: hoveredOption === option.id
? 'var(--color-brand-accent)'
: 'var(--color-brand-primary)'
}}
>
<div style={{ color: hoveredOption === option.id ? 'var(--color-brand-black)' : 'white' }}>
{option.icon}
</div>
</div>
{/* Content */}
<h3
className="text-2xl font-bold mb-4"
style={{ color: 'var(--color-brand-black)' }}
>
{option.title}
</h3>
<p className="text-gray-600 text-lg leading-relaxed mb-6">
{option.description}
</p>
{/* Benefits List */}
<div className="mb-8">
<h4 className="text-sm font-semibold text-gray-800 mb-4 uppercase tracking-wider">
Key Benefits
</h4>
<ul className="space-y-3">
{option.benefits.map((benefit, benefitIndex) => (
<motion.li
key={benefitIndex}
className="flex items-start gap-3"
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.5, delay: 0.8 + index * 0.2 + benefitIndex * 0.1 }}
>
<div
className="w-2 h-2 rounded-full mt-2 flex-shrink-0"
style={{ backgroundColor: 'var(--color-brand-accent)' }}
/>
<span className="text-gray-700 leading-relaxed">{benefit}</span>
</motion.li>
))}
</ul>
</div>
{/* CTA Button */}
<motion.button
className="w-full flex items-center justify-center gap-3 px-8 py-4 font-semibold text-lg transition-all duration-300 hover:shadow-lg hover:-translate-y-1"
style={{
borderRadius: '10px',
backgroundColor: hoveredOption === option.id
? 'var(--color-brand-primary)'
: 'var(--color-brand-accent)',
color: hoveredOption === option.id
? 'white'
: 'var(--color-brand-black)'
}}
onClick={option.onClick}
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
>
<span>{option.buttonText}</span>
<ArrowRight className="w-5 h-5" />
</motion.button>
</div>
</motion.div>
))}
</div>
</div>
</section>
</div>
);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
// This component has been consolidated into LogosSection.tsx
// All logo ticker functionality is now integrated into the main LogosSection component
// with enhanced features including:
// - Actual Figma logo assets
// - Enhanced scrolling animations
// - Responsive design
// - Brand guidelines compliance
// - Accessibility features
export default function LogoTicker() {
return null;
}

View File

@@ -0,0 +1,167 @@
import React from 'react';
import imgImage36 from "figma:asset/6bdf8056f51bbdc6dd9dab9044a6579a254bd02c.png";
import imgImage39 from "figma:asset/037c4659b7b0bf15b1dfdcd4868cb42e8257e838.png";
import imgImage43 from "figma:asset/c57ec1f4466f68e607139a3cd6d52f7e2f372408.png";
import imgImage45 from "figma:asset/4833274f0a593cd31fdefe553b70bb016de281af.png";
import imgImage38 from "figma:asset/d5bab6ea4f3d8cef3b0425c45cfee7faea19fdbc.png";
import imgImage47 from "figma:asset/e8fad960112d5eba554c3969d08891ebe4d4b9c7.png";
import Frame1597884933 from "../imports/Frame1597884933-44-374";
// Logo data using Frame1597884944 logos with proper dimensions
const logoData = [
{ src: imgImage36, name: 'CANMOOR', width: 302, height: 54 }, // CANMOOR
{ src: imgImage45, name: 'BlackRock', width: 210, height: 54 }, // BlackRock
{ src: imgImage38, name: 'Royal London', width: 145, height: 54 }, // Royal London
{ src: imgImage39, name: 'Abstract', width: 172, height: 54 }, // Abstract
{ src: imgImage47, name: 'ARES', width: 163, height: 54 }, // ARES
{ src: imgImage43, name: 'KADANS', width: 206, height: 54 }, // KADANS
// Repeat logos for more variety in scrolling
{ src: imgImage36, name: 'CANMOOR', width: 302, height: 54 }, // CANMOOR (repeat)
{ src: imgImage45, name: 'BlackRock', width: 210, height: 54 }, // BlackRock (repeat)
{ src: imgImage38, name: 'Royal London', width: 145, height: 54 }, // Royal London (repeat)
{ src: imgImage39, name: 'Abstract', width: 172, height: 54 }, // Abstract (repeat)
{ src: imgImage47, name: 'ARES', width: 163, height: 54 }, // ARES (repeat)
{ src: imgImage43, name: 'KADANS', width: 206, height: 54 }, // KADANS (repeat)
];
// Top row logos - Original 6 unique logos
const topRowLogos = logoData.slice(0, 6);
// Bottom row logos - Repeated 6 logos for variety
const bottomRowLogos = logoData.slice(6, 12);
interface LogoItemProps {
logo: typeof logoData[0];
index: number;
duplicate?: boolean;
}
function LogoItem({ logo, index, duplicate = false }: LogoItemProps) {
// Scale down larger logos while maintaining aspect ratio
const scaledWidth = logo.width > 250 ? Math.round(logo.width * 0.8) : logo.width;
const displayWidth = Math.max(120, Math.min(scaledWidth, 250)); // Min 120px, Max 250px
return (
<div
className="logo-ticker-item flex-shrink-0 flex items-center justify-center mx-8"
style={{
width: `${displayWidth}px`,
height: '54px',
minWidth: `${displayWidth}px`,
}}
aria-label={logo.name}
role="listitem"
tabIndex={duplicate ? -1 : 0}
>
<img
src={logo.src}
alt={`${logo.name} logo`}
style={{
width: '100%',
height: 'auto',
maxHeight: '54px',
objectFit: 'contain',
}}
className="logo-ticker-item-image"
/>
</div>
);
}
export function LogosSection() {
return (
<section
className="py-16 overflow-hidden"
style={{
backgroundColor: '#F7F7FD', // Same as app background
width: '100%',
}}
>
{/* Reference Frame Component (Hidden - maintains import) */}
<div className="hidden" aria-hidden="true">
<Frame1597884933 />
</div>
{/* Logo Ticker - Two Rows */}
<div
className="w-full relative"
role="region"
aria-label="Client logos showcase"
>
{/* Top Row - Scrolling Left to Right */}
<div
className="relative h-[54px] mb-16 overflow-hidden"
role="list"
aria-label="Client logos row 1"
>
<div className="flex items-center h-full will-change-transform">
<div
className="scroll-left flex items-center h-full"
style={{
width: '400%',
gap: '80px',
paddingLeft: '40px',
paddingRight: '40px'
}}
>
{/* Create multiple sets for seamless infinite scroll */}
{[1, 2, 3, 4].map((setNumber) => (
<div
key={`top-set-${setNumber}`}
className="flex items-center h-full"
style={{ gap: '80px' }}
>
{topRowLogos.map((logo, index) => (
<LogoItem
key={`top-${setNumber}-${index}`}
logo={logo}
index={index}
duplicate={setNumber > 1}
/>
))}
</div>
))}
</div>
</div>
</div>
{/* Bottom Row - Scrolling Right to Left */}
<div
className="relative h-[54px] overflow-hidden"
role="list"
aria-label="Client logos row 2"
>
<div className="flex items-center h-full will-change-transform">
<div
className="scroll-right flex items-center h-full"
style={{
width: '400%',
gap: '80px',
paddingLeft: '40px',
paddingRight: '40px'
}}
>
{/* Create multiple sets for seamless infinite scroll */}
{[1, 2, 3, 4].map((setNumber) => (
<div
key={`bottom-set-${setNumber}`}
className="flex items-center h-full"
style={{ gap: '80px' }}
>
{bottomRowLogos.map((logo, index) => (
<LogoItem
key={`bottom-${setNumber}-${index}`}
logo={logo}
index={index}
duplicate={setNumber > 1}
/>
))}
</div>
))}
</div>
</div>
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,747 @@
import React, { useState, useEffect } from 'react';
import { Button } from './ui/button';
import { Avatar, AvatarFallback, AvatarImage } from './ui/avatar';
import { Badge } from './ui/badge';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
DropdownMenuSeparator,
DropdownMenuLabel,
} from './ui/dropdown-menu';
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger,
} from './ui/sheet';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './ui/collapsible';
import { navigateTo } from './Router';
import { useAuth } from './AuthContext';
import { useCart } from './CartContext';
import { ImageWithFallback } from './figma/ImageWithFallback';
import { PrimaryCTAButton } from './PrimaryCTAButton';
import { StandardCTAButton } from './StandardCTAButton';
import klcLogo from 'figma:asset/e98caa8afd8d11246bbff1dde75bbaae6f6a0894.png';
import {
Menu,
ChevronDown,
ChevronRight,
Building2,
User,
Settings,
LogOut,
LayoutDashboard,
Users,
Target,
Award,
Lightbulb,
GraduationCap,
BookOpen,
Video,
FileText,
Eye,
Heart,
MapPin,
Calendar,
Play,
Home,
Monitor,
Headphones,
Globe,
Download,
Clock,
TrendingUp,
Star,
BookMarked,
Podcast,
Building,
ShoppingCart,
ArrowRight
} from 'lucide-react';
interface NavigationProps {
currentPage?: string;
}
interface NavLink {
label: string;
href?: string;
items?: { label: string; href: string; description?: string; icon?: any }[];
icon?: any;
}
const navigationItems: NavLink[] = [
{
label: 'Services',
items: [
{
label: 'Leadership Development',
href: '/services/leadership-development',
description: 'Executive and senior leadership programs',
icon: Target
},
{
label: 'Management Development',
href: '/services/management-development',
description: 'Middle management and team leader training',
icon: Users
},
{
label: 'Culture Competence',
href: '/services/culture-competence',
description: 'Building inclusive and high-performance cultures',
icon: Heart
},
{
label: 'Consulting',
href: '/services/consulting',
description: 'Strategic organizational transformation',
icon: Lightbulb
},
{
label: 'Executive Coaching',
href: '/services/executive-coaching',
description: 'Personalized leadership development',
icon: GraduationCap
}
]
},
{
label: 'About Us',
items: [
{
label: 'Our Vision',
href: '/about/our-vision',
description: 'Our mission to transform leadership globally',
icon: Eye
},
{
label: 'Our Impact',
href: '/about/our-impact',
description: 'Real results and measurable outcomes',
icon: TrendingUp
},
{
label: 'Our Expertise',
href: '/about/our-expertise',
description: 'Industry-leading knowledge and experience',
icon: Star
}
]
},
{
label: 'Learning Facility',
href: '/services/learning-facility'
},
{
label: 'Resources',
items: [
{
label: 'Article Blog',
href: '/learning/articles',
description: 'Latest insights and thought leadership',
icon: BookMarked
},
{
label: 'Webcast',
href: '/learning/webcast',
description: 'Live and recorded leadership sessions',
icon: Podcast
}
]
},
{
label: 'Online Courses',
href: '/learning-online'
},
{
label: 'Contact Us',
href: '/contact'
}
];
const signInOptions = [
{
label: 'Corporate HR',
href: '/signin/corporate-hr',
description: 'HR dashboard, team management, and bulk enrollment tools'
},
{
label: 'Corporate Learner',
href: '/signin/corporate-learner',
description: 'Employee learning dashboard and assigned programs'
},
{
label: 'Self-Learner',
href: '/signin/self-learner',
description: 'Individual professional development access'
}
];
function NavLink({ item, isMobile = false }: { item: NavLink; isMobile?: boolean }) {
const [isOpen, setIsOpen] = useState(false);
if (item.href) {
return (
<Button
variant="ghost"
onClick={() => navigateTo(item.href!)}
className={isMobile ? "w-full justify-start min-h-[44px]" : "min-h-[44px]"}
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontWeight: 'normal',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{item.icon && <item.icon className="w-4 h-4 mr-2" />}
{item.label}
</Button>
);
}
if (isMobile) {
return (
<Collapsible open={isOpen} onOpenChange={setIsOpen}>
<CollapsibleTrigger asChild>
<Button
variant="ghost"
className="w-full justify-between min-h-[44px]"
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontWeight: 'normal',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
<span className="flex items-center">
{item.icon && <item.icon className="w-4 h-4 mr-2" />}
{item.label}
</span>
<ChevronRight className={`w-4 h-4 transition-transform ${isOpen ? 'rotate-90' : ''}`} />
</Button>
</CollapsibleTrigger>
<CollapsibleContent className="pl-4 space-y-1">
{item.items?.map((subItem) => (
<Button
key={subItem.href}
variant="ghost"
onClick={() => navigateTo(subItem.href)}
className="w-full justify-start min-h-[44px] pl-6"
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontWeight: 'normal',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{subItem.icon && <subItem.icon className="w-4 h-4 mr-2" />}
{subItem.label}
</Button>
))}
</CollapsibleContent>
</Collapsible>
);
}
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
className="flex items-center gap-1 min-h-[44px] transition-all duration-300 hover:transform hover:-translate-y-1"
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontWeight: 'normal',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{item.icon && <item.icon className="w-4 h-4 mr-2" />}
{item.label}
<ChevronDown className="w-4 h-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="start"
className="w-80"
style={{
backgroundColor: 'var(--color-bg-white)',
border: `1px solid var(--color-border)`,
borderRadius: '12px',
boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
fontFamily: 'var(--font-family-base)'
}}
>
{item.items?.map((subItem) => (
<DropdownMenuItem
key={subItem.href}
onClick={() => navigateTo(subItem.href)}
className="flex items-start gap-3 p-4 cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-1"
style={{
fontFamily: 'var(--font-family-base)'
}}
>
{subItem.icon && (
<div
className="w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0 mt-1"
style={{
backgroundColor: 'rgba(4, 4, 91, 0.1)',
color: 'var(--color-brand-primary)'
}}
>
<subItem.icon className="w-4 h-4" />
</div>
)}
<div className="flex-1">
<div
className="font-medium"
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontWeight: '400',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{subItem.label}
</div>
{subItem.description && (
<div
className="mt-1"
style={{
fontSize: '12px', // Reduced from var(--font-small) by 2px
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-small)'
}}
>
{subItem.description}
</div>
)}
</div>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
);
}
function ProfileDropdown({ user }: { user: any }) {
const { signOut } = useAuth();
const handleSignOut = () => {
signOut();
navigateTo('/');
};
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
className="flex items-center gap-3 px-3 py-2 h-auto min-h-[44px]"
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontFamily: 'var(--font-family-base)'
}}
>
<Avatar className="h-8 w-8">
<AvatarImage src={user.avatar} alt={user.name} />
<AvatarFallback
className="text-sm"
style={{ fontFamily: 'var(--font-family-base)' }}
>
{user.name.split(' ').map((n: string) => n[0]).join('')}
</AvatarFallback>
</Avatar>
<div className="text-left">
<div
className="font-medium"
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontWeight: '400',
fontFamily: 'var(--font-family-base)'
}}
>
{user.corporateName}
</div>
<div
style={{
fontSize: '12px', // Reduced from var(--font-small) by 2px
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
{user.name}
</div>
</div>
<ChevronDown className="w-4 h-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
className="w-64"
style={{
backgroundColor: 'var(--color-bg-white)',
border: `1px solid var(--color-border)`,
borderRadius: '12px',
fontFamily: 'var(--font-family-base)'
}}
>
<DropdownMenuLabel
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontFamily: 'var(--font-family-base)'
}}
>
<div
className="font-medium"
style={{ fontWeight: '400' }}
>
{user.corporateName}
</div>
<div
className="font-normal"
style={{
fontSize: '12px', // Reduced from var(--font-small) by 2px
color: 'var(--color-gray-muted)'
}}
>
{user.email}
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem
onClick={() => navigateTo('/dashboard')}
className="min-h-[44px]"
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontFamily: 'var(--font-family-base)'
}}
>
<LayoutDashboard className="w-4 h-4 mr-2" />
Dashboard
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => navigateTo('/team')}
className="min-h-[44px]"
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontFamily: 'var(--font-family-base)'
}}
>
<Users className="w-4 h-4 mr-2" />
Team Management
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => navigateTo('/profile')}
className="min-h-[44px]"
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontFamily: 'var(--font-family-base)'
}}
>
<User className="w-4 h-4 mr-2" />
Profile
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => navigateTo('/settings')}
className="min-h-[44px]"
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontFamily: 'var(--font-family-base)'
}}
>
<Settings className="w-4 h-4 mr-2" />
Settings
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
onClick={handleSignOut}
className="min-h-[44px]"
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontFamily: 'var(--font-family-base)',
color: 'var(--destructive)'
}}
>
<LogOut className="w-4 h-4 mr-2" />
Sign Out
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
function CartIcon() {
const { cartCount } = useCart();
const handleCartClick = () => {
navigateTo('/cart');
};
return (
<Button
variant="ghost"
size="icon"
onClick={handleCartClick}
className="relative min-h-[44px] min-w-[44px] hover:bg-gray-100 transition-all duration-300"
aria-label={`Shopping cart with ${cartCount} items`}
>
<ShoppingCart className="w-5 h-5 text-gray-600" />
{/* Cart Count Badge */}
{cartCount > 0 && (
<div
className="absolute -top-1 -right-1 min-w-[18px] h-[18px] flex items-center justify-center rounded-full text-xs font-medium text-white animate-in fade-in zoom-in duration-300"
style={{
backgroundColor: '#dc2626', // Red background for notification
fontSize: '11px',
fontFamily: 'var(--font-family-base)',
lineHeight: '1'
}}
>
{cartCount > 9 ? '9+' : cartCount}
</div>
)}
</Button>
);
}
export function Navigation({ currentPage }: NavigationProps) {
const [isScrolled, setIsScrolled] = useState(false);
const { user, isAuthenticated, signOut } = useAuth();
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 10);
};
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
const handleMobileSignOut = () => {
signOut();
navigateTo('/');
};
return (
<>
{/* Top notification bar - PRESERVED */}
<div className="notification-strip">
<span className="notification-text">
Join Our Upcoming Leadership Webinars - Transform Your Leadership Journey
</span>
<Button
variant="ghost"
size="sm"
onClick={() => navigateTo('/enroll')}
className="notification-button"
>
Enroll Now
<ChevronRight className="w-4 h-4 ml-1" />
</Button>
</div>
{/* Main navigation header - ENHANCED STICKY */}
<header
className={`w-full border-b transition-all duration-300 navbar-sticky ${isScrolled ? 'shadow-lg scrolled' : 'shadow-sm'}`}
style={{
borderColor: 'var(--color-border)'
}}
>
<nav className="container mx-auto px-4 lg:px-8">
<div className="flex items-center justify-between h-20">
{/* Logo */}
<div className="flex items-center">
<Button
variant="ghost"
className="p-2 hover:bg-transparent"
onClick={() => navigateTo('/')}
>
<img
src={klcLogo}
alt="Kautilya Leadership Centre"
className="h-12 w-auto object-contain"
/>
</Button>
</div>
{/* Desktop Navigation */}
<div className="hidden lg:flex items-center gap-2">
{navigationItems.map((item) => (
<NavLink key={item.label} item={item} />
))}
</div>
{/* Right Side Actions */}
<div className="flex items-center gap-4">
{/* Cart Icon - Always visible */}
<CartIcon />
{/* Authentication Button/Profile */}
{isAuthenticated && user ? (
<div className="hidden md:flex">
<ProfileDropdown user={user} />
</div>
) : (
<div className="hidden md:flex items-center">
<Button
onClick={() => navigateTo('/leadership-journey')}
className="management-dev-glassmorphic-btn text-body px-8 py-4 min-h-[52px] border transition-all duration-300 group"
style={{
fontFamily: 'var(--font-family-base)',
color: '#04045B'
}}
>
Start Leadership Journey
<ArrowRight
className="w-5 h-5 ml-2 transition-transform duration-300 group-hover:translate-x-1"
style={{ color: '#04045B' }}
/>
</Button>
</div>
)}
{/* Mobile Menu */}
<Sheet>
<SheetTrigger asChild>
<Button variant="ghost" size="icon" className="lg:hidden min-h-[44px] min-w-[44px]">
<Menu className="w-6 h-6" />
</Button>
</SheetTrigger>
<SheetContent
side="right"
className="w-80"
style={{
backgroundColor: 'var(--color-bg-white)',
fontFamily: 'var(--font-family-base)',
zIndex: 10000
}}
>
<SheetHeader>
<SheetTitle
style={{
fontSize: 'var(--font-h4)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
Navigation
</SheetTitle>
</SheetHeader>
<div className="mt-6 space-y-4">
{navigationItems.map((item) => (
<NavLink key={item.label} item={item} isMobile />
))}
<div className="pt-4 border-t space-y-3">
{isAuthenticated && user ? (
<div className="space-y-3">
<div
className="flex items-center gap-3 p-3 rounded-lg"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.05)' }}
>
<Avatar className="h-10 w-10">
<AvatarImage src={user.avatar} alt={user.name} />
<AvatarFallback style={{ fontFamily: 'var(--font-family-base)' }}>
{user.name.split(' ').map((n: string) => n[0]).join('')}
</AvatarFallback>
</Avatar>
<div>
<div
className="font-medium"
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontWeight: '400',
fontFamily: 'var(--font-family-base)'
}}
>
{user.corporateName}
</div>
<div
style={{
fontSize: '12px', // Reduced from var(--font-small) by 2px
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
{user.name}
</div>
</div>
</div>
<Button
variant="outline"
className="w-full justify-start min-h-[44px]"
onClick={() => navigateTo('/dashboard')}
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontFamily: 'var(--font-family-base)'
}}
>
<LayoutDashboard className="w-4 h-4 mr-2" />
Dashboard
</Button>
<Button
variant="outline"
className="w-full justify-start min-h-[44px]"
onClick={() => navigateTo('/profile')}
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontFamily: 'var(--font-family-base)'
}}
>
<User className="w-4 h-4 mr-2" />
Profile
</Button>
<Button
variant="outline"
className="w-full justify-start min-h-[44px]"
onClick={handleMobileSignOut}
style={{
fontSize: '14px', // Reduced from var(--font-body) by 2px
fontFamily: 'var(--font-family-base)',
color: 'var(--destructive)'
}}
>
<LogOut className="w-4 h-4 mr-2" />
Sign Out
</Button>
</div>
) : (
<div className="space-y-2">
<Button
onClick={() => navigateTo('/leadership-journey')}
className="management-dev-glassmorphic-btn text-body px-8 py-4 min-h-[52px] border transition-all duration-300 w-full group"
style={{
fontFamily: 'var(--font-family-base)',
color: '#04045B'
}}
>
Start Leadership Journey
<ArrowRight
className="w-5 h-5 ml-2 transition-transform duration-300 group-hover:translate-x-1"
style={{ color: '#04045B' }}
/>
</Button>
</div>
)}
</div>
</div>
</SheetContent>
</Sheet>
</div>
</div>
</nav>
</header>
</>
);
}

View File

@@ -0,0 +1 @@
// This file has been removed

View File

@@ -0,0 +1 @@
// This file has been removed

View File

@@ -0,0 +1 @@
// This file has been removed

View File

@@ -0,0 +1,146 @@
import React, { useEffect } from 'react';
import svgPaths from "../imports/svg-i1joeov37f";
import { navigateTo } from './Router';
interface PrimaryCTAButtonProps {
text: string;
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
className?: string;
ariaLabel?: string;
debugId?: string; // Add debug identifier
}
export const PrimaryCTAButton: React.FC<PrimaryCTAButtonProps> = ({
text,
onClick,
className = '',
ariaLabel,
debugId = 'unknown'
}) => {
// Debug: Log when component mounts
useEffect(() => {
console.log(`PrimaryCTAButton ${debugId} mounted`);
}, [debugId]);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
console.log(`Primary CTA Button ${debugId} clicked with text: "${text}"`); // Debug log
// Handle webinars navigation
if (text === "Join Our Webinars" || text === "Explore Webinars" || text === "View Webinars") {
console.log(`Navigating to webinars page for ${debugId}`);
navigateTo('/webinars');
} else if (text === "Register Free" || text === "Watch Replay" || text === "Launch in Zoom") {
// These are handled by individual webinar detail pages
console.log(`Webinar CTA handled by detail page for ${debugId}`);
} else if (onClick) {
console.log(`Custom onClick handler found for ${debugId}, executing it`); // Debug log
onClick(e);
} else {
console.log(`No custom onClick for ${debugId}, navigating to webcast page`); // Debug log
// Navigate to webcast page by default
navigateTo('/learning/webcast');
}
};
return (
<button
className={`primary-cta-button group box-border content-stretch flex flex-row gap-2.5 items-center justify-start p-0 relative cursor-pointer overflow-hidden ${className}`}
style={{
background: 'transparent',
border: 'none',
width: 'fit-content' // Perfect width - no extra horizontal space
}}
onClick={handleClick}
aria-label={ariaLabel || text}
>
{/* Icon Container with Slide Animation */}
<div className="relative shrink-0 size-[50px] overflow-hidden">
{/* Background Rectangle - Consistent Yellow Color */}
<div className="absolute inset-0 bg-[#F8C301]" />
{/* Icon Layer - Sliding Animation */}
<div className="icon-layer absolute inset-0 w-full h-full">
{/* Primary Arrow - Slides out diagonally up-right */}
<div className="icon absolute inset-0 flex items-center justify-center transition-all duration-300 ease-in-out group-hover:translate-x-6 group-hover:-translate-y-6 group-hover:opacity-0">
<svg
className="block w-full h-full"
fill="none"
preserveAspectRatio="none"
viewBox="0 0 50 50"
>
<g clipPath="url(#clip0_primary_cta_primary)">
<path d={svgPaths.p5b8d700} fill="white" />
<path d={svgPaths.p30b71a00} fill="white" />
</g>
<defs>
<clipPath id="clip0_primary_cta_primary">
<rect fill="white" height="50" width="50" />
</clipPath>
</defs>
</svg>
</div>
{/* Secondary Arrow - Slides in from bottom-left */}
<div className="icon absolute inset-0 flex items-center justify-center opacity-0 -translate-x-6 translate-y-6 transition-all duration-300 ease-in-out group-hover:translate-x-0 group-hover:translate-y-0 group-hover:opacity-100">
<svg
className="block w-full h-full"
fill="none"
preserveAspectRatio="none"
viewBox="0 0 50 50"
>
<g clipPath="url(#clip0_primary_cta_secondary)">
<path d={svgPaths.p5b8d700} fill="white" />
<path d={svgPaths.p30b71a00} fill="white" />
</g>
<defs>
<clipPath id="clip0_primary_cta_secondary">
<rect fill="white" height="50" width="50" />
</clipPath>
</defs>
</svg>
</div>
</div>
</div>
{/* Text Section with Vertical Slide Animation */}
<div className="text-layer relative shrink-0 overflow-hidden flex items-center" style={{
height: '28px',
fontFamily: 'Inter, sans-serif',
fontSize: '20px',
fontWeight: '400',
lineHeight: '28px',
whiteSpace: 'nowrap',
color: '#ffffff',
width: 'fit-content' // Perfect text width - no extra horizontal space
}}>
{/* Primary Text - Slides up and out */}
<div
className="text-element absolute inset-0 flex items-center justify-start transition-all duration-300 ease-in-out group-hover:-translate-y-full group-hover:opacity-0"
style={{
color: '#ffffff',
fontFamily: 'Inter, sans-serif',
fontSize: '20px',
fontWeight: '400',
lineHeight: '28px'
}}
>
{text}
</div>
{/* Secondary Text - Slides in from bottom */}
<div
className="text-element absolute inset-0 flex items-center justify-start translate-y-full opacity-0 transition-all duration-300 ease-in-out group-hover:translate-y-0 group-hover:opacity-100"
style={{
color: '#ffffff',
fontFamily: 'Inter, sans-serif',
fontSize: '20px',
fontWeight: '400',
lineHeight: '28px'
}}
>
{text}
</div>
</div>
</button>
);
};

View File

@@ -0,0 +1,33 @@
import React from 'react';
import { PrimaryCTAButton, PrimaryCTAButtonProps } from './PrimaryCTAButton';
/**
* Blue Primary CTA Button Component
*
* A variant of the Primary CTA Button with blue background (#04045B) and black text (#26231A).
* Preserves all sophisticated animations and functionality from the main component.
*
* Features:
* - Blue background (#04045B) instead of yellow
* - Black text (#26231A) for contrast
* - All sophisticated slide animations preserved
* - Consistent with brand guidelines
*
* Usage:
* ```tsx
* <PrimaryCTAButtonBlue
* text="Get Started"
* onClick={() => handleClick()}
* />
* ```
*/
export const PrimaryCTAButtonBlue: React.FC<PrimaryCTAButtonProps> = (props) => {
return (
<PrimaryCTAButton
{...props}
className={`primary-cta-button-blue ${props.className || ''}`}
/>
);
};
export default PrimaryCTAButtonBlue;

View File

@@ -0,0 +1,90 @@
import React from 'react';
import { PrimaryCTAButton, PrimaryCTAButtonProps } from './PrimaryCTAButton';
export type CTAButtonVariant = 'yellow' | 'blue' | 'custom';
export interface PrimaryCTAButtonVariantProps extends PrimaryCTAButtonProps {
variant?: CTAButtonVariant;
customBackgroundColor?: string;
customTextColor?: string;
customHoverBackgroundColor?: string;
}
/**
* Primary CTA Button Variant Component
*
* A flexible variant of the Primary CTA Button that supports multiple color schemes
* while preserving all sophisticated animations and functionality.
*
* Variants:
* - 'yellow': Original yellow background (#F8C301) with white text (default)
* - 'blue': Blue background (#04045B) with black text (#26231A)
* - 'custom': Custom colors using customBackgroundColor and customTextColor props
*
* Features:
* - Multiple pre-defined color variants
* - Custom color support
* - All sophisticated slide animations preserved
* - Consistent with brand guidelines
*
* Usage:
* ```tsx
* // Yellow variant (default)
* <PrimaryCTAButtonVariant text="Learn More" onClick={handleClick} />
*
* // Blue variant
* <PrimaryCTAButtonVariant variant="blue" text="Get Started" onClick={handleClick} />
*
* // Custom colors
* <PrimaryCTAButtonVariant
* variant="custom"
* customBackgroundColor="#FF6B6B"
* customTextColor="#FFFFFF"
* customHoverBackgroundColor="#FF5252"
* text="Custom Button"
* onClick={handleClick}
* />
* ```
*/
export const PrimaryCTAButtonVariant: React.FC<PrimaryCTAButtonVariantProps> = ({
variant = 'yellow',
customBackgroundColor,
customTextColor,
customHoverBackgroundColor,
className,
...props
}) => {
// Generate variant-specific className
const getVariantClassName = () => {
switch (variant) {
case 'blue':
return 'primary-cta-button-blue';
case 'yellow':
return 'primary-cta-button-yellow';
case 'custom':
return 'primary-cta-button-custom';
default:
return 'primary-cta-button-yellow';
}
};
// Custom CSS variables for custom variant
const customStyles = variant === 'custom' ? {
'--custom-bg-color': customBackgroundColor || '#F8C301',
'--custom-text-color': customTextColor || '#FFFFFF',
'--custom-hover-bg-color': customHoverBackgroundColor || customBackgroundColor || '#F8C301',
} as React.CSSProperties : {};
const combinedClassName = `${getVariantClassName()} ${className || ''}`;
return (
<div style={customStyles}>
<PrimaryCTAButton
{...props}
className={combinedClassName}
/>
</div>
);
};
export default PrimaryCTAButtonVariant;

View File

@@ -0,0 +1,33 @@
import React from 'react';
import { PrimaryCTAButton, PrimaryCTAButtonProps } from './PrimaryCTAButton';
/**
* Yellow Primary CTA Button Component
*
* A variant of the Primary CTA Button that maintains the original yellow background (#F8C301) with white text.
* This is the default styling variant that preserves the original design.
*
* Features:
* - Original yellow background (#F8C301)
* - White text for contrast
* - All sophisticated slide animations preserved
* - Default brand styling
*
* Usage:
* ```tsx
* <PrimaryCTAButtonYellow
* text="Learn More"
* onClick={() => handleClick()}
* />
* ```
*/
export const PrimaryCTAButtonYellow: React.FC<PrimaryCTAButtonProps> = (props) => {
return (
<PrimaryCTAButton
{...props}
className={`primary-cta-button-yellow ${props.className || ''}`}
/>
);
};
export default PrimaryCTAButtonYellow;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,197 @@
# CTA Button Spacing Optimization Guidelines
## 🎯 No Extra Horizontal Spacing Policy
This document establishes the **zero extra spacing** standard for all CTA buttons throughout the KLC website to ensure perfect, tight layouts with no unnecessary horizontal space.
## ✅ Primary CTA Button (Reference Implementation)
The `PrimaryCTAButton` component serves as the **gold standard** for spacing optimization:
```tsx
// ✅ CORRECT: Perfect width with no extra space
style={{
width: 'fit-content' // Button sizes exactly to content
}}
// ❌ AVOID: Fixed widths that create extra space
style={{
width: '324px' // Creates unnecessary horizontal padding
}}
// ❌ AVOID: Calculated widths that may be imprecise
style={{
width: `${estimatedWidth + padding}px` // Can create extra space
}}
```
## 🔧 Implementation Standards
### 1. Button Container Sizing
```tsx
// Use fit-content for perfect sizing
button: {
width: 'fit-content',
display: 'flex',
alignItems: 'center',
gap: '10px' // Consistent gap between elements
}
```
### 2. Text Container Optimization
```tsx
// Text containers should also use fit-content
textContainer: {
width: 'fit-content',
whiteSpace: 'nowrap',
overflow: 'hidden'
}
```
### 3. Icon Container Standards
```tsx
// Fixed icon sizes with no extra space
iconContainer: {
width: '50px',
height: '50px',
flexShrink: 0 // Prevent compression
}
```
## 📏 Components to Update
Apply these principles to ALL CTA buttons throughout the website:
### ✅ Already Optimized
- `PrimaryCTAButton.tsx` - ✅ Fully optimized
- `Navigation.tsx` CTA button - ✅ Now uses PrimaryCTAButton
### 🔄 Needs Review & Optimization
#### Hero Section
- Hero CTA buttons in `HeroSection.tsx`
- Any custom hero buttons
#### Services Section
- Service CTA buttons in `ServicesSection.tsx`
- Service card action buttons
- "Learn More" buttons
#### CTA Banner Section
- Main CTA buttons in `CTABannerSection.tsx`
- Secondary action buttons
#### Footer
- Newsletter signup buttons in `Footer.tsx`
- Footer CTA buttons
#### Page-Specific CTAs
- Leadership Journey page buttons
- Service detail page CTAs
- About page action buttons
- Learning page CTAs
#### Modal & Dialog CTAs
- Popup action buttons
- Form submission buttons
- Modal confirmation buttons
## 🎨 Styling Principles
### Width Calculation Method
```tsx
// ✅ PREFERRED: CSS fit-content
width: 'fit-content'
// ✅ ACCEPTABLE: Flexbox natural sizing
display: 'flex'
// No explicit width = natural sizing
// ❌ AVOID: Manual calculations
width: `${textWidth + iconWidth + gaps + padding}px`
```
### Responsive Considerations
```tsx
// Ensure responsiveness is maintained
@media (max-width: 768px) {
button: {
width: 'fit-content', // Still use fit-content
fontSize: '16px', // Adjust text size
gap: '8px' // Adjust spacing
}
}
```
## 🔍 Quality Assurance Checklist
For each CTA button, verify:
- [ ] **No Extra Width**: Button width exactly matches content needs
- [ ] **No Horizontal Padding**: Only necessary internal spacing
- [ ] **Consistent Gap**: Proper spacing between icon and text (10px)
- [ ] **Text Fit**: Text container width matches text content exactly
- [ ] **Icon Precision**: Icon container has exact dimensions (50px × 50px)
- [ ] **Responsive Behavior**: Maintains fit-content approach across breakpoints
- [ ] **Animation Compatibility**: Width optimization doesn't break hover/click animations
## 🚀 Implementation Process
### Step 1: Identify Current CTA Buttons
1. Audit all components containing CTA buttons
2. Document current width calculation methods
3. Identify components with excessive horizontal spacing
### Step 2: Apply Optimization
1. Replace fixed widths with `width: 'fit-content'`
2. Remove manual width calculations
3. Ensure text containers use `width: 'fit-content'`
4. Test responsive behavior
### Step 3: Validation
1. Visual inspection for extra spacing
2. Test across different text lengths
3. Verify responsive behavior
4. Confirm animation functionality
## 📱 Responsive Standards
```tsx
// Consistent approach across breakpoints
.cta-button {
width: fit-content;
@media (max-width: 768px) {
width: fit-content; // Maintain principle
gap: 8px; // Adjust spacing only
}
@media (max-width: 480px) {
width: fit-content; // Maintain principle
gap: 6px; // Adjust spacing only
}
}
```
## 💡 Benefits Achieved
1. **Perfect Visual Alignment**: No unnecessary gaps or spacing
2. **Dynamic Adaptation**: Buttons automatically adjust to content
3. **Responsive Excellence**: Consistent behavior across devices
4. **Maintenance Simplicity**: No complex width calculations to maintain
5. **Design System Consistency**: Uniform spacing approach across all CTAs
6. **Performance Optimization**: Reduced layout calculations
## 🔗 Related Components
When implementing, also consider:
- Button hover states
- Focus indicators
- Loading states
- Disabled states
- Icon animations
- Text animations
---
**Next Steps**: Apply this optimization approach to all identified CTA buttons throughout the website to achieve perfect, space-efficient button layouts across the entire KLC platform.

View File

@@ -0,0 +1,381 @@
# Independent Primary CTA Button System
## Overview
The KLC Primary CTA Button system has been updated to provide **complete independence** between button instances. Each Primary CTA Button can now have unique styling without affecting any other buttons on the website, while preserving all sophisticated animations and functionality.
## 🎯 Key Benefits
### ✅ **Complete Independence**
- Each button instance is completely separate
- Changes to one button will NEVER affect others
- No global CSS overrides that impact all buttons
### ✅ **Animation Preservation**
- All sophisticated slide animations maintained
- Text and icon transitions work perfectly
- 300ms ease-in-out timing preserved
### ✅ **Component Protection**
- Main `/components/PrimaryCTAButton.tsx` never modified
- Core functionality remains intact
- Sophisticated animation structure protected
### ✅ **Unlimited Flexibility**
- Support for any color combination
- Custom colors via CSS classes or variant props
- Pre-built variants for common use cases
## 🛠️ Implementation Methods
### Method 1: Variant Components (Recommended)
Use pre-built variant components for common color schemes:
```tsx
import { PrimaryCTAButton } from './components/PrimaryCTAButton';
import { PrimaryCTAButtonYellow } from './components/PrimaryCTAButtonYellow';
import { PrimaryCTAButtonVariant } from './components/PrimaryCTAButtonVariant';
// Default blue variant - NEW DEFAULT with brand blue and black text
<PrimaryCTAButton
text="Get Started"
onClick={handleGetStarted}
ariaLabel="Get started with KLC services"
/>
// Yellow variant - Former default styling
<PrimaryCTAButtonYellow
text="Learn More"
onClick={handleLearnMore}
ariaLabel="Learn more about our programs"
/>
// Custom variant with any colors
<PrimaryCTAButtonVariant
variant="custom"
customBackgroundColor="#28A745"
customTextColor="#FFFFFF"
customHoverBackgroundColor="#1E7E34"
text="Custom Action"
onClick={handleCustomAction}
/>
```
### Method 2: Unique CSS Classes
Add unique CSS class modifiers to any Primary CTA Button:
```tsx
import { PrimaryCTAButton } from './components/PrimaryCTAButton';
// Default blue button (no class needed)
<PrimaryCTAButton
text="Blue Action"
onClick={handleBlueAction}
/>
// Yellow button with unique CSS class
<PrimaryCTAButton
text="Yellow Action"
onClick={handleYellowAction}
className="cta-custom-yellow"
/>
// Green button with unique CSS class
<PrimaryCTAButton
text="Green Action"
onClick={handleGreenAction}
className="cta-custom-green"
/>
// Red button with unique CSS class
<PrimaryCTAButton
text="Red Action"
onClick={handleRedAction}
className="cta-custom-red"
/>
```
## 🎨 Available CSS Class Modifiers
### Pre-defined Classes
**Default (no class needed):** Primary CTA Button
- Background: `#04045B` (Brand Blue) - **NEW DEFAULT**
- Text: `#26231A` (Brand Black)
- Hover Background: `#030359` (Darker Blue)
**Yellow Variant:** `.cta-custom-yellow`
- Background: `#F8C301` (Yellow) - **Former Default**
- Text: `#FFFFFF` (White)
- Hover Background: `#E6AF01` (Darker Yellow)
**Green Variant:** `.cta-custom-green`
- Background: `#28A745` (Green)
- Text: `#FFFFFF` (White)
- Hover Background: `#1E7E34` (Darker Green)
### Creating Custom Classes
Add new color combinations in `/styles/globals.css`:
```css
/* Custom Red Button */
.primary-cta-button.cta-custom-red .bg-\[#F8C301\] {
background-color: #DC3545 !important; /* Red background */
}
.primary-cta-button.cta-custom-red div[class*="bg-[#F8C301]"] {
background-color: #DC3545 !important;
}
.primary-cta-button.cta-custom-red .text-layer,
.primary-cta-button.cta-custom-red .text-element,
.primary-cta-button.cta-custom-red .text-layer *,
.primary-cta-button.cta-custom-red .text-element * {
color: #FFFFFF !important; /* White text */
}
/* Red hover state */
.primary-cta-button.cta-custom-red:hover .bg-\[#F8C301\] {
background-color: #C82333 !important; /* Darker red on hover */
}
.primary-cta-button.cta-custom-red:hover div[class*="bg-[#F8C301]"] {
background-color: #C82333 !important;
}
```
## 📋 Component Reference
### PrimaryCTAButtonBlue
**Purpose:** Blue variant for brand-consistent primary actions
**Colors:** Blue background (#04045B), Black text (#26231A)
```tsx
interface PrimaryCTAButtonBlueProps extends PrimaryCTAButtonProps {
// Inherits all PrimaryCTAButton props
}
```
### PrimaryCTAButtonYellow
**Purpose:** Original yellow variant (default styling)
**Colors:** Yellow background (#F8C301), White text (#FFFFFF)
```tsx
interface PrimaryCTAButtonYellowProps extends PrimaryCTAButtonProps {
// Inherits all PrimaryCTAButton props
}
```
### PrimaryCTAButtonVariant
**Purpose:** Flexible component with variant and custom color support
```tsx
interface PrimaryCTAButtonVariantProps extends PrimaryCTAButtonProps {
variant?: 'yellow' | 'blue' | 'custom';
customBackgroundColor?: string;
customTextColor?: string;
customHoverBackgroundColor?: string;
}
// Usage examples
<PrimaryCTAButtonVariant variant="blue" text="Blue Button" />
<PrimaryCTAButtonVariant
variant="custom"
customBackgroundColor="#FF6B6B"
customTextColor="#FFFFFF"
text="Custom Button"
/>
```
## 🔧 Advanced Usage Examples
### Multiple Independent Buttons on Same Page
```tsx
function HomePage() {
return (
<div>
{/* Hero section - Blue button */}
<section className="hero">
<PrimaryCTAButtonBlue
text="Get Started Today"
onClick={handleGetStarted}
/>
</section>
{/* Services section - Yellow button */}
<section className="services">
<PrimaryCTAButtonYellow
text="Explore Services"
onClick={handleExploreServices}
/>
</section>
{/* Contact section - Custom green button */}
<section className="contact">
<PrimaryCTAButtonVariant
variant="custom"
customBackgroundColor="#28A745"
customTextColor="#FFFFFF"
text="Contact Us"
onClick={handleContact}
/>
</section>
{/* Footer - Custom purple button */}
<footer>
<PrimaryCTAButton
text="Subscribe"
onClick={handleSubscribe}
className="cta-custom-purple"
/>
</footer>
</div>
);
}
```
### Dynamic Button Colors
```tsx
function DynamicButton({ buttonType }: { buttonType: 'primary' | 'secondary' | 'danger' }) {
const getVariantProps = () => {
switch (buttonType) {
case 'primary':
return {
variant: 'blue' as const,
text: 'Primary Action'
};
case 'secondary':
return {
variant: 'yellow' as const,
text: 'Secondary Action'
};
case 'danger':
return {
variant: 'custom' as const,
customBackgroundColor: '#DC3545',
customTextColor: '#FFFFFF',
text: 'Danger Action'
};
}
};
return (
<PrimaryCTAButtonVariant
{...getVariantProps()}
onClick={handleDynamicAction}
/>
);
}
```
## 🚨 Important Guidelines
### ✅ DO
- Use variant components for common color schemes
- Create unique CSS classes for custom colors
- Test hover states for proper contrast
- Maintain accessibility with proper ARIA labels
- Follow brand guidelines for color choices
### ❌ DON'T
- Modify `/components/PrimaryCTAButton.tsx` directly
- Use global CSS that affects all buttons
- Break the animation structure
- Forget to test accessibility
- Use colors that don't meet contrast requirements
## 🎨 Color Guidelines
### Brand-Approved Colors
**Primary Blue:** `#04045B`
- Use for main call-to-action buttons
- Pair with black text (`#26231A`) for contrast
**Accent Yellow:** `#F8C301`
- Original brand color
- Pair with white text (`#FFFFFF`)
**Secondary Colors:** Use sparingly
- Green: `#28A745` for success actions
- Red: `#DC3545` for warning/danger actions
- Purple: `#6F42C1` for special campaigns
### Accessibility Requirements
- Ensure minimum 4.5:1 contrast ratio
- Test with screen readers
- Provide meaningful ARIA labels
- Support keyboard navigation
## 🔄 Migration Guide
### From Global CSS Overrides
**Old approach:**
```css
/* This affected ALL buttons globally */
.primary-cta-button .bg-[#F8C301] {
background-color: #04045B !important;
}
```
**New approach:**
```tsx
// Use specific variant components
<PrimaryCTAButtonBlue text="Get Started" onClick={handleClick} />
// Or unique CSS classes
<PrimaryCTAButton text="Custom" onClick={handleClick} className="cta-custom-blue" />
```
### From Direct Component Modification
**Old approach:**
```tsx
// Modifying main component (❌ PROHIBITED)
// Never do this!
```
**New approach:**
```tsx
// Use independent styling methods
<PrimaryCTAButtonVariant
variant="custom"
customBackgroundColor="#your-color"
text="Your Text"
onClick={handleClick}
/>
```
## 🧪 Testing Checklist
When implementing independent Primary CTA buttons:
- [ ] Animations work correctly
- [ ] Hover states display properly
- [ ] Text contrast meets accessibility standards
- [ ] Multiple buttons on same page don't interfere
- [ ] Responsive behavior is maintained
- [ ] Keyboard navigation works
- [ ] Screen reader compatibility
- [ ] Focus indicators are visible
## 📞 Support
For questions about the independent Primary CTA Button system:
1. Check this documentation first
2. Review `/components/README-PrimaryCTAButton-Variants.md`
3. Examine existing implementations in the codebase
4. Follow component protection guidelines strictly
Remember: The main `/components/PrimaryCTAButton.tsx` file must NEVER be modified for styling changes. Always use the independent styling methods documented here.

View File

@@ -0,0 +1,173 @@
# Primary CTA Button Variants
This document explains how to use the different Primary CTA Button variants available in the KLC website design system.
## Overview
To provide individual color control while preserving the sophisticated animations, we've created separate Primary CTA Button variant components. Each variant maintains all the original functionality and animations while allowing different color schemes.
## Available Components
### 1. Original PrimaryCTAButton (Protected)
- **File**: `/components/PrimaryCTAButton.tsx`
- **Status**: 🔒 PROTECTED - Never modify directly
- **Default**: Yellow background (#F8C301) with white text
### 2. PrimaryCTAButtonYellow
- **File**: `/components/PrimaryCTAButtonYellow.tsx`
- **Purpose**: Maintains original yellow styling
- **Colors**: Yellow background (#F8C301), White text (#FFFFFF)
### 3. PrimaryCTAButtonBlue
- **File**: `/components/PrimaryCTAButtonBlue.tsx`
- **Purpose**: Blue variant for brand consistency
- **Colors**: Blue background (#04045B), Black text (#26231A)
### 4. PrimaryCTAButtonVariant
- **File**: `/components/PrimaryCTAButtonVariant.tsx`
- **Purpose**: Flexible component with variant and custom color support
- **Variants**: 'yellow', 'blue', 'custom'
## Usage Examples
### Yellow Variant (Default Styling)
```tsx
import { PrimaryCTAButtonYellow } from './components/PrimaryCTAButtonYellow';
<PrimaryCTAButtonYellow
text="Learn More"
onClick={() => handleClick()}
ariaLabel="Learn more about our services"
/>
```
### Blue Variant (Brand Blue)
```tsx
import { PrimaryCTAButtonBlue } from './components/PrimaryCTAButtonBlue';
<PrimaryCTAButtonBlue
text="Get Started"
onClick={() => handleClick()}
ariaLabel="Get started with KLC"
/>
```
### Flexible Variant Component
```tsx
import { PrimaryCTAButtonVariant } from './components/PrimaryCTAButtonVariant';
// Yellow variant
<PrimaryCTAButtonVariant
variant="yellow"
text="Default Yellow"
onClick={handleClick}
/>
// Blue variant
<PrimaryCTAButtonVariant
variant="blue"
text="Brand Blue"
onClick={handleClick}
/>
// Custom colors
<PrimaryCTAButtonVariant
variant="custom"
customBackgroundColor="#FF6B6B"
customTextColor="#FFFFFF"
customHoverBackgroundColor="#FF5252"
text="Custom Red Button"
onClick={handleClick}
/>
```
## Component Protection Policy
### 🔒 CRITICAL RULES
1. **NEVER modify `/components/PrimaryCTAButton.tsx`** - This is the protected base component
2. **All variants preserve animations** - Sophisticated slide animations are maintained
3. **Use variants for color changes** - Instead of modifying the main component
4. **CSS overrides are component-specific** - Each variant has its own CSS classes
### ✅ APPROVED MODIFICATIONS
- ✅ Create new variant components
- ✅ Use CSS classes for variant-specific styling
- ✅ Extend functionality through wrapper components
- ✅ Add custom color support via props
### ❌ PROHIBITED MODIFICATIONS
- ❌ Direct changes to main PrimaryCTAButton.tsx
- ❌ Global CSS overrides affecting all buttons
- ❌ Modifying animation structure or timing
- ❌ Breaking accessibility features
## CSS Classes Used
### Blue Variant
- `.primary-cta-button-blue` - Main blue variant class
- Background: #04045B (Brand Blue)
- Text: #26231A (Brand Black)
- Hover Background: #030359 (Darker Blue)
### Yellow Variant
- `.primary-cta-button-yellow` - Main yellow variant class
- Preserves original component styling
### Custom Variant
- `.primary-cta-button-custom` - Custom variant class
- Uses CSS custom properties:
- `--custom-bg-color`
- `--custom-text-color`
- `--custom-hover-bg-color`
## Migration Guide
### Existing Code
```tsx
// Old approach - affects all buttons globally
<PrimaryCTAButton text="Click Me" onClick={handleClick} />
```
### New Approach
```tsx
// New approach - specific variant control
<PrimaryCTAButtonBlue text="Click Me" onClick={handleClick} />
// or
<PrimaryCTAButtonYellow text="Click Me" onClick={handleClick} />
// or
<PrimaryCTAButtonVariant variant="blue" text="Click Me" onClick={handleClick} />
```
## Benefits
1. **Individual Control**: Each button can have different colors
2. **Animation Preservation**: All sophisticated animations maintained
3. **Component Protection**: Main component remains untouched
4. **Flexibility**: Support for custom colors when needed
5. **Brand Consistency**: Pre-defined variants follow brand guidelines
6. **Type Safety**: Full TypeScript support with proper prop types
## Best Practices
1. **Use specific variants** when you know the color scheme
2. **Use PrimaryCTAButtonVariant** for dynamic or custom colors
3. **Always provide meaningful ariaLabel** for accessibility
4. **Test hover states** to ensure proper color contrast
5. **Follow brand guidelines** when using custom colors
## Accessibility
All variants maintain the original accessibility features:
- Proper ARIA labels
- Keyboard navigation support
- Focus indicators
- Color contrast compliance (when using approved color combinations)
## Performance
- **No performance impact**: Variants are lightweight wrappers
- **CSS optimization**: Specific classes prevent global overrides
- **Animation performance**: All GPU-accelerated animations preserved

View File

@@ -0,0 +1,223 @@
# Primary CTA Button - Design System Component
## Overview
The `PrimaryCTAButton` is a sophisticated, reusable component that provides the exact same slide animations, design, and behavior as the hero section CTA button. It features advanced text and icon animations with dynamic width adjustment.
## Features
### ✨ Sophisticated Animations
- **Text Slide Animation**: Current text slides up and fades out while identical text slides in from below (300ms ease-in-out)
- **Arrow Icon Animation**: Arrow slides diagonally up-right and fades out while new arrow enters from bottom-left
- **Hardware Accelerated**: Optimized with proper transforms and will-change properties
### 🎨 Design Specifications
- **Icon**: Blue background (#04045B) with white arrow SVG, 50x50px container
- **Text**: White Inter font, 20px size, 400 weight, with text shadows for visibility
- **Responsive**: Automatically scales for mobile (48px icon) and mobile small (46px icon)
- **Dynamic Width**: Button width adjusts automatically based on text length
### ⚙️ Technical Implementation
- Uses the same SVG paths as the hero button
- Maintains brand consistency with design system colors
- Proper accessibility with ARIA labels and focus states
- Cross-browser compatible animations
## Usage
### Basic Example
```tsx
import { PrimaryCTAButton } from './components/PrimaryCTAButton';
// Simple usage
<PrimaryCTAButton
text="Get Started Today"
onClick={() => console.log('CTA clicked')}
/>
```
### With Custom aria-label
```tsx
<PrimaryCTAButton
text="Learn More"
onClick={() => navigate('/about')}
ariaLabel="Learn more about our services"
/>
```
### With Additional Classes
```tsx
<PrimaryCTAButton
text="Contact Us Now"
onClick={() => window.location.href = '/contact'}
className="mt-8 mx-auto"
/>
```
## Props Interface
```tsx
interface PrimaryCTAButtonProps {
text: string; // Button text content (required)
onClick: () => void; // Click handler (required)
ariaLabel?: string; // Custom aria-label (optional, defaults to text)
className?: string; // Additional CSS classes (optional)
}
```
## Dynamic Width Calculation
The component automatically calculates the optimal width based on text length:
- **Minimum Width**: 280px (ensures usability on mobile)
- **Dynamic Calculation**: Icon width (50px) + gap (10px) + padding (32px) + estimated text width
- **Text Width Estimation**: ~12px per character for 20px Inter font
### Width Examples:
- `"Get Started"` (11 chars) → ~324px
- `"Learn More About Us"` (18 chars) → ~372px
- `"Build Your Leadership Pipeline"` (31 chars) → ~464px
- `"Contact Our Team Today"` (21 chars) → ~384px
## Responsive Behavior
### Desktop (Default)
- Icon: 50x50px
- Text: 20px font size, 28px line height
- Gap: 10px between icon and text
### Tablet (≤768px)
- Icon: 48x48px
- Text: 18px font size, 24px line height
- Gap: 8px between icon and text
### Mobile (≤480px)
- Icon: 46x46px
- Text: 16px font size, 22px line height
- Gap: 6px between icon and text
## Animation Details
### Text Animation
1. **Initial State**: Primary text visible, secondary text positioned below (translateY(100%))
2. **Hover State**: Primary text slides up (translateY(-100%)) and fades out
3. **Simultaneous**: Secondary text slides to center (translateY(0)) and fades in
4. **Duration**: 300ms with ease-in-out timing
5. **Reverse**: Perfect reverse animation on mouse leave
### Icon Animation
1. **Initial State**: Primary arrow visible, secondary arrow positioned bottom-left
2. **Hover State**: Primary arrow slides up-right diagonally (translateX(24px), translateY(-24px)) and fades out
3. **Simultaneous**: Secondary arrow slides to center from bottom-left and fades in
4. **Duration**: 300ms with ease-in-out timing
5. **Background**: Consistent blue background throughout (no color change)
## Design System Integration
### Colors Used
- **Icon Background**: `#04045B` (Brand Primary Blue)
- **Icon/Arrow**: `#FFFFFF` (White)
- **Text**: `#FFFFFF` (White with shadow)
- **Text Shadow**: `0 1px 2px rgba(0, 0, 0, 0.4)`
### Typography
- **Font**: Inter (design system font)
- **Size**: 20px (desktop), 18px (tablet), 16px (mobile)
- **Weight**: 400 (Regular)
- **Line Height**: 28px (desktop), 24px (tablet), 22px (mobile)
### Accessibility
- **Focus Ring**: 3px rgba(248, 195, 1, 0.3) outline
- **ARIA Support**: Proper aria-label attributes
- **Keyboard Navigation**: Full keyboard accessibility
- **Screen Readers**: Semantic button element with descriptive labels
## Example Scenarios
### Hero Sections
```tsx
<PrimaryCTAButton
text="Transform Your Leadership"
onClick={() => navigate('/leadership-program')}
ariaLabel="Start your leadership transformation journey"
/>
```
### Service Pages
```tsx
<PrimaryCTAButton
text="Book a Consultation"
onClick={() => setShowBookingModal(true)}
/>
```
### Landing Pages
```tsx
<PrimaryCTAButton
text="Download Free Guide"
onClick={() => triggerDownload()}
className="mt-6"
/>
```
### Contact Forms
```tsx
<PrimaryCTAButton
text="Send Message"
onClick={handleSubmit}
ariaLabel="Send your message to our team"
/>
```
## Best Practices
### Text Content
- **Length**: Keep text concise (2-4 words ideal)
- **Action-Oriented**: Use verbs ("Get", "Start", "Learn", "Download")
- **Clear Value**: Communicate what happens when clicked
- **Consistent Tone**: Match your brand voice
### Implementation
- **Single CTA**: Use only one Primary CTA per section for maximum impact
- **Strategic Placement**: Position at natural conversion points
- **Sufficient Spacing**: Provide adequate whitespace around button
- **Context Relevant**: Ensure CTA matches the surrounding content
### Accessibility
- **Descriptive Labels**: Use clear, descriptive aria-labels when needed
- **Keyboard Focus**: Ensure button is reachable via keyboard navigation
- **Color Contrast**: White text on blue background meets WCAG AA standards
- **Touch Targets**: Minimum 44px height maintained on mobile
## CSS Classes Reference
### Component Classes
- `.primary-cta-button` - Main button container
- `.icon-layer` - Icon animation container
- `.text-layer` - Text animation container
- `.text-element` - Individual text instances
### State Classes
- `.group` - Enables group-hover functionality
- `.group-hover:*` - Triggered animation states
### Responsive Classes
- Media queries handle automatic responsive scaling
- No additional classes needed for responsive behavior
## Integration Notes
When implementing "Update as per Primary CTA Button":
1. **Replace existing button** with `<PrimaryCTAButton>`
2. **Update text prop** with new button content
3. **Adjust onClick handler** for new functionality
4. **Add custom aria-label** if button text isn't descriptive enough
5. **Apply additional classes** if positioning adjustments needed
The component will automatically handle:
- ✅ Width adjustment for new text
- ✅ Responsive scaling
- ✅ Animation consistency
- ✅ Design system compliance
- ✅ Accessibility requirements
This ensures perfect consistency across all Primary CTA buttons while maintaining the sophisticated slide animations that enhance user engagement.

View File

@@ -0,0 +1,337 @@
# Reusable Carousel Component Documentation
## Overview
The `ReusableCarousel` component provides a consistent, sophisticated carousel design that can be used across different sections of the website. It maintains the same design pattern as the "Our Services" section but allows for customizable content, styling, and functionality.
## Key Features
- **Consistent Design Language**: Maintains the same layout, spacing, and visual hierarchy
- **Flexible Content**: Accepts any data structure with customizable card rendering
- **Responsive Navigation**: Built-in carousel controls with proper accessibility
- **Customizable Styling**: Adjustable card dimensions, spacing, and layout
- **CTA Integration**: Built-in call-to-action button with custom configuration
- **Pre-built Variants**: Ready-to-use components for common use cases
## Basic Usage
### 1. Import the Component
```tsx
import { ReusableCarousel, CarouselItem, CarouselConfig } from '../ReusableCarousel';
```
### 2. Prepare Your Data
```tsx
const myItems: CarouselItem[] = [
{
title: "Item Title",
description: "Item description text",
icon: MyIcon, // Lucide React icon component
features: ["Feature 1", "Feature 2", "Feature 3"],
outcome: "Expected outcome description"
},
// ... more items
];
```
### 3. Configure the Carousel
```tsx
const config: CarouselConfig = {
eyebrowText: "SECTION CATEGORY",
title: "Section Title",
description: "Section description that appears below the title",
ctaText: "Call to Action Text",
ctaAction: () => navigateTo('/target-page'),
ctaAriaLabel: "Accessible description for the CTA button"
};
```
### 4. Render the Carousel
```tsx
<ReusableCarousel
items={myItems}
config={config}
/>
```
## Advanced Configuration
### Custom Card Rendering
For specialized card layouts, provide a custom renderer:
```tsx
const customRenderer = (item: CarouselItem, index: number) => (
<Card className="custom-card-styles">
<CardContent className="p-6">
{/* Your custom card content */}
<h3>{item.title}</h3>
<p>{item.description}</p>
{/* Add any custom fields from your CarouselItem */}
</CardContent>
</Card>
);
<ReusableCarousel
items={myItems}
config={config}
customCardRenderer={customRenderer}
/>
```
### Styling Customization
```tsx
<ReusableCarousel
items={myItems}
config={config}
className="my-custom-section" // Additional CSS classes
cardWidth="80%" // Adjust card width (default: "70%")
cardSpacing="mr-8" // Adjust spacing between cards (default: "mr-7")
featuresTitle="Custom Features Title:" // Override features section title
outcomesTitle="Custom Outcomes Title:" // Override outcomes section title
/>
```
## Pre-built Variants
For common use cases, use the pre-configured variants:
### Consulting Services Carousel
```tsx
import { ConsultingServicesCarousel } from '../ReusableCarousel';
<ConsultingServicesCarousel consultingServices={consultingData} />
```
### Leadership Programs Carousel
```tsx
import { LeadershipProgramsCarousel } from '../ReusableCarousel';
<LeadershipProgramsCarousel leadershipPrograms={programsData} />
```
### Expert Services Carousel
```tsx
import { ExpertServicesCarousel } from '../ReusableCarousel';
<ExpertServicesCarousel expertServices={servicesData} />
```
### Platform Features Carousel
```tsx
import { PlatformFeaturesCarousel } from '../ReusableCarousel';
<PlatformFeaturesCarousel platformFeatures={featuresData} />
```
## Data Structure Requirements
### CarouselItem Interface
```tsx
interface CarouselItem {
title: string; // Required: Item title
description: string; // Required: Item description
icon: React.ComponentType<any>; // Required: Lucide React icon
features?: string[]; // Optional: Array of feature bullets
outcome?: string; // Optional: Expected outcome text
[key: string]: any; // Additional custom properties
}
```
### CarouselConfig Interface
```tsx
interface CarouselConfig {
eyebrowText: string; // Branded tag text (e.g., "CONSULTING SERVICES")
title: string; // Main section title
description: string; // Section description
ctaText: string; // CTA button text
ctaAction: () => void; // CTA button click handler
ctaAriaLabel: string; // Accessibility label for CTA
}
```
## Real-World Examples
### Creating a Training Programs Carousel
```tsx
// 1. Define your data
const trainingPrograms: CarouselItem[] = [
{
title: "Executive Leadership Program",
description: "Comprehensive leadership development for senior executives",
icon: Crown,
features: [
"Strategic thinking development",
"Executive presence coaching",
"Board governance training",
"Crisis leadership skills"
],
outcome: "Enhanced executive effectiveness and organizational impact within 6 months"
},
// ... more programs
];
// 2. Configure the carousel
const trainingConfig: CarouselConfig = {
eyebrowText: "TRAINING PROGRAMS",
title: "Leadership Training Excellence",
description: "Comprehensive training programs designed to develop leadership capabilities at every organizational level.",
ctaText: "Explore Training Programs",
ctaAction: () => navigateTo('/training'),
ctaAriaLabel: "Explore our leadership training programs"
};
// 3. Use in your component
export function TrainingSection() {
return (
<section className="py-24" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<ReusableCarousel
items={trainingPrograms}
config={trainingConfig}
featuresTitle="Program Highlights:"
outcomesTitle="Program Results:"
/>
</div>
</section>
);
}
```
### Creating a Technology Solutions Carousel
```tsx
const techSolutions: CarouselItem[] = [
{
title: "Learning Management System",
description: "Advanced LMS platform for enterprise learning",
icon: Monitor,
features: [
"Cloud-based infrastructure",
"Mobile-responsive design",
"Advanced analytics",
"Integration capabilities"
],
outcome: "Improved learning engagement and completion rates",
// Custom properties for this use case
deployment: "Cloud or On-premise",
integration: "API-first architecture"
},
// ... more solutions
];
// Custom renderer for technology-specific cards
const techRenderer = (item: CarouselItem, index: number) => (
<Card className="border border-gray-200 h-full overflow-hidden">
<CardContent className="p-6">
<div className="flex items-center gap-4 mb-4">
<div className="w-14 h-14 rounded-xl bg-blue-100 flex items-center justify-center">
{React.createElement(item.icon, { className: "w-7 h-7 text-blue-600" })}
</div>
<h3 className="text-h4 text-black">{item.title}</h3>
</div>
<p className="text-body text-muted mb-6">{item.description}</p>
{/* Custom technology info */}
<div className="bg-gray-50 rounded-lg p-4 mb-6">
<div className="grid grid-cols-2 gap-4">
<div>
<span className="text-small font-medium text-black">Deployment:</span>
<span className="text-small text-muted ml-2">{item.deployment}</span>
</div>
<div>
<span className="text-small font-medium text-black">Integration:</span>
<span className="text-small text-muted ml-2">{item.integration}</span>
</div>
</div>
</div>
{/* Standard features section */}
{item.features && (
<div className="mb-6">
<h4 className="text-subhead text-black mb-4">Key Features:</h4>
<div className="space-y-2">
{item.features.map((feature: string, idx: number) => (
<div key={idx} className="flex items-center gap-2">
<CheckCircle className="w-4 h-4 text-blue-600" />
<span className="text-small text-muted">{feature}</span>
</div>
))}
</div>
</div>
)}
</CardContent>
</Card>
);
// Usage with custom renderer
<ReusableCarousel
items={techSolutions}
config={techConfig}
customCardRenderer={techRenderer}
cardWidth="75%"
cardSpacing="mr-6"
/>
```
## Design Guidelines
### When to Use
- **Multiple Related Items**: When you have 3+ related items to showcase
- **Detailed Information**: When each item needs substantial description and features
- **Call-to-Action Flow**: When the section should lead to a specific action
- **Consistent Branding**: When you want to maintain the established design language
### When NOT to Use
- **Simple Lists**: For basic lists without detailed descriptions
- **Static Content**: For content that doesn't benefit from carousel navigation
- **Single Items**: For individual content pieces
- **Grid Layouts**: When users need to see all items simultaneously
### Best Practices
1. **Content Length**: Keep titles concise (2-6 words), descriptions to 1-2 sentences
2. **Feature Lists**: Limit to 4-6 features per item for optimal readability
3. **Icons**: Use consistent icon style from Lucide React library
4. **Outcomes**: Make outcomes specific and measurable when possible
5. **CTA Alignment**: Ensure CTA leads to relevant, valuable content
## Accessibility Features
- **Keyboard Navigation**: Full keyboard support for carousel controls
- **ARIA Labels**: Proper accessibility labels for all interactive elements
- **Focus Management**: Clear focus indicators and logical tab order
- **Screen Readers**: Semantic HTML structure for assistive technologies
## Browser Support
- **Modern Browsers**: Full support in Chrome, Firefox, Safari, Edge
- **Responsive Design**: Optimized for all device sizes
- **Performance**: Optimized animations and minimal re-renders
- **Fallbacks**: Graceful degradation for older browsers
## Contributing
When extending the reusable carousel:
1. **Maintain Consistency**: Keep the established design patterns
2. **Test Accessibility**: Ensure all new features are accessible
3. **Document Changes**: Update this documentation for new features
4. **Performance**: Consider performance impact of customizations
This reusable carousel system allows you to quickly implement consistent, professional carousels across any section while maintaining design cohesion and user experience standards.

View File

@@ -0,0 +1,298 @@
import React, { useState } from 'react';
import { navigateTo } from './Router';
import { Card, CardContent } from './ui/card';
import { PrimaryCTAButton } from './PrimaryCTAButton';
import { CheckCircle, Target, ChevronLeft, ChevronRight } from 'lucide-react';
// Types for the reusable carousel
export interface CarouselItem {
title: string;
description: string;
icon: React.ComponentType<any>;
features?: string[];
outcome?: string;
// Additional flexible properties for different content types
[key: string]: any;
}
export interface CarouselConfig {
eyebrowText: string;
title: string;
description: string;
ctaText: string;
ctaAction: () => void;
ctaAriaLabel: string;
}
export interface ReusableCarouselProps {
items: CarouselItem[];
config: CarouselConfig;
className?: string;
cardWidth?: string; // Default: "70%"
cardSpacing?: string; // Default: "mr-7" (28px)
featuresTitle?: string; // Default: "Key Features & Benefits:"
outcomesTitle?: string; // Default: "Expected Outcomes:"
customCardRenderer?: (item: CarouselItem, index: number) => React.ReactNode;
}
export function ReusableCarousel({
items,
config,
className = "",
cardWidth = "70%",
cardSpacing = "mr-7",
featuresTitle = "Key Features & Benefits:",
outcomesTitle = "Expected Outcomes:",
customCardRenderer
}: ReusableCarouselProps) {
const [currentIndex, setCurrentIndex] = useState(0);
const nextSlide = () => {
setCurrentIndex((prev) => (prev + 1) % items.length);
};
const prevSlide = () => {
setCurrentIndex((prev) => (prev - 1 + items.length) % items.length);
};
const renderDefaultCard = (item: CarouselItem, index: number) => (
<Card
className="border border-gray-200 h-full overflow-hidden"
style={{ backgroundColor: '#FFFFFF' }}
>
<CardContent className="p-6">
{/* Service Icon & Header - Inline Layout */}
<div className="flex items-center gap-4 mb-4">
<div
className="w-14 h-14 rounded-xl flex items-center justify-center flex-shrink-0"
style={{ backgroundColor: 'rgba(4, 4, 91, 0.1)' }}
>
{React.createElement(item.icon, {
className: "w-7 h-7 text-primary"
})}
</div>
<h3 className="text-h4 text-black leading-tight">
{item.title}
</h3>
</div>
{/* Divider Line */}
<div
className="w-full h-px mb-4"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.1)' }}
></div>
{/* Description */}
<p className="text-body text-muted leading-relaxed mb-6">
{item.description}
</p>
{/* Key Features */}
{item.features && item.features.length > 0 && (
<div className="mb-6">
<h4 className="text-subhead text-black mb-4 font-medium">
{featuresTitle}
</h4>
<div className="grid md:grid-cols-2 gap-3">
{item.features.map((feature: string, featureIndex: number) => (
<div key={featureIndex} className="flex items-start gap-2">
<CheckCircle className="w-4 h-4 flex-shrink-0 mt-0.5 text-primary" />
<span className="text-small text-muted leading-relaxed">
{feature}
</span>
</div>
))}
</div>
</div>
)}
{/* Expected Outcomes */}
{item.outcome && (
<div
className="rounded-lg p-4"
style={{ backgroundColor: 'rgba(247, 247, 253, 0.5)' }}
>
<h4 className="text-subhead text-black mb-3 font-medium">
{outcomesTitle}
</h4>
<div className="flex items-start gap-3">
<Target className="w-4 h-4 flex-shrink-0 mt-0.5 text-primary" />
<span className="text-small text-muted leading-relaxed">
{item.outcome}
</span>
</div>
</div>
)}
</CardContent>
</Card>
);
return (
<div className={`max-w-7xl mx-auto mb-16 ${className}`}>
{/* Header Section */}
<div className="mb-12 relative">
{/* Left Side - Eyebrow Text, Header & Subtext */}
<div className="flex-1 max-w-2xl">
<div className="branded-tag-system mb-6">
<div className="dot"></div>
<span className="text">{config.eyebrowText}</span>
</div>
<h2 className="text-h2 mb-4 leading-tight">{config.title}</h2>
<p className="text-body-lg text-muted leading-relaxed">
{config.description}
</p>
</div>
{/* Navigation Controls - Bottom Right of Header */}
<div className="absolute bottom-0 right-0 flex items-center gap-4">
<span className="text-body text-muted font-medium">
{String(currentIndex + 1).padStart(2, '0')} / {String(items.length).padStart(2, '0')}
</span>
<div className="flex gap-2">
<button
onClick={prevSlide}
className="w-12 h-12 rounded-lg border-2 border-gray-200 flex items-center justify-center hover:border-primary hover:bg-primary hover:text-white transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed"
disabled={currentIndex === 0}
aria-label="Previous item"
>
<ChevronLeft className="w-5 h-5" />
</button>
<button
onClick={nextSlide}
className="w-12 h-12 rounded-lg border-2 border-gray-200 flex items-center justify-center hover:border-primary hover:bg-primary hover:text-white transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed"
disabled={currentIndex === items.length - 1}
aria-label="Next item"
>
<ChevronRight className="w-5 h-5" />
</button>
</div>
</div>
</div>
{/* Main Carousel Content */}
<div className="relative">
{/* Carousel Container */}
<div className="overflow-hidden">
<div
className="flex transition-transform duration-700 ease-in-out"
style={{ transform: `translateX(-${currentIndex * 75}%)` }}
>
{items.map((item, index) => (
<div
key={`${item.title}-${index}`}
className={`flex-shrink-0 w-[${cardWidth}] ${cardSpacing}`}
>
{customCardRenderer ? customCardRenderer(item, index) : renderDefaultCard(item, index)}
</div>
))}
</div>
</div>
</div>
{/* CTA Button - Right Bottom with 40px spacing */}
<div className="flex justify-end" style={{ marginTop: '40px' }}>
<PrimaryCTAButton
text={config.ctaText}
onClick={config.ctaAction}
ariaLabel={config.ctaAriaLabel}
/>
</div>
</div>
);
}
// Pre-configured carousel variants for common use cases
export function ConsultingServicesCarousel({
consultingServices
}: {
consultingServices: CarouselItem[]
}) {
const config: CarouselConfig = {
eyebrowText: "CONSULTING & ADVISORY SERVICES",
title: "Our Services",
description: "Comprehensive consulting solutions designed to drive organizational transformation and leadership excellence across all levels of your business.",
ctaText: "Explore Consulting Services",
ctaAction: () => navigateTo('/services/consulting'),
ctaAriaLabel: "Explore our consulting services"
};
return (
<ReusableCarousel
items={consultingServices}
config={config}
/>
);
}
export function LeadershipProgramsCarousel({
leadershipPrograms
}: {
leadershipPrograms: CarouselItem[]
}) {
const config: CarouselConfig = {
eyebrowText: "LEADERSHIP DEVELOPMENT PROGRAMS",
title: "Our Programs",
description: "Comprehensive leadership development programs designed to build capabilities and drive organizational transformation with measurable impact.",
ctaText: "Explore Leadership Programs",
ctaAction: () => navigateTo('/services/leadership-development'),
ctaAriaLabel: "Explore our leadership development programs"
};
return (
<ReusableCarousel
items={leadershipPrograms}
config={config}
featuresTitle="Program Features:"
outcomesTitle="Program Outcomes:"
/>
);
}
export function ExpertServicesCarousel({
expertServices
}: {
expertServices: CarouselItem[]
}) {
const config: CarouselConfig = {
eyebrowText: "EXPERT CONSULTATION & SERVICES",
title: "Expert Services",
description: "Personalized guidance from industry thought leaders and senior practitioners who bring decades of real-world experience.",
ctaText: "Connect with Experts",
ctaAction: () => navigateTo('/services/executive-coaching'),
ctaAriaLabel: "Connect with our expert consultants"
};
return (
<ReusableCarousel
items={expertServices}
config={config}
featuresTitle="Service Features:"
outcomesTitle="Expected Results:"
/>
);
}
export function PlatformFeaturesCarousel({
platformFeatures
}: {
platformFeatures: CarouselItem[]
}) {
const config: CarouselConfig = {
eyebrowText: "DIGITAL PLATFORM FEATURES",
title: "Platform Capabilities",
description: "State-of-the-art digital learning platform with cutting-edge technology and interactive experiences for modern learning.",
ctaText: "Explore Platform",
ctaAction: () => navigateTo('/learning-online'),
ctaAriaLabel: "Explore our online learning platform"
};
return (
<ReusableCarousel
items={platformFeatures}
config={config}
featuresTitle="Platform Features:"
outcomesTitle="Learning Benefits:"
/>
);
}

90
src/components/Router.tsx Normal file
View File

@@ -0,0 +1,90 @@
// Enhanced router for reliable navigation with proper browser integration
let currentPath = window.location.pathname + window.location.search || '/';
const listeners: (() => void)[] = [];
export function navigateTo(path: string) {
try {
console.log(`Navigating to: ${path}`);
// Update current path
currentPath = path;
// Update browser URL and history
if (window.history && window.history.pushState) {
window.history.pushState({ path }, '', path);
} else {
// Fallback for older browsers
window.location.href = path;
return;
}
// Force a state change event
window.dispatchEvent(new PopStateEvent('popstate', { state: { path } }));
// Notify all listeners of the route change
listeners.forEach(listener => {
try {
listener();
} catch (error) {
console.error('Error in route listener:', error);
}
});
} catch (error) {
console.error('Navigation error:', error);
// Ultimate fallback
window.location.href = path;
}
}
export function getCurrentPath() {
try {
// Always get the current path from the browser URL
const path = window.location.pathname + window.location.search;
currentPath = path;
return path;
} catch (error) {
console.error('Error getting current path:', error);
return currentPath;
}
}
export function addRouteListener(listener: () => void) {
listeners.push(listener);
// Listen for browser back/forward button events
const handlePopState = (event: PopStateEvent) => {
try {
currentPath = window.location.pathname + window.location.search;
listener();
} catch (error) {
console.error('Error in popstate handler:', error);
}
};
// Listen for our custom navigation events
const handleNavigation = () => {
try {
listener();
} catch (error) {
console.error('Error in navigation handler:', error);
}
};
window.addEventListener('popstate', handlePopState);
window.addEventListener('navigation', handleNavigation);
return () => {
const index = listeners.indexOf(listener);
if (index > -1) {
listeners.splice(index, 1);
}
window.removeEventListener('popstate', handlePopState);
window.removeEventListener('navigation', handleNavigation);
};
}
// Helper function to trigger navigation events
export function triggerNavigationUpdate() {
window.dispatchEvent(new CustomEvent('navigation'));
}

View File

@@ -0,0 +1,586 @@
import React, { useState } from 'react';
import { Button } from './ui/button';
import { Input } from './ui/input';
import { Label } from './ui/label';
import { Card, CardContent } from './ui/card';
import { Checkbox } from './ui/checkbox';
import {
BookOpen,
Users,
Target,
Award,
ArrowRight,
Eye,
EyeOff,
User
} from 'lucide-react';
import { navigateTo } from './Router';
export function SelfLearnerSignIn() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [showPassword, setShowPassword] = useState(false);
const [rememberMe, setRememberMe] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const handleSignIn = async (e: React.FormEvent) => {
e.preventDefault();
setIsLoading(true);
// Simulate authentication
setTimeout(() => {
setIsLoading(false);
// Navigate to dashboard or success page
navigateTo('/dashboard');
}, 1500);
};
const transformationFeatures = [
{
icon: BookOpen,
title: 'World-Class Content',
description: 'Access premium leadership courses from industry experts'
},
{
icon: Users,
title: 'Global Community',
description: 'Join 25,000+ leaders from top organizations worldwide'
},
{
icon: Award,
title: 'Recognized Credentials',
description: 'Earn certificates valued by Fortune 500 companies'
},
{
icon: Target,
title: 'Personalized Path',
description: 'Get customized learning recommendations based on your goals'
}
];
const learningFeatures = [
{
icon: BookOpen,
title: 'Expert-Led Programs',
description: 'Learn from industry leaders and world-class faculty'
},
{
icon: Users,
title: 'Peer Learning Network',
description: 'Connect with like-minded professionals and expand your network'
},
{
icon: Target,
title: 'Personalized Growth',
description: 'Tailored learning paths to accelerate your leadership journey'
},
{
icon: Award,
title: 'Recognized Certification',
description: 'Industry-recognized credentials to advance your career'
}
];
return (
<div style={{ backgroundColor: '#FFFFFF' }}>
{/* Main Content */}
<div className="section-margin-x py-16">
<div className="max-w-6xl mx-auto">
{/* Header Section */}
<div className="text-center mb-12">
<div className="mb-6">
<span
className="inline-flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium"
style={{
backgroundColor: 'rgba(248, 195, 1, 0.15)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
<User className="w-4 h-4" />
Individual Learning
</span>
</div>
<h1
className="mb-6"
style={{
fontSize: 'var(--font-h2)',
fontWeight: 'var(--font-weight-h2)',
lineHeight: 'var(--line-height-h2)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Welcome Back to Your Leadership Journey
</h1>
<p
className="mb-12 max-w-2xl mx-auto"
style={{
fontSize: 'var(--font-body-lg)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-body-lg)'
}}
>
Continue your transformation with KLC's world-class leadership development
programs. Access your personalized learning dashboard and connect with a global
community of leaders.
</p>
</div>
{/* Two Column Layout */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-start">
{/* Left Column - Content */}
<div>
{/* Leadership Transformation Section */}
<div className="mb-12">
<div className="mb-6">
<span
className="inline-flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium"
style={{
backgroundColor: 'rgba(248, 195, 1, 0.15)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
⭐ Join KLC Community
</span>
</div>
<h2
className="mb-4"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Start Your Leadership Transformation
</h2>
<p
className="mb-8"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-body)'
}}
>
Join thousands of professionals who have accelerated their careers through KLC's
proven leadership development programs. Your journey to becoming an exceptional leader starts here.
</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{transformationFeatures.map((feature, index) => (
<div key={index} className="flex items-start gap-3">
<div
className="w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0"
style={{ backgroundColor: 'var(--color-primary)' }}
>
<feature.icon className="w-4 h-4 text-white" />
</div>
<div className="flex-1">
<h3
className="font-medium mb-1"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{feature.title}
</h3>
<p
style={{
fontSize: '0.75rem',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: '1.3'
}}
>
{feature.description}
</p>
</div>
</div>
))}
</div>
</div>
{/* Your Learning Experience */}
<div>
<h2
className="mb-8"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Your Learning Experience
</h2>
<div className="space-y-6">
{learningFeatures.map((feature, index) => (
<div key={index} className="flex items-start gap-4">
<div
className="w-12 h-12 rounded-lg flex items-center justify-center flex-shrink-0"
style={{ backgroundColor: 'var(--color-primary)' }}
>
<feature.icon className="w-6 h-6 text-white" />
</div>
<div className="flex-1">
<h3
className="font-medium mb-2"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{feature.title}
</h3>
<p
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-small)'
}}
>
{feature.description}
</p>
</div>
</div>
))}
</div>
{/* Existing Account Note */}
<div
className="mt-8 p-4 rounded-lg border"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.02)' }}
>
<p
className="mb-2"
style={{
fontSize: 'var(--font-small)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Already have an account?
</p>
<div className="space-y-2">
<button
onClick={() => navigateTo('/self-learner-signin')}
className="block text-blue-600 hover:text-blue-700 transition-colors"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Sign in to your account
</button>
<button
onClick={() => navigateTo('/corporate-login')}
className="block text-blue-600 hover:text-blue-700 transition-colors"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Corporate sign in
</button>
</div>
</div>
</div>
</div>
{/* Right Column - Sign In Form */}
<div>
<Card className="shadow-lg border-0">
<CardContent className="p-8">
{/* Form Header */}
<div className="text-center mb-8">
<h2
className="mb-2"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Welcome Back
</h2>
<p
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Sign in to your KLC account
</p>
</div>
{/* Sign In Form */}
<form onSubmit={handleSignIn} className="space-y-6">
{/* Email Field */}
<div>
<Label
htmlFor="email"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Email Address *
</Label>
<Input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="you@example.com"
required
className="mt-2 h-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)'
}}
/>
</div>
{/* Password Field */}
<div>
<Label
htmlFor="password"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Password *
</Label>
<div className="relative mt-2">
<Input
id="password"
type={showPassword ? 'text' : 'password'}
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Enter your password"
required
className="h-12 pr-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)'
}}
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500 hover:text-gray-700"
>
{showPassword ? <EyeOff className="w-5 h-5" /> : <Eye className="w-5 h-5" />}
</button>
</div>
</div>
{/* Remember Me & Forgot Password */}
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<Checkbox
id="remember"
checked={rememberMe}
onCheckedChange={setRememberMe}
/>
<Label
htmlFor="remember"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Remember me
</Label>
</div>
<button
type="button"
onClick={() => navigateTo('/forgot-password')}
className="text-blue-600 hover:text-blue-700 transition-colors"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Forgot password?
</button>
</div>
{/* Sign In Button */}
<Button
type="submit"
disabled={isLoading}
className="w-full h-14 text-white font-medium flex items-center justify-center gap-2"
style={{
backgroundColor: 'var(--color-primary)',
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
borderRadius: '10px'
}}
>
{isLoading ? (
<div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
) : (
<>
Sign In
<ArrowRight className="w-5 h-5" />
</>
)}
</Button>
</form>
{/* Demo Credentials */}
<div
className="mt-8 p-4 rounded-lg border"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.02)' }}
>
<h4
className="mb-2 flex items-center gap-2"
style={{
fontSize: 'var(--font-small)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
<div className="w-4 h-4 rounded-full bg-gray-300 flex items-center justify-center">
<span className="text-xs text-gray-600">i</span>
</div>
Demo credentials:
</h4>
<div
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-small)'
}}
>
Email: demo@klc.edu.in | Password: demo123
</div>
</div>
{/* Sign Up Links */}
<div className="text-center mt-8 space-y-3">
<div>
<span
className="text-gray-600"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Don't have an account?{' '}
</span>
<button
onClick={() => navigateTo('/self-learner-signup')}
className="text-blue-600 hover:text-blue-700 transition-colors font-medium"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Sign up here
</button>
</div>
<div>
<span
className="text-gray-600"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Looking for corporate access?{' '}
</span>
<button
onClick={() => navigateTo('/corporate-login')}
className="text-blue-600 hover:text-blue-700 transition-colors font-medium"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Corporate Sign In
</button>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
</div>
{/* Need Help Section - Separate Section Below */}
<div
className="section-margin-x py-12"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.02)' }}
>
<div className="max-w-4xl mx-auto text-center">
<h3
className="mb-4"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Need Help Getting Started?
</h3>
<p
className="mb-6"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-body)'
}}
>
Our learning advisors are here to help you choose the right programs and get the most out of your leadership development experience.
</p>
<Button
variant="outline"
className="border-2 border-blue-600 text-blue-600 hover:bg-blue-600 hover:text-white"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500',
padding: '0.75rem 2rem',
borderRadius: '10px'
}}
>
Speak with Learning Advisor
</Button>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,504 @@
import React, { useState } from 'react';
import { Button } from './ui/button';
import { Input } from './ui/input';
import { Label } from './ui/label';
import { Card, CardContent } from './ui/card';
import { Checkbox } from './ui/checkbox';
import {
BookOpen,
Users,
Target,
Award,
ArrowRight,
Eye,
EyeOff,
User,
Mail,
Lock,
Phone
} from 'lucide-react';
import { navigateTo } from './Router';
export function SelfLearnerSignUp() {
const [formData, setFormData] = useState({
fullName: '',
email: '',
password: '',
phoneNumber: ''
});
const [showPassword, setShowPassword] = useState(false);
const [agreeToTerms, setAgreeToTerms] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const handleInputChange = (field: string, value: string) => {
setFormData(prev => ({ ...prev, [field]: value }));
};
const handleSignUp = async (e: React.FormEvent) => {
e.preventDefault();
if (!agreeToTerms) {
alert('Please agree to the Terms of Service and Privacy Policy');
return;
}
setIsLoading(true);
// Simulate registration
setTimeout(() => {
setIsLoading(false);
// Navigate to dashboard or success page
navigateTo('/dashboard');
}, 2000);
};
const transformationFeatures = [
{
icon: BookOpen,
title: 'World-Class Content',
description: 'Access premium leadership courses from industry experts'
},
{
icon: Users,
title: 'Global Community',
description: 'Join 25,000+ leaders from top organizations worldwide'
},
{
icon: Award,
title: 'Recognized Credentials',
description: 'Earn certificates valued by Fortune 500 companies'
},
{
icon: Target,
title: 'Personalized Path',
description: 'Get customized learning recommendations based on your goals'
}
];
const learningFeatures = [
{
icon: BookOpen,
title: 'World-Class Content',
description: 'Access cutting-edge leadership programs from industry experts and renowned faculty'
},
{
icon: Users,
title: 'Global Network',
description: 'Connect with ambitious leaders worldwide and build lasting professional relationships'
},
{
icon: Target,
title: 'Personalized Learning',
description: 'Get customized learning paths based on your goals and leadership style'
},
{
icon: Award,
title: 'Recognized Credentials',
description: 'Earn certificates and credentials that advance your career and open new opportunities'
}
];
return (
<div style={{ backgroundColor: '#FFFFFF' }}>
{/* Main Content */}
<div className="section-margin-x py-16">
<div className="max-w-6xl mx-auto">
{/* Two Column Layout */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-start">
{/* Left Column - Content */}
<div>
{/* Leadership Transformation Section */}
<div className="mb-12">
<div className="mb-6">
<span
className="inline-flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium"
style={{
backgroundColor: 'rgba(248, 195, 1, 0.15)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Join KLC Community
</span>
</div>
<h2
className="mb-4"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Start Your Leadership Transformation
</h2>
<p
className="mb-8"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-body)'
}}
>
Join thousands of professionals who have accelerated their careers through KLC's
proven leadership development programs. Your journey to becoming an exceptional leader starts here.
</p>
</div>
{/* Your Learning Experience Awaits */}
<div>
<h2
className="mb-8"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Your Learning Experience Awaits
</h2>
<div className="space-y-6">
{learningFeatures.map((feature, index) => (
<div key={index} className="flex items-start gap-4">
<div
className="w-12 h-12 rounded-lg flex items-center justify-center flex-shrink-0"
style={{ backgroundColor: 'var(--color-primary)' }}
>
<feature.icon className="w-6 h-6 text-white" />
</div>
<div className="flex-1">
<h3
className="font-medium mb-2"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{feature.title}
</h3>
<p
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-small)'
}}
>
{feature.description}
</p>
</div>
</div>
))}
</div>
</div>
</div>
{/* Right Column - Sign Up Form */}
<div>
<Card className="shadow-lg border-0">
<CardContent className="p-8">
{/* Form Header */}
<div className="text-center mb-8">
<h2
className="mb-2"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Create Your Account
</h2>
<p
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
Join KLC and start your leadership journey
</p>
</div>
{/* Sign Up Form */}
<form onSubmit={handleSignUp} className="space-y-6">
{/* Full Name */}
<div>
<Label
htmlFor="fullName"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Full Name *
</Label>
<div className="relative mt-2">
<div className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500">
<User className="w-5 h-5" />
</div>
<Input
id="fullName"
type="text"
value={formData.fullName}
onChange={(e) => handleInputChange('fullName', e.target.value)}
placeholder="Your full name"
required
className="h-12 pl-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
backgroundColor: '#F3F3F5'
}}
/>
</div>
</div>
{/* Email Address */}
<div>
<Label
htmlFor="email"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Email Address *
</Label>
<div className="relative mt-2">
<div className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500">
<Mail className="w-5 h-5" />
</div>
<Input
id="email"
type="email"
value={formData.email}
onChange={(e) => handleInputChange('email', e.target.value)}
placeholder="you@example.com"
required
className="h-12 pl-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
backgroundColor: '#F3F3F5'
}}
/>
</div>
</div>
{/* Password */}
<div>
<Label
htmlFor="password"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Password *
</Label>
<div className="relative mt-2">
<div className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500">
<Lock className="w-5 h-5" />
</div>
<Input
id="password"
type={showPassword ? 'text' : 'password'}
value={formData.password}
onChange={(e) => handleInputChange('password', e.target.value)}
placeholder="Create a strong password"
required
className="h-12 pl-12 pr-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
backgroundColor: '#F3F3F5'
}}
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500 hover:text-gray-700"
>
{showPassword ? <EyeOff className="w-5 h-5" /> : <Eye className="w-5 h-5" />}
</button>
</div>
</div>
{/* Phone Number (Optional) */}
<div>
<Label
htmlFor="phoneNumber"
style={{
fontSize: 'var(--font-body)',
fontWeight: '500',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Phone Number (Optional)
</Label>
<div className="relative mt-2">
<div className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500">
<Phone className="w-5 h-5" />
</div>
<Input
id="phoneNumber"
type="tel"
value={formData.phoneNumber}
onChange={(e) => handleInputChange('phoneNumber', e.target.value)}
placeholder="+1 234 567 8900"
className="h-12 pl-12"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
backgroundColor: '#F3F3F5'
}}
/>
</div>
</div>
{/* Terms and Conditions */}
<div className="flex items-start space-x-2">
<Checkbox
id="agreeToTerms"
checked={agreeToTerms}
onCheckedChange={setAgreeToTerms}
className="mt-1"
/>
<Label
htmlFor="agreeToTerms"
className="text-sm leading-relaxed"
style={{
fontSize: 'var(--font-small)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-small)'
}}
>
I agree to the{' '}
<span className="text-blue-600 hover:text-blue-700 cursor-pointer">
Terms of Service
</span>{' '}
and{' '}
<span className="text-blue-600 hover:text-blue-700 cursor-pointer">
Privacy Policy
</span>
</Label>
</div>
{/* Create Account Button */}
<Button
type="submit"
disabled={isLoading}
className="w-full h-14 text-white font-medium flex items-center justify-center gap-2"
style={{
backgroundColor: 'var(--color-primary)',
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
borderRadius: '10px'
}}
>
{isLoading ? (
<div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
) : (
<>
Create Account
<ArrowRight className="w-5 h-5" />
</>
)}
</Button>
</form>
{/* Sign In Link */}
<div className="text-center mt-6">
<span
className="text-gray-600"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Already have an account?{' '}
</span>
<button
onClick={() => navigateTo('/self-learner-signin')}
className="text-blue-600 hover:text-blue-700 transition-colors font-medium"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Sign in here
</button>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
</div>
{/* Need Help Section - Separate Section Below */}
<div
className="section-margin-x py-12"
style={{ backgroundColor: 'rgba(0, 0, 0, 0.02)' }}
>
<div className="max-w-4xl mx-auto text-center">
<h3
className="mb-4"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Questions About Your Learning Journey?
</h3>
<p
className="mb-6"
style={{
fontSize: 'var(--font-body)',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-body)'
}}
>
Our learning advisors are here to help you choose the right programs and get the most out of your leadership development experience.
</p>
<Button
variant="outline"
className="border-2 border-blue-600 text-blue-600 hover:bg-blue-600 hover:text-white"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
fontWeight: '500',
padding: '0.75rem 2rem',
borderRadius: '10px'
}}
>
Speak with Learning Advisor
</Button>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,47 @@
import { motion } from "motion/react";
import { ArrowRight } from "lucide-react";
export function ServicesCTASection() {
return (
<section className="py-16 px-[var(--section-margin-x)] max-lg:px-8 max-md:py-12">
<div className="max-w-4xl mx-auto text-center">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7 }}
viewport={{ once: true }}
className="space-y-8"
>
{/* CTA Button */}
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.3 }}
viewport={{ once: true }}
>
<button className="services-cta-button">
<div className="services-cta-icon">
<ArrowRight size={20} />
</div>
<span className="services-cta-text">
Get Started Today
</span>
</button>
</motion.div>
{/* Supporting Text */}
<motion.p
className="text-sm max-md:text-xs"
style={{ color: 'var(--color-brand-gray-muted)' }}
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
transition={{ duration: 0.6, delay: 0.5 }}
viewport={{ once: true }}
>
Free consultation No commitment required Expert guidance
</motion.p>
</motion.div>
</div>
</section>
);
}

View File

@@ -0,0 +1,237 @@
import { useState, useEffect, useRef } from "react";
import { motion } from "motion/react";
import {
Users,
Settings,
User,
Globe,
MessageSquare,
GraduationCap,
ArrowRight
} from "lucide-react";
import { BrandedTag } from "./about/BrandedTag";
import { PrimaryCTAButton } from "./PrimaryCTAButton";
import { navigateTo } from "./Router";
// Services data
const recognitionItems = [
{
id: 1,
title: "Leadership Development",
description: "Comprehensive programs designed to cultivate strategic thinking and emotional intelligence. Develop capabilities that drive organizational success through authentic leadership practices.",
icon: <Users size={28} />,
badge: "CORE PROGRAM",
badgeColor: "#F8C301"
},
{
id: 2,
title: "Management Development",
description: "Essential skills training for first-time and experienced managers seeking growth. Focus on communication, delegation, and performance management excellence.",
icon: <Settings size={28} />,
badge: "POPULAR",
badgeColor: "#04045B"
},
{
id: 3,
title: "Culture Competence",
description: "Build cultural awareness and inclusive practices that enhance team collaboration. Navigate cultural differences with confidence and create inclusive environments.",
icon: <Globe size={28} />,
badge: "GLOBAL FOCUS",
badgeColor: "#F8C301"
},
{
id: 4,
title: "Executive Coaching",
description: "One-on-one personalized development for senior leaders and high-potential talent. Strategic guidance for complex leadership challenges and career advancement.",
icon: <User size={28} />,
badge: "PREMIUM",
badgeColor: "#04045B"
},
{
id: 5,
title: "Communication Excellence",
description: "Master the art of influential communication across all organizational levels. Develop presentation skills, difficult conversation navigation, and stakeholder engagement.",
icon: <MessageSquare size={28} />,
badge: "ESSENTIAL",
badgeColor: "#F8C301"
},
{
id: 6,
title: "Change Leadership",
description: "Guide organizations through transformation with confidence and clarity. Learn frameworks for managing resistance, building momentum, and sustaining change initiatives.",
icon: <GraduationCap size={28} />,
badge: "STRATEGIC",
badgeColor: "#04045B"
}
];
export function ServicesSection() {
const [isVisible, setIsVisible] = useState(false);
const cardRefs = useRef<(HTMLDivElement | null)[]>([]);
const sectionRef = useRef<HTMLDivElement>(null);
// Add card refs helper
const addCardRef = (el: HTMLDivElement | null, index: number) => {
cardRefs.current[index] = el;
};
// Intersection observer for animations
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setIsVisible(true);
}
});
},
{ threshold: 0.2 }
);
if (sectionRef.current) {
observer.observe(sectionRef.current);
}
return () => observer.disconnect();
}, []);
// Keyboard navigation
const handleKeyDown = (e: React.KeyboardEvent, index: number) => {
if (e.key === 'ArrowDown' && index < cardRefs.current.length - 1) {
cardRefs.current[index + 1]?.focus();
e.preventDefault();
} else if (e.key === 'ArrowUp' && index > 0) {
cardRefs.current[index - 1]?.focus();
e.preventDefault();
}
};
return (
<section
ref={sectionRef}
className="py-16 lg:py-20"
style={{
backgroundColor: '#F7F7FD',
fontFamily: 'var(--font-family-brand)'
}}
aria-labelledby="recognition-section-heading"
>
<div className="section-margin-x">
<div className="max-w-7xl mx-auto">
<div className="grid grid-cols-12 gap-12 min-h-screen">
{/* Left Side - Sticky Content */}
<div className="col-span-5 sticky top-24 self-start">
<div className="recognition-header pr-8">
<BrandedTag
text="Leadership Development Programs"
/>
<h2
id="recognition-section-heading"
className="text-h2 mb-6"
>
Services That Shape Stronger Leaders
</h2>
<p className="text-body-lg text-muted">
Our comprehensive leadership development programs are designed to build future-ready leaders who thrive in complexity and drive measurable organizational impact.
</p>
</div>
</div>
{/* Right Side - Scrolling Cards */}
<div className="col-span-7">
<div
className="recognition-cards space-y-6"
role="list"
aria-label="Leadership development services"
>
{recognitionItems.map((item, index) => (
<div
key={item.id}
ref={(el) => addCardRef(el, index)}
className={`recognition-card group scroll-animate-stagger focus-ring ${isVisible ? 'animate-in' : ''}`}
role="listitem"
aria-labelledby={`recognition-title-${item.id}`}
aria-describedby={`recognition-desc-${item.id}`}
tabIndex={0}
onKeyDown={(e) => handleKeyDown(e, index)}
style={{
transitionDelay: `${(index + 1) * 150}ms`,
opacity: isVisible ? 1 : 0
}}
>
<div
className="p-8 transition-all duration-300 hover:shadow-xl hover:-translate-y-1 border bg-white"
style={{
borderColor: 'var(--color-border)',
borderRadius: '12px',
fontFamily: 'var(--font-family-brand)'
}}
>
<div className="flex items-start justify-between mb-6">
<div
className="w-14 h-14 flex items-center justify-center transition-transform duration-300 group-hover:scale-110"
style={{
backgroundColor: 'var(--color-brand-primary)',
borderRadius: '12px',
color: 'white'
}}
>
{item.icon}
</div>
{item.badge && (
<div
className="px-3 py-1 text-xs font-bold uppercase tracking-wider"
style={{
backgroundColor: item.badgeColor,
color: item.badgeColor === '#F8C301' ? 'var(--color-brand-black)' : 'white',
borderRadius: '20px',
fontFamily: 'var(--font-family-brand)'
}}
>
{item.badge}
</div>
)}
</div>
<div className="recognition-card-content">
<h3
id={`recognition-title-${item.id}`}
className="text-h4 mb-4"
>
{item.title}
</h3>
<p
id={`recognition-desc-${item.id}`}
className="text-small text-muted leading-relaxed"
>
{item.description}
</p>
</div>
</div>
</div>
))}
</div>
</div>
</div>
{/* CTA Button - Updated to redirect to leadership journey */}
<div className="flex justify-center mt-16">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.6 }}
viewport={{ once: true }}
>
<PrimaryCTAButton
text="Get Started Today"
onClick={() => navigateTo('/leadership-journey')}
ariaLabel="Get started with leadership development programs"
className="get-started-cta-override"
/>
</motion.div>
</div>
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,374 @@
import React, { useEffect, useRef, useState } from "react";
/**
* StackedOfferSection Component
*
* @param {Object} props - Component props
* @param {Array} props.cards - Array of card objects with the following structure:
* - id: number
* - title: string
* - subtitle?: string
* - description?: string
* - badge?: string
* - color: string (no longer used - all cards are white)
* - features?: string[]
* - stats?: Array<{label: string, value: string}>
* - icon?: React.ComponentType
*/
export type StackedOfferCard = {
id: number;
title: string;
subtitle?: string;
description?: string;
badge?: string;
features?: string[];
stats?: Array<{ label: string; value: string }>;
icon?: React.ComponentType<any>;
};
const demoCards: StackedOfferCard[] = [
{
id: 1,
title: "Leadership Foundations",
subtitle: "Orientation • Strategy",
description:
"Build strong leadership behaviors with research-backed frameworks and deliberate practice.",
badge: "Featured",
color: "from-indigo-500 to-blue-600", // No longer used
features: ["Decision Making", "Self-awareness", "Feedback Loops", "Coaching"],
stats: [
{ label: "Modules", value: "08" },
{ label: "Hours", value: "12" },
{ label: "Format", value: "Self-paced" }
]
},
{
id: 2,
title: "Executive Presence",
subtitle: "Influence • Communication",
description:
"Elevate your impact with persuasive narratives, clarity, and confident delivery.",
badge: "New",
color: "from-emerald-500 to-teal-600", // No longer used
features: ["Narratives", "Storylining", "Speaking", "Signals"],
stats: [
{ label: "Modules", value: "06" },
{ label: "Hours", value: "10" },
{ label: "Format", value: "Cohort" }
]
},
{
id: 3,
title: "Strategic Execution",
subtitle: "Operating Rhythm",
description:
"Translate strategy into outcomes with ruthless prioritization and cadence.",
color: "from-rose-500 to-orange-500", // No longer used
features: ["OKRs", "Cadence", "Reviews", "Debriefs"],
stats: [
{ label: "Modules", value: "07" },
{ label: "Hours", value: "11" },
{ label: "Format", value: "Hybrid" }
]
},
{
id: 4,
title: "Change Leadership",
subtitle: "Adoption • Momentum",
description:
"Lead transformation with systems thinking and stakeholder alignment.",
color: "from-purple-500 to-fuchsia-600", // No longer used
features: ["Systems", "Stakeholders", "Momentum", "Sustain"],
stats: [
{ label: "Modules", value: "05" },
{ label: "Hours", value: "09" },
{ label: "Format", value: "Self-paced" }
]
}
];
type StackedOfferSectionProps = {
cards?: StackedOfferCard[];
headingTitle?: string;
headingEmphasis?: string;
headingDescription?: string;
};
export default function StackedOfferSection({
cards = demoCards,
headingTitle = "What We",
headingEmphasis = "Offer",
headingDescription = "Comprehensive executive leadership development solutions designed to transform\nsenior leadership capabilities and drive organizational excellence.",
}: StackedOfferSectionProps) {
const sectionRef = useRef<HTMLDivElement | null>(null);
const [activeIndex, setActiveIndex] = useState(0);
const [stickyStartPosition, setStickyStartPosition] = useState<number | null>(null);
const [isSticky, setIsSticky] = useState(false);
// Constants - Increased card height from 400px to 480px
const CARD_HEIGHT = 480;
const SCROLL_PER_CARD = 200; // Pixels to scroll for each card
useEffect(() => {
let ticking = false;
const handleScroll = () => {
if (!ticking) {
requestAnimationFrame(() => {
if (!sectionRef.current) return;
const section = sectionRef.current;
const rect = section.getBoundingClientRect();
const currentScrollY = window.scrollY;
// Check if section has reached the top (becomes sticky)
const sectionIsSticky = rect.top <= 0;
if (sectionIsSticky && !isSticky) {
// Section just became sticky - record the scroll position
setStickyStartPosition(currentScrollY);
setIsSticky(true);
setActiveIndex(0); // Start with first card
return;
} else if (!sectionIsSticky && isSticky) {
// Section is no longer sticky - reset everything
setIsSticky(false);
setStickyStartPosition(null);
setActiveIndex(0);
return;
}
// If section is sticky and we have a starting position
if (sectionIsSticky && stickyStartPosition !== null) {
// Calculate how much we've scrolled since becoming sticky
const scrolledSinceSticky = currentScrollY - stickyStartPosition;
// Determine which card should be active based on scroll distance
let newCardIndex = 0;
if (scrolledSinceSticky >= SCROLL_PER_CARD * 3) {
newCardIndex = 3; // Card 4 (Change Leadership)
} else if (scrolledSinceSticky >= SCROLL_PER_CARD * 2) {
newCardIndex = 2; // Card 3 (Strategic Execution)
} else if (scrolledSinceSticky >= SCROLL_PER_CARD) {
newCardIndex = 1; // Card 2 (Executive Presence)
} else {
newCardIndex = 0; // Card 1 (Leadership Foundations)
}
// Only update if card index has changed
if (newCardIndex !== activeIndex) {
setActiveIndex(newCardIndex);
}
}
ticking = false;
});
ticking = true;
}
};
// Add scroll listener
window.addEventListener('scroll', handleScroll, { passive: true });
// Initial call
handleScroll();
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, [activeIndex, stickyStartPosition, isSticky]);
return (
<div className="relative">
{/* Sticky Section - What We Offer */}
<section
ref={sectionRef}
className="sticky top-0 py-20 min-h-screen flex items-center justify-center z-10"
style={{ backgroundColor: '#FFFFFF' }}
>
<div className="container mx-auto section-margin-x">
{/* Heading */}
<div className="text-center mb-16 max-w-4xl mx-auto">
<h2 className="text-h2 mb-6">
{headingTitle} <span className="text-primary">{headingEmphasis}</span>
</h2>
<p className="text-body-lg text-muted" style={{ whiteSpace: 'pre-line' }}>
{headingDescription}
</p>
</div>
{/* Desktop: Stacking Cards */}
<div className="hidden lg:block relative">
{/* Stack Container - Increased width from max-w-2xl to max-w-3xl and height to match new card height */}
<div className="relative mx-auto max-w-3xl h-[480px]">
{/* Stack Area */}
<div className="relative w-full h-full flex items-center justify-center">
{cards.map((card, index) => {
const shouldShow = index <= activeIndex;
const isActive = activeIndex === index;
return (
<div
key={card.id}
className={`
absolute inset-0 transition-all duration-700 ease-out
${shouldShow
? 'opacity-100 translate-y-0 scale-100'
: 'opacity-0 translate-y-full scale-95'
}
`}
style={{
zIndex: 10 + index,
transitionDelay: shouldShow ? `${index * 100}ms` : '0ms'
}}
>
{/* Card Content - White Background with Brand Colors */}
<div
className="w-full h-full rounded-3xl p-8 bg-white border border-gray-200 card-shadow-dramatic"
style={{ height: `${CARD_HEIGHT}px` }}
>
{/* Header */}
<div className="flex items-start justify-between mb-6">
<div className="flex items-center gap-4">
<div className="w-16 h-16 rounded-2xl bg-blue-50 border border-blue-100 flex items-center justify-center">
{card.icon && <card.icon className="w-8 h-8 text-primary" />}
</div>
<div>
{card.badge && (
<span className="inline-flex items-center px-2.5 py-0.5 rounded-md text-primary border border-primary bg-blue-50 mb-2 text-xs font-medium">
{card.badge}
</span>
)}
{card.subtitle && (
<div className="text-sm text-muted">{card.subtitle}</div>
)}
</div>
</div>
<div className="text-right">
<div className="text-4xl font-bold mb-1 text-primary">
{String(card.id).padStart(2, "0")}
</div>
<div className="w-8 h-0.5 bg-primary ml-auto" />
</div>
</div>
{/* Content */}
<div className="mb-6">
<h3 className="text-h3 mb-3 text-black">{card.title}</h3>
{card.description && (
<p className="text-body text-muted leading-relaxed mb-4">
{card.description}
</p>
)}
{card.features?.length && (
<div className="grid grid-cols-2 gap-3">
{card.features.map((feature, idx) => (
<div key={idx} className="flex items-center gap-2">
<div className="w-1.5 h-1.5 rounded-full bg-primary" />
<span className="text-sm text-black">{feature}</span>
</div>
))}
</div>
)}
</div>
{/* Footer stats */}
{card.stats?.length && (
<div className="flex justify-between items-center pt-6 border-t border-gray-200">
{card.stats.map((stat, idx) => (
<div key={idx} className="text-center">
<div className="text-2xl font-bold text-primary">{stat.value}</div>
<div className="text-xs text-muted">{stat.label}</div>
</div>
))}
</div>
)}
</div>
</div>
);
})}
</div>
</div>
</div>
{/* Progress Indicators */}
<div className="hidden lg:block fixed right-8 top-1/2 transform -translate-y-1/2 z-50">
</div>
{/* Mobile/Tablet: Simple Card List - Updated with White Background */}
<div className="lg:hidden">
<div className="space-y-8">
{cards.map((card, index) => (
<div
key={`mobile-${card.id}`}
className="rounded-2xl p-6 bg-white border border-gray-200 card-shadow-elevated card-hover-lift"
>
<div className="flex items-center gap-3 mb-4">
<div className="w-12 h-12 rounded-xl bg-blue-50 border border-blue-100 flex items-center justify-center">
{card.icon && <card.icon className="w-6 h-6 text-primary" />}
</div>
<div>
{card.badge && (
<span className="inline-block px-2 py-0.5 rounded text-xs bg-blue-50 border border-primary text-primary mb-1 font-medium">
{card.badge}
</span>
)}
{card.subtitle && (
<div className="text-xs text-muted">{card.subtitle}</div>
)}
</div>
</div>
<h3 className="text-h4 mb-2 text-black">{card.title}</h3>
{card.description && (
<p className="text-body text-muted mb-4">{card.description}</p>
)}
{card.features?.length && (
<div className="grid grid-cols-2 gap-2 mb-4">
{card.features.map((feature, idx) => (
<div key={idx} className="flex items-center gap-2">
<div className="w-1 h-1 rounded-full bg-primary" />
<span className="text-xs text-black">{feature}</span>
</div>
))}
</div>
)}
{card.stats?.length && (
<div className="flex justify-between pt-4 border-t border-gray-200">
{card.stats.map((stat, idx) => (
<div key={idx} className="text-center">
<div className="text-lg font-bold text-primary">{stat.value}</div>
<div className="text-xs text-muted">{stat.label}</div>
</div>
))}
</div>
)}
</div>
))}
</div>
</div>
</div>
</section>
{/* Optimized Scroll Space - Matches actual scroll distance needed */}
<div style={{ height: `${SCROLL_PER_CARD * (cards.length - 1) + 100}px` }} className="relative">
{/*
This div creates the exact scroll space needed for card reveals:
- Card 1: 0px (immediately when sticky)
- Card 2: 200px
- Card 3: 400px
- Card 4: 600px
Total: 600px + 100px buffer = 700px
*/}
<div className="w-full h-full" />
</div>
</div>
);
}

View File

@@ -0,0 +1,100 @@
import React, { useState } from 'react';
import { ArrowRight } from 'lucide-react';
interface StandardCTAButtonProps {
text: string;
onClick: () => void;
ariaLabel?: string;
className?: string;
disabled?: boolean;
}
export function StandardCTAButton({
text,
onClick,
ariaLabel,
className = '',
disabled = false
}: StandardCTAButtonProps) {
const [isHovered, setIsHovered] = useState(false);
return (
<button
onClick={onClick}
disabled={disabled}
aria-label={ariaLabel || text}
className={`standard-cta-button ${className}`}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '8px',
padding: '16px 28px',
borderRadius: '12px',
border: 'none',
cursor: disabled ? 'not-allowed' : 'pointer',
fontSize: 'var(--font-body)',
fontWeight: 'var(--font-weight-h3)',
fontFamily: 'var(--font-family-base)',
backgroundColor: disabled ? '#9CA3AF' : 'var(--color-primary)',
color: '#FFFFFF',
boxShadow: disabled
? 'none'
: '0 2px 4px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06)',
transition: 'all 200ms ease-in-out',
position: 'relative',
overflow: 'hidden',
opacity: disabled ? 0.6 : 1,
transform: isHovered && !disabled ? 'translateY(-1px)' : 'translateY(0)',
...(isHovered && !disabled && {
backgroundColor: '#030359', // Darker shade of primary brand color
boxShadow: '0 4px 8px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(0, 0, 0, 0.1)'
})
}}
>
{/* Text with underline animation */}
<span
style={{
position: 'relative',
display: 'inline-block',
transition: 'all 200ms ease-in-out'
}}
>
{text}
{/* Animated underline */}
<span
style={{
position: 'absolute',
bottom: '-2px',
left: '0',
height: '1px',
backgroundColor: '#FFFFFF',
transition: 'width 200ms ease-in-out',
width: isHovered && !disabled ? '100%' : '0%'
}}
/>
</span>
{/* Arrow icon with slide-in animation */}
<span
style={{
display: 'flex',
alignItems: 'center',
transition: 'transform 200ms ease-in-out',
transform: isHovered && !disabled ? 'translateX(0)' : 'translateX(4px)',
opacity: isHovered && !disabled ? 1 : 0.8
}}
>
<ArrowRight
size={16}
style={{
color: '#FFFFFF',
transition: 'all 200ms ease-in-out'
}}
/>
</span>
</button>
);
}

View File

@@ -0,0 +1,143 @@
import { Button } from "./ui/button";
import { useAnimatedCounter } from "./hooks/useAnimatedCounter";
import { ArrowUpRight } from "lucide-react";
import { useState, useEffect } from "react";
import { BrandedTag } from "./about/BrandedTag";
import { PrimaryCTAButton } from "./PrimaryCTAButton";
interface StatItemProps {
end: number;
suffix: string;
label: string;
duration?: number;
}
function StatItem({ end, suffix, label, duration = 2000 }: StatItemProps) {
const { count, ref } = useAnimatedCounter({ end, suffix, duration });
return (
<div className="mb-0">
{/* Top line */}
<div
className="w-full h-[1px] mb-4"
style={{ backgroundColor: 'var(--color-brand-gray-muted)' }}
/>
{/* Large number */}
<div
ref={ref}
className="stats-number mb-3 leading-none"
style={{
color: 'var(--color-brand-primary)',
fontFamily: 'var(--font-family-base)'
}}
>
{count}
</div>
{/* Yellow square and label */}
<div className="flex items-center mb-4">
<div
className="w-2 h-2 mr-3 flex-shrink-0"
style={{ backgroundColor: 'var(--color-brand-accent)' }}
/>
<span
className="text-eyebrow"
style={{ color: 'var(--color-brand-black)' }}
>
{label}
</span>
</div>
{/* Bottom line */}
<div
className="w-full h-[1px]"
style={{ backgroundColor: 'var(--color-brand-gray-muted)' }}
/>
</div>
);
}
export function StatsSection() {
return (
<section
className="py-20"
style={{ backgroundColor: 'var(--color-brand-bg-light)' }}
>
<div className="section-margin-x">
<div className="max-w-7xl mx-auto">
<div className="mb-12 lg:mb-16 md:mb-12 sm:mb-8">
{/* Branded Tag */}
<BrandedTag
text="Serving Leaders Across Industries"
/>
{/* Main Heading */}
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8 lg:gap-12 items-start">
<div className="lg:col-span-6 md:col-span-8 sm:col-span-12">
<h2 className="text-h2 mb-8">
Driving impact by building future-ready leaders who thrive in
complexity and lead with confidence.
</h2>
{/* CTA Button */}
<PrimaryCTAButton
text="About Us"
onClick={() => console.log('About us clicked')}
ariaLabel="Learn more about KLC"
/>
</div>
{/* Desktop Statistics */}
<div className="hidden lg:block lg:col-start-9 lg:col-end-13">
<div className="space-y-6">
<StatItem
end={27000}
suffix="+"
label="LEADERS DEVELOPED"
duration={2500}
/>
<StatItem
end={150}
suffix="+"
label="CORPORATE CLIENTS"
duration={2000}
/>
<StatItem
end={20}
suffix="+"
label="COUNTRIES SERVED"
duration={1800}
/>
</div>
</div>
</div>
{/* Mobile Statistics - Show below content on mobile/tablet */}
<div className="block lg:hidden mt-12">
<div className="grid grid-cols-2 gap-6 sm:gap-8">
<StatItem
end={27000}
suffix="+"
label="LEADERS DEVELOPED"
duration={2500}
/>
<StatItem
end={150}
suffix="+"
label="CORPORATE CLIENTS"
duration={2000}
/>
<StatItem
end={20}
suffix="+"
label="COUNTRIES SERVED"
duration={1800}
/>
</div>
</div>
</div>
</div>
</div>
</section>
);
}

853
src/components/Terms.tsx Normal file
View File

@@ -0,0 +1,853 @@
import React, { useState, useEffect } from "react";
import { Navigation } from "./Navigation";
import { Footer } from "./Footer";
import {
ChevronRight,
Download,
ExternalLink,
} from "lucide-react";
interface TocItem {
id: string;
title: string;
level: number;
}
export function Terms() {
const [activeSection, setActiveSection] =
useState<string>("acceptance");
const [tocOpen, setTocOpen] = useState(false);
// Table of Contents items
const tocItems: TocItem[] = [
{
id: "acceptance",
title: "Acceptance of Terms",
level: 1,
},
{
id: "eligibility",
title: "Eligibility & Jurisdiction",
level: 1,
},
{ id: "use-of-site", title: "Use of Site", level: 1 },
{
id: "purchases-refunds",
title: "Purchases & Refunds",
level: 1,
},
{
id: "intellectual-property",
title: "Intellectual Property",
level: 1,
},
{
id: "disclaimers",
title: "Disclaimers & Limitations",
level: 1,
},
{ id: "governing-law", title: "Governing Law", level: 1 },
{
id: "modifications",
title: "Terms Modifications",
level: 1,
},
{
id: "contact-info",
title: "Contact Information",
level: 1,
},
{ id: "download-pdf", title: "Download PDF", level: 1 },
];
// Scroll to section and update active state
const scrollToSection = (sectionId: string) => {
const element = document.getElementById(sectionId);
if (element) {
const offsetTop = element.offsetTop - 100; // Account for sticky nav
window.scrollTo({
top: offsetTop,
behavior: "smooth",
});
setActiveSection(sectionId);
}
};
// Update active section on scroll
useEffect(() => {
const handleScroll = () => {
const sections = tocItems
.map((item) => document.getElementById(item.id))
.filter(Boolean);
const scrollPosition = window.scrollY + 150;
for (let i = sections.length - 1; i >= 0; i--) {
const section = sections[i];
if (section && section.offsetTop <= scrollPosition) {
setActiveSection(section.id);
break;
}
}
};
window.addEventListener("scroll", handleScroll);
return () =>
window.removeEventListener("scroll", handleScroll);
}, []);
// Handle URL fragments
useEffect(() => {
const hash = window.location.hash.replace("#", "");
if (hash && tocItems.find((item) => item.id === hash)) {
setTimeout(() => scrollToSection(hash), 100);
}
}, []);
const lastUpdated = "2025-01-01";
const versionHash = "v25.01";
return (
<div style={{ backgroundColor: "#FFFFFF" }}>
<Navigation />
{/* Hero Banner */}
<section
className="py-16 section-margin-x"
style={{ backgroundColor: "#FFFFFF" }}
>
<div className="max-w-4xl mx-auto text-center">
<div className="inline-flex items-center gap-2 px-4 py-2 bg-blue-100 text-blue-800 rounded-full text-small mb-6">
<span className="w-2 h-2 bg-blue-600 rounded-full"></span>
Legal Document
<span className="ml-2 px-2 py-1 bg-blue-200 text-blue-900 rounded text-xs font-medium">
{versionHash}
</span>
</div>
<h1 className="text-h1 mb-6">Terms & Conditions</h1>
<p className="text-body-lg text-muted max-w-2xl mx-auto mb-4">
These terms govern your use of the Kautilya
Leadership Centre website and services. Please read
carefully before using our platform.
</p>
<p className="text-small text-muted">
Last updated:{" "}
{new Date(lastUpdated).toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
})}
</p>
</div>
</section>
<div
className="section-margin-x"
style={{ backgroundColor: "#FFFFFF" }}
>
<div className="max-w-6xl mx-auto">
<div className="grid grid-cols-12 gap-8">
{/* Sticky Table of Contents */}
<div className="col-span-12 lg:col-span-3">
<div className="sticky top-24">
<nav
aria-label="On-page navigation"
className="bg-white border border-gray-200 rounded-lg p-6 shadow-sm"
>
<div className="flex items-center justify-between mb-4 lg:hidden">
<h3 className="text-h4">Contents</h3>
<button
onClick={() => setTocOpen(!tocOpen)}
className="p-2 hover:bg-gray-100 rounded-md transition-colors"
aria-expanded={tocOpen}
>
<ChevronRight
className={`w-4 h-4 transition-transform ${tocOpen ? "rotate-90" : ""}`}
/>
</button>
</div>
<div
className={`space-y-2 ${tocOpen ? "block" : "hidden lg:block"}`}
>
{tocItems.map((item) => (
<button
key={item.id}
onClick={() => scrollToSection(item.id)}
className={`block w-full text-left p-2 rounded-md text-small transition-all duration-200 hover:bg-gray-100 ${
activeSection === item.id
? "bg-blue-50 text-primary border-l-2 border-primary pl-3"
: "text-muted hover:text-black"
}`}
>
{item.title}
</button>
))}
</div>
</nav>
</div>
</div>
{/* Main Content */}
<div className="col-span-12 lg:col-span-9">
<div
className="max-w-3xl prose prose-lg"
style={{ maxWidth: "720px" }}
>
{/* Acceptance of Terms */}
<section
id="acceptance"
className="mb-12 scroll-mt-24"
>
<h2
className="text-h2 mb-6 group cursor-pointer"
onClick={() =>
scrollToSection("acceptance")
}
>
<span className="inline-flex items-center gap-2">
Acceptance of Terms
<ExternalLink className="w-5 h-5 opacity-0 group-hover:opacity-100 transition-opacity" />
</span>
</h2>
<div className="space-y-4">
<p className="text-body-lg">
By accessing and using the Kautilya
Leadership Centre (KLC) website and
services, you accept and agree to be bound
by the terms and provision of this
agreement.
</p>
<p className="text-body">
If you do not agree to abide by the above,
please do not use this service. Your
continued use of our platform constitutes
acceptance of these terms as they may be
modified from time to time.
</p>
<div className="bg-yellow-50 border-l-4 border-yellow-400 p-4 rounded-r-lg">
<p className="text-body text-yellow-800">
<strong>Important:</strong> These terms
create a legally binding agreement
between you and KLC. Please ensure you
understand your rights and obligations.
</p>
</div>
</div>
</section>
{/* Eligibility & Jurisdiction */}
<section
id="eligibility"
className="mb-12 scroll-mt-24"
>
<h2
className="text-h2 mb-6 group cursor-pointer"
onClick={() =>
scrollToSection("eligibility")
}
>
<span className="inline-flex items-center gap-2">
Eligibility & Jurisdiction
<ExternalLink className="w-5 h-5 opacity-0 group-hover:opacity-100 transition-opacity" />
</span>
</h2>
<div className="space-y-4">
<h3 className="text-h3 mb-4">
Age Requirements
</h3>
<p className="text-body">
You must be at least 18 years of age to
use our services. If you are between 13
and 18 years old, you may only use our
services with the involvement and consent
of a parent or guardian.
</p>
<h3 className="text-h3 mb-4 mt-8">
Geographic Scope
</h3>
<p className="text-body">
Our services are primarily intended for
users in India and regions where our
educational content and leadership
development programs are legally
permissible and culturally appropriate.
</p>
<h3 className="text-h3 mb-4 mt-8">
Corporate Access
</h3>
<p className="text-body">
Organizations and corporate entities
accessing our services must ensure they
have proper authorization to enter into
these terms on behalf of their
organization.
</p>
</div>
</section>
{/* Use of Site */}
<section
id="use-of-site"
className="mb-12 scroll-mt-24"
>
<h2
className="text-h2 mb-6 group cursor-pointer"
onClick={() =>
scrollToSection("use-of-site")
}
>
<span className="inline-flex items-center gap-2">
Use of Site
<ExternalLink className="w-5 h-5 opacity-0 group-hover:opacity-100 transition-opacity" />
</span>
</h2>
<div className="space-y-4">
<h3 className="text-h3 mb-4">
Permitted Uses
</h3>
<ul className="list-disc pl-6 space-y-2 text-body">
<li>
Accessing educational content and
leadership development materials
</li>
<li>
Participating in webinars, courses, and
training programs
</li>
<li>
Using our virtual learning facility for
authorized purposes
</li>
<li>
Downloading materials explicitly marked
as downloadable
</li>
<li>
Sharing content through our designated
social sharing features
</li>
</ul>
<h3 className="text-h3 mb-4 mt-8">
Prohibited Activities
</h3>
<ul className="list-disc pl-6 space-y-2 text-body">
<li>
Unauthorized copying, distribution, or
modification of our content
</li>
<li>
Using automated systems to access or
scrape our website
</li>
<li>
Attempting to gain unauthorized access
to our systems
</li>
<li>
Sharing login credentials or accessing
accounts not belonging to you
</li>
<li>
Using our services for any illegal or
harmful purposes
</li>
<li>
Disrupting the normal operation of our
platform
</li>
</ul>
<div className="bg-red-50 border-l-4 border-red-400 p-4 rounded-r-lg mt-6">
<p className="text-body text-red-800">
<strong>Warning:</strong> Violation of
these terms may result in immediate
termination of your access to our
services and potential legal action.
</p>
</div>
</div>
</section>
{/* Purchases & Refunds */}
<section
id="purchases-refunds"
className="mb-12 scroll-mt-24"
>
<h2
className="text-h2 mb-6 group cursor-pointer"
onClick={() =>
scrollToSection("purchases-refunds")
}
>
<span className="inline-flex items-center gap-2">
Purchases & Refunds
<ExternalLink className="w-5 h-5 opacity-0 group-hover:opacity-100 transition-opacity" />
</span>
</h2>
<div className="space-y-4">
<h3 className="text-h3 mb-4">
Payment Terms
</h3>
<p className="text-body">
All payments must be made in full before
accessing paid content or services. We
accept major credit cards, debit cards,
and approved corporate payment methods.
</p>
<h3 className="text-h3 mb-4 mt-8">
GST & Taxes
</h3>
<p className="text-body">
All prices are inclusive of applicable
Goods and Services Tax (GST) as required
by Indian law. International customers may
be subject to additional taxes in their
jurisdiction.
</p>
<h3 className="text-h3 mb-4 mt-8">
Refund Policy
</h3>
<div className="bg-gray-50 border border-gray-200 rounded-lg p-6">
<h4 className="text-body font-semibold mb-3">
Standard Refund Terms:
</h4>
<ul className="list-disc pl-6 space-y-2 text-body">
<li>
<strong>Online Courses:</strong> 7-day
refund period from date of purchase
(before 25% completion)
</li>
<li>
<strong>Live Webinars:</strong> Full
refund if cancelled 24 hours before
start time
</li>
<li>
<strong>Corporate Programs:</strong>{" "}
Refund terms specified in individual
agreements
</li>
<li>
<strong>Digital Materials:</strong> No
refunds after download or access
</li>
</ul>
<h4 className="text-body font-semibold mb-3 mt-6">
Refund Process:
</h4>
<p className="text-body">
To request a refund, contact our support
team with your order details. Approved
refunds will be processed within 7-10
business days to the original payment
method.
</p>
</div>
</div>
</section>
{/* Intellectual Property */}
<section
id="intellectual-property"
className="mb-12 scroll-mt-24"
>
<h2
className="text-h2 mb-6 group cursor-pointer"
onClick={() =>
scrollToSection("intellectual-property")
}
>
<span className="inline-flex items-center gap-2">
Intellectual Property
<ExternalLink className="w-5 h-5 opacity-0 group-hover:opacity-100 transition-opacity" />
</span>
</h2>
<div className="space-y-4">
<p className="text-body-lg">
All content on this website, including but
not limited to text, graphics, logos,
images, audio clips, video content, and
software, is the property of KLC or its
content suppliers.
</p>
<h3 className="text-h3 mb-4 mt-8">
Copyright Notice
</h3>
<div className="bg-blue-50 border border-blue-200 rounded-lg p-6">
<p className="text-body text-blue-800">
© 2025 Kautilya Leadership Centre. All
rights reserved. This website and its
contents are protected by copyright,
trademark, and other intellectual
property laws.
</p>
</div>
<h3 className="text-h3 mb-4 mt-8">
Limited License
</h3>
<p className="text-body">
We grant you a limited, non-exclusive,
non-transferable license to access and use
our content for personal or internal
business purposes in accordance with these
terms.
</p>
<h3 className="text-h3 mb-4 mt-8">
Trademark Information
</h3>
<p className="text-body">
"Kautilya Leadership Centre" and all
related logos are trademarks of KLC. You
may not use our trademarks without prior
written permission.
</p>
</div>
</section>
{/* Disclaimers & Limitations */}
<section
id="disclaimers"
className="mb-12 scroll-mt-24"
>
<h2
className="text-h2 mb-6 group cursor-pointer"
onClick={() =>
scrollToSection("disclaimers")
}
>
<span className="inline-flex items-center gap-2">
Disclaimers & Limitations
<ExternalLink className="w-5 h-5 opacity-0 group-hover:opacity-100 transition-opacity" />
</span>
</h2>
<div className="space-y-4">
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-6">
<h3 className="text-h3 mb-4 text-yellow-800">
Important Legal Notice
</h3>
<p className="text-body text-yellow-800">
The information provided on this website
is for educational purposes only and
does not constitute professional advice.
KLC makes no warranties about the
completeness, reliability, or accuracy
of this information.
</p>
</div>
<h3 className="text-h3 mb-4 mt-8">
Limitation of Liability
</h3>
<p className="text-body">
In no event shall KLC be liable for any
direct, indirect, incidental, special, or
consequential damages resulting from your
use of our website or services, even if we
have been advised of the possibility of
such damages.
</p>
<h3 className="text-h3 mb-4 mt-8">
Service Availability
</h3>
<p className="text-body">
We strive to maintain continuous service
availability but do not guarantee
uninterrupted access. Scheduled
maintenance and unforeseen technical
issues may temporarily affect service
availability.
</p>
<h3 className="text-h3 mb-4 mt-8">
Third-Party Links
</h3>
<p className="text-body">
Our website may contain links to
third-party websites. We are not
responsible for the content, privacy
policies, or practices of these external
sites.
</p>
</div>
</section>
{/* Governing Law */}
<section
id="governing-law"
className="mb-12 scroll-mt-24"
>
<h2
className="text-h2 mb-6 group cursor-pointer"
onClick={() =>
scrollToSection("governing-law")
}
>
<span className="inline-flex items-center gap-2">
Governing Law
<ExternalLink className="w-5 h-5 opacity-0 group-hover:opacity-100 transition-opacity" />
</span>
</h2>
<div className="space-y-4">
<p className="text-body-lg">
These terms and conditions are governed by
and construed in accordance with the laws
of India.
</p>
<h3 className="text-h3 mb-4 mt-8">
Jurisdiction
</h3>
<div className="bg-gray-50 border border-gray-200 rounded-lg p-6">
<p className="text-body">
<strong>Exclusive Jurisdiction:</strong>{" "}
Chennai, Tamil Nadu, India
</p>
<p className="text-body mt-2">
Any disputes arising from these terms or
your use of our services shall be
subject to the exclusive jurisdiction of
the courts in Chennai, Tamil Nadu,
India.
</p>
</div>
<h3 className="text-h3 mb-4 mt-8">
Dispute Resolution
</h3>
<p className="text-body">
We encourage resolving disputes through
direct communication. If formal legal
action becomes necessary, both parties
agree to first attempt mediation before
pursuing litigation.
</p>
</div>
</section>
{/* Terms Modifications */}
<section
id="modifications"
className="mb-12 scroll-mt-24"
>
<h2
className="text-h2 mb-6 group cursor-pointer"
onClick={() =>
scrollToSection("modifications")
}
>
<span className="inline-flex items-center gap-2">
Terms Modifications
<ExternalLink className="w-5 h-5 opacity-0 group-hover:opacity-100 transition-opacity" />
</span>
</h2>
<div className="space-y-4">
<p className="text-body-lg">
KLC reserves the right to modify these
terms at any time. Changes will be
effective immediately upon posting on this
website.
</p>
<h3 className="text-h3 mb-4 mt-8">
Notification Process
</h3>
<ul className="list-disc pl-6 space-y-2 text-body">
<li>
Material changes will be highlighted at
the top of this page
</li>
<li>
Registered users will receive email
notifications of significant updates
</li>
<li>
The "Last Updated" date will reflect the
most recent modifications
</li>
<li>
Version history is available upon
request
</li>
</ul>
<div className="bg-blue-50 border-l-4 border-blue-400 p-4 rounded-r-lg mt-6">
<p className="text-body text-blue-800">
<strong>Your Responsibility:</strong> It
is your responsibility to periodically
review these terms. Continued use of our
services after changes constitutes
acceptance of the modified terms.
</p>
</div>
</div>
</section>
{/* Contact Information */}
<section
id="contact-info"
className="mb-12 scroll-mt-24"
>
<h2
className="text-h2 mb-6 group cursor-pointer"
onClick={() =>
scrollToSection("contact-info")
}
>
<span className="inline-flex items-center gap-2">
Contact Information
<ExternalLink className="w-5 h-5 opacity-0 group-hover:opacity-100 transition-opacity" />
</span>
</h2>
<div className="space-y-4">
<p className="text-body-lg">
For questions about these terms or to
report violations, please contact our
legal team:
</p>
<div className="bg-white border border-gray-200 rounded-lg p-6 space-y-4">
<div>
<h3 className="text-h4 mb-2">
Legal Inquiries
</h3>
<p className="text-body">
<strong>Email:</strong>{" "}
legal@klc.edu.in
<br />
<strong>Response Time:</strong> 3-5
business days
</p>
</div>
<div>
<h3 className="text-h4 mb-2">
Registered Office
</h3>
<p className="text-body">
Kautilya Leadership Centre
<br />
123 Leadership Avenue
<br />
Chennai, Tamil Nadu 600001
<br />
India
</p>
</div>
<div>
<h3 className="text-h4 mb-2">
General Inquiries
</h3>
<p className="text-body">
<strong>Phone:</strong>{" "}
+91-44-1234-5678
<br />
<strong>Email:</strong>{" "}
info@klc.edu.in
</p>
</div>
</div>
</div>
</section>
{/* Download PDF */}
<section
id="download-pdf"
className="mb-12 scroll-mt-24"
>
<h2
className="text-h2 mb-6 group cursor-pointer"
onClick={() =>
scrollToSection("download-pdf")
}
>
<span className="inline-flex items-center gap-2">
Download PDF
<ExternalLink className="w-5 h-5 opacity-0 group-hover:opacity-100 transition-opacity" />
</span>
</h2>
<div className="space-y-4">
<p className="text-body">
Download a timestamped PDF version of
these terms for your records.
</p>
<div className="bg-gray-50 border border-gray-200 rounded-lg p-6">
<div className="flex items-center justify-between">
<div>
<h3 className="text-h4 mb-2">
Terms & Conditions PDF
</h3>
<p className="text-small text-muted">
Version {versionHash} Last updated{" "}
{new Date(
lastUpdated,
).toLocaleDateString()}{" "}
156 KB
</p>
</div>
<button
onClick={() => {
// In a real implementation, this would download the actual PDF
alert(
"PDF download would start here",
);
}}
className="flex items-center gap-2 px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors"
aria-label="Download Terms & Conditions PDF (156 KB)"
>
<Download className="w-4 h-4" />
Download PDF
</button>
</div>
</div>
<p className="text-small text-muted">
The PDF version includes a digital
signature and timestamp for authenticity
verification.
</p>
</div>
</section>
</div>
</div>
</div>
</div>
</div>
<Footer />
{/* Print Styles */}
<style>{`
@media print {
.sticky { position: static !important; }
nav[aria-label="On-page navigation"] { display: none !important; }
.bg-gradient-to-r { background: white !important; }
.text-white { color: black !important; }
.bg-blue-50, .bg-yellow-50, .bg-red-50, .bg-gray-50 {
background: white !important;
border: 1px solid #ccc !important;
}
.shadow-sm, .shadow-lg { box-shadow: none !important; }
h1, h2, h3, h4 { break-after: avoid; }
.space-y-4 > * { break-inside: avoid; }
@page { margin: 2cm; }
.page-break { page-break-before: always; }
}
`}</style>
</div>
);
}

View File

@@ -0,0 +1,286 @@
import { motion } from "motion/react";
import { ImageWithFallback } from "./figma/ImageWithFallback";
import { Play, X } from "lucide-react";
import { useState } from "react";
interface Testimonial {
id: number;
quote: string;
name: string;
title: string;
company: string;
image: string;
hasVideo: boolean;
}
const testimonials: Testimonial[] = [
{
id: 1,
quote: "KLC's leadership programs fundamentally changed how I approach team management and strategic decision-making in our organization.",
name: "Rachel Thompson",
title: "Senior Vice President",
company: "Global Enterprises",
image: "https://images.unsplash.com/photo-1580489944761-15a19d654956?w=600&h=800&fit=crop&crop=face",
hasVideo: true
},
{
id: 2,
quote: "KLC's leadership development programs have completely changed how we approach team building and strategic planning. The results speak for themselves.",
name: "Sarah Chen",
title: "Chief Executive Officer",
company: "TechForward Solutions",
image: "https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=600&h=800&fit=crop&crop=face",
hasVideo: true
},
{
id: 3,
quote: "Working with KLC's consulting team was transformational. Their evidence-based approach helped us build stronger, more resilient leadership across all departments.",
name: "Michael Rodriguez",
title: "Head of Operations",
company: "Innovation Dynamics Inc",
image: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=600&h=800&fit=crop&crop=face",
hasVideo: true
}
];
export function TestimonialsHeroSection() {
const [currentTestimonial, setCurrentTestimonial] = useState(0);
const [isVideoPlaying, setIsVideoPlaying] = useState(false);
const [showLightbox, setShowLightbox] = useState(false);
const testimonial = testimonials[currentTestimonial];
const handlePlayVideo = () => {
setShowLightbox(true);
setIsVideoPlaying(true);
};
const handleCloseLightbox = () => {
setShowLightbox(false);
setIsVideoPlaying(false);
};
return (
<section
className="relative py-20 flex items-center"
style={{
backgroundColor: '#F7F7FD'
}}
>
<div className="w-full section-margin-x">
{/* Branded Tag */}
<motion.div
className="flex justify-center mb-12"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
<div className="inline-flex items-center gap-3 bg-[rgba(248,195,1,0.1)] px-4 py-2 rounded-lg">
<div className="w-[7px] h-[7px] bg-[#f8c301] rounded-full" />
<span className="text-[#26231a] text-lg lg:text-lg md:text-base sm:text-sm uppercase tracking-wider font-light">
Client Success Stories
</span>
</div>
</motion.div>
{/* Main heading */}
<motion.h2
className="text-h2 leading-tight mb-12 text-center"
style={{ color: 'var(--color-brand-primary)' }}
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, delay: 0.2 }}
>
What Our Clients Say
</motion.h2>
{/* Split Layout Container with Max Width - Compact Version */}
<div className="max-w-5xl mx-auto">
<div className="flex h-[400px] rounded-2xl overflow-hidden shadow-2xl">
{/* Left Side - Video Thumbnail */}
<motion.div
className="flex-1 relative group cursor-pointer"
initial={{ opacity: 0, x: -50 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.8, delay: 0.4 }}
onClick={handlePlayVideo}
>
<div className="relative w-full h-full overflow-hidden">
{/* Video Thumbnail */}
<ImageWithFallback
src={testimonial.image}
alt={testimonial.name}
className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105"
/>
{/* Dark overlay on hover */}
<div className="absolute inset-0 bg-black/20 opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
{/* Centered Play Button Overlay */}
{testimonial.hasVideo && (
<div className="absolute inset-0 flex items-center justify-center">
<motion.div
className="flex items-center justify-center w-16 h-16 bg-white/90 backdrop-blur-sm rounded-full shadow-lg group-hover:scale-110 transition-all duration-300"
whileHover={{ scale: 1.15 }}
whileTap={{ scale: 0.95 }}
>
<Play
className="w-7 h-7 ml-1 text-blue-600"
fill="currentColor"
/>
</motion.div>
</div>
)}
{/* Watch Video Text */}
<div className="absolute bottom-4 left-4 text-white">
<div className="bg-black/30 backdrop-blur-sm rounded-lg px-3 py-1">
<span className="text-xs font-medium"> Video</span>
</div>
</div>
</div>
</motion.div>
{/* Right Side - Quote Content with White Background - Compact */}
<motion.div
className="flex-1 flex items-center justify-center p-8 relative"
style={{
backgroundColor: 'white'
}}
initial={{ opacity: 0, x: 50 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.8, delay: 0.6 }}
>
{/* Large Opening Quotation Mark */}
<div
className="absolute top-4 left-4 text-3xl opacity-30"
style={{ color: 'var(--color-brand-primary)' }}
>
"
</div>
<div className="space-y-4 max-w-lg relative z-10">
{/* Quote with Compact Typography */}
<blockquote
className="text-lg leading-relaxed font-medium"
style={{
fontFamily: 'var(--font-family-brand)',
color: 'var(--color-brand-black)'
}}
>
{testimonial.quote}
</blockquote>
{/* Attribution */}
<div className="space-y-1 pt-3">
<div
className="text-base font-semibold"
style={{ color: 'var(--color-brand-primary)' }}
>
{testimonial.name}
</div>
{testimonial.title && (
<div
className="text-xs"
style={{ color: 'var(--color-brand-gray-muted)' }}
>
{testimonial.title} {testimonial.company && `at ${testimonial.company}`}
</div>
)}
</div>
{/* Testimonial Navigation Dots */}
<div className="flex items-center space-x-2 pt-4">
{testimonials.map((_, index) => (
<button
key={index}
className={`w-2 h-2 rounded-full transition-all duration-300 ${
index === currentTestimonial
? 'opacity-100'
: 'opacity-30 hover:opacity-60'
}`}
style={{
backgroundColor: index === currentTestimonial
? 'var(--color-brand-accent)'
: 'var(--color-brand-gray-muted)'
}}
onClick={() => setCurrentTestimonial(index)}
/>
))}
</div>
</div>
{/* Large Closing Quotation Mark */}
<div
className="absolute bottom-4 right-4 text-3xl opacity-30"
style={{ color: 'var(--color-brand-primary)' }}
>
"
</div>
</motion.div>
</div>
</div>
</div>
{/* Video Lightbox Modal */}
{showLightbox && (
<motion.div
className="fixed inset-0 bg-black/90 flex items-center justify-center z-50"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
{/* Close Button */}
<button
className="absolute top-6 right-6 text-white hover:text-gray-300 transition-colors z-60"
onClick={handleCloseLightbox}
>
<X className="w-8 h-8" />
</button>
{/* Video Container */}
<motion.div
className="relative w-full max-w-4xl mx-4"
initial={{ scale: 0.8, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ duration: 0.3 }}
>
<div className="relative aspect-video bg-black rounded-lg overflow-hidden">
{/* Placeholder for actual video */}
<div className="absolute inset-0 flex items-center justify-center bg-gray-900">
<div className="text-center text-white">
<Play className="w-16 h-16 mx-auto mb-4 opacity-60" fill="currentColor" />
<p className="text-lg">Video would play here</p>
<p className="text-sm opacity-70 mt-2">Replace with actual video element</p>
</div>
</div>
{/* Video Controls */}
<div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/60 to-transparent p-4">
<div className="flex items-center space-x-3">
<button
className="text-white hover:text-gray-300 transition-colors"
onClick={() => setIsVideoPlaying(!isVideoPlaying)}
>
<Play className="w-6 h-6" fill="currentColor" />
</button>
<div className="flex-1 bg-white/30 rounded-full h-1">
<motion.div
className="h-full rounded-full"
style={{ backgroundColor: 'var(--color-brand-accent)' }}
initial={{ width: '0%' }}
animate={{ width: isVideoPlaying ? '100%' : '0%' }}
transition={{ duration: 30, ease: "linear" }}
/>
</div>
<span className="text-white text-sm">2:34</span>
</div>
</div>
</div>
</motion.div>
</motion.div>
)}
</section>
);
}

View File

@@ -0,0 +1,553 @@
import { motion } from "motion/react";
import { ImageWithFallback } from "./figma/ImageWithFallback";
import { Play, X, ChevronLeft, ChevronRight, Star } from "lucide-react";
import { useState, useRef, useEffect } from "react";
import { BrandedTag } from "./about/BrandedTag";
interface Testimonial {
id?: number;
name: string;
role: string;
company?: string;
avatar?: string;
image?: string;
quote: string;
rating: number;
isVideo?: boolean;
videoThumbnail?: string;
videoUrl?: string;
}
const defaultTestimonialsData: Testimonial[] = [
{
id: 1,
name: "Sarah Chen",
role: "Chief Executive Officer",
company: "TechCorp Solutions",
avatar: "https://images.unsplash.com/photo-1494790108755-2616b612b786?w=400&h=400&fit=crop&crop=face",
quote: "KLC has revolutionized how we approach leadership development. The AI-powered insights are incredibly precise and have transformed our management effectiveness across our entire organization.",
rating: 5,
isVideo: true,
videoThumbnail: "https://images.unsplash.com/photo-1552664730-d307ca884978?w=600&h=300&fit=crop",
videoUrl: "https://example.com/testimonial-video-1.mp4"
},
{
id: 2,
name: "Michael Rodriguez",
role: "VP of Operations",
company: "Global Industries",
avatar: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=400&h=400&fit=crop&crop=face",
quote: "The strategic leadership programs have equipped our team with the tools needed to navigate complex business challenges with confidence and clarity. The transformation has been remarkable.",
rating: 5,
isVideo: false
},
{
id: 3,
name: "Jennifer Park",
role: "Director of Human Resources",
company: "Innovation Labs",
avatar: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=400&h=400&fit=crop&crop=face",
quote: "KLC's approach to leadership development is refreshingly practical. Our managers have shown remarkable improvement in team engagement and decision-making capabilities.",
rating: 4,
isVideo: true,
videoThumbnail: "https://images.unsplash.com/photo-1560472355-109703aa3edc?w=600&h=300&fit=crop",
videoUrl: "https://example.com/testimonial-video-2.mp4"
},
{
id: 4,
name: "David Thompson",
role: "Senior Manager",
company: "Enterprise Solutions",
avatar: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=400&h=400&fit=crop&crop=face",
quote: "The personalized coaching and development programs have been game-changing for our organization's leadership pipeline and succession planning initiatives.",
rating: 5,
isVideo: false
},
{
id: 5,
name: "Lisa Wang",
role: "Product Manager",
company: "Digital Ventures",
avatar: "https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=400&h=400&fit=crop&crop=face",
quote: "KLC has transformed how we think about leadership in the digital age. The insights and strategies have been invaluable for our team's growth and innovation culture.",
rating: 5,
isVideo: true,
videoThumbnail: "https://images.unsplash.com/photo-1559136555-9303baea8ebd?w=600&h=300&fit=crop",
videoUrl: "https://example.com/testimonial-video-3.mp4"
},
{
id: 6,
name: "Robert Kim",
role: "Regional Director",
company: "Global Corp",
avatar: "https://images.unsplash.com/photo-1519244703995-f4e0f30006d5?w=400&h=400&fit=crop&crop=face",
quote: "The leadership development framework provided by KLC has been instrumental in building a more cohesive and effective leadership team across our regions.",
rating: 4,
isVideo: false
}
];
// Star Rating Component
function StarRating({ rating }: { rating: number }) {
return (
<div className="flex gap-1 mb-3">
{[1, 2, 3, 4, 5].map((star) => (
<Star
key={star}
size={16}
className={`${
star <= rating
? 'fill-current'
: 'text-gray-300'
}`}
style={{
color: star <= rating ? 'var(--color-accent)' : '#D1D5DB'
}}
/>
))}
</div>
);
}
// Video Modal Component
function VideoModal({ isOpen, onClose, videoUrl }: {
isOpen: boolean;
onClose: () => void;
videoUrl: string;
}) {
if (!isOpen) return null;
return (
<div className="fixed inset-0 bg-black/80 backdrop-blur-sm z-50 flex items-center justify-center p-4">
<div className="relative w-full max-w-4xl aspect-video bg-black rounded-xl overflow-hidden">
<button
onClick={onClose}
className="absolute top-4 right-4 z-10 w-10 h-10 bg-black/50 hover:bg-black/70 rounded-full flex items-center justify-center text-white transition-all duration-200"
>
<X size={20} />
</button>
<div className="w-full h-full flex items-center justify-center text-white">
<div className="text-center">
<Play size={64} className="mx-auto mb-4 opacity-60" />
<p className="text-lg opacity-80">Video Testimonial</p>
<p className="text-sm opacity-60 mt-2">{videoUrl}</p>
</div>
</div>
</div>
</div>
);
}
// Individual Testimonial Card - Updated with Landing Page Design Standards
function TestimonialCard({ testimonial, onPlayVideo }: {
testimonial: Testimonial;
onPlayVideo: (videoUrl: string) => void;
}) {
const avatarSrc = testimonial.avatar || testimonial.image;
return (
<motion.div
className="testimonial-card bg-white rounded-xl border transition-all duration-300 flex-shrink-0 w-[350px] h-[300px] card-hover-lift"
style={{
borderColor: 'rgba(0, 0, 0, 0.1)',
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)'
}}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
viewport={{ once: true }}
whileHover={{
boxShadow: '0 8px 25px rgba(0, 0, 0, 0.15)',
transform: 'translateY(-4px)'
}}
>
{/* Video Testimonials */}
{testimonial.isVideo ? (
<div
className="relative h-full cursor-pointer overflow-hidden group rounded-xl"
onClick={() => onPlayVideo(testimonial.videoUrl || "")}
>
<ImageWithFallback
src={testimonial.videoThumbnail || avatarSrc || ""}
alt={`${testimonial.name} video testimonial`}
className="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105"
/>
{/* Video Overlay with Gradient */}
<div className="absolute inset-0 bg-gradient-to-t from-black/60 via-black/20 to-transparent group-hover:from-black/70 transition-all duration-300" />
{/* Play Button - Compact Design */}
<div className="absolute inset-0 flex items-center justify-center">
<motion.div
className="flex items-center justify-center w-16 h-16 bg-white/90 backdrop-blur-sm rounded-full shadow-lg"
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
>
<Play
className="w-7 h-7 ml-1 text-blue-600"
fill="currentColor"
/>
</motion.div>
</div>
{/* Video Label - Compact Style */}
<div className="absolute top-4 left-4">
<div className="px-3 py-1 rounded-full text-xs font-medium text-white bg-blue-600">
🎥 Video
</div>
</div>
{/* Profile Info - Bottom Section */}
<div className="absolute bottom-0 left-0 right-0 p-4">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-full overflow-hidden bg-white shadow-lg flex-shrink-0">
<ImageWithFallback
src={avatarSrc || ""}
alt={testimonial.name}
className="w-full h-full object-cover"
/>
</div>
<div className="min-w-0 flex-1">
<h4 className="font-semibold text-white mb-1 text-sm">
{testimonial.name}
</h4>
<p className="text-xs text-white/80 truncate">
{testimonial.role}
{testimonial.company && `${testimonial.company}`}
</p>
</div>
{/* Star Rating */}
<div className="flex gap-1">
{[1, 2, 3, 4, 5].map((star) => (
<Star
key={star}
size={14}
className={star <= testimonial.rating ? 'fill-current text-yellow-400' : 'text-white/40'}
/>
))}
</div>
</div>
</div>
</div>
) : (
/* Text Testimonials - Compact Design */
<div className="h-full flex flex-col p-6">
{/* Header Section */}
<div className="flex items-start justify-between mb-4">
<div className="flex items-center gap-3">
<div className="w-12 h-12 rounded-full overflow-hidden bg-gray-100 flex-shrink-0">
<ImageWithFallback
src={avatarSrc || ""}
alt={testimonial.name}
className="w-full h-full object-cover"
/>
</div>
<div className="min-w-0">
<h4 className="font-semibold text-black mb-1 text-sm">
{testimonial.name}
</h4>
<p className="text-xs text-gray-600">
{testimonial.role}
</p>
{testimonial.company && (
<p className="text-xs text-gray-500 font-medium">
{testimonial.company}
</p>
)}
</div>
</div>
{/* Star Rating - Top Right */}
<div className="flex gap-1">
{[1, 2, 3, 4, 5].map((star) => (
<Star
key={star}
size={14}
className={star <= testimonial.rating ? 'fill-current text-yellow-400' : 'text-gray-300'}
/>
))}
</div>
</div>
{/* Quote Section - Compact Typography */}
<blockquote className="flex-1 mb-4">
<div className="text-sm leading-relaxed text-black relative">
<span className="text-4xl absolute -top-1 -left-1 leading-none opacity-20 text-blue-600">
"
</span>
<span className="relative z-10">
{testimonial.quote}
</span>
</div>
</blockquote>
{/* Bottom Accent Line */}
<div className="w-12 h-1 rounded-full bg-blue-600" />
</div>
)}
</motion.div>
);
}
export function TestimonialsSection({
customTestimonials,
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?: Testimonial[];
title?: string;
subtitle?: string;
tagText?: string;
}) {
const [isVideoModalOpen, setIsVideoModalOpen] = useState(false);
const [currentVideoUrl, setCurrentVideoUrl] = useState("");
const [canScrollLeft, setCanScrollLeft] = useState(false);
const [canScrollRight, setCanScrollRight] = useState(true);
const [isDragging, setIsDragging] = useState(false);
const scrollContainerRef = useRef<HTMLDivElement>(null);
// Use custom testimonials if provided, otherwise use default
const testimonialsData = customTestimonials || defaultTestimonialsData;
// Handle scroll state
const handleScroll = () => {
if (scrollContainerRef.current) {
const { scrollLeft, scrollWidth, clientWidth } = scrollContainerRef.current;
setCanScrollLeft(scrollLeft > 0);
setCanScrollRight(scrollLeft < scrollWidth - clientWidth - 10);
}
};
// Scroll to direction - Updated for compact card width
const scrollToDirection = (direction: 'left' | 'right') => {
if (scrollContainerRef.current) {
const scrollAmount = 390; // Adjusted for compact card width (350px + 32px gap)
const currentScroll = scrollContainerRef.current.scrollLeft;
const targetScroll = direction === 'left'
? Math.max(0, currentScroll - scrollAmount)
: currentScroll + scrollAmount;
scrollContainerRef.current.scrollTo({
left: targetScroll,
behavior: 'smooth'
});
}
};
// Mouse drag functionality
const [dragStart, setDragStart] = useState({ x: 0, scrollLeft: 0 });
const handleMouseDown = (e: React.MouseEvent) => {
setIsDragging(true);
if (scrollContainerRef.current) {
setDragStart({
x: e.pageX,
scrollLeft: scrollContainerRef.current.scrollLeft
});
}
};
const handleMouseMove = (e: React.MouseEvent) => {
if (!isDragging || !scrollContainerRef.current) return;
e.preventDefault();
const x = e.pageX;
const walk = (x - dragStart.x) * 2;
scrollContainerRef.current.scrollLeft = dragStart.scrollLeft - walk;
};
const handleMouseUp = () => {
setIsDragging(false);
};
// Touch functionality
const [touchStart, setTouchStart] = useState({ x: 0, scrollLeft: 0 });
const handleTouchStart = (e: React.TouchEvent) => {
if (scrollContainerRef.current) {
setTouchStart({
x: e.touches[0].clientX,
scrollLeft: scrollContainerRef.current.scrollLeft
});
}
};
const handleTouchMove = (e: React.TouchEvent) => {
if (!scrollContainerRef.current) return;
const x = e.touches[0].clientX;
const walk = (x - touchStart.x) * 2;
scrollContainerRef.current.scrollLeft = touchStart.scrollLeft - walk;
};
const handleTouchEnd = () => {
// Touch ended
};
const handlePlayVideo = (videoUrl: string) => {
setCurrentVideoUrl(videoUrl);
setIsVideoModalOpen(true);
};
const handleCloseModal = () => {
setIsVideoModalOpen(false);
setCurrentVideoUrl("");
};
// Initialize scroll state and keyboard navigation
useEffect(() => {
const timer = setTimeout(() => {
handleScroll();
}, 100);
// Keyboard navigation support
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'ArrowLeft' && canScrollLeft) {
e.preventDefault();
scrollToDirection('left');
} else if (e.key === 'ArrowRight' && canScrollRight) {
e.preventDefault();
scrollToDirection('right');
}
};
document.addEventListener('keydown', handleKeyDown);
return () => {
clearTimeout(timer);
document.removeEventListener('keydown', handleKeyDown);
};
}, [canScrollLeft, canScrollRight]);
return (
<section
className="py-24"
style={{ backgroundColor: '#FFFFFF' }}
aria-labelledby="testimonials-heading"
>
<div className="max-w-7xl mx-auto section-margin-x" data-layout="testimonials-v1">
{/* Section Header */}
<div className="text-center mb-16">
{/* Branded Tag */}
<div className="flex justify-center">
<BrandedTag text={tagText} />
</div>
<h2 id="testimonials-heading" className="text-h2 mb-6">{title}</h2>
<p className="text-body-lg text-muted max-w-3xl mx-auto">{subtitle}</p>
</div>
{/* Testimonials Cards Area */}
<div className="relative">
{/* Compact Navigation Controls */}
<div className="flex justify-end gap-3 mb-8 relative z-20">
<button
className={`w-12 h-12 flex items-center justify-center rounded-lg border-2 transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 ${
!canScrollLeft
? 'opacity-40 cursor-not-allowed bg-gray-50 border-gray-200'
: 'bg-white border-blue-600 hover:bg-blue-600 hover:text-white'
}`}
onClick={() => scrollToDirection('left')}
disabled={!canScrollLeft}
aria-label="Scroll testimonials left"
>
<ChevronLeft size={18} />
</button>
<button
className={`w-12 h-12 flex items-center justify-center rounded-lg border-2 transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 ${
!canScrollRight
? 'opacity-40 cursor-not-allowed bg-gray-50 border-gray-200'
: 'bg-white border-blue-600 hover:bg-blue-600 hover:text-white'
}`}
onClick={() => scrollToDirection('right')}
disabled={!canScrollRight}
aria-label="Scroll testimonials right"
>
<ChevronRight size={18} />
</button>
</div>
{/* Cards Container with Enhanced Design */}
<div className="relative">
{/* Scrollable Cards Container */}
<div
ref={scrollContainerRef}
className={`${isDragging ? 'cursor-grabbing' : 'cursor-grab'} flex overflow-x-auto gap-6 py-4 pb-6 scrollbar-hide`}
onScroll={handleScroll}
onMouseDown={handleMouseDown}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
onMouseLeave={handleMouseUp}
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onTouchEnd={handleTouchEnd}
style={{
userSelect: 'none',
WebkitUserSelect: 'none',
msUserSelect: 'none',
MozUserSelect: 'none',
scrollbarWidth: 'none',
msOverflowStyle: 'none',
scrollBehavior: 'smooth'
}}
>
<div className="flex gap-6 px-2">
{testimonialsData.map((testimonial, index) => (
<TestimonialCard
key={testimonial.id || index}
testimonial={testimonial}
onPlayVideo={handlePlayVideo}
/>
))}
</div>
</div>
{/* Left Side White Fade Overlay */}
<div
className="absolute top-0 left-0 bottom-0 w-20 pointer-events-none z-5"
style={{
background: 'linear-gradient(to right, #FFFFFF, transparent)'
}}
/>
{/* Right Side Fade Gradient Overlay - Now properly positioned */}
<div
className="absolute top-0 right-0 bottom-0 w-20 pointer-events-none z-5"
style={{
background: 'linear-gradient(to right, transparent, #FFFFFF)'
}}
/>
</div>
</div>
</div>
{/* Video Modal */}
<VideoModal
isOpen={isVideoModalOpen}
onClose={handleCloseModal}
videoUrl={currentVideoUrl}
/>
<style>{`
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
/* Enhanced testimonial card animations */
.testimonial-card {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.testimonial-card:hover {
transform: translateY(-4px);
}
`}</style>
</section>
);
}

View File

@@ -0,0 +1,66 @@
interface StatItemProps {
value: string;
label: string;
}
function StatItem({ value, label }: StatItemProps) {
return (
<div className="text-center">
{/* Large Numeric Value */}
<div className="mb-4">
<span
className="text-6xl font-bold tracking-tight max-lg:text-5xl max-md:text-4xl"
style={{ color: 'var(--color-brand-primary)' }}
>
{value}
</span>
</div>
{/* Short Bold Title */}
<h3
className="text-lg font-semibold max-lg:text-base max-md:text-sm"
style={{ color: 'var(--color-brand-black)' }}
>
{label}
</h3>
</div>
);
}
export function TrustStatsSection() {
const stats = [
{
value: "27,000+",
label: "Leaders Developed"
},
{
value: "150+",
label: "Corporate Clients"
},
{
value: "20+",
label: "Countries Served"
}
];
return (
<section
className="py-20 px-[200px] max-lg:px-8 max-md:py-16"
style={{ backgroundColor: 'var(--color-brand-bg-white)' }}
>
{/* Centered content block with max-width: 1200px */}
<div className="max-w-[1200px] mx-auto">
{/* 3 Equal Columns Grid - Desktop / Stack Vertically - Mobile */}
<div className="grid grid-cols-3 gap-12 max-lg:gap-8 max-md:grid-cols-1 max-md:gap-16">
{stats.map((stat, index) => (
<StatItem
key={index}
value={stat.value}
label={stat.label}
/>
))}
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,397 @@
import { ArrowRight, ChevronLeft, ChevronRight, ArrowUpRight } from "lucide-react";
import { useState, useRef, useEffect } from "react";
import svgPaths from "../imports/svg-ec87ex3oms";
import { PrimaryCTAButton } from "./PrimaryCTAButton";
import { navigateTo } from "./Router";
import { sharedWebinarsData, type WebinarData } from "../data/webinarsData";
// WebinarCard Component with unified data structure and navigation
interface WebinarCardProps {
webinar: WebinarData;
}
function WebinarCard({ webinar }: WebinarCardProps) {
const handleCardClick = () => {
// All webinar cards now navigate to the same route for consistency
navigateTo(`/webinar/${webinar.slug}`);
};
const handleKeyDown = (event: React.KeyboardEvent) => {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
handleCardClick();
}
};
// Format date for display
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleDateString('en-US', {
month: 'long',
day: 'numeric',
year: 'numeric'
});
};
// Get status badge styling
const getStatusBadge = () => {
switch (webinar.status) {
case 'live':
return (
<span className="px-3 py-1 text-xs font-semibold text-white bg-red-600 rounded-full animate-pulse">
LIVE
</span>
);
case 'upcoming':
return (
<span className="px-3 py-1 text-xs font-semibold text-white bg-blue-600 rounded-full">
UPCOMING
</span>
);
case 'recorded':
return (
<span className="px-3 py-1 text-xs font-semibold text-white bg-green-600 rounded-full">
RECORDED
</span>
);
default:
return null;
}
};
// Get action text based on status
const getActionText = () => {
switch (webinar.status) {
case 'live':
return 'Join Now';
case 'upcoming':
return 'Register';
case 'recorded':
return 'Watch Recording';
default:
return 'Learn More';
}
};
return (
<div
className="flex-shrink-0 w-80 bg-white rounded-lg shadow-lg overflow-hidden cursor-pointer transition-all duration-300 hover:shadow-xl hover:transform hover:-translate-y-2 group"
onClick={handleCardClick}
onKeyDown={handleKeyDown}
tabIndex={0}
role="button"
aria-label={`View webinar: ${webinar.title}`}
style={{
fontFamily: 'var(--font-family-base)'
}}
>
{/* Image Container */}
<div className="relative h-48 overflow-hidden">
<img
src={webinar.thumbnail}
alt={webinar.title}
className="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105"
/>
{/* Status Badge */}
<div className="absolute top-4 left-4">
{getStatusBadge()}
</div>
{/* Featured Badge */}
{webinar.featured && (
<div className="absolute top-4 right-4">
<span className="px-3 py-1 text-xs font-semibold text-yellow-800 bg-yellow-100 rounded-full border border-yellow-200">
Featured
</span>
</div>
)}
{/* Hover Overlay */}
<div className="absolute inset-0 bg-black bg-opacity-40 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center">
<div className="text-white text-center">
<ArrowUpRight className="w-8 h-8 mx-auto mb-2" />
<span className="text-sm font-medium">View Details</span>
</div>
</div>
</div>
{/* Content */}
<div className="p-6">
<h3
className="text-lg font-semibold mb-3 text-gray-900 group-hover:text-blue-600 transition-colors duration-200 line-clamp-2"
style={{
color: 'var(--color-brand-black)',
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
lineHeight: 'var(--line-height-h4)'
}}
>
{webinar.title}
</h3>
<div className="space-y-2 mb-4">
<p
className="text-sm text-muted flex items-center"
style={{
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-small)'
}}
>
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg>
{webinar.presenter}
</p>
<p
className="text-sm text-muted flex items-center"
style={{
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-small)'
}}
>
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
{formatDate(webinar.date)} at {webinar.time} {webinar.timezone}
</p>
<div className="flex items-center justify-between">
<p
className="text-sm text-muted flex items-center"
style={{
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-small)'
}}
>
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
{webinar.duration}
</p>
<p
className="text-sm text-muted flex items-center"
style={{
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-small)'
}}
>
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
{webinar.attendees}
</p>
</div>
</div>
{/* Action Indicator - Consistent with status */}
<div className="flex items-center justify-between">
<span
className="text-sm font-medium group-hover:text-blue-600 transition-colors duration-200"
style={{
color: 'var(--color-primary)',
fontFamily: 'var(--font-family-base)',
fontSize: 'var(--font-small)',
fontWeight: 'var(--font-weight-subhead)'
}}
>
{getActionText()}
</span>
<ArrowRight className="w-4 h-4 text-blue-600 group-hover:translate-x-1 transition-transform duration-200" />
</div>
</div>
</div>
);
}
export function UpcomingWebinarsSection() {
const [canScrollLeft, setCanScrollLeft] = useState(false);
const [canScrollRight, setCanScrollRight] = useState(true);
const carouselRef = useRef<HTMLDivElement>(null);
const checkScrollButtons = () => {
if (carouselRef.current) {
const { scrollLeft, scrollWidth, clientWidth } = carouselRef.current;
setCanScrollLeft(scrollLeft > 0);
setCanScrollRight(scrollLeft < scrollWidth - clientWidth - 1);
}
};
const scrollLeft = () => {
if (carouselRef.current) {
carouselRef.current.scrollBy({ left: -340, behavior: 'smooth' });
}
};
const scrollRight = () => {
if (carouselRef.current) {
carouselRef.current.scrollBy({ left: 340, behavior: 'smooth' });
}
};
useEffect(() => {
const carousel = carouselRef.current;
if (carousel) {
carousel.addEventListener('scroll', checkScrollButtons);
checkScrollButtons(); // Initial check
return () => carousel.removeEventListener('scroll', checkScrollButtons);
}
}, []);
return (
<div
className="py-20"
style={{ backgroundColor: '#FFFFFF' }}
>
<div className="section-margin-x">
<div className="grid grid-cols-12 gap-16 items-start">
{/* Left Column - Content */}
<div className="col-span-12 lg:col-span-5">
{/* Heading */}
<h2
className="text-4xl leading-tight mb-6"
style={{
color: 'var(--color-brand-black)',
fontFamily: 'var(--font-family-brand)',
fontWeight: '700'
}}
>
Upcoming Corporate Webinars
</h2>
{/* Description */}
<p
className="text-lg leading-relaxed mb-8"
style={{
color: 'var(--color-brand-black)',
fontFamily: 'var(--font-family-brand)',
fontWeight: '400'
}}
>
Join live sessions led by leadership experts designed for professionals looking to elevate strategic thinking, decision-making, and people leadership.
</p>
{/* Navigation Controls */}
<div className="flex gap-3 mb-8">
<button
className={`w-12 h-12 flex items-center justify-center rounded-lg border-2 transition-all duration-300 ${
!canScrollLeft
? 'opacity-40 cursor-not-allowed bg-gray-100 border-gray-300'
: 'bg-white hover:scale-105 hover:shadow-lg active:scale-95'
}`}
onClick={scrollLeft}
disabled={!canScrollLeft}
aria-label="Previous webinar"
style={{
fontFamily: 'var(--font-family-brand)',
borderColor: !canScrollLeft ? '#D1D5DB' : '#04045B',
backgroundColor: !canScrollLeft ? '#F3F4F6' : 'white'
}}
onMouseEnter={(e) => {
if (!canScrollLeft) return;
e.currentTarget.style.backgroundColor = '#04045B';
const icon = e.currentTarget.querySelector('svg');
if (icon) icon.style.color = 'white';
}}
onMouseLeave={(e) => {
if (!canScrollLeft) return;
e.currentTarget.style.backgroundColor = 'white';
const icon = e.currentTarget.querySelector('svg');
if (icon) icon.style.color = '#04045B';
}}
>
<ChevronLeft
size={20}
style={{
color: !canScrollLeft ? '#9CA3AF' : '#04045B',
transition: 'color 0.3s ease'
}}
strokeWidth={2.5}
/>
</button>
<button
className={`w-12 h-12 flex items-center justify-center rounded-lg border-2 transition-all duration-300 ${
!canScrollRight
? 'opacity-40 cursor-not-allowed bg-gray-100 border-gray-300'
: 'bg-white hover:scale-105 hover:shadow-lg active:scale-95'
}`}
onClick={scrollRight}
disabled={!canScrollRight}
aria-label="Next webinar"
style={{
fontFamily: 'var(--font-family-brand)',
borderColor: !canScrollRight ? '#D1D5DB' : '#04045B',
backgroundColor: !canScrollRight ? '#F3F4F6' : 'white'
}}
onMouseEnter={(e) => {
if (!canScrollRight) return;
e.currentTarget.style.backgroundColor = '#04045B';
const icon = e.currentTarget.querySelector('svg');
if (icon) icon.style.color = 'white';
}}
onMouseLeave={(e) => {
if (!canScrollRight) return;
e.currentTarget.style.backgroundColor = 'white';
const icon = e.currentTarget.querySelector('svg');
if (icon) icon.style.color = '#04045B';
}}
>
<ChevronRight
size={20}
style={{
color: !canScrollRight ? '#9CA3AF' : '#04045B',
transition: 'color 0.3s ease'
}}
strokeWidth={2.5}
/>
</button>
</div>
{/* CTA Button - Navigate to main webinars page */}
<PrimaryCTAButton
text="Explore All"
onClick={() => navigateTo('/webinars')}
ariaLabel="Explore all upcoming webinars"
/>
</div>
{/* Right Column - Carousel */}
<div className="col-span-12 lg:col-span-7">
<div className="relative">
{/* Carousel Container */}
<div
ref={carouselRef}
className="flex gap-6 overflow-x-hidden scroll-smooth"
style={{
scrollbarWidth: 'none',
msOverflowStyle: 'none'
}}
>
{/* Use shared webinar data for consistency */}
{sharedWebinarsData.map((webinar) => (
<WebinarCard key={webinar.id} webinar={webinar} />
))}
</div>
{/* Fade Gradient Overlay */}
<div
className="absolute top-0 right-0 bottom-0 w-16 pointer-events-none"
style={{
background: 'linear-gradient(to right, transparent, #FFFFFF)'
}}
/>
</div>
</div>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,829 @@
import React, { useState } from "react";
import { motion } from "motion/react";
import {
Building,
Users,
Presentation,
Coffee,
Play,
Calendar,
ArrowRight,
Eye,
X,
ChevronLeft,
ChevronRight
} from "lucide-react";
import { ImageWithFallback } from "./figma/ImageWithFallback";
import { BrandedTag } from "./about/BrandedTag";
import { PrimaryCTAButton } from "./PrimaryCTAButton";
import { Button } from "./ui/button";
import { Input } from "./ui/input";
import { Label } from "./ui/label";
import { Textarea } from "./ui/textarea";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select";
import { navigateTo } from "./Router";
// Calendar helper functions
const getDaysInMonth = (date: Date) => {
return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
};
const getFirstDayOfMonth = (date: Date) => {
return new Date(date.getFullYear(), date.getMonth(), 1).getDay();
};
const formatDate = (date: Date) => {
return date.toISOString().split('T')[0];
};
const isDateAvailable = (date: Date) => {
const today = new Date();
today.setHours(0, 0, 0, 0);
const selectedDate = new Date(date);
selectedDate.setHours(0, 0, 0, 0);
// Available if it's today or in the future, and not a Sunday
return selectedDate >= today && selectedDate.getDay() !== 0;
};
const facilities = [
{
id: 1,
name: "Campus",
description: "Our flagship campus offers comprehensive leadership development with state-of-the-art facilities.",
icon: Building,
image: "https://images.unsplash.com/photo-1497366216548-37526070297c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1200&q=80",
videoUrl: "https://www.youtube.com/embed/dQw4w9WgXcQ", // Virtual tour video
capacity: "50-80",
features: ["State-of-the-art facilities", "Comprehensive programs", "Modern infrastructure"]
},
{
id: 2,
name: "Classroom",
description: "Interactive learning environment with flexible seating and cutting-edge educational technology.",
icon: Users,
image: "https://images.unsplash.com/photo-1562774053-701939374585?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1200&q=80",
videoUrl: "https://www.youtube.com/embed/dQw4w9WgXcQ", // Virtual tour video
capacity: "20-30",
features: ["Interactive learning", "Flexible seating", "Educational technology"]
},
{
id: 3,
name: "Auditorium",
description: "Premier presentation venue with theater-style seating and professional AV systems for impactful presentations.",
icon: Presentation,
image: "https://images.unsplash.com/photo-1540575467063-178a50c2df87?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1200&q=80",
videoUrl: "https://www.youtube.com/embed/dQw4w9WgXcQ", // Virtual tour video
capacity: "100-150",
features: ["Theater-style seating", "Professional AV systems", "Impactful presentations"]
},
{
id: 4,
name: "Boardroom",
description: "Executive meeting space designed for strategic discussions and high-level decision making with premium amenities.",
icon: Coffee,
image: "https://images.unsplash.com/photo-1497366754035-f200968a6e72?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1200&q=80",
videoUrl: "https://www.youtube.com/embed/dQw4w9WgXcQ", // Virtual tour video
capacity: "8-15",
features: ["Executive meeting space", "Strategic discussions", "Premium amenities"]
}
];
interface BookingFormData {
companyName: string;
contactName: string;
email: string;
phone: string;
role: string;
teamSize: string;
facilityType: string;
preferredDate: string;
additionalRequirements: string;
}
interface FacilityCardProps {
facility: typeof facilities[0];
index: number;
onBookNow: (facility: typeof facilities[0]) => void;
}
function FacilityCard({ facility, index, onBookNow }: FacilityCardProps) {
const IconComponent = facility.icon;
return (
<motion.div
className="relative group h-full overflow-hidden"
initial={{ opacity: 0, y: 60 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, delay: index * 0.15 }}
viewport={{ once: true, margin: "-50px" }}
>
{/* Background Image - Full Height */}
<div className="absolute inset-0">
<ImageWithFallback
src={facility.image}
alt={facility.name}
className="w-full h-full object-cover transition-transform duration-700 ease-out group-hover:scale-110"
/>
{/* Dark overlay with hover effect */}
<div className="absolute inset-0 bg-black/60 transition-all duration-500 ease-out group-hover:bg-black/40" />
</div>
{/* Content - Positioned at bottom of card */}
<div className="relative z-10 h-full flex flex-col justify-end p-8 max-lg:p-6">
{/* Icon */}
<div className="flex justify-center mb-4">
<div
className="w-16 h-16 rounded-2xl flex items-center justify-center bg-white/20 backdrop-blur-sm border border-white/30"
>
<IconComponent
className="w-8 h-8 text-white"
/>
</div>
</div>
{/* Title */}
<h3 className="text-3xl font-bold mb-3 text-white max-lg:text-2xl text-center">
{facility.name}
</h3>
{/* Description */}
<p className="text-white/90 leading-relaxed mb-6 text-base max-lg:text-sm text-center max-lg:mb-5">
{facility.description}
</p>
{/* Book Now Button */}
<div className="flex justify-center">
<div className="hero-slide-button">
<PrimaryCTAButton
text="Book Now"
onClick={() => onBookNow(facility)}
ariaLabel={`Book ${facility.name} now`}
/>
</div>
</div>
</div>
</motion.div>
);
}
// Modal Component for Virtual Tour and Booking
function BookingModal({
facility,
isOpen,
onClose
}: {
facility: typeof facilities[0] | null;
isOpen: boolean;
onClose: () => void;
}) {
const [bookingForm, setBookingForm] = useState<BookingFormData>({
companyName: '',
contactName: '',
email: '',
phone: '',
role: '',
teamSize: '',
facilityType: facility?.name || '',
preferredDate: '',
additionalRequirements: ''
});
// Calendar state
const [currentMonth, setCurrentMonth] = useState(new Date());
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
// Lock body scroll when modal is open
React.useEffect(() => {
if (isOpen) {
document.body.style.overflow = 'hidden';
document.body.style.paddingRight = '15px'; // Prevent layout shift from scrollbar
} else {
document.body.style.overflow = '';
document.body.style.paddingRight = '';
}
// Cleanup on unmount or when modal closes
return () => {
document.body.style.overflow = '';
document.body.style.paddingRight = '';
};
}, [isOpen]);
const handleFormSubmit = (e: React.FormEvent) => {
e.preventDefault();
console.log('Booking form submitted:', bookingForm);
// Here you would typically send the form data to your backend
alert('Booking request submitted successfully! We will contact you soon.');
onClose();
};
const updateFormField = (field: keyof BookingFormData, value: string) => {
setBookingForm(prev => ({ ...prev, [field]: value }));
};
// Calendar functions
const handleDateSelect = (date: Date) => {
if (isDateAvailable(date)) {
setSelectedDate(date);
updateFormField('preferredDate', formatDate(date));
}
};
const navigateMonth = (direction: 'prev' | 'next') => {
setCurrentMonth(prev => {
const newMonth = new Date(prev);
if (direction === 'prev') {
newMonth.setMonth(prev.getMonth() - 1);
} else {
newMonth.setMonth(prev.getMonth() + 1);
}
return newMonth;
});
};
const renderCalendar = () => {
const daysInMonth = getDaysInMonth(currentMonth);
const firstDay = getFirstDayOfMonth(currentMonth);
const days = [];
const monthNames = [
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
];
const dayNames = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
// Empty cells for days before the first day of the month
for (let i = 0; i < firstDay; i++) {
days.push(<div key={`empty-${i}`} className="h-6" />);
}
// Days of the month
for (let day = 1; day <= daysInMonth; day++) {
const date = new Date(currentMonth.getFullYear(), currentMonth.getMonth(), day);
const isAvailable = isDateAvailable(date);
const isSelected = selectedDate &&
date.getFullYear() === selectedDate.getFullYear() &&
date.getMonth() === selectedDate.getMonth() &&
date.getDate() === selectedDate.getDate();
days.push(
<button
key={day}
type="button"
onClick={() => handleDateSelect(date)}
disabled={!isAvailable}
className={`
h-6 w-6 rounded text-xs font-medium transition-all duration-200 flex items-center justify-center
${isSelected
? 'bg-primary text-white shadow-sm'
: isAvailable
? 'hover:bg-blue-50 hover:text-primary text-gray-700'
: 'text-gray-300 cursor-not-allowed'
}
`}
style={{
backgroundColor: isSelected ? 'var(--color-primary)' : undefined,
color: isSelected ? 'white' : undefined
}}
>
{day}
</button>
);
}
return (
<div className="bg-white rounded-lg border border-gray-200 p-3">
{/* Calendar Header */}
<div className="flex items-center justify-between mb-3">
<button
type="button"
onClick={() => navigateMonth('prev')}
className="p-1 rounded hover:bg-gray-100 transition-colors"
>
<ChevronLeft className="w-3 h-3 text-gray-600" />
</button>
<h4 className="text-sm font-semibold text-gray-900">
{monthNames[currentMonth.getMonth()]} {currentMonth.getFullYear()}
</h4>
<button
type="button"
onClick={() => navigateMonth('next')}
className="p-1 rounded hover:bg-gray-100 transition-colors"
>
<ChevronRight className="w-3 h-3 text-gray-600" />
</button>
</div>
{/* Day Names */}
<div className="grid grid-cols-7 gap-1 mb-2">
{dayNames.map((day, index) => (
<div key={`day-${index}`} className="h-6 flex items-center justify-center">
<span className="text-xs font-medium text-gray-500">{day}</span>
</div>
))}
</div>
{/* Calendar Grid */}
<div className="grid grid-cols-7 gap-1 mb-3">
{days}
</div>
{/* Calendar Footer - Compact */}
<div className="pt-2 border-t border-gray-200">
<div className="flex items-center justify-center gap-3 text-xs text-gray-500">
<div className="flex items-center gap-1">
<div className="w-2 h-2 rounded-full bg-primary"></div>
<span>Selected</span>
</div>
<div className="flex items-center gap-1">
<div className="w-2 h-2 rounded-full border border-gray-300"></div>
<span>Available</span>
</div>
</div>
</div>
</div>
);
};
if (!isOpen || !facility) return null;
return (
<div
className="fixed inset-0 bg-black/60 flex items-center justify-center p-2 lg:p-4 z-popup-modal virtual-space-modal-overlay"
onClick={onClose}
>
<div
className="bg-white rounded-xl lg:rounded-2xl max-w-5xl w-full h-[85vh] overflow-hidden virtual-space-modal-container flex flex-col"
onClick={(e) => e.stopPropagation()}
>
{/* Modal Header - Compact */}
<div
className="flex items-center justify-between p-4 lg:p-6 border-b flex-shrink-0"
style={{ backgroundColor: 'rgba(4, 4, 91, 0.02)' }}
>
<div className="flex items-center gap-3 lg:gap-4">
<div
className="w-10 h-10 lg:w-12 lg:h-12 rounded-lg flex items-center justify-center"
style={{ backgroundColor: 'var(--color-primary)' }}
>
<facility.icon className="w-5 h-5 lg:w-6 lg:h-6 text-white" />
</div>
<div>
<h2 className="text-body lg:text-subhead mb-1">
{facility.name} Virtual Tour & Booking
</h2>
<p className="text-small text-muted">
Capacity: {facility.capacity} people
</p>
</div>
</div>
<Button
variant="ghost"
size="sm"
onClick={onClose}
className="rounded-full w-8 h-8 lg:w-10 lg:h-10 p-0 hover:bg-gray-100"
>
<X className="w-4 h-4 lg:w-5 lg:h-5" />
</Button>
</div>
{/* Modal Content - Side by Side Layout No Scroll */}
<div className="grid grid-cols-1 lg:grid-cols-2 flex-1 min-h-0">
{/* Left Side - Virtual Tour */}
<div className="p-3 lg:p-6 border-r border-gray-100 flex flex-col min-h-0">
<div className="flex flex-col h-full space-y-2 lg:space-y-3">
{/* Video Section - Compact */}
<div className="flex-shrink-0">
<div className="flex items-center gap-2 mb-2">
<Play className="w-4 h-4 text-primary" />
<h3 className="text-small lg:text-body font-semibold">Virtual Tour</h3>
</div>
{/* Virtual Tour Container - Developer-Ready for 360 Viewer or Video */}
<div className="aspect-video rounded-lg overflow-hidden bg-gray-100 shadow-md relative">
{/*
DEVELOPER NOTE: Replace this container with your preferred 360 viewer
Popular options:
- A-Frame (https://aframe.io/) for WebXR 360 content
- Three.js with 360 photo/video support
- Pannellum (https://pannellum.org/) for 360 photos
- Krpano (https://krpano.com/) for advanced 360 tours
- React 360 (https://facebook.github.io/react-360/)
Current implementation: Fallback video iframe
Replace the entire div below with your 360 viewer component
*/}
<div
id={`virtual-tour-container-${facility.id}`}
className="w-full h-full relative"
data-facility-id={facility.id}
data-facility-name={facility.name}
data-tour-type="360-viewer" // Change to "video" for video fallback
>
{/* Fallback: Video iframe - Replace this entire section with 360 viewer */}
<iframe
src={facility.videoUrl}
title={`${facility.name} Virtual Tour`}
className="w-full h-full"
allowFullScreen
frameBorder="0"
/>
{/* 360 Viewer Placeholder - Remove iframe above and uncomment/implement below */}
{/*
Example A-Frame 360 implementation:
<a-scene
embedded
style={{width: '100%', height: '100%'}}
vr-mode-ui="enabled: false"
>
<a-sky src={facility.panoramaUrl || facility.image} />
<a-camera wasd-controls-enabled="false" look-controls="enabled: true" />
</a-scene>
*/}
{/* Alternative: Custom 360 Photo Viewer Container */}
{/*
<div className="w-full h-full" id={`pannellum-${facility.id}`}>
// Pannellum or other 360 viewer initialization
</div>
*/}
</div>
{/* Interactive Controls Overlay (optional) */}
<div className="absolute bottom-2 left-2 right-2 flex justify-between items-center pointer-events-none">
<div className="bg-black/20 backdrop-blur-sm rounded px-2 py-1">
<span className="text-white text-xs">360° Virtual Tour</span>
</div>
<div className="bg-black/20 backdrop-blur-sm rounded px-2 py-1">
<span className="text-white text-xs">Click & Drag to Explore</span>
</div>
</div>
</div>
</div>
{/* Compact Info Section */}
<div className="flex-1 min-h-0 space-y-2 lg:space-y-3">
{/* About - Compact */}
<div className="bg-gray-50 rounded-lg p-2 lg:p-3">
<h4 className="text-small font-semibold mb-1">About This Space</h4>
<p className="text-xs lg:text-small text-muted leading-relaxed line-clamp-2">
{facility.description}
</p>
</div>
{/* Features - Compact */}
<div className="bg-gray-50 rounded-lg p-2 lg:p-3">
<h4 className="text-small font-semibold mb-2">Key Features</h4>
<div className="space-y-1">
{facility.features.slice(0, 3).map((feature, index) => (
<div key={index} className="flex items-center gap-2">
<div
className="w-1.5 h-1.5 rounded-full flex-shrink-0"
style={{ backgroundColor: 'var(--color-primary)' }}
/>
<span className="text-xs lg:text-small">{feature}</span>
</div>
))}
</div>
</div>
{/* Quick Stats - Compact */}
<div className="grid grid-cols-2 gap-2 p-2 lg:p-3 bg-blue-50 rounded-lg">
<div className="text-center">
<div className="text-xs lg:text-small font-semibold text-primary">Capacity</div>
<div className="text-xs lg:text-small text-muted">{facility.capacity}</div>
</div>
<div className="text-center">
<div className="text-xs lg:text-small font-semibold text-primary">Zone</div>
<div className="text-xs lg:text-small text-muted">Premium</div>
</div>
</div>
{/* Action Button - Compact */}
<Button
variant="outline"
onClick={() => navigateTo('/services/learning-facility')}
className="w-full h-8 lg:h-10 text-xs lg:text-small"
>
<Building className="w-3 h-3 lg:w-4 lg:h-4 mr-1" />
View All Facilities
</Button>
</div>
</div>
</div>
{/* Right Side - Booking Form */}
<div className="p-4 lg:p-6 flex flex-col min-h-0 overflow-y-auto">
<form onSubmit={handleFormSubmit} className="flex flex-col h-full">
{/* Form Header */}
<div className="flex items-center gap-3 mb-4 flex-shrink-0">
<Calendar className="w-5 h-5 text-primary" />
<h3 className="text-subhead">Book This Space</h3>
</div>
{/* Form Content with Compact Spacing */}
<div className="flex-1 min-h-0 space-y-4 overflow-y-auto pr-2 virtual-space-modal-scroll">
{/* Company Information Section */}
<div className="space-y-3">
<div className="space-y-1">
<h4 className="text-small font-medium text-primary">Company Information</h4>
<div className="w-10 h-0.5 bg-primary"></div>
</div>
<div className="space-y-2">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-2">
<div>
<Label htmlFor="companyName" className="text-xs font-normal text-black mb-1 block">
Company Name *
</Label>
<Input
id="companyName"
required
value={bookingForm.companyName}
onChange={(e) => updateFormField('companyName', e.target.value)}
placeholder="Company"
className="h-8 text-sm border border-gray-300 rounded focus:border-primary focus:ring-1 focus:ring-primary/30 transition-all duration-200 placeholder:text-gray-400 placeholder:opacity-50"
/>
</div>
<div>
<Label htmlFor="contactName" className="text-xs font-normal text-black mb-1 block">
Contact Person *
</Label>
<Input
id="contactName"
required
value={bookingForm.contactName}
onChange={(e) => updateFormField('contactName', e.target.value)}
placeholder="Name"
className="h-8 text-sm border border-gray-300 rounded focus:border-primary focus:ring-1 focus:ring-primary/30 transition-all duration-200 placeholder:text-gray-400 placeholder:opacity-50"
/>
</div>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-2">
<div>
<Label htmlFor="email" className="text-xs font-normal text-black mb-1 block">
Email Address *
</Label>
<Input
id="email"
type="email"
required
value={bookingForm.email}
onChange={(e) => updateFormField('email', e.target.value)}
placeholder="email@company.com"
className="h-8 text-sm border border-gray-300 rounded focus:border-primary focus:ring-1 focus:ring-primary/30 transition-all duration-200 placeholder:text-gray-400 placeholder:opacity-50"
/>
</div>
<div>
<Label htmlFor="phone" className="text-xs font-normal text-black mb-1 block">
Phone Number *
</Label>
<Input
id="phone"
required
value={bookingForm.phone}
onChange={(e) => updateFormField('phone', e.target.value)}
placeholder="+91 98765 43210"
className="h-8 text-sm border border-gray-300 rounded focus:border-primary focus:ring-1 focus:ring-primary/30 transition-all duration-200 placeholder:text-gray-400 placeholder:opacity-50"
/>
</div>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-2">
<div>
<Label htmlFor="role" className="text-xs font-normal text-black mb-1 block">
Your Role *
</Label>
<Select value={bookingForm.role} onValueChange={(value) => updateFormField('role', value)}>
<SelectTrigger className="h-8 text-sm border border-gray-300 rounded focus:border-primary focus:ring-1 focus:ring-primary/30 transition-all duration-200">
<SelectValue placeholder="Role" className="text-gray-400 opacity-50" />
</SelectTrigger>
<SelectContent>
<SelectItem value="ceo">CEO/Founder</SelectItem>
<SelectItem value="hr-director">HR Director</SelectItem>
<SelectItem value="training-manager">Training Manager</SelectItem>
<SelectItem value="operations-manager">Operations Manager</SelectItem>
<SelectItem value="executive-assistant">Executive Assistant</SelectItem>
<SelectItem value="other">Other</SelectItem>
</SelectContent>
</Select>
</div>
<div>
<Label htmlFor="teamSize" className="text-xs font-normal text-black mb-1 block">
Expected Team Size *
</Label>
<Select value={bookingForm.teamSize} onValueChange={(value) => updateFormField('teamSize', value)}>
<SelectTrigger className="h-8 text-sm border border-gray-300 rounded focus:border-primary focus:ring-1 focus:ring-primary/30 transition-all duration-200">
<SelectValue placeholder="Size" className="text-gray-400 opacity-50" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1-5">1-5 people</SelectItem>
<SelectItem value="6-15">6-15 people</SelectItem>
<SelectItem value="16-30">16-30 people</SelectItem>
<SelectItem value="31-50">31-50 people</SelectItem>
<SelectItem value="50+">50+ people</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</div>
</div>
{/* Booking Details Section */}
<div className="space-y-3">
<div className="space-y-1">
<h4 className="text-small font-medium text-primary">Select Your Date</h4>
<div className="w-10 h-0.5 bg-primary"></div>
</div>
<div className="space-y-3">
{/* Selected Facility Info */}
<div className="bg-blue-50 rounded p-2 border border-blue-100">
<div className="flex items-center gap-2">
<div
className="w-6 h-6 rounded flex items-center justify-center"
style={{ backgroundColor: 'var(--color-primary)' }}
>
<facility.icon className="w-3 h-3 text-white" />
</div>
<div>
<p className="text-sm font-medium text-gray-900">{facility.name}</p>
<p className="text-xs text-gray-600">Capacity: {facility.capacity} people</p>
</div>
</div>
</div>
{/* Calendar Date Selection */}
<div className="space-y-2">
<Label className="text-xs font-normal text-black">
Choose Your Preferred Date *
</Label>
{renderCalendar()}
{selectedDate && (
<div className="mt-2 p-2 bg-green-50 rounded border border-green-200">
<div className="flex items-center gap-2">
<Calendar className="w-3 h-3 text-green-600" />
<span className="text-xs font-medium text-green-800">
Selected: {selectedDate.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric'
})}
</span>
</div>
</div>
)}
</div>
{/* Additional Requirements */}
<div>
<Label htmlFor="additionalRequirements" className="text-xs font-normal text-black mb-1 block">
Additional Requirements
</Label>
<Textarea
id="additionalRequirements"
value={bookingForm.additionalRequirements}
onChange={(e) => updateFormField('additionalRequirements', e.target.value)}
placeholder="Special setup, AV equipment, catering..."
rows={2}
className="text-sm border border-gray-300 rounded focus:border-primary focus:ring-1 focus:ring-primary/30 transition-all duration-200 placeholder:text-gray-400 placeholder:opacity-50 resize-none"
/>
</div>
</div>
</div>
</div>
{/* Form Actions */}
<div className="flex flex-col sm:flex-row gap-2 pt-3 border-t border-gray-200 mt-3 flex-shrink-0">
<Button
type="submit"
disabled={!selectedDate}
className="flex-1 h-9 text-sm font-medium bg-primary hover:bg-primary/90 disabled:bg-gray-300 disabled:cursor-not-allowed text-white border-0 rounded shadow-sm hover:shadow-md transition-all duration-200"
style={{
backgroundColor: selectedDate ? 'var(--color-primary)' : '#d1d5db',
color: 'white'
}}
>
<Calendar className="w-3 h-3 mr-2" />
{selectedDate ? 'Submit Request' : 'Select Date First'}
</Button>
<Button
type="button"
variant="outline"
onClick={onClose}
className="px-4 h-9 text-sm font-normal border border-gray-300 hover:border-gray-400 hover:bg-gray-50 rounded transition-all duration-200"
>
Cancel
</Button>
</div>
</form>
</div>
</div>
</div>
</div>
);
}
export function VirtualSpaceSection() {
const [selectedFacility, setSelectedFacility] = useState<typeof facilities[0] | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const handleBookNow = (facility: typeof facilities[0]) => {
setSelectedFacility(facility);
setIsModalOpen(true);
};
const handleCloseModal = () => {
setIsModalOpen(false);
setSelectedFacility(null);
};
return (
<section className="relative overflow-hidden">
{/* Full-Width Image Section with Overlaid Content */}
<div className="relative h-screen min-h-[600px] max-h-[800px]">
{/* Facility Cards Grid - Single Row, Side by Side */}
<div className="h-full grid grid-cols-4 max-lg:grid-cols-2 max-md:grid-cols-1">
{facilities.map((facility, index) => (
<FacilityCard
key={facility.id}
facility={facility}
index={index}
onBookNow={handleBookNow}
/>
))}
</div>
{/* Overlaid Content - Centered at top of image section */}
<div className="absolute top-0 left-0 right-0 z-20 py-16 max-md:py-12 section-margin-x">
<div className="max-w-4xl mx-auto text-center">
{/* Branded Tag */}
<motion.div
initial={{ opacity: 0, y: -20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
>
<BrandedTag
text="Virtual Learning Environment"
className="justify-center"
variant="white"
/>
</motion.div>
{/* Main Heading */}
<motion.h2
className="text-5xl font-bold leading-tight mb-4 max-lg:text-4xl max-md:text-3xl text-white"
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.2 }}
viewport={{ once: true }}
>
Experience Our Space Virtually
</motion.h2>
{/* Subheading */}
<motion.p
className="text-lg leading-relaxed max-w-2xl mx-auto max-lg:text-base mb-6 text-white/90"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.4 }}
viewport={{ once: true }}
>
Take a virtual walk through our state-of-the-art facility designed to inspire leadership excellence and foster collaborative learning.
</motion.p>
{/* Main CTA Button - Explore Our Space */}
<motion.div
className="flex justify-center"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.6 }}
viewport={{ once: true }}
>
<div className="hero-slide-button">
<PrimaryCTAButton
text="Explore Our Space"
onClick={() => navigateTo('/services/learning-facility')}
ariaLabel="Explore our virtual learning space and facilities"
/>
</div>
</motion.div>
</div>
</div>
{/* Additional overlay for better text readability over images */}
<div className="absolute top-0 left-0 right-0 h-80 bg-gradient-to-b from-black/70 via-black/40 to-transparent z-10" />
</div>
{/* Booking Modal */}
<BookingModal
facility={selectedFacility}
isOpen={isModalOpen}
onClose={handleCloseModal}
/>
</section>
);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,69 @@
import { ArrowRight } from "lucide-react";
import { ImageWithFallback } from "./figma/ImageWithFallback";
import { BrandedTag } from "./about/BrandedTag";
import { PrimaryCTAButton } from "./PrimaryCTAButton";
import { navigateTo } from "./Router";
export function WebcastCTABanner() {
return (
<section className="relative h-[700px] overflow-hidden">
{/* Background Image */}
<div className="absolute inset-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1712903276180-eda90d32c182?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHx2aXJ0dWFsJTIwd2ViaW5hciUyMG9ubGluZSUyMG1lZXRpbmclMjBkaWdpdGFsJTIwcHJlc2VudGF0aW9ufGVufDF8fHx8MTc1NjEzMDY1MHww&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral"
alt="Virtual webinar and online meeting digital presentation"
className="w-full h-full object-cover"
/>
{/* Subtle dark overlay for overall image */}
<div className="absolute inset-0 bg-black/30" />
{/* Gradient overlay for better text readability */}
<div className="absolute inset-0 bg-gradient-to-r from-black/20 via-transparent to-black/60" />
</div>
{/* Content Container */}
<div className="relative h-full flex items-center justify-end section-margin-x">
{/* CTA Content Block */}
<div
className="bg-opacity-95 backdrop-blur-sm rounded-lg p-16 max-w-2xl"
style={{
backgroundColor: 'var(--color-brand-primary)'
}}
>
{/* Branded Tag */}
<BrandedTag text="Join Our Webcasts" variant="white" />
{/* Main Headline */}
<h2
className="text-h2-white mb-8"
>
Want to host your own webcast?
<span
className="italic"
style={{ color: 'var(--color-brand-accent)' }}
>
{" "}Partner with us{" "}
</span>
to share your expertise with our community.
</h2>
{/* CTA Button - Updated to redirect to contact page */}
<PrimaryCTAButton
text="Propose a Webcast"
onClick={() => navigateTo('/contact?topic=webcast')}
ariaLabel="Propose a webcast partnership with KLC"
className="cta-banner-yellow"
/>
{/* Supporting Text */}
<p
className="text-body-white mt-6 opacity-90"
>
Share your leadership insights with our engaged community through expert-led webcasts and interactive sessions.
</p>
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,610 @@
import React from 'react';
import { Button } from './ui/button';
import { Badge } from './ui/badge';
import { Calendar, Clock, Users, Play, Download, ArrowLeft, Share2, BookOpen } from 'lucide-react';
import { navigateTo } from './Router';
import { ImageWithFallback } from './figma/ImageWithFallback';
interface WebcastDetailProps {
params: {
slug: string;
};
}
// Mock webcast data - in a real app, this would come from an API
const webcastData = {
'leadership-in-digital-age': {
id: '1',
title: 'Leadership in the Digital Age: Navigating Change and Innovation',
description: 'Discover how modern leaders can adapt and thrive in an increasingly digital world. This comprehensive webcast covers digital transformation strategies, leading remote teams, and fostering innovation.',
presenter: 'Dr. Sarah Mitchell',
presenterTitle: 'Chief Digital Transformation Officer',
presenterBio: 'Dr. Sarah Mitchell is a renowned expert in digital transformation with over 15 years of experience helping organizations navigate digital change.',
date: '2024-02-15',
time: '2:00 PM EST',
duration: '90 minutes',
attendees: '2,400+',
category: 'Digital Transformation',
tags: ['Leadership', 'Digital Strategy', 'Innovation', 'Change Management'],
thumbnail: 'https://images.unsplash.com/photo-1560472355-536de3962603?w=800&h=400&fit=crop',
status: 'Available',
recordingUrl: '#',
resourcesUrl: '#',
slidesUrl: '#',
keyTakeaways: [
'Understanding the digital leadership mindset',
'Strategies for leading remote and hybrid teams',
'Building a culture of innovation',
'Managing digital transformation initiatives',
'Leveraging technology for competitive advantage'
],
agenda: [
{ time: '2:00 PM', topic: 'Introduction to Digital Leadership' },
{ time: '2:15 PM', topic: 'The Digital Transformation Landscape' },
{ time: '2:45 PM', topic: 'Leading Remote Teams Effectively' },
{ time: '3:15 PM', topic: 'Q&A Session' },
{ time: '3:30 PM', topic: 'Closing Remarks and Next Steps' }
]
},
'building-resilient-teams': {
id: '2',
title: 'Building Resilient Teams: Strategies for Sustainable Performance',
description: 'Learn proven methodologies for creating teams that can withstand challenges and maintain high performance under pressure.',
presenter: 'Marcus Rodriguez',
presenterTitle: 'Director of Organizational Development',
presenterBio: 'Marcus Rodriguez specializes in team dynamics and organizational resilience with experience across Fortune 500 companies.',
date: '2024-02-08',
time: '1:00 PM EST',
duration: '75 minutes',
attendees: '1,850+',
category: 'Team Development',
tags: ['Team Building', 'Resilience', 'Performance', 'Leadership'],
thumbnail: 'https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=800&h=400&fit=crop',
status: 'Available',
recordingUrl: '#',
resourcesUrl: '#',
slidesUrl: '#',
keyTakeaways: [
'Principles of team resilience',
'Building psychological safety',
'Managing team stress and pressure',
'Creating sustainable performance systems',
'Tools for team assessment and development'
],
agenda: [
{ time: '1:00 PM', topic: 'Understanding Team Resilience' },
{ time: '1:20 PM', topic: 'Building Psychological Safety' },
{ time: '1:45 PM', topic: 'Sustainable Performance Strategies' },
{ time: '2:10 PM', topic: 'Interactive Q&A' },
{ time: '2:15 PM', topic: 'Resources and Action Planning' }
]
},
'strategic-decision-making': {
id: '3',
title: 'Strategic Decision Making: Tools and Frameworks for Leaders',
description: 'Master the art of strategic thinking and decision-making with proven frameworks and methodologies used by top executives.',
presenter: 'Dr. Emily Chen',
presenterTitle: 'Strategic Leadership Consultant',
presenterBio: 'Dr. Emily Chen is a strategic leadership consultant who has advised C-suite executives across multiple industries.',
date: '2024-01-25',
time: '3:00 PM EST',
duration: '60 minutes',
attendees: '3,200+',
category: 'Strategy',
tags: ['Strategic Thinking', 'Decision Making', 'Leadership', 'Planning'],
thumbnail: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=800&h=400&fit=crop',
status: 'Available',
recordingUrl: '#',
resourcesUrl: '#',
slidesUrl: '#',
keyTakeaways: [
'Strategic thinking frameworks',
'Decision-making methodologies',
'Risk assessment and management',
'Stakeholder analysis techniques',
'Implementation and monitoring strategies'
],
agenda: [
{ time: '3:00 PM', topic: 'Introduction to Strategic Decision Making' },
{ time: '3:15 PM', topic: 'Framework Deep Dive' },
{ time: '3:35 PM', topic: 'Case Study Analysis' },
{ time: '3:50 PM', topic: 'Q&A and Discussion' },
{ time: '4:00 PM', topic: 'Action Planning' }
]
}
};
export function WebcastDetail({ params }: WebcastDetailProps) {
const webcast = webcastData[params.slug as keyof typeof webcastData];
if (!webcast) {
return (
<div className="min-h-screen flex items-center justify-center" style={{ backgroundColor: '#F7F7FD' }}>
<div className="text-center">
<h1 className="text-h2 mb-4">Webcast Not Found</h1>
<p className="text-body-lg text-muted mb-8">
The webcast you're looking for doesn't exist.
</p>
<Button
onClick={() => navigateTo('/learning/webcast')}
className="brand-button-system"
>
<ArrowLeft className="w-4 h-4 mr-2" />
Back to Webcasts
</Button>
</div>
</div>
);
}
const formattedDate = new Date(webcast.date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
return (
<div style={{ backgroundColor: '#F7F7FD' }}>
{/* Header Section */}
<div className="hero-margin-x py-12">
<div className="max-w-4xl mx-auto">
{/* Back Button */}
<Button
variant="ghost"
onClick={() => navigateTo('/learning/webcast')}
className="mb-6 hover:bg-white/50"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
<ArrowLeft className="w-4 h-4 mr-2" />
Back to Webcasts
</Button>
{/* Webcast Header */}
<div className="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
{/* Webcast Image */}
<div className="aspect-video w-full bg-gray-100 relative">
<ImageWithFallback
src={webcast.thumbnail}
alt={webcast.title}
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-black bg-opacity-40 flex items-center justify-center">
<Button
variant="default"
size="lg"
className="bg-white text-black hover:bg-gray-100"
onClick={() => window.open(webcast.recordingUrl, '_blank')}
>
<Play className="w-6 h-6 mr-2" />
Watch Recording
</Button>
</div>
</div>
{/* Webcast Content */}
<div className="p-8">
{/* Category Badge */}
<Badge
variant="secondary"
className="mb-4"
style={{
backgroundColor: 'rgba(248, 195, 1, 0.1)',
color: 'var(--color-black)',
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
{webcast.category}
</Badge>
{/* Title */}
<h1
className="mb-4"
style={{
fontSize: 'var(--font-h2)',
fontWeight: 'var(--font-weight-h2)',
lineHeight: 'var(--line-height-h2)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{webcast.title}
</h1>
{/* Meta Information */}
<div className="flex flex-wrap gap-6 mb-6 text-muted">
<div className="flex items-center gap-2">
<Calendar className="w-4 h-4" />
<span style={{ fontSize: 'var(--font-body)', fontFamily: 'var(--font-family-base)' }}>
{formattedDate}
</span>
</div>
<div className="flex items-center gap-2">
<Clock className="w-4 h-4" />
<span style={{ fontSize: 'var(--font-body)', fontFamily: 'var(--font-family-base)' }}>
{webcast.duration}
</span>
</div>
<div className="flex items-center gap-2">
<Users className="w-4 h-4" />
<span style={{ fontSize: 'var(--font-body)', fontFamily: 'var(--font-family-base)' }}>
{webcast.attendees} attendees
</span>
</div>
</div>
{/* Description */}
<p
className="mb-8"
style={{
fontSize: 'var(--font-body-lg)',
lineHeight: 'var(--line-height-body-lg)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{webcast.description}
</p>
{/* Action Buttons */}
<div className="flex flex-wrap gap-4">
<Button
onClick={() => window.open(webcast.recordingUrl, '_blank')}
className="brand-button-system"
>
<Play className="w-4 h-4 mr-2" />
Watch Recording
</Button>
<Button
variant="outline"
onClick={() => window.open(webcast.slidesUrl, '_blank')}
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
borderColor: 'var(--color-primary)'
}}
>
<Download className="w-4 h-4 mr-2" />
Download Slides
</Button>
<Button
variant="outline"
onClick={() => window.open(webcast.resourcesUrl, '_blank')}
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
borderColor: 'var(--color-primary)'
}}
>
<BookOpen className="w-4 h-4 mr-2" />
Resources
</Button>
<Button
variant="outline"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
borderColor: 'var(--color-primary)'
}}
>
<Share2 className="w-4 h-4 mr-2" />
Share
</Button>
</div>
</div>
</div>
</div>
</div>
{/* Content Sections */}
<div className="section-margin-x pb-12">
<div className="max-w-4xl mx-auto">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
{/* Main Content */}
<div className="lg:col-span-2 space-y-8">
{/* Presenter Information */}
<div className="bg-white rounded-lg p-6 shadow-sm border border-gray-200">
<h2
className="mb-4"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
About the Presenter
</h2>
<div className="flex items-start gap-4">
<div className="w-16 h-16 bg-gray-200 rounded-full flex items-center justify-center">
<span
className="text-xl font-semibold"
style={{
color: 'var(--color-primary)',
fontFamily: 'var(--font-family-base)'
}}
>
{webcast.presenter.split(' ').map(n => n[0]).join('')}
</span>
</div>
<div>
<h3
className="mb-1"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{webcast.presenter}
</h3>
<p
className="text-muted mb-2"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)'
}}
>
{webcast.presenterTitle}
</p>
<p
style={{
fontSize: 'var(--font-body)',
lineHeight: 'var(--line-height-body)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{webcast.presenterBio}
</p>
</div>
</div>
</div>
{/* Key Takeaways */}
<div className="bg-white rounded-lg p-6 shadow-sm border border-gray-200">
<h2
className="mb-4"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Key Takeaways
</h2>
<ul className="space-y-2">
{webcast.keyTakeaways.map((takeaway, index) => (
<li key={index} className="flex items-start gap-3">
<div
className="w-2 h-2 rounded-full mt-2 flex-shrink-0"
style={{ backgroundColor: 'var(--color-accent)' }}
/>
<span
style={{
fontSize: 'var(--font-body)',
lineHeight: 'var(--line-height-body)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{takeaway}
</span>
</li>
))}
</ul>
</div>
{/* Agenda */}
<div className="bg-white rounded-lg p-6 shadow-sm border border-gray-200">
<h2
className="mb-4"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Agenda
</h2>
<div className="space-y-3">
{webcast.agenda.map((item, index) => (
<div key={index} className="flex items-start gap-4 py-2">
<span
className="text-sm font-medium text-muted min-w-[80px]"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
{item.time}
</span>
<span
style={{
fontSize: 'var(--font-body)',
lineHeight: 'var(--line-height-body)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{item.topic}
</span>
</div>
))}
</div>
</div>
</div>
{/* Sidebar */}
<div className="space-y-6">
{/* Tags */}
<div className="bg-white rounded-lg p-6 shadow-sm border border-gray-200">
<h3
className="mb-4"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Topics Covered
</h3>
<div className="flex flex-wrap gap-2">
{webcast.tags.map((tag, index) => (
<Badge
key={index}
variant="secondary"
style={{
backgroundColor: 'var(--color-bg-light)',
color: 'var(--color-black)',
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
{tag}
</Badge>
))}
</div>
</div>
{/* Quick Actions */}
<div className="bg-white rounded-lg p-6 shadow-sm border border-gray-200">
<h3
className="mb-4"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Quick Actions
</h3>
<div className="space-y-3">
<Button
variant="outline"
className="w-full justify-start"
onClick={() => window.open(webcast.recordingUrl, '_blank')}
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
borderColor: 'var(--color-primary)'
}}
>
<Play className="w-4 h-4 mr-2" />
Watch Recording
</Button>
<Button
variant="outline"
className="w-full justify-start"
onClick={() => window.open(webcast.slidesUrl, '_blank')}
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
borderColor: 'var(--color-primary)'
}}
>
<Download className="w-4 h-4 mr-2" />
Download Slides
</Button>
<Button
variant="outline"
className="w-full justify-start"
onClick={() => window.open(webcast.resourcesUrl, '_blank')}
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
borderColor: 'var(--color-primary)'
}}
>
<BookOpen className="w-4 h-4 mr-2" />
Resources
</Button>
</div>
</div>
{/* Related Webcasts */}
<div className="bg-white rounded-lg p-6 shadow-sm border border-gray-200">
<h3
className="mb-4"
style={{
fontSize: 'var(--font-h4)',
fontWeight: 'var(--font-weight-h4)',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
Related Webcasts
</h3>
<div className="space-y-3">
<Button
variant="ghost"
className="w-full justify-start h-auto p-0"
onClick={() => navigateTo('/learning/webcast/building-resilient-teams')}
>
<div className="text-left">
<div
className="font-medium mb-1"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
Building Resilient Teams
</div>
<div
className="text-sm text-muted"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Team Development
</div>
</div>
</Button>
<Button
variant="ghost"
className="w-full justify-start h-auto p-0"
onClick={() => navigateTo('/learning/webcast/strategic-decision-making')}
>
<div className="text-left">
<div
className="font-medium mb-1"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
Strategic Decision Making
</div>
<div
className="text-sm text-muted"
style={{
fontSize: 'var(--font-small)',
fontFamily: 'var(--font-family-base)'
}}
>
Strategy
</div>
</div>
</Button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}

File diff suppressed because it is too large Load Diff

764
src/components/Webinars.tsx Normal file
View File

@@ -0,0 +1,764 @@
import React, { useState, useRef, useEffect } from 'react';
import { Button } from './ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from './ui/card';
import { Badge } from './ui/badge';
import { Input } from './ui/input';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
import { Slider } from './ui/slider';
import { ImageWithFallback } from './figma/ImageWithFallback';
import { PrimaryCTAButton } from './PrimaryCTAButton';
import { navigateTo } from './Router';
import { sharedWebinarsData, type WebinarData } from '../data/webinarsData';
import { WebcastCTABanner } from './WebcastCTABanner';
import {
Search,
Calendar,
Clock,
Users,
Play,
ArrowRight,
Filter,
Grid,
List,
SortAsc,
Eye,
Star,
ChevronLeft,
ChevronRight,
X
} from 'lucide-react';
export function Webinars() {
const [searchTerm, setSearchTerm] = useState('');
const [selectedCategory, setSelectedCategory] = useState('All Categories');
const [selectedFormat, setSelectedFormat] = useState('All Formats');
const [selectedLevel, setSelectedLevel] = useState('All Levels');
// Updated state for multi-select status pills
const [selectedStatuses, setSelectedStatuses] = useState<string[]>([]);
// Updated state for duration slider (min, max in minutes)
const [durationRange, setDurationRange] = useState([0, 120]);
// Attendee range slider state
const [attendeeRange, setAttendeeRange] = useState([0, 5000]);
const [sortBy, setSortBy] = useState('Most Popular');
const [viewType, setViewType] = useState<'grid' | 'list'>('grid');
const [currentPage, setCurrentPage] = useState(1);
const webinarsPerPage = 6;
const containerRef = useRef<HTMLDivElement>(null);
// Use shared webinars data instead of local mock data
const webinars = sharedWebinarsData;
// Get unique values for filters from shared data
const categories = ['All Categories', ...Array.from(new Set(webinars.map(webinar => webinar.category)))];
const formats = ['All Formats', ...Array.from(new Set(webinars.map(webinar => webinar.format)))];
const levels = ['All Levels', ...Array.from(new Set(webinars.map(webinar => webinar.level)))];
// Status options for pills - updated to match shared data structure
const statusOptions = [
{ value: 'upcoming', label: '📅 Upcoming', color: 'bg-blue-100 text-blue-800 border-blue-200' },
{ value: 'live', label: '🔴 Live', color: 'bg-red-100 text-red-800 border-red-200' },
{ value: 'recorded', label: '▶️ Recorded', color: 'bg-green-100 text-green-800 border-green-200' },
{ value: 'featured', label: '⭐ Featured', color: 'bg-yellow-100 text-yellow-800 border-yellow-200' }
];
const sortOptions = [
{ value: 'Most Popular', label: 'Most Popular' },
{ value: 'newest', label: 'Newest First' },
{ value: 'oldest', label: 'Oldest First' },
{ value: 'title', label: 'Title A-Z' },
{ value: 'duration', label: 'Duration' }
];
// Helper function to convert attendees string to number
const parseAttendees = (attendeesStr: string): number => {
const numStr = attendeesStr.replace(/[^\d]/g, '');
return parseInt(numStr) || 0;
};
// Helper function to convert duration string to minutes
const parseDuration = (durationStr: string): number => {
const numStr = durationStr.replace(/[^\d]/g, '');
return parseInt(numStr) || 0;
};
// Filter and sort webinars
const filteredWebinars = webinars.filter(webinar => {
const matchesSearch = webinar.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
webinar.description.toLowerCase().includes(searchTerm.toLowerCase()) ||
webinar.presenter.toLowerCase().includes(searchTerm.toLowerCase()) ||
webinar.tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase()));
const matchesCategory = selectedCategory === 'All Categories' || webinar.category === selectedCategory;
const matchesFormat = selectedFormat === 'All Formats' || webinar.format === selectedFormat;
const matchesLevel = selectedLevel === 'All Levels' || webinar.level === selectedLevel;
// Updated status filter for multi-select with shared data structure
const matchesStatus = selectedStatuses.length === 0 ||
selectedStatuses.some(status => {
if (status === 'featured') return webinar.featured;
return webinar.status === status;
});
// Duration filter using range
const durationMinutes = parseDuration(webinar.duration);
const matchesDuration = durationMinutes >= durationRange[0] && durationMinutes <= durationRange[1];
// Attendee filter using range
const attendeeCount = parseAttendees(webinar.attendees);
const matchesAttendees = attendeeCount >= attendeeRange[0] && attendeeCount <= attendeeRange[1];
return matchesSearch && matchesCategory && matchesFormat && matchesLevel && matchesStatus && matchesDuration && matchesAttendees;
}).sort((a, b) => {
switch (sortBy) {
case 'newest':
return new Date(b.date).getTime() - new Date(a.date).getTime();
case 'oldest':
return new Date(a.date).getTime() - new Date(b.date).getTime();
case 'title':
return a.title.localeCompare(b.title);
case 'duration':
return parseDuration(b.duration) - parseDuration(a.duration);
default:
return 0;
}
});
// Statistics
const stats = {
total: webinars.length,
upcoming: webinars.filter(w => w.status === 'upcoming').length,
live: webinars.filter(w => w.status === 'live').length,
recorded: webinars.filter(w => w.status === 'recorded').length,
featured: webinars.filter(w => w.featured).length,
categories: new Set(webinars.map(w => w.category)).size
};
// Paginate results
const totalPages = Math.ceil(filteredWebinars.length / webinarsPerPage);
const currentWebinars = filteredWebinars.slice((currentPage - 1) * webinarsPerPage, currentPage * webinarsPerPage);
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
};
const clearAllFilters = () => {
setSearchTerm('');
setSelectedCategory('All Categories');
setSelectedFormat('All Formats');
setSelectedLevel('All Levels');
setSelectedStatuses([]);
setDurationRange([0, 120]);
setAttendeeRange([0, 5000]);
setSortBy('Most Popular');
};
const hasActiveFilters = searchTerm ||
selectedCategory !== 'All Categories' ||
selectedFormat !== 'All Formats' ||
selectedLevel !== 'All Levels' ||
selectedStatuses.length > 0 ||
durationRange[0] !== 0 || durationRange[1] !== 120 ||
attendeeRange[0] !== 0 || attendeeRange[1] !== 5000;
// Status pill toggle function
const toggleStatus = (status: string) => {
setSelectedStatuses(prev =>
prev.includes(status)
? prev.filter(s => s !== status)
: [...prev, status]
);
};
// Updated WebinarCard component that navigates to consistent route
const WebinarCard = ({ webinar }: { webinar: WebinarData }) => {
const handleCardClick = () => {
// Navigate to consistent webinar detail route
navigateTo(`/webinar/${webinar.slug}`);
};
const getStatusBadge = () => {
switch (webinar.status) {
case 'live':
return <Badge className="bg-red-600 text-white animate-pulse">LIVE</Badge>;
case 'upcoming':
return <Badge className="bg-blue-600 text-white">UPCOMING</Badge>;
case 'recorded':
return <Badge className="bg-green-600 text-white">RECORDED</Badge>;
default:
return null;
}
};
const getActionText = () => {
switch (webinar.status) {
case 'live':
return 'Join Now';
case 'upcoming':
return 'Register';
case 'recorded':
return 'Watch Recording';
default:
return 'Learn More';
}
};
if (viewType === 'list') {
return (
<Card
className="mb-4 cursor-pointer transition-all duration-300 hover:shadow-lg hover:transform hover:-translate-y-1"
onClick={handleCardClick}
>
<CardContent className="p-6">
<div className="flex gap-6">
{/* Thumbnail */}
<div className="flex-shrink-0 w-32 h-24 rounded-lg overflow-hidden">
<ImageWithFallback
src={webinar.thumbnail}
alt={webinar.title}
className="w-full h-full object-cover"
/>
</div>
{/* Content */}
<div className="flex-1">
<div className="flex justify-between items-start mb-2">
<div className="flex items-center gap-2">
{getStatusBadge()}
{webinar.featured && (
<Badge className="bg-yellow-100 text-yellow-800">Featured</Badge>
)}
</div>
<span className="text-small text-gray-500">{formatDate(webinar.date)}</span>
</div>
<h3 className="text-h4 mb-2 line-clamp-2">{webinar.title}</h3>
<p className="text-body text-gray-600 mb-3 line-clamp-2">{webinar.description}</p>
<div className="flex items-center justify-between">
<div className="flex items-center gap-4 text-small text-gray-500">
<span className="flex items-center gap-1">
<Users className="w-4 h-4" />
{webinar.presenter}
</span>
<span className="flex items-center gap-1">
<Clock className="w-4 h-4" />
{webinar.duration}
</span>
<span className="flex items-center gap-1">
<Eye className="w-4 h-4" />
{webinar.attendees}
</span>
</div>
<div className="flex items-center gap-2 text-primary font-medium">
<span className="text-small">{getActionText()}</span>
<ArrowRight className="w-4 h-4" />
</div>
</div>
</div>
</div>
</CardContent>
</Card>
);
}
return (
<Card
className="cursor-pointer transition-all duration-300 hover:shadow-lg hover:transform hover:-translate-y-2 group overflow-hidden"
onClick={handleCardClick}
>
{/* Image */}
<div className="aspect-video relative overflow-hidden">
<ImageWithFallback
src={webinar.thumbnail}
alt={webinar.title}
className="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105"
/>
{/* Status Badge */}
<div className="absolute top-4 left-4">
{getStatusBadge()}
</div>
{/* Featured Badge */}
{webinar.featured && (
<div className="absolute top-4 right-4">
<Badge className="bg-yellow-100 text-yellow-800 border border-yellow-200">
<Star className="w-3 h-3 mr-1" />
Featured
</Badge>
</div>
)}
{/* Play Icon Overlay */}
<div className="absolute inset-0 bg-black bg-opacity-40 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center">
<div className="bg-white bg-opacity-90 rounded-full p-3">
<Play className="w-6 h-6 text-gray-800" />
</div>
</div>
</div>
{/* Content */}
<CardContent className="p-6">
<div className="flex items-center justify-between mb-2">
<Badge variant="secondary" className="text-xs">
{webinar.category}
</Badge>
<span className="text-small text-gray-500">{formatDate(webinar.date)}</span>
</div>
<h3 className="text-h4 mb-3 line-clamp-2 group-hover:text-primary transition-colors">
{webinar.title}
</h3>
<p className="text-body text-gray-600 mb-4 line-clamp-2">
{webinar.description}
</p>
<div className="space-y-3">
<div className="flex items-center gap-2 text-small text-gray-500">
<Users className="w-4 h-4" />
<span>{webinar.presenter}</span>
</div>
<div className="flex items-center justify-between text-small text-gray-500">
<div className="flex items-center gap-1">
<Clock className="w-4 h-4" />
<span>{webinar.duration}</span>
</div>
<div className="flex items-center gap-1">
<Eye className="w-4 h-4" />
<span>{webinar.attendees}</span>
</div>
</div>
</div>
<div className="flex items-center justify-between mt-4 pt-4 border-t">
<div className="flex items-center gap-1">
{webinar.tags.slice(0, 2).map((tag, index) => (
<Badge key={index} variant="outline" className="text-xs">
{tag}
</Badge>
))}
</div>
<div className="flex items-center gap-2 text-primary font-medium group-hover:translate-x-1 transition-transform">
<span className="text-small">{getActionText()}</span>
<ArrowRight className="w-4 h-4" />
</div>
</div>
</CardContent>
</Card>
);
};
return (
<div style={{ backgroundColor: '#FFFFFF' }}>
{/* Hero Section with Background Image */}
<section className="relative h-[400px] overflow-hidden">
{/* Background Image */}
<div className="absolute inset-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1652265540589-46f91535337b?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxidXNpbmVzcyUyMHByZXNlbnRhdGlvbiUyMHdlYmluYXIlMjBjb25mZXJlbmNlfGVufDF8fHx8MTc1NTg1NDI3MHww&ixlib=rb-4.1.0&q=80&w=1080"
alt="Professional webinar and conference presentation"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-black/60" />
</div>
{/* Hero Content */}
<div className="relative h-full flex flex-col justify-center section-margin-x">
<div className="text-center">
<h1 className="text-h1-white mb-6">
Leadership Webcasts &<br />
Expert Insights
</h1>
<p className="text-body-lg-white max-w-3xl mx-auto">
Explore our comprehensive collection of expert insights, research, and practical guidance
to elevate your leadership journey and drive organizational excellence.
</p>
</div>
</div>
{/* Statistics Strip at Bottom */}
<div className="absolute bottom-0 left-0 right-0">
<div className="bg-black/80 backdrop-blur-sm px-8 py-6">
<div className="section-margin-x">
<div className="grid grid-cols-3 gap-8 text-center">
<div>
<div className="text-h2-white mb-2">{stats.total}+</div>
<div className="text-small-white">Expert Webcasts</div>
</div>
<div>
<div className="text-h2-white mb-2">{stats.categories}</div>
<div className="text-small-white">Categories</div>
</div>
<div>
<div className="text-h2-white mb-2">15,200</div>
<div className="text-small-white">Total Views</div>
</div>
</div>
</div>
</div>
</div>
</section>
{/* Search and Controls Section */}
<section className="py-8" style={{ backgroundColor: '#FFFFFF' }}>
<div className="section-margin-x">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6">
{/* Search Bar */}
<div className="relative max-w-md flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
<Input
type="text"
placeholder="Search webcasts..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-10 pr-4 py-3 text-body rounded-lg border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all duration-200 w-full bg-gray-50"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
height: '48px'
}}
/>
</div>
{/* View Toggle and Sort */}
<div className="flex items-center gap-4">
<div className="flex items-center border border-gray-300 rounded-lg overflow-hidden">
<button
onClick={() => setViewType('grid')}
className={`p-2 transition-colors ${
viewType === 'grid'
? 'text-white'
: 'bg-white text-gray-600 hover:bg-gray-50'
}`}
style={{
backgroundColor: viewType === 'grid' ? 'var(--color-primary)' : undefined
}}
aria-label="Grid view"
>
<Grid className="w-4 h-4" />
</button>
<button
onClick={() => setViewType('list')}
className={`p-2 transition-colors ${
viewType === 'list'
? 'text-white'
: 'bg-white text-gray-600 hover:bg-gray-50'
}`}
style={{
backgroundColor: viewType === 'list' ? 'var(--color-primary)' : undefined
}}
aria-label="List view"
>
<List className="w-4 h-4" />
</button>
</div>
<Select value={sortBy} onValueChange={setSortBy}>
<SelectTrigger className="w-40 text-body">
<SelectValue placeholder="Sort by" />
</SelectTrigger>
<SelectContent>
{sortOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
</div>
</section>
{/* Main Content Section with Sidebar */}
<section className="pb-16" style={{ backgroundColor: '#FFFFFF' }}>
<div className="section-margin-x">
<div className="grid grid-cols-12 gap-8">
{/* Left Sidebar - Sticky Filters */}
<div className="col-span-12 lg:col-span-3">
<div className="sticky top-4">
<Card className="bg-white border border-gray-200 rounded-lg shadow-md overflow-hidden">
{/* Filter Header */}
<div className="bg-gray-50 px-4 py-3 border-b border-gray-200">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<div className="p-1.5 rounded-md" style={{ backgroundColor: 'rgba(4, 4, 91, 0.1)' }}>
<Filter className="w-3.5 h-3.5" style={{ color: 'var(--color-primary)' }} />
</div>
<h3 className="text-body font-semibold text-gray-800">
Filters
</h3>
</div>
{hasActiveFilters && (
<Button
variant="ghost"
size="sm"
onClick={clearAllFilters}
className="text-xs px-2 py-1 rounded-md transition-colors filter-clear-btn"
>
<X className="w-3 h-3 mr-1" />
Clear
</Button>
)}
</div>
</div>
{/* Filter Content */}
<div className="p-4">
<div className="space-y-6">
{/* Category Filter */}
<div className="filter-section">
<label className="block text-small mb-2 font-medium text-gray-700">
Category
</label>
<Select value={selectedCategory} onValueChange={setSelectedCategory}>
<SelectTrigger className="w-full text-small h-9 border-gray-300 hover:border-gray-400 transition-colors">
<SelectValue placeholder="All Categories" />
</SelectTrigger>
<SelectContent>
{categories.map((category) => (
<SelectItem key={category} value={category} className="text-small">
{category}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{/* Format Filter */}
<div className="filter-section">
<label className="block text-small mb-2 font-medium text-gray-700">
Format
</label>
<Select value={selectedFormat} onValueChange={setSelectedFormat}>
<SelectTrigger className="w-full text-small h-9 border-gray-300 hover:border-gray-400 transition-colors">
<SelectValue placeholder="All Formats" />
</SelectTrigger>
<SelectContent>
{formats.map((format) => (
<SelectItem key={format} value={format} className="text-small">
{format}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{/* Level Filter */}
<div className="filter-section">
<label className="block text-small mb-2 font-medium text-gray-700">
Level
</label>
<Select value={selectedLevel} onValueChange={setSelectedLevel}>
<SelectTrigger className="w-full text-small h-9 border-gray-300 hover:border-gray-400 transition-colors">
<SelectValue placeholder="All Levels" />
</SelectTrigger>
<SelectContent>
{levels.map((level) => (
<SelectItem key={level} value={level} className="text-small">
{level}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{/* Status Filter - Multi-select Pills */}
<div className="filter-section">
<label className="block text-small mb-3 font-medium text-gray-700">
Status
</label>
<div className="flex flex-wrap gap-2">
{statusOptions.map((status) => (
<button
key={status.value}
onClick={() => toggleStatus(status.value)}
className={`
px-3 py-1.5 rounded-full text-xs font-medium border transition-all duration-200
${selectedStatuses.includes(status.value)
? `${status.color} ring-2 ring-blue-200 shadow-sm`
: 'bg-gray-50 text-gray-600 border-gray-200 hover:bg-gray-100 hover:border-gray-300'
}
`}
>
{status.label}
</button>
))}
</div>
{selectedStatuses.length > 0 && (
<div className="mt-2 text-xs text-gray-500">
{selectedStatuses.length} selected
</div>
)}
</div>
{/* Duration Filter - Slider */}
<div className="filter-section">
<label className="block text-small mb-3 font-medium text-gray-700">
Duration
</label>
<div className="px-2">
<Slider
value={durationRange}
onValueChange={setDurationRange}
max={120}
min={0}
step={5}
className="w-full"
/>
<div className="flex justify-between mt-2 text-xs text-gray-500">
<span>{durationRange[0]} min</span>
<span>{durationRange[1]} min</span>
</div>
<div className="mt-1 text-center text-xs text-gray-400">
{durationRange[0] === 0 && durationRange[1] === 120
? 'All durations'
: `${durationRange[0]}-${durationRange[1]} minutes`
}
</div>
</div>
</div>
{/* Attendee Count Filter - Slider */}
<div className="filter-section">
<label className="block text-small mb-3 font-medium text-gray-700">
Attendees
</label>
<div className="px-2">
<Slider
value={attendeeRange}
onValueChange={setAttendeeRange}
max={5000}
min={0}
step={100}
className="w-full"
/>
<div className="flex justify-between mt-2 text-xs text-gray-500">
<span>{attendeeRange[0].toLocaleString()}</span>
<span>{attendeeRange[1].toLocaleString()}+</span>
</div>
<div className="mt-1 text-center text-xs text-gray-400">
{attendeeRange[0] === 0 && attendeeRange[1] === 5000
? 'Any size'
: `${attendeeRange[0].toLocaleString()}-${attendeeRange[1].toLocaleString()}+`
}
</div>
</div>
</div>
</div>
</div>
</Card>
</div>
</div>
{/* Right Main Content */}
<div className="col-span-12 lg:col-span-9">
{/* Results Header */}
<div className="flex items-center justify-between mb-6">
<div className="text-body text-gray-600">
Showing {currentWebinars.length} of {filteredWebinars.length} webcasts
</div>
<div className="text-small text-gray-500">
Page {currentPage} of {totalPages}
</div>
</div>
{/* Content Area */}
<div ref={containerRef}>
{currentWebinars.length === 0 ? (
<div className="text-center py-12">
<div className="text-gray-400 mb-4">
<Search className="w-12 h-12 mx-auto mb-4" />
</div>
<h3 className="text-h4 mb-2">No webcasts found</h3>
<p className="text-body text-gray-600 mb-4">
Try adjusting your filters or search terms
</p>
{hasActiveFilters && (
<Button onClick={clearAllFilters}>
Clear all filters
</Button>
)}
</div>
) : (
<>
{/* Grid View */}
{viewType === 'grid' ? (
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6 mb-8">
{currentWebinars.map((webinar) => (
<WebinarCard key={webinar.id} webinar={webinar} />
))}
</div>
) : (
/* List View */
<div className="space-y-4 mb-8">
{currentWebinars.map((webinar) => (
<WebinarCard key={webinar.id} webinar={webinar} />
))}
</div>
)}
{/* Pagination */}
{totalPages > 1 && (
<div className="flex items-center justify-center gap-2">
<Button
variant="outline"
size="sm"
onClick={() => setCurrentPage(prev => Math.max(1, prev - 1))}
disabled={currentPage === 1}
>
<ChevronLeft className="w-4 h-4 mr-1" />
Previous
</Button>
<div className="flex items-center gap-1">
{Array.from({ length: Math.min(5, totalPages) }, (_, i) => {
const page = Math.max(1, Math.min(totalPages - 4, currentPage - 2)) + i;
return (
<Button
key={page}
variant={currentPage === page ? "default" : "outline"}
size="sm"
onClick={() => setCurrentPage(page)}
className="w-10"
>
{page}
</Button>
);
})}
</div>
<Button
variant="outline"
size="sm"
onClick={() => setCurrentPage(prev => Math.min(totalPages, prev + 1))}
disabled={currentPage === totalPages}
>
Next
<ChevronRight className="w-4 h-4 ml-1" />
</Button>
</div>
)}
</>
)}
</div>
</div>
</div>
</div>
</section>
{/* Webcast CTA Banner */}
<WebcastCTABanner />
</div>
);
}

View File

@@ -0,0 +1,738 @@
import React, { useState, useEffect, useRef } from 'react';
import { Button } from './ui/button';
import { Input } from './ui/input';
import { Badge } from './ui/badge';
import { Card, CardContent } from './ui/card';
import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs';
import { Avatar, AvatarFallback, AvatarImage } from './ui/avatar';
import {
Search,
Filter,
ChevronDown,
Play,
Calendar,
Clock,
Users,
X,
Mail,
ArrowRight,
ExternalLink,
Loader2
} from 'lucide-react';
import { motion, AnimatePresence } from 'motion/react';
import { navigateTo } from './Router';
import { ImageWithFallback } from './figma/ImageWithFallback';
import { BrandedTag } from './about/BrandedTag';
import { PrimaryCTAButton } from './PrimaryCTAButton';
// Mock data for webinars
const mockWebinars = {
upcoming: [
{
id: 1,
title: "Future-Ready Leadership: Navigating Digital Transformation",
abstract: "Explore how modern leaders are adapting to digital disruption and driving organizational change through innovative leadership approaches.",
speaker: {
name: "Sarah Chen",
title: "Chief Digital Officer",
avatar: "https://images.unsplash.com/photo-1494790108755-2616b612b0e0?w=80&h=80&fit=crop&crop=face"
},
date: "2024-12-15",
time: "14:00",
duration: "60 min",
status: "upcoming",
theme: "Digital Leadership",
registrationOpen: true,
coverImage: "https://images.unsplash.com/photo-1542744094-24638eff58bb?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxidXNpbmVzcyUyMHN0cmF0ZWd5JTIwZGlnaXRhbCUyMHRyYW5zZm9ybWF0aW9ufGVufDF8fHx8MTc1NjExNDc5OXww&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral",
attendees: 245
},
{
id: 2,
title: "Building Resilient Teams in Uncertain Times",
abstract: "Learn proven strategies for developing team resilience and maintaining high performance during challenging periods.",
speaker: {
name: "Marcus Thompson",
title: "Leadership Coach",
avatar: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=80&h=80&fit=crop&crop=face"
},
date: "2024-12-18",
time: "15:30",
duration: "45 min",
status: "upcoming",
theme: "Team Leadership",
registrationOpen: true,
coverImage: "https://images.unsplash.com/photo-1598015132635-131afe3ba07f?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxsZWFkZXJzaGlwJTIwdGVhbSUyMGNvbGxhYm9yYXRpb258ZW58MXx8fHwxNzU2MTE0Nzk0fDA&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral",
attendees: 189
},
{
id: 3,
title: "The Art of Strategic Decision Making",
abstract: "Master the frameworks and methodologies that top executives use to make complex strategic decisions.",
speaker: {
name: "Dr. Rachel Park",
title: "Strategy Consultant",
avatar: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=80&h=80&fit=crop&crop=face"
},
date: "2024-12-20",
time: "13:00",
duration: "75 min",
status: "upcoming",
theme: "Strategic Leadership",
registrationOpen: false,
coverImage: "https://images.unsplash.com/photo-1742996111692-2d924f12a058?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxwcm9mZXNzaW9uYWwlMjBidXNpbmVzcyUyMG1lZXRpbmclMjBjb25mZXJlbmNlfGVufDF8fHx8MTc1NjExNDc4NXww&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral",
attendees: 312
}
],
past: [
{
id: 4,
title: "Emotional Intelligence in Leadership",
abstract: "Discover how emotional intelligence drives effective leadership and creates positive organizational culture.",
speaker: {
name: "James Wilson",
title: "Executive Coach",
avatar: "/api/placeholder/40/40"
},
date: "2024-11-25",
time: "14:00",
duration: "60 min",
status: "replay",
theme: "Personal Leadership",
coverImage: "https://images.unsplash.com/photo-1561993629-67302018480e?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxlbW90aW9uYWwlMjBpbnRlbGxpZ2VuY2UlMjBwcm9mZXNzaW9uYWwlMjBkZXZlbG9wbWVudHxlbnwxfHx8fDE3NTYxMTQ4NTJ8MA&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral",
views: 1245
},
{
id: 5,
title: "Innovation Leadership: Fostering Creative Culture",
abstract: "Learn how to create an environment that encourages innovation and creative problem-solving.",
speaker: {
name: "Lisa Rodriguez",
title: "Innovation Director",
avatar: "/api/placeholder/40/40"
},
date: "2024-11-20",
time: "16:00",
duration: "50 min",
status: "replay",
theme: "Innovation Leadership",
coverImage: "https://images.unsplash.com/photo-1744339699989-550c61f3ecb8?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxpbm5vdmF0aW9uJTIwY3JlYXRpdmUlMjB3b3JrcGxhY2V8ZW58MXx8fHwxNzU2MTE0ODU2fDA&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral",
views: 892
},
{
id: 6,
title: "Global Leadership: Managing Across Cultures",
abstract: "Navigate the complexities of leading diverse, multicultural teams in a global business environment.",
speaker: {
name: "Ahmed Hassan",
title: "Global Operations Manager",
avatar: "/api/placeholder/40/40"
},
date: "2024-11-15",
time: "10:00",
duration: "65 min",
status: "replay",
theme: "Global Leadership",
coverImage: "https://images.unsplash.com/photo-1650784854945-264d5b0b6b07?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxnbG9iYWwlMjBtdWx0aWN1bHR1cmFsJTIwYnVzaW5lc3MlMjB0ZWFtfGVufDF8fHx8MTc1NjExNDg2Mnww&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral",
views: 1567
}
]
};
const themes = [
"All Themes",
"Digital Leadership",
"Team Leadership",
"Strategic Leadership",
"Personal Leadership",
"Innovation Leadership",
"Global Leadership"
];
const speakers = [
"All Speakers",
"Sarah Chen",
"Marcus Thompson",
"Dr. Rachel Park",
"James Wilson",
"Lisa Rodriguez",
"Ahmed Hassan"
];
export function WebinarsListing() {
const [activeTab, setActiveTab] = useState('upcoming');
const [searchQuery, setSearchQuery] = useState('');
const [selectedTheme, setSelectedTheme] = useState('All Themes');
const [selectedSpeaker, setSelectedSpeaker] = useState('All Speakers');
const [filtersOpen, setFiltersOpen] = useState(false);
const [emailInput, setEmailInput] = useState('');
const [isSubscribing, setIsSubscribing] = useState(false);
const [loadingMore, setLoadingMore] = useState(false);
const [page, setPage] = useState(1);
const searchTimeout = useRef(null);
// Handle URL hash changes for deep linking
useEffect(() => {
const hash = window.location.hash.replace('#', '');
if (hash === 'upcoming' || hash === 'past') {
setActiveTab(hash);
}
}, []);
// Update URL hash when tab changes
const handleTabChange = (value) => {
setActiveTab(value);
window.history.pushState(null, null, `/webinars#${value}`);
// Announce to screen readers
const announcement = `Switched to ${value} webinars. Showing ${getFilteredWebinars(value).length} results.`;
const liveRegion = document.createElement('div');
liveRegion.setAttribute('aria-live', 'polite');
liveRegion.setAttribute('aria-atomic', 'true');
liveRegion.className = 'sr-only';
liveRegion.textContent = announcement;
document.body.appendChild(liveRegion);
setTimeout(() => document.body.removeChild(liveRegion), 1000);
};
// Debounced search
useEffect(() => {
if (searchTimeout.current) {
clearTimeout(searchTimeout.current);
}
searchTimeout.current = setTimeout(() => {
// Search logic would trigger here
}, 300);
return () => {
if (searchTimeout.current) {
clearTimeout(searchTimeout.current);
}
};
}, [searchQuery]);
// Filter webinars based on current filters
const getFilteredWebinars = (tab = activeTab) => {
let webinars = mockWebinars[tab] || [];
if (searchQuery) {
webinars = webinars.filter(webinar =>
webinar.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
webinar.abstract.toLowerCase().includes(searchQuery.toLowerCase()) ||
webinar.speaker.name.toLowerCase().includes(searchQuery.toLowerCase())
);
}
if (selectedTheme !== 'All Themes') {
webinars = webinars.filter(webinar => webinar.theme === selectedTheme);
}
if (selectedSpeaker !== 'All Speakers') {
webinars = webinars.filter(webinar => webinar.speaker.name === selectedSpeaker);
}
return webinars;
};
// Handle newsletter subscription
const handleSubscribe = async (e) => {
e.preventDefault();
if (!emailInput || isSubscribing) return;
setIsSubscribing(true);
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1500));
setIsSubscribing(false);
setEmailInput('');
alert('Successfully subscribed to webinar reminders!');
};
// Handle load more for past webinars
const handleLoadMore = async () => {
setLoadingMore(true);
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1000));
setPage(prev => prev + 1);
setLoadingMore(false);
};
// Clear all filters
const clearFilters = () => {
setSearchQuery('');
setSelectedTheme('All Themes');
setSelectedSpeaker('All Speakers');
};
const hasActiveFilters = searchQuery || selectedTheme !== 'All Themes' || selectedSpeaker !== 'All Speakers';
const filteredWebinars = getFilteredWebinars();
return (
<div className="min-h-screen" style={{ backgroundColor: '#FFFFFF' }}>
{/* Hero Banner */}
<section className="relative py-20 overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-r from-[#04045B] via-[#04045B] to-[#030359]" />
<div className="absolute inset-0 bg-[url('https://images.unsplash.com/photo-1580863651276-3a1669b2e65a?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHx3ZWJpbmFyJTIwaGVybyUyMGJhY2tncm91bmQlMjBwcmVzZW50YXRpb258ZW58MXx8fHwxNzU2MTE0ODA0fDA&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral')] bg-cover bg-center opacity-10" />
<div className="relative z-10 section-margin-x">
<div className="max-w-4xl">
<BrandedTag text="LEARN & GROW" variant="white" />
<h1 className="text-h1-white mb-6">
Expert-Led Webinars for <br />
Leadership Excellence
</h1>
<p className="text-body-lg-white mb-8 max-w-2xl">
Join industry experts and thought leaders as they share cutting-edge insights,
proven strategies, and practical tools to elevate your leadership journey.
</p>
{/* Hero Stats */}
<div className="grid grid-cols-3 gap-8 max-w-lg">
<div className="text-center">
<div className="text-h2-white">50+</div>
<div className="text-small-white">Expert Sessions</div>
</div>
<div className="text-center">
<div className="text-h2-white">12K+</div>
<div className="text-small-white">Global Attendees</div>
</div>
<div className="text-center">
<div className="text-h2-white">95%</div>
<div className="text-small-white">Satisfaction Rate</div>
</div>
</div>
</div>
</div>
</section>
{/* Main Content */}
<section className="py-16 section-margin-x">
{/* Tab Switcher */}
<Tabs value={activeTab} onValueChange={handleTabChange} className="w-full">
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-between mb-8">
<TabsList className="grid w-full lg:w-auto grid-cols-2 mb-4 lg:mb-0">
<TabsTrigger
value="upcoming"
className="data-[state=active]:bg-[#04045B] data-[state=active]:text-white"
>
Upcoming Webinars
</TabsTrigger>
<TabsTrigger
value="past"
className="data-[state=active]:bg-[#04045B] data-[state=active]:text-white"
>
Past Webinars
</TabsTrigger>
</TabsList>
{/* Results Count */}
<div className="text-small text-muted">
Showing {filteredWebinars.length} result{filteredWebinars.length !== 1 ? 's' : ''}
</div>
</div>
{/* Filter & Search Bar */}
<Card className="mb-8">
<CardContent className="p-6">
{/* Mobile Filter Toggle */}
<div className="lg:hidden mb-4">
<Button
variant="outline"
onClick={() => setFiltersOpen(!filtersOpen)}
className="w-full justify-between"
>
<div className="flex items-center gap-2">
<Filter className="w-4 h-4" />
Filters & Search
</div>
<ChevronDown className={`w-4 h-4 transition-transform ${filtersOpen ? 'rotate-180' : ''}`} />
</Button>
</div>
{/* Filter Content */}
<div className={`space-y-4 lg:space-y-0 lg:grid lg:grid-cols-12 lg:gap-4 lg:items-end ${!filtersOpen ? 'hidden lg:grid' : ''}`}>
{/* Search Input */}
<div className="lg:col-span-4">
<label className="block text-small font-medium mb-2">Search Webinars</label>
<div className="relative">
<Input
type="text"
placeholder="Search by title, speaker, or topic..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10"
/>
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-muted" />
</div>
</div>
{/* Theme Filter */}
<div className="lg:col-span-3">
<label className="block text-small font-medium mb-2">Theme</label>
<select
value={selectedTheme}
onChange={(e) => setSelectedTheme(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#04045B] focus:border-transparent"
>
{themes.map(theme => (
<option key={theme} value={theme}>{theme}</option>
))}
</select>
</div>
{/* Speaker Filter */}
<div className="lg:col-span-3">
<label className="block text-small font-medium mb-2">Speaker</label>
<select
value={selectedSpeaker}
onChange={(e) => setSelectedSpeaker(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#04045B] focus:border-transparent"
>
{speakers.map(speaker => (
<option key={speaker} value={speaker}>{speaker}</option>
))}
</select>
</div>
{/* Clear Filters */}
<div className="lg:col-span-2">
{hasActiveFilters && (
<Button
variant="outline"
onClick={clearFilters}
className="w-full"
>
<X className="w-4 h-4 mr-2" />
Clear
</Button>
)}
</div>
</div>
</CardContent>
</Card>
{/* Tab Content */}
<TabsContent value="upcoming" className="mt-0">
<WebinarGrid webinars={filteredWebinars} type="upcoming" />
</TabsContent>
<TabsContent value="past" className="mt-0">
<WebinarGrid webinars={filteredWebinars} type="past" />
{/* Load More Button for Past Webinars */}
{filteredWebinars.length > 0 && (
<div className="text-center mt-8">
<Button
onClick={handleLoadMore}
disabled={loadingMore}
className="bg-[#04045B] hover:bg-[#030359] text-white"
>
{loadingMore ? (
<>
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
Loading More...
</>
) : (
'Load More Webinars'
)}
</Button>
</div>
)}
</TabsContent>
</Tabs>
{/* Empty State */}
{filteredWebinars.length === 0 && (
<EmptyState
type={activeTab}
hasFilters={hasActiveFilters}
onClearFilters={clearFilters}
onSwitchTab={() => handleTabChange(activeTab === 'upcoming' ? 'past' : 'upcoming')}
/>
)}
</section>
{/* Newsletter CTA Panel */}
<section className="py-16 bg-gray-50">
<div className="section-margin-x">
<div className="max-w-4xl mx-auto text-center">
<div className="mb-8">
<h2 className="text-h2 mb-4">Never Miss a Session</h2>
<p className="text-body-lg text-muted max-w-2xl mx-auto">
Get notified about upcoming webinars, exclusive leadership insights, and
early access to replay content. Join our community of 12,000+ leaders.
</p>
</div>
<form onSubmit={handleSubscribe} className="max-w-md mx-auto">
<div className="flex gap-3">
<div className="flex-1">
<Input
type="email"
placeholder="Enter your email address"
value={emailInput}
onChange={(e) => setEmailInput(e.target.value)}
required
className="h-12"
/>
</div>
<Button
type="submit"
disabled={isSubscribing || !emailInput}
className="bg-[#04045B] hover:bg-[#030359] text-white h-12 px-6"
>
{isSubscribing ? (
<Loader2 className="w-4 h-4 animate-spin" />
) : (
<>
<Mail className="w-4 h-4 mr-2" />
Subscribe
</>
)}
</Button>
</div>
<p className="text-small text-muted mt-3">
No spam, unsubscribe at any time. We respect your privacy.
</p>
</form>
</div>
</div>
</section>
</div>
);
}
// Webinar Grid Component
function WebinarGrid({ webinars, type }) {
if (webinars.length === 0) return null;
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{webinars.map((webinar, index) => (
<WebinarCard key={webinar.id} webinar={webinar} type={type} index={index} />
))}
</div>
);
}
// Individual Webinar Card Component
function WebinarCard({ webinar, type, index }) {
const [isHovered, setIsHovered] = useState(false);
const [imageError, setImageError] = useState(false);
const formatDate = (dateString) => {
const date = new Date(dateString);
return date.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric'
});
};
const getStatusBadge = () => {
switch (webinar.status) {
case 'live':
return <Badge className="bg-red-500 text-white">LIVE</Badge>;
case 'upcoming':
return <Badge className="bg-[#04045B] text-white">Upcoming</Badge>;
case 'replay':
return <Badge className="bg-green-600 text-white">Replay</Badge>;
default:
return null;
}
};
const handleCardClick = () => {
// Navigate to webinar detail page
navigateTo(`/webinar/${webinar.id}`);
};
const handleCTAClick = (e) => {
e.stopPropagation();
if (webinar.status === 'upcoming') {
if (webinar.registrationOpen) {
// Handle registration
alert('Registration functionality would be implemented here');
} else {
// Show tooltip or message
alert('Registration is closed for this webinar');
}
} else if (webinar.status === 'replay') {
// Navigate to replay
navigateTo(`/webinar/${webinar.id}`);
}
};
return (
<motion.article
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="group cursor-pointer"
onClick={handleCardClick}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
role="article"
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleCardClick();
}
}}
>
<Card className="overflow-hidden transition-all duration-300 hover:shadow-lg hover:-translate-y-1 focus-within:shadow-lg focus-within:-translate-y-1">
<div className="relative">
{/* Status Badge */}
<div className="absolute top-3 left-3 z-10">
{getStatusBadge()}
</div>
{/* Cover Image */}
<div className="relative h-48 overflow-hidden">
<ImageWithFallback
src={webinar.coverImage}
alt={webinar.title}
className="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105"
onError={() => setImageError(true)}
/>
{imageError && (
<div className="absolute inset-0 bg-gray-200 flex items-center justify-center">
<Play className="w-12 h-12 text-gray-400" />
</div>
)}
</div>
{/* Hover Overlay */}
<AnimatePresence>
{isHovered && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center"
>
<div className="text-center text-white p-4">
<Play className="w-12 h-12 mx-auto mb-2" />
<p className="text-small">{webinar.abstract}</p>
</div>
</motion.div>
)}
</AnimatePresence>
</div>
<CardContent className="p-6">
{/* Theme Badge */}
<Badge variant="secondary" className="mb-3 bg-[#F8C301] bg-opacity-10 text-[#04045B]">
{webinar.theme}
</Badge>
{/* Title */}
<h3 className="text-h4 mb-3 line-clamp-2 group-hover:text-[#04045B] transition-colors">
{webinar.title}
</h3>
{/* Speaker */}
<div className="flex items-center gap-3 mb-4">
<Avatar className="w-10 h-10">
<AvatarImage src={webinar.speaker.avatar} alt={webinar.speaker.name} />
<AvatarFallback>{webinar.speaker.name.split(' ').map(n => n[0]).join('')}</AvatarFallback>
</Avatar>
<div>
<div className="text-body font-medium">{webinar.speaker.name}</div>
<div className="text-small text-muted">{webinar.speaker.title}</div>
</div>
</div>
{/* Meta Information */}
<div className="flex items-center gap-4 mb-4 text-small text-muted">
<div className="flex items-center gap-1">
<Calendar className="w-4 h-4" />
{formatDate(webinar.date)}
</div>
<div className="flex items-center gap-1">
<Clock className="w-4 h-4" />
{webinar.duration}
</div>
{type === 'upcoming' && (
<div className="flex items-center gap-1">
<Users className="w-4 h-4" />
{webinar.attendees} registered
</div>
)}
{type === 'past' && (
<div className="flex items-center gap-1">
<Play className="w-4 h-4" />
{webinar.views} views
</div>
)}
</div>
{/* CTA Button */}
<Button
onClick={handleCTAClick}
disabled={webinar.status === 'upcoming' && !webinar.registrationOpen}
className={`w-full ${
webinar.status === 'upcoming' && !webinar.registrationOpen
? 'bg-gray-300 text-gray-500 cursor-not-allowed'
: 'bg-[#04045B] hover:bg-[#030359] text-white'
}`}
>
{webinar.status === 'upcoming' && webinar.registrationOpen && 'Register Now'}
{webinar.status === 'upcoming' && !webinar.registrationOpen && 'Registration Closed'}
{webinar.status === 'replay' && (
<>
Watch Replay
<ExternalLink className="w-4 h-4 ml-2" />
</>
)}
</Button>
</CardContent>
</Card>
</motion.article>
);
}
// Empty State Component
function EmptyState({ type, hasFilters, onClearFilters, onSwitchTab }) {
const isUpcoming = type === 'upcoming';
return (
<div className="text-center py-16">
<div className="max-w-md mx-auto">
<div className="w-20 h-20 mx-auto mb-6 bg-gray-100 rounded-full flex items-center justify-center">
<Calendar className="w-10 h-10 text-gray-400" />
</div>
<h3 className="text-h3 mb-4">
{hasFilters ? 'No Results Found' :
isUpcoming ? 'No Upcoming Webinars' : 'No Past Webinars'}
</h3>
<p className="text-body text-muted mb-6">
{hasFilters ?
'Try adjusting your search criteria or clear filters to see more results.' :
isUpcoming ?
'We\'re planning exciting sessions. Check back soon or explore our past webinars.' :
'Our webinar archive is growing. Check out our upcoming sessions.'
}
</p>
<div className="flex flex-col sm:flex-row gap-3 justify-center">
{hasFilters && (
<Button onClick={onClearFilters} variant="outline">
Clear Filters
</Button>
)}
<Button onClick={onSwitchTab} className="bg-[#04045B] hover:bg-[#030359] text-white">
{isUpcoming ? 'View Past Webinars' : 'View Upcoming Webinars'}
<ArrowRight className="w-4 h-4 ml-2" />
</Button>
</div>
</div>
</div>
);
}
export default WebinarsListing;

View File

@@ -0,0 +1,883 @@
import React, { useState, useRef, useEffect } from 'react';
import { Button } from './ui/button';
import { Card, CardContent } from './ui/card';
import { Badge } from './ui/badge';
import { Input } from './ui/input';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
import { ImageWithFallback } from './figma/ImageWithFallback';
import { PrimaryCTAButton } from './PrimaryCTAButton';
import { navigateTo } from './Router';
import {
Search,
Calendar,
Clock,
Users,
Play,
Filter,
Grid,
List,
ChevronLeft,
ChevronRight,
X,
TrendingUp,
Award,
Globe
} from 'lucide-react';
// Comprehensive webinar data
const webinarsData = [
{
id: '1',
slug: 'leadership-in-digital-age',
title: 'Leadership in the Digital Age: Navigating Change and Innovation',
description: 'Discover how modern leaders can adapt and thrive in an increasingly digital world. This comprehensive webcast covers digital transformation strategies, leading remote teams, and fostering innovation.',
presenter: 'Dr. Sarah Mitchell',
presenterTitle: 'Chief Digital Transformation Officer',
company: 'Global Leadership Institute',
date: '2024-02-15',
time: '2:00 PM EST',
duration: '90 minutes',
attendees: '2,400+',
category: 'Digital Transformation',
tags: ['Leadership', 'Digital Strategy', 'Innovation', 'Change Management'],
thumbnail: 'https://images.unsplash.com/photo-1560472355-536de3962603?w=600&h=400&fit=crop',
status: 'Available',
featured: true,
level: 'Advanced',
format: 'Hybrid',
rating: 4.8,
price: 'Free'
},
{
id: '2',
slug: 'building-resilient-teams',
title: 'Building Resilient Teams: Strategies for Sustainable Performance',
description: 'Learn proven methodologies for creating teams that can withstand challenges and maintain high performance under pressure.',
presenter: 'Marcus Rodriguez',
presenterTitle: 'Director of Organizational Development',
company: 'Excellence Consulting',
date: '2024-02-08',
time: '1:00 PM EST',
duration: '75 minutes',
attendees: '1,850+',
category: 'Team Development',
tags: ['Team Building', 'Resilience', 'Performance', 'Leadership'],
thumbnail: 'https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=600&h=400&fit=crop',
status: 'Available',
featured: true,
level: 'Intermediate',
format: 'In Person',
rating: 4.9,
price: 'Free'
},
{
id: '3',
slug: 'strategic-decision-making',
title: 'Strategic Decision Making: Tools and Frameworks for Leaders',
description: 'Master the art of strategic thinking and decision-making with proven frameworks and methodologies used by top executives.',
presenter: 'Dr. Emily Chen',
presenterTitle: 'Strategic Leadership Consultant',
company: 'Strategy First',
date: '2024-01-25',
time: '3:00 PM EST',
duration: '60 minutes',
attendees: '3,200+',
category: 'Strategy',
tags: ['Strategic Thinking', 'Decision Making', 'Leadership', 'Planning'],
thumbnail: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=600&h=400&fit=crop',
status: 'Available',
featured: false,
level: 'Advanced',
format: 'Virtual',
rating: 4.7,
price: 'Free'
},
{
id: '4',
slug: 'emotional-intelligence-workplace',
title: 'Emotional Intelligence in the Workplace: Leading with Empathy',
description: 'Explore the critical role of emotional intelligence in effective leadership and learn practical techniques for developing empathy and emotional awareness.',
presenter: 'Jennifer Adams',
presenterTitle: 'Executive Coach & EQ Specialist',
company: 'Empathy Leadership Group',
date: '2024-01-18',
time: '2:30 PM EST',
duration: '85 minutes',
attendees: '2,100+',
category: 'Personal Development',
tags: ['Emotional Intelligence', 'Empathy', 'Communication', 'Leadership'],
thumbnail: 'https://images.unsplash.com/photo-1559027615-cd4628902d4a?w=600&h=400&fit=crop',
status: 'Recorded',
featured: false,
level: 'Intermediate',
format: 'Hybrid',
rating: 4.6,
price: 'Free'
},
{
id: '5',
slug: 'crisis-leadership-management',
title: 'Crisis Leadership: Managing Through Uncertainty and Change',
description: 'Learn essential crisis leadership skills and strategies for guiding organizations through challenging times and uncertainty.',
presenter: 'David Park',
presenterTitle: 'Crisis Management Expert',
company: 'Risk Management Solutions',
date: '2024-01-10',
time: '1:30 PM EST',
duration: '70 minutes',
attendees: '2,800+',
category: 'Crisis Management',
tags: ['Crisis Leadership', 'Change Management', 'Communication', 'Strategy'],
thumbnail: 'https://images.unsplash.com/photo-1552664730-d307ca884978?w=600&h=400&fit=crop',
status: 'Live',
featured: false,
level: 'Advanced',
format: 'Virtual',
rating: 4.8,
price: 'Free'
},
{
id: '6',
slug: 'future-workplace-trends',
title: 'The Future of Work: Preparing for Tomorrow\'s Workplace',
description: 'Discover emerging workplace trends and learn how to prepare your organization and teams for the future of work.',
presenter: 'Lisa Thompson',
presenterTitle: 'Future of Work Analyst',
company: 'Tomorrow Institute',
date: '2024-01-05',
time: '4:00 PM EST',
duration: '80 minutes',
attendees: '1,950+',
category: 'Future of Work',
tags: ['Future Trends', 'Workplace Evolution', 'Technology', 'Leadership'],
thumbnail: 'https://images.unsplash.com/photo-1600880292203-757bb62b4baf?w=600&h=400&fit=crop',
status: 'Upcoming',
featured: false,
level: 'Beginner',
format: 'Hybrid',
rating: 4.5,
price: 'Free'
},
{
id: '7',
slug: 'ai-leadership-transformation',
title: 'AI-Powered Leadership: Transforming Decision Making',
description: 'Explore how artificial intelligence is reshaping leadership practices and learn to leverage AI tools for better decision-making.',
presenter: 'Dr. Alex Kim',
presenterTitle: 'AI Strategy Director',
company: 'AI Leadership Labs',
date: '2024-03-15',
time: '2:00 PM EST',
duration: '75 minutes',
attendees: '3,500+',
category: 'Technology Leadership',
tags: ['Artificial Intelligence', 'Decision Making', 'Technology', 'Innovation'],
thumbnail: 'https://images.unsplash.com/photo-1677442136019-21780ecad995?w=600&h=400&fit=crop',
status: 'Upcoming',
featured: true,
level: 'Advanced',
format: 'Virtual',
rating: 4.9,
price: 'Free'
},
{
id: '8',
slug: 'sustainable-leadership-live',
title: 'Sustainable Leadership: Building for the Future - LIVE SESSION',
description: 'Join us LIVE as we discuss sustainable leadership practices and environmental responsibility in business leadership.',
presenter: 'Maria Santos',
presenterTitle: 'Sustainability Leadership Expert',
company: 'Green Leadership Council',
date: '2024-02-20',
time: '1:00 PM EST',
duration: '90 minutes',
attendees: '2,200+',
category: 'Sustainable Leadership',
tags: ['Sustainability', 'Environmental Leadership', 'Future Business', 'Corporate Responsibility'],
thumbnail: 'https://images.unsplash.com/photo-1542601906990-b4d3fb778b09?w=600&h=400&fit=crop',
status: 'Live',
featured: true,
level: 'Intermediate',
format: 'Virtual',
rating: 4.7,
price: 'Free'
},
{
id: '9',
slug: 'cross-cultural-leadership',
title: 'Cross-Cultural Leadership: Leading Global Teams Effectively',
description: 'Develop the skills needed to lead diverse, multicultural teams across different time zones and cultural contexts.',
presenter: 'Dr. Raj Patel',
presenterTitle: 'Global Leadership Specialist',
company: 'International Business Academy',
date: '2024-02-25',
time: '11:00 AM EST',
duration: '65 minutes',
attendees: '1,750+',
category: 'Global Leadership',
tags: ['Cross-Cultural', 'Global Teams', 'Diversity', 'Communication'],
thumbnail: 'https://images.unsplash.com/photo-1573164713714-d95e436ab8d6?w=600&h=400&fit=crop',
status: 'Available',
featured: false,
level: 'Intermediate',
format: 'Virtual',
rating: 4.6,
price: 'Free'
}
];
// Filter configurations
const categories = ['All Categories', 'Digital Transformation', 'Team Development', 'Strategy', 'Personal Development', 'Crisis Management', 'Future of Work', 'Technology Leadership', 'Sustainable Leadership', 'Global Leadership'];
const formats = ['All Formats', 'Virtual', 'Hybrid', 'In Person'];
const levels = ['All Levels', 'Beginner', 'Intermediate', 'Advanced'];
const statuses = ['All Status', 'Available', 'Live', 'Upcoming', 'Recorded', 'Featured'];
const sortOptions = [
{ value: 'Most Popular', label: 'Most Popular' },
{ value: 'newest', label: 'Newest First' },
{ value: 'oldest', label: 'Oldest First' },
{ value: 'title', label: 'Title A-Z' },
{ value: 'duration', label: 'Duration' },
{ value: 'rating', label: 'Highest Rated' }
];
export function WebinarsPage() {
const [searchTerm, setSearchTerm] = useState('');
const [selectedCategory, setSelectedCategory] = useState('All Categories');
const [selectedFormat, setSelectedFormat] = useState('All Formats');
const [selectedLevel, setSelectedLevel] = useState('All Levels');
const [selectedStatus, setSelectedStatus] = useState('All Status');
const [sortBy, setSortBy] = useState('Most Popular');
const [viewType, setViewType] = useState<'grid' | 'list'>('grid');
const [currentPage, setCurrentPage] = useState(1);
const webinarsPerPage = 9;
const containerRef = useRef<HTMLDivElement>(null);
// Filter and sort webinars
const filteredWebinars = webinarsData.filter(webinar => {
const matchesSearch = webinar.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
webinar.description.toLowerCase().includes(searchTerm.toLowerCase()) ||
webinar.presenter.toLowerCase().includes(searchTerm.toLowerCase()) ||
webinar.tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase()));
const matchesCategory = selectedCategory === 'All Categories' || webinar.category === selectedCategory;
const matchesFormat = selectedFormat === 'All Formats' || webinar.format === selectedFormat;
const matchesLevel = selectedLevel === 'All Levels' || webinar.level === selectedLevel;
const matchesStatus = selectedStatus === 'All Status' ||
webinar.status === selectedStatus ||
(selectedStatus === 'Featured' && webinar.featured);
return matchesSearch && matchesCategory && matchesFormat && matchesLevel && matchesStatus;
}).sort((a, b) => {
switch (sortBy) {
case 'newest':
return new Date(b.date).getTime() - new Date(a.date).getTime();
case 'oldest':
return new Date(a.date).getTime() - new Date(b.date).getTime();
case 'title':
return a.title.localeCompare(b.title);
case 'duration':
return parseInt(b.duration) - parseInt(a.duration);
case 'rating':
return b.rating - a.rating;
default:
return 0;
}
});
// Statistics
const stats = {
total: webinarsData.length,
available: webinarsData.filter(w => w.status === 'Available').length,
live: webinarsData.filter(w => w.status === 'Live').length,
upcoming: webinarsData.filter(w => w.status === 'Upcoming').length,
recorded: webinarsData.filter(w => w.status === 'Recorded').length,
featured: webinarsData.filter(w => w.featured).length,
avgRating: (webinarsData.reduce((sum, w) => sum + w.rating, 0) / webinarsData.length).toFixed(1)
};
// Paginate results
const totalPages = Math.ceil(filteredWebinars.length / webinarsPerPage);
const currentWebinars = filteredWebinars.slice((currentPage - 1) * webinarsPerPage, currentPage * webinarsPerPage);
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
};
const clearAllFilters = () => {
setSearchTerm('');
setSelectedCategory('All Categories');
setSelectedFormat('All Formats');
setSelectedLevel('All Levels');
setSelectedStatus('All Status');
setSortBy('Most Popular');
};
const hasActiveFilters = searchTerm ||
selectedCategory !== 'All Categories' ||
selectedFormat !== 'All Formats' ||
selectedLevel !== 'All Levels' ||
selectedStatus !== 'All Status';
const renderStars = (rating: number) => {
return Array.from({ length: 5 }, (_, i) => (
<span key={i} className={`text-sm ${i < Math.floor(rating) ? 'text-yellow-400' : 'text-gray-300'}`}></span>
));
};
return (
<div style={{ backgroundColor: '#FFFFFF' }}>
{/* Hero Section with Background Image */}
<section className="relative h-[500px] overflow-hidden">
{/* Background Image */}
<div className="absolute inset-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1552664730-d307ca884978?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxidXNpbmVzcyUyMHByZXNlbnRhdGlvbiUyMHdlYmluYXIlMjBjb25mZXJlbmNlfGVufDF8fHx8MTc1NTg1NDI3MHww&ixlib=rb-4.1.0&q=80&w=1080"
alt="Professional webinar and conference presentation"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-black/60" />
</div>
{/* Hero Content */}
<div className="relative h-full flex flex-col justify-center section-margin-x">
<div className="text-center max-w-4xl mx-auto">
<div className="branded-tag-system-white mb-6">
<span className="dot"></span>
<span className="text">Expert Leadership Insights</span>
</div>
<h1 className="text-h1-white mb-6">
Transform Your Leadership<br />
Through Expert Webcasts
</h1>
<p className="text-body-lg-white max-w-3xl mx-auto mb-8">
Access world-class leadership development content from industry experts.
Join thousands of leaders who are advancing their skills through our
comprehensive webcast library.
</p>
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
<PrimaryCTAButton
text="Browse All Webcasts"
onClick={() => {
const filtersSection = document.getElementById('webinars-filters');
if (filtersSection) {
filtersSection.scrollIntoView({ behavior: 'smooth' });
}
}}
className="cta-text-black"
/>
<Button
variant="outline"
size="lg"
className="bg-white/10 text-white border-white/30 hover:bg-white/20 backdrop-blur-sm"
onClick={() => navigateTo('/contact?topic=webinars')}
>
<Calendar className="w-5 h-5 mr-2" />
Schedule a Session
</Button>
</div>
</div>
</div>
{/* Statistics Strip at Bottom */}
<div className="absolute bottom-0 left-0 right-0">
<div className="bg-black/80 backdrop-blur-sm px-8 py-6">
<div className="section-margin-x">
<div className="grid grid-cols-2 md:grid-cols-4 gap-8 text-center">
<div>
<div className="text-h2-white mb-2">{stats.total}+</div>
<div className="text-small-white">Expert Webcasts</div>
</div>
<div>
<div className="text-h2-white mb-2">{stats.live + stats.upcoming}</div>
<div className="text-small-white">Live & Upcoming</div>
</div>
<div>
<div className="text-h2-white mb-2">25K+</div>
<div className="text-small-white">Total Attendees</div>
</div>
<div>
<div className="text-h2-white mb-2">{stats.avgRating}/5</div>
<div className="text-small-white">Average Rating</div>
</div>
</div>
</div>
</div>
</div>
</section>
{/* Search and Controls Section */}
<section id="webinars-filters" className="py-8" style={{ backgroundColor: '#FFFFFF' }}>
<div className="section-margin-x">
{/* Search and View Controls */}
<div className="flex flex-col lg:flex-row gap-6 mb-8">
{/* Search Bar */}
<div className="relative max-w-md flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
<Input
type="text"
placeholder="Search webcasts, presenters, topics..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-10 pr-4 py-3 text-body rounded-lg border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all duration-200 w-full bg-gray-50"
style={{
fontSize: 'var(--font-body)',
fontFamily: 'var(--font-family-base)',
height: '48px'
}}
/>
</div>
{/* Controls */}
<div className="flex items-center gap-4">
{/* View Toggle */}
<div className="flex items-center border border-gray-300 rounded-lg overflow-hidden">
<button
onClick={() => setViewType('grid')}
className={`p-2 transition-colors ${
viewType === 'grid'
? 'text-white'
: 'bg-white text-gray-600 hover:bg-gray-50'
}`}
style={{
backgroundColor: viewType === 'grid' ? 'var(--color-primary)' : undefined
}}
aria-label="Grid view"
>
<Grid className="w-4 h-4" />
</button>
<button
onClick={() => setViewType('list')}
className={`p-2 transition-colors ${
viewType === 'list'
? 'text-white'
: 'bg-white text-gray-600 hover:bg-gray-50'
}`}
style={{
backgroundColor: viewType === 'list' ? 'var(--color-primary)' : undefined
}}
aria-label="List view"
>
<List className="w-4 h-4" />
</button>
</div>
{/* Sort */}
<Select value={sortBy} onValueChange={setSortBy}>
<SelectTrigger className="w-48 text-body">
<SelectValue placeholder="Sort by" />
</SelectTrigger>
<SelectContent>
{sortOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
{/* Filters */}
<div className="grid grid-cols-2 md:grid-cols-5 gap-4 mb-6">
<Select value={selectedCategory} onValueChange={setSelectedCategory}>
<SelectTrigger>
<SelectValue placeholder="Category" />
</SelectTrigger>
<SelectContent>
{categories.map((category) => (
<SelectItem key={category} value={category}>
{category}
</SelectItem>
))}
</SelectContent>
</Select>
<Select value={selectedFormat} onValueChange={setSelectedFormat}>
<SelectTrigger>
<SelectValue placeholder="Format" />
</SelectTrigger>
<SelectContent>
{formats.map((format) => (
<SelectItem key={format} value={format}>
{format}
</SelectItem>
))}
</SelectContent>
</Select>
<Select value={selectedLevel} onValueChange={setSelectedLevel}>
<SelectTrigger>
<SelectValue placeholder="Level" />
</SelectTrigger>
<SelectContent>
{levels.map((level) => (
<SelectItem key={level} value={level}>
{level}
</SelectItem>
))}
</SelectContent>
</Select>
<Select value={selectedStatus} onValueChange={setSelectedStatus}>
<SelectTrigger>
<SelectValue placeholder="Status" />
</SelectTrigger>
<SelectContent>
{statuses.map((status) => (
<SelectItem key={status} value={status}>
{status}
</SelectItem>
))}
</SelectContent>
</Select>
{hasActiveFilters && (
<Button
variant="outline"
onClick={clearAllFilters}
className="text-gray-600 hover:text-gray-800"
>
<X className="w-4 h-4 mr-2" />
Clear All
</Button>
)}
</div>
<div className="text-small text-gray-600 mb-8">
Showing {currentWebinars.length} of {filteredWebinars.length} webcasts
</div>
</div>
</section>
{/* Webinars Content */}
<section className="pb-16" style={{ backgroundColor: '#FFFFFF' }}>
<div className="section-margin-x">
{currentWebinars.length === 0 ? (
<div className="text-center py-16">
<div className="w-16 h-16 mx-auto mb-4 bg-gray-100 rounded-full flex items-center justify-center">
<Search className="w-8 h-8 text-gray-400" />
</div>
<h3 className="text-h4 mb-4">No webcasts found</h3>
<p className="text-body text-gray-600 mb-6">
Try adjusting your filters or search terms to find relevant content.
</p>
<Button onClick={clearAllFilters} variant="outline">
Clear All Filters
</Button>
</div>
) : (
<>
{/* Grid View */}
{viewType === 'grid' && (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{currentWebinars.map((webinar) => (
<Card
key={webinar.id}
className="overflow-hidden hover:shadow-xl transition-all duration-300 cursor-pointer group border-0 shadow-lg"
onClick={() => navigateTo(`/webinar/${webinar.slug}`)}
>
<div className="aspect-video w-full bg-gray-100 overflow-hidden relative">
<ImageWithFallback
src={webinar.thumbnail}
alt={webinar.title}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
/>
{/* Status Badge */}
<div className="absolute top-4 left-4">
{webinar.status === 'Live' && (
<Badge className="bg-red-600 text-white border-red-600 animate-pulse">
LIVE
</Badge>
)}
{webinar.status === 'Upcoming' && (
<Badge className="bg-blue-600 text-white border-blue-600">
Upcoming
</Badge>
)}
{webinar.status === 'Recorded' && (
<Badge className="bg-green-600 text-white border-green-600">
Replay Available
</Badge>
)}
</div>
{webinar.featured && (
<div className="absolute top-4 right-4">
<Badge className="bg-yellow-500 text-white border-yellow-500">
<Award className="w-3 h-3 mr-1" />
Featured
</Badge>
</div>
)}
{/* Play Button Overlay */}
<div className="absolute inset-0 bg-black bg-opacity-40 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300">
<Button
variant="secondary"
size="lg"
className="bg-white text-black hover:bg-gray-100"
>
<Play className="w-5 h-5 mr-2" />
{webinar.status === 'Live' ? 'Join Live' : webinar.status === 'Upcoming' ? 'Register' : 'Watch'}
</Button>
</div>
</div>
<CardContent className="p-6">
{/* Meta Info */}
<div className="flex items-center gap-2 mb-3">
<Badge variant="outline" className="text-xs">
{webinar.format}
</Badge>
<Badge variant="outline" className="text-xs">
{webinar.level}
</Badge>
<div className="flex items-center gap-1 ml-auto">
{renderStars(webinar.rating)}
<span className="text-xs text-gray-600 ml-1">{webinar.rating}</span>
</div>
</div>
<h3 className="text-h4 mb-3 group-hover:text-blue-600 transition-colors line-clamp-2">
{webinar.title}
</h3>
<p className="text-small text-gray-600 mb-4 line-clamp-2">
{webinar.description}
</p>
{/* Presenter Info */}
<div className="flex items-center mb-4">
<div className="w-10 h-10 bg-gray-200 rounded-full flex items-center justify-center mr-3">
<Users className="w-5 h-5 text-gray-400" />
</div>
<div>
<div className="text-small font-medium">{webinar.presenter}</div>
<div className="text-xs text-gray-500">{webinar.presenterTitle}</div>
</div>
</div>
{/* Details */}
<div className="flex items-center justify-between text-small text-gray-500 mb-4">
<div className="flex items-center gap-4">
<div className="flex items-center gap-1">
<Clock className="w-4 h-4" />
<span>{webinar.duration}</span>
</div>
<div className="flex items-center gap-1">
<Users className="w-4 h-4" />
<span>{webinar.attendees}</span>
</div>
</div>
<div className="flex items-center gap-1">
<Globe className="w-4 h-4" />
<span>{webinar.format}</span>
</div>
</div>
{/* Date and Price */}
<div className="flex items-center justify-between">
<div className="text-small text-gray-600">
{formatDate(webinar.date)}
</div>
<div className="text-small font-medium text-green-600">
{webinar.price}
</div>
</div>
</CardContent>
</Card>
))}
</div>
)}
{/* List View */}
{viewType === 'list' && (
<div className="space-y-6">
{currentWebinars.map((webinar) => (
<Card
key={webinar.id}
className="overflow-hidden hover:shadow-xl transition-all duration-300 cursor-pointer border-0 shadow-lg"
onClick={() => navigateTo(`/webinar/${webinar.slug}`)}
>
<div className="flex">
<div className="w-80 h-48 bg-gray-100 overflow-hidden relative flex-shrink-0">
<ImageWithFallback
src={webinar.thumbnail}
alt={webinar.title}
className="w-full h-full object-cover"
/>
{webinar.featured && (
<div className="absolute top-4 right-4">
<Badge className="bg-yellow-500 text-white border-yellow-500">
<Award className="w-3 h-3 mr-1" />
Featured
</Badge>
</div>
)}
</div>
<CardContent className="flex-1 p-6">
<div className="flex items-start justify-between mb-4">
<div className="flex items-center gap-2">
<Badge variant="outline" className="text-xs">
{webinar.format}
</Badge>
<Badge variant="outline" className="text-xs">
{webinar.level}
</Badge>
{webinar.status === 'Live' && (
<Badge className="bg-red-600 text-white border-red-600 animate-pulse">
LIVE
</Badge>
)}
{webinar.status === 'Upcoming' && (
<Badge className="bg-blue-600 text-white border-blue-600">
Upcoming
</Badge>
)}
{webinar.status === 'Recorded' && (
<Badge className="bg-green-600 text-white border-green-600">
Replay Available
</Badge>
)}
</div>
<div className="flex items-center gap-1">
{renderStars(webinar.rating)}
<span className="text-xs text-gray-600 ml-1">{webinar.rating}</span>
</div>
</div>
<h3 className="text-h4 mb-3 hover:text-blue-600 transition-colors">
{webinar.title}
</h3>
<p className="text-small text-gray-600 mb-4">
{webinar.description}
</p>
<div className="flex items-center justify-between">
<div className="flex items-center gap-6 text-small text-gray-500">
<div className="flex items-center gap-1">
<Clock className="w-4 h-4" />
<span>{webinar.duration}</span>
</div>
<div className="flex items-center gap-1">
<Users className="w-4 h-4" />
<span>{webinar.attendees}</span>
</div>
<div className="flex items-center gap-2">
<span>By {webinar.presenter}</span>
</div>
</div>
<div className="flex items-center gap-4">
<div className="text-small text-gray-600">
{formatDate(webinar.date)}
</div>
<div className="text-small font-medium text-green-600">
{webinar.price}
</div>
</div>
</div>
</CardContent>
</div>
</Card>
))}
</div>
)}
{/* Pagination */}
{totalPages > 1 && (
<div className="flex items-center justify-center gap-2 mt-12">
<Button
variant="outline"
size="sm"
onClick={() => setCurrentPage(prev => Math.max(1, prev - 1))}
disabled={currentPage === 1}
>
<ChevronLeft className="w-4 h-4" />
Previous
</Button>
<div className="flex items-center gap-1">
{Array.from({ length: Math.min(totalPages, 7) }, (_, i) => {
let page;
if (totalPages <= 7) {
page = i + 1;
} else if (currentPage <= 4) {
page = i + 1;
} else if (currentPage >= totalPages - 3) {
page = totalPages - 6 + i;
} else {
page = currentPage - 3 + i;
}
return (
<Button
key={page}
variant={currentPage === page ? "default" : "outline"}
size="sm"
onClick={() => setCurrentPage(page)}
className="w-10 h-10 p-0"
style={{
backgroundColor: currentPage === page ? 'var(--color-primary)' : undefined,
color: currentPage === page ? 'white' : undefined
}}
>
{page}
</Button>
);
})}
</div>
<Button
variant="outline"
size="sm"
onClick={() => setCurrentPage(prev => Math.min(totalPages, prev + 1))}
disabled={currentPage === totalPages}
>
Next
<ChevronRight className="w-4 h-4" />
</Button>
</div>
)}
</>
)}
</div>
</section>
{/* CTA Section */}
<section className="py-16 bg-gray-50">
<div className="section-margin-x text-center">
<div className="max-w-3xl mx-auto">
<h2 className="text-h2 mb-6">Ready to Transform Your Leadership?</h2>
<p className="text-body-lg text-gray-600 mb-8">
Join thousands of professionals who are advancing their careers through our expert-led webcasts.
Start your leadership transformation today.
</p>
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
<PrimaryCTAButton
text="Get Started Today"
onClick={() => navigateTo('/contact?topic=leadership-development')}
className="cta-text-black"
/>
<Button
variant="outline"
size="lg"
onClick={() => navigateTo('/about/our-expertise')}
>
<TrendingUp className="w-5 h-5 mr-2" />
Learn More About Us
</Button>
</div>
</div>
</div>
</section>
</div>
);
}

View File

@@ -0,0 +1,221 @@
import { motion } from "motion/react";
import { FileText, Target, BarChart3, Download, Eye } from "lucide-react";
import { BrandedTag } from "./about/BrandedTag";
import { PrimaryCTAButton } from "./PrimaryCTAButton";
import { navigateTo } from "./Router";
interface Resource {
id: number;
title: string;
description: string;
type: string;
category: string;
icon: any;
color: string;
}
const resources: Resource[] = [
{
id: 1,
title: "Leadership Assessment Framework",
description: "Comprehensive self-leadership evaluation tool with detailed scoring methodology.",
type: "PDF Guide",
category: "Stage",
icon: FileText,
color: "#8B5CF6"
},
{
id: 2,
title: "Executive Decision Making Toolkit",
description: "Strategic frameworks and templates for complex organizational decision making.",
type: "Toolkit",
category: "B Frame",
icon: Target,
color: "#3B82F6"
},
{
id: 3,
title: "Team Performance Metrics Dashboard",
description: "Ready-to-use Excel template for tracking and improving team performance indicators.",
type: "Excel Template",
category: "Dashboard",
icon: BarChart3,
color: "#10B981"
}
];
interface ResourceCardProps {
resource: Resource;
index: number;
}
function ResourceCard({ resource, index }: ResourceCardProps) {
const IconComponent = resource.icon;
return (
<motion.div
className="bg-white rounded-xl border border-gray-100 p-8 hover:shadow-lg transition-all duration-300 group"
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: index * 0.1 }}
viewport={{ once: true }}
>
{/* Icon and Category */}
<div className="flex items-center justify-center mb-6">
<div
className="w-16 h-16 rounded-xl flex items-center justify-center"
style={{ backgroundColor: `${resource.color}20` }}
>
<IconComponent
className="w-8 h-8"
style={{ color: resource.color }}
/>
</div>
</div>
{/* Type and Category Tags */}
<div className="flex items-center justify-center gap-2 mb-4">
<span
className="px-3 py-1 text-xs font-semibold rounded-full"
style={{
backgroundColor: `${resource.color}15`,
color: resource.color
}}
>
{resource.type}
</span>
<span
className="px-3 py-1 text-xs font-semibold rounded-full"
style={{
backgroundColor: 'var(--color-brand-primary)',
color: 'white'
}}
>
{resource.category}
</span>
</div>
{/* Title */}
<h3
className="text-xl font-bold text-center mb-4 leading-tight"
style={{
color: 'var(--color-brand-black)',
display: '-webkit-box',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
minHeight: '3.5rem'
}}
>
{resource.title}
</h3>
{/* Description */}
<p
className="text-sm text-center leading-relaxed mb-8"
style={{ color: '#6B7280' }}
>
{resource.description}
</p>
{/* Download Button - Updated to redirect to learning resources */}
<button
className="w-full flex items-center justify-center space-x-2 px-6 py-3 font-semibold text-sm transition-all duration-300 hover:shadow-lg hover:-translate-y-1"
style={{
borderRadius: '10px',
backgroundColor: 'var(--color-brand-primary)',
color: 'white'
}}
onClick={() => navigateTo('/learning/articles')}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = 'var(--color-brand-accent)';
e.currentTarget.style.color = 'var(--color-brand-black)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = 'var(--color-brand-primary)';
e.currentTarget.style.color = 'white';
}}
>
<Download className="w-4 h-4" />
<span>Free Download</span>
</button>
</motion.div>
);
}
export function WhitepapersSection() {
return (
<section
className="py-20"
style={{ backgroundColor: 'var(--color-brand-bg-light)' }}
>
<div className="max-w-7xl mx-auto section-margin-x">
{/* Section Header */}
<div className="mb-16">
{/* Branded Tag */}
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
>
<BrandedTag text="Free Leadership Resources" />
</motion.div>
{/* Heading and CTA Container */}
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-between mb-6 gap-6">
{/* Main Heading */}
<motion.h2
className="text-5xl font-bold leading-tight max-lg:text-4xl max-md:text-3xl"
style={{ color: 'var(--color-brand-black)' }}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, delay: 0.2 }}
viewport={{ once: true }}
>
Free Leadership Downloads
</motion.h2>
{/* Browse All Resources Button - Updated to redirect to articles */}
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.4 }}
viewport={{ once: true }}
>
<PrimaryCTAButton
text="Browse All Resources"
onClick={() => navigateTo('/learning/articles')}
ariaLabel="Browse all leadership resources"
className="browse-resources-cta-override"
/>
</motion.div>
</div>
{/* Description */}
<motion.p
className="text-lg leading-relaxed max-w-2xl"
style={{ color: '#6B7280' }}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.6 }}
viewport={{ once: true }}
>
Access our collection of premium leadership tools, frameworks, and templates at no cost. Start implementing proven leadership strategies today.
</motion.p>
</div>
{/* Resources Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{resources.map((resource, index) => (
<ResourceCard
key={resource.id}
resource={resource}
index={index}
/>
))}
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,42 @@
interface BrandedTagProps {
text: string;
className?: string;
textColor?: string;
variant?: "default" | "white" | "next-steps";
}
export function BrandedTag({
text,
className = "",
textColor,
variant = "default",
}: BrandedTagProps) {
let baseClass = "branded-tag-system";
let defaultTextColor = "#26231A"; // Default to black
if (variant === "white") {
baseClass = "branded-tag-system-white";
defaultTextColor = "#ffffff"; // White text for dark backgrounds
} else if (variant === "next-steps") {
baseClass = "branded-tag-system-next-steps";
defaultTextColor = "#26231A"; // Brand black for NEXT STEPS
}
return (
<div
className={`${baseClass} ${className}`}
style={{ marginBottom: "20px" }}
>
<div className="dot" />
<span
className="text"
style={{
color: textColor || defaultTextColor,
fontFamily: "var(--font-family-base)",
}}
>
{text}
</span>
</div>
);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,739 @@
import React, { useEffect, useState, useRef } from 'react';
import { Button } from '../ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../ui/card';
import { Badge } from '../ui/badge';
import { ImageWithFallback } from '../figma/ImageWithFallback';
import { TestimonialsSection } from '../TestimonialsSection';
import { navigateTo } from '../Router';
import { PrimaryCTAButton } from '../PrimaryCTAButton';
import {
TrendingUp,
Users,
Award,
ArrowRight,
Star,
Quote,
Building,
Target,
Globe,
Sparkles,
CheckCircle,
BarChart3,
PieChart,
Activity
} from 'lucide-react';
// Import the actual logos from Figma assets (same as LogosSection)
import imgImage36 from "figma:asset/6bdf8056f51bbdc6dd9dab9044a6579a254bd02c.png";
import imgImage39 from "figma:asset/037c4659b7b0bf15b1dfdcd4868cb42e8257e838.png";
import imgImage43 from "figma:asset/c57ec1f4466f68e607139a3cd6d52f7e2f372408.png";
import imgImage45 from "figma:asset/4833274f0a593cd31fdefe553b70bb016de281af.png";
import imgImage38 from "figma:asset/d5bab6ea4f3d8cef3b0425c45cfee7faea19fdbc.png";
import imgImage47 from "figma:asset/e8fad960112d5eba554c3969d08891ebe4d4b9c7.png";
const impactStats = [
{
number: 26643,
suffix: "",
label: "PARTICIPANTS",
description: "Leaders developed across all programs",
icon: Users,
bgColor: "bg-primary/10"
},
{
number: 1220,
suffix: "",
label: "PROGRAMS",
description: "Successfully delivered initiatives",
icon: Target,
bgColor: "bg-primary/15"
},
{
number: 152,
suffix: "",
label: "CLIENTS",
description: "Organizations transformed",
icon: Building,
bgColor: "bg-primary/20"
}
];
const clientLogos = [
{
name: "CANMOOR",
logo: imgImage36,
sector: "Financial Services",
width: 302,
height: 54
},
{
name: "BlackRock",
logo: imgImage45,
sector: "Investment Management",
width: 210,
height: 54
},
{
name: "Royal London",
logo: imgImage38,
sector: "Insurance",
width: 145,
height: 54
},
{
name: "Abstract",
logo: imgImage39,
sector: "Technology",
width: 172,
height: 54
},
{
name: "ARES",
logo: imgImage47,
sector: "Asset Management",
width: 163,
height: 54
},
{
name: "KADANS",
logo: imgImage43,
sector: "Real Estate",
width: 206,
height: 54
},
// Add repeats for more variety
{
name: "CANMOOR",
logo: imgImage36,
sector: "Financial Services",
width: 302,
height: 54
},
{
name: "BlackRock",
logo: imgImage45,
sector: "Investment Management",
width: 210,
height: 54
},
{
name: "Royal London",
logo: imgImage38,
sector: "Insurance",
width: 145,
height: 54
},
{
name: "Abstract",
logo: imgImage39,
sector: "Technology",
width: 172,
height: 54
},
{
name: "ARES",
logo: imgImage47,
sector: "Asset Management",
width: 163,
height: 54
},
{
name: "KADANS",
logo: imgImage43,
sector: "Real Estate",
width: 206,
height: 54
},
{
name: "CANMOOR",
logo: imgImage36,
sector: "Financial Services",
width: 302,
height: 54
},
{
name: "BlackRock",
logo: imgImage45,
sector: "Investment Management",
width: 210,
height: 54
},
{
name: "Royal London",
logo: imgImage38,
sector: "Insurance",
width: 145,
height: 54
}
];
const testimonialHighlights = [
{
quote: "KLC's leadership program transformed our entire management approach. The ROI was evident within 6 months.",
author: "Rajesh Kumar",
position: "CEO, TechVision Ltd",
program: "Executive Leadership Program",
image: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=150&h=150&fit=crop",
rating: 5
},
{
quote: "The practical frameworks and peer learning experience exceeded our expectations. Highly recommend KLC.",
author: "Priya Sharma",
position: "VP Operations, Global Manufacturing",
program: "Team Leadership Intensive",
image: "https://images.unsplash.com/photo-1494790108755-2616b612b47c?w=150&h=150&fit=crop",
rating: 5
},
{
quote: "KLC's consulting approach helped us navigate complex organizational change with remarkable success.",
author: "Dr. Amit Patel",
position: "Director, Healthcare Innovation",
program: "Organizational Consulting",
image: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=150&h=150&fit=crop",
rating: 5
}
];
// Animated counter component
function AnimatedCounter({
targetValue,
suffix = "",
duration = 2000,
isVisible = false
}: {
targetValue: number;
suffix?: string;
duration?: number;
isVisible?: boolean;
}) {
const [currentValue, setCurrentValue] = useState(0);
useEffect(() => {
if (!isVisible) return;
const startTime = Date.now();
const animate = () => {
const elapsed = Date.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
// Easing function for smooth animation
const easeOutExpo = progress === 1 ? 1 : 1 - Math.pow(2, -10 * progress);
const newValue = Math.floor(targetValue * easeOutExpo);
setCurrentValue(newValue);
if (progress < 1) {
requestAnimationFrame(animate);
}
};
requestAnimationFrame(animate);
}, [isVisible, targetValue, duration]);
return (
<span>
{currentValue.toLocaleString()}{suffix}
</span>
);
}
// Intersection Observer hook for triggering animations
function useIntersectionObserver(options = {}) {
const [isVisible, setIsVisible] = useState(false);
const elementRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true);
}
},
{ threshold: 0.3, ...options }
);
if (elementRef.current) {
observer.observe(elementRef.current);
}
return () => observer.disconnect();
}, []);
return [elementRef, isVisible] as const;
}
export function OurImpact() {
const [statsRef, statsVisible] = useIntersectionObserver();
useEffect(() => {
document.title = 'Our Impact - About Us | KLC';
window.scrollTo(0, 0);
}, []);
return (
<div className="min-h-screen" style={{ backgroundColor: '#FFFFFF' }}>
{/* Hero Section - Services Page Style */}
<section className="relative min-h-[90vh] flex flex-col">
<div className="absolute inset-0 z-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1460472178825-e5240623afd5?w=1920&h=1080&fit=crop"
alt="Measuring leadership impact and organizational transformation"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-r from-black/80 via-black/70 to-black/60"></div>
</div>
<div className="relative z-10 flex-1 flex items-center">
<div className="container mx-auto section-margin-x">
<div className="text-center max-w-5xl mx-auto">
<div className="branded-tag-system-white mb-8 justify-center">
<div className="dot"></div>
<span className="text">Knowledge Leadership Centre</span>
</div>
<h1 className="text-h1-white mb-6">
Our Impact
</h1>
<p className="text-body-lg-white mb-8 max-w-2xl mx-auto">
Real numbers. Real transformation. Discover the measurable difference we've made
across industries and organizations worldwide through our leadership development expertise.
</p>
<div className="flex flex-col sm:flex-row gap-4 mb-12 justify-center">
<PrimaryCTAButton
text="View Success Stories"
onClick={() => document.getElementById('testimonials')?.scrollIntoView({ behavior: 'smooth' })}
className="management-dev-primary-cta"
/>
<Button
onClick={() => navigateTo('/contact')}
className="management-dev-glassmorphic-btn text-body px-8 py-4 min-h-[52px] border text-white transition-all duration-300"
style={{
fontFamily: 'var(--font-family-base)'
}}
>
<ArrowRight className="w-5 h-5 mr-2" />
Get Started
</Button>
</div>
</div>
</div>
</div>
{/* Statistics Section - Embedded in Hero */}
<div className="relative z-10 border-t border-white/20 backdrop-blur-sm bg-black/20" ref={statsRef}>
<div className="container mx-auto section-margin-x py-12">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8 text-center max-w-5xl mx-auto">
<div>
<div className="text-h2-white mb-2">
<AnimatedCounter
targetValue={26643}
isVisible={statsVisible}
/>
</div>
<div className="text-small-white opacity-90">Participants Developed</div>
</div>
<div>
<div className="text-h2-white mb-2">
<AnimatedCounter
targetValue={1220}
isVisible={statsVisible}
/>
</div>
<div className="text-small-white opacity-90">Programs Delivered</div>
</div>
<div>
<div className="text-h2-white mb-2">
<AnimatedCounter
targetValue={152}
isVisible={statsVisible}
/>
+
</div>
<div className="text-small-white opacity-90">Organizations Transformed</div>
</div>
<div>
<div className="text-h2-white mb-2">96%</div>
<div className="text-small-white opacity-90">Client Satisfaction</div>
</div>
</div>
</div>
</div>
</section>
{/* Partners Section - Redesigned According to JSON Config */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
{/* Statistics Section - Landing Page Style */}
<div className="mb-20">
<div className="grid lg:grid-cols-2 gap-16 items-center max-w-7xl mx-auto">
{/* Left Column - Descriptive Content */}
<div>
<h2 className="text-h2 mb-6 text-black">
Trusted by Industry Leaders
</h2>
{/* Industries We Serve */}
<div className="mb-6">
<h3 className="text-h3 mb-6">Industries We Serve</h3>
<div className="flex flex-wrap gap-4">
{[
"Financial Services", "Investment Banking", "Asset Management", "Technology",
"Healthcare", "Manufacturing", "Real Estate", "Consulting"
].map((sector) => (
<span
key={sector}
className="px-6 py-3 text-body text-gray-700 border border-primary rounded-full transition-all duration-300 hover:bg-primary hover:text-white hover:shadow-lg hover:scale-105 cursor-default group"
style={{
backgroundColor: '#FFFFFF',
borderColor: 'var(--color-primary)',
}}
>
<span className="group-hover:animate-pulse">{sector}</span>
</span>
))}
</div>
</div>
</div>
{/* Right Column - Statistics with Yellow Bullets */}
<div className="space-y-8">
{[
{ value: "27,000+", label: "Leaders Developed" },
{ value: "150+", label: "Corporate Clients" },
{ value: "20+", label: "Countries Served" }
].map((stat, i) => (
<div
key={stat.label}
className={`flex items-center gap-6 ${i < 2 ? 'border-b border-gray-200 pb-8' : ''}`}
style={{ animation: `fade-in-up 0.6s ease-out ${i * 0.1}s both` }}
>
{/* Yellow Bullet Point */}
<div
className="w-3 h-3 rounded-full flex-shrink-0"
style={{ backgroundColor: 'var(--color-accent)' }}
></div>
{/* Stats Content */}
<div>
<div className="stats-number text-primary mb-1">{stat.value}</div>
<p className="text-body font-semibold text-black uppercase tracking-wide">
{stat.label}
</p>
</div>
</div>
))}
</div>
</div>
</div>
{/* Client Logos Grid */}
<div className="mb-20">
<h3 className="text-h3 text-center mb-12">Our Valued Partners</h3>
<div className="grid grid-cols-2 md:grid-cols-4 gap-8 max-w-6xl mx-auto">
{clientLogos.slice(0, 16).map((client, index) => {
// Calculate appropriate width based on original logo dimensions
const scaledWidth = client.width > 200 ? Math.round(client.width * 0.7) : client.width * 1.1;
const displayWidth = Math.max(120, Math.min(scaledWidth, 200));
return (
<div
key={`${client.name}-${index}`}
className="group p-6 flex items-center justify-center h-24 transition-all duration-300 cursor-pointer border border-gray-100 rounded-xl hover:border-primary/30 hover:shadow-lg hover:-translate-y-1"
>
<img
src={client.logo}
alt={client.name}
style={{
width: `${displayWidth}px`,
height: 'auto',
maxHeight: '50px',
objectFit: 'contain',
filter: 'grayscale(100%) opacity(0.7)',
transition: 'all 0.3s ease'
}}
onMouseEnter={(e) => {
e.currentTarget.style.filter = 'grayscale(0%) opacity(1)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.filter = 'grayscale(100%) opacity(0.7)';
}}
/>
</div>
);
})}
</div>
</div>
{/* Partnership CTA Section - Two Column Layout */}
<div className="max-w-7xl mx-auto">
<Card className="border-0 rounded-2xl overflow-hidden card-shadow-dramatic" style={{ backgroundColor: 'rgb(249, 250, 251)' }}>
<CardContent className="p-0">
<div className="grid lg:grid-cols-2 gap-0 items-center min-h-[400px]">
{/* Left Column - Partnership Graphic */}
<div className="relative h-full min-h-[400px] overflow-hidden">
<img
src="https://images.unsplash.com/photo-1739285452621-59d92842fcc8?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxidXNpbmVzcyUyMGhhbmRzaGFrZSUyMHBhcnRuZXJzaGlwJTIwcHJvZmVzc2lvbmFsJTIwbWVldGluZ3xlbnwxfHx8fDE3NTU1OTg0NTV8MA&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral"
alt="Partnership collaboration"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-r from-primary/80 to-primary/40"></div>
</div>
{/* Right Column - CTA Content */}
<div className="p-12 flex flex-col justify-center bg-gray-50">
{/* Branded Tag */}
<div className="mb-6">
<div className="branded-tag-system">
<div className="dot"></div>
<span className="text">Partner With Us</span>
</div>
</div>
{/* Heading */}
<h3 className="text-h2 mb-6 text-black">
Ready to Transform Your Leadership?
</h3>
{/* Description */}
<p className="text-body-lg text-muted mb-8 leading-relaxed">
Join our network of successful organizations and unlock your team's full potential.
<span className="text-primary font-semibold"> Get in touch</span> to start your development journey today.
</p>
{/* Sticky CTA Button */}
<div className="sticky top-8">
<button
onClick={() => navigateTo('/contact')}
className="w-full px-8 py-4 rounded-lg font-semibold transition-all duration-300 hover:shadow-xl mb-4 group"
style={{
backgroundColor: 'var(--color-primary)',
color: '#FFFFFF',
fontFamily: 'var(--font-family-base)',
fontSize: '1.125rem',
fontWeight: '600',
border: 'none'
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = '#030359';
e.currentTarget.style.transform = 'translateY(-2px)';
e.currentTarget.style.boxShadow = '0 12px 24px rgba(4, 4, 91, 0.3)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = 'var(--color-primary)';
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.boxShadow = 'none';
}}
>
<span className="flex items-center justify-center gap-2">
Schedule a Partnership Discussion
<ArrowRight className="w-5 h-5 group-hover:translate-x-1 transition-transform duration-300" />
</span>
</button>
{/* Supporting Information */}
<div className="bg-white/80 backdrop-blur-sm rounded-lg p-4 border border-primary/20">
<p className="text-small text-muted text-center leading-relaxed">
Connect with our partnership specialists to explore collaboration opportunities
and discuss your organization's specific leadership development needs.
</p>
</div>
</div>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
</section>
{/* Success Stories Section - Branded Testimonials */}
<div id="testimonials">
<TestimonialsSection
customTestimonials={testimonialHighlights.map(testimonial => ({
name: testimonial.author,
role: testimonial.position,
company: testimonial.program,
avatar: testimonial.image,
quote: testimonial.quote,
rating: testimonial.rating,
isVideo: false
}))}
title="What Our Clients Say"
subtitle="Don't just take our word for it. Here's what leaders from our partner organizations have to say about their transformational experiences with KLC."
tagText="Client Success"
/>
</div>
{/* Additional Metrics Section - Redesigned */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="text-center mb-16">
<Badge
className="mb-6 text-body px-4 py-2"
style={{
backgroundColor: 'rgba(4, 4, 91, 0.1)',
color: 'var(--color-primary)',
border: 'none'
}}
>
Transformation Metrics
</Badge>
<h2 className="text-h2 mb-6">
Measuring Real Transformation
</h2>
<p className="text-body-lg text-muted max-w-3xl mx-auto leading-relaxed">
Our impact extends far beyond statistics. We measure success through the
lasting transformation we create in leadership capabilities, organizational
culture, and sustainable business outcomes.
</p>
</div>
<div className="grid lg:grid-cols-3 gap-8 max-w-6xl mx-auto">
{[
{
icon: TrendingUp,
metric: "85%",
label: "Leadership Effectiveness",
description: "Average improvement in leadership effectiveness scores within 6 months",
details: ["Decision-making quality", "Team engagement", "Strategic thinking", "Change management"]
},
{
icon: Award,
metric: "92%",
label: "Client Satisfaction",
description: "Client satisfaction and program completion rate across all services",
details: ["Program quality", "Facilitator expertise", "Content relevance", "Measurable outcomes"]
},
{
icon: Globe,
metric: "15+",
label: "Global Reach",
description: "Countries where our alumni now lead organizations and drive change",
details: ["Global network", "Cultural diversity", "Best practices", "Knowledge transfer"]
}
].map((stat, index) => {
const Icon = stat.icon;
return (
<Card
key={index}
className="border-0 shadow-sm hover:shadow-lg transition-all duration-300 group h-full"
style={{ backgroundColor: '#FFFFFF' }}
>
<CardContent className="p-8">
{/* Icon and Metric */}
<div className="text-center mb-6">
<div
className="w-20 h-20 rounded-2xl flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform duration-300"
style={{ backgroundColor: 'rgba(4, 4, 91, 0.1)' }}
>
<Icon className="w-10 h-10 text-primary" />
</div>
<div className="text-4xl font-bold text-primary mb-2">
{stat.metric}
</div>
<h3 className="text-h4 text-black font-semibold">
{stat.label}
</h3>
</div>
{/* Description */}
<p className="text-body text-muted leading-relaxed mb-6 text-center">
{stat.description}
</p>
{/* Details */}
<div className="space-y-3">
<h4 className="text-subhead text-black font-medium">Key Areas:</h4>
{stat.details.map((detail, detailIndex) => (
<div key={detailIndex} className="flex items-center gap-3">
<CheckCircle className="w-4 h-4 text-primary flex-shrink-0" />
<span className="text-small text-muted">{detail}</span>
</div>
))}
</div>
</CardContent>
</Card>
);
})}
</div>
</div>
</section>
{/* CTA Section - Branded Banner Style */}
<section className="relative h-[700px] overflow-hidden">
{/* Background Image */}
<div className="absolute inset-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1552664730-d307ca884978?w=2940&h=1200&fit=crop"
alt="Professional team collaborating in modern office"
className="w-full h-full object-cover"
/>
{/* Subtle dark overlay for overall image */}
<div className="absolute inset-0 bg-black/30" />
{/* Gradient overlay for better text readability */}
<div className="absolute inset-0 bg-gradient-to-r from-black/20 via-transparent to-black/60" />
</div>
{/* Content Container */}
<div className="relative h-full flex items-center justify-end section-margin-x">
{/* CTA Content Block */}
<div
className="bg-opacity-95 backdrop-blur-sm rounded-lg p-16 max-w-2xl"
style={{
backgroundColor: 'var(--color-primary)'
}}
>
{/* Branded Tag */}
<div className="mb-6">
<div className="branded-tag-system-white">
<div className="dot"></div>
<span className="text">
Next Steps
</span>
</div>
</div>
{/* Main Headline */}
<h2 className="text-h2-white leading-tight mb-8">
Ready to Create Your Own Success Story?
<span
className="italic"
style={{ color: 'var(--color-accent)' }}
>
{" "}Join the leaders{" "}
</span>
transforming their organizations.
</h2>
{/* CTA Button */}
<PrimaryCTAButton
text="Explore Our Services"
onClick={() => navigateTo('/services/leadership-development')}
ariaLabel="Explore our leadership development services"
className="cta-banner-yellow"
/>
{/* Supporting Text */}
<p className="text-body-white mt-6 opacity-90">
Connect with our leadership experts to discover how KLC's proven methodologies
can transform your organization's performance and culture.
</p>
</div>
</div>
</section>
</div>
);
}

View File

@@ -0,0 +1,997 @@
import React, { useEffect, useState } from 'react';
import { navigateTo } from '../Router';
import { PrimaryCTAButton } from '../PrimaryCTAButton';
import { Button } from '../ui/button';
import { Card, CardContent } from '../ui/card';
import { Badge } from '../ui/badge';
import { ImageWithFallback } from '../figma/ImageWithFallback';
import { BrandedTag } from './BrandedTag';
import {
Eye,
Target,
Users,
Brain,
TrendingUp,
Lightbulb,
ArrowRight,
CheckCircle,
Globe,
BarChart3,
Layers,
Compass
} from 'lucide-react';
// Vision pillars data
const visionPillars = [
{
title: "World-Class Institution in Leadership",
description: "Establishing ourselves as a premier global institution recognized for excellence in leadership thought and practice, setting industry standards for development methodologies.",
icon: Globe,
gradient: "from-blue-600 to-blue-700",
mainStat: {
label: "Global Recognition",
value: "+96%",
color: "text-primary"
},
chartData: [
{ label: "2020", value: 20 },
{ label: "2021", value: 45 },
{ label: "2022", value: 70 },
{ label: "2023", value: 85 },
{ label: "2024", value: 96 }
],
metrics: [
{ label: "Excellence", value: "94%", color: "text-primary" },
{ label: "Recognition", value: "91%", color: "text-primary" }
]
},
{
title: "Partnership-Driven Capacity Building",
description: "Collaborating with institutions to build sustainable leadership capacity and capability that drives organizational transformation and long-term success.",
icon: Users,
gradient: "from-yellow-500 to-yellow-600",
mainStat: {
label: "Partnership Growth",
value: "+78%",
color: "text-primary"
},
progressMetrics: [
{ label: "Partner Satisfaction", value: 82, color: "#F8C301" },
{ label: "Capacity Building", value: 76, color: "#04045B" },
{ label: "Retention Rate", value: 84, color: "#F8C301" }
],
metrics: []
},
{
title: "Individual Leadership Discovery",
description: "Facilitating individuals to discover and develop their personal leadership resources, unlocking their unique potential to create meaningful impact.",
icon: Compass,
gradient: "from-purple-600 to-indigo-600",
mainStat: {
label: "Development Speed",
value: "65%",
color: "text-primary"
},
topMetrics: [
{ label: "Speed", value: "65%", color: "text-primary" },
{ label: "Alignment", value: "89%", color: "text-primary" }
],
bottomMetrics: [
{ label: "Quality", value: "91%", color: "text-primary" },
{ label: "Time Reduction", value: "-65%", color: "text-primary" },
{ label: "Impact", value: "89%", color: "text-primary" }
]
}
];
// Approach timeline data
const approachSteps = [
{
title: "Client Context Alignment",
description: "Deep understanding of unique organizational challenges, culture, and strategic objectives through comprehensive assessment and stakeholder engagement.",
details: [
"Organizational diagnostic and culture assessment",
"Leadership capability gap analysis",
"Strategic business alignment review",
"Stakeholder needs analysis"
],
icon: Target
},
{
title: "Research Anchored Methodology",
description: "Evidence-based methodologies and frameworks grounded in behavioral science, leadership psychology, and proven best practices from global research.",
details: [
"Latest research in leadership effectiveness",
"Behavioral science applications",
"Validated assessment tools and frameworks",
"Global best practice integration"
],
icon: Brain
},
{
title: "Co-Created Program Design",
description: "Collaborative program development with clients, ensuring solutions are tailored, practical, and aligned with specific organizational needs and constraints.",
details: [
"Joint design workshops with key stakeholders",
"Customized learning journeys and pathways",
"Practical application focus",
"Measurable outcome definition"
],
icon: Lightbulb
}
];
// Leadership orientations preview
const leadershipOrientations = [
{
orientation: "Thinking",
description: "How leaders process information, make decisions, and approach complex challenges",
aspects: ["Strategic thinking", "Systems thinking", "Critical analysis", "Creative problem-solving"]
},
{
orientation: "Risk Appetite",
description: "Leaders' comfort with uncertainty, innovation, and calculated risk-taking",
aspects: ["Innovation tolerance", "Change agility", "Calculated risk-taking", "Uncertainty navigation"]
},
{
orientation: "Power",
description: "How leaders use influence, authority, and positional power to drive results",
aspects: ["Influence strategies", "Authority dynamics", "Empowerment approaches", "Decision rights"]
},
{
orientation: "Interpersonal/Political",
description: "Leaders' ability to navigate relationships, coalitions, and organizational dynamics",
aspects: ["Relationship building", "Coalition management", "Stakeholder engagement", "Political savvy"]
}
];
export function OurVision() {
const [activeStep, setActiveStep] = useState(0);
useEffect(() => {
document.title = 'Our Vision - About Us | KLC';
window.scrollTo(0, 0);
}, []);
// Auto-advance timeline steps
useEffect(() => {
const interval = setInterval(() => {
setActiveStep((prev) => (prev + 1) % approachSteps.length);
}, 4000);
return () => clearInterval(interval);
}, []);
return (
<div className="min-h-screen" style={{ backgroundColor: '#FFFFFF' }}>
{/* Hero Section - Our Impact Page Style */}
<section className="relative min-h-[90vh] flex flex-col">
<div className="absolute inset-0 z-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1552664730-d307ca884978?w=1920&h=1080&fit=crop"
alt="Leadership vision and transformation - Our Vision"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-r from-black/80 via-black/70 to-black/60"></div>
</div>
<div className="relative z-10 flex-1 flex items-center">
<div className="container mx-auto section-margin-x">
<div className="text-center max-w-5xl mx-auto">
<div className="branded-tag-system-white mb-8 justify-center">
<div className="dot"></div>
<span className="text">Knowledge Leadership Centre</span>
</div>
<h1 className="text-h1-white mb-6">
Our Vision
</h1>
<p className="text-body-lg-white mb-8 max-w-2xl mx-auto">
Building the next generation of transformational leaders who drive organizational
success and create lasting positive impact worldwide through excellence in leadership development.
</p>
<div className="flex flex-col sm:flex-row gap-4 mb-12 justify-center">
<PrimaryCTAButton
text="Explore Our Approach"
onClick={() => document.getElementById('vision-pillars')?.scrollIntoView({ behavior: 'smooth' })}
className="management-dev-primary-cta"
/>
<Button
onClick={() => navigateTo('/contact')}
className="management-dev-glassmorphic-btn text-body px-8 py-4 min-h-[52px] border text-white transition-all duration-300"
style={{
fontFamily: 'var(--font-family-base)'
}}
>
<ArrowRight className="w-5 h-5 mr-2" />
Get Started
</Button>
</div>
</div>
</div>
</div>
{/* Vision Statistics Section - Embedded in Hero */}
<div className="relative z-10 border-t border-white/20 backdrop-blur-sm bg-black/20">
<div className="container mx-auto section-margin-x py-8">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8 text-center max-w-5xl mx-auto">
<div>
<div className="text-h2-white mb-2">3</div>
<div className="text-small-white opacity-90">Vision Pillars</div>
</div>
<div>
<div className="text-h2-white mb-2">96%</div>
<div className="text-small-white opacity-90">Client Success Rate</div>
</div>
<div>
<div className="text-h2-white mb-2">25+</div>
<div className="text-small-white opacity-90">Years Experience</div>
</div>
<div>
<div className="text-h2-white mb-2">Global</div>
<div className="text-small-white opacity-90">Impact Reach</div>
</div>
</div>
</div>
</div>
</section>
{/* Vision Pillars - Redesigned */}
<section id="vision-pillars" className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="text-center mb-16">
<Badge
className="mb-6 text-body px-4 py-2"
style={{
backgroundColor: 'rgba(4, 4, 91, 0.1)',
color: 'var(--color-primary)',
border: 'none'
}}
>
Foundation
</Badge>
<h2 className="text-h2 mb-6">Three Pillars of Our Vision</h2>
<p className="text-body-lg text-muted max-w-3xl mx-auto leading-relaxed">
Our comprehensive approach to leadership development is built on three foundational pillars
that guide everything we do and drive measurable transformation.
</p>
</div>
<div className="grid lg:grid-cols-3 gap-12 max-w-7xl mx-auto">
{visionPillars.map((pillar, index) => (
<div key={pillar.title} className="group">
<Card
className="border-0 shadow-sm hover:shadow-xl transition-all duration-300 h-full bg-white p-0"
>
<CardContent className="p-8">
{/* Icon */}
<div
className="w-16 h-16 rounded-xl flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-300"
style={{ backgroundColor: 'rgba(4, 4, 91, 0.08)' }}
>
{React.createElement(pillar.icon, {
className: "w-8 h-8 text-primary"
})}
</div>
{/* Title */}
<h3 className="text-h4 mb-4 text-black leading-tight">
{pillar.title}
</h3>
{/* Description */}
<p className="text-body text-muted leading-relaxed mb-6">
{pillar.description}
</p>
{/* Main Stat */}
<div className="mb-6">
<div className="text-small text-muted mb-1">{pillar.mainStat.label}</div>
<div className={`text-3xl font-bold ${pillar.mainStat.color}`}>
{pillar.mainStat.value}
</div>
</div>
{/* Data Visualization Section */}
{/* First Pillar: Bar Chart */}
{index === 0 && (
<>
<div className="mb-6">
<div className="flex items-end justify-between gap-1 h-20 mb-2">
{pillar.chartData.map((item, barIndex) => (
<div key={item.label} className="flex flex-col items-center flex-1">
<div
className="w-full rounded-t-sm transition-all duration-1000 delay-300"
style={{
height: `${item.value}%`,
backgroundColor: barIndex >= 3 ? '#04045B' : '#E5E7EB',
minHeight: '8px'
}}
></div>
<div className="text-xs text-muted mt-1">{item.label}</div>
</div>
))}
</div>
</div>
<div className="grid grid-cols-2 gap-4">
{pillar.metrics.map((metric, metricIndex) => (
<div key={metric.label} className="text-center">
<div className={`text-2xl font-bold ${metric.color}`}>
{metric.value}
</div>
<div className="text-small text-muted">
{metric.label}
</div>
</div>
))}
</div>
</>
)}
{/* Second Pillar: Progress Bars */}
{index === 1 && (
<div className="space-y-4">
{pillar.progressMetrics.map((metric, metricIndex) => (
<div key={metric.label}>
<div className="flex justify-between items-center mb-2">
<span className="text-small text-muted">{metric.label}</span>
<span className="text-small font-medium text-black">{metric.value}%</span>
</div>
<div className="w-full bg-gray-200 rounded-full h-2">
<div
className="h-2 rounded-full transition-all duration-1000"
style={{
width: `${metric.value}%`,
backgroundColor: metric.color,
animationDelay: `${(metricIndex + 1) * 200}ms`
}}
></div>
</div>
</div>
))}
</div>
)}
{/* Third Pillar: Multiple Metrics Grid */}
{index === 2 && (
<>
{/* Top Metrics */}
<div className="grid grid-cols-2 gap-4 mb-6">
{pillar.topMetrics.map((metric, metricIndex) => (
<div key={metric.label} className="text-center">
<div className="text-small text-muted mb-1">{metric.label}</div>
<div className={`text-2xl font-bold ${metric.color}`}>
{metric.value}
</div>
</div>
))}
</div>
{/* Bottom Metrics */}
<div className="grid grid-cols-3 gap-3">
{pillar.bottomMetrics.map((metric, metricIndex) => (
<div key={metric.label} className="text-center">
<div className={`text-lg font-bold ${metric.color}`}>
{metric.value}
</div>
<div className="text-xs text-muted">
{metric.label}
</div>
</div>
))}
</div>
</>
)}
</CardContent>
</Card>
</div>
))}
</div>
</div>
</section>
{/* How Our Work Aligns - Redesigned Interactive Timeline */}
<section className="py-20" style={{ background: 'linear-gradient(135deg, rgba(247, 247, 253, 0.3) 0%, rgba(248, 195, 1, 0.05) 100%)' }}>
<div className="container mx-auto section-margin-x">
<div className="text-center mb-16">
<Badge
className="mb-6 text-body px-4 py-2"
style={{
backgroundColor: 'rgba(4, 4, 91, 0.1)',
color: 'var(--color-primary)',
border: 'none'
}}
>
Methodology
</Badge>
<h2 className="text-h2 mb-6">Our Strategic Approach</h2>
<p className="text-body-lg text-muted max-w-3xl mx-auto leading-relaxed">
A clear step-by-step process that drives measurable impact and lasting transformation.
</p>
</div>
<div className="flex flex-col lg:flex-row gap-12 max-w-6xl mx-auto">
{/* Timeline Steps - Left Side */}
<div className="flex lg:flex-col gap-6 lg:w-1/3">
{/* Progress Indicator */}
<div className="hidden lg:block text-center mb-6">
<div className="text-small text-muted font-medium">
Step {activeStep + 1} of {approachSteps.length}
</div>
<div className="w-full rounded-full h-2 mt-2" style={{ backgroundColor: 'rgba(4, 4, 91, 0.1)' }}>
<div
className="h-2 rounded-full transition-all duration-500 ease-out"
style={{
backgroundColor: 'var(--color-primary)',
width: `${((activeStep + 1) / approachSteps.length) * 100}%`
}}
></div>
</div>
</div>
{/* Step Buttons */}
{approachSteps.map((step, index) => (
<button
key={step.title}
onClick={() => setActiveStep(index)}
className={`group flex items-center gap-4 px-6 py-4 rounded-xl border-2 transition-all duration-300 text-left w-full
${activeStep === index
? 'bg-primary text-white border-primary shadow-lg'
: 'bg-white text-black hover:shadow-md hover:scale-105'
}
`}
style={{
borderColor: activeStep === index ? 'var(--color-primary)' : 'rgba(4, 4, 91, 0.2)',
backgroundColor: activeStep === index ? 'var(--color-primary)' : '#FFFFFF'
}}
onMouseEnter={(e) => {
if (activeStep !== index) {
e.currentTarget.style.borderColor = 'var(--color-primary)';
}
}}
onMouseLeave={(e) => {
if (activeStep !== index) {
e.currentTarget.style.borderColor = 'rgba(4, 4, 91, 0.2)';
}
}}
>
{/* Step Number */}
<div
className={`w-10 h-10 flex items-center justify-center rounded-full font-bold text-lg transition-all duration-300
${activeStep === index
? 'bg-white text-primary'
: 'bg-primary text-white group-hover:scale-110'
}
`}
>
{index + 1}
</div>
{/* Step Info */}
<div className="flex-1 min-w-0">
<div
className={`font-medium text-body leading-tight transition-colors duration-300
${activeStep === index ? 'text-white' : 'text-black'}
`}
>
{step.title}
</div>
{/* Step Icon */}
<div className="mt-2">
{React.createElement(step.icon, {
className: `w-5 h-5 transition-all duration-300 ${
activeStep === index ? 'text-white' : 'text-primary'
}`
})}
</div>
</div>
</button>
))}
</div>
{/* Active Step Content - Right Side */}
<div className="flex-1 lg:w-2/3">
<Card
className="border-0 shadow-xl transition-all duration-500 ease-out bg-white"
style={{ minHeight: '500px' }}
>
<CardContent className="p-8 lg:p-10">
{/* Mobile Progress Indicator */}
<div className="lg:hidden text-center mb-6">
<div className="text-small text-muted font-medium">
Step {activeStep + 1} of {approachSteps.length}
</div>
<div className="w-full rounded-full h-2 mt-2" style={{ backgroundColor: 'rgba(4, 4, 91, 0.1)' }}>
<div
className="h-2 rounded-full transition-all duration-500 ease-out"
style={{
backgroundColor: 'var(--color-primary)',
width: `${((activeStep + 1) / approachSteps.length) * 100}%`
}}
></div>
</div>
</div>
{/* Step Content */}
<div className="mb-8 fade-in animate-in duration-700">
<div className="flex items-center gap-4 mb-6">
<div
className="w-16 h-16 rounded-xl flex items-center justify-center transition-transform duration-300 hover:scale-110"
style={{ backgroundColor: 'rgba(4, 4, 91, 0.1)' }}
>
{React.createElement(approachSteps[activeStep].icon, {
className: "w-8 h-8 text-primary"
})}
</div>
<div>
<h3 className="text-h3 text-black leading-tight">
{approachSteps[activeStep].title}
</h3>
<div className="text-small text-primary font-medium mt-1">
Step {activeStep + 1} of {approachSteps.length}
</div>
</div>
</div>
<p className="text-body-lg text-muted leading-relaxed mb-8">
{approachSteps[activeStep].description}
</p>
</div>
{/* Key Components Accordion-Style */}
<div className="mb-8">
<h4 className="text-h4 text-black mb-6">Key Components</h4>
<div className="space-y-3">
{approachSteps[activeStep].details.map((detail, index) => (
<div key={index} className="group">
<div
className="flex items-start gap-3 p-4 rounded-lg transition-all duration-300 cursor-pointer hover:scale-102"
style={{
backgroundColor: 'rgba(4, 4, 91, 0.05)',
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = 'rgba(4, 4, 91, 0.08)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = 'rgba(4, 4, 91, 0.05)';
}}
>
<div className="w-6 h-6 rounded-full bg-primary flex items-center justify-center flex-shrink-0 mt-0.5 group-hover:scale-110 transition-transform duration-300">
<CheckCircle className="w-4 h-4 text-white" />
</div>
<span className="text-body text-black leading-relaxed">{detail}</span>
</div>
</div>
))}
</div>
</div>
{/* CTA Button - Always Visible */}
<div className="pt-6" style={{ borderTop: '1px solid rgba(4, 4, 91, 0.1)' }}>
<PrimaryCTAButton
text="Learn More About Our Approach"
onClick={() => navigateTo('/services/consulting')}
/>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
</section>
{/* Leadership Framework CTA - Redesigned */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="max-w-7xl mx-auto">
<div className="grid lg:grid-cols-2 gap-16 items-center">
{/* Content Side */}
<div>
{/* Modern Pill Badge */}
<div className="inline-flex items-center gap-3 px-6 py-3 rounded-full mb-8 shadow-sm transition-all duration-300 hover:shadow-md"
style={{
backgroundColor: 'rgba(248, 195, 1, 0.12)',
border: '1px solid rgba(248, 195, 1, 0.2)'
}}>
<div className="w-3 h-3 rounded-full animate-pulse"
style={{ backgroundColor: 'var(--color-accent)' }} />
<span className="text-small font-semibold text-black uppercase tracking-wide">
Proprietary Framework
</span>
</div>
<h3 className="text-h2 mb-8 text-black leading-tight">
Leadership Orientations Framework
</h3>
<p className="text-body-lg text-muted mb-10 leading-relaxed">
Our research-backed framework examines four critical dimensions that define
leadership effectiveness and drive organizational results. This proprietary
methodology helps leaders understand their natural orientations and develop
adaptive capabilities.
</p>
{/* Enhanced Framework Items */}
<div className="grid grid-cols-2 gap-6 mb-12">
{[
{
label: 'Thinking',
desc: 'Strategic & analytical approaches',
icon: Brain,
color: '#FFFFFF',
accentColor: 'var(--color-primary)'
},
{
label: 'Risk Appetite',
desc: 'Innovation & change tolerance',
icon: TrendingUp,
color: '#FFFFFF',
accentColor: 'var(--color-primary)'
},
{
label: 'Power',
desc: 'Influence & authority usage',
icon: Target,
color: '#FFFFFF',
accentColor: 'var(--color-primary)'
},
{
label: 'Interpersonal',
desc: 'Relationship & political navigation',
icon: Users,
color: '#FFFFFF',
accentColor: 'var(--color-primary)'
}
].map((item, index) => {
const Icon = item.icon;
return (
<Card
key={item.label}
className="border border-gray-200 shadow-md hover:shadow-lg transition-all duration-300 hover:-translate-y-2 cursor-pointer group overflow-hidden"
style={{ backgroundColor: item.color }}
>
<CardContent className="p-6 relative">
{/* Subtle background pattern */}
<div
className="absolute inset-0 opacity-5 transition-opacity duration-300 group-hover:opacity-10"
style={{
backgroundImage: 'radial-gradient(circle at 80% 20%, rgba(4,4,91,0.1) 0%, transparent 50%)'
}}
/>
<div className="relative z-10">
<div className="flex items-start gap-4 mb-4">
<div
className="w-12 h-12 rounded-xl flex items-center justify-center transition-all duration-300 group-hover:scale-110 group-hover:rotate-3"
style={{
backgroundColor: item.accentColor,
boxShadow: '0 4px 12px rgba(4,4,91,0.25)'
}}
>
<Icon
className="w-6 h-6 text-white"
/>
</div>
<div className="flex-1">
<h4 className="text-subhead text-black mb-2 font-semibold group-hover:text-primary transition-colors">
{item.label}
</h4>
<p className="text-small text-muted leading-relaxed">
{item.desc}
</p>
</div>
</div>
{/* Enhanced progress indicator */}
<div className="mt-4">
<div className="h-1.5 bg-gray-100 rounded-full overflow-hidden shadow-inner">
<div
className="h-full rounded-full transition-all duration-1000 group-hover:w-full"
style={{
width: '60%',
backgroundColor: item.accentColor,
boxShadow: '0 0 8px rgba(4,4,91,0.3)'
}}
/>
</div>
</div>
{/* Floating accent */}
<div
className="absolute top-4 right-4 w-2 h-2 rounded-full opacity-60 group-hover:opacity-100 transition-opacity duration-300"
style={{ backgroundColor: item.accentColor }}
/>
</div>
</CardContent>
</Card>
);
})}
</div>
<PrimaryCTAButton
text="Explore Our Framework"
onClick={() => navigateTo('/about/our-expertise')}
/>
</div>
{/* Enhanced Visual Side */}
<div className="relative">
<Card
className="border border-gray-200 shadow-2xl overflow-hidden"
style={{
background: '#FFFFFF'
}}
>
<CardContent className="p-10 relative">
{/* Sophisticated Background Pattern */}
<div
className="absolute inset-0 opacity-5"
style={{
backgroundImage: `
radial-gradient(circle at 25% 25%, rgba(4,4,91,0.3) 0%, transparent 40%),
radial-gradient(circle at 75% 75%, rgba(4,4,91,0.1) 0%, transparent 40%),
linear-gradient(45deg, rgba(4,4,91,0.05) 0%, transparent 30%, rgba(4,4,91,0.05) 70%, transparent 100%)
`
}}
/>
{/* Geometric accent elements */}
<div className="absolute top-8 right-8 w-16 h-16 border border-blue-300 opacity-30 rounded-lg rotate-12" />
<div className="absolute bottom-8 left-8 w-12 h-12 bg-blue-300 opacity-15 rounded-full" />
{/* Content */}
<div className="relative z-10">
{/* Header */}
<div className="text-center mb-10">
<div
className="w-20 h-20 rounded-2xl flex items-center justify-center mx-auto mb-6 relative overflow-hidden"
style={{
backgroundColor: 'var(--color-primary)',
border: '1px solid rgba(4, 4, 91, 0.3)'
}}
>
{/* Inner glow */}
<div className="absolute inset-2 rounded-xl bg-gradient-to-br from-white/20 to-transparent" />
<BarChart3 className="w-10 h-10 text-white relative z-10" />
</div>
<h4 className="text-h4 text-black mb-3 font-semibold">Framework Impact</h4>
<p className="text-body text-muted">
Proven results across organizations
</p>
</div>
{/* Enhanced Infographic Stats */}
<div className="space-y-8">
{/* Leadership Effectiveness */}
<div className="flex items-center gap-6">
<div className="relative">
{/* Circular progress ring */}
<svg className="w-20 h-20 transform -rotate-90" viewBox="0 0 80 80">
<circle
cx="40"
cy="40"
r="30"
stroke="rgba(4, 4, 91, 0.2)"
strokeWidth="4"
fill="none"
/>
<circle
cx="40"
cy="40"
r="30"
stroke="var(--color-primary)"
strokeWidth="4"
fill="none"
strokeDasharray={`${2 * Math.PI * 30}`}
strokeDashoffset={`${2 * Math.PI * 30 * (1 - 89 / 100)}`}
className="transition-all duration-2000 ease-out"
strokeLinecap="round"
/>
</svg>
<div className="absolute inset-0 flex items-center justify-center">
<span className="text-xl font-bold text-blue-600">89%</span>
</div>
</div>
<div className="flex-1">
<div className="text-body-lg text-black font-semibold mb-2">Leadership Effectiveness</div>
<div className="text-small text-muted mb-3">Improvement in 6 months</div>
{/* Horizontal progress bar */}
<div className="h-2 bg-gray-200 rounded-full overflow-hidden">
<div
className="h-full rounded-full transition-all duration-2000 ease-out"
style={{
width: '89%',
background: 'linear-gradient(90deg, var(--color-primary) 0%, rgba(4, 4, 91, 0.8) 100%)'
}}
/>
</div>
</div>
</div>
{/* Self-Awareness Growth */}
<div className="flex items-center gap-6">
<div className="relative">
{/* Circular progress ring */}
<svg className="w-20 h-20 transform -rotate-90" viewBox="0 0 80 80">
<circle
cx="40"
cy="40"
r="30"
stroke="rgba(4, 4, 91, 0.2)"
strokeWidth="4"
fill="none"
/>
<circle
cx="40"
cy="40"
r="30"
stroke="var(--color-primary)"
strokeWidth="4"
fill="none"
strokeDasharray={`${2 * Math.PI * 30}`}
strokeDashoffset={`${2 * Math.PI * 30 * (1 - 92 / 100)}`}
className="transition-all duration-2000 ease-out"
strokeLinecap="round"
style={{ transitionDelay: '0.5s' }}
/>
</svg>
<div className="absolute inset-0 flex items-center justify-center">
<span className="text-xl font-bold text-blue-600">92%</span>
</div>
</div>
<div className="flex-1">
<div className="text-body-lg text-black font-semibold mb-2">Self-Awareness Growth</div>
<div className="text-small text-muted mb-3">Better decision making</div>
{/* Horizontal progress bar */}
<div className="h-2 bg-gray-200 rounded-full overflow-hidden">
<div
className="h-full rounded-full transition-all duration-2000 ease-out"
style={{
width: '92%',
background: 'linear-gradient(90deg, var(--color-primary) 0%, rgba(4, 4, 91, 0.8) 100%)',
transitionDelay: '0.5s'
}}
/>
</div>
</div>
</div>
{/* Team Performance */}
<div className="flex items-center gap-6">
<div className="relative">
{/* Circular progress ring */}
<svg className="w-20 h-20 transform -rotate-90" viewBox="0 0 80 80">
<circle
cx="40"
cy="40"
r="30"
stroke="rgba(4, 4, 91, 0.2)"
strokeWidth="4"
fill="none"
/>
<circle
cx="40"
cy="40"
r="30"
stroke="var(--color-primary)"
strokeWidth="4"
fill="none"
strokeDasharray={`${2 * Math.PI * 30}`}
strokeDashoffset={`${2 * Math.PI * 30 * (1 - 76 / 100)}`}
className="transition-all duration-2000 ease-out"
strokeLinecap="round"
style={{ transitionDelay: '1s' }}
/>
</svg>
<div className="absolute inset-0 flex items-center justify-center">
<span className="text-xl font-bold text-blue-600">76%</span>
</div>
</div>
<div className="flex-1">
<div className="text-body-lg text-black font-semibold mb-2">Team Performance</div>
<div className="text-small text-muted mb-3">Enhanced collaboration</div>
{/* Horizontal progress bar */}
<div className="h-2 bg-gray-200 rounded-full overflow-hidden">
<div
className="h-full rounded-full transition-all duration-2000 ease-out"
style={{
width: '76%',
background: 'linear-gradient(90deg, var(--color-primary) 0%, rgba(4, 4, 91, 0.8) 100%)',
transitionDelay: '1s'
}}
/>
</div>
</div>
</div>
</div>
{/* Bottom accent with trust indicator */}
<div className="flex items-center justify-center mt-10 pt-8 border-t border-gray-200">
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
<CheckCircle className="w-5 h-5 text-blue-500" />
<span className="text-small text-black font-medium">500+ Organizations</span>
</div>
<div className="w-1 h-1 bg-blue-500 rounded-full" />
<div className="flex items-center gap-2">
<CheckCircle className="w-5 h-5 text-blue-500" />
<span className="text-small text-black font-medium">Proven Results</span>
</div>
</div>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
</div>
</section>
{/* CTA Section - Vision Banner Style */}
<section className="relative h-[700px] overflow-hidden">
{/* Background Image */}
<div className="absolute inset-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1600880292203-757bb62b4baf?w=2940&h=1200&fit=crop"
alt="Visionary leadership team planning strategy"
className="w-full h-full object-cover"
/>
{/* Subtle dark overlay for overall image */}
<div className="absolute inset-0 bg-black/30" />
{/* Gradient overlay for better text readability */}
<div className="absolute inset-0 bg-gradient-to-r from-black/20 via-transparent to-black/60" />
</div>
{/* Content Container */}
<div className="relative h-full flex items-center justify-end section-margin-x">
{/* CTA Content Block */}
<div
className="bg-opacity-95 backdrop-blur-sm rounded-lg p-16 max-w-2xl"
style={{
backgroundColor: 'var(--color-primary)'
}}
>
{/* Branded Tag */}
<div className="mb-6">
<div className="branded-tag-system-white">
<div className="dot"></div>
<span className="text">
Transform Your Vision
</span>
</div>
</div>
{/* Main Headline */}
<h2 className="text-h2-white leading-tight mb-8">
Ready to Build Your Leadership Vision?
<span
className="italic"
style={{ color: 'var(--color-accent)' }}
>
{" "}Start your transformation{" "}
</span>
journey today.
</h2>
{/* CTA Button */}
<PrimaryCTAButton
text="Explore Our Services"
onClick={() => navigateTo('/services/leadership-development')}
ariaLabel="Explore our leadership development services"
className="cta-banner-yellow"
/>
</div>
</div>
</section>
</div>
);
}

View File

@@ -0,0 +1 @@
// This file has been removed

View File

@@ -0,0 +1 @@
// This file has been removed

View File

@@ -0,0 +1 @@
// This file has been removed

View File

@@ -0,0 +1,27 @@
import React, { useState } from 'react'
const ERROR_IMG_SRC =
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODgiIGhlaWdodD0iODgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBvcGFjaXR5PSIuMyIgZmlsbD0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIzLjciPjxyZWN0IHg9IjE2IiB5PSIxNiIgd2lkdGg9IjU2IiBoZWlnaHQ9IjU2IiByeD0iNiIvPjxwYXRoIGQ9Im0xNiA1OCAxNi0xOCAzMiAzMiIvPjxjaXJjbGUgY3g9IjUzIiBjeT0iMzUiIHI9IjciLz48L3N2Zz4KCg=='
export function ImageWithFallback(props: React.ImgHTMLAttributes<HTMLImageElement>) {
const [didError, setDidError] = useState(false)
const handleError = () => {
setDidError(true)
}
const { src, alt, style, className, ...rest } = props
return didError ? (
<div
className={`inline-block bg-gray-100 text-center align-middle ${className ?? ''}`}
style={style}
>
<div className="flex items-center justify-center w-full h-full">
<img src={ERROR_IMG_SRC} alt="Error loading image" {...rest} data-original-url={src} />
</div>
</div>
) : (
<img src={src} alt={alt} className={className} style={style} {...rest} onError={handleError} />
)
}

View File

@@ -0,0 +1,78 @@
import { useState, useEffect, useRef } from 'react';
interface UseAnimatedCounterOptions {
start?: number;
end: number;
duration?: number;
decimals?: number;
suffix?: string;
}
export function useAnimatedCounter({
start = 0,
end,
duration = 2000,
decimals = 0,
suffix = ''
}: UseAnimatedCounterOptions) {
const [count, setCount] = useState(start);
const [isInView, setIsInView] = useState(false);
const countRef = useRef<HTMLSpanElement>(null);
const frameRef = useRef<number>();
const startTimeRef = useRef<number>();
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting && !isInView) {
setIsInView(true);
}
},
{ threshold: 0.1 }
);
if (countRef.current) {
observer.observe(countRef.current);
}
return () => observer.disconnect();
}, [isInView]);
useEffect(() => {
if (!isInView) return;
const animate = (currentTime: number) => {
if (!startTimeRef.current) startTimeRef.current = currentTime;
const elapsed = currentTime - startTimeRef.current;
const progress = Math.min(elapsed / duration, 1);
// Easing function for smooth animation
const easeOutQuart = 1 - Math.pow(1 - progress, 4);
const currentCount = start + (end - start) * easeOutQuart;
setCount(currentCount);
if (progress < 1) {
frameRef.current = requestAnimationFrame(animate);
}
};
frameRef.current = requestAnimationFrame(animate);
return () => {
if (frameRef.current) {
cancelAnimationFrame(frameRef.current);
}
};
}, [isInView, start, end, duration]);
const formattedCount = decimals > 0
? count.toFixed(decimals)
: Math.floor(count).toLocaleString();
return {
count: formattedCount + suffix,
ref: countRef
};
}

View File

@@ -0,0 +1,693 @@
import React, { useEffect, useState } from 'react';
import { Button } from '../ui/button';
import { Card, CardContent } from '../ui/card';
import { Badge } from '../ui/badge';
import { ImageWithFallback } from '../figma/ImageWithFallback';
import { navigateTo } from '../Router';
import { BrandedTag } from '../about/BrandedTag';
import { TestimonialsSection } from '../TestimonialsSection';
import { CTABannerSection } from '../CTABannerSection';
import StackedOfferSection from '../StackedOfferSection';
import {
Users,
Target,
ArrowRight,
CheckCircle,
Lightbulb,
Brain,
Eye,
TrendingUp,
MessageCircle,
BarChart3,
Compass,
Shield,
Network,
Zap,
Settings,
ChevronDown,
ChevronUp,
ArrowLeft,
Download,
Crown
} from 'lucide-react';
import { PrimaryCTAButton } from '../PrimaryCTAButton';
// Strategic consulting cards data for the stacking section
const consultingCards = [
{
id: 1,
title: "Organizational Structure Design",
subtitle: "Strategic Design & Optimization",
description:
"Comprehensive organizational design services that optimize structure, roles, and reporting relationships for enhanced performance and strategic alignment across all business functions.",
badge: "Featured",
color: "from-blue-600 to-blue-700",
icon: Network,
features: ["Organizational Assessment", "Structure Optimization", "Role Clarification", "Governance Design"],
stats: [
{ label: "Success Rate", value: "96%" },
{ label: "Organizations", value: "250+" },
{ label: "Duration", value: "3-6 Mo" }
]
},
{
id: 2,
title: "Vision & Mission Redefinition",
subtitle: "Purpose-Driven Strategic Alignment",
description:
"Collaborative development of inspiring vision and mission statements that drive organizational alignment, stakeholder engagement, and sustainable competitive advantage.",
badge: "Strategic",
color: "from-purple-600 to-purple-700",
icon: Compass,
features: ["Stakeholder Engagement", "Values Articulation", "Purpose Definition", "Strategic Narrative"],
stats: [
{ label: "Alignment Rate", value: "92%" },
{ label: "Leaders Engaged", value: "500+" },
{ label: "Duration", value: "2-4 Mo" }
]
},
{
id: 3,
title: "Leadership Capability Building",
subtitle: "Strategic Leadership Development",
description:
"Systematic development of leadership capabilities aligned with organizational strategy, including succession planning, talent development, and leadership pipeline optimization.",
badge: "Popular",
color: "from-green-600 to-green-700",
icon: TrendingUp,
features: ["Capability Frameworks", "Leadership Pipeline", "Succession Planning", "Talent Development"],
stats: [
{ label: "Development Rate", value: "89%" },
{ label: "Leaders Developed", value: "1,000+" },
{ label: "Duration", value: "6-12 Mo" }
]
},
{
id: 4,
title: "Strategic Transformation",
subtitle: "End-to-End Change Management",
description:
"Complete transformation support for major organizational change initiatives, including change strategy, stakeholder alignment, and cultural integration for sustainable success.",
badge: "Comprehensive",
color: "from-orange-600 to-orange-700",
icon: Zap,
features: ["Change Strategy", "Stakeholder Alignment", "Implementation Roadmap", "Culture Integration"],
stats: [
{ label: "Success Rate", value: "91%" },
{ label: "Transformations", value: "180+" },
{ label: "Duration", value: "12-24 Mo" }
]
}
];
const targetAudience = [
{
title: "Founders & CXOs",
description: "Visionary leaders driving organizational transformation and strategic growth",
icon: Lightbulb,
characteristics: ["Strategic vision", "Growth focus", "Change leadership", "Stakeholder management"]
},
{
title: "Boards",
description: "Board members seeking governance excellence and strategic oversight capabilities",
icon: Shield,
characteristics: ["Governance focus", "Risk oversight", "Strategic guidance", "Performance monitoring"]
},
{
title: "OD Leaders",
description: "Organizational development professionals implementing systematic change initiatives",
icon: Settings,
characteristics: ["Change expertise", "System thinking", "Process optimization", "Culture development"]
}
];
const outcomes = [
{
title: "Clarity in Leadership Direction",
description: "Clear strategic direction with aligned leadership behaviors and decision-making",
icon: Compass,
metrics: "96% of leadership teams report improved strategic clarity and alignment"
},
{
title: "Scalable Org Models",
description: "Organizational structures that support growth while maintaining operational efficiency",
icon: Network,
metrics: "78% improvement in organizational agility and decision-making speed"
},
{
title: "Faster Decision-Making & Alignment",
description: "Streamlined processes that enable rapid, informed decision-making across the organization",
icon: Zap,
metrics: "65% reduction in decision cycle time with improved cross-functional alignment"
}
];
const approachSteps = [
{
step: "01",
title: "Strategic Assessment",
description: "Comprehensive analysis of organizational current state, strategic challenges, and transformation opportunities. Together, we make your vision manifest through proven assessment methodologies and frameworks.",
details: ["Organizational scan", "Stakeholder interviews", "Performance analysis", "Gap assessment"],
icon: Eye
},
{
step: "02",
title: "Co-Creation Process",
description: "Collaborative design sessions with leadership to develop tailored strategic solutions and alignment. Together, we make your vision manifest through structured co-creation methodologies and proven frameworks.",
details: ["Leadership workshops", "Co-design sessions", "Stakeholder alignment", "Solution development"],
icon: Users
},
{
step: "03",
title: "Implementation Support",
description: "Hands-on guidance and support throughout the strategic transformation implementation journey. Together, we make your vision manifest through comprehensive support methodologies and proven frameworks.",
details: ["Change management", "Project oversight", "Training delivery", "Progress monitoring"],
icon: TrendingUp
},
{
step: "04",
title: "Continuous Optimization",
description: "Ongoing refinement and optimization to ensure sustainable transformation success and impact. Together, we make your vision manifest through continuous improvement methodologies and proven frameworks.",
details: ["Performance tracking", "Feedback integration", "Process refinement", "Capability building"],
icon: BarChart3
}
];
export function Consulting() {
const [expandedAudienceIndex, setExpandedAudienceIndex] = useState<number | null>(0);
useEffect(() => {
window.scrollTo(0, 0);
}, []);
const toggleAudienceExpanded = (index: number) => {
setExpandedAudienceIndex(expandedAudienceIndex === index ? null : index);
};
return (
<div className="min-h-screen" style={{ backgroundColor: '#FFFFFF' }}>
{/* Hero Section */}
<section className="relative min-h-[90vh] flex flex-col">
<div className="absolute inset-0 z-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1560472354-b33ff0c44a43?w=1920&h=1080&fit=crop"
alt="Strategic consulting meeting - business transformation"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-r from-black/80 via-black/70 to-black/60"></div>
</div>
<div className="relative z-10 flex-1 flex items-center">
<div className="container mx-auto section-margin-x">
<div className="text-center max-w-5xl mx-auto">
<div className="branded-tag-system-white mb-8 justify-center">
<div className="dot"></div>
<span className="text">Strategic Advisory</span>
</div>
<h1 className="text-h1-white mb-6">
Strategic Consulting Services
</h1>
<p className="text-body-lg-white mb-8 max-w-2xl mx-auto">
Expert strategic guidance for organizational transformation. Drive clarity,
alignment, and sustainable business growth through proven consulting methodologies.
</p>
<div className="flex flex-col sm:flex-row gap-4 mb-12 justify-center">
<PrimaryCTAButton
text="Book a consultation"
onClick={() => navigateTo('/contact')}
className="management-dev-primary-cta"
/>
<Button
onClick={() => window.open('/strategic-overview', '_blank')}
className="management-dev-glassmorphic-btn text-body px-8 py-4 min-h-[52px] border text-white transition-all duration-300"
style={{
fontFamily: 'var(--font-family-base)'
}}
>
<Download className="w-5 h-5 mr-2" />
Download Overview
</Button>
</div>
</div>
</div>
</div>
<div className="relative z-10 border-t border-white/20 backdrop-blur-sm bg-black/20">
<div className="container mx-auto section-margin-x py-8">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8 text-center max-w-5xl mx-auto">
<div>
<div className="text-h2-white mb-2">96%</div>
<div className="text-small-white opacity-90">Strategic alignment improvement</div>
</div>
<div>
<div className="text-h2-white mb-2">250+</div>
<div className="text-small-white opacity-90">Organizations transformed</div>
</div>
<div>
<div className="text-h2-white mb-2">78%</div>
<div className="text-small-white opacity-90">Faster decision-making</div>
</div>
<div>
<div className="text-h2-white mb-2">91%</div>
<div className="text-small-white opacity-90">Client satisfaction rating</div>
</div>
</div>
</div>
</div>
</section>
{/* Stacked Offer Section */}
<StackedOfferSection cards={consultingCards} />
{/* Who It's For Section */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="grid lg:grid-cols-2 gap-16 items-start max-w-7xl mx-auto">
<div className="lg:pr-8">
<h2 className="text-h2 mb-6 text-black leading-tight">
Who It's <span className="text-primary">For</span>
</h2>
<p className="text-body-lg text-muted leading-relaxed">
Our strategic consulting services are designed for leaders and organizations
committed to transformation, growth, and sustainable competitive advantage.
</p>
</div>
<div className="space-y-1">
{targetAudience.map((audience, index) => (
<div
key={index}
className="border-b border-gray-400 last:border-b-0"
>
<button
onClick={() => toggleAudienceExpanded(index)}
className="w-full py-6 px-0 flex items-center justify-between text-left hover:bg-transparent focus:outline-none group transition-all duration-200"
style={{ backgroundColor: 'transparent' }}
>
<span className="text-h4 text-black group-hover:text-primary transition-colors duration-200 pr-4">
{audience.title}
</span>
<div className="flex-shrink-0 ml-4">
{expandedAudienceIndex === index ? (
<ChevronUp className="w-6 h-6 text-primary transition-transform duration-200" />
) : (
<ChevronDown className="w-6 h-6 text-gray-400 group-hover:text-primary transition-all duration-200" />
)}
</div>
</button>
<div className={`overflow-hidden transition-all duration-300 ease-in-out ${
expandedAudienceIndex === index ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
}`}>
<div className="pb-6 pr-8">
<p className="text-body text-muted leading-relaxed mb-4">
{audience.description}
</p>
<div className="flex flex-wrap gap-2">
{audience.characteristics.map((characteristic, charIndex) => (
<Badge key={charIndex} variant="outline" className="text-small" style={{ fontFamily: 'var(--font-family-base)' }}>
{characteristic}
</Badge>
))}
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</section>
{/* Expected Outcomes Section */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="text-center mb-16 max-w-4xl mx-auto">
<h2 className="text-h2 mb-6">
Expected <span className="text-primary">Outcomes</span>
</h2>
<p className="text-body-lg text-muted">
Our strategic consulting delivers measurable improvements in organizational
clarity, agility, and decision-making effectiveness across all business functions.
</p>
</div>
{/* Three-Column Layout - Reference Design Style */}
<div className="grid lg:grid-cols-3 gap-8 max-w-7xl mx-auto">
{/* Clarity in Leadership Direction */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-blue-50 to-blue-100 flex items-center justify-center mb-6">
<Compass className="w-10 h-10 text-primary" />
</div>
<h3 className="text-h3 text-black mb-4">
Clarity in Leadership Direction
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Clear strategic direction with aligned leadership behaviors and
decision-making frameworks for enhanced organizational effectiveness.
</p>
</div>
{/* Strategic Leadership Visualization */}
<div className="space-y-6">
<div className="flex justify-between items-center">
<span className="text-small text-muted font-medium">Strategic Clarity</span>
<span className="text-h4 text-green-600 font-bold">+96%</span>
</div>
<div className="relative">
<div className="flex items-end space-x-1 h-24 mb-4">
<div className="bg-gray-200 h-8 w-4 rounded-sm"></div>
<div className="bg-gray-300 h-12 w-4 rounded-sm"></div>
<div className="bg-gray-200 h-16 w-4 rounded-sm"></div>
<div className="bg-gray-300 h-10 w-4 rounded-sm"></div>
<div className="bg-green-400 h-20 w-4 rounded-sm"></div>
<div className="bg-green-500 h-24 w-4 rounded-sm"></div>
<div className="bg-green-600 h-22 w-4 rounded-sm"></div>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="text-center p-3 bg-blue-50 rounded-lg border border-blue-100">
<div className="text-xl font-bold text-primary">94%</div>
<div className="text-small text-muted">Alignment</div>
</div>
<div className="text-center p-3 bg-green-50 rounded-lg border border-green-100">
<div className="text-xl font-bold text-green-600">91%</div>
<div className="text-small text-muted">Direction</div>
</div>
</div>
</div>
</div>
{/* Scalable Org Models */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-yellow-50 to-yellow-100 flex items-center justify-center mb-6">
<Network className="w-10 h-10 text-accent" />
</div>
<h3 className="text-h3 text-black mb-4">
Scalable Org Models
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Organizational structures that support growth while maintaining
operational efficiency and strategic flexibility.
</p>
</div>
{/* Scalable Organization Metrics */}
<div className="space-y-6">
<div className="flex items-center justify-between mb-4">
<span className="text-small text-muted font-medium">Organizational Agility</span>
<div className="flex items-center">
<TrendingUp className="w-4 h-4 text-green-500 mr-1" />
<span className="text-small text-green-600 font-medium">+78%</span>
</div>
</div>
<div className="relative bg-gray-100 rounded-full h-3 mb-6">
<div
className="bg-gradient-to-r from-yellow-400 to-yellow-500 h-3 rounded-full transition-all duration-1000"
style={{ width: '78%' }}
></div>
</div>
<div className="space-y-3">
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Decision Speed</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
82%
</div>
</div>
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Structure Efficiency</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
76%
</div>
</div>
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Growth Readiness</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
84%
</div>
</div>
</div>
</div>
</div>
{/* Faster Decision-Making & Alignment */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-purple-50 to-purple-100 flex items-center justify-center mb-6">
<Zap className="w-10 h-10 text-primary" />
</div>
<h3 className="text-h3 text-black mb-4">
Faster Decision-Making & Alignment
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Streamlined processes that enable rapid, informed decision-making
with improved cross-functional alignment.
</p>
</div>
{/* Decision-Making KPIs */}
<div className="space-y-6">
<div className="grid grid-cols-2 gap-4">
<div className="text-center p-3 bg-blue-50 rounded-lg border border-blue-100">
<div className="flex items-center justify-center mb-1">
<span className="text-small text-muted mr-2">Speed</span>
<TrendingUp className="w-3 h-3 text-green-500" />
</div>
<div className="text-xl font-bold text-primary">65%</div>
</div>
<div className="text-center p-3 bg-green-50 rounded-lg border border-green-100">
<div className="flex items-center justify-center mb-1">
<span className="text-small text-muted mr-2">Alignment</span>
<div className="w-3 h-3 flex items-center justify-center">
<div className="w-0 h-0 border-l-2 border-r-2 border-b-3 border-transparent border-b-green-500"></div>
</div>
</div>
<div className="text-xl font-bold text-green-500">89%</div>
</div>
</div>
<div className="bg-gray-50 rounded-lg p-4">
<div className="flex justify-between items-center mb-2">
<span className="text-small text-muted font-medium">Decision Impact</span>
<span className="text-small text-primary font-bold">Cycle Time</span>
</div>
<div className="flex items-end justify-between">
<div className="text-2xl font-bold text-primary">91%</div>
<div className="text-2xl font-bold text-green-600">-65%</div>
</div>
</div>
<div className="grid grid-cols-3 gap-2">
<div className="text-center">
<div className="text-lg font-bold text-primary">91%</div>
<div className="text-xs text-muted">Quality</div>
</div>
<div className="text-center">
<div className="text-lg font-bold text-green-600">-65%</div>
<div className="text-xs text-muted">Time Reduction</div>
</div>
<div className="text-center">
<div className="text-lg font-bold text-blue-500">89%</div>
<div className="text-xs text-muted">Alignment</div>
</div>
</div>
</div>
</div>
</div>
{/* Results Confirmation Banner */}
<div className="mt-16 max-w-4xl mx-auto">
<div className="bg-gradient-to-r from-green-50 to-blue-50 rounded-xl p-6 border border-green-200">
<div className="flex items-center justify-center gap-3">
<div className="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center">
<CheckCircle className="w-5 h-5 text-green-600" />
</div>
<p className="text-body text-center" style={{ fontWeight: 'var(--font-weight-subhead)', color: '#059669' }}>
All outcomes measured within 4-6 months of engagement completion
</p>
</div>
</div>
</div>
</div>
</section>
{/* Our Approach Section - Carousel Design */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12 items-start max-w-7xl mx-auto">
{/* Left Side - Title, Description & Navigation */}
<div className="lg:col-span-5 lg:pr-8">
<h2 className="text-h2 mb-6 leading-tight">
Our <span className="text-primary">Approach</span>
</h2>
<p className="text-body-lg text-muted leading-relaxed mb-8">
Co-creation model with leadership using proven strategic methodologies: organizational
assessments, stakeholder interviews, and collaborative consulting for maximum impact.
</p>
{/* Navigation Controls */}
<div className="flex gap-3">
<button
onClick={() => {
const container = document.getElementById('consulting-approach-carousel');
if (container) {
container.scrollBy({ left: -384, behavior: 'smooth' });
}
}}
className="w-12 h-12 rounded-full bg-gray-100 hover:bg-primary hover:text-white transition-all duration-300 flex items-center justify-center border border-gray-200 hover:border-primary"
aria-label="Previous approach step"
>
<ArrowLeft className="w-5 h-5" />
</button>
<button
onClick={() => {
const container = document.getElementById('consulting-approach-carousel');
if (container) {
container.scrollBy({ left: 384, behavior: 'smooth' });
}
}}
className="w-12 h-12 rounded-full bg-gray-100 hover:bg-primary hover:text-white transition-all duration-300 flex items-center justify-center border border-gray-200 hover:border-primary"
aria-label="Next approach step"
>
<ArrowRight className="w-5 h-5" />
</button>
</div>
</div>
{/* Right Side - Scrollable Approach Cards */}
<div className="lg:col-span-7 relative">
<div
id="consulting-approach-carousel"
className="flex gap-6 overflow-x-auto pb-4"
style={{
scrollSnapType: 'x mandatory',
WebkitOverflowScrolling: 'touch',
msOverflowStyle: 'none',
scrollbarWidth: 'none'
}}
>
{approachSteps.map((step, index) => (
<div
key={index}
className="flex-shrink-0 w-96 bg-white rounded-2xl border border-gray-200 p-8 shadow-md hover:shadow-2xl transition-all duration-300 hover:transform hover:scale-[1.02]"
style={{ scrollSnapAlign: 'start' }}
>
{/* Step Number */}
<div className="flex items-center justify-between mb-6">
<div
className="leading-none font-medium"
style={{
fontSize: 'var(--font-h2)',
fontWeight: '500',
lineHeight: 'var(--line-height-h2)',
color: 'var(--color-accent)',
fontFamily: 'var(--font-family-base)'
}}
>
{step.step}
</div>
<div className="w-16 h-0.5 bg-gradient-to-r from-accent to-transparent opacity-40"></div>
</div>
{/* Step Title */}
<h3
className="leading-tight mb-6"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
lineHeight: 'var(--line-height-h3)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{step.title}
</h3>
{/* Step Description */}
<p
className="leading-relaxed mb-6"
style={{
fontSize: 'var(--font-body)',
lineHeight: 'var(--line-height-body)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-gray-muted)'
}}
>
{step.description}
</p>
{/* Bullet Points */}
<div className="space-y-3">
{step.details.map((detail, detailIndex) => (
<div key={detailIndex} className="flex items-start gap-3">
<div className="w-1.5 h-1.5 rounded-full bg-primary flex-shrink-0 mt-2"></div>
<span
className="leading-relaxed"
style={{
fontSize: 'var(--font-small)',
lineHeight: 'var(--line-height-small)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{detail}
</span>
</div>
))}
</div>
</div>
))}
</div>
{/* Right Side Fade Overlay */}
<div
className="absolute top-0 right-0 h-full w-16 pointer-events-none z-10"
style={{
background: 'linear-gradient(to left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0.8) 40%, rgba(255, 255, 255, 0) 100%)'
}}
></div>
{/* Hide scrollbar with CSS */}
<style>{`
#consulting-approach-carousel::-webkit-scrollbar {
display: none;
}
`}</style>
</div>
</div>
</div>
</section>
{/* Testimonials Section - Using home page testimonials with custom headers */}
<TestimonialsSection
title="What Our Clients Say"
subtitle="Success stories from CXOs, founders, and board members who have achieved transformational results through our strategic consulting services."
tagText="Client Success Stories"
/>
{/* CTA Section - Using standardized home page CTA */}
<CTABannerSection />
</div>
);
}

View File

@@ -0,0 +1,695 @@
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 { TestimonialsSection } from '../TestimonialsSection';
import { CTABannerSection } from '../CTABannerSection';
import StackedOfferSection from '../StackedOfferSection';
import {
ArrowRight,
CheckCircle,
Settings,
Calendar,
Download,
Network,
Users,
Target,
Brain,
Eye,
TrendingUp,
BarChart3,
Award,
Lightbulb,
Shield,
ChevronDown,
ChevronUp,
ArrowLeft,
Star,
Zap,
Globe,
Heart,
Users2,
Sparkles
} from 'lucide-react';
import { PrimaryCTAButton } from '../PrimaryCTAButton';
// Culture competence cards data for the stacking section
const cultureCards = [
{
id: 1,
title: "Inclusive Leadership Development",
subtitle: "Building Inclusive Excellence",
description:
"Comprehensive inclusive leadership development that creates belonging, drives performance, and transforms organizational culture through proven methodologies and sustainable practices.",
badge: "Featured",
color: "from-blue-600 to-blue-700",
icon: Heart,
features: ["Inclusive Leadership", "Cultural Intelligence", "Bias Mitigation", "Equity Practices"],
stats: [
{ label: "Success Rate", value: "87%" },
{ label: "Leaders Trained", value: "2,000+" },
{ label: "Duration", value: "6-12 Mo" }
]
},
{
id: 2,
title: "Cultural Transformation",
subtitle: "Comprehensive Culture Change",
description:
"End-to-end organizational culture transformation initiatives that create sustainable change, enhanced engagement, and measurable business impact through strategic implementation.",
badge: "Popular",
color: "from-purple-600 to-purple-700",
icon: Sparkles,
features: ["Culture Assessment", "Change Strategy", "Implementation Support", "Sustainability Planning"],
stats: [
{ label: "Transformation Rate", value: "92%" },
{ label: "Organizations", value: "300+" },
{ label: "Duration", value: "12-18 Mo" }
]
},
{
id: 3,
title: "Diversity & Inclusion Programs",
subtitle: "Strategic D&I Excellence",
description:
"Strategic diversity and inclusion initiatives that create measurable organizational impact, enhanced representation, and inclusive cultures that drive innovation and performance.",
badge: "Strategic",
color: "from-green-600 to-green-700",
icon: Users2,
features: ["D&I Strategy", "Program Development", "Metrics & Measurement", "Stakeholder Engagement"],
stats: [
{ label: "Inclusion Score", value: "+79%" },
{ label: "Programs Delivered", value: "500+" },
{ label: "Duration", value: "8-15 Mo" }
]
},
{
id: 4,
title: "High-Performance Culture Building",
subtitle: "Excellence-Driven Cultures",
description:
"Create high-performance cultures that drive exceptional results, employee engagement, and organizational excellence through strategic culture design and implementation.",
badge: "Comprehensive",
color: "from-orange-600 to-orange-700",
icon: Target,
features: ["Performance Culture", "Engagement Strategies", "Recognition Systems", "Values Integration"],
stats: [
{ label: "Performance Lift", value: "+68%" },
{ label: "Engagement Increase", value: "+79%" },
{ label: "Duration", value: "9-18 Mo" }
]
}
];
const targetAudience = [
{
title: "Chief Diversity Officers",
description: "CDOs and diversity leaders responsible for creating inclusive organizational cultures and D&I strategy",
icon: Heart,
characteristics: ["D&I strategy", "Cultural transformation", "Inclusive leadership", "Organizational change"]
},
{
title: "HR Leadership",
description: "CHROs and HR leaders driving culture change, employee engagement, and organizational development",
icon: Users2,
characteristics: ["Culture development", "Employee engagement", "Organizational design", "Change management"]
},
{
title: "Executive Teams",
description: "Senior leadership teams committed to building inclusive, high-performance organizational cultures",
icon: Star,
characteristics: ["Executive commitment", "Culture strategy", "Performance excellence", "Inclusive leadership"]
}
];
const outcomes = [
{
title: "Inclusive Culture Excellence",
description: "Enhanced inclusive leadership capabilities and organizational belonging measures",
icon: Heart,
metrics: "87% improvement in inclusion scores and employee belonging metrics within 12 months"
},
{
title: "Enhanced Employee Engagement",
description: "Significant improvements in employee engagement, retention, and performance outcomes",
icon: Sparkles,
metrics: "79% increase in employee engagement scores and 23% improvement in retention rates"
},
{
title: "Organizational Performance",
description: "Measurable business impact through improved culture, innovation, and team effectiveness",
icon: TrendingUp,
metrics: "68% improvement in team performance and 31% increase in innovation metrics"
}
];
const approachSteps = [
{
step: "01",
title: "Culture Assessment",
description: "Comprehensive organizational culture and inclusion assessment using proven methodologies. Together, we make your vision manifest through comprehensive assessment methodologies and proven frameworks.",
details: ["Culture diagnostic", "Inclusion assessment", "Employee insights", "Gap analysis"],
icon: Eye
},
{
step: "02",
title: "Strategy Development",
description: "Customized culture and inclusion strategy aligned with organizational goals and values. Together, we make your vision manifest through comprehensive design methodologies and proven frameworks.",
details: ["Culture strategy", "D&I roadmap", "Leadership alignment", "Success metrics"],
icon: Brain
},
{
step: "03",
title: "Implementation & Training",
description: "Comprehensive implementation with leadership development, training, and change support. Together, we make your vision manifest through comprehensive learning methodologies and proven frameworks.",
details: ["Leadership development", "Culture training", "Change support", "Skills building"],
icon: Network
},
{
step: "04",
title: "Measurement & Sustainability",
description: "Ongoing measurement, reinforcement, and continuous improvement for sustained culture change. Together, we make your vision manifest through comprehensive review methodologies and proven frameworks.",
details: ["Progress tracking", "Impact measurement", "Continuous improvement", "Sustainability planning"],
icon: BarChart3
}
];
export function CultureCompetence() {
const [expandedAudienceIndex, setExpandedAudienceIndex] = useState<number | null>(0);
useEffect(() => {
window.scrollTo(0, 0);
}, []);
const toggleAudienceExpanded = (index: number) => {
setExpandedAudienceIndex(expandedAudienceIndex === index ? null : index);
};
return (
<div className="min-h-screen" style={{ backgroundColor: '#FFFFFF' }}>
{/* Hero Section */}
<section className="relative min-h-[90vh] flex flex-col">
<div className="absolute inset-0 z-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1522202176988-66273c2fd55f?w=1920&h=1080&fit=crop"
alt="Diverse team collaboration - culture competence"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-r from-black/80 via-black/70 to-black/60"></div>
</div>
<div className="relative z-10 flex-1 flex items-center">
<div className="container mx-auto section-margin-x">
<div className="text-center max-w-5xl mx-auto">
<div className="branded-tag-system-white mb-8 justify-center">
<div className="dot"></div>
<span className="text">Culture Excellence</span>
</div>
<h1 className="text-h1-white mb-6">
Culture Competence Services
</h1>
<p className="text-body-lg-white mb-8 max-w-2xl mx-auto">
Build inclusive, high-performance cultures that drive organizational excellence,
employee engagement, and sustainable business success.
</p>
<div className="flex flex-col sm:flex-row gap-4 mb-12 justify-center">
<PrimaryCTAButton
text="Start culture assessment"
onClick={() => navigateTo('/contact')}
className="management-dev-primary-cta"
/>
<Button
onClick={() => window.open('/culture-guide', '_blank')}
className="management-dev-glassmorphic-btn text-body px-8 py-4 min-h-[52px] border text-white transition-all duration-300"
style={{
fontFamily: 'var(--font-family-base)'
}}
>
<Download className="w-5 h-5 mr-2" />
Download Culture Guide
</Button>
</div>
</div>
</div>
</div>
<div className="relative z-10 border-t border-white/20 backdrop-blur-sm bg-black/20">
<div className="container mx-auto section-margin-x py-8">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8 text-center max-w-5xl mx-auto">
<div>
<div className="text-h2-white mb-2">87%</div>
<div className="text-small-white opacity-90">Inclusion score improvement</div>
</div>
<div>
<div className="text-h2-white mb-2">300+</div>
<div className="text-small-white opacity-90">Organizations transformed</div>
</div>
<div>
<div className="text-h2-white mb-2">79%</div>
<div className="text-small-white opacity-90">Engagement increase</div>
</div>
<div>
<div className="text-h2-white mb-2">92%</div>
<div className="text-small-white opacity-90">Culture satisfaction rating</div>
</div>
</div>
</div>
</div>
</section>
{/* Stacked Offer Section */}
<StackedOfferSection cards={cultureCards} />
{/* Who It's For Section */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="grid lg:grid-cols-2 gap-16 items-start max-w-7xl mx-auto">
<div className="lg:pr-8">
<h2 className="text-h2 mb-6 text-black leading-tight">
Who It's <span className="text-primary">For</span>
</h2>
<p className="text-body-lg text-muted leading-relaxed">
Our culture competence programs are designed for diversity leaders, HR executives,
and senior leadership teams committed to building inclusive, high-performance cultures.
</p>
</div>
<div className="space-y-1">
{targetAudience.map((audience, index) => (
<div
key={index}
className="border-b border-gray-400 last:border-b-0"
>
<button
onClick={() => toggleAudienceExpanded(index)}
className="w-full py-6 px-0 flex items-center justify-between text-left hover:bg-transparent focus:outline-none group transition-all duration-200"
style={{ backgroundColor: 'transparent' }}
>
<span className="text-h4 text-black group-hover:text-primary transition-colors duration-200 pr-4">
{audience.title}
</span>
<div className="flex-shrink-0 ml-4">
{expandedAudienceIndex === index ? (
<ChevronUp className="w-6 h-6 text-primary transition-transform duration-200" />
) : (
<ChevronDown className="w-6 h-6 text-gray-400 group-hover:text-primary transition-all duration-200" />
)}
</div>
</button>
<div className={`overflow-hidden transition-all duration-300 ease-in-out ${
expandedAudienceIndex === index ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
}`}>
<div className="pb-6 pr-8">
<p className="text-body text-muted leading-relaxed mb-4">
{audience.description}
</p>
<div className="flex flex-wrap gap-2">
{audience.characteristics.map((characteristic, charIndex) => (
<Badge key={charIndex} variant="outline" className="text-small" style={{ fontFamily: 'var(--font-family-base)' }}>
{characteristic}
</Badge>
))}
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</section>
{/* Expected Outcomes Section */}
<section className="py-20" style={{ backgroundColor: 'rgba(247, 247, 253, 0.5)' }}>
<div className="container mx-auto section-margin-x">
<div className="text-center mb-16 max-w-4xl mx-auto">
<h2 className="text-h2 mb-6">
Expected <span className="text-primary">Outcomes</span>
</h2>
<p className="text-body-lg text-muted">
Our culture competence programs deliver measurable improvements in inclusion,
employee engagement, and organizational performance outcomes.
</p>
</div>
{/* Three-Column Layout - Reference Design Style */}
<div className="grid lg:grid-cols-3 gap-8 max-w-7xl mx-auto">
{/* Inclusive Culture Excellence */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-blue-50 to-blue-100 flex items-center justify-center mb-6">
<Heart className="w-10 h-10 text-primary" />
</div>
<h3 className="text-h3 text-black mb-4">
Inclusive Culture Excellence
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Build inclusive leadership capabilities and organizational belonging measures
that drive engagement and performance excellence.
</p>
</div>
{/* Culture Excellence Visualization */}
<div className="space-y-6">
<div className="flex justify-between items-center">
<span className="text-small text-muted font-medium">Inclusion Score</span>
<span className="text-h4 text-green-600 font-bold">+87%</span>
</div>
<div className="relative">
<div className="flex items-end space-x-1 h-24 mb-4">
<div className="bg-gray-200 h-8 w-4 rounded-sm"></div>
<div className="bg-gray-300 h-12 w-4 rounded-sm"></div>
<div className="bg-gray-200 h-16 w-4 rounded-sm"></div>
<div className="bg-gray-300 h-10 w-4 rounded-sm"></div>
<div className="bg-green-400 h-20 w-4 rounded-sm"></div>
<div className="bg-green-500 h-24 w-4 rounded-sm"></div>
<div className="bg-green-600 h-22 w-4 rounded-sm"></div>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="text-center p-3 bg-green-50 rounded-lg border border-green-100">
<div className="text-xl font-bold text-green-600">89%</div>
<div className="text-small text-muted">Belonging</div>
</div>
<div className="text-center p-3 bg-blue-50 rounded-lg border border-blue-100">
<div className="text-xl font-bold text-primary">84%</div>
<div className="text-small text-muted">Inclusion</div>
</div>
</div>
</div>
</div>
{/* Enhanced Employee Engagement */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-yellow-50 to-yellow-100 flex items-center justify-center mb-6">
<Sparkles className="w-10 h-10 text-accent" />
</div>
<h3 className="text-h3 text-black mb-4">
Enhanced Employee Engagement
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Significant improvements in employee engagement, retention rates,
and overall organizational satisfaction metrics.
</p>
</div>
{/* Engagement Metrics */}
<div className="space-y-6">
<div className="flex items-center justify-between mb-4">
<span className="text-small text-muted font-medium">Engagement Level</span>
<div className="flex items-center">
<TrendingUp className="w-4 h-4 text-green-500 mr-1" />
<span className="text-small text-green-600 font-medium">+79%</span>
</div>
</div>
<div className="relative bg-gray-100 rounded-full h-3 mb-6">
<div
className="bg-gradient-to-r from-yellow-400 to-yellow-500 h-3 rounded-full transition-all duration-1000"
style={{ width: '79%' }}
></div>
</div>
<div className="space-y-3">
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Employee Satisfaction</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
82%
</div>
</div>
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Retention Rate</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
77%
</div>
</div>
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Culture Rating</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
85%
</div>
</div>
</div>
</div>
</div>
{/* Organizational Performance */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-purple-50 to-purple-100 flex items-center justify-center mb-6">
<TrendingUp className="w-10 h-10 text-primary" />
</div>
<h3 className="text-h3 text-black mb-4">
Organizational Performance
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Measurable business impact through improved culture, innovation metrics,
and team effectiveness outcomes.
</p>
</div>
{/* Performance KPIs */}
<div className="space-y-6">
<div className="grid grid-cols-2 gap-4">
<div className="text-center p-3 bg-blue-50 rounded-lg border border-blue-100">
<div className="flex items-center justify-center mb-1">
<span className="text-small text-muted mr-2">Performance</span>
<TrendingUp className="w-3 h-3 text-green-500" />
</div>
<div className="text-xl font-bold text-primary">68%</div>
</div>
<div className="text-center p-3 bg-purple-50 rounded-lg border border-purple-100">
<div className="flex items-center justify-center mb-1">
<span className="text-small text-muted mr-2">Innovation</span>
<div className="w-3 h-3 flex items-center justify-center">
<div className="w-0 h-0 border-l-2 border-r-2 border-b-3 border-transparent border-b-purple-500"></div>
</div>
</div>
<div className="text-xl font-bold text-purple-500">31%</div>
</div>
</div>
<div className="bg-gray-50 rounded-lg p-4">
<div className="flex justify-between items-center mb-2">
<span className="text-small text-muted font-medium">Culture Impact</span>
<span className="text-small text-primary font-bold">Business ROI</span>
</div>
<div className="flex items-end justify-between">
<div className="text-2xl font-bold text-primary">74%</div>
<div className="text-2xl font-bold text-green-600">$1.8M</div>
</div>
</div>
<div className="grid grid-cols-3 gap-2">
<div className="text-center">
<div className="text-lg font-bold text-primary">68%</div>
<div className="text-xs text-muted">Performance</div>
</div>
<div className="text-center">
<div className="text-lg font-bold text-green-600">+31%</div>
<div className="text-xs text-muted">Innovation</div>
</div>
<div className="text-center">
<div className="text-lg font-bold text-purple-500">23%</div>
<div className="text-xs text-muted">Retention</div>
</div>
</div>
</div>
</div>
</div>
{/* Results Confirmation Banner */}
<div className="mt-16 max-w-4xl mx-auto">
<div className="bg-gradient-to-r from-green-50 to-blue-50 rounded-xl p-6 border border-green-200">
<div className="flex items-center justify-center gap-3">
<div className="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center">
<CheckCircle className="w-5 h-5 text-green-600" />
</div>
<p className="text-body text-center" style={{ fontWeight: 'var(--font-weight-subhead)', color: '#059669' }}>
All outcomes measured within 12 months of program implementation
</p>
</div>
</div>
</div>
</div>
</section>
{/* Our Approach Section - Carousel Design */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12 items-start max-w-7xl mx-auto">
{/* Left Side - Title, Description & Navigation */}
<div className="lg:col-span-5 lg:pr-8">
<h2 className="text-h2 mb-6 leading-tight">
Our <span className="text-primary">Approach</span>
</h2>
<p className="text-body-lg text-muted leading-relaxed mb-8">
Comprehensive culture transformation journey combining assessment, strategic planning,
implementation support, and measurement for sustainable organizational change.
</p>
{/* Navigation Controls */}
<div className="flex gap-3">
<button
onClick={() => {
const container = document.getElementById('approach-carousel');
if (container) {
container.scrollBy({ left: -320, behavior: 'smooth' });
}
}}
className="w-12 h-12 rounded-full bg-gray-100 hover:bg-primary hover:text-white transition-all duration-300 flex items-center justify-center border border-gray-200 hover:border-primary"
aria-label="Previous approach step"
>
<ArrowLeft className="w-5 h-5" />
</button>
<button
onClick={() => {
const container = document.getElementById('approach-carousel');
if (container) {
container.scrollBy({ left: 320, behavior: 'smooth' });
}
}}
className="w-12 h-12 rounded-full bg-gray-100 hover:bg-primary hover:text-white transition-all duration-300 flex items-center justify-center border border-gray-200 hover:border-primary"
aria-label="Next approach step"
>
<ArrowRight className="w-5 h-5" />
</button>
</div>
</div>
{/* Right Side - Scrollable Approach Cards */}
<div className="lg:col-span-7 relative">
<div
id="approach-carousel"
className="flex gap-6 overflow-x-auto pb-4"
style={{
scrollSnapType: 'x mandatory',
WebkitOverflowScrolling: 'touch',
msOverflowStyle: 'none',
scrollbarWidth: 'none'
}}
>
{approachSteps.map((step, index) => (
<div
key={index}
className="flex-shrink-0 w-80 bg-white rounded-2xl border border-gray-100 p-8 hover:shadow-lg transition-all duration-300 hover:transform hover:scale-[1.02]"
style={{ scrollSnapAlign: 'start' }}
>
{/* Step Number */}
<div className="flex items-center justify-between mb-6">
<div
className="leading-none font-medium"
style={{
fontSize: 'var(--font-h2)',
fontWeight: '500',
lineHeight: 'var(--line-height-h2)',
color: 'var(--color-accent)',
fontFamily: 'var(--font-family-base)'
}}
>
{step.step}
</div>
<div className="w-16 h-0.5 bg-gradient-to-r from-accent to-transparent opacity-40"></div>
</div>
{/* Step Title */}
<h3
className="leading-tight mb-6"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
lineHeight: 'var(--line-height-h3)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{step.title}
</h3>
{/* Step Description */}
<p
className="leading-relaxed mb-6"
style={{
fontSize: 'var(--font-body)',
lineHeight: 'var(--line-height-body)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-gray-muted)'
}}
>
{step.description}
</p>
{/* Bullet Points */}
<div className="space-y-3">
{step.details.map((detail, detailIndex) => (
<div key={detailIndex} className="flex items-start gap-3">
<div className="w-1.5 h-1.5 rounded-full bg-primary flex-shrink-0 mt-2"></div>
<span
className="leading-relaxed"
style={{
fontSize: 'var(--font-small)',
lineHeight: 'var(--line-height-small)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{detail}
</span>
</div>
))}
</div>
</div>
))}
</div>
{/* Right Side Fade Overlay */}
<div
className="absolute top-0 right-0 h-full w-16 pointer-events-none z-10"
style={{
background: 'linear-gradient(to left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0.8) 40%, rgba(255, 255, 255, 0) 100%)'
}}
></div>
{/* Hide scrollbar with CSS */}
<style>{`
#approach-carousel::-webkit-scrollbar {
display: none;
}
`}</style>
</div>
</div>
</div>
</section>
<TestimonialsSection
title="What Our Culture Leaders Say"
subtitle="Hear from diversity officers and HR leaders who have transformed their organizational cultures through our comprehensive programs."
tagText="Culture Success"
/>
<CTABannerSection />
</div>
);
}

View File

@@ -0,0 +1,693 @@
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 { TestimonialsSection } from '../TestimonialsSection';
import { CTABannerSection } from '../CTABannerSection';
import StackedOfferSection from '../StackedOfferSection';
import {
Users,
Target,
ArrowRight,
CheckCircle,
Award,
Lightbulb,
Brain,
UserCheck,
Eye,
TrendingUp,
MessageCircle,
Calendar,
BarChart3,
Shield,
Star,
User,
ChevronDown,
ChevronUp,
ArrowLeft,
Download
} from 'lucide-react';
import { PrimaryCTAButton } from '../PrimaryCTAButton';
// Executive coaching cards data for the stacking section
const coachingCards = [
{
id: 1,
title: "1:1 Coaching Programs",
subtitle: "Personalized Executive Development",
description:
"Confidential, personalized executive coaching programs tailored to individual leadership challenges and growth goals, designed for maximum impact and sustainable change.",
badge: "Featured",
color: "from-blue-600 to-blue-700",
icon: User,
features: ["Individual Assessment", "Customized Development Plan", "Regular Coaching Sessions", "Progress Tracking"],
stats: [
{ label: "Success Rate", value: "91%" },
{ label: "Executives Coached", value: "450+" },
{ label: "Duration", value: "3-6 Mo" }
]
},
{
id: 2,
title: "360° Feedback Debriefs",
subtitle: "Comprehensive Leadership Assessment",
description:
"Expert-facilitated 360-degree feedback analysis and development planning based on multi-source insights that drive meaningful behavioral change and leadership effectiveness.",
badge: "Popular",
color: "from-purple-600 to-purple-700",
icon: Eye,
features: ["Multi-source Feedback", "Behavioral Analysis", "Strengths Identification", "Development Prioritization"],
stats: [
{ label: "Awareness Increase", value: "+88%" },
{ label: "Leaders Assessed", value: "800+" },
{ label: "Duration", value: "4-8 Wks" }
]
},
{
id: 3,
title: "Executive Presence & Transition Support",
subtitle: "Leadership Transition Excellence",
description:
"Specialized coaching for leadership transitions and executive presence enhancement that ensures successful role transitions and enhanced stakeholder confidence.",
badge: "Strategic",
color: "from-green-600 to-green-700",
icon: Award,
features: ["Presence Development", "Transition Planning", "Stakeholder Management", "Communication Skills"],
stats: [
{ label: "Transition Success", value: "96%" },
{ label: "Leaders Transitioned", value: "300+" },
{ label: "Duration", value: "6-12 Mo" }
]
},
{
id: 4,
title: "Strategic Leadership Coaching",
subtitle: "Complex Challenge Navigation",
description:
"Advanced coaching for complex strategic challenges and organizational transformation that develops exceptional strategic thinking and decision-making capabilities.",
badge: "Comprehensive",
color: "from-orange-600 to-orange-700",
icon: Target,
features: ["Strategic Thinking", "Decision-Making", "Change Leadership", "Organizational Impact"],
stats: [
{ label: "Strategic Impact", value: "+79%" },
{ label: "Strategic Leaders", value: "250+" },
{ label: "Duration", value: "6-18 Mo" }
]
}
];
const targetAudience = [
{
title: "CXOs",
description: "Chief executives seeking to enhance their leadership effectiveness and organizational impact",
icon: Award,
characteristics: ["Strategic leadership", "Organizational vision", "Stakeholder management", "Performance accountability"]
},
{
title: "Senior Leaders Taking on New Roles",
description: "Executives transitioning into expanded responsibilities or new organizational contexts",
icon: TrendingUp,
characteristics: ["Role transition", "New challenges", "Expanded scope", "Stakeholder expectations"]
},
{
title: "High-Potential Successors",
description: "Emerging leaders being prepared for senior executive roles and strategic responsibilities",
icon: Star,
characteristics: ["Leadership potential", "Career acceleration", "Strategic development", "Future leadership"]
}
];
const outcomes = [
{
title: "Heightened Self-Awareness",
description: "Deep understanding of leadership strengths, blind spots, and impact on others",
icon: Brain,
metrics: "91% of executives report significantly increased self-awareness and emotional intelligence"
},
{
title: "Enhanced Leadership Confidence",
description: "Increased confidence in leadership abilities and decision-making in complex situations",
icon: Shield,
metrics: "88% improvement in leadership confidence and presence in challenging situations"
},
{
title: "Clearer Strategic Execution",
description: "Improved ability to translate strategy into action and drive organizational results",
icon: Target,
metrics: "79% better strategic execution effectiveness and organizational impact"
}
];
const approachSteps = [
{
step: "01",
title: "Assessment & Goal Setting",
description: "Comprehensive leadership assessment to understand current state and define specific coaching objectives. Together, we make your vision manifest through proven assessment methodologies and frameworks.",
details: ["Leadership assessment", "360-degree feedback", "Goal clarification", "Success metrics"],
icon: Eye
},
{
step: "02",
title: "Coach Matching",
description: "Careful matching with ICF-certified executive coaches based on industry experience and leadership style compatibility. Together, we make your vision manifest through proven matching methodologies and frameworks.",
details: ["Coach selection", "Chemistry session", "Approach alignment", "Relationship building"],
icon: UserCheck
},
{
step: "03",
title: "Coaching Journey",
description: "Confidential, goal-oriented coaching engagement over 36 months with regular sessions and ongoing support. Together, we make your vision manifest through proven coaching methodologies and frameworks.",
details: ["Regular sessions", "Action planning", "Skill development", "Progress monitoring"],
icon: TrendingUp
},
{
step: "04",
title: "Impact Measurement",
description: "Comprehensive evaluation of coaching impact and integration of learning into ongoing leadership practice. Together, we make your vision manifest through proven measurement methodologies and frameworks.",
details: ["Progress review", "Impact assessment", "Learning integration", "Sustained development"],
icon: BarChart3
}
];
export function ExecutiveCoaching() {
const [expandedAudienceIndex, setExpandedAudienceIndex] = useState<number | null>(0);
useEffect(() => {
window.scrollTo(0, 0);
}, []);
const toggleAudienceExpanded = (index: number) => {
setExpandedAudienceIndex(expandedAudienceIndex === index ? null : index);
};
return (
<div className="min-h-screen" style={{ backgroundColor: '#FFFFFF' }}>
{/* Hero Section */}
<section className="relative min-h-[90vh] flex flex-col">
<div className="absolute inset-0 z-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1573164713714-d95e436ab8d6?w=1920&h=1080&fit=crop"
alt="Executive coaching session - leadership development"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-r from-black/80 via-black/70 to-black/60"></div>
</div>
<div className="relative z-10 flex-1 flex items-center">
<div className="container mx-auto section-margin-x">
<div className="text-center max-w-5xl mx-auto">
<div className="branded-tag-system-white mb-8 justify-center">
<div className="dot"></div>
<span className="text">Executive Excellence</span>
</div>
<h1 className="text-h1-white mb-6">
Executive Coaching Services
</h1>
<p className="text-body-lg-white mb-8 max-w-2xl mx-auto">
Transform your leadership effectiveness through confidential, personalized coaching
tailored to your unique challenges and growth objectives.
</p>
<div className="flex flex-col sm:flex-row gap-4 mb-12 justify-center">
<PrimaryCTAButton
text="Match me with a coach"
onClick={() => navigateTo('/contact')}
className="management-dev-primary-cta"
/>
<Button
onClick={() => window.open('/coaching-guide', '_blank')}
className="management-dev-glassmorphic-btn text-body px-8 py-4 min-h-[52px] border text-white transition-all duration-300"
style={{
fontFamily: 'var(--font-family-base)'
}}
>
<Download className="w-5 h-5 mr-2" />
Download Coaching Guide
</Button>
</div>
</div>
</div>
</div>
<div className="relative z-10 border-t border-white/20 backdrop-blur-sm bg-black/20">
<div className="container mx-auto section-margin-x py-8">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8 text-center max-w-5xl mx-auto">
<div>
<div className="text-h2-white mb-2">91%</div>
<div className="text-small-white opacity-90">Self-awareness improvement</div>
</div>
<div>
<div className="text-h2-white mb-2">450+</div>
<div className="text-small-white opacity-90">Executives coached</div>
</div>
<div>
<div className="text-h2-white mb-2">88%</div>
<div className="text-small-white opacity-90">Leadership confidence boost</div>
</div>
<div>
<div className="text-h2-white mb-2">96%</div>
<div className="text-small-white opacity-90">Client satisfaction rating</div>
</div>
</div>
</div>
</div>
</section>
{/* Stacked Offer Section */}
<StackedOfferSection cards={coachingCards} />
{/* Who It's For Section */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="grid lg:grid-cols-2 gap-16 items-start max-w-7xl mx-auto">
<div className="lg:pr-8">
<h2 className="text-h2 mb-6 text-black leading-tight">
Who It's <span className="text-primary">For</span>
</h2>
<p className="text-body-lg text-muted leading-relaxed">
Our executive coaching programs serve senior leaders and high-potential executives
who are committed to accelerating their leadership impact and effectiveness.
</p>
</div>
<div className="space-y-1">
{targetAudience.map((audience, index) => (
<div
key={index}
className="border-b border-gray-400 last:border-b-0"
>
<button
onClick={() => toggleAudienceExpanded(index)}
className="w-full py-6 px-0 flex items-center justify-between text-left hover:bg-transparent focus:outline-none group transition-all duration-200"
style={{ backgroundColor: 'transparent' }}
>
<span className="text-h4 text-black group-hover:text-primary transition-colors duration-200 pr-4">
{audience.title}
</span>
<div className="flex-shrink-0 ml-4">
{expandedAudienceIndex === index ? (
<ChevronUp className="w-6 h-6 text-primary transition-transform duration-200" />
) : (
<ChevronDown className="w-6 h-6 text-gray-400 group-hover:text-primary transition-all duration-200" />
)}
</div>
</button>
<div className={`overflow-hidden transition-all duration-300 ease-in-out ${
expandedAudienceIndex === index ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
}`}>
<div className="pb-6 pr-8">
<p className="text-body text-muted leading-relaxed mb-4">
{audience.description}
</p>
<div className="flex flex-wrap gap-2">
{audience.characteristics.map((characteristic, charIndex) => (
<Badge key={charIndex} variant="outline" className="text-small" style={{ fontFamily: 'var(--font-family-base)' }}>
{characteristic}
</Badge>
))}
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</section>
{/* Expected Outcomes Section */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="text-center mb-16 max-w-4xl mx-auto">
<h2 className="text-h2 mb-6">
Expected <span className="text-primary">Outcomes</span>
</h2>
<p className="text-body-lg text-muted">
Our executive coaching delivers transformational results in leadership effectiveness,
confidence, and strategic execution capabilities for sustained success.
</p>
</div>
{/* Three-Column Layout - Reference Design Style */}
<div className="grid lg:grid-cols-3 gap-8 max-w-7xl mx-auto">
{/* Heightened Self-Awareness */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-blue-50 to-blue-100 flex items-center justify-center mb-6">
<Brain className="w-10 h-10 text-primary" />
</div>
<h3 className="text-h3 text-black mb-4">
Heightened Self-Awareness
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Deep understanding of leadership strengths, blind spots, and impact on
others for enhanced emotional intelligence and effectiveness.
</p>
</div>
{/* Self-Awareness Visualization */}
<div className="space-y-6">
<div className="flex justify-between items-center">
<span className="text-small text-muted font-medium">Self-Awareness Growth</span>
<span className="text-h4 text-green-600 font-bold">+91%</span>
</div>
<div className="relative">
<div className="flex items-end space-x-1 h-24 mb-4">
<div className="bg-gray-200 h-8 w-4 rounded-sm"></div>
<div className="bg-gray-300 h-12 w-4 rounded-sm"></div>
<div className="bg-gray-200 h-16 w-4 rounded-sm"></div>
<div className="bg-gray-300 h-10 w-4 rounded-sm"></div>
<div className="bg-green-400 h-20 w-4 rounded-sm"></div>
<div className="bg-green-500 h-24 w-4 rounded-sm"></div>
<div className="bg-green-600 h-22 w-4 rounded-sm"></div>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="text-center p-3 bg-blue-50 rounded-lg border border-blue-100">
<div className="text-xl font-bold text-primary">88%</div>
<div className="text-small text-muted">EQ Improvement</div>
</div>
<div className="text-center p-3 bg-green-50 rounded-lg border border-green-100">
<div className="text-xl font-bold text-green-600">94%</div>
<div className="text-small text-muted">Impact Clarity</div>
</div>
</div>
</div>
</div>
{/* Enhanced Leadership Confidence */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-yellow-50 to-yellow-100 flex items-center justify-center mb-6">
<Shield className="w-10 h-10 text-accent" />
</div>
<h3 className="text-h3 text-black mb-4">
Enhanced Leadership Confidence
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Increased confidence in leadership abilities and decision-making
in complex and challenging situations.
</p>
</div>
{/* Leadership Confidence Metrics */}
<div className="space-y-6">
<div className="flex items-center justify-between mb-4">
<span className="text-small text-muted font-medium">Leadership Confidence</span>
<div className="flex items-center">
<TrendingUp className="w-4 h-4 text-green-500 mr-1" />
<span className="text-small text-green-600 font-medium">+88%</span>
</div>
</div>
<div className="relative bg-gray-100 rounded-full h-3 mb-6">
<div
className="bg-gradient-to-r from-yellow-400 to-yellow-500 h-3 rounded-full transition-all duration-1000"
style={{ width: '88%' }}
></div>
</div>
<div className="space-y-3">
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Decision Making</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
91%
</div>
</div>
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Complex Situations</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
85%
</div>
</div>
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Executive Presence</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
89%
</div>
</div>
</div>
</div>
</div>
{/* Clearer Strategic Execution */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-purple-50 to-purple-100 flex items-center justify-center mb-6">
<Target className="w-10 h-10 text-primary" />
</div>
<h3 className="text-h3 text-black mb-4">
Clearer Strategic Execution
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Improved ability to translate strategy into action and drive
measurable organizational results and impact.
</p>
</div>
{/* Strategic Execution KPIs */}
<div className="space-y-6">
<div className="grid grid-cols-2 gap-4">
<div className="text-center p-3 bg-blue-50 rounded-lg border border-blue-100">
<div className="flex items-center justify-center mb-1">
<span className="text-small text-muted mr-2">Strategy</span>
<TrendingUp className="w-3 h-3 text-green-500" />
</div>
<div className="text-xl font-bold text-primary">79%</div>
</div>
<div className="text-center p-3 bg-green-50 rounded-lg border border-green-100">
<div className="flex items-center justify-center mb-1">
<span className="text-small text-muted mr-2">Execution</span>
<div className="w-3 h-3 flex items-center justify-center">
<div className="w-0 h-0 border-l-2 border-r-2 border-b-3 border-transparent border-b-green-500"></div>
</div>
</div>
<div className="text-xl font-bold text-green-500">86%</div>
</div>
</div>
<div className="bg-gray-50 rounded-lg p-4">
<div className="flex justify-between items-center mb-2">
<span className="text-small text-muted font-medium">Strategic Impact</span>
<span className="text-small text-primary font-bold">Result Quality</span>
</div>
<div className="flex items-end justify-between">
<div className="text-2xl font-bold text-primary">83%</div>
<div className="text-2xl font-bold text-green-600">92%</div>
</div>
</div>
<div className="grid grid-cols-3 gap-2">
<div className="text-center">
<div className="text-lg font-bold text-primary">79%</div>
<div className="text-xs text-muted">Execution</div>
</div>
<div className="text-center">
<div className="text-lg font-bold text-green-600">+24%</div>
<div className="text-xs text-muted">Results</div>
</div>
<div className="text-center">
<div className="text-lg font-bold text-blue-500">92%</div>
<div className="text-xs text-muted">Impact</div>
</div>
</div>
</div>
</div>
</div>
{/* Results Confirmation Banner */}
<div className="mt-16 max-w-4xl mx-auto">
<div className="bg-gradient-to-r from-green-50 to-blue-50 rounded-xl p-6 border border-green-200">
<div className="flex items-center justify-center gap-3">
<div className="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center">
<CheckCircle className="w-5 h-5 text-green-600" />
</div>
<p className="text-body text-center" style={{ fontWeight: 'var(--font-weight-subhead)', color: '#059669' }}>
All outcomes measured within 3-6 months of coaching engagement
</p>
</div>
</div>
</div>
</div>
</section>
{/* Our Approach Section - Carousel Design */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12 items-start max-w-7xl mx-auto">
{/* Left Side - Title, Description & Navigation */}
<div className="lg:col-span-5 lg:pr-8">
<h2 className="text-h2 mb-6 leading-tight">
Our <span className="text-primary">Approach</span>
</h2>
<p className="text-body-lg text-muted leading-relaxed mb-8">
Confidential, goal-oriented coaching over 36 months matched with ICF-certified
executive coaches for maximum leadership impact and sustainable transformation.
</p>
{/* Navigation Controls */}
<div className="flex gap-3">
<button
onClick={() => {
const container = document.getElementById('coaching-approach-carousel');
if (container) {
container.scrollBy({ left: -384, behavior: 'smooth' });
}
}}
className="w-12 h-12 rounded-full bg-gray-100 hover:bg-primary hover:text-white transition-all duration-300 flex items-center justify-center border border-gray-200 hover:border-primary"
aria-label="Previous approach step"
>
<ArrowLeft className="w-5 h-5" />
</button>
<button
onClick={() => {
const container = document.getElementById('coaching-approach-carousel');
if (container) {
container.scrollBy({ left: 384, behavior: 'smooth' });
}
}}
className="w-12 h-12 rounded-full bg-gray-100 hover:bg-primary hover:text-white transition-all duration-300 flex items-center justify-center border border-gray-200 hover:border-primary"
aria-label="Next approach step"
>
<ArrowRight className="w-5 h-5" />
</button>
</div>
</div>
{/* Right Side - Scrollable Approach Cards */}
<div className="lg:col-span-7 relative">
<div
id="coaching-approach-carousel"
className="flex gap-6 overflow-x-auto pb-4"
style={{
scrollSnapType: 'x mandatory',
WebkitOverflowScrolling: 'touch',
msOverflowStyle: 'none',
scrollbarWidth: 'none'
}}
>
{approachSteps.map((step, index) => (
<div
key={index}
className="flex-shrink-0 w-96 bg-white rounded-2xl border border-gray-200 p-8 shadow-md hover:shadow-2xl transition-all duration-300 hover:transform hover:scale-[1.02]"
style={{ scrollSnapAlign: 'start' }}
>
{/* Step Number */}
<div className="flex items-center justify-between mb-6">
<div
className="leading-none font-medium"
style={{
fontSize: 'var(--font-h2)',
fontWeight: '500',
lineHeight: 'var(--line-height-h2)',
color: 'var(--color-accent)',
fontFamily: 'var(--font-family-base)'
}}
>
{step.step}
</div>
<div className="w-16 h-0.5 bg-gradient-to-r from-accent to-transparent opacity-40"></div>
</div>
{/* Step Title */}
<h3
className="leading-tight mb-6"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
lineHeight: 'var(--line-height-h3)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{step.title}
</h3>
{/* Step Description */}
<p
className="leading-relaxed mb-6"
style={{
fontSize: 'var(--font-body)',
lineHeight: 'var(--line-height-body)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-gray-muted)'
}}
>
{step.description}
</p>
{/* Bullet Points */}
<div className="space-y-3">
{step.details.map((detail, detailIndex) => (
<div key={detailIndex} className="flex items-start gap-3">
<div className="w-1.5 h-1.5 rounded-full bg-primary flex-shrink-0 mt-2"></div>
<span
className="leading-relaxed"
style={{
fontSize: 'var(--font-small)',
lineHeight: 'var(--line-height-small)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{detail}
</span>
</div>
))}
</div>
</div>
))}
</div>
{/* Right Side Fade Overlay */}
<div
className="absolute top-0 right-0 h-full w-16 pointer-events-none z-10"
style={{
background: 'linear-gradient(to left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0.8) 40%, rgba(255, 255, 255, 0) 100%)'
}}
></div>
{/* Hide scrollbar with CSS */}
<style>{`
#coaching-approach-carousel::-webkit-scrollbar {
display: none;
}
`}</style>
</div>
</div>
</div>
</section>
{/* Testimonials Section - Using home page testimonials with custom headers */}
<TestimonialsSection
title="Success Stories"
subtitle="Private success stories from executives who have achieved breakthrough results through our confidential coaching programs."
tagText="Executive Success"
/>
{/* CTA Section - Using standardized home page CTA */}
<CTABannerSection />
</div>
);
}

View File

@@ -0,0 +1,695 @@
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 { TestimonialsSection } from '../TestimonialsSection';
import { CTABannerSection } from '../CTABannerSection';
import StackedOfferSection from '../StackedOfferSection';
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
} from 'lucide-react';
import { PrimaryCTAButton } from '../PrimaryCTAButton';
const targetAudience = [
{
title: "C-Suite Executives",
description: "CEOs, Presidents, and C-level executives leading organizational transformation and strategic initiatives",
icon: Crown,
characteristics: ["Strategic leadership", "Organizational vision", "Board governance", "Executive presence"]
},
{
title: "Senior Directors",
description: "Directors and Vice Presidents responsible for major business units and strategic functions",
icon: Users2,
characteristics: ["Business unit leadership", "Strategic execution", "Cross-functional leadership", "P&L responsibility"]
},
{
title: "High-Potential Leaders",
description: "Emerging leaders identified for accelerated development and future executive roles",
icon: Star,
characteristics: ["Leadership potential", "Career advancement", "Executive readiness", "Strategic capability"]
}
];
const outcomes = [
{
title: "Strategic Leadership Excellence",
description: "Enhanced strategic thinking, vision development, and organizational leadership capabilities",
icon: Compass,
metrics: "94% of executives report improved strategic leadership effectiveness within 6 months"
},
{
title: "Enhanced Executive Presence",
description: "Strengthened executive presence, communication skills, and stakeholder influence",
icon: Crown,
metrics: "91% improvement in executive presence and stakeholder confidence ratings"
},
{
title: "Organizational Impact",
description: "Measurable improvements in organizational performance, culture, and strategic outcomes",
icon: TrendingUp,
metrics: "83% improvement in organizational performance metrics and strategic goal achievement"
}
];
const approachSteps = [
{
step: "01",
title: "Leadership Assessment",
description: "Comprehensive 360-degree assessment of current leadership capabilities and strategic readiness. Together, we make your vision manifest through comprehensive assessment methodologies and proven frameworks.",
details: ["Executive assessment", "Leadership competency analysis", "Strategic readiness evaluation", "Development priorities"],
icon: Eye
},
{
step: "02",
title: "Strategic Program Design",
description: "Customized executive development curriculum aligned with organizational strategy and leadership needs. Together, we make your vision manifest through comprehensive design methodologies and proven frameworks.",
details: ["Executive curriculum", "Strategic alignment", "Leadership development", "Program customization"],
icon: Brain
},
{
step: "03",
title: "Executive Learning",
description: "High-impact leadership development through executive coaching, peer learning, and strategic simulations. Together, we make your vision manifest through comprehensive learning methodologies and proven frameworks.",
details: ["Executive workshops", "Strategic simulations", "Peer learning groups", "Leadership coaching"],
icon: Network
},
{
step: "04",
title: "Impact & Sustainability",
description: "Ongoing support and measurement to ensure leadership transformation and organizational impact. Together, we make your vision manifest through comprehensive review methodologies and proven frameworks.",
details: ["Leadership application", "Impact measurement", "Ongoing coaching", "Sustainability planning"],
icon: BarChart3
}
];
// Leadership development cards data for the stacking section
const leadershipCards = [
{
id: 1,
title: "Executive Leadership Program",
subtitle: "C-Suite & Senior Executive Development",
description:
"Transform senior executives into visionary leaders who drive organizational transformation, strategic excellence, and sustainable business growth through proven executive development methodologies.",
badge: "Featured",
color: "from-blue-600 to-blue-700",
icon: Crown,
features: ["Strategic Vision", "Executive Presence", "Organizational Impact", "Crisis Leadership"],
stats: [
{ label: "Success Rate", value: "94%" },
{ label: "Executives Trained", value: "500+" },
{ label: "Duration", value: "6-12 Mo" }
]
},
{
id: 2,
title: "Senior Management Development",
subtitle: "Advanced Leadership for Directors & VPs",
description:
"Comprehensive leadership development for directors and vice presidents leading major business units and strategic functions across the organization.",
badge: "Popular",
color: "from-purple-600 to-purple-700",
icon: Users2,
features: ["Change Management", "Strategic Execution", "Cross-functional Leadership", "P&L Responsibility"],
stats: [
{ label: "Success Rate", value: "91%" },
{ label: "Managers Trained", value: "800+" },
{ label: "Duration", value: "4-8 Mo" }
]
},
{
id: 3,
title: "Leadership Pipeline Building",
subtitle: "Succession Planning & Development",
description:
"Systematic development of future leaders and comprehensive succession planning initiatives to build organizational leadership capacity.",
badge: "Strategic",
color: "from-green-600 to-green-700",
icon: TrendingUp,
features: ["Succession Planning", "High-potential Development", "Leadership Assessment", "Career Progression"],
stats: [
{ label: "Pipeline Success", value: "87%" },
{ label: "Leaders Identified", value: "1,200+" },
{ label: "Duration", value: "12-18 Mo" }
]
},
{
id: 4,
title: "Leadership Transformation",
subtitle: "Organizational Culture Change",
description:
"Comprehensive organizational leadership culture transformation initiatives that create lasting change and sustainable business performance.",
badge: "Comprehensive",
color: "from-orange-600 to-orange-700",
icon: Target,
features: ["Culture Change", "Leadership Alignment", "Transformation Strategy", "Capability Building"],
stats: [
{ label: "Transformation Rate", value: "89%" },
{ label: "Organizations", value: "150+" },
{ label: "Duration", value: "6-24 Mo" }
]
}
];
export function LeadershipDevelopment() {
const [expandedAudienceIndex, setExpandedAudienceIndex] = useState<number | null>(0);
useEffect(() => {
window.scrollTo(0, 0);
}, []);
const toggleAudienceExpanded = (index: number) => {
setExpandedAudienceIndex(expandedAudienceIndex === index ? null : index);
};
return (
<div className="min-h-screen" style={{ backgroundColor: '#F7F7FD' }}>
{/* Hero Section */}
<section className="relative min-h-[90vh] flex flex-col">
<div className="absolute inset-0 z-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1560472354-b33ff0c44a43?w=1920&h=1080&fit=crop"
alt="Executive leadership meeting - leadership development"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-r from-black/80 via-black/70 to-black/60"></div>
</div>
<div className="relative z-10 flex-1 flex items-center">
<div className="container mx-auto section-margin-x">
<div className="text-center max-w-5xl mx-auto">
<div className="branded-tag-system-white mb-8 justify-center">
<div className="dot"></div>
<span className="text">Executive Excellence</span>
</div>
<h1 className="text-h1-white mb-6">
Leadership Development Services
</h1>
<p className="text-body-lg-white mb-8 max-w-2xl mx-auto">
Transform your executive leadership capabilities and organizational impact through
comprehensive leadership development programs designed for senior leaders.
</p>
<div className="flex flex-col sm:flex-row gap-4 mb-12 justify-center">
<PrimaryCTAButton
text="Book a consultation"
onClick={() => navigateTo('/contact')}
className="management-dev-primary-cta"
/>
<Button
onClick={() => window.open('/executive-overview', '_blank')}
className="management-dev-glassmorphic-btn text-body px-8 py-4 min-h-[52px] border text-white transition-all duration-300"
style={{
fontFamily: 'var(--font-family-base)'
}}
>
<Download className="w-5 h-5 mr-2" />
Download Overview
</Button>
</div>
</div>
</div>
</div>
<div className="relative z-10 border-t border-white/20 backdrop-blur-sm bg-black/20">
<div className="container mx-auto section-margin-x py-8">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8 text-center max-w-5xl mx-auto">
<div>
<div className="text-h2-white mb-2">94%</div>
<div className="text-small-white opacity-90">Leadership effectiveness improvement</div>
</div>
<div>
<div className="text-h2-white mb-2">500+</div>
<div className="text-small-white opacity-90">Executives developed</div>
</div>
<div>
<div className="text-h2-white mb-2">65%</div>
<div className="text-small-white opacity-90">Faster strategic execution</div>
</div>
<div>
<div className="text-h2-white mb-2">89%</div>
<div className="text-small-white opacity-90">Organizational impact rating</div>
</div>
</div>
</div>
</div>
</section>
{/* Stacked Offer Section */}
<StackedOfferSection cards={leadershipCards} />
{/* Who It's For Section */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="grid lg:grid-cols-2 gap-16 items-start max-w-7xl mx-auto">
<div className="lg:pr-8">
<h2 className="text-h2 mb-6 text-black leading-tight">
Who It's <span className="text-primary">For</span>
</h2>
<p className="text-body-lg text-muted leading-relaxed">
Our leadership development programs are designed for senior executives, directors, and
high-potential leaders who drive organizational strategy and transformation.
</p>
</div>
<div className="space-y-1">
{targetAudience.map((audience, index) => (
<div
key={index}
className="border-b border-gray-400 last:border-b-0"
>
<button
onClick={() => toggleAudienceExpanded(index)}
className="w-full py-6 px-0 flex items-center justify-between text-left hover:bg-transparent focus:outline-none group transition-all duration-200"
style={{ backgroundColor: 'transparent' }}
>
<span className="text-h4 text-black group-hover:text-primary transition-colors duration-200 pr-4">
{audience.title}
</span>
<div className="flex-shrink-0 ml-4">
{expandedAudienceIndex === index ? (
<ChevronUp className="w-6 h-6 text-primary transition-transform duration-200" />
) : (
<ChevronDown className="w-6 h-6 text-gray-400 group-hover:text-primary transition-all duration-200" />
)}
</div>
</button>
<div className={`overflow-hidden transition-all duration-300 ease-in-out ${
expandedAudienceIndex === index ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
}`}>
<div className="pb-6 pr-8">
<p className="text-body text-muted leading-relaxed mb-4">
{audience.description}
</p>
<div className="flex flex-wrap gap-2">
{audience.characteristics.map((characteristic, charIndex) => (
<Badge key={charIndex} variant="outline" className="text-small" style={{ fontFamily: 'var(--font-family-base)' }}>
{characteristic}
</Badge>
))}
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</section>
{/* Expected Outcomes Section */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="text-center mb-16 max-w-4xl mx-auto">
<h2 className="text-h2 mb-6">
Expected <span className="text-primary">Outcomes</span>
</h2>
<p className="text-body-lg text-muted">
Our leadership development programs deliver measurable improvements in strategic leadership,
executive effectiveness, and organizational performance.
</p>
</div>
{/* Three-Column Layout - Reference Design Style */}
<div className="grid lg:grid-cols-3 gap-8 max-w-7xl mx-auto">
{/* Strategic Leadership Excellence */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-blue-50 to-blue-100 flex items-center justify-center mb-6">
<Compass className="w-10 h-10 text-primary" />
</div>
<h3 className="text-h3 text-black mb-4">
Strategic Leadership Excellence
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Enhance strategic thinking capabilities, vision development, and organizational
leadership effectiveness where it matters most.
</p>
</div>
{/* Strategic Leadership Visualization */}
<div className="space-y-6">
<div className="flex justify-between items-center">
<span className="text-small text-muted font-medium">Strategic Effectiveness</span>
<span className="text-h4 text-green-600 font-bold">+94%</span>
</div>
<div className="relative">
<div className="flex items-end space-x-1 h-24 mb-4">
<div className="bg-gray-200 h-8 w-4 rounded-sm"></div>
<div className="bg-gray-300 h-12 w-4 rounded-sm"></div>
<div className="bg-gray-200 h-16 w-4 rounded-sm"></div>
<div className="bg-gray-300 h-10 w-4 rounded-sm"></div>
<div className="bg-green-400 h-20 w-4 rounded-sm"></div>
<div className="bg-green-500 h-24 w-4 rounded-sm"></div>
<div className="bg-green-600 h-22 w-4 rounded-sm"></div>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="text-center p-3 bg-green-50 rounded-lg border border-green-100">
<div className="text-xl font-bold text-green-600">91%</div>
<div className="text-small text-muted">Vision Clarity</div>
</div>
<div className="text-center p-3 bg-blue-50 rounded-lg border border-blue-100">
<div className="text-xl font-bold text-primary">88%</div>
<div className="text-small text-muted">Strategic Impact</div>
</div>
</div>
</div>
</div>
{/* Enhanced Executive Presence */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-yellow-50 to-yellow-100 flex items-center justify-center mb-6">
<Crown className="w-10 h-10 text-accent" />
</div>
<h3 className="text-h3 text-black mb-4">
Enhanced Executive Presence
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Strengthen executive presence, stakeholder influence, and communication
effectiveness for enhanced leadership impact.
</p>
</div>
{/* Executive Presence Metrics */}
<div className="space-y-6">
<div className="flex items-center justify-between mb-4">
<span className="text-small text-muted font-medium">Executive Presence</span>
<div className="flex items-center">
<TrendingUp className="w-4 h-4 text-green-500 mr-1" />
<span className="text-small text-green-600 font-medium">+91%</span>
</div>
</div>
<div className="relative bg-gray-100 rounded-full h-3 mb-6">
<div
className="bg-gradient-to-r from-yellow-400 to-yellow-500 h-3 rounded-full transition-all duration-1000"
style={{ width: '91%' }}
></div>
</div>
<div className="space-y-3">
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Communication Impact</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
93%
</div>
</div>
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Stakeholder Confidence</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
89%
</div>
</div>
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Leadership Influence</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
91%
</div>
</div>
</div>
</div>
</div>
{/* Organizational Impact */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-purple-50 to-purple-100 flex items-center justify-center mb-6">
<TrendingUp className="w-10 h-10 text-primary" />
</div>
<h3 className="text-h3 text-black mb-4">
Organizational Impact
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Drive measurable organizational performance improvements and strategic
goal achievement through enhanced leadership effectiveness.
</p>
</div>
{/* Organizational Impact KPIs */}
<div className="space-y-6">
<div className="grid grid-cols-2 gap-4">
<div className="text-center p-3 bg-blue-50 rounded-lg border border-blue-100">
<div className="flex items-center justify-center mb-1">
<span className="text-small text-muted mr-2">Performance</span>
<TrendingUp className="w-3 h-3 text-green-500" />
</div>
<div className="text-xl font-bold text-primary">83%</div>
</div>
<div className="text-center p-3 bg-red-50 rounded-lg border border-red-100">
<div className="flex items-center justify-center mb-1">
<span className="text-small text-muted mr-2">Goal Achievement</span>
<div className="w-3 h-3 flex items-center justify-center">
<div className="w-0 h-0 border-l-2 border-r-2 border-b-3 border-transparent border-b-green-500"></div>
</div>
</div>
<div className="text-xl font-bold text-green-500">89%</div>
</div>
</div>
<div className="bg-gray-50 rounded-lg p-4">
<div className="flex justify-between items-center mb-2">
<span className="text-small text-muted font-medium">Leadership Impact</span>
<span className="text-small text-primary font-bold">Annual ROI</span>
</div>
<div className="flex items-end justify-between">
<div className="text-2xl font-bold text-primary">87%</div>
<div className="text-2xl font-bold text-green-600">$2.3M</div>
</div>
</div>
<div className="grid grid-cols-3 gap-2">
<div className="text-center">
<div className="text-lg font-bold text-primary">83%</div>
<div className="text-xs text-muted">Performance</div>
</div>
<div className="text-center">
<div className="text-lg font-bold text-green-600">+28%</div>
<div className="text-xs text-muted">Revenue</div>
</div>
<div className="text-center">
<div className="text-lg font-bold text-blue-500">89%</div>
<div className="text-xs text-muted">Goals</div>
</div>
</div>
</div>
</div>
</div>
{/* Results Confirmation Banner */}
<div className="mt-16 max-w-4xl mx-auto">
<div className="bg-gradient-to-r from-green-50 to-blue-50 rounded-xl p-6 border border-green-200">
<div className="flex items-center justify-center gap-3">
<div className="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center">
<CheckCircle className="w-5 h-5 text-green-600" />
</div>
<p className="text-body text-center" style={{ fontWeight: 'var(--font-weight-subhead)', color: '#059669' }}>
All outcomes measured within 6 months of program completion
</p>
</div>
</div>
</div>
</div>
</section>
{/* Our Approach Section - Carousel Design */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12 items-start max-w-7xl mx-auto">
{/* Left Side - Title, Description & Navigation */}
<div className="lg:col-span-5 lg:pr-8">
<h2 className="text-h2 mb-6 leading-tight">
Our <span className="text-primary">Approach</span>
</h2>
<p className="text-body-lg text-muted leading-relaxed mb-8">
Comprehensive leadership development journey combining strategic assessment, customized
program design, and ongoing support for sustained executive excellence.
</p>
{/* Navigation Controls */}
<div className="flex gap-3">
<button
onClick={() => {
const container = document.getElementById('approach-carousel');
if (container) {
container.scrollBy({ left: -384, behavior: 'smooth' });
}
}}
className="w-12 h-12 rounded-full bg-gray-100 hover:bg-primary hover:text-white transition-all duration-300 flex items-center justify-center border border-gray-200 hover:border-primary"
aria-label="Previous approach step"
>
<ArrowLeft className="w-5 h-5" />
</button>
<button
onClick={() => {
const container = document.getElementById('approach-carousel');
if (container) {
container.scrollBy({ left: 384, behavior: 'smooth' });
}
}}
className="w-12 h-12 rounded-full bg-gray-100 hover:bg-primary hover:text-white transition-all duration-300 flex items-center justify-center border border-gray-200 hover:border-primary"
aria-label="Next approach step"
>
<ArrowRight className="w-5 h-5" />
</button>
</div>
</div>
{/* Right Side - Scrollable Approach Cards */}
<div className="lg:col-span-7 relative">
<div
id="approach-carousel"
className="flex gap-6 overflow-x-auto pb-4"
style={{
scrollSnapType: 'x mandatory',
WebkitOverflowScrolling: 'touch',
msOverflowStyle: 'none',
scrollbarWidth: 'none'
}}
>
{approachSteps.map((step, index) => (
<div
key={index}
className="flex-shrink-0 w-96 bg-white rounded-2xl border border-gray-200 p-8 shadow-md hover:shadow-2xl transition-all duration-300 hover:transform hover:scale-[1.02]"
style={{ scrollSnapAlign: 'start' }}
>
{/* Step Number */}
<div className="flex items-center justify-between mb-6">
<div
className="leading-none font-medium"
style={{
fontSize: 'var(--font-h2)',
fontWeight: '500',
lineHeight: 'var(--line-height-h2)',
color: 'var(--color-accent)',
fontFamily: 'var(--font-family-base)'
}}
>
{step.step}
</div>
<div className="w-16 h-0.5 bg-gradient-to-r from-accent to-transparent opacity-40"></div>
</div>
{/* Step Title */}
<h3
className="leading-tight mb-6"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
lineHeight: 'var(--line-height-h3)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{step.title}
</h3>
{/* Step Description */}
<p
className="leading-relaxed mb-6"
style={{
fontSize: 'var(--font-body)',
lineHeight: 'var(--line-height-body)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-gray-muted)'
}}
>
{step.description}
</p>
{/* Bullet Points */}
<div className="space-y-3">
{step.details.map((detail, detailIndex) => (
<div key={detailIndex} className="flex items-start gap-3">
<div className="w-1.5 h-1.5 rounded-full bg-primary flex-shrink-0 mt-2"></div>
<span
className="leading-relaxed"
style={{
fontSize: 'var(--font-small)',
lineHeight: 'var(--line-height-small)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{detail}
</span>
</div>
))}
</div>
</div>
))}
</div>
{/* Right Side Fade Overlay */}
<div
className="absolute top-0 right-0 h-full w-16 pointer-events-none z-10"
style={{
background: 'linear-gradient(to left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0.8) 40%, rgba(255, 255, 255, 0) 100%)'
}}
></div>
{/* Hide scrollbar with CSS */}
<style>{`
#approach-carousel::-webkit-scrollbar {
display: none;
}
`}</style>
</div>
</div>
</div>
</section>
<TestimonialsSection
title="What Our Executives Say"
subtitle="Hear from senior leaders who have transformed their leadership effectiveness and organizational impact through our development programs."
tagText="Executive Success"
/>
<CTABannerSection />
</div>
);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,692 @@
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 { TestimonialsSection } from '../TestimonialsSection';
import { CTABannerSection } from '../CTABannerSection';
import StackedOfferSection from '../StackedOfferSection';
import {
ArrowRight,
CheckCircle,
Settings,
Calendar,
Download,
Network,
Users,
Target,
Brain,
Eye,
TrendingUp,
BarChart3,
Award,
Lightbulb,
Shield,
ChevronDown,
ChevronUp,
ArrowLeft,
Star,
Zap,
Globe
} from 'lucide-react';
import { PrimaryCTAButton } from '../PrimaryCTAButton';
// Management development cards data for the stacking section
const managementCards = [
{
id: 1,
title: "First-Time Manager Programs",
subtitle: "Essential Leadership Transition",
description:
"Comprehensive programs for new supervisors transitioning from individual contributor roles to leadership positions, building essential management skills and confidence.",
badge: "Featured",
color: "from-blue-600 to-blue-700",
icon: Users,
features: ["Team Leadership Basics", "Delegation Skills", "Performance Conversations", "Time Management"],
stats: [
{ label: "Success Rate", value: "92%" },
{ label: "Managers Trained", value: "1,800+" },
{ label: "Duration", value: "6-12 Wks" }
]
},
{
id: 2,
title: "Operational Excellence Training",
subtitle: "Process & Quality Management",
description:
"Advanced training in process optimization, quality management, and operational efficiency that drives measurable business results and team performance improvements.",
badge: "Popular",
color: "from-purple-600 to-purple-700",
icon: Settings,
features: ["Process Improvement", "Quality Systems", "Lean Methodologies", "Performance Metrics"],
stats: [
{ label: "Efficiency Gain", value: "+76%" },
{ label: "Teams Trained", value: "900+" },
{ label: "Duration", value: "8-16 Wks" }
]
},
{
id: 3,
title: "Team Development & Coaching",
subtitle: "High-Performance Team Building",
description:
"Develop skills to build high-performing teams through effective coaching, feedback delivery, and conflict resolution that creates lasting team effectiveness.",
badge: "Strategic",
color: "from-green-600 to-green-700",
icon: Network,
features: ["Team Dynamics", "Coaching Skills", "Feedback Delivery", "Conflict Resolution"],
stats: [
{ label: "Team Performance", value: "+89%" },
{ label: "Coaches Trained", value: "1,200+" },
{ label: "Duration", value: "10-20 Wks" }
]
},
{
id: 4,
title: "Performance Management Systems",
subtitle: "Goal-Driven Excellence",
description:
"Comprehensive training in goal setting, performance tracking, and accountability frameworks that drive consistent results and organizational success.",
badge: "Comprehensive",
color: "from-orange-600 to-orange-700",
icon: Target,
features: ["Goal Setting", "KPI Development", "Performance Reviews", "Accountability Systems"],
stats: [
{ label: "Goal Achievement", value: "+93%" },
{ label: "Systems Deployed", value: "650+" },
{ label: "Duration", value: "4-12 Wks" }
]
}
];
const targetAudience = [
{
title: "First-Time Managers",
description: "New supervisors and team leaders learning essential management skills and responsibilities",
icon: Users,
characteristics: ["New to management", "Team oversight", "Skill development", "Leadership transition"]
},
{
title: "Operations Managers",
description: "Managers focused on operational efficiency, process improvement, and team performance",
icon: Settings,
characteristics: ["Operational focus", "Process optimization", "Team performance", "Quality management"]
},
{
title: "Department Heads",
description: "Mid-level managers responsible for multiple teams and cross-functional collaboration",
icon: Award,
characteristics: ["Multi-team leadership", "Cross-functional work", "Strategic execution", "Resource management"]
}
];
const outcomes = [
{
title: "Improved Team Performance",
description: "Measurable improvements in team productivity, engagement, and operational effectiveness",
icon: TrendingUp,
metrics: "89% of managers report improved team performance and productivity within 90 days"
},
{
title: "Enhanced Management Confidence",
description: "Increased confidence in handling management responsibilities and challenging situations",
icon: Shield,
metrics: "92% improvement in management confidence and decision-making effectiveness"
},
{
title: "Better Operational Results",
description: "Improved operational metrics, process efficiency, and quality outcomes",
icon: BarChart3,
metrics: "76% improvement in operational KPIs and process efficiency measures"
}
];
const approachSteps = [
{
step: "01",
title: "Skills Assessment",
description: "Comprehensive assessment of current management skills and development needs. Together, we make your vision manifest through comprehensive assessment methodologies and proven frameworks.",
details: ["Management assessment", "Skills gap analysis", "360-degree feedback", "Development priorities"],
icon: Eye
},
{
step: "02",
title: "Program Design",
description: "Customized curriculum design based on assessment results and operational context. Together, we make your vision manifest through comprehensive design methodologies and proven frameworks.",
details: ["Curriculum development", "Learning objectives", "Practical application", "Timeline planning"],
icon: Brain
},
{
step: "03",
title: "Interactive Learning",
description: "Hands-on workshops and peer learning sessions with real-world application. Together, we make your vision manifest through comprehensive learning methodologies and proven frameworks.",
details: ["Management workshops", "Peer collaboration", "Case studies", "Skills practice"],
icon: Network
},
{
step: "04",
title: "Application & Review",
description: "Ongoing support and progress tracking to ensure skills transfer and improvement. Together, we make your vision manifest through comprehensive review methodologies and proven frameworks.",
details: ["Skills application", "Progress tracking", "Feedback sessions", "Continuous improvement"],
icon: BarChart3
}
];
export function ManagementDevelopment() {
const [expandedAudienceIndex, setExpandedAudienceIndex] = useState<number | null>(0);
useEffect(() => {
window.scrollTo(0, 0);
}, []);
const toggleAudienceExpanded = (index: number) => {
setExpandedAudienceIndex(expandedAudienceIndex === index ? null : index);
};
return (
<div className="min-h-screen" style={{ backgroundColor: '#FFFFFF' }}>
{/* Hero Section */}
<section className="relative min-h-[90vh] flex flex-col">
<div className="absolute inset-0 z-0">
<ImageWithFallback
src="https://images.unsplash.com/photo-1521737711867-e3b97375f902?w=1920&h=1080&fit=crop"
alt="Professional business meeting - management development"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-r from-black/80 via-black/70 to-black/60"></div>
</div>
<div className="relative z-10 flex-1 flex items-center">
<div className="container mx-auto section-margin-x">
<div className="text-center max-w-5xl mx-auto">
<div className="branded-tag-system-white mb-8 justify-center">
<div className="dot"></div>
<span className="text">Management Excellence</span>
</div>
<h1 className="text-h1-white mb-6">
Management Development Services
</h1>
<p className="text-body-lg-white mb-8 max-w-2xl mx-auto">
As your trusted management development partner, we bring the expertise and
experience to ensure your leadership workforce aligns seamlessly with your goals.
</p>
<div className="flex flex-col sm:flex-row gap-4 mb-12 justify-center">
<PrimaryCTAButton
text="Book a demo"
onClick={() => navigateTo('/contact')}
className="management-dev-primary-cta"
/>
<Button
onClick={() => window.open('/curriculum-download', '_blank')}
className="management-dev-glassmorphic-btn text-body px-8 py-4 min-h-[52px] border text-white transition-all duration-300"
style={{
fontFamily: 'var(--font-family-base)'
}}
>
<Download className="w-5 h-5 mr-2" />
Download Curriculum
</Button>
</div>
</div>
</div>
</div>
<div className="relative z-10 border-t border-white/20 backdrop-blur-sm bg-black/20">
<div className="container mx-auto section-margin-x py-8">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8 text-center max-w-5xl mx-auto">
<div>
<div className="text-h2-white mb-2">85%</div>
<div className="text-small-white opacity-90">Improvement in team performance</div>
</div>
<div>
<div className="text-h2-white mb-2">1,800+</div>
<div className="text-small-white opacity-90">Managers trained</div>
</div>
<div>
<div className="text-h2-white mb-2">40%</div>
<div className="text-small-white opacity-90">Faster decision making</div>
</div>
<div>
<div className="text-h2-white mb-2">93%</div>
<div className="text-small-white opacity-90">Project completion rate</div>
</div>
</div>
</div>
</div>
</section>
{/* Stacked Offer Section */}
<StackedOfferSection cards={managementCards} />
{/* Who It's For Section */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="grid lg:grid-cols-2 gap-16 items-start max-w-7xl mx-auto">
<div className="lg:pr-8">
<h2 className="text-h2 mb-6 text-black leading-tight">
Who It's <span className="text-primary">For</span>
</h2>
<p className="text-body-lg text-muted leading-relaxed">
Our management development programs cater to professionals at various stages of their
management journey, from first-time supervisors to experienced leaders.
</p>
</div>
<div className="space-y-1">
{targetAudience.map((audience, index) => (
<div
key={index}
className="border-b border-gray-400 last:border-b-0"
>
<button
onClick={() => toggleAudienceExpanded(index)}
className="w-full py-6 px-0 flex items-center justify-between text-left hover:bg-transparent focus:outline-none group transition-all duration-200"
style={{ backgroundColor: 'transparent' }}
>
<span className="text-h4 text-black group-hover:text-primary transition-colors duration-200 pr-4">
{audience.title}
</span>
<div className="flex-shrink-0 ml-4">
{expandedAudienceIndex === index ? (
<ChevronUp className="w-6 h-6 text-primary transition-transform duration-200" />
) : (
<ChevronDown className="w-6 h-6 text-gray-400 group-hover:text-primary transition-all duration-200" />
)}
</div>
</button>
<div className={`overflow-hidden transition-all duration-300 ease-in-out ${
expandedAudienceIndex === index ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
}`}>
<div className="pb-6 pr-8">
<p className="text-body text-muted leading-relaxed mb-4">
{audience.description}
</p>
<div className="flex flex-wrap gap-2">
{audience.characteristics.map((characteristic, charIndex) => (
<Badge key={charIndex} variant="outline" className="text-small" style={{ fontFamily: 'var(--font-family-base)' }}>
{characteristic}
</Badge>
))}
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</section>
{/* Expected Outcomes Section - Redesigned to Match Reference */}
<section className="py-20" style={{ backgroundColor: 'rgba(247, 247, 253, 0.5)' }}>
<div className="container mx-auto section-margin-x">
<div className="text-center mb-16 max-w-4xl mx-auto">
<h2 className="text-h2 mb-6">
Expected <span className="text-primary">Outcomes</span>
</h2>
<p className="text-body-lg text-muted">
Our management development programs deliver tangible improvements in team performance,
operational efficiency, and leadership effectiveness.
</p>
</div>
{/* Three-Column Layout - Reference Design Style */}
<div className="grid lg:grid-cols-3 gap-8 max-w-7xl mx-auto">
{/* Improved Team Performance */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-blue-50 to-blue-100 flex items-center justify-center mb-6">
<TrendingUp className="w-10 h-10 text-primary" />
</div>
<h3 className="text-h3 text-black mb-4">
Improved Team Performance
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Smooth out team inefficiencies, conserve leadership capital, and invest
in your management capabilities where it matters most.
</p>
</div>
{/* Performance Visualization */}
<div className="space-y-6">
<div className="flex justify-between items-center">
<span className="text-small text-muted font-medium">Team Productivity</span>
<span className="text-h4 text-green-600 font-bold">+89%</span>
</div>
<div className="relative">
<div className="flex items-end space-x-1 h-24 mb-4">
<div className="bg-gray-200 h-8 w-4 rounded-sm"></div>
<div className="bg-gray-300 h-12 w-4 rounded-sm"></div>
<div className="bg-gray-200 h-16 w-4 rounded-sm"></div>
<div className="bg-gray-300 h-10 w-4 rounded-sm"></div>
<div className="bg-green-400 h-20 w-4 rounded-sm"></div>
<div className="bg-green-500 h-24 w-4 rounded-sm"></div>
<div className="bg-green-600 h-22 w-4 rounded-sm"></div>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="text-center p-3 bg-green-50 rounded-lg border border-green-100">
<div className="text-xl font-bold text-green-600">85%</div>
<div className="text-small text-muted">Engagement</div>
</div>
<div className="text-center p-3 bg-blue-50 rounded-lg border border-blue-100">
<div className="text-xl font-bold text-primary">92%</div>
<div className="text-small text-muted">Retention</div>
</div>
</div>
</div>
</div>
{/* Enhanced Management Confidence */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-yellow-50 to-yellow-100 flex items-center justify-center mb-6">
<Shield className="w-10 h-10 text-accent" />
</div>
<h3 className="text-h3 text-black mb-4">
Enhanced Management Confidence
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Close confidence gaps and streamline decision-making processes
without compromising leadership relationships.
</p>
</div>
{/* Confidence Metrics */}
<div className="space-y-6">
<div className="flex items-center justify-between mb-4">
<span className="text-small text-muted font-medium">Confidence Level</span>
<div className="flex items-center">
<TrendingUp className="w-4 h-4 text-green-500 mr-1" />
<span className="text-small text-green-600 font-medium">+92%</span>
</div>
</div>
<div className="relative bg-gray-100 rounded-full h-3 mb-6">
<div
className="bg-gradient-to-r from-yellow-400 to-yellow-500 h-3 rounded-full transition-all duration-1000"
style={{ width: '92%' }}
></div>
</div>
<div className="space-y-3">
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Decision Making</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
95%
</div>
</div>
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Team Leadership</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
89%
</div>
</div>
<div className="flex justify-between items-center py-2">
<span className="text-small text-muted">Conflict Resolution</span>
<div className="bg-yellow-100 text-yellow-700 px-2 py-1 rounded text-small font-medium">
87%
</div>
</div>
</div>
</div>
</div>
{/* Better Operational Results */}
<div className="bg-white p-10 rounded-2xl border border-gray-100 shadow-sm hover:shadow-lg transition-all duration-300">
<div className="mb-8">
<div className="w-20 h-20 rounded-2xl bg-gradient-to-br from-purple-50 to-purple-100 flex items-center justify-center mb-6">
<BarChart3 className="w-10 h-10 text-primary" />
</div>
<h3 className="text-h3 text-black mb-4">
Better Operational Results
</h3>
<p className="text-body text-muted leading-relaxed mb-8">
Seize control of your operational KPIs and build towards your
performance goals without barriers.
</p>
</div>
{/* Operational KPIs */}
<div className="space-y-6">
<div className="grid grid-cols-2 gap-4">
<div className="text-center p-3 bg-blue-50 rounded-lg border border-blue-100">
<div className="flex items-center justify-center mb-1">
<span className="text-small text-muted mr-2">Process Efficiency</span>
<TrendingUp className="w-3 h-3 text-green-500" />
</div>
<div className="text-xl font-bold text-primary">76%</div>
</div>
<div className="text-center p-3 bg-red-50 rounded-lg border border-red-100">
<div className="flex items-center justify-center mb-1">
<span className="text-small text-muted mr-2">Cost Reduction</span>
<div className="w-3 h-3 flex items-center justify-center">
<div className="w-0 h-0 border-l-2 border-r-2 border-b-3 border-transparent border-b-red-500"></div>
</div>
</div>
<div className="text-xl font-bold text-red-500">12%</div>
</div>
</div>
<div className="bg-gray-50 rounded-lg p-4">
<div className="flex justify-between items-center mb-2">
<span className="text-small text-muted font-medium">Quality Metrics</span>
<span className="text-small text-primary font-bold">Annual Revenue</span>
</div>
<div className="flex items-end justify-between">
<div className="text-2xl font-bold text-primary">82%</div>
<div className="text-2xl font-bold text-green-600">$1.7M</div>
</div>
</div>
<div className="grid grid-cols-3 gap-2">
<div className="text-center">
<div className="text-lg font-bold text-primary">76%</div>
<div className="text-xs text-muted">Efficiency</div>
</div>
<div className="text-center">
<div className="text-lg font-bold text-green-600">+25%</div>
<div className="text-xs text-muted">Revenue</div>
</div>
<div className="text-center">
<div className="text-lg font-bold text-red-500">-12%</div>
<div className="text-xs text-muted">Costs</div>
</div>
</div>
</div>
</div>
</div>
{/* Results Confirmation Banner */}
<div className="mt-16 max-w-4xl mx-auto">
<div className="bg-gradient-to-r from-green-50 to-blue-50 rounded-xl p-6 border border-green-200">
<div className="flex items-center justify-center gap-3">
<div className="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center">
<CheckCircle className="w-5 h-5 text-green-600" />
</div>
<p className="text-body text-center" style={{ fontWeight: 'var(--font-weight-subhead)', color: '#059669' }}>
All outcomes measured within 6 months of program completion
</p>
</div>
</div>
</div>
</div>
</section>
{/* Our Approach Section - Carousel Design */}
<section className="py-20" style={{ backgroundColor: '#FFFFFF' }}>
<div className="container mx-auto section-margin-x">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12 items-start max-w-7xl mx-auto">
{/* Left Side - Title, Description & Navigation */}
<div className="lg:col-span-5 lg:pr-8">
<h2 className="text-h2 mb-6 leading-tight">
Our <span className="text-primary">Approach</span>
</h2>
<p className="text-body-lg text-muted leading-relaxed mb-8">
Programmatic journey over 612 weeks combining practical application with peer learning
for maximum management effectiveness.
</p>
{/* Navigation Controls */}
<div className="flex gap-3">
<button
onClick={() => {
const container = document.getElementById('approach-carousel');
if (container) {
container.scrollBy({ left: -320, behavior: 'smooth' });
}
}}
className="w-12 h-12 rounded-full bg-gray-100 hover:bg-primary hover:text-white transition-all duration-300 flex items-center justify-center border border-gray-200 hover:border-primary"
aria-label="Previous approach step"
>
<ArrowLeft className="w-5 h-5" />
</button>
<button
onClick={() => {
const container = document.getElementById('approach-carousel');
if (container) {
container.scrollBy({ left: 320, behavior: 'smooth' });
}
}}
className="w-12 h-12 rounded-full bg-gray-100 hover:bg-primary hover:text-white transition-all duration-300 flex items-center justify-center border border-gray-200 hover:border-primary"
aria-label="Next approach step"
>
<ArrowRight className="w-5 h-5" />
</button>
</div>
</div>
{/* Right Side - Scrollable Approach Cards */}
<div className="lg:col-span-7 relative">
<div
id="approach-carousel"
className="flex gap-6 overflow-x-auto pb-4"
style={{
scrollSnapType: 'x mandatory',
WebkitOverflowScrolling: 'touch',
msOverflowStyle: 'none',
scrollbarWidth: 'none'
}}
>
{approachSteps.map((step, index) => (
<div
key={index}
className="flex-shrink-0 w-80 bg-white rounded-2xl border border-gray-100 p-8 hover:shadow-lg transition-all duration-300 hover:transform hover:scale-[1.02]"
style={{ scrollSnapAlign: 'start' }}
>
{/* Step Number */}
<div className="flex items-center justify-between mb-6">
<div
className="leading-none font-medium"
style={{
fontSize: 'var(--font-h2)',
fontWeight: '500',
lineHeight: 'var(--line-height-h2)',
color: 'var(--color-accent)',
fontFamily: 'var(--font-family-base)'
}}
>
{step.step}
</div>
<div className="w-16 h-0.5 bg-gradient-to-r from-accent to-transparent opacity-40"></div>
</div>
{/* Step Title */}
<h3
className="leading-tight mb-6"
style={{
fontSize: 'var(--font-h3)',
fontWeight: 'var(--font-weight-h3)',
lineHeight: 'var(--line-height-h3)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{step.title}
</h3>
{/* Step Description */}
<p
className="leading-relaxed mb-6"
style={{
fontSize: 'var(--font-body)',
lineHeight: 'var(--line-height-body)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-gray-muted)'
}}
>
{step.description}
</p>
{/* Bullet Points */}
<div className="space-y-3">
{step.details.map((detail, detailIndex) => (
<div key={detailIndex} className="flex items-start gap-3">
<div className="w-1.5 h-1.5 rounded-full bg-primary flex-shrink-0 mt-2"></div>
<span
className="leading-relaxed"
style={{
fontSize: 'var(--font-small)',
lineHeight: 'var(--line-height-small)',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{detail}
</span>
</div>
))}
</div>
</div>
))}
</div>
{/* Right Side Fade Overlay */}
<div
className="absolute top-0 right-0 h-full w-16 pointer-events-none z-10"
style={{
background: 'linear-gradient(to left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0.8) 40%, rgba(255, 255, 255, 0) 100%)'
}}
></div>
{/* Hide scrollbar with CSS */}
<style>{`
#approach-carousel::-webkit-scrollbar {
display: none;
}
`}</style>
</div>
</div>
</div>
</section>
<TestimonialsSection
title="What Our Managers Say"
subtitle="Hear from participants who have enhanced their management effectiveness and operational results through our development programs."
tagText="Management Success"
/>
<CTABannerSection />
</div>
);
}

View File

@@ -0,0 +1,66 @@
"use client";
import * as React from "react";
import * as AccordionPrimitive from "@radix-ui/react-accordion@1.2.3";
import { ChevronDownIcon } from "lucide-react@0.487.0";
import { cn } from "./utils";
function Accordion({
...props
}: React.ComponentProps<typeof AccordionPrimitive.Root>) {
return <AccordionPrimitive.Root data-slot="accordion" {...props} />;
}
function AccordionItem({
className,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
return (
<AccordionPrimitive.Item
data-slot="accordion-item"
className={cn("border-b last:border-b-0", className)}
{...props}
/>
);
}
function AccordionTrigger({
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
return (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
data-slot="accordion-trigger"
className={cn(
"focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180",
className,
)}
{...props}
>
{children}
<ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
);
}
function AccordionContent({
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Content>) {
return (
<AccordionPrimitive.Content
data-slot="accordion-content"
className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm"
{...props}
>
<div className={cn("pt-0 pb-4", className)}>{children}</div>
</AccordionPrimitive.Content>
);
}
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };

View File

@@ -0,0 +1,157 @@
"use client";
import * as React from "react";
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog@1.1.6";
import { cn } from "./utils";
import { buttonVariants } from "./button";
function AlertDialog({
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
}
function AlertDialogTrigger({
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
return (
<AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
);
}
function AlertDialogPortal({
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
return (
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
);
}
function AlertDialogOverlay({
className,
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
return (
<AlertDialogPrimitive.Overlay
data-slot="alert-dialog-overlay"
className={cn(
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
className,
)}
{...props}
/>
);
}
function AlertDialogContent({
className,
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {
return (
<AlertDialogPortal>
<AlertDialogOverlay />
<AlertDialogPrimitive.Content
data-slot="alert-dialog-content"
className={cn(
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
className,
)}
{...props}
/>
</AlertDialogPortal>
);
}
function AlertDialogHeader({
className,
...props
}: React.ComponentProps<"div">) {
return (
<div
data-slot="alert-dialog-header"
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
{...props}
/>
);
}
function AlertDialogFooter({
className,
...props
}: React.ComponentProps<"div">) {
return (
<div
data-slot="alert-dialog-footer"
className={cn(
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
className,
)}
{...props}
/>
);
}
function AlertDialogTitle({
className,
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
return (
<AlertDialogPrimitive.Title
data-slot="alert-dialog-title"
className={cn("text-lg font-semibold", className)}
{...props}
/>
);
}
function AlertDialogDescription({
className,
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
return (
<AlertDialogPrimitive.Description
data-slot="alert-dialog-description"
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
);
}
function AlertDialogAction({
className,
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {
return (
<AlertDialogPrimitive.Action
className={cn(buttonVariants(), className)}
{...props}
/>
);
}
function AlertDialogCancel({
className,
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {
return (
<AlertDialogPrimitive.Cancel
className={cn(buttonVariants({ variant: "outline" }), className)}
{...props}
/>
);
}
export {
AlertDialog,
AlertDialogPortal,
AlertDialogOverlay,
AlertDialogTrigger,
AlertDialogContent,
AlertDialogHeader,
AlertDialogFooter,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogAction,
AlertDialogCancel,
};

View File

@@ -0,0 +1,66 @@
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority@0.7.1";
import { cn } from "./utils";
const alertVariants = cva(
"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
{
variants: {
variant: {
default: "bg-card text-card-foreground",
destructive:
"text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
},
},
defaultVariants: {
variant: "default",
},
},
);
function Alert({
className,
variant,
...props
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
return (
<div
data-slot="alert"
role="alert"
className={cn(alertVariants({ variant }), className)}
{...props}
/>
);
}
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="alert-title"
className={cn(
"col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight",
className,
)}
{...props}
/>
);
}
function AlertDescription({
className,
...props
}: React.ComponentProps<"div">) {
return (
<div
data-slot="alert-description"
className={cn(
"text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed",
className,
)}
{...props}
/>
);
}
export { Alert, AlertTitle, AlertDescription };

View File

@@ -0,0 +1,11 @@
"use client";
import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio@1.1.2";
function AspectRatio({
...props
}: React.ComponentProps<typeof AspectRatioPrimitive.Root>) {
return <AspectRatioPrimitive.Root data-slot="aspect-ratio" {...props} />;
}
export { AspectRatio };

View File

@@ -0,0 +1,53 @@
"use client";
import * as React from "react";
import * as AvatarPrimitive from "@radix-ui/react-avatar@1.1.3";
import { cn } from "./utils";
function Avatar({
className,
...props
}: React.ComponentProps<typeof AvatarPrimitive.Root>) {
return (
<AvatarPrimitive.Root
data-slot="avatar"
className={cn(
"relative flex size-10 shrink-0 overflow-hidden rounded-full",
className,
)}
{...props}
/>
);
}
function AvatarImage({
className,
...props
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
return (
<AvatarPrimitive.Image
data-slot="avatar-image"
className={cn("aspect-square size-full", className)}
{...props}
/>
);
}
function AvatarFallback({
className,
...props
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
return (
<AvatarPrimitive.Fallback
data-slot="avatar-fallback"
className={cn(
"bg-muted flex size-full items-center justify-center rounded-full",
className,
)}
{...props}
/>
);
}
export { Avatar, AvatarImage, AvatarFallback };

View File

@@ -0,0 +1,46 @@
import * as React from "react";
import { Slot } from "@radix-ui/react-slot@1.1.2";
import { cva, type VariantProps } from "class-variance-authority@0.7.1";
import { cn } from "./utils";
const badgeVariants = cva(
"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
secondary:
"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
destructive:
"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:
"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
},
},
defaultVariants: {
variant: "default",
},
},
);
function Badge({
className,
variant,
asChild = false,
...props
}: React.ComponentProps<"span"> &
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
const Comp = asChild ? Slot : "span";
return (
<Comp
data-slot="badge"
className={cn(badgeVariants({ variant }), className)}
{...props}
/>
);
}
export { Badge, badgeVariants };

Some files were not shown because too many files have changed in this diff Show More