"use client"; import { useEffect, useRef, useState } from "react"; import { useTranslations } from "next-intl"; import clsx from "clsx"; import { Icon, IconName, Typography } from "@/components/ui"; import { useDynamicSize } from "@/hooks/DOM/useDynamicSize"; import styles from "./Progress.module.scss"; interface IProgressProps { items: string[]; activeItemIndex: number; } export default function Progress({ items, activeItemIndex }: IProgressProps) { const t = useTranslations("AdditionalPurchases.Progress"); const { width: containerWidth, elementRef } = useDynamicSize({ defaultWidth: 327, }); const wrapperRef = useRef(null); const [isScrolled, setIsScrolled] = useState(false); const [containerHeight, setContainerHeight] = useState(0); // Всегда добавляем финальный пункт в конец const finalStep = t("final_step"); const allItems = [...items, finalStep]; // Фиксированные отступы от краев (центр кружочка = 50px от края) const edgeOffset = 50; // 50px от края до центра кружочка const totalItems = allItems.length; // Рассчитываем позицию каждого элемента с равными отступами const calculateItemPosition = (index: number) => { if (totalItems === 1) return 50; // Центрируем если один элемент // Распределяем элементы равномерно между краями const availableWidth = containerWidth - (edgeOffset * 2); const spacing = availableWidth / (totalItems - 1); return edgeOffset + (spacing * index); }; // Динамическое определение высоты контейнера useEffect(() => { if (elementRef.current) { // Находим все элементы прогресс бара const items = elementRef.current.querySelectorAll(`.${styles.item}`); let maxHeight = 0; items.forEach((item) => { const height = (item as HTMLElement).offsetHeight; if (height > maxHeight) { maxHeight = height; } }); setContainerHeight(maxHeight); } }, [allItems, containerWidth]); // Отслеживаем скролл для появления фона useEffect(() => { const handleScroll = () => { if (wrapperRef.current) { const rect = wrapperRef.current.getBoundingClientRect(); // Показываем фон только когда элемент прокручен вверх (скроллится) // При начальной загрузке top будет около 0, но мы проверяем window.scrollY const hasScrolled = window.scrollY > 0 && rect.top <= 1; setIsScrolled(hasScrolled); } }; window.addEventListener("scroll", handleScroll, { passive: true }); // При монтировании проверяем - если страница уже прокручена handleScroll(); return () => window.removeEventListener("scroll", handleScroll); }, []); return (
0 ? `${containerHeight}px` : undefined, }} > {allItems.map((item, index) => { const itemPosition = calculateItemPosition(index); return (
index && styles.done )} style={{ left: `${itemPosition}px`, transform: 'translateX(-50%)', // Центрируем относительно позиции }} >
{activeItemIndex > index && styles.done && ( )} {index + 1}
{item}
); })}
0 ? `linear-gradient( 90deg, #2866ed 0%, #2866ed ${((activeItemIndex) / (totalItems - 1)) * 100}%, #E2E8F0 ${((activeItemIndex) / (totalItems - 1)) * 100}%, #E2E8F0 100% )` : "#E2E8F0", }} />
); }