feat: add loader for image and video on prime

This commit is contained in:
2025-03-28 18:16:26 +05:00
parent 90efe1aac9
commit e3c79a31aa
5 changed files with 57 additions and 11 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 52 KiB

@@ -13,12 +13,15 @@ import {
incrementRemote,
} from '@/stores/configurator-store/configurationStore';
import { Details, Ads, Remote } from '@/types/IConfigurator';
import { useEffect, useRef, useState } from 'react';
import LoaderIcon from '../../../../public/icons/loader.svg';
function CategoryCounter({
titleCategory,
}: {
titleCategory: keyof typeof categories;
}) {
const [isLoading, setIsLoading] = useState(true);
const configuration = useUnit($configurationStore);
const arrayCounters = categories[titleCategory];
const isAdvertisementMaterials =
@@ -28,6 +31,7 @@ function CategoryCounter({
Array.isArray(arrayCounters) && isAdvertisementMaterials
? arrayCounters
: [arrayCounters];
const preloaded = useRef(new Set());
function handleIncrement(index: number) {
if (titleCategory === 'Детальная проработка окружения') {
@@ -49,6 +53,28 @@ function CategoryCounter({
}
}
useEffect(() => {
const imageSizes = ['250', '500', '1000', 'без ограничений'];
let loadedCount = 0;
imageSizes.forEach((size) => {
if (!preloaded.current.has(size)) {
const img = new Image();
img.src = `/img/pages/prime/details/details${size.replace(
' ',
'_'
)}.jpg`;
img.onload = () => {
loadedCount++;
if (loadedCount === imageSizes.length) {
setIsLoading(false);
}
};
preloaded.current.add(size);
}
});
}, []);
return (
<div className={`flex gap-1 flex-row flex-shrink-0`}>
{counterItems.map((item, index) => {
@@ -62,7 +88,7 @@ function CategoryCounter({
return (
<div key={index} className={`flex flex-col gap-0.5 flex-1`}>
<div
className={`w-full rounded-t-2xl ${
className={`relative w-full rounded-t-2xl ${
titleCategory === 'Рекламные материалы'
? 'h-[169px]'
: 'h-[162px]'
@@ -86,6 +112,14 @@ function CategoryCounter({
},
})}
>
{isLoading &&
titleCategory === 'Детальная проработка окружения' && (
<div className='absolute rounded-t-2xl top-0 left-0 w-full h-full bg-black/50 flex items-center justify-center text-white'>
<div className='flex gap-4 items-center'>
<LoaderIcon className='animate-spin h-9 w-9' />
</div>
</div>
)}
{typeof item === 'object' && 'name' in item && (
<p className='mt-auto btns'>{item.name}</p>
)}
@@ -66,10 +66,6 @@ function CategoryModal({
};
}, []);
const handleClose = () => {
setModal(false);
};
return (
<div
className={`fixed inset-0 bg-[#0F1011] z-[1] px-2.5 py-4 flex flex-col gap-5 h-full w-full md:p-10 md:gap-10`}
@@ -5,9 +5,14 @@ import { categories } from '@/consts/categories';
import { Title } from '@/ui/Title';
import { Variants } from '@/types/types';
import PrimeForm from './PrimeForm';
import { useEffect } from 'react';
function PrimePageMobile() {
const categoriesArray: [string, Variants][] = Object.entries(categories);
useEffect(() => {
const img = new Image();
img.src = `/img/pages/home/presentation/touch_screen.png`;
});
return (
<div className='lg:hidden space-y-12'>
@@ -1,6 +1,10 @@
import { motion } from 'framer-motion';
import { useEffect, useState } from 'react';
import LoaderIcon from '../../../../public/icons/loader.svg';
function VideoPrimeModal({ src }: { src: string }) {
const [buffering, setBuffering] = useState(true);
return (
<motion.div
style={{
@@ -17,15 +21,22 @@ function VideoPrimeModal({ src }: { src: string }) {
loop
muted
playsInline
// style={{
// width: '39.822vw',
// height: '19vw',
// top: '3.602vw',
// }}
className={`absolute w-[81.467vw] h-[39vw] object-cover object-bottom origin-top top-[7vw] !rotate-x-4 left-1/2 -translate-x-1/2
onWaiting={() => setBuffering(true)}
onPlaying={() => setBuffering(false)}
className={`absolute w-[81.467vw] h-[39vw] object-cover object-bottom origin-top top-[7vw] !rotate-x-4 left-1/2 -translate-x-1/2
md:w-[58.809vw] md:h-[28vw] md:top-[5vw]
`}
/>
<div
className={`absolute w-[81.467vw] h-[39vw] origin-top bg-black/35 !rotate-x-4 z-10 flex justify-center items-center transition-opacity left-1/2 -translate-x-1/2 ${
buffering ? 'opacity-100' : 'opacity-0'
} max-md:top-[7vw] md:top-[5vw] md:w-[58.809vw] md:h-[28vw]`}
>
<div className='flex gap-4 items-center'>
<LoaderIcon className='animate-spin lg:w-[1.389vw] lg:h-[1.389vw] h-5 w-5' />
<span className='text2 select-none'>Загружаем видео...</span>
</div>
</div>
<div className='h-[5.5vw] w-full bg-gradient-to-t from-[#0f1011] via-75% left-1/2 -translate-x-1/2 bottom-0 absolute' />
</motion.div>
);