'use client' import { useRouter } from 'next/navigation' import { useMediaQuery } from 'usehooks-ts' import { ChevronLeft, ChevronRight } from 'lucide-react' import { getUriWithOrg } from '@services/config/config' import React from 'react' interface ActivityNavigationProps { course: any currentActivityId: string orgslug: string } export default function ActivityNavigation(props: ActivityNavigationProps): React.ReactNode { const router = useRouter(); const isMobile = useMediaQuery('(max-width: 768px)'); const [isBottomNavVisible, setIsBottomNavVisible] = React.useState(true); const bottomNavRef = React.useRef(null); const [navWidth, setNavWidth] = React.useState(null); // Function to find the current activity's position in the course const findActivityPosition = () => { let allActivities: any[] = []; let currentIndex = -1; // Flatten all activities from all chapters props.course.chapters.forEach((chapter: any) => { chapter.activities.forEach((activity: any) => { const cleanActivityUuid = activity.activity_uuid?.replace('activity_', ''); allActivities.push({ ...activity, cleanUuid: cleanActivityUuid, chapterName: chapter.name }); // Check if this is the current activity if (cleanActivityUuid === props.currentActivityId.replace('activity_', '')) { currentIndex = allActivities.length - 1; } }); }); return { allActivities, currentIndex }; }; const { allActivities, currentIndex } = findActivityPosition(); // Get previous and next activities const prevActivity = currentIndex > 0 ? allActivities[currentIndex - 1] : null; const nextActivity = currentIndex < allActivities.length - 1 ? allActivities[currentIndex + 1] : null; // Navigate to an activity const navigateToActivity = (activity: any) => { if (!activity) return; const cleanCourseUuid = props.course.course_uuid?.replace('course_', ''); router.push(getUriWithOrg(props.orgslug, '') + `/course/${cleanCourseUuid}/activity/${activity.cleanUuid}`); }; // Set up intersection observer to detect when bottom nav is out of viewport // and measure the width of the bottom navigation React.useEffect(() => { if (!bottomNavRef.current) return; // Update width when component mounts and on window resize const updateWidth = () => { if (bottomNavRef.current) { setNavWidth(bottomNavRef.current.offsetWidth); } }; // Initial width measurement updateWidth(); // Set up resize listener window.addEventListener('resize', updateWidth); const observer = new IntersectionObserver( ([entry]) => { setIsBottomNavVisible(entry.isIntersecting); }, { threshold: 0.1 } ); observer.observe(bottomNavRef.current); return () => { window.removeEventListener('resize', updateWidth); if (bottomNavRef.current) { observer.unobserve(bottomNavRef.current); } }; }, []); // Navigation buttons component - reused for both top and bottom const NavigationButtons = ({ isFloating = false }) => (
{isFloating ? ( // Floating navigation - original flex layout <> ) : ( // Regular navigation - grid layout with centered counter <>
{currentIndex + 1} of {allActivities.length}
)}
); return ( <> {/* Bottom navigation (in-place) */}
{/* Floating bottom navigation - shown when bottom nav is not visible */} {!isBottomNavVisible && (
)} ); }