@devvistatech/devvista-kit 0.0.12 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/app/ClientLayout.tsx +66 -0
- package/app/about/page.tsx +11 -248
- package/app/adRequest/page.tsx +101 -25
- package/app/admin-profile/page.tsx +123 -0
- package/app/analytics/page.tsx +41 -5
- package/app/api/about/route.ts +2 -18
- package/app/api/adRequest/route.ts +7 -27
- package/app/api/analytics/[reportType]/route.ts +1 -64
- package/app/api/bio/route.ts +1 -17
- package/app/api/blog/route.ts +1 -19
- package/app/api/contacts/route.ts +1 -46
- package/app/api/files/route.ts +1 -15
- package/app/api/gallery-data/route.ts +53 -61
- package/app/api/schedule/route.ts +5 -21
- package/app/api/signup/route.ts +129 -0
- package/app/api/sync-user/route.ts +268 -94
- package/app/api/verify-admin/route.ts +46 -0
- package/app/blog/[id]/page.tsx +71 -52
- package/app/blog/page.tsx +43 -10
- package/app/favicon.ico +0 -0
- package/app/gallery/page.tsx +27 -6
- package/app/layout.tsx +31 -82
- package/app/page.tsx +20 -311
- package/app/products/constants/product.ts +27 -0
- package/app/products/page.tsx +296 -0
- package/app/products/productOne/page.tsx +266 -0
- package/app/products/productTwo/page.tsx +272 -0
- package/app/schedule/page.tsx +78 -40
- package/bin/init.js +0 -12
- package/components/addOns/functional/ClassList.tsx +21 -17
- package/components/addOns/functional/ProductList.tsx +1027 -0
- package/components/addOns/functional/aboutSections/AboutSection.tsx +107 -70
- package/components/addOns/functional/aboutSections/constants/aboutSection.ts +9 -4
- package/components/addOns/functional/banner/Banner.tsx +150 -0
- package/components/addOns/functional/banner/BannerDashboard.tsx +283 -0
- package/components/addOns/functional/bioSections/BioEditor.tsx +471 -0
- package/components/addOns/functional/bioSections/constants/bioEditor.ts +36 -0
- package/components/addOns/functional/blogSections/BlogDashboard.tsx +1 -1
- package/components/addOns/functional/blogSections/BlogFormPopUp.tsx +2 -1
- package/components/addOns/functional/{ImageDescCarousel.tsx → carousels/ImageDescCarousel.tsx} +166 -57
- package/components/addOns/functional/carousels/ProductDescCarousel.tsx +1129 -0
- package/components/addOns/functional/{ScheduleCarousel.tsx → carousels/ScheduleCarousel.tsx} +110 -50
- package/components/addOns/functional/carousels/constants.ts/productDescCarousel.ts +197 -0
- package/components/addOns/functional/carousels/constants.ts/scheduleCarousel.ts +20 -0
- package/components/addOns/functional/contactsDashboard/ContactsDashboard.tsx +1 -1
- package/components/addOns/functional/fileUploaders/FileUploader.tsx +437 -0
- package/components/addOns/functional/fileUploaders/constants/fileUploader.ts +45 -0
- package/components/addOns/functional/galleries/GalleryComplex.tsx +468 -267
- package/components/addOns/functional/galleries/GallerySimple.tsx +78 -50
- package/components/addOns/functional/galleries/ThreeSetGallery.tsx +260 -0
- package/components/addOns/functional/schedules/ScheduleGridOne.tsx +22 -8
- package/components/addOns/functional/schedules/ScheduleGridTwo.tsx +12 -7
- package/components/addOns/functional/schedules/ScheduleGridTwoBasic.tsx +12 -7
- package/components/addOns/non-functional/SampleCarousel.tsx +3 -3
- package/components/addOns/non-functional/ThreeSetGallery.tsx +3 -3
- package/components/addOns/non-functional/featureSections/FeaturesSection.tsx +74 -0
- package/components/addOns/non-functional/featureSections/constants/featuresSection.ts +30 -0
- package/components/addOns/non-functional/{Heros/HeroSection.tsx → heros/HomeHero.tsx} +17 -15
- package/components/addOns/non-functional/heros/ProductHero.tsx +111 -0
- package/components/addOns/non-functional/heros/constants/hero.ts +62 -0
- package/components/addOns/non-functional/imageCarousels/ProductSlider.tsx +6 -6
- package/components/addOns/non-functional/imageCarousels/ProgramCarousel.tsx +10 -10
- package/components/footers/footer.tsx +161 -198
- package/components/other/admin-menu.tsx +1 -1
- package/lib/auth/auth-context.tsx +225 -0
- package/lib/auth/auth-utils.tsx +30 -0
- package/lib/constants/adRequest.ts +199 -56
- package/lib/constants/admin-profile.ts +12 -0
- package/lib/constants/page.ts +15 -15
- package/lib/google/google-analytics-tracking.tsx +44 -0
- package/lib/types.ts +235 -0
- package/lib/utils/compressImage.tsx +32 -0
- package/middleware.ts +9 -5
- package/next.config.js +1 -1
- package/package.json +3 -2
- package/public/images/test.png +0 -0
- package/components/addOns/functional/BioEditor.tsx +0 -447
- package/components/addOns/functional/FileUploader.tsx +0 -295
- package/components/addOns/non-functional/FeaturesSection.tsx +0 -63
- package/components/types.ts +0 -50
- package/lib/auth-context.tsx +0 -131
- package/lib/verify-user.ts +0 -118
- /package/lib/{google-analytics.tsx → google/google-analytics.tsx} +0 -0
|
@@ -46,21 +46,21 @@ export default function SampleCarousel() {
|
|
|
46
46
|
{
|
|
47
47
|
brand: 'Lorem',
|
|
48
48
|
type: 'Ipsum Dolor',
|
|
49
|
-
src: '
|
|
49
|
+
src: '',
|
|
50
50
|
alt: '',
|
|
51
51
|
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.',
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
brand: 'Lorem',
|
|
55
55
|
type: 'Sit Amet',
|
|
56
|
-
src: '
|
|
56
|
+
src: '',
|
|
57
57
|
alt: '',
|
|
58
58
|
description: 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium.',
|
|
59
59
|
},
|
|
60
60
|
{
|
|
61
61
|
brand: 'Lorem',
|
|
62
62
|
type: 'Consectetur',
|
|
63
|
-
src: '
|
|
63
|
+
src: '',
|
|
64
64
|
alt: '',
|
|
65
65
|
description: 'At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis.',
|
|
66
66
|
}
|
|
@@ -13,19 +13,19 @@ interface ThreeSetGalleryProps {
|
|
|
13
13
|
const ThreeSetGallery = ({
|
|
14
14
|
images = [
|
|
15
15
|
{
|
|
16
|
-
src: '
|
|
16
|
+
src: '',
|
|
17
17
|
alt: 'Gallery Image 1',
|
|
18
18
|
title: 'Image One',
|
|
19
19
|
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
|
-
src: '
|
|
22
|
+
src: '',
|
|
23
23
|
alt: 'Gallery Image 2',
|
|
24
24
|
title: 'Image Two',
|
|
25
25
|
description: 'Sed do eiusmod tempor incididunt ut labore et dolore.',
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
|
-
src: '
|
|
28
|
+
src: '',
|
|
29
29
|
alt: 'Gallery Image 3',
|
|
30
30
|
title: 'Image Three',
|
|
31
31
|
description: 'Ut enim ad minim veniam, quis nostrud exercitation.',
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// src/components/addOns/non-functional/FeaturesSection.tsx
|
|
2
|
+
"use client";
|
|
3
|
+
|
|
4
|
+
import { motion } from "framer-motion";
|
|
5
|
+
import { ActionButton } from "@/components/other/button";
|
|
6
|
+
import { CheckCircle, ArrowRight } from "lucide-react";
|
|
7
|
+
import Link from "next/link";
|
|
8
|
+
import { FEATURES_SECTION } from "./constants/featuresSection";
|
|
9
|
+
|
|
10
|
+
interface Feature {
|
|
11
|
+
text: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function FeaturesSection() {
|
|
15
|
+
const sectionVariants = {
|
|
16
|
+
hidden: { opacity: 0, y: 20 },
|
|
17
|
+
visible: { opacity: 1, y: 0, transition: { duration: 0.5, ease: "easeOut" } },
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const itemVariants = {
|
|
21
|
+
hidden: { opacity: 0, y: 10 },
|
|
22
|
+
visible: { opacity: 1, y: 0, transition: { duration: 0.5, ease: "easeOut" } },
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<motion.section
|
|
27
|
+
variants={sectionVariants}
|
|
28
|
+
initial="hidden"
|
|
29
|
+
animate="visible"
|
|
30
|
+
className="w-full py-16 sm:py-24 px-4 sm:px-8 bg-blue-200 z-0"
|
|
31
|
+
>
|
|
32
|
+
<style jsx>{`
|
|
33
|
+
:root {
|
|
34
|
+
--jubilee: #F47C7C;
|
|
35
|
+
--exuberant-blue: #FF69B4;
|
|
36
|
+
}
|
|
37
|
+
`}</style>
|
|
38
|
+
<div className="w-full pt-16 sm:pt-24 pb-16 sm:pb-24">
|
|
39
|
+
<div className="max-w-7xl mx-auto px-4 sm:px-6">
|
|
40
|
+
<div className="flex flex-col md:flex-row gap-6 justify-center items-center">
|
|
41
|
+
<motion.div variants={itemVariants} className="w-full md:w-1/2 space-y-6 flex justify-center">
|
|
42
|
+
<ul className="space-y-4 text-2xl font-semibold">
|
|
43
|
+
{FEATURES_SECTION.UI.FEATURES.map((feature, index) => (
|
|
44
|
+
<motion.li
|
|
45
|
+
key={index}
|
|
46
|
+
variants={itemVariants}
|
|
47
|
+
className="flex items-center justify-start"
|
|
48
|
+
>
|
|
49
|
+
<CheckCircle className="mr-3 h-6 w-6 text-[#FF69B4] flex-shrink-0" />
|
|
50
|
+
<span>{feature.text}</span>
|
|
51
|
+
</motion.li>
|
|
52
|
+
))}
|
|
53
|
+
</ul>
|
|
54
|
+
</motion.div>
|
|
55
|
+
<motion.div variants={itemVariants} className="w-full md:w-1/2 space-y-6 text-center pt-12">
|
|
56
|
+
<h4 className="text-4xl sm:text-5xl font-bold text-[#333] tracking-tight">
|
|
57
|
+
{FEATURES_SECTION.UI.TITLE}
|
|
58
|
+
</h4>
|
|
59
|
+
<p className="text-xl sm:text-2xl font-semibold text-[#333]">
|
|
60
|
+
{FEATURES_SECTION.UI.DESCRIPTION}
|
|
61
|
+
</p>
|
|
62
|
+
<ActionButton asChild>
|
|
63
|
+
<Link href={FEATURES_SECTION.UI.CTA_LINK} className="flex items-center justify-center">
|
|
64
|
+
{FEATURES_SECTION.UI.CTA_TEXT}
|
|
65
|
+
<ArrowRight className="ml-2 h-6 w-6" />
|
|
66
|
+
</Link>
|
|
67
|
+
</ActionButton>
|
|
68
|
+
</motion.div>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</motion.section>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/components/addOns/non-functional/constants/featuresSection.ts
|
|
2
|
+
export const FEATURES_SECTION = {
|
|
3
|
+
UI: {
|
|
4
|
+
TITLE: "Our Features",
|
|
5
|
+
DESCRIPTION: "Discover the unique features that make our fitness studio stand out.",
|
|
6
|
+
CTA_TEXT: "Join Now",
|
|
7
|
+
CTA_LINK: "/schedule",
|
|
8
|
+
FEATURES: [
|
|
9
|
+
{ text: "State-of-the-art equipment" },
|
|
10
|
+
{ text: "Expert trainers" },
|
|
11
|
+
{ text: "Flexible class schedules" },
|
|
12
|
+
{ text: "Community-driven environment" },
|
|
13
|
+
{ text: "Personalized fitness plans" },
|
|
14
|
+
],
|
|
15
|
+
},
|
|
16
|
+
ERRORS: {
|
|
17
|
+
// Add error messages if dynamic fetching or updates are implemented
|
|
18
|
+
FETCH_FAILED: "Failed to fetch features data",
|
|
19
|
+
FETCH_ERROR: "An error occurred while fetching features",
|
|
20
|
+
UNAUTHORIZED_UPDATE: "You are not authorized to update features",
|
|
21
|
+
NO_AUTH_TOKEN: "Authentication token not found",
|
|
22
|
+
UPDATE_FAILED: "Failed to update features: ${response.status}",
|
|
23
|
+
UPDATE_ERROR: "An error occurred while updating features",
|
|
24
|
+
},
|
|
25
|
+
BUTTONS: {
|
|
26
|
+
UPDATE_BUTTON: "Update Features",
|
|
27
|
+
SAVING_BUTTON: "Saving...",
|
|
28
|
+
CANCEL_BUTTON: "Cancel",
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -1,29 +1,31 @@
|
|
|
1
|
+
// components/addOns/non-functional/heros/constants/HomeHero.tsx
|
|
1
2
|
"use client";
|
|
2
3
|
|
|
3
4
|
import { useRef, useEffect, useState } from "react";
|
|
4
5
|
import { HeroButton } from "@/components/other/button";
|
|
5
6
|
import Link from "next/link";
|
|
6
7
|
import SocialIcons from "@/components/other/social-icons";
|
|
8
|
+
import { HERO } from "./constants/hero";
|
|
7
9
|
|
|
8
10
|
interface HeroSectionProps {
|
|
9
|
-
title
|
|
10
|
-
subtitle
|
|
11
|
-
ctaText
|
|
12
|
-
ctaLink
|
|
13
|
-
videoSrc
|
|
14
|
-
posterSrc
|
|
15
|
-
videoAriaLabel
|
|
11
|
+
title?: string;
|
|
12
|
+
subtitle?: string;
|
|
13
|
+
ctaText?: string;
|
|
14
|
+
ctaLink?: string;
|
|
15
|
+
videoSrc?: string;
|
|
16
|
+
posterSrc?: string;
|
|
17
|
+
videoAriaLabel?: string;
|
|
16
18
|
onVideoReady?: () => void;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
export function
|
|
20
|
-
title,
|
|
21
|
-
subtitle,
|
|
22
|
-
ctaText,
|
|
23
|
-
ctaLink,
|
|
24
|
-
videoSrc,
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
export function HomeHero({
|
|
22
|
+
title = HERO.HOME_HERO.UI.TITLE,
|
|
23
|
+
subtitle = HERO.HOME_HERO.UI.SUBTITLE,
|
|
24
|
+
ctaText = HERO.HOME_HERO.UI.CTA_TEXT,
|
|
25
|
+
ctaLink = HERO.HOME_HERO.UI.CTA_LINK,
|
|
26
|
+
videoSrc = HERO.HOME_HERO.UI.VIDEO_SRC,
|
|
27
|
+
posterSrc = HERO.HOME_HERO.UI.POSTER_SRC,
|
|
28
|
+
videoAriaLabel = HERO.HOME_HERO.UI.VIDEO_ARIA_LABEL,
|
|
27
29
|
onVideoReady,
|
|
28
30
|
}: HeroSectionProps) {
|
|
29
31
|
const heroBackgroundRef = useRef<HTMLDivElement>(null);
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Image from "next/image";
|
|
4
|
+
import Link from "next/link";
|
|
5
|
+
import { HeroButton, ReadMoreButton } from "@/components/other/button";
|
|
6
|
+
import { useRef, useEffect, useState } from "react";
|
|
7
|
+
import { HERO } from "./constants/hero";
|
|
8
|
+
|
|
9
|
+
type ProductHeroProps = {
|
|
10
|
+
title?: string;
|
|
11
|
+
subtitle?: string;
|
|
12
|
+
imageSrc?: string;
|
|
13
|
+
imageAlt?: string;
|
|
14
|
+
primaryButtonText?: string;
|
|
15
|
+
primaryButtonLink?: string;
|
|
16
|
+
secondaryButtonText?: string;
|
|
17
|
+
secondaryButtonLink?: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const ProductHero = ({
|
|
21
|
+
title = HERO.PRODUCT_HERO.UI.MAIN_HEADING,
|
|
22
|
+
subtitle = HERO.PRODUCT_HERO.UI.SUBTITLE,
|
|
23
|
+
imageSrc = HERO.PRODUCT_HERO.UI.IMAGE_SRC,
|
|
24
|
+
imageAlt = HERO.PRODUCT_HERO.UI.IMAGE_ALT,
|
|
25
|
+
primaryButtonText = HERO.PRODUCT_HERO.BUTTONS.PRIMARY_TEXT,
|
|
26
|
+
primaryButtonLink = HERO.PRODUCT_HERO.BUTTONS.PRIMARY_LINK,
|
|
27
|
+
secondaryButtonText = HERO.PRODUCT_HERO.BUTTONS.SECONDARY_TEXT,
|
|
28
|
+
secondaryButtonLink = HERO.PRODUCT_HERO.BUTTONS.SECONDARY_LINK,
|
|
29
|
+
}: ProductHeroProps) => {
|
|
30
|
+
const heroBackgroundRef = useRef<HTMLDivElement>(null);
|
|
31
|
+
const [imageFailed, setImageFailed] = useState(false);
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const handleScroll = () => {
|
|
35
|
+
if (!heroBackgroundRef.current) {
|
|
36
|
+
if (process.env.NODE_ENV === "development") {
|
|
37
|
+
console.warn("Product hero background ref is not assigned");
|
|
38
|
+
}
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const scrollPosition = window.scrollY;
|
|
42
|
+
const parallaxOffset = scrollPosition * 0.5;
|
|
43
|
+
heroBackgroundRef.current.style.transform = `translateY(${parallaxOffset}px)`;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
window.addEventListener("scroll", handleScroll, { passive: true });
|
|
47
|
+
|
|
48
|
+
return () => {
|
|
49
|
+
window.removeEventListener("scroll", handleScroll);
|
|
50
|
+
};
|
|
51
|
+
}, []);
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<section className="relative min-h-screen flex items-center justify-center w-full">
|
|
55
|
+
<div
|
|
56
|
+
className="absolute inset-0 z-10 overflow-hidden bg-gradient-to-br from-[#9b7c266c] to-[#ffffff00]"
|
|
57
|
+
style={{ backgroundColor: !imageSrc || imageFailed ? "var(--amber-fallback)" : "transparent" }}
|
|
58
|
+
>
|
|
59
|
+
<div ref={heroBackgroundRef} className="absolute inset-0 will-change-transform">
|
|
60
|
+
{imageSrc && !imageFailed && imageAlt && (
|
|
61
|
+
<Image
|
|
62
|
+
src={imageSrc}
|
|
63
|
+
alt={imageAlt}
|
|
64
|
+
fill
|
|
65
|
+
style={{ objectFit: "cover" }}
|
|
66
|
+
className="brightness-75 blur-sm"
|
|
67
|
+
sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
|
|
68
|
+
priority
|
|
69
|
+
onError={() => {
|
|
70
|
+
setImageFailed(true);
|
|
71
|
+
}}
|
|
72
|
+
/>
|
|
73
|
+
)}
|
|
74
|
+
</div>
|
|
75
|
+
<div className="absolute inset-0 bg-gradient-to-b from-[var(--green-primary)]/85 to-[var(--green-primary)]/65" />
|
|
76
|
+
</div>
|
|
77
|
+
<div className="relative z-20 px-4 sm:px-6 lg:px-8 py-16 sm:py-24 lg:py-32 text-center text-white animate-fade-in lg:-translate-y-32">
|
|
78
|
+
<h1
|
|
79
|
+
className="text-6xl sm:text-7xl lg:text-8xl font-extrabold mb-6 sm:mb-8 tracking-tight drop-shadow-md [text-shadow:1px_1px_0_#000,-1px_-1px_0_#000,1px_-1px_0_#000,-1px_1px_0_#000]"
|
|
80
|
+
>
|
|
81
|
+
{title}
|
|
82
|
+
</h1>
|
|
83
|
+
<p
|
|
84
|
+
className="text-lg sm:text-xl lg:text-2xl mb-8 sm:mb-10 text-white/90 drop-shadow-md max-w-3xl mx-auto [text-shadow:1px_1px_0_#000,-1px_-1px_0_#000,1px_-1px_0_#000,-1px_1px_0_#000]"
|
|
85
|
+
>
|
|
86
|
+
{subtitle}
|
|
87
|
+
</p>
|
|
88
|
+
<div className="flex justify-center gap-4 sm:gap-6 lg:gap-8 flex-wrap">
|
|
89
|
+
<HeroButton
|
|
90
|
+
asChild
|
|
91
|
+
className="text-base sm:text-lg lg:text-lg py-7 sm:py-9 lg:py-9 px-10 sm:px-12 lg:px-12 rounded-xl shadow-lg hover:shadow-xl hover:scale-105 transition-all duration-300"
|
|
92
|
+
>
|
|
93
|
+
<Link href={primaryButtonLink ?? "/products"} aria-label={primaryButtonText}>
|
|
94
|
+
{primaryButtonText}
|
|
95
|
+
</Link>
|
|
96
|
+
</HeroButton>
|
|
97
|
+
<ReadMoreButton
|
|
98
|
+
asChild
|
|
99
|
+
className="text-base sm:text-lg lg:text-lg py-7 sm:py-9 lg:py-9 px-10 sm:px-12 lg:px-12 border-2 border-white text-white hover:bg-white/20 rounded-xl shadow-lg hover:shadow-xl hover:scale-105 transition-all duration-300"
|
|
100
|
+
>
|
|
101
|
+
<Link href={secondaryButtonLink ?? "/products"} aria-label={secondaryButtonText}>
|
|
102
|
+
{secondaryButtonText}
|
|
103
|
+
</Link>
|
|
104
|
+
</ReadMoreButton>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</section>
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export default ProductHero;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Constants for ProductHero and HomeHero components
|
|
2
|
+
|
|
3
|
+
// Interface for ProductHero constants
|
|
4
|
+
interface ProductHeroConstants {
|
|
5
|
+
UI: {
|
|
6
|
+
MAIN_HEADING: string;
|
|
7
|
+
SUBTITLE: string;
|
|
8
|
+
IMAGE_SRC: string;
|
|
9
|
+
IMAGE_ALT: string;
|
|
10
|
+
};
|
|
11
|
+
BUTTONS: {
|
|
12
|
+
PRIMARY_TEXT: string;
|
|
13
|
+
PRIMARY_LINK: string;
|
|
14
|
+
SECONDARY_TEXT: string;
|
|
15
|
+
SECONDARY_LINK: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Interface for HomeHero constants
|
|
20
|
+
interface HomeHeroConstants {
|
|
21
|
+
UI: {
|
|
22
|
+
TITLE: string;
|
|
23
|
+
SUBTITLE: string;
|
|
24
|
+
CTA_TEXT: string;
|
|
25
|
+
CTA_LINK: string;
|
|
26
|
+
VIDEO_SRC: string;
|
|
27
|
+
VIDEO_ARIA_LABEL: string;
|
|
28
|
+
POSTER_SRC: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Main HERO constants object
|
|
33
|
+
export const HERO: {
|
|
34
|
+
PRODUCT_HERO: ProductHeroConstants;
|
|
35
|
+
HOME_HERO: HomeHeroConstants;
|
|
36
|
+
} = {
|
|
37
|
+
PRODUCT_HERO: {
|
|
38
|
+
UI: {
|
|
39
|
+
MAIN_HEADING: "Discover Our Products",
|
|
40
|
+
SUBTITLE: "Explore innovative solutions designed to meet your needs.",
|
|
41
|
+
IMAGE_SRC: "/images/product-hero-bg.jpg",
|
|
42
|
+
IMAGE_ALT: "Product hero background image",
|
|
43
|
+
},
|
|
44
|
+
BUTTONS: {
|
|
45
|
+
PRIMARY_TEXT: "Shop Now",
|
|
46
|
+
PRIMARY_LINK: "/products",
|
|
47
|
+
SECONDARY_TEXT: "Learn More",
|
|
48
|
+
SECONDARY_LINK: "/about",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
HOME_HERO: {
|
|
52
|
+
UI: {
|
|
53
|
+
TITLE: "Welcome to Our World",
|
|
54
|
+
SUBTITLE: "Experience the journey with stunning visuals and immersive content.",
|
|
55
|
+
CTA_TEXT: "Get Started",
|
|
56
|
+
CTA_LINK: "/explore",
|
|
57
|
+
VIDEO_SRC: "/videos/home-hero-video.mp4",
|
|
58
|
+
VIDEO_ARIA_LABEL: "Home page hero background video",
|
|
59
|
+
POSTER_SRC: "/images/home-hero-poster.jpg",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
@@ -21,37 +21,37 @@ const ProductSlider = ({
|
|
|
21
21
|
id: '1',
|
|
22
22
|
name: PROGRAM_SLIDER.UI.PRODUCT_NAMES[0],
|
|
23
23
|
description: PROGRAM_SLIDER.UI.PRODUCT_DESCRIPTIONS[0],
|
|
24
|
-
image: '
|
|
24
|
+
image: '',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
id: '2',
|
|
28
28
|
name: PROGRAM_SLIDER.UI.PRODUCT_NAMES[1],
|
|
29
29
|
description: PROGRAM_SLIDER.UI.PRODUCT_DESCRIPTIONS[1],
|
|
30
|
-
image: '
|
|
30
|
+
image: '',
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
id: '3',
|
|
34
34
|
name: PROGRAM_SLIDER.UI.PRODUCT_NAMES[2],
|
|
35
35
|
description: PROGRAM_SLIDER.UI.PRODUCT_DESCRIPTIONS[2],
|
|
36
|
-
image: '
|
|
36
|
+
image: '',
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
id: '4',
|
|
40
40
|
name: PROGRAM_SLIDER.UI.PRODUCT_NAMES[3],
|
|
41
41
|
description: PROGRAM_SLIDER.UI.PRODUCT_DESCRIPTIONS[3],
|
|
42
|
-
image: '
|
|
42
|
+
image: '',
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
id: '5',
|
|
46
46
|
name: PROGRAM_SLIDER.UI.PRODUCT_NAMES[4],
|
|
47
47
|
description: PROGRAM_SLIDER.UI.PRODUCT_DESCRIPTIONS[4],
|
|
48
|
-
image: '
|
|
48
|
+
image: '',
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
id: '6',
|
|
52
52
|
name: PROGRAM_SLIDER.UI.PRODUCT_NAMES[5],
|
|
53
53
|
description: PROGRAM_SLIDER.UI.PRODUCT_DESCRIPTIONS[5],
|
|
54
|
-
image: '
|
|
54
|
+
image: '',
|
|
55
55
|
},
|
|
56
56
|
],
|
|
57
57
|
}: ProductSliderProps) => {
|
|
@@ -100,36 +100,36 @@ const ProgramsCarousel = ({
|
|
|
100
100
|
programs = [
|
|
101
101
|
{
|
|
102
102
|
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[0],
|
|
103
|
-
video: '
|
|
104
|
-
poster: '
|
|
103
|
+
video: '',
|
|
104
|
+
poster: '',
|
|
105
105
|
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[0],
|
|
106
106
|
link: '/',
|
|
107
107
|
},
|
|
108
108
|
{
|
|
109
109
|
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[1],
|
|
110
|
-
video: '
|
|
111
|
-
poster: '
|
|
110
|
+
video: '',
|
|
111
|
+
poster: '',
|
|
112
112
|
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[1],
|
|
113
113
|
link: '/',
|
|
114
114
|
},
|
|
115
115
|
{
|
|
116
116
|
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[2],
|
|
117
|
-
video: '
|
|
118
|
-
poster: '
|
|
117
|
+
video: '',
|
|
118
|
+
poster: '',
|
|
119
119
|
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[2],
|
|
120
120
|
link: '/',
|
|
121
121
|
},
|
|
122
122
|
{
|
|
123
123
|
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[3],
|
|
124
|
-
video: '
|
|
125
|
-
poster: '
|
|
124
|
+
video: '',
|
|
125
|
+
poster: '',
|
|
126
126
|
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[3],
|
|
127
127
|
link: '/',
|
|
128
128
|
},
|
|
129
129
|
{
|
|
130
130
|
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[4],
|
|
131
|
-
video: '
|
|
132
|
-
poster: '
|
|
131
|
+
video: '',
|
|
132
|
+
poster: '',
|
|
133
133
|
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[4],
|
|
134
134
|
link: '/',
|
|
135
135
|
},
|