feat: add loader for image and video on prime
This commit is contained in:
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>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user