diff --git a/apps/frontend/app/[locale]/page.tsx b/apps/frontend/app/[locale]/page.tsx index 262c40c..895f078 100644 --- a/apps/frontend/app/[locale]/page.tsx +++ b/apps/frontend/app/[locale]/page.tsx @@ -27,6 +27,7 @@ import { import { useTranslations, useLocale } from 'next-intl'; import { useAuth } from '@/lib/context/auth-context'; import { LandingHeader, LandingFooter } from '@/components/layout'; +import { DemoVideoModal } from '@/components/DemoVideoModal'; function AnimatedCounter({ end, @@ -96,6 +97,7 @@ export default function LandingPage() { const isHowInView = useInView(howRef, { once: true, amount: 0.2 }); const [billingYearly, setBillingYearly] = useState(false); + const [isDemoOpen, setIsDemoOpen] = useState(false); const { scrollYProgress } = useScroll(); const backgroundY = useTransform(scrollYProgress, [0, 1], ['0%', '50%']); @@ -374,26 +376,23 @@ export default function LandingPage() { ) : ( - <> - - {t('hero.ctaRegister')} - - - - {t('hero.ctaDemo')} - - + + {t('hero.ctaRegister')} + + )} + @@ -1076,6 +1075,8 @@ export default function LandingPage() { + + setIsDemoOpen(false)} /> ); } diff --git a/apps/frontend/public/assets/videos/demo-xpeditis.mp4 b/apps/frontend/public/assets/videos/demo-xpeditis.mp4 new file mode 100644 index 0000000..8788246 Binary files /dev/null and b/apps/frontend/public/assets/videos/demo-xpeditis.mp4 differ diff --git a/apps/frontend/public/assets/videos/demo-xpeditis.webm b/apps/frontend/public/assets/videos/demo-xpeditis.webm new file mode 100644 index 0000000..3578c55 Binary files /dev/null and b/apps/frontend/public/assets/videos/demo-xpeditis.webm differ diff --git a/apps/frontend/src/components/DemoVideoModal.tsx b/apps/frontend/src/components/DemoVideoModal.tsx new file mode 100644 index 0000000..e6813d6 --- /dev/null +++ b/apps/frontend/src/components/DemoVideoModal.tsx @@ -0,0 +1,74 @@ +'use client'; + +import { useEffect, useCallback } from 'react'; +import { createPortal } from 'react-dom'; +import { motion, AnimatePresence } from 'framer-motion'; +import { X } from 'lucide-react'; + +interface DemoVideoModalProps { + isOpen: boolean; + onClose: () => void; +} + +export function DemoVideoModal({ isOpen, onClose }: DemoVideoModalProps) { + const handleKeyDown = useCallback( + (e: KeyboardEvent) => { + if (e.key === 'Escape') onClose(); + }, + [onClose] + ); + + useEffect(() => { + if (!isOpen) return; + document.addEventListener('keydown', handleKeyDown); + document.body.style.overflow = 'hidden'; + return () => { + document.removeEventListener('keydown', handleKeyDown); + document.body.style.overflow = ''; + }; + }, [isOpen, handleKeyDown]); + + if (typeof document === 'undefined') return null; + + return createPortal( + + {isOpen && ( + + e.stopPropagation()} + > + +
+ +
+
+
+ )} +
, + document.body + ); +}