@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,149 @@
|
|
|
1
|
+
import React, { useState, useEffect, useRef } from "react";
|
|
2
|
+
import { useRouter } from "next/navigation";
|
|
3
|
+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/other/card";
|
|
4
|
+
import { Calendar } from "lucide-react";
|
|
5
|
+
import Spinner from "@/components/addOns/non-functional/spinner";
|
|
6
|
+
import { BLOG_LIST } from "./constants/blogList";
|
|
7
|
+
|
|
8
|
+
interface BlogPost {
|
|
9
|
+
id: number;
|
|
10
|
+
documentId: string;
|
|
11
|
+
title: string;
|
|
12
|
+
description: string;
|
|
13
|
+
author: string;
|
|
14
|
+
publishedAt: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default function BlogList() {
|
|
18
|
+
const router = useRouter();
|
|
19
|
+
const [posts, setPosts] = useState<BlogPost[]>([]);
|
|
20
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
21
|
+
const [error, setError] = useState<string | null>(null);
|
|
22
|
+
const [isMobile, setIsMobile] = useState(false);
|
|
23
|
+
const hasFetched = useRef(false);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const handleResize = () => {
|
|
27
|
+
setIsMobile(window.innerWidth < 640);
|
|
28
|
+
};
|
|
29
|
+
handleResize();
|
|
30
|
+
window.addEventListener("resize", handleResize);
|
|
31
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
32
|
+
}, []);
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (hasFetched.current) return;
|
|
36
|
+
hasFetched.current = true;
|
|
37
|
+
|
|
38
|
+
const fetchPosts = async () => {
|
|
39
|
+
setIsLoading(true);
|
|
40
|
+
try {
|
|
41
|
+
const response = await fetch("/api/blog", {
|
|
42
|
+
headers: { "Content-Type": "application/json" },
|
|
43
|
+
cache: "no-store",
|
|
44
|
+
});
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
const errorData = await response.json();
|
|
47
|
+
throw new Error(errorData.error || BLOG_LIST.ERRORS.FETCH_FAILED);
|
|
48
|
+
}
|
|
49
|
+
const { data } = await response.json();
|
|
50
|
+
const blogPosts = data.blogPosts.map((p: BlogPost) => ({
|
|
51
|
+
...p,
|
|
52
|
+
publishedAt: new Date(p.publishedAt).toISOString(),
|
|
53
|
+
}));
|
|
54
|
+
setPosts(blogPosts);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
setError(err instanceof Error ? err.message : BLOG_LIST.ERRORS.UNKNOWN_ERROR);
|
|
57
|
+
} finally {
|
|
58
|
+
setIsLoading(false);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
fetchPosts();
|
|
62
|
+
}, []);
|
|
63
|
+
|
|
64
|
+
const truncateText = (text: string, field: "title" | "description" | "authorDate"): string => {
|
|
65
|
+
const maxLength = isMobile ? (field === "authorDate" ? 30 : 20) : 50;
|
|
66
|
+
if (text.length <= maxLength) return text;
|
|
67
|
+
return text.slice(0, maxLength - 3) + "...";
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
if (isLoading) {
|
|
71
|
+
return (
|
|
72
|
+
<div className="py-8 text-center">
|
|
73
|
+
<Spinner />
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<div className="w-full bg-[#1E2A44] border-none outline-none z-0 px-0 py-8 sm:px-6 sm:py-16 md:p-8">
|
|
80
|
+
<style jsx>{`
|
|
81
|
+
.file-item {
|
|
82
|
+
z-index: 30;
|
|
83
|
+
pointer-events: auto;
|
|
84
|
+
cursor: pointer;
|
|
85
|
+
}
|
|
86
|
+
`}</style>
|
|
87
|
+
<section className="relative z-10">
|
|
88
|
+
<div className="w-full max-w-7xl mx-auto">
|
|
89
|
+
<Card className="w-full max-w-7xl mx-auto p-4 sm:p-8 text-white flex flex-col items-center space-y-6 bg-[#1E2A44] border-none rounded-none">
|
|
90
|
+
<CardHeader className="pb-4 text-center">
|
|
91
|
+
<CardTitle className="text-2xl sm:text-3xl md:text-4xl font-bold tracking-tight text-white">
|
|
92
|
+
{BLOG_LIST.UI.CARD_TITLE}
|
|
93
|
+
</CardTitle>
|
|
94
|
+
<p className="text-gray-300 text-base sm:text-lg md:text-xl">
|
|
95
|
+
{BLOG_LIST.UI.CARD_DESCRIPTION}
|
|
96
|
+
</p>
|
|
97
|
+
</CardHeader>
|
|
98
|
+
<CardContent className="w-full space-y-4">
|
|
99
|
+
{error && (
|
|
100
|
+
<p className="text-red-400 text-base sm:text-lg md:text-xl text-center">
|
|
101
|
+
{error}
|
|
102
|
+
</p>
|
|
103
|
+
)}
|
|
104
|
+
{posts.length > 0 ? (
|
|
105
|
+
<div className="space-y-4 max-h-[400px] overflow-y-auto">
|
|
106
|
+
{posts.map((post) => (
|
|
107
|
+
<div
|
|
108
|
+
key={post.id}
|
|
109
|
+
className="file-item w-full flex flex-col sm:flex-row items-start sm:items-center justify-between p-3 sm:p-4 rounded-lg bg-[#2A3A66]/50 hover:bg-[#2A3A66]/70 hover:shadow-lg hover:border-[#FF69B4]/50 transition-all cursor-pointer"
|
|
110
|
+
onClick={() => router.push(`/blog/${post.id}`)}
|
|
111
|
+
role="link"
|
|
112
|
+
aria-label={`View post: ${post.title}`}
|
|
113
|
+
>
|
|
114
|
+
<div className="flex flex-col w-full">
|
|
115
|
+
<h4 className="font-bold text-base sm:text-lg md:text-xl text-white mb-1 truncate">
|
|
116
|
+
{truncateText(post.title, "title")}
|
|
117
|
+
</h4>
|
|
118
|
+
<div className="flex items-center gap-2 text-sm text-gray-300">
|
|
119
|
+
<Calendar className="h-4 w-4 sm:h-5 sm:w-5 text-[#FF69B4] flex-shrink-0" />
|
|
120
|
+
<span>
|
|
121
|
+
{truncateText(
|
|
122
|
+
`By ${post.author} | ${new Date(post.publishedAt).toLocaleDateString("en-US", {
|
|
123
|
+
year: "numeric",
|
|
124
|
+
month: "short",
|
|
125
|
+
day: "numeric",
|
|
126
|
+
})}`,
|
|
127
|
+
"authorDate"
|
|
128
|
+
)}
|
|
129
|
+
</span>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
{/* <p className="text-sm text-gray-300 mt-2 sm:mt-0 sm:ml-4 w-full sm:w-auto flex-1 truncate">
|
|
133
|
+
{truncateText(post.description, "description")}
|
|
134
|
+
</p> */}
|
|
135
|
+
</div>
|
|
136
|
+
))}
|
|
137
|
+
</div>
|
|
138
|
+
) : (
|
|
139
|
+
<p className="text-gray-300 font-bold text-base sm:text-lg md:text-xl text-center">
|
|
140
|
+
{BLOG_LIST.UI.NO_POSTS_MESSAGE}
|
|
141
|
+
</p>
|
|
142
|
+
)}
|
|
143
|
+
</CardContent>
|
|
144
|
+
</Card>
|
|
145
|
+
</div>
|
|
146
|
+
</section>
|
|
147
|
+
</div>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import Link from "next/link";
|
|
5
|
+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/other/card";
|
|
6
|
+
import { BLOG_SIDEBAR } from "./constants/blogSidebar";
|
|
7
|
+
|
|
8
|
+
interface BlogPost {
|
|
9
|
+
id: number;
|
|
10
|
+
documentId: string;
|
|
11
|
+
title: string;
|
|
12
|
+
description: string;
|
|
13
|
+
author: string;
|
|
14
|
+
publishedAt: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface BlogSidebarProps {
|
|
18
|
+
posts: BlogPost[];
|
|
19
|
+
currentPostId: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default function BlogSidebar({ posts, currentPostId }: BlogSidebarProps) {
|
|
23
|
+
const otherPosts = posts
|
|
24
|
+
.filter((post) => post.id !== currentPostId)
|
|
25
|
+
.sort((a, b) => new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime())
|
|
26
|
+
.slice(0, 5);
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Card className="w-full max-w-xs min-h-[300px] rounded-2xl border border-gray-700/50 bg-gray-800/50 backdrop-blur-md shadow-lg hover:border-blue-500/50 transition-colors">
|
|
30
|
+
<CardHeader className="pb-4">
|
|
31
|
+
<CardTitle className="text-lg font-bold text-white">{BLOG_SIDEBAR.UI.CARD_TITLE}</CardTitle>
|
|
32
|
+
</CardHeader>
|
|
33
|
+
<CardContent className="p-6">
|
|
34
|
+
{otherPosts.length > 0 ? (
|
|
35
|
+
<ul className="space-y-4">
|
|
36
|
+
{otherPosts.map((post) => (
|
|
37
|
+
<li key={post.id}>
|
|
38
|
+
<Link href={`/blog/${post.id}`} className="text-gray-200 hover:text-blue-400 transition-colors">
|
|
39
|
+
<span className="font-medium text-blue-300 block truncate">
|
|
40
|
+
{post.title}
|
|
41
|
+
</span>
|
|
42
|
+
<div className="text-sm text-white">
|
|
43
|
+
{new Date(post.publishedAt).toLocaleDateString("en-US", {
|
|
44
|
+
year: "numeric",
|
|
45
|
+
month: "long",
|
|
46
|
+
day: "numeric",
|
|
47
|
+
})}
|
|
48
|
+
</div>
|
|
49
|
+
</Link>
|
|
50
|
+
</li>
|
|
51
|
+
))}
|
|
52
|
+
</ul>
|
|
53
|
+
) : (
|
|
54
|
+
<p className="text-gray-400 text-sm font-medium">{BLOG_SIDEBAR.UI.NO_POSTS_MESSAGE}</p>
|
|
55
|
+
)}
|
|
56
|
+
</CardContent>
|
|
57
|
+
</Card>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// components/addOns/functional/blogSections/constants/blogDashboard.ts
|
|
2
|
+
// Constants for hardcoded text in BlogDashboard.tsx, organized by purpose
|
|
3
|
+
|
|
4
|
+
export const BLOG_DASHBOARD = {
|
|
5
|
+
// UI Text for BlogDashboard
|
|
6
|
+
UI: {
|
|
7
|
+
// Card title
|
|
8
|
+
CARD_TITLE: "Blog Posts",
|
|
9
|
+
// Card description
|
|
10
|
+
CARD_DESCRIPTION: "View and manage your recent blog posts",
|
|
11
|
+
// Success message for blog post submission
|
|
12
|
+
SUCCESS_MESSAGE: "Blog post submitted successfully!",
|
|
13
|
+
// Text when no blog posts exist
|
|
14
|
+
NO_POSTS_MESSAGE: "No blog posts yet",
|
|
15
|
+
// Subtext when no blog posts exist
|
|
16
|
+
NO_POSTS_SUBTEXT: "Submit your first blog post to get started",
|
|
17
|
+
},
|
|
18
|
+
// Button Text for BlogDashboard
|
|
19
|
+
BUTTONS: {
|
|
20
|
+
// AddButton text
|
|
21
|
+
ADD_BUTTON: "Add New Post",
|
|
22
|
+
// EditButton aria-label template
|
|
23
|
+
EDIT_BUTTON_ARIA: "Edit ${post.title}",
|
|
24
|
+
// TrashButton aria-label template
|
|
25
|
+
DELETE_BUTTON_ARIA: "Delete ${post.title}",
|
|
26
|
+
},
|
|
27
|
+
// Error Messages for BlogDashboard
|
|
28
|
+
ERRORS: {}, // No direct errors in JSX
|
|
29
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// components/addOns/functional/blogSections/constants/blogFormPopUp.ts
|
|
2
|
+
// Constants for hardcoded text in BlogFormPopUp.tsx, organized by purpose
|
|
3
|
+
|
|
4
|
+
export const BLOG_FORM_POP_UP = {
|
|
5
|
+
// UI Text for BlogFormPopUp
|
|
6
|
+
UI: {
|
|
7
|
+
// Modal heading when editing
|
|
8
|
+
EDIT_MODAL_HEADING: "Edit Blog Post",
|
|
9
|
+
// Modal heading when adding
|
|
10
|
+
ADD_MODAL_HEADING: "Add New Blog Post",
|
|
11
|
+
// Label for title input
|
|
12
|
+
TITLE_LABEL: "Title",
|
|
13
|
+
// Placeholder for title input
|
|
14
|
+
TITLE_PLACEHOLDER: "Enter post title",
|
|
15
|
+
// Title character and word count template
|
|
16
|
+
TITLE_COUNT_TEXT: "${titleCharCount}/50 characters, ${titleWordCount} words",
|
|
17
|
+
// Label for author input
|
|
18
|
+
AUTHOR_LABEL: "Author",
|
|
19
|
+
// Label for description textarea
|
|
20
|
+
DESCRIPTION_LABEL: "Description",
|
|
21
|
+
// Placeholder for description textarea
|
|
22
|
+
DESCRIPTION_PLACEHOLDER: "Enter post description",
|
|
23
|
+
// Description character and word count template
|
|
24
|
+
DESCRIPTION_COUNT_TEXT: "${descriptionCharCount}/1500 characters, ${descriptionWordCount} words",
|
|
25
|
+
// ToggleButton text when keywords are shown
|
|
26
|
+
HIDE_KEYWORDS_BUTTON: "Hide Keywords",
|
|
27
|
+
// ToggleButton text when keywords are hidden
|
|
28
|
+
SHOW_KEYWORDS_BUTTON: "Show SEO Keywords",
|
|
29
|
+
// SEO keywords for form
|
|
30
|
+
SEO_KEYWORDS: [
|
|
31
|
+
"fitness training",
|
|
32
|
+
"gym workout plans",
|
|
33
|
+
"strength exercises",
|
|
34
|
+
"cardio routines",
|
|
35
|
+
"weight loss tips",
|
|
36
|
+
"muscle building",
|
|
37
|
+
"home workouts",
|
|
38
|
+
"personal trainer",
|
|
39
|
+
"fitness motivation",
|
|
40
|
+
"healthy lifestyle",
|
|
41
|
+
"gym equipment",
|
|
42
|
+
"bodybuilding tips",
|
|
43
|
+
"HIIT workouts",
|
|
44
|
+
"nutrition for fitness",
|
|
45
|
+
"exercise routines",
|
|
46
|
+
],
|
|
47
|
+
// Aria-label for keyword list items
|
|
48
|
+
KEYWORD_ARIA: "Insert keyword: ${keyword}",
|
|
49
|
+
// Chatbot heading
|
|
50
|
+
CHATBOT_HEADING: "AI Chatbot is coming soon!",
|
|
51
|
+
// Chatbot input placeholder
|
|
52
|
+
CHATBOT_PLACEHOLDER: "Ask for suggestions...",
|
|
53
|
+
// Delete confirmation modal heading
|
|
54
|
+
DELETE_MODAL_HEADING: "Confirm Deletion",
|
|
55
|
+
// Delete confirmation message
|
|
56
|
+
DELETE_CONFIRMATION_TEXT: "Are you sure you want to delete the post "${postToDelete.title}"? This action cannot be undone.",
|
|
57
|
+
// System prompt for chatbot
|
|
58
|
+
CHATBOT_SYSTEM_PROMPT: "You are an AI assistant helping with blog writing and SEO optimization. You are aware of the current blog post's title: \"${formData.title}\", description: \"${formData.description}\", and the following SEO keywords: ${seoKeywords.join(', ')}. Provide suggestions to improve the blog post's SEO, such as keyword usage, content structure, or meta descriptions. Respond concisely and relevantly to user queries.",
|
|
59
|
+
},
|
|
60
|
+
// Button Text for BlogFormPopUp
|
|
61
|
+
BUTTONS: {
|
|
62
|
+
// UpdateButton text when loading
|
|
63
|
+
SAVING_BUTTON: "Saving...",
|
|
64
|
+
// UpdateButton text when editing
|
|
65
|
+
UPDATE_BUTTON: "Update",
|
|
66
|
+
// UpdateButton text when adding
|
|
67
|
+
SUBMIT_BUTTON: "Submit",
|
|
68
|
+
// CancelButton text
|
|
69
|
+
CANCEL_BUTTON: "Cancel",
|
|
70
|
+
// ChatToggleButton aria-label when open
|
|
71
|
+
CLOSE_CHATBOT_ARIA: "Close AI chatbot",
|
|
72
|
+
// ChatToggleButton aria-label when closed
|
|
73
|
+
OPEN_CHATBOT_ARIA: "Open AI chatbot",
|
|
74
|
+
// DeleteButton text when loading
|
|
75
|
+
DELETING_BUTTON: "Deleting...",
|
|
76
|
+
// DeleteButton text
|
|
77
|
+
DELETE_BUTTON: "Delete",
|
|
78
|
+
},
|
|
79
|
+
// Error Messages for BlogFormPopUp
|
|
80
|
+
ERRORS: {
|
|
81
|
+
// Error when textarea is not initialized
|
|
82
|
+
TEXTAREA_NOT_INITIALIZED: "Text area not initialized",
|
|
83
|
+
// Error when authentication is loading
|
|
84
|
+
AUTH_LOADING: "Authentication is still loading, please wait...",
|
|
85
|
+
// Error when not signed in
|
|
86
|
+
NOT_SIGNED_IN: "You must be signed in to create or edit a blog post",
|
|
87
|
+
// Warning when business title is missing
|
|
88
|
+
NO_BUSINESS_TITLE: "Business title not found; using username or default author name",
|
|
89
|
+
// Error for incomplete form
|
|
90
|
+
REQUIRED_FIELDS: "Please fill in all required fields",
|
|
91
|
+
// Error when delete fails
|
|
92
|
+
DELETE_FAILED: "Failed to delete blog post",
|
|
93
|
+
// Generic error for delete and submit
|
|
94
|
+
UNKNOWN_ERROR: "An unknown error occurred",
|
|
95
|
+
// Error when submit fails
|
|
96
|
+
SUBMIT_FAILED: "Failed to submit blog post",
|
|
97
|
+
},
|
|
98
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// components/addOns/functional/blogSections/constants/blogList.ts
|
|
2
|
+
// Constants for hardcoded text in BlogList.tsx, organized by purpose
|
|
3
|
+
|
|
4
|
+
export const BLOG_LIST = {
|
|
5
|
+
// UI Text for BlogList
|
|
6
|
+
UI: {
|
|
7
|
+
// Card title
|
|
8
|
+
CARD_TITLE: "Latest Blog Posts",
|
|
9
|
+
// Card header description
|
|
10
|
+
CARD_DESCRIPTION: "Discover our latest tips and updates",
|
|
11
|
+
// Text when no blog posts exist
|
|
12
|
+
NO_POSTS_MESSAGE: "No blog posts yet. Check back soon for new updates!",
|
|
13
|
+
},
|
|
14
|
+
// Button Text for BlogList
|
|
15
|
+
BUTTONS: {}, // No buttons in JSX
|
|
16
|
+
// Error Messages for BlogList
|
|
17
|
+
ERRORS: {
|
|
18
|
+
// Error when fetch fails
|
|
19
|
+
FETCH_FAILED: "Failed to fetch blog posts",
|
|
20
|
+
// Generic error for fetch
|
|
21
|
+
UNKNOWN_ERROR: "An unknown error occurred",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// components/addOns/functional/blogSections/constants/blogSidebar.ts
|
|
2
|
+
// Constants for hardcoded text in BlogSidebar.tsx, organized by purpose
|
|
3
|
+
|
|
4
|
+
export const BLOG_SIDEBAR = {
|
|
5
|
+
// UI Text for BlogSidebar
|
|
6
|
+
UI: {
|
|
7
|
+
// Card title
|
|
8
|
+
CARD_TITLE: "Other Blog Posts",
|
|
9
|
+
// Text when no other posts exist
|
|
10
|
+
NO_POSTS_MESSAGE: "No other posts available.",
|
|
11
|
+
},
|
|
12
|
+
// Button Text for BlogSidebar
|
|
13
|
+
BUTTONS: {}, // No buttons in JSX
|
|
14
|
+
// Error Messages for BlogSidebar
|
|
15
|
+
ERRORS: {}, // No errors in JSX
|
|
16
|
+
};
|