@devvistatech/devvista-kit 0.0.9 → 0.0.10
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/CHANGELOG.md +12 -12
- package/LICENSE +6 -6
- package/README.md +15 -15
- package/app/about/page.tsx +298 -298
- package/app/adRequest/page.tsx +549 -549
- package/app/analytics/page.tsx +346 -346
- package/app/api/about/route.ts +306 -306
- package/app/api/adRequest/route.ts +567 -567
- package/app/api/analytics/[reportType]/route.ts +337 -337
- package/app/api/bio/route.ts +313 -313
- package/app/api/blog/route.ts +306 -306
- package/app/api/chat/route.ts +14 -14
- package/app/api/contact/route.ts +409 -409
- package/app/api/contacts/route.ts +224 -224
- package/app/api/files/route.ts +429 -429
- package/app/api/gallery-data/route.ts +735 -735
- package/app/api/schedule/route.ts +455 -455
- package/app/api/sync-user/route.ts +131 -131
- package/app/api/trial-request/route.ts +297 -297
- package/app/blog/[id]/page.tsx +288 -288
- package/app/blog/page.tsx +216 -216
- package/app/contact/page.tsx +284 -284
- package/app/faq/page.tsx +191 -191
- package/app/gallery/page.tsx +315 -315
- package/app/globals.css +58 -58
- package/app/layout.tsx +110 -110
- package/app/not-found.tsx +20 -20
- package/app/page.tsx +338 -338
- package/app/schedule/page.tsx +660 -660
- package/bin/init.js +219 -219
- package/components/addOns/functional/BioEditor.tsx +446 -446
- package/components/addOns/functional/CalendlyWidget.tsx +107 -107
- package/components/addOns/functional/ClassList.tsx +145 -145
- package/components/addOns/functional/ClassPopup.tsx +398 -398
- package/components/addOns/functional/ContactForm.tsx +284 -284
- package/components/addOns/functional/FileUploader.tsx +294 -294
- package/components/addOns/functional/ImageDescCarousel.tsx +730 -730
- package/components/addOns/functional/NewUserAnalytics.tsx +100 -100
- package/components/addOns/functional/ScheduleCarousel.tsx +171 -171
- package/components/addOns/functional/aboutSections/AboutSection.tsx +544 -544
- package/components/addOns/functional/aboutSections/constants/aboutSection.ts +65 -65
- package/components/addOns/functional/blogSections/BlogDashboard.tsx +184 -184
- package/components/addOns/functional/blogSections/BlogFormPopUp.tsx +554 -554
- package/components/addOns/functional/blogSections/BlogList.tsx +148 -148
- package/components/addOns/functional/blogSections/BlogSidebar.tsx +58 -58
- package/components/addOns/functional/blogSections/constants/blogDashboard.ts +28 -28
- package/components/addOns/functional/blogSections/constants/blogFormPopUp.ts +97 -97
- package/components/addOns/functional/blogSections/constants/blogList.ts +22 -22
- package/components/addOns/functional/blogSections/constants/blogSidebar.ts +15 -15
- package/components/addOns/functional/contactsDashboard/ContactsDashboard.tsx +366 -366
- package/components/addOns/functional/contactsDashboard/constants/contactsDashboard.ts +70 -70
- package/components/addOns/functional/galleries/GalleryComplex.tsx +836 -836
- package/components/addOns/functional/galleries/GallerySimple.tsx +509 -509
- package/components/addOns/functional/galleries/constants/galleryComplex.ts +106 -106
- package/components/addOns/functional/galleries/constants/gallerySimple.ts +76 -76
- package/components/addOns/functional/schedules/ScheduleGridOne.tsx +262 -262
- package/components/addOns/functional/schedules/ScheduleGridTwo.tsx +294 -294
- package/components/addOns/functional/schedules/ScheduleGridTwoBasic.tsx +288 -288
- package/components/addOns/functional/schedules/SchedulerForm.tsx +428 -428
- package/components/addOns/functional/schedules/constants/ScheduleGridTwo.ts +40 -40
- package/components/addOns/functional/schedules/constants/ScheduleGridTwoBasic.ts +40 -40
- package/components/addOns/functional/schedules/constants/SchedulerForm.ts +65 -65
- package/components/addOns/functional/schedules/constants/scheduleGridOne.ts +54 -54
- package/components/addOns/non-functional/AnnouncementBanner.tsx +46 -46
- package/components/addOns/non-functional/FeaturesSection.tsx +62 -62
- package/components/addOns/non-functional/Heros/HeroSection.tsx +142 -142
- package/components/addOns/non-functional/IconBubble.tsx +49 -49
- package/components/addOns/non-functional/SampleCarousel.tsx +204 -204
- package/components/addOns/non-functional/Testimonials.tsx +334 -334
- package/components/addOns/non-functional/ThreeSetGallery.tsx +63 -63
- package/components/addOns/non-functional/aboutSections/AboutSection.tsx +62 -62
- package/components/addOns/non-functional/aboutSections/constants/aboutSection.ts +24 -24
- package/components/addOns/non-functional/imageCarousels/ProductSlider.tsx +117 -117
- package/components/addOns/non-functional/imageCarousels/ProgramCarousel.tsx +232 -232
- package/components/addOns/non-functional/imageCarousels/constants/programCarousel.ts +39 -39
- package/components/addOns/non-functional/imageCarousels/constants/programSlider.ts +36 -36
- package/components/addOns/non-functional/spinner.tsx +21 -21
- package/components/footers/footer.tsx +453 -453
- package/components/navBars/navbar.tsx +310 -310
- package/components/other/accordion.tsx +58 -58
- package/components/other/admin-menu.tsx +68 -68
- package/components/other/alert-dialog.tsx +141 -141
- package/components/other/alert.tsx +59 -59
- package/components/other/aspect-ratio.tsx +7 -7
- package/components/other/avatar.tsx +50 -50
- package/components/other/badge.tsx +36 -36
- package/components/other/breadcrumb.tsx +115 -115
- package/components/other/button.tsx +738 -738
- package/components/other/calendar.tsx +66 -66
- package/components/other/card.tsx +86 -86
- package/components/other/carousel.tsx +274 -274
- package/components/other/chart.tsx +363 -363
- package/components/other/checkbox.tsx +30 -30
- package/components/other/collapsible.tsx +11 -11
- package/components/other/command.tsx +155 -155
- package/components/other/context-menu.tsx +200 -200
- package/components/other/dialog.tsx +122 -122
- package/components/other/drawer.tsx +118 -118
- package/components/other/dropdown-menu.tsx +200 -200
- package/components/other/form.tsx +179 -179
- package/components/other/hover-card.tsx +29 -29
- package/components/other/input-otp.tsx +71 -71
- package/components/other/input.tsx +25 -25
- package/components/other/label.tsx +26 -26
- package/components/other/menubar.tsx +236 -236
- package/components/other/mobile-icon.tsx +21 -21
- package/components/other/navigation-menu.tsx +128 -128
- package/components/other/pagination.tsx +117 -117
- package/components/other/popover.tsx +31 -31
- package/components/other/progress.tsx +28 -28
- package/components/other/radio-group.tsx +44 -44
- package/components/other/resizable.tsx +45 -45
- package/components/other/scroll-area.tsx +48 -48
- package/components/other/select.tsx +160 -160
- package/components/other/separator.tsx +31 -31
- package/components/other/sheet.tsx +140 -140
- package/components/other/skeleton.tsx +15 -15
- package/components/other/slider.tsx +28 -28
- package/components/other/social-icons.tsx +39 -39
- package/components/other/sonner.tsx +31 -31
- package/components/other/switch.tsx +29 -29
- package/components/other/table.tsx +117 -117
- package/components/other/tabs.tsx +55 -55
- package/components/other/textarea.tsx +24 -24
- package/components/other/toast.tsx +122 -122
- package/components/other/toaster.tsx +35 -35
- package/components/other/toggle-group.tsx +61 -61
- package/components/other/toggle.tsx +45 -45
- package/components/other/tooltip.tsx +30 -30
- package/components/theme-provider.tsx +8 -8
- package/components/types.ts +49 -49
- package/dist/.next/types/app/api/about/route.js +52 -0
- package/dist/.next/types/app/api/blog/route.js +52 -0
- package/dist/.next/types/app/api/files/route.js +52 -0
- package/dist/.next/types/app/api/schedule/route.js +52 -0
- package/dist/.next/types/app/api/sync-user/route.js +52 -0
- package/dist/.next/types/app/layout.js +22 -0
- package/dist/.next/types/app/page.js +22 -0
- package/dist/app/about/page.jsx +258 -0
- package/dist/app/adRequest/page.jsx +531 -0
- package/dist/app/analytics/page.jsx +298 -0
- package/dist/app/api/about/route.js +285 -0
- package/dist/app/api/adRequest/route.js +440 -0
- package/dist/app/api/analytics/[reportType]/route.js +357 -0
- package/dist/app/api/bio/route.js +293 -0
- package/dist/app/api/blog/route.js +366 -0
- package/dist/app/api/chat/route.js +58 -0
- package/dist/app/api/contact/route.js +163 -0
- package/dist/app/api/contacts/route.js +234 -0
- package/dist/app/api/files/route.js +444 -0
- package/dist/app/api/gallery-data/route.js +719 -0
- package/dist/app/api/schedule/route.js +461 -0
- package/dist/app/api/sync-user/route.js +186 -0
- package/dist/app/api/trial-request/route.js +165 -0
- package/dist/app/blog/[id]/page.jsx +312 -0
- package/dist/app/blog/page.jsx +210 -0
- package/dist/app/constants/about.js +32 -0
- package/dist/app/constants/adRequest.js +113 -0
- package/dist/app/constants/contact.js +40 -0
- package/dist/app/constants/faq.js +36 -0
- package/dist/app/constants/gallery.js +42 -0
- package/dist/app/constants/page.js +69 -0
- package/dist/app/constants/schedule.js +71 -0
- package/dist/app/contact/page.jsx +119 -0
- package/dist/app/faq/page.jsx +97 -0
- package/dist/app/gallery/page.jsx +281 -0
- package/dist/app/layout.jsx +45 -0
- package/dist/app/not-found.jsx +14 -0
- package/dist/app/page.jsx +324 -0
- package/dist/app/schedule/page.jsx +500 -0
- package/dist/components/addOns/functional/BioEditor.jsx +187 -0
- package/dist/components/addOns/functional/CalendlyWidget.jsx +61 -0
- package/dist/components/addOns/functional/ClassList.jsx +158 -0
- package/dist/components/addOns/functional/ClassPopup.jsx +300 -0
- package/dist/components/addOns/functional/ContactForm.jsx +219 -0
- package/dist/components/addOns/functional/FileUploader.jsx +222 -0
- package/dist/components/addOns/functional/ImageDescCarousel.jsx +491 -0
- package/dist/components/addOns/functional/NewUserAnalytics.jsx +71 -0
- package/dist/components/addOns/functional/ScheduleCarousel.jsx +68 -0
- package/dist/components/addOns/functional/aboutSections/AboutSection.jsx +372 -0
- package/dist/components/addOns/functional/aboutSections/constants/aboutSection.js +65 -0
- package/dist/components/addOns/functional/blogSections/BlogDashboard.jsx +111 -0
- package/dist/components/addOns/functional/blogSections/BlogFormPopUp.jsx +465 -0
- package/dist/components/addOns/functional/blogSections/BlogList.jsx +170 -0
- package/dist/components/addOns/functional/blogSections/BlogSidebar.jsx +35 -0
- package/dist/components/addOns/functional/blogSections/constants/blogDashboard.js +28 -0
- package/dist/components/addOns/functional/blogSections/constants/blogFormPopUp.js +97 -0
- package/dist/components/addOns/functional/blogSections/constants/blogList.js +22 -0
- package/dist/components/addOns/functional/blogSections/constants/blogSidebar.js +15 -0
- package/dist/components/addOns/functional/contactsDashboard/ContactsDashboard.jsx +355 -0
- package/dist/components/addOns/functional/contactsDashboard/constants/contactsDashboard.js +70 -0
- package/dist/components/addOns/functional/galleries/GalleryComplex.jsx +605 -0
- package/dist/components/addOns/functional/galleries/GallerySimple.jsx +363 -0
- package/dist/components/addOns/functional/galleries/constants/galleryComplex.js +106 -0
- package/dist/components/addOns/functional/galleries/constants/gallerySimple.js +76 -0
- package/dist/components/addOns/functional/schedules/ScheduleGridOne.jsx +167 -0
- package/dist/components/addOns/functional/schedules/ScheduleGridTwo.jsx +100 -0
- package/dist/components/addOns/functional/schedules/ScheduleGridTwoBasic.jsx +97 -0
- package/dist/components/addOns/functional/schedules/SchedulerForm.jsx +188 -0
- package/dist/components/addOns/functional/schedules/constants/ScheduleGridTwo.js +40 -0
- package/dist/components/addOns/functional/schedules/constants/ScheduleGridTwoBasic.js +40 -0
- package/dist/components/addOns/functional/schedules/constants/SchedulerForm.js +65 -0
- package/dist/components/addOns/functional/schedules/constants/scheduleGridOne.js +54 -0
- package/dist/components/addOns/non-functional/AnnouncementBanner.jsx +24 -0
- package/dist/components/addOns/non-functional/FeaturesSection.jsx +38 -0
- package/dist/components/addOns/non-functional/HeroSection.jsx +71 -0
- package/dist/components/addOns/non-functional/Heros/HeroSection.jsx +71 -0
- package/dist/components/addOns/non-functional/IconBubble.jsx +36 -0
- package/dist/components/addOns/non-functional/SampleCarousel.jsx +114 -0
- package/dist/components/addOns/non-functional/Testimonials.jsx +177 -0
- package/dist/components/addOns/non-functional/ThreeSetGallery.jsx +40 -0
- package/dist/components/addOns/non-functional/aboutSections/AboutSection.jsx +35 -0
- package/dist/components/addOns/non-functional/aboutSections/constants/aboutSection.js +24 -0
- package/dist/components/addOns/non-functional/imageCarousels/ProductSlider.jsx +80 -0
- package/dist/components/addOns/non-functional/imageCarousels/ProgramCarousel.jsx +155 -0
- package/dist/components/addOns/non-functional/imageCarousels/constants/programCarousel.js +39 -0
- package/dist/components/addOns/non-functional/imageCarousels/constants/programSlider.js +36 -0
- package/dist/components/addOns/non-functional/spinner.jsx +13 -0
- package/dist/components/footers/footer.jsx +217 -0
- package/dist/components/navBars/navbar.jsx +159 -0
- package/dist/components/other/accordion.jsx +40 -0
- package/dist/components/other/admin-menu.jsx +34 -0
- package/dist/components/other/alert-dialog.jsx +64 -0
- package/dist/components/other/alert.jsx +41 -0
- package/dist/components/other/aspect-ratio.jsx +4 -0
- package/dist/components/other/avatar.jsx +31 -0
- package/dist/components/other/badge.jsx +32 -0
- package/dist/components/other/breadcrumb.jsx +57 -0
- package/dist/components/other/button.jsx +322 -0
- package/dist/components/other/calendar.jsx +43 -0
- package/dist/components/other/card.jsx +44 -0
- package/dist/components/other/carousel.jsx +140 -0
- package/dist/components/other/chart.jsx +182 -0
- package/dist/components/other/checkbox.jsx +26 -0
- package/dist/components/other/collapsible.jsx +6 -0
- package/dist/components/other/command.jsx +68 -0
- package/dist/components/other/context-menu.jsx +88 -0
- package/dist/components/other/dialog.jsx +60 -0
- package/dist/components/other/drawer.jsx +60 -0
- package/dist/components/other/dropdown-menu.jsx +90 -0
- package/dist/components/other/form.jsx +89 -0
- package/dist/components/other/hover-card.jsx +23 -0
- package/dist/components/other/input-otp.jsx +46 -0
- package/dist/components/other/input.jsx +19 -0
- package/dist/components/other/label.jsx +23 -0
- package/dist/components/other/login-popup.jsx +1 -0
- package/dist/components/other/menubar.jsx +96 -0
- package/dist/components/other/mobile-icon.jsx +11 -0
- package/dist/components/other/navigation-menu.jsx +62 -0
- package/dist/components/other/pagination.jsx +63 -0
- package/dist/components/other/popover.jsx +25 -0
- package/dist/components/other/progress.jsx +23 -0
- package/dist/components/other/radio-group.jsx +31 -0
- package/dist/components/other/resizable.jsx +29 -0
- package/dist/components/other/scroll-area.jsx +36 -0
- package/dist/components/other/select.jsx +83 -0
- package/dist/components/other/separator.jsx +21 -0
- package/dist/components/other/sheet.jsx +74 -0
- package/dist/components/other/signup-popup.jsx +1 -0
- package/dist/components/other/skeleton.jsx +17 -0
- package/dist/components/other/slider.jsx +26 -0
- package/dist/components/other/social-icons.jsx +15 -0
- package/dist/components/other/sonner.jsx +27 -0
- package/dist/components/other/switch.jsx +23 -0
- package/dist/components/other/table.jsx +56 -0
- package/dist/components/other/tabs.jsx +32 -0
- package/dist/components/other/textarea.jsx +19 -0
- package/dist/components/other/toast.jsx +58 -0
- package/dist/components/other/toaster.jsx +31 -0
- package/dist/components/other/toggle-group.jsx +41 -0
- package/dist/components/other/toggle.jsx +39 -0
- package/dist/components/other/tooltip.jsx +24 -0
- package/dist/components/theme-provider.jsx +18 -0
- package/dist/components/types.js +1 -0
- package/dist/hooks/use-toast.js +135 -0
- package/dist/lib/auth-context.jsx +144 -0
- package/dist/lib/constants/about.js +32 -0
- package/dist/lib/constants/adRequest.js +113 -0
- package/dist/lib/constants/contact.js +40 -0
- package/dist/lib/constants/faq.js +36 -0
- package/dist/lib/constants/gallery.js +42 -0
- package/dist/lib/constants/page.js +69 -0
- package/dist/lib/constants/schedule.js +71 -0
- package/dist/lib/google-analytics.jsx +148 -0
- package/dist/lib/utils.js +9 -0
- package/dist/lib/verify-user.js +142 -0
- package/dist/middleware.js +37 -0
- package/dist/tailwind.config.js +86 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/hooks/use-toast.ts +188 -188
- package/lib/auth-context.tsx +130 -130
- package/lib/constants/about.ts +34 -34
- package/lib/constants/adRequest.ts +113 -113
- package/lib/constants/contact.ts +40 -40
- package/lib/constants/faq.ts +34 -21
- package/lib/constants/gallery.ts +42 -42
- package/lib/constants/page.ts +69 -69
- package/lib/constants/schedule.ts +71 -71
- package/lib/google-analytics.tsx +97 -97
- package/lib/verify-user.ts +117 -117
- package/middleware.ts +42 -42
- package/netlify.toml +5 -5
- package/next.config.js +10 -10
- package/package.json +115 -115
- package/tailwind.config.ts +89 -89
- package/tsconfig.json +23 -23
|
@@ -1,233 +1,233 @@
|
|
|
1
|
-
// src/components/ProgramsCarousel.tsx
|
|
2
|
-
"use client";
|
|
3
|
-
|
|
4
|
-
import Link from 'next/link';
|
|
5
|
-
import { PrevButton, NextButton, ActionButton } from "@/components/other/button";
|
|
6
|
-
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/other/card';
|
|
7
|
-
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|
8
|
-
import { motion } from 'framer-motion';
|
|
9
|
-
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
10
|
-
import useEmblaCarousel from 'embla-carousel-react';
|
|
11
|
-
import { PROGRAM_CAROUSEL } from './constants/programCarousel';
|
|
12
|
-
|
|
13
|
-
const staggerChildren = {
|
|
14
|
-
hidden: { opacity: 0 },
|
|
15
|
-
visible: {
|
|
16
|
-
opacity: 1,
|
|
17
|
-
transition: {
|
|
18
|
-
staggerChildren: 0.2,
|
|
19
|
-
delayChildren: 0.3,
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const childVariant = {
|
|
25
|
-
hidden: { opacity: 0, y: 20 },
|
|
26
|
-
visible: {
|
|
27
|
-
opacity: 1,
|
|
28
|
-
y: 0,
|
|
29
|
-
transition: { duration: 0.5, ease: 'easeOut' },
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
interface Program {
|
|
34
|
-
title: string;
|
|
35
|
-
video: string;
|
|
36
|
-
poster: string;
|
|
37
|
-
description: string;
|
|
38
|
-
link: string;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
interface ProgramsCarouselProps {
|
|
42
|
-
programs?: Program[];
|
|
43
|
-
sectionTitle?: string;
|
|
44
|
-
buttonText?: string;
|
|
45
|
-
buttonLink?: string;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Separate component for each slide
|
|
49
|
-
const ProgramSlide = ({ program }: { program: Program }) => {
|
|
50
|
-
const videoRef = useRef<HTMLVideoElement>(null);
|
|
51
|
-
|
|
52
|
-
const handleMouseEnter = () => {
|
|
53
|
-
if (videoRef.current) {
|
|
54
|
-
videoRef.current.play().catch((error) => console.error(PROGRAM_CAROUSEL.ERRORS.VIDEO_PLAY_ERROR, error));
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const handleMouseLeave = () => {
|
|
59
|
-
if (videoRef.current) {
|
|
60
|
-
videoRef.current.pause();
|
|
61
|
-
videoRef.current.currentTime = 0;
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
return (
|
|
66
|
-
<motion.div
|
|
67
|
-
className="embla__slide flex-[0_0_100%] max-[640px]:h-[400px] sm:flex-[0_0_33.333333%] sm:h-[900px] w-full flex items-center justify-center"
|
|
68
|
-
variants={childVariant}
|
|
69
|
-
onMouseEnter={handleMouseEnter}
|
|
70
|
-
onMouseLeave={handleMouseLeave}
|
|
71
|
-
>
|
|
72
|
-
<Card className="bg-white/90 w-full max-[640px]:h-[400px] sm:h-[900px] flex flex-col border-none pb-6 sm:pb-12 shadow-lg hover:shadow-xl transition-shadow duration-300">
|
|
73
|
-
<div className="relative w-full max-[640px]:h-[280px] sm:h-[800px]">
|
|
74
|
-
<video
|
|
75
|
-
ref={videoRef}
|
|
76
|
-
src={program.video}
|
|
77
|
-
poster={program.poster}
|
|
78
|
-
className="w-full h-full object-cover"
|
|
79
|
-
muted
|
|
80
|
-
playsInline
|
|
81
|
-
loop
|
|
82
|
-
/>
|
|
83
|
-
</div>
|
|
84
|
-
<CardHeader className="flex-shrink-0 max-[640px]">
|
|
85
|
-
<CardTitle className="max-[640px]:text-xl sm:text-3xl font-bold text-center">
|
|
86
|
-
{program.title}
|
|
87
|
-
</CardTitle>
|
|
88
|
-
</CardHeader>
|
|
89
|
-
<CardContent className="flex-grow flex items-center justify-center max-[640px]">
|
|
90
|
-
<CardDescription className="max-[640px]:text-lg sm:text-lg text-gray-800 text-center line-clamp-3">
|
|
91
|
-
{program.description}
|
|
92
|
-
</CardDescription>
|
|
93
|
-
</CardContent>
|
|
94
|
-
</Card>
|
|
95
|
-
</motion.div>
|
|
96
|
-
);
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const ProgramsCarousel = ({
|
|
100
|
-
programs = [
|
|
101
|
-
{
|
|
102
|
-
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[0],
|
|
103
|
-
video: '/videos/placeholder1.mp4',
|
|
104
|
-
poster: '/images/placeholder1.jpg',
|
|
105
|
-
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[0],
|
|
106
|
-
link: '/',
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[1],
|
|
110
|
-
video: '/videos/placeholder2.mp4',
|
|
111
|
-
poster: '/images/placeholder2.jpg',
|
|
112
|
-
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[1],
|
|
113
|
-
link: '/',
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[2],
|
|
117
|
-
video: '/videos/placeholder3.mp4',
|
|
118
|
-
poster: '/images/placeholder3.jpg',
|
|
119
|
-
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[2],
|
|
120
|
-
link: '/',
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[3],
|
|
124
|
-
video: '/videos/placeholder4.mp4',
|
|
125
|
-
poster: '/images/placeholder4.jpg',
|
|
126
|
-
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[3],
|
|
127
|
-
link: '/',
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[4],
|
|
131
|
-
video: '/videos/placeholder5.mp4',
|
|
132
|
-
poster: '/images/placeholder5.jpg',
|
|
133
|
-
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[4],
|
|
134
|
-
link: '/',
|
|
135
|
-
},
|
|
136
|
-
],
|
|
137
|
-
sectionTitle = PROGRAM_CAROUSEL.UI.SECTION_TITLE,
|
|
138
|
-
buttonText = PROGRAM_CAROUSEL.UI.VIEW_ALL_BUTTON_TEXT,
|
|
139
|
-
buttonLink = '/',
|
|
140
|
-
}: ProgramsCarouselProps) => {
|
|
141
|
-
const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true, align: 'start', containScroll: 'trimSnaps', slidesToScroll: 1 });
|
|
142
|
-
const [canPrev, setCanPrev] = useState(false);
|
|
143
|
-
const [canNext, setCanNext] = useState(true);
|
|
144
|
-
|
|
145
|
-
const scrollPrev = useCallback(() => {
|
|
146
|
-
if (emblaApi) emblaApi.scrollPrev();
|
|
147
|
-
}, [emblaApi]);
|
|
148
|
-
|
|
149
|
-
const scrollNext = useCallback(() => {
|
|
150
|
-
if (emblaApi) emblaApi.scrollNext();
|
|
151
|
-
}, [emblaApi]);
|
|
152
|
-
|
|
153
|
-
const onSelect = useCallback(() => {
|
|
154
|
-
if (!emblaApi) return;
|
|
155
|
-
setCanPrev(emblaApi.canScrollPrev());
|
|
156
|
-
setCanNext(emblaApi.canScrollNext());
|
|
157
|
-
}, [emblaApi]);
|
|
158
|
-
|
|
159
|
-
useEffect(() => {
|
|
160
|
-
if (!emblaApi) return;
|
|
161
|
-
emblaApi.on('select', onSelect);
|
|
162
|
-
emblaApi.on('reInit', onSelect);
|
|
163
|
-
onSelect();
|
|
164
|
-
|
|
165
|
-
emblaApi.reInit();
|
|
166
|
-
emblaApi.scrollTo(0, false);
|
|
167
|
-
|
|
168
|
-
const handleResize = () => emblaApi.reInit();
|
|
169
|
-
window.addEventListener('resize', handleResize);
|
|
170
|
-
return () => window.removeEventListener('resize', handleResize);
|
|
171
|
-
}, [emblaApi, onSelect]);
|
|
172
|
-
|
|
173
|
-
return (
|
|
174
|
-
<motion.section
|
|
175
|
-
className="w-full bg-white/80 relative overflow-hidden p-0 m-0"
|
|
176
|
-
initial="hidden"
|
|
177
|
-
whileInView="visible"
|
|
178
|
-
>
|
|
179
|
-
<div className="w-full py-12 sm:py-24 m-0">
|
|
180
|
-
<motion.h2 className="text-4xl sm:text-6xl font-bold text-center mb-8">
|
|
181
|
-
{sectionTitle}
|
|
182
|
-
</motion.h2>
|
|
183
|
-
<div className="embla relative border-none outline-none w-full" ref={emblaRef}>
|
|
184
|
-
<motion.div
|
|
185
|
-
className="embla__container flex gap-0 w-full"
|
|
186
|
-
variants={staggerChildren}
|
|
187
|
-
initial="hidden"
|
|
188
|
-
whileInView="visible"
|
|
189
|
-
viewport={{ once: true }}
|
|
190
|
-
>
|
|
191
|
-
{programs.map((program, index) => (
|
|
192
|
-
<ProgramSlide key={index} program={program} />
|
|
193
|
-
))}
|
|
194
|
-
</motion.div>
|
|
195
|
-
<PrevButton
|
|
196
|
-
className="absolute left-0 top-1/2 transform -translate-y-1/2 p-2 rounded-r-full"
|
|
197
|
-
onClick={scrollPrev}
|
|
198
|
-
disabled={!canPrev}
|
|
199
|
-
aria-label={PROGRAM_CAROUSEL.BUTTONS.PREVIOUS_SLIDE_ARIA}
|
|
200
|
-
>
|
|
201
|
-
<ChevronLeft size={24} />
|
|
202
|
-
</PrevButton>
|
|
203
|
-
<NextButton
|
|
204
|
-
className="absolute right-0 top-1/2 transform -translate-y-1/2 p-2 rounded-l-full"
|
|
205
|
-
onClick={scrollNext}
|
|
206
|
-
disabled={!canNext}
|
|
207
|
-
aria-label={PROGRAM_CAROUSEL.BUTTONS.NEXT_SLIDE_ARIA}
|
|
208
|
-
>
|
|
209
|
-
<ChevronRight size={24} />
|
|
210
|
-
</NextButton>
|
|
211
|
-
</div>
|
|
212
|
-
<motion.div
|
|
213
|
-
className="mt-8 text-center"
|
|
214
|
-
initial={{ opacity: 0, y: 20 }}
|
|
215
|
-
whileInView={{ opacity: 1, y: 0 }}
|
|
216
|
-
viewport={{ once: true }}
|
|
217
|
-
transition={{ duration: 0.5, delay: 0.6, ease: 'easeOut' }}
|
|
218
|
-
>
|
|
219
|
-
<Link href={buttonLink}>
|
|
220
|
-
<ActionButton
|
|
221
|
-
className="hover:scale-110 hover:shadow-lg hover:shadow-gray-800"
|
|
222
|
-
aria-label={buttonText}
|
|
223
|
-
>
|
|
224
|
-
{buttonText}
|
|
225
|
-
</ActionButton>
|
|
226
|
-
</Link>
|
|
227
|
-
</motion.div>
|
|
228
|
-
</div>
|
|
229
|
-
</motion.section>
|
|
230
|
-
);
|
|
231
|
-
};
|
|
232
|
-
|
|
1
|
+
// src/components/ProgramsCarousel.tsx
|
|
2
|
+
"use client";
|
|
3
|
+
|
|
4
|
+
import Link from 'next/link';
|
|
5
|
+
import { PrevButton, NextButton, ActionButton } from "@/components/other/button";
|
|
6
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/other/card';
|
|
7
|
+
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|
8
|
+
import { motion } from 'framer-motion';
|
|
9
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
10
|
+
import useEmblaCarousel from 'embla-carousel-react';
|
|
11
|
+
import { PROGRAM_CAROUSEL } from './constants/programCarousel';
|
|
12
|
+
|
|
13
|
+
const staggerChildren = {
|
|
14
|
+
hidden: { opacity: 0 },
|
|
15
|
+
visible: {
|
|
16
|
+
opacity: 1,
|
|
17
|
+
transition: {
|
|
18
|
+
staggerChildren: 0.2,
|
|
19
|
+
delayChildren: 0.3,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const childVariant = {
|
|
25
|
+
hidden: { opacity: 0, y: 20 },
|
|
26
|
+
visible: {
|
|
27
|
+
opacity: 1,
|
|
28
|
+
y: 0,
|
|
29
|
+
transition: { duration: 0.5, ease: 'easeOut' },
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
interface Program {
|
|
34
|
+
title: string;
|
|
35
|
+
video: string;
|
|
36
|
+
poster: string;
|
|
37
|
+
description: string;
|
|
38
|
+
link: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface ProgramsCarouselProps {
|
|
42
|
+
programs?: Program[];
|
|
43
|
+
sectionTitle?: string;
|
|
44
|
+
buttonText?: string;
|
|
45
|
+
buttonLink?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Separate component for each slide
|
|
49
|
+
const ProgramSlide = ({ program }: { program: Program }) => {
|
|
50
|
+
const videoRef = useRef<HTMLVideoElement>(null);
|
|
51
|
+
|
|
52
|
+
const handleMouseEnter = () => {
|
|
53
|
+
if (videoRef.current) {
|
|
54
|
+
videoRef.current.play().catch((error) => console.error(PROGRAM_CAROUSEL.ERRORS.VIDEO_PLAY_ERROR, error));
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const handleMouseLeave = () => {
|
|
59
|
+
if (videoRef.current) {
|
|
60
|
+
videoRef.current.pause();
|
|
61
|
+
videoRef.current.currentTime = 0;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<motion.div
|
|
67
|
+
className="embla__slide flex-[0_0_100%] max-[640px]:h-[400px] sm:flex-[0_0_33.333333%] sm:h-[900px] w-full flex items-center justify-center"
|
|
68
|
+
variants={childVariant}
|
|
69
|
+
onMouseEnter={handleMouseEnter}
|
|
70
|
+
onMouseLeave={handleMouseLeave}
|
|
71
|
+
>
|
|
72
|
+
<Card className="bg-white/90 w-full max-[640px]:h-[400px] sm:h-[900px] flex flex-col border-none pb-6 sm:pb-12 shadow-lg hover:shadow-xl transition-shadow duration-300">
|
|
73
|
+
<div className="relative w-full max-[640px]:h-[280px] sm:h-[800px]">
|
|
74
|
+
<video
|
|
75
|
+
ref={videoRef}
|
|
76
|
+
src={program.video}
|
|
77
|
+
poster={program.poster}
|
|
78
|
+
className="w-full h-full object-cover"
|
|
79
|
+
muted
|
|
80
|
+
playsInline
|
|
81
|
+
loop
|
|
82
|
+
/>
|
|
83
|
+
</div>
|
|
84
|
+
<CardHeader className="flex-shrink-0 max-[640px]">
|
|
85
|
+
<CardTitle className="max-[640px]:text-xl sm:text-3xl font-bold text-center">
|
|
86
|
+
{program.title}
|
|
87
|
+
</CardTitle>
|
|
88
|
+
</CardHeader>
|
|
89
|
+
<CardContent className="flex-grow flex items-center justify-center max-[640px]">
|
|
90
|
+
<CardDescription className="max-[640px]:text-lg sm:text-lg text-gray-800 text-center line-clamp-3">
|
|
91
|
+
{program.description}
|
|
92
|
+
</CardDescription>
|
|
93
|
+
</CardContent>
|
|
94
|
+
</Card>
|
|
95
|
+
</motion.div>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const ProgramsCarousel = ({
|
|
100
|
+
programs = [
|
|
101
|
+
{
|
|
102
|
+
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[0],
|
|
103
|
+
video: '/videos/placeholder1.mp4',
|
|
104
|
+
poster: '/images/placeholder1.jpg',
|
|
105
|
+
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[0],
|
|
106
|
+
link: '/',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[1],
|
|
110
|
+
video: '/videos/placeholder2.mp4',
|
|
111
|
+
poster: '/images/placeholder2.jpg',
|
|
112
|
+
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[1],
|
|
113
|
+
link: '/',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[2],
|
|
117
|
+
video: '/videos/placeholder3.mp4',
|
|
118
|
+
poster: '/images/placeholder3.jpg',
|
|
119
|
+
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[2],
|
|
120
|
+
link: '/',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[3],
|
|
124
|
+
video: '/videos/placeholder4.mp4',
|
|
125
|
+
poster: '/images/placeholder4.jpg',
|
|
126
|
+
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[3],
|
|
127
|
+
link: '/',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
title: PROGRAM_CAROUSEL.UI.PROGRAM_TITLES[4],
|
|
131
|
+
video: '/videos/placeholder5.mp4',
|
|
132
|
+
poster: '/images/placeholder5.jpg',
|
|
133
|
+
description: PROGRAM_CAROUSEL.UI.PROGRAM_DESCRIPTIONS[4],
|
|
134
|
+
link: '/',
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
sectionTitle = PROGRAM_CAROUSEL.UI.SECTION_TITLE,
|
|
138
|
+
buttonText = PROGRAM_CAROUSEL.UI.VIEW_ALL_BUTTON_TEXT,
|
|
139
|
+
buttonLink = '/',
|
|
140
|
+
}: ProgramsCarouselProps) => {
|
|
141
|
+
const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true, align: 'start', containScroll: 'trimSnaps', slidesToScroll: 1 });
|
|
142
|
+
const [canPrev, setCanPrev] = useState(false);
|
|
143
|
+
const [canNext, setCanNext] = useState(true);
|
|
144
|
+
|
|
145
|
+
const scrollPrev = useCallback(() => {
|
|
146
|
+
if (emblaApi) emblaApi.scrollPrev();
|
|
147
|
+
}, [emblaApi]);
|
|
148
|
+
|
|
149
|
+
const scrollNext = useCallback(() => {
|
|
150
|
+
if (emblaApi) emblaApi.scrollNext();
|
|
151
|
+
}, [emblaApi]);
|
|
152
|
+
|
|
153
|
+
const onSelect = useCallback(() => {
|
|
154
|
+
if (!emblaApi) return;
|
|
155
|
+
setCanPrev(emblaApi.canScrollPrev());
|
|
156
|
+
setCanNext(emblaApi.canScrollNext());
|
|
157
|
+
}, [emblaApi]);
|
|
158
|
+
|
|
159
|
+
useEffect(() => {
|
|
160
|
+
if (!emblaApi) return;
|
|
161
|
+
emblaApi.on('select', onSelect);
|
|
162
|
+
emblaApi.on('reInit', onSelect);
|
|
163
|
+
onSelect();
|
|
164
|
+
|
|
165
|
+
emblaApi.reInit();
|
|
166
|
+
emblaApi.scrollTo(0, false);
|
|
167
|
+
|
|
168
|
+
const handleResize = () => emblaApi.reInit();
|
|
169
|
+
window.addEventListener('resize', handleResize);
|
|
170
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
171
|
+
}, [emblaApi, onSelect]);
|
|
172
|
+
|
|
173
|
+
return (
|
|
174
|
+
<motion.section
|
|
175
|
+
className="w-full bg-white/80 relative overflow-hidden p-0 m-0"
|
|
176
|
+
initial="hidden"
|
|
177
|
+
whileInView="visible"
|
|
178
|
+
>
|
|
179
|
+
<div className="w-full py-12 sm:py-24 m-0">
|
|
180
|
+
<motion.h2 className="text-4xl sm:text-6xl font-bold text-center mb-8">
|
|
181
|
+
{sectionTitle}
|
|
182
|
+
</motion.h2>
|
|
183
|
+
<div className="embla relative border-none outline-none w-full" ref={emblaRef}>
|
|
184
|
+
<motion.div
|
|
185
|
+
className="embla__container flex gap-0 w-full"
|
|
186
|
+
variants={staggerChildren}
|
|
187
|
+
initial="hidden"
|
|
188
|
+
whileInView="visible"
|
|
189
|
+
viewport={{ once: true }}
|
|
190
|
+
>
|
|
191
|
+
{programs.map((program, index) => (
|
|
192
|
+
<ProgramSlide key={index} program={program} />
|
|
193
|
+
))}
|
|
194
|
+
</motion.div>
|
|
195
|
+
<PrevButton
|
|
196
|
+
className="absolute left-0 top-1/2 transform -translate-y-1/2 p-2 rounded-r-full"
|
|
197
|
+
onClick={scrollPrev}
|
|
198
|
+
disabled={!canPrev}
|
|
199
|
+
aria-label={PROGRAM_CAROUSEL.BUTTONS.PREVIOUS_SLIDE_ARIA}
|
|
200
|
+
>
|
|
201
|
+
<ChevronLeft size={24} />
|
|
202
|
+
</PrevButton>
|
|
203
|
+
<NextButton
|
|
204
|
+
className="absolute right-0 top-1/2 transform -translate-y-1/2 p-2 rounded-l-full"
|
|
205
|
+
onClick={scrollNext}
|
|
206
|
+
disabled={!canNext}
|
|
207
|
+
aria-label={PROGRAM_CAROUSEL.BUTTONS.NEXT_SLIDE_ARIA}
|
|
208
|
+
>
|
|
209
|
+
<ChevronRight size={24} />
|
|
210
|
+
</NextButton>
|
|
211
|
+
</div>
|
|
212
|
+
<motion.div
|
|
213
|
+
className="mt-8 text-center"
|
|
214
|
+
initial={{ opacity: 0, y: 20 }}
|
|
215
|
+
whileInView={{ opacity: 1, y: 0 }}
|
|
216
|
+
viewport={{ once: true }}
|
|
217
|
+
transition={{ duration: 0.5, delay: 0.6, ease: 'easeOut' }}
|
|
218
|
+
>
|
|
219
|
+
<Link href={buttonLink}>
|
|
220
|
+
<ActionButton
|
|
221
|
+
className="hover:scale-110 hover:shadow-lg hover:shadow-gray-800"
|
|
222
|
+
aria-label={buttonText}
|
|
223
|
+
>
|
|
224
|
+
{buttonText}
|
|
225
|
+
</ActionButton>
|
|
226
|
+
</Link>
|
|
227
|
+
</motion.div>
|
|
228
|
+
</div>
|
|
229
|
+
</motion.section>
|
|
230
|
+
);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
233
|
export default ProgramsCarousel;
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
// components/addOns/non-functional/imageCarousels/constants/programCarousel.ts
|
|
2
|
-
// Constants for hardcoded text in ProgramsCarousel.tsx, organized by purpose
|
|
3
|
-
|
|
4
|
-
export const PROGRAM_CAROUSEL = {
|
|
5
|
-
// UI Text for ProgramsCarousel
|
|
6
|
-
UI: {
|
|
7
|
-
// Default program titles
|
|
8
|
-
PROGRAM_TITLES: [
|
|
9
|
-
"Program One",
|
|
10
|
-
"Program Two",
|
|
11
|
-
"Program Three",
|
|
12
|
-
"Program Four",
|
|
13
|
-
"Program Five",
|
|
14
|
-
],
|
|
15
|
-
// Default program descriptions
|
|
16
|
-
PROGRAM_DESCRIPTIONS: [
|
|
17
|
-
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
|
18
|
-
"Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
|
19
|
-
"Ut enim ad minim veniam, quis nostrud exercitation ullamco.",
|
|
20
|
-
"Duis aute irure dolor in reprehenderit in voluptate velit.",
|
|
21
|
-
"Excepteur sint occaecat cupidatat non proident.",
|
|
22
|
-
],
|
|
23
|
-
// Default section title
|
|
24
|
-
SECTION_TITLE: "Our Programs",
|
|
25
|
-
// Default button text (also used as aria-label)
|
|
26
|
-
VIEW_ALL_BUTTON_TEXT: "View All Programs",
|
|
27
|
-
},
|
|
28
|
-
// Button Text for ProgramsCarousel
|
|
29
|
-
BUTTONS: {
|
|
30
|
-
// Aria-label for previous button
|
|
31
|
-
PREVIOUS_SLIDE_ARIA: "Previous slide",
|
|
32
|
-
// Aria-label for next button
|
|
33
|
-
NEXT_SLIDE_ARIA: "Next slide",
|
|
34
|
-
},
|
|
35
|
-
// Error Messages for ProgramsCarousel
|
|
36
|
-
ERRORS: {
|
|
37
|
-
// Console error message for video playback failure
|
|
38
|
-
VIDEO_PLAY_ERROR: "Video play error:",
|
|
39
|
-
},
|
|
1
|
+
// components/addOns/non-functional/imageCarousels/constants/programCarousel.ts
|
|
2
|
+
// Constants for hardcoded text in ProgramsCarousel.tsx, organized by purpose
|
|
3
|
+
|
|
4
|
+
export const PROGRAM_CAROUSEL = {
|
|
5
|
+
// UI Text for ProgramsCarousel
|
|
6
|
+
UI: {
|
|
7
|
+
// Default program titles
|
|
8
|
+
PROGRAM_TITLES: [
|
|
9
|
+
"Program One",
|
|
10
|
+
"Program Two",
|
|
11
|
+
"Program Three",
|
|
12
|
+
"Program Four",
|
|
13
|
+
"Program Five",
|
|
14
|
+
],
|
|
15
|
+
// Default program descriptions
|
|
16
|
+
PROGRAM_DESCRIPTIONS: [
|
|
17
|
+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
|
18
|
+
"Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
|
19
|
+
"Ut enim ad minim veniam, quis nostrud exercitation ullamco.",
|
|
20
|
+
"Duis aute irure dolor in reprehenderit in voluptate velit.",
|
|
21
|
+
"Excepteur sint occaecat cupidatat non proident.",
|
|
22
|
+
],
|
|
23
|
+
// Default section title
|
|
24
|
+
SECTION_TITLE: "Our Programs",
|
|
25
|
+
// Default button text (also used as aria-label)
|
|
26
|
+
VIEW_ALL_BUTTON_TEXT: "View All Programs",
|
|
27
|
+
},
|
|
28
|
+
// Button Text for ProgramsCarousel
|
|
29
|
+
BUTTONS: {
|
|
30
|
+
// Aria-label for previous button
|
|
31
|
+
PREVIOUS_SLIDE_ARIA: "Previous slide",
|
|
32
|
+
// Aria-label for next button
|
|
33
|
+
NEXT_SLIDE_ARIA: "Next slide",
|
|
34
|
+
},
|
|
35
|
+
// Error Messages for ProgramsCarousel
|
|
36
|
+
ERRORS: {
|
|
37
|
+
// Console error message for video playback failure
|
|
38
|
+
VIDEO_PLAY_ERROR: "Video play error:",
|
|
39
|
+
},
|
|
40
40
|
};
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
// components/addOns/non-functional/imageCarousels/constants/programSlider.ts
|
|
2
|
-
// Constants for hardcoded text in ProductSlider.tsx, organized by purpose
|
|
3
|
-
|
|
4
|
-
export const PROGRAM_SLIDER = {
|
|
5
|
-
// UI Text for ProductSlider
|
|
6
|
-
UI: {
|
|
7
|
-
// Default product names
|
|
8
|
-
PRODUCT_NAMES: [
|
|
9
|
-
"Product One",
|
|
10
|
-
"Product Two",
|
|
11
|
-
"Product Three",
|
|
12
|
-
"Product Four",
|
|
13
|
-
"Product Five",
|
|
14
|
-
"Product Six",
|
|
15
|
-
],
|
|
16
|
-
// Default product descriptions
|
|
17
|
-
PRODUCT_DESCRIPTIONS: [
|
|
18
|
-
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
|
19
|
-
"Sed do eiusmod tempor incididunt ut labore et dolore.",
|
|
20
|
-
"Ut enim ad minim veniam, quis nostrud exercitation.",
|
|
21
|
-
"Duis aute irure dolor in reprehenderit in voluptate velit.",
|
|
22
|
-
"Excepteur sint occaecat cupidatat non proident.",
|
|
23
|
-
"Sunt in culpa qui officia deserunt mollit anim id est laborum.",
|
|
24
|
-
],
|
|
25
|
-
},
|
|
26
|
-
// Button Text for ProductSlider
|
|
27
|
-
BUTTONS: {
|
|
28
|
-
// Aria-label for previous button
|
|
29
|
-
PREVIOUS_PRODUCT_ARIA: "Previous product",
|
|
30
|
-
// Aria-label for next button
|
|
31
|
-
NEXT_PRODUCT_ARIA: "Next product",
|
|
32
|
-
},
|
|
33
|
-
// Error Messages for ProductSlider
|
|
34
|
-
ERRORS: {
|
|
35
|
-
// No hardcoded errors
|
|
36
|
-
},
|
|
1
|
+
// components/addOns/non-functional/imageCarousels/constants/programSlider.ts
|
|
2
|
+
// Constants for hardcoded text in ProductSlider.tsx, organized by purpose
|
|
3
|
+
|
|
4
|
+
export const PROGRAM_SLIDER = {
|
|
5
|
+
// UI Text for ProductSlider
|
|
6
|
+
UI: {
|
|
7
|
+
// Default product names
|
|
8
|
+
PRODUCT_NAMES: [
|
|
9
|
+
"Product One",
|
|
10
|
+
"Product Two",
|
|
11
|
+
"Product Three",
|
|
12
|
+
"Product Four",
|
|
13
|
+
"Product Five",
|
|
14
|
+
"Product Six",
|
|
15
|
+
],
|
|
16
|
+
// Default product descriptions
|
|
17
|
+
PRODUCT_DESCRIPTIONS: [
|
|
18
|
+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
|
19
|
+
"Sed do eiusmod tempor incididunt ut labore et dolore.",
|
|
20
|
+
"Ut enim ad minim veniam, quis nostrud exercitation.",
|
|
21
|
+
"Duis aute irure dolor in reprehenderit in voluptate velit.",
|
|
22
|
+
"Excepteur sint occaecat cupidatat non proident.",
|
|
23
|
+
"Sunt in culpa qui officia deserunt mollit anim id est laborum.",
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
// Button Text for ProductSlider
|
|
27
|
+
BUTTONS: {
|
|
28
|
+
// Aria-label for previous button
|
|
29
|
+
PREVIOUS_PRODUCT_ARIA: "Previous product",
|
|
30
|
+
// Aria-label for next button
|
|
31
|
+
NEXT_PRODUCT_ARIA: "Next product",
|
|
32
|
+
},
|
|
33
|
+
// Error Messages for ProductSlider
|
|
34
|
+
ERRORS: {
|
|
35
|
+
// No hardcoded errors
|
|
36
|
+
},
|
|
37
37
|
};
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { motion } from "framer-motion";
|
|
4
|
-
|
|
5
|
-
const spinnerVariants = {
|
|
6
|
-
animate: {
|
|
7
|
-
rotate: 360,
|
|
8
|
-
transition: { duration: 1, repeat: Infinity, ease: "linear" },
|
|
9
|
-
},
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export default function Spinner() {
|
|
13
|
-
return (
|
|
14
|
-
<div className="fixed inset-0 flex items-center justify-center bg-gray-900/80 z-50">
|
|
15
|
-
<motion.div
|
|
16
|
-
variants={spinnerVariants}
|
|
17
|
-
animate="animate"
|
|
18
|
-
className="w-12 h-12 border-4 border-t-4 border-gray-300 border-t-blue-500 rounded-full"
|
|
19
|
-
/>
|
|
20
|
-
</div>
|
|
21
|
-
);
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { motion } from "framer-motion";
|
|
4
|
+
|
|
5
|
+
const spinnerVariants = {
|
|
6
|
+
animate: {
|
|
7
|
+
rotate: 360,
|
|
8
|
+
transition: { duration: 1, repeat: Infinity, ease: "linear" },
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default function Spinner() {
|
|
13
|
+
return (
|
|
14
|
+
<div className="fixed inset-0 flex items-center justify-center bg-gray-900/80 z-50">
|
|
15
|
+
<motion.div
|
|
16
|
+
variants={spinnerVariants}
|
|
17
|
+
animate="animate"
|
|
18
|
+
className="w-12 h-12 border-4 border-t-4 border-gray-300 border-t-blue-500 rounded-full"
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
22
|
}
|