@devvistatech/devvista-kit 0.0.1
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 +13 -0
- package/LICENSE +7 -0
- package/README.md +15 -0
- package/app/about/page.tsx +306 -0
- package/app/adRequest/page.tsx +550 -0
- package/app/analytics/page.tsx +347 -0
- package/app/api/about/route.ts +307 -0
- package/app/api/adRequest/route.ts +568 -0
- package/app/api/analytics/[reportType]/route.ts +338 -0
- package/app/api/bio/route.ts +314 -0
- package/app/api/blog/route.ts +307 -0
- package/app/api/chat/route.ts +15 -0
- package/app/api/contact/route.ts +410 -0
- package/app/api/contacts/route.ts +225 -0
- package/app/api/files/route.ts +430 -0
- package/app/api/gallery-data/route.ts +661 -0
- package/app/api/schedule/route.ts +456 -0
- package/app/api/sync-user/route.ts +114 -0
- package/app/api/trial-request/route.ts +298 -0
- package/app/blog/[id]/page.tsx +281 -0
- package/app/blog/page.tsx +217 -0
- package/app/constants/about.ts +49 -0
- package/app/constants/adRequest.ts +114 -0
- package/app/constants/contact.ts +41 -0
- package/app/constants/faq.ts +46 -0
- package/app/constants/gallery.ts +43 -0
- package/app/constants/page.ts +70 -0
- package/app/constants/schedule.ts +72 -0
- package/app/contact/page.tsx +285 -0
- package/app/faq/page.tsx +192 -0
- package/app/favicon.ico +0 -0
- package/app/gallery/page.tsx +320 -0
- package/app/globals.css +58 -0
- package/app/layout.tsx +62 -0
- package/app/page.tsx +339 -0
- package/app/schedule/page.tsx +661 -0
- package/bin/init.js +187 -0
- package/components/addOns/functional/BioEditor.tsx +430 -0
- package/components/addOns/functional/CalendlyWidget.tsx +101 -0
- package/components/addOns/functional/ClassList.tsx +146 -0
- package/components/addOns/functional/ClassPopup.tsx +399 -0
- package/components/addOns/functional/ContactForm.tsx +285 -0
- package/components/addOns/functional/FileUploader.tsx +293 -0
- package/components/addOns/functional/ImageDescCarousel.tsx +821 -0
- package/components/addOns/functional/NewUserAnalytics.tsx +101 -0
- package/components/addOns/functional/ScheduleCarousel.tsx +172 -0
- package/components/addOns/functional/aboutSections/AboutSection.tsx +571 -0
- package/components/addOns/functional/aboutSections/constants/aboutSection.ts +66 -0
- package/components/addOns/functional/blogSections/BlogDashboard.tsx +185 -0
- package/components/addOns/functional/blogSections/BlogFormPopUp.tsx +555 -0
- package/components/addOns/functional/blogSections/BlogList.tsx +149 -0
- package/components/addOns/functional/blogSections/BlogSidebar.tsx +59 -0
- package/components/addOns/functional/blogSections/constants/blogDashboard.ts +29 -0
- package/components/addOns/functional/blogSections/constants/blogFormPopUp.ts +98 -0
- package/components/addOns/functional/blogSections/constants/blogList.ts +23 -0
- package/components/addOns/functional/blogSections/constants/blogSidebar.ts +16 -0
- package/components/addOns/functional/contactsDashboard/ContactsDashboard.tsx +348 -0
- package/components/addOns/functional/contactsDashboard/constants/contactsDashboard.ts +71 -0
- package/components/addOns/functional/galleries/GalleryComplex.tsx +908 -0
- package/components/addOns/functional/galleries/GallerySimple.tsx +604 -0
- package/components/addOns/functional/galleries/constants/galleryComplex.ts +105 -0
- package/components/addOns/functional/galleries/constants/gallerySimple.ts +75 -0
- package/components/addOns/functional/schedules/ScheduleGridOne.tsx +263 -0
- package/components/addOns/functional/schedules/ScheduleGridTwo.tsx +295 -0
- package/components/addOns/functional/schedules/ScheduleGridTwoBasic.tsx +289 -0
- package/components/addOns/functional/schedules/SchedulerForm.tsx +429 -0
- package/components/addOns/functional/schedules/constants/ScheduleGridTwo.ts +41 -0
- package/components/addOns/functional/schedules/constants/ScheduleGridTwoBasic.ts +41 -0
- package/components/addOns/functional/schedules/constants/SchedulerForm.ts +66 -0
- package/components/addOns/functional/schedules/constants/scheduleGridOne.ts +55 -0
- package/components/addOns/non-functional/AnnouncementBanner.tsx +47 -0
- package/components/addOns/non-functional/FeaturesSection.tsx +63 -0
- package/components/addOns/non-functional/HeroSection.tsx +143 -0
- package/components/addOns/non-functional/IconBubble.tsx +50 -0
- package/components/addOns/non-functional/SampleCarousel.tsx +205 -0
- package/components/addOns/non-functional/Testimonials.tsx +336 -0
- package/components/addOns/non-functional/ThreeSetGallery.tsx +64 -0
- package/components/addOns/non-functional/aboutSections/AboutSection.tsx +63 -0
- package/components/addOns/non-functional/aboutSections/constants/aboutSection.ts +25 -0
- package/components/addOns/non-functional/imageCarousels/ProductSlider.tsx +118 -0
- package/components/addOns/non-functional/imageCarousels/ProgramCarousel.tsx +233 -0
- package/components/addOns/non-functional/imageCarousels/constants/programCarousel.ts +40 -0
- package/components/addOns/non-functional/imageCarousels/constants/programSlider.ts +37 -0
- package/components/addOns/non-functional/spinner.tsx +22 -0
- package/components/footers/footer.tsx +454 -0
- package/components/navBars/navbar.tsx +311 -0
- package/components/other/accordion.tsx +58 -0
- package/components/other/admin-menu.tsx +69 -0
- package/components/other/alert-dialog.tsx +141 -0
- package/components/other/alert.tsx +59 -0
- package/components/other/aspect-ratio.tsx +7 -0
- package/components/other/avatar.tsx +50 -0
- package/components/other/badge.tsx +36 -0
- package/components/other/breadcrumb.tsx +115 -0
- package/components/other/button.tsx +733 -0
- package/components/other/calendar.tsx +66 -0
- package/components/other/card.tsx +86 -0
- package/components/other/carousel.tsx +275 -0
- package/components/other/chart.tsx +363 -0
- package/components/other/checkbox.tsx +30 -0
- package/components/other/collapsible.tsx +11 -0
- package/components/other/command.tsx +155 -0
- package/components/other/context-menu.tsx +200 -0
- package/components/other/dialog.tsx +122 -0
- package/components/other/drawer.tsx +118 -0
- package/components/other/dropdown-menu.tsx +200 -0
- package/components/other/form.tsx +179 -0
- package/components/other/hover-card.tsx +29 -0
- package/components/other/input-otp.tsx +71 -0
- package/components/other/input.tsx +25 -0
- package/components/other/label.tsx +26 -0
- package/components/other/login-popup.tsx +0 -0
- package/components/other/menubar.tsx +236 -0
- package/components/other/mobile-icon.tsx +22 -0
- package/components/other/navigation-menu.tsx +128 -0
- package/components/other/pagination.tsx +117 -0
- package/components/other/popover.tsx +31 -0
- package/components/other/progress.tsx +28 -0
- package/components/other/radio-group.tsx +44 -0
- package/components/other/resizable.tsx +45 -0
- package/components/other/scroll-area.tsx +48 -0
- package/components/other/select.tsx +160 -0
- package/components/other/separator.tsx +31 -0
- package/components/other/sheet.tsx +140 -0
- package/components/other/signup-popup.tsx +0 -0
- package/components/other/skeleton.tsx +15 -0
- package/components/other/slider.tsx +28 -0
- package/components/other/social-icons.tsx +40 -0
- package/components/other/sonner.tsx +31 -0
- package/components/other/switch.tsx +29 -0
- package/components/other/table.tsx +117 -0
- package/components/other/tabs.tsx +55 -0
- package/components/other/textarea.tsx +24 -0
- package/components/other/toast.tsx +123 -0
- package/components/other/toaster.tsx +35 -0
- package/components/other/toggle-group.tsx +61 -0
- package/components/other/toggle.tsx +45 -0
- package/components/other/tooltip.tsx +30 -0
- package/components/theme-provider.tsx +9 -0
- package/components/types.ts +22 -0
- 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 +259 -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 +346 -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 +642 -0
- package/dist/app/api/schedule/route.js +461 -0
- package/dist/app/api/sync-user/route.js +174 -0
- package/dist/app/api/trial-request/route.js +165 -0
- package/dist/app/blog/[id]/page.jsx +307 -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 +280 -0
- package/dist/app/layout.jsx +45 -0
- package/dist/app/page.jsx +324 -0
- package/dist/app/schedule/page.jsx +500 -0
- package/dist/components/addOns/functional/BioEditor.jsx +175 -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 +464 -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 +369 -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 +323 -0
- package/dist/components/addOns/functional/contactsDashboard/constants/contactsDashboard.js +70 -0
- package/dist/components/addOns/functional/galleries/GalleryComplex.jsx +586 -0
- package/dist/components/addOns/functional/galleries/GallerySimple.jsx +385 -0
- package/dist/components/addOns/functional/galleries/constants/galleryComplex.js +104 -0
- package/dist/components/addOns/functional/galleries/constants/gallerySimple.js +74 -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/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 +219 -0
- package/dist/components/navBars/navbar.jsx +158 -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 +321 -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/google-analytics.jsx +148 -0
- package/dist/lib/utils.js +9 -0
- package/dist/lib/verify-user.js +142 -0
- package/dist/middleware.js +32 -0
- package/dist/tailwind.config.js +86 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/hooks/use-toast.ts +188 -0
- package/lib/auth-context.tsx +131 -0
- package/lib/google-analytics.tsx +98 -0
- package/lib/utils.ts +6 -0
- package/lib/verify-user.ts +118 -0
- package/middleware.ts +35 -0
- package/next.config.js +10 -0
- package/package.json +116 -0
- package/postcss.config.js +6 -0
- package/public/images/FitStop.png +0 -0
- package/public/images/classes/bodyblast.JPG +0 -0
- package/public/images/classes/cardioxtrain.JPG +0 -0
- package/public/images/classes/combo.JPG +0 -0
- package/public/images/classes/flexiblefriday.JPG +0 -0
- package/public/images/classes/freestyle.jpg +0 -0
- package/public/images/classes/noclasses.jpg +0 -0
- package/public/images/classes/seniorstretch.JPG +0 -0
- package/public/images/classes/stretch.JPG +0 -0
- package/public/images/classes/zoomba.JPG +0 -0
- package/public/images/fitstoproom1.jpg +0 -0
- package/public/images/fitstoproom2.jpg +0 -0
- package/public/images/gallery/021-1024x768.jpg +0 -0
- package/public/images/gallery/023-1024x768.jpg +0 -0
- package/public/images/gallery/027-1024x768.jpg +0 -0
- package/public/images/gallery/029-1024x768.jpg +0 -0
- package/public/images/gallery/030-1024x768.jpg +0 -0
- package/public/images/gallery/042-1024x768.jpg +0 -0
- package/public/images/gallery/049-1024x768.jpg +0 -0
- package/public/images/gallery/073-1024x768.jpg +0 -0
- package/public/images/gallery/108-300x225.jpg +0 -0
- package/public/images/gallery/109-300x225.jpg +0 -0
- package/public/images/gallery/116.jpg +0 -0
- package/public/images/gallery/123-1-1024x768.jpg +0 -0
- package/public/images/gallery/133.jpg +0 -0
- package/public/images/gallery/142-1.jpg +0 -0
- package/public/images/gallery/143.jpg +0 -0
- package/public/images/gallery/145-1-1024x768.jpg +0 -0
- package/public/images/gallery/151-1024x768.jpg +0 -0
- package/public/images/gallery/166-300x225.jpg +0 -0
- package/public/images/gallery/175.jpg +0 -0
- package/public/images/gallery/183-1024x768.jpg +0 -0
- package/public/images/gallery/311.JPG +0 -0
- package/public/images/gallery/413-1.jpg +0 -0
- package/public/images/gallery/Cathys-Fit-Stop-Holiday-Party-0003-1024x683.jpg +0 -0
- package/public/images/gallery/Cathys-Fit-Stop-Holiday-Party-0076-1024x683.jpg +0 -0
- package/public/images/gallery/Cathys-Fit-Stop-Holiday-Party-0171-1024x683.jpg +0 -0
- package/public/images/gallery/DSCN0233-1024x768.jpg +0 -0
- package/public/images/gallery/DSCN0245-1-1024x768.jpg +0 -0
- package/public/images/gallery/Fitstopgirls2.jpg +0 -0
- package/public/images/gallery/GrandOpening2009.JPG +0 -0
- package/public/images/gallery/IMG_1937.JPG +0 -0
- package/public/images/gallery/IMG_1950-20.jpg +0 -0
- package/public/images/gallery/IMG_2112.JPG +0 -0
- package/public/images/gallery/IMG_2229.JPG +0 -0
- package/public/images/gallery/IMG_2272.JPG +0 -0
- package/public/images/gallery/IMG_2336.JPG +0 -0
- package/public/images/gallery/IMG_2367.JPG +0 -0
- package/public/images/gallery/IMG_2520.jpg +0 -0
- package/public/images/gallery/IMG_2564.jpg +0 -0
- package/public/images/gallery/IMG_3678.jpg +0 -0
- package/public/images/gallery/IMG_3744.jpg +0 -0
- package/public/images/gallery/IMG_3745.jpg +0 -0
- package/public/images/gallery/IMG_6383.jpg +0 -0
- package/public/images/gallery/Jillian-8-Months-2338-1024x683.jpg +0 -0
- package/public/images/gallery/Kathys-Fit-Stop-0032-1024x675.jpg +0 -0
- package/public/images/gallery/LaurieinPlank.jpeg +0 -0
- package/public/images/gallery/May2017032.JPG +0 -0
- package/public/images/gallery/clubpic10.jpg +0 -0
- package/public/images/gallery/clubpic15.jpg +0 -0
- package/public/images/gallery/clubpic2.jpg +0 -0
- package/public/images/gallery/clubpic3.jpg +0 -0
- package/public/images/gallery/clubpic4.jpg +0 -0
- package/public/images/gallery/clubpic5.jpg +0 -0
- package/public/images/gallery/clubpic6.jpg +0 -0
- package/public/images/gallery/clubpic7.jpg +0 -0
- package/public/images/gallery/clubpic8.jpg +0 -0
- package/public/images/gallery/clubpic9.jpg +0 -0
- package/public/images/gallery/z014-1024x768.jpg +0 -0
- package/public/images/gallery/z019-1-1024x768.jpg +0 -0
- package/public/images/kathy_faq-300x132.jpg +0 -0
- package/public/images/kathyportrait.jpg +0 -0
- package/public/images/kristiportrait.jpg +0 -0
- package/public/images/maincoverbackground.JPG +0 -0
- package/public/images/videos/FitStopLoopVideo.mp4 +0 -0
- package/public/images/weights.jpg +0 -0
- package/public/pdf/FitStop-Forum-April-2025.pdf +0 -0
- package/tailwind.config.ts +89 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
// src/pages/Schedule.tsx
|
|
2
|
+
"use client";
|
|
3
|
+
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { AddButton, CancelButton, DeleteButton, CloseButton } from "@/components/other/button";
|
|
6
|
+
import { motion } from "framer-motion";
|
|
7
|
+
import { X } from "lucide-react";
|
|
8
|
+
import { useAuth } from "@clerk/nextjs";
|
|
9
|
+
import { SCHEDULER_FORM } from "./constants/SchedulerForm";
|
|
10
|
+
|
|
11
|
+
interface ScheduleClass {
|
|
12
|
+
name: string;
|
|
13
|
+
startTime: string;
|
|
14
|
+
endTime: string;
|
|
15
|
+
id: number;
|
|
16
|
+
documentId: string;
|
|
17
|
+
daysOfWeek: number[];
|
|
18
|
+
classDescription?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ScheduleProps {
|
|
22
|
+
isModalOpen: boolean;
|
|
23
|
+
setIsModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
|
24
|
+
isConfirmDeleteOpen: boolean;
|
|
25
|
+
setIsConfirmDeleteOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
|
26
|
+
classToDelete: { id: number; documentId: string; day: string } | null;
|
|
27
|
+
setClassToDelete: React.Dispatch<
|
|
28
|
+
React.SetStateAction<{ id: number; documentId: string; day: string } | null>
|
|
29
|
+
>;
|
|
30
|
+
isLoading: boolean;
|
|
31
|
+
error: string | null;
|
|
32
|
+
formData: {
|
|
33
|
+
name: string;
|
|
34
|
+
startTime: string;
|
|
35
|
+
endTime: string;
|
|
36
|
+
daysOfWeek: number[];
|
|
37
|
+
classDescription: string;
|
|
38
|
+
id: number | null;
|
|
39
|
+
documentId: string | null;
|
|
40
|
+
};
|
|
41
|
+
setFormData: React.Dispatch<
|
|
42
|
+
React.SetStateAction<{
|
|
43
|
+
name: string;
|
|
44
|
+
startTime: string;
|
|
45
|
+
endTime: string;
|
|
46
|
+
daysOfWeek: number[];
|
|
47
|
+
classDescription: string;
|
|
48
|
+
id: number | null;
|
|
49
|
+
documentId: string | null;
|
|
50
|
+
}>
|
|
51
|
+
>;
|
|
52
|
+
isAdmin: boolean;
|
|
53
|
+
handleSubmit: (e: React.FormEvent) => Promise<void>;
|
|
54
|
+
handleConfirmDelete: () => Promise<void>;
|
|
55
|
+
handleCancelDelete: () => void;
|
|
56
|
+
roundToNearestFiveMinutes: (time: string) => string;
|
|
57
|
+
modalVariants: {
|
|
58
|
+
hidden: { opacity: number; y: string };
|
|
59
|
+
visible: { opacity: number; y: number; transition: { duration: number; ease: number[] } };
|
|
60
|
+
exit: { opacity: number; y: string; transition: { duration: number; ease: string } };
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export default function Schedule({
|
|
65
|
+
isModalOpen,
|
|
66
|
+
setIsModalOpen,
|
|
67
|
+
isConfirmDeleteOpen,
|
|
68
|
+
setIsConfirmDeleteOpen,
|
|
69
|
+
classToDelete,
|
|
70
|
+
setClassToDelete,
|
|
71
|
+
isLoading,
|
|
72
|
+
error,
|
|
73
|
+
formData,
|
|
74
|
+
setFormData,
|
|
75
|
+
isAdmin,
|
|
76
|
+
handleSubmit,
|
|
77
|
+
handleConfirmDelete,
|
|
78
|
+
handleCancelDelete,
|
|
79
|
+
roundToNearestFiveMinutes,
|
|
80
|
+
modalVariants,
|
|
81
|
+
}: ScheduleProps) {
|
|
82
|
+
const { getToken } = useAuth();
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<div>
|
|
86
|
+
<style jsx>{`
|
|
87
|
+
.modal-form input,
|
|
88
|
+
.modal-form select,
|
|
89
|
+
.modal-form textarea {
|
|
90
|
+
font-size: 0.875rem;
|
|
91
|
+
padding: 0.5rem;
|
|
92
|
+
border-radius: 0.375rem;
|
|
93
|
+
background: #374151;
|
|
94
|
+
color: #f3f4f6;
|
|
95
|
+
border: 1px solid #4b5563;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.modal-form input:focus,
|
|
99
|
+
.modal-form select:focus,
|
|
100
|
+
.modal-form textarea:focus {
|
|
101
|
+
outline: none;
|
|
102
|
+
ring: 2px solid #3b82f6;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.modal-form button {
|
|
106
|
+
padding: 0.5rem 1rem;
|
|
107
|
+
font-size: 0.875rem;
|
|
108
|
+
border-radius: 0.375rem;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.modal-form label {
|
|
112
|
+
font-size: 0.875rem;
|
|
113
|
+
color: #d1d5db;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@media (max-width: 640px) {
|
|
117
|
+
.modal-form input,
|
|
118
|
+
.modal-form select,
|
|
119
|
+
.modal-form textarea {
|
|
120
|
+
font-size: 0.875rem;
|
|
121
|
+
padding: 0.5rem;
|
|
122
|
+
border-radius: 0.375rem;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.modal-form button {
|
|
126
|
+
padding: 0.5rem 1rem;
|
|
127
|
+
font-size: 0.875rem;
|
|
128
|
+
border-radius: 0.375rem;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.modal-form label {
|
|
132
|
+
font-size: 0.875rem;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.modal-form .flex {
|
|
136
|
+
flex-direction: column;
|
|
137
|
+
gap: 0.5rem;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.modal-form select {
|
|
141
|
+
appearance: none;
|
|
142
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%23A1A1AA'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'/%3E%3C/svg%3E");
|
|
143
|
+
background-repeat: no-repeat;
|
|
144
|
+
background-position: right 0.75rem center;
|
|
145
|
+
background-size: 1rem;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.modal-form input[type="checkbox"] {
|
|
149
|
+
height: 1.25rem;
|
|
150
|
+
width: 1.25rem;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.modal-form textarea {
|
|
154
|
+
min-height: 80px;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@media (max-width: 320px) {
|
|
159
|
+
.modal-form input,
|
|
160
|
+
.modal-form select,
|
|
161
|
+
.modal-form textarea {
|
|
162
|
+
font-size: 0.75rem;
|
|
163
|
+
padding: 0.5rem;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.modal-form button {
|
|
167
|
+
padding: 0.5rem 0.75rem;
|
|
168
|
+
font-size: 0.75rem;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.modal-form label {
|
|
172
|
+
font-size: 0.75rem;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
`}</style>
|
|
176
|
+
|
|
177
|
+
{/* Modal for Add/Edit */}
|
|
178
|
+
{isModalOpen && isAdmin && (
|
|
179
|
+
<motion.div
|
|
180
|
+
variants={modalVariants}
|
|
181
|
+
initial="hidden"
|
|
182
|
+
animate="visible"
|
|
183
|
+
exit="exit"
|
|
184
|
+
className="fixed inset-0 bg-black/90 flex items-center justify-center z-[10000] p-4 isolate"
|
|
185
|
+
onClick={() => setIsModalOpen(false)}
|
|
186
|
+
>
|
|
187
|
+
<div
|
|
188
|
+
className="relative max-w-5xl w-full mx-4 p-6 bg-gray-800/50 border border-gray-700/50 rounded-lg shadow-lg max-h-[90vh] overflow-y-auto"
|
|
189
|
+
onClick={(e) => e.stopPropagation()}
|
|
190
|
+
>
|
|
191
|
+
<CloseButton
|
|
192
|
+
onClick={() => setIsModalOpen(false)}
|
|
193
|
+
>
|
|
194
|
+
<X className="h-6 w-6 sm:h-8 sm:w-8" />
|
|
195
|
+
</CloseButton>
|
|
196
|
+
<h3 className="text-xl font-bold text-white mb-4">
|
|
197
|
+
{formData.id ? SCHEDULER_FORM.UI.EDIT_CLASS_HEADING : SCHEDULER_FORM.UI.ADD_NEW_CLASS_HEADING}
|
|
198
|
+
</h3>
|
|
199
|
+
<form onSubmit={handleSubmit} className="space-y-4 modal-form">
|
|
200
|
+
<div>
|
|
201
|
+
<label htmlFor="className" className="block text-sm font-medium text-gray-300 mb-1">
|
|
202
|
+
{SCHEDULER_FORM.UI.CLASS_NAME_LABEL}
|
|
203
|
+
</label>
|
|
204
|
+
<input
|
|
205
|
+
id="className"
|
|
206
|
+
type="text"
|
|
207
|
+
placeholder={SCHEDULER_FORM.UI.CLASS_NAME_PLACEHOLDER}
|
|
208
|
+
value={formData.name}
|
|
209
|
+
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
|
210
|
+
className="w-full p-2 rounded bg-gray-700 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
|
211
|
+
required
|
|
212
|
+
/>
|
|
213
|
+
</div>
|
|
214
|
+
|
|
215
|
+
<div>
|
|
216
|
+
<label className="block text-sm font-medium text-gray-300 mb-1">{SCHEDULER_FORM.UI.START_TIME_LABEL}</label>
|
|
217
|
+
<div className="flex flex-col sm:flex-row sm:space-x-2 space-y-2 sm:space-y-0">
|
|
218
|
+
<select
|
|
219
|
+
value={formData.startTime ? formData.startTime.split(":")[0] : ""}
|
|
220
|
+
onChange={(e) => {
|
|
221
|
+
const hours = e.target.value;
|
|
222
|
+
const minutes = formData.startTime ? formData.startTime.split(":")[1] : "00";
|
|
223
|
+
const newTime = roundToNearestFiveMinutes(`${hours}:${minutes}`);
|
|
224
|
+
setFormData({ ...formData, startTime: newTime });
|
|
225
|
+
}}
|
|
226
|
+
className="w-full sm:w-1/3 p-2 rounded bg-gray-700 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
|
227
|
+
required
|
|
228
|
+
>
|
|
229
|
+
<option value="" disabled>{SCHEDULER_FORM.UI.HOUR_OPTION}</option>
|
|
230
|
+
{Array.from({ length: 12 }, (_, i) => i + 1).map((hour) => (
|
|
231
|
+
<option key={hour} value={String(hour).padStart(2, "0")}>{hour}</option>
|
|
232
|
+
))}
|
|
233
|
+
</select>
|
|
234
|
+
<select
|
|
235
|
+
value={formData.startTime ? formData.startTime.split(":")[1] : ""}
|
|
236
|
+
onChange={(e) => {
|
|
237
|
+
const minutes = e.target.value;
|
|
238
|
+
const hours = formData.startTime ? formData.startTime.split(":")[0] : "12";
|
|
239
|
+
const newTime = roundToNearestFiveMinutes(`${hours}:${minutes}`);
|
|
240
|
+
setFormData({ ...formData, startTime: newTime });
|
|
241
|
+
}}
|
|
242
|
+
className="w-full sm:w-1/3 p-2 rounded bg-gray-700 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
|
243
|
+
required
|
|
244
|
+
>
|
|
245
|
+
<option value="" disabled>{SCHEDULER_FORM.UI.MINUTE_OPTION}</option>
|
|
246
|
+
{["00", "05", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55"].map((minute) => (
|
|
247
|
+
<option key={minute} value={minute}>{minute}</option>
|
|
248
|
+
))}
|
|
249
|
+
</select>
|
|
250
|
+
<select
|
|
251
|
+
value={formData.startTime && Number(formData.startTime.split(":")[0]) >= 12 ? SCHEDULER_FORM.UI.PM_OPTION : SCHEDULER_FORM.UI.AM_OPTION}
|
|
252
|
+
onChange={(e) => {
|
|
253
|
+
const period = e.target.value;
|
|
254
|
+
let hours = formData.startTime ? Number(formData.startTime.split(":")[0]) : 12;
|
|
255
|
+
const minutes = formData.startTime ? formData.startTime.split(":")[1] : "00";
|
|
256
|
+
if (period === SCHEDULER_FORM.UI.AM_OPTION && hours >= 12) hours -= 12;
|
|
257
|
+
else if (period === SCHEDULER_FORM.UI.PM_OPTION && hours < 12) hours += 12;
|
|
258
|
+
const newTime = roundToNearestFiveMinutes(`${String(hours).padStart(2, "0")}:${minutes}`);
|
|
259
|
+
setFormData({ ...formData, startTime: newTime });
|
|
260
|
+
}}
|
|
261
|
+
className="w-full sm:w-1/3 p-2 rounded bg-gray-700 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
|
262
|
+
required
|
|
263
|
+
>
|
|
264
|
+
<option value={SCHEDULER_FORM.UI.AM_OPTION}>{SCHEDULER_FORM.UI.AM_OPTION}</option>
|
|
265
|
+
<option value={SCHEDULER_FORM.UI.PM_OPTION}>{SCHEDULER_FORM.UI.PM_OPTION}</option>
|
|
266
|
+
</select>
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
269
|
+
|
|
270
|
+
<div>
|
|
271
|
+
<label className="block text-sm font-medium text-gray-300 mb-1">{SCHEDULER_FORM.UI.END_TIME_LABEL}</label>
|
|
272
|
+
<div className="flex flex-col sm:flex-row sm:space-x-2 space-y-2 sm:space-y-0">
|
|
273
|
+
<select
|
|
274
|
+
value={formData.endTime ? formData.endTime.split(":")[0] : ""}
|
|
275
|
+
onChange={(e) => {
|
|
276
|
+
const hours = e.target.value;
|
|
277
|
+
const minutes = formData.endTime ? formData.endTime.split(":")[1] : "00";
|
|
278
|
+
const newTime = roundToNearestFiveMinutes(`${hours}:${minutes}`);
|
|
279
|
+
setFormData({ ...formData, endTime: newTime });
|
|
280
|
+
}}
|
|
281
|
+
className="w-full sm:w-1/3 p-2 rounded bg-gray-700 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
|
282
|
+
required
|
|
283
|
+
>
|
|
284
|
+
<option value="" disabled>{SCHEDULER_FORM.UI.HOUR_OPTION}</option>
|
|
285
|
+
{Array.from({ length: 12 }, (_, i) => i + 1).map((hour) => (
|
|
286
|
+
<option key={hour} value={String(hour).padStart(2, "0")}>{hour}</option>
|
|
287
|
+
))}
|
|
288
|
+
</select>
|
|
289
|
+
<select
|
|
290
|
+
value={formData.endTime ? formData.endTime.split(":")[1] : ""}
|
|
291
|
+
onChange={(e) => {
|
|
292
|
+
const minutes = e.target.value;
|
|
293
|
+
const hours = formData.endTime ? formData.endTime.split(":")[0] : "12";
|
|
294
|
+
const newTime = roundToNearestFiveMinutes(`${hours}:${minutes}`);
|
|
295
|
+
setFormData({ ...formData, endTime: newTime });
|
|
296
|
+
}}
|
|
297
|
+
className="w-full sm:w-1/3 p-2 rounded bg-gray-700 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
|
298
|
+
required
|
|
299
|
+
>
|
|
300
|
+
<option value="" disabled>{SCHEDULER_FORM.UI.MINUTE_OPTION}</option>
|
|
301
|
+
{["00", "05", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55"].map((minute) => (
|
|
302
|
+
<option key={minute} value={minute}>{minute}</option>
|
|
303
|
+
))}
|
|
304
|
+
</select>
|
|
305
|
+
<select
|
|
306
|
+
value={formData.endTime && Number(formData.endTime.split(":")[0]) >= 12 ? SCHEDULER_FORM.UI.PM_OPTION : SCHEDULER_FORM.UI.AM_OPTION}
|
|
307
|
+
onChange={(e) => {
|
|
308
|
+
const period = e.target.value;
|
|
309
|
+
let hours = formData.endTime ? Number(formData.endTime.split(":")[0]) : 12;
|
|
310
|
+
const minutes = formData.endTime ? formData.endTime.split(":")[1] : "00";
|
|
311
|
+
if (period === SCHEDULER_FORM.UI.AM_OPTION && hours >= 12) hours -= 12;
|
|
312
|
+
else if (period === SCHEDULER_FORM.UI.PM_OPTION && hours < 12) hours += 12;
|
|
313
|
+
const newTime = roundToNearestFiveMinutes(`${String(hours).padStart(2, "0")}:${minutes}`);
|
|
314
|
+
setFormData({ ...formData, endTime: newTime });
|
|
315
|
+
}}
|
|
316
|
+
className="w-full sm:w-1/3 p-2 rounded bg-gray-700 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
|
317
|
+
required
|
|
318
|
+
>
|
|
319
|
+
<option value={SCHEDULER_FORM.UI.AM_OPTION}>{SCHEDULER_FORM.UI.AM_OPTION}</option>
|
|
320
|
+
<option value={SCHEDULER_FORM.UI.PM_OPTION}>{SCHEDULER_FORM.UI.PM_OPTION}</option>
|
|
321
|
+
</select>
|
|
322
|
+
</div>
|
|
323
|
+
</div>
|
|
324
|
+
|
|
325
|
+
<div>
|
|
326
|
+
<label className="block text-sm font-medium text-gray-300 mb-1">{SCHEDULER_FORM.UI.DAYS_OF_WEEK_LABEL}</label>
|
|
327
|
+
<div className="grid grid-cols-2 sm:grid-cols-4 gap-2">
|
|
328
|
+
{SCHEDULER_FORM.UI.DAYS_OF_WEEK.map((day) => (
|
|
329
|
+
<label key={day.value} className="flex items-center space-x-2 cursor-pointer">
|
|
330
|
+
<input
|
|
331
|
+
type="checkbox"
|
|
332
|
+
value={day.value}
|
|
333
|
+
checked={formData.daysOfWeek.includes(day.value)}
|
|
334
|
+
onChange={(e) => {
|
|
335
|
+
const value = Number(e.target.value);
|
|
336
|
+
setFormData({
|
|
337
|
+
...formData,
|
|
338
|
+
daysOfWeek: e.target.checked
|
|
339
|
+
? [...formData.daysOfWeek, value].sort()
|
|
340
|
+
: formData.daysOfWeek.filter((d) => d !== value),
|
|
341
|
+
});
|
|
342
|
+
}}
|
|
343
|
+
className="h-5 w-5 text-blue-500 focus:ring-blue-500 border-gray-600 rounded bg-gray-700"
|
|
344
|
+
/>
|
|
345
|
+
<span className="text-gray-300 text-sm">{day.label}</span>
|
|
346
|
+
</label>
|
|
347
|
+
))}
|
|
348
|
+
</div>
|
|
349
|
+
</div>
|
|
350
|
+
|
|
351
|
+
<div>
|
|
352
|
+
<label htmlFor="classDescription" className="block text-sm font-medium text-gray-300 mb-1">
|
|
353
|
+
{SCHEDULER_FORM.UI.CLASS_DESCRIPTION_LABEL}
|
|
354
|
+
</label>
|
|
355
|
+
<textarea
|
|
356
|
+
id="classDescription"
|
|
357
|
+
placeholder={SCHEDULER_FORM.UI.CLASS_DESCRIPTION_PLACEHOLDER}
|
|
358
|
+
value={formData.classDescription}
|
|
359
|
+
onChange={(e) => setFormData({ ...formData, classDescription: e.target.value })}
|
|
360
|
+
className="w-full p-2 rounded bg-gray-700 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm min-h-[80px]"
|
|
361
|
+
/>
|
|
362
|
+
</div>
|
|
363
|
+
|
|
364
|
+
<div className="flex space-x-3">
|
|
365
|
+
<div className="flex flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-3">
|
|
366
|
+
<AddButton
|
|
367
|
+
type="submit"
|
|
368
|
+
disabled={isLoading}
|
|
369
|
+
>
|
|
370
|
+
{isLoading
|
|
371
|
+
? SCHEDULER_FORM.BUTTONS.SAVING_BUTTON
|
|
372
|
+
: formData.id
|
|
373
|
+
? SCHEDULER_FORM.BUTTONS.UPDATE_BUTTON
|
|
374
|
+
: SCHEDULER_FORM.BUTTONS.ADD_BUTTON}
|
|
375
|
+
</AddButton>
|
|
376
|
+
<CancelButton
|
|
377
|
+
type="button"
|
|
378
|
+
onClick={() => setIsModalOpen(false)}
|
|
379
|
+
>
|
|
380
|
+
{SCHEDULER_FORM.BUTTONS.CANCEL_BUTTON}
|
|
381
|
+
</CancelButton>
|
|
382
|
+
</div>
|
|
383
|
+
</div>
|
|
384
|
+
{error && <p className="text-red-400 text-sm font-medium">{error}</p>}
|
|
385
|
+
</form>
|
|
386
|
+
</div>
|
|
387
|
+
</motion.div>
|
|
388
|
+
)}
|
|
389
|
+
|
|
390
|
+
{/* Confirmation Popup for Delete */}
|
|
391
|
+
{isConfirmDeleteOpen && isAdmin && (
|
|
392
|
+
<motion.div
|
|
393
|
+
variants={modalVariants}
|
|
394
|
+
initial="hidden"
|
|
395
|
+
animate="visible"
|
|
396
|
+
exit="exit"
|
|
397
|
+
className="fixed inset-0 bg-black/90 flex items-center justify-center z-[10000] p-4 isolate"
|
|
398
|
+
onClick={handleCancelDelete}
|
|
399
|
+
>
|
|
400
|
+
<div
|
|
401
|
+
className="relative max-w-5xl w-full mx-4 p-6 bg-gray-800/50 border border-gray-700/50 rounded-lg shadow-lg"
|
|
402
|
+
onClick={(e) => e.stopPropagation()}
|
|
403
|
+
>
|
|
404
|
+
<CloseButton
|
|
405
|
+
onClick={handleCancelDelete}
|
|
406
|
+
>
|
|
407
|
+
<X className="h-6 w-6 sm:h-8 sm:w-8" />
|
|
408
|
+
</CloseButton>
|
|
409
|
+
<h3 className="text-xl font-bold text-white mb-4">{SCHEDULER_FORM.UI.DELETE_CONFIRMATION_HEADING}</h3>
|
|
410
|
+
<p className="text-gray-300 text-sm mb-4">{SCHEDULER_FORM.UI.DELETE_CONFIRMATION_MESSAGE}</p>
|
|
411
|
+
<div className="flex space-x-3">
|
|
412
|
+
<DeleteButton
|
|
413
|
+
onClick={handleConfirmDelete}
|
|
414
|
+
disabled={isLoading}
|
|
415
|
+
>
|
|
416
|
+
{isLoading ? SCHEDULER_FORM.BUTTONS.DELETING_BUTTON : SCHEDULER_FORM.BUTTONS.DELETE_BUTTON}
|
|
417
|
+
</DeleteButton>
|
|
418
|
+
<CancelButton
|
|
419
|
+
onClick={handleCancelDelete}
|
|
420
|
+
>
|
|
421
|
+
{SCHEDULER_FORM.BUTTONS.CANCEL_BUTTON}
|
|
422
|
+
</CancelButton>
|
|
423
|
+
</div>
|
|
424
|
+
</div>
|
|
425
|
+
</motion.div>
|
|
426
|
+
)}
|
|
427
|
+
</div>
|
|
428
|
+
);
|
|
429
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// components/addOns/functional/schedules/constants/scheduleGridTwo.ts
|
|
2
|
+
// Constants for hardcoded text in ScheduleGridTwo.tsx, organized by purpose
|
|
3
|
+
|
|
4
|
+
export const SCHEDULE_GRID_TWO = {
|
|
5
|
+
// UI Text for ScheduleGridTwo
|
|
6
|
+
UI: {
|
|
7
|
+
// Heading for schedule section
|
|
8
|
+
CLASS_SCHEDULE_HEADING: "Class Schedule",
|
|
9
|
+
// Text when no classes exist for a day
|
|
10
|
+
NO_CLASSES_MESSAGE: "No classes",
|
|
11
|
+
// Footer text before phone number
|
|
12
|
+
COMPLIMENTARY_CLASS_TEXT: "Your first class is complimentary! Questions? Call ",
|
|
13
|
+
// Phone number in footer link
|
|
14
|
+
PHONE_NUMBER: "315-415-4043",
|
|
15
|
+
// Footer disclaimer
|
|
16
|
+
SCHEDULE_DISCLAIMER: "*Management reserves the right to cancel or alter class schedules based on attendance.",
|
|
17
|
+
// Days of the week for headers
|
|
18
|
+
DAYS_OF_WEEK: [
|
|
19
|
+
"Monday",
|
|
20
|
+
"Tuesday",
|
|
21
|
+
"Wednesday",
|
|
22
|
+
"Thursday",
|
|
23
|
+
"Friday",
|
|
24
|
+
"Saturday",
|
|
25
|
+
"Sunday",
|
|
26
|
+
],
|
|
27
|
+
// Hardcoded age group for popup
|
|
28
|
+
ALL_AGES_TEXT: "All Ages",
|
|
29
|
+
// DeleteIconButton aria-label template
|
|
30
|
+
DELETE_BUTTON_ARIA: "Delete ${cls.name} class",
|
|
31
|
+
},
|
|
32
|
+
// Button Text for ScheduleGridTwo
|
|
33
|
+
BUTTONS: {
|
|
34
|
+
// AddButton text for adding new class
|
|
35
|
+
ADD_NEW_CLASS_BUTTON: "Add New Class",
|
|
36
|
+
},
|
|
37
|
+
// Error Messages for ScheduleGridTwo
|
|
38
|
+
ERRORS: {
|
|
39
|
+
// No hardcoded errors
|
|
40
|
+
},
|
|
41
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// components/addOns/functional/schedules/constants/scheduleGridTwoBasic.ts
|
|
2
|
+
// Constants for hardcoded text in ScheduleGridTwoBasic.tsx, organized by purpose
|
|
3
|
+
|
|
4
|
+
export const SCHEDULE_GRID_TWO_BASIC = {
|
|
5
|
+
// UI Text for ScheduleGridTwoBasic
|
|
6
|
+
UI: {
|
|
7
|
+
// Heading for schedule section
|
|
8
|
+
CLASS_SCHEDULE_HEADING: "Class Schedule",
|
|
9
|
+
// Text when no classes exist for a day
|
|
10
|
+
NO_CLASSES_MESSAGE: "No classes",
|
|
11
|
+
// Footer text before phone number
|
|
12
|
+
COMPLIMENTARY_CLASS_TEXT: "Your first class is complimentary! Questions? Call ",
|
|
13
|
+
// Phone number in footer link
|
|
14
|
+
PHONE_NUMBER: "315-415-4043",
|
|
15
|
+
// Footer disclaimer
|
|
16
|
+
SCHEDULE_DISCLAIMER: "*Management reserves the right to cancel or alter class schedules based on attendance.",
|
|
17
|
+
// Days of the week for headers
|
|
18
|
+
DAYS_OF_WEEK: [
|
|
19
|
+
"Monday",
|
|
20
|
+
"Tuesday",
|
|
21
|
+
"Wednesday",
|
|
22
|
+
"Thursday",
|
|
23
|
+
"Friday",
|
|
24
|
+
"Saturday",
|
|
25
|
+
"Sunday",
|
|
26
|
+
],
|
|
27
|
+
// Hardcoded age group for popup
|
|
28
|
+
ALL_AGES_TEXT: "All Ages",
|
|
29
|
+
// DeleteIconButton aria-label template
|
|
30
|
+
DELETE_BUTTON_ARIA: "Delete ${cls.name} class",
|
|
31
|
+
},
|
|
32
|
+
// Button Text for ScheduleGridTwoBasic
|
|
33
|
+
BUTTONS: {
|
|
34
|
+
// AddButton text for adding new class
|
|
35
|
+
ADD_NEW_CLASS_BUTTON: "Add New Class",
|
|
36
|
+
},
|
|
37
|
+
// Error Messages for ScheduleGridTwoBasic
|
|
38
|
+
ERRORS: {
|
|
39
|
+
// No hardcoded errors
|
|
40
|
+
},
|
|
41
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// components/addOns/functional/schedules/constants/schedulerForm.ts
|
|
2
|
+
// Constants for hardcoded text in Schedule.tsx (SchedulerForm), organized by purpose
|
|
3
|
+
|
|
4
|
+
export const SCHEDULER_FORM = {
|
|
5
|
+
// UI Text for SchedulerForm
|
|
6
|
+
UI: {
|
|
7
|
+
// Heading for edit class modal
|
|
8
|
+
EDIT_CLASS_HEADING: "Edit Class",
|
|
9
|
+
// Heading for add new class modal
|
|
10
|
+
ADD_NEW_CLASS_HEADING: "Add New Class",
|
|
11
|
+
// Label for class name input
|
|
12
|
+
CLASS_NAME_LABEL: "Class Name",
|
|
13
|
+
// Placeholder for class name input
|
|
14
|
+
CLASS_NAME_PLACEHOLDER: "Enter class name",
|
|
15
|
+
// Label for start time inputs
|
|
16
|
+
START_TIME_LABEL: "Start Time",
|
|
17
|
+
// Default option for hour select
|
|
18
|
+
HOUR_OPTION: "Hour",
|
|
19
|
+
// Default option for minute select
|
|
20
|
+
MINUTE_OPTION: "Minute",
|
|
21
|
+
// Options for period select
|
|
22
|
+
AM_OPTION: "AM",
|
|
23
|
+
PM_OPTION: "PM",
|
|
24
|
+
// Label for end time inputs
|
|
25
|
+
END_TIME_LABEL: "End Time",
|
|
26
|
+
// Label for days of week checkboxes
|
|
27
|
+
DAYS_OF_WEEK_LABEL: "Days of the Week",
|
|
28
|
+
// Checkbox labels for days of the week
|
|
29
|
+
DAYS_OF_WEEK: [
|
|
30
|
+
{ value: 1, label: "Monday" },
|
|
31
|
+
{ value: 2, label: "Tuesday" },
|
|
32
|
+
{ value: 3, label: "Wednesday" },
|
|
33
|
+
{ value: 4, label: "Thursday" },
|
|
34
|
+
{ value: 5, label: "Friday" },
|
|
35
|
+
{ value: 6, label: "Saturday" },
|
|
36
|
+
{ value: 7, label: "Sunday" },
|
|
37
|
+
],
|
|
38
|
+
// Label for class description textarea
|
|
39
|
+
CLASS_DESCRIPTION_LABEL: "Class Description (optional)",
|
|
40
|
+
// Placeholder for class description textarea
|
|
41
|
+
CLASS_DESCRIPTION_PLACEHOLDER: "Enter class description",
|
|
42
|
+
// Heading for delete confirmation modal
|
|
43
|
+
DELETE_CONFIRMATION_HEADING: "Confirm Deletion",
|
|
44
|
+
// Text in delete confirmation modal
|
|
45
|
+
DELETE_CONFIRMATION_MESSAGE: "Are you sure you want to delete this class? This action cannot be undone.",
|
|
46
|
+
},
|
|
47
|
+
// Button Text for SchedulerForm
|
|
48
|
+
BUTTONS: {
|
|
49
|
+
// AddButton text when loading
|
|
50
|
+
SAVING_BUTTON: "Saving...",
|
|
51
|
+
// AddButton text when editing a class
|
|
52
|
+
UPDATE_BUTTON: "Update",
|
|
53
|
+
// AddButton text when adding a new class
|
|
54
|
+
ADD_BUTTON: "Add",
|
|
55
|
+
// DeleteButton text when loading
|
|
56
|
+
DELETING_BUTTON: "Deleting...",
|
|
57
|
+
// DeleteButton text for delete confirmation
|
|
58
|
+
DELETE_BUTTON: "Delete",
|
|
59
|
+
// CancelButton text for both modals
|
|
60
|
+
CANCEL_BUTTON: "Cancel",
|
|
61
|
+
},
|
|
62
|
+
// Error Messages for SchedulerForm
|
|
63
|
+
ERRORS: {
|
|
64
|
+
// No hardcoded errors
|
|
65
|
+
},
|
|
66
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// components/addOns/functional/schedules/constants/scheduleGridOne.ts
|
|
2
|
+
// Constants for hardcoded text in ScheduleGridOne.tsx, organized by purpose
|
|
3
|
+
|
|
4
|
+
export const SCHEDULE_GRID_ONE = {
|
|
5
|
+
// UI Text for ScheduleGridOne
|
|
6
|
+
UI: {
|
|
7
|
+
// Label for search input
|
|
8
|
+
SEARCH_LABEL: "Search by Class Name",
|
|
9
|
+
// Placeholder for search input
|
|
10
|
+
SEARCH_PLACEHOLDER: "Search classes...",
|
|
11
|
+
// Label for time filter select
|
|
12
|
+
TIME_FILTER_LABEL: "Time of Day",
|
|
13
|
+
// Default option for time filter select
|
|
14
|
+
ALL_TIMES_OPTION: "All Times",
|
|
15
|
+
// Time filter options
|
|
16
|
+
MORNING_OPTION: "Morning (Before 12:00 PM)",
|
|
17
|
+
AFTERNOON_OPTION: "Afternoon (12:00 PM - 5:00 PM)",
|
|
18
|
+
EVENING_OPTION: "Evening (After 5:00 PM)",
|
|
19
|
+
// Heading for schedule section
|
|
20
|
+
CLASS_SCHEDULE_HEADING: "Class Schedule",
|
|
21
|
+
// Text when no classes exist for a day
|
|
22
|
+
NO_CLASSES_MESSAGE: "No classes",
|
|
23
|
+
// Footer text before phone number
|
|
24
|
+
COMPLIMENTARY_CLASS_TEXT: "Your first class is complimentary! Questions? Call ",
|
|
25
|
+
// Phone number in footer link
|
|
26
|
+
PHONE_NUMBER: "315-415-4043",
|
|
27
|
+
// Footer disclaimer
|
|
28
|
+
SCHEDULE_DISCLAIMER: "*Management reserves the right to cancel or alter class schedules based on attendance.",
|
|
29
|
+
// Days of the week for headers
|
|
30
|
+
DAYS_OF_WEEK: [
|
|
31
|
+
"Monday",
|
|
32
|
+
"Tuesday",
|
|
33
|
+
"Wednesday",
|
|
34
|
+
"Thursday",
|
|
35
|
+
"Friday",
|
|
36
|
+
"Saturday",
|
|
37
|
+
"Sunday",
|
|
38
|
+
],
|
|
39
|
+
// Hardcoded age group for popup
|
|
40
|
+
ALL_AGES_TEXT: "All Ages",
|
|
41
|
+
// DeleteIconButton aria-label template
|
|
42
|
+
DELETE_BUTTON_ARIA: "Delete ${cls.name} class",
|
|
43
|
+
},
|
|
44
|
+
// Button Text for ScheduleGridOne
|
|
45
|
+
BUTTONS: {
|
|
46
|
+
// SubmitButton text for resetting filters
|
|
47
|
+
RESET_FILTERS_BUTTON: "Reset Filters",
|
|
48
|
+
// AddButton text for adding new class
|
|
49
|
+
ADD_NEW_CLASS_BUTTON: "Add New Class",
|
|
50
|
+
},
|
|
51
|
+
// Error Messages for ScheduleGridOne
|
|
52
|
+
ERRORS: {
|
|
53
|
+
// No hardcoded errors
|
|
54
|
+
},
|
|
55
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { motion } from "framer-motion";
|
|
4
|
+
import { X } from "lucide-react";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
|
|
7
|
+
export default function AnnouncementBanner() {
|
|
8
|
+
const [isVisible, setIsVisible] = useState(true);
|
|
9
|
+
|
|
10
|
+
if (!isVisible) return null;
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<motion.div
|
|
14
|
+
className="fixed top-0 left-0 right-0 bg-blue-500/80 backdrop-blur-sm text-white py-3 sm:py-6 px-4 sm:px-6 z-50 shadow-md"
|
|
15
|
+
style={{
|
|
16
|
+
maskImage: "linear-gradient(to right, transparent 0%, black 20%, black 80%, transparent 100%)",
|
|
17
|
+
WebkitMaskImage: "linear-gradient(to right, transparent 0%, black 20%, black 80%, transparent 100%)",
|
|
18
|
+
}}
|
|
19
|
+
initial={{ y: -100, opacity: 0 }}
|
|
20
|
+
animate={{ y: 0, opacity: 1 }}
|
|
21
|
+
exit={{ y: -100, opacity: 0 }}
|
|
22
|
+
transition={{ duration: 0.5, ease: "easeOut" }}
|
|
23
|
+
>
|
|
24
|
+
<div className="max-w-7xl mx-auto flex items-center justify-between relative pr-10 sm:pr-14">
|
|
25
|
+
<p className="text-xs sm:text-sm md:text-base font-medium text-center flex-1">
|
|
26
|
+
We will be closed this Friday and Saturday (July 4–5) in observance of Independence Day.
|
|
27
|
+
</p>
|
|
28
|
+
<button
|
|
29
|
+
onClick={() => setIsVisible(false)}
|
|
30
|
+
className="absolute right-2 sm:right-4 bg-blue-600/50 hover:bg-blue-700/70 text-white rounded-full p-1.5 sm:p-2 focus:outline-none focus:ring-2 focus:ring-blue-300 transition-colors"
|
|
31
|
+
aria-label="Close announcement"
|
|
32
|
+
>
|
|
33
|
+
<X className="w-5 h-5 sm:w-8 sm:h-8" />
|
|
34
|
+
</button>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<style jsx>{`
|
|
38
|
+
.gradient-text {
|
|
39
|
+
background: linear-gradient(45deg, #80ff80 25%, #80ff80 50%, #00b7eb 85%, #00b7eb 75%);
|
|
40
|
+
-webkit-background-clip: text;
|
|
41
|
+
background-clip: text;
|
|
42
|
+
color: transparent;
|
|
43
|
+
}
|
|
44
|
+
`}</style>
|
|
45
|
+
</motion.div>
|
|
46
|
+
);
|
|
47
|
+
}
|