This commit is contained in:
2025-01-24 20:26:26 +05:00
parent 894660cbe9
commit c455b62395
29 changed files with 191 additions and 198 deletions
BIN
View File
Binary file not shown.
+5 -3
View File
@@ -12,6 +12,9 @@
"generate": "graphql-codegen --config .graphqlrc.json"
},
"dependencies": {
"@measured/puck": "^0.18.0",
"@tailwindcss/postcss": "^4.0.0",
"@tailwindcss/vite": "^4.0.0",
"@tanstack/react-query": "^5.62.7",
"@tanstack/react-query-devtools": "^5.64.2",
"@tinymce/tinymce-react": "^5.1.1",
@@ -23,6 +26,7 @@
"ky": "^1.4.0",
"libphonenumber-js": "^1.11.7",
"next": "14.2.5",
"postcss": "^8.5.1",
"react": "^18",
"react-circular-progressbar": "^2.1.0",
"react-dom": "^18",
@@ -34,6 +38,7 @@
"react-swipeable": "^7.0.1",
"react-transition-group": "^4.4.5",
"sharp": "^0.33.5",
"tailwindcss": "^4.0.0",
"tinymce": "^7.4.1",
"usehooks-ts": "^3.1.0",
"zustand": "^4.5.4"
@@ -46,11 +51,8 @@
"@types/react-phone-number-input": "^3.1.37",
"@types/react-rangeslider": "^2.2.7",
"@types/react-transition-group": "^4.4.11",
"autoprefixer": "^10.4.19",
"eslint": "^8",
"eslint-config-next": "14.2.5",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5"
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
'@tailwindcss/postcss': {},
},
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 620 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -1
View File
@@ -2,6 +2,7 @@ import { api } from '@/api';
import { Awards } from '@/components/pages/MainPage/Awards';
import { Calculator } from '@/components/pages/MainPage/Calculator/Calculator';
import { Clients } from '@/components/pages/MainPage/Clients';
import { InteractivePresentation } from '@/components/pages/MainPage/InteractivePresentaion/IntreractivePresentation';
import { ProjectsMap } from '@/components/pages/MainPage/Map/ProjectsMap';
import { Projects } from '@/components/pages/MainPage/Projects';
import { Statistics } from '@/components/pages/MainPage/Statistics';
@@ -57,7 +58,7 @@ export default async function HomePage() {
return (
<HydrationBoundary state={dehydrate(queryClient)}>
<Motivation />
{/* <InteractivePresentation /> */}
<InteractivePresentation />
<Statistics />
<ProjectsMap />
<Streaming />
+8 -7
View File
@@ -1,6 +1,9 @@
@import url('/fonts/TTHovesProAll/stylesheet.css');
@import 'tailwindcss';
@tailwind base;
@theme {
--gradient: linear-gradient(87deg, #798fff 15%, #d375ff 100%);
}
@layer base {
.no-tailwindcss-base {
@@ -57,9 +60,6 @@
}
}
@tailwind components;
@tailwind utilities;
html {
scroll-behavior: smooth;
}
@@ -70,9 +70,9 @@ body {
background-color: #0f1011;
}
.bg-gradient {
/* .bg-gradient {
background: linear-gradient(87deg, #798fff 15%, #d375ff 100%);
}
} */
.bg-gradient-card {
content: '';
@@ -109,6 +109,7 @@ body {
.h1 {
@apply -tracking-[.02em] 2xl:text-[clamp(96px,96px+(100vw-1560px)/360*16,112px)] text-[clamp(40px,40px+(100vw-360px)/1240*56,96px)] leading-[clamp(36px,36px+(100vw-360px)/1240*50.4,86.4px)] font-medium;
}
.h2 {
@apply -tracking-[.02em] 2xl:text-[clamp(64px,64px+(100vw-1560px)/360*12,76px)] text-[clamp(28px,28px+(100vw-360px)/1240*36,64px)] leading-none font-medium;
}
@@ -217,7 +218,7 @@ body {
}
.accent {
@apply min-[1440px]:text-[clamp(32px,32px+(100vw-1440px)/480*8,40px)] text-2xl min-[1440px]:leading-[1.1] leading-none;
@apply min-[1440px]:text-[clamp(32px,32px+(100vw-1440px)/480*8,40px)] text-[clamp(24px,32px+(100vw-360px)/1080*8,32px)] min-[1440px]:leading-[1.1] leading-none;
}
.text1 {
+4 -4
View File
@@ -7,7 +7,7 @@ import { usePathname, useRouter } from 'next/navigation';
import { UseFormSetValue } from 'react-hook-form';
import { DeleteIcon } from './icons/DeleteIcon';
import { EditIcon } from './icons/EditIcon';
import { ArticleFormModal, IArticleFormInput } from './modals/ArticleFormModal';
import { ArticleFormModal, IArticleInput } from './modals/ArticleFormModal';
import { DeleteArticleModal } from './modals/DeleteArticleModal';
export function ArticleActions({
@@ -20,7 +20,7 @@ export function ArticleActions({
setValue,
inCard = false,
}: IArticle & {
setValue?: UseFormSetValue<IArticleFormInput>;
setValue?: UseFormSetValue<IArticleInput>;
inCard?: boolean;
}) {
const { push } = useRouter();
@@ -61,13 +61,13 @@ export function ArticleActions({
<>
<button
onClick={handleEditArticle}
className="relative p-2 transition-opacity bg-black rounded-full bg-opacity-60 hover:bg-opacity-70"
className="bg-opacity-60 hover:bg-opacity-70 relative p-2 transition-opacity bg-black rounded-full"
>
<EditIcon />
</button>
<button
onClick={handleDeleteArticle}
className="relative p-2 transition-opacity bg-black rounded-full bg-opacity-60 hover:bg-opacity-70"
className="bg-opacity-60 hover:bg-opacity-70 relative p-2 transition-opacity bg-black rounded-full"
>
<DeleteIcon />
</button>
+3 -3
View File
@@ -17,14 +17,14 @@ export function Feedback() {
return (
<div
id="contacts"
className="lg:mb-20 sm:mb-12 mb-10 lg:pt-40 pt-[100px] lg:flex lg:gap-3 max-lg:space-y-12"
className="lg:mb-20 sm:mb-12 mb-10 lg:pt-40 pt-[100px] lg:flex lg:gap-3 max-lg:space-y-12 justify-between"
>
<h2 className="line2 font-medium max-lg:mb-6 lg:max-w-[50%]">
<h2 className="line2 font-medium max-lg:mb-6 lg:max-w-[45%]">
<span className="text-[#7A7A7A]">Хотите увеличить конверсию?</span>
<br />
Давайте обсудим детали.
</h2>
<div className="flex-1 space-y-4">
<div className="flex-1 space-y-4 max-w-[50%]">
<p className="heading2 font-medium">Нам нужна</p>
<FeedbackForm />
</div>
+32 -18
View File
@@ -3,6 +3,7 @@
import { api } from '@/api';
import { ClassNameWrapper } from '@/hocs/ClassNameWrapper';
import { useMediaQueries } from '@/hooks/useMediaQueries';
import { useScroll } from '@/hooks/useScroll';
import { useCheckAuthQuery } from '@/queries/checkAuth';
import { useModalStore } from '@/stores/useModalStore';
import { Button } from '@/ui/Button';
@@ -49,6 +50,7 @@ export function Header() {
const burgerBtnRef = useRef<HTMLDivElement>(null);
const productsRef = useRef<HTMLDivElement>(null);
const productsBtnRef = useRef<HTMLDivElement>(null);
const logoRef = useRef<HTMLAnchorElement>(null);
useOnClickOutside([productsRef, productsBtnRef], () => {
setProductsOpened(false);
@@ -58,9 +60,11 @@ export function Header() {
setBurgerOpened(false);
});
const scroll = useScroll(logoRef);
return (
<header className="lg:mt-5 relative flex items-center px-5">
<Link href={'/'}>
<Link href={'/'} ref={logoRef}>
<ClassNameWrapper className="max-lg:hidden">
<LogoWithTextIcon />
</ClassNameWrapper>
@@ -80,14 +84,16 @@ export function Header() {
}}
className="fixed lg:top-5 top-4 p-1 rounded-[20px] bg-[#37393B99] backdrop-blur-2xl flex gap-1 z-[12]"
>
<Link
href={'/'}
className="aspect-square p-4 lg:hidden hover:bg-[#232425] rounded-xl content-center"
>
<ClassNameWrapper className={'w-4 h-4'}>
<LogoIcon />
</ClassNameWrapper>
</Link>
{((isLg && scroll < -logoRef.current?.clientHeight!) || !isLg) && (
<Link
href={'/'}
className="aspect-square p-4 alg:hidden hover:bg-[#37393B99] rounded-xl content-center"
>
<ClassNameWrapper className={'w-4 h-4'}>
<LogoIcon />
</ClassNameWrapper>
</Link>
)}
<div ref={productsBtnRef} className="max-md:hidden">
<button
className="px-6 py-4 font-medium btnm hover:bg-[#37393B99] rounded-2xl active:bg-white active:text-black"
@@ -99,21 +105,21 @@ export function Header() {
</button>
</div>
<HeaderLink
className="max-md:hidden"
className="max-md:hidden btnm"
href={'/about'}
text={'О нас'}
/>
<HeaderLink
className="max-md:hidden"
className="max-md:hidden btnm"
href={'/blog'}
text={'Блог'}
/>
<HeaderLink
className="max-md:hidden"
className="max-md:hidden btnm"
href={'/projects'}
text={'Проекты'}
/>
<div className="flex-1 flex md:justify-end justify-center">
<div className="md:justify-end flex justify-center flex-1">
<Button
className="btnm font-medium py-[17px] text-nowrap"
rounded="2xl"
@@ -122,7 +128,7 @@ export function Header() {
Оставить заявку
</Button>
</div>
<div className="md:hidden flex md:justify-end" ref={burgerBtnRef}>
<div className="md:hidden md:justify-end flex" ref={burgerBtnRef}>
<button
className="!border-none p-[18px] hover:bg-[#232425] rounded-2xl active:opacity-50 outline-none"
onClick={() => setBurgerOpened((prev) => !prev)}
@@ -151,10 +157,18 @@ export function Header() {
exit={{ opacity: 0 }}
className="absolute w-full p-4 pt-2 top-16 rounded-2xl bg-[#232425] md:hidden space-y-6"
>
<div className="space-y-1 -mx-4 -mb-2 px-2">
<HeaderLink href={'/about'} text={'О нас'} />
<HeaderLink href={'/'} text={'Блог'} />
<HeaderLink href={'/projects'} text={'Проекты'} />
<div className="px-2 -mx-4 space-y-1">
<HeaderLink
href={'/about'}
text={'О нас'}
className="accent"
/>
<HeaderLink href={'/'} text={'Блог'} className="accent" />
<HeaderLink
href={'/projects'}
text={'Проекты'}
className="accent"
/>
</div>
<hr className="border-[#37393B]" />
<div className="space-y-[10px]">
+1 -7
View File
@@ -1,12 +1,6 @@
export function NatureIcon() {
return (
<svg
width={98}
height={98}
viewBox="0 0 98 98"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<svg viewBox="0 0 98 98" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle
cx={48.763}
cy={48.763}
+4 -4
View File
@@ -71,20 +71,20 @@ export function ArticleFormModal<TAction extends 'create' | 'edit'>({
<>
<div className="space-y-2 absolute left-7 top-5 z-[2]">
<button
className="flex items-center gap-2 py-2 px-3 bg-gradient disabled:bg-[#232425] disabled:bg-none rounded-xl group"
className="flex items-center gap-2 py-2 px-3 bg-gradient disabled:bg-[#232425] disabled:bg-none rounded-xl"
disabled={!title || !tags || !cardImage || !posterImage}
onClick={() => handleSave(false)}
>
<ClassNameWrapper className="w-4 h-4 text-white group-disabled:opacity-20">
<ClassNameWrapper className="in-disabled:opacity-20 w-4 h-4 text-white">
<CheckIcon />
</ClassNameWrapper>
<p className="btns font-medium group-disabled:opacity-20">
<p className="btns in-disabled:opacity-20 font-medium">
Опубликовать
</p>
</button>
<Button
color="secondary"
className="px-5 py-2 btns disabled:opacity-20"
className="btns disabled:opacity-20 px-5 py-2"
disabled={!title || !tags || !cardImage || !posterImage}
onClick={() => handleSave(true)}
>
+3 -3
View File
@@ -12,12 +12,12 @@ export function FormModalHeader({
return (
<div className="flex justify-end top-0 right-4 h-[60px] w-full items-end absolute bg-[#232425] z-[1]">
<button
className="flex gap-2 items-center p-4 disabled:bg-transparent bg-gradient disabled:bg-none group rounded-2xl"
className="disabled:bg-transparent bg-gradient disabled:bg-none rounded-2xl flex items-center gap-2 p-4"
disabled={disabled}
onClick={submitHandler}
>
<p className="btnm font-medium group-disabled:opacity-20">Сохранить</p>
<ClassNameWrapper className="w-4 h-4 group-disabled:opacity-20">
<p className="btnm in-disabled:opacity-20 font-medium">Сохранить</p>
<ClassNameWrapper className="in-disabled:opacity-20 w-4 h-4">
<CheckIcon />
</ClassNameWrapper>
</button>
@@ -39,7 +39,7 @@ export function ArticleCard({
className="!relative object-cover rounded-xl z-[1]"
/>
{auth && (
<div className="absolute top-0 left-0 w-full h-full z-[2] group-hover:block hidden bg-[#0F1011] bg-opacity-40 rounded-xl" />
<div className="absolute top-0 left-0 w-full h-full z-[2] group-hover:block hidden bg-[#0F1011] opacity-40 rounded-xl" />
)}
</div>
<p className="heading1 font-medium">{title}</p>
@@ -133,8 +133,10 @@ export function Calculator() {
return (
<div className="flex flex-col items-center lg:gap-y-16 gap-y-10 lg:mt-[140px] mt-[100px]">
<Title className="text-center">
Оцените эффективность инструмента{' '}
<span className="text-gradient">GRAFF.estate</span>
Оцените эффективность
<br />
инструмента
<span className="text-gradient"> GRAFF.estate</span>
</Title>
<div className="md:flex gap-x-3 gap-y-4 md:items-end grid relative max-md:bg-[#232425B8] max-md:rounded-[20px] max-md:p-4 max-md:pt-10 w-full lg:justify-center md:justify-stretch max-md:order-2">
{selectedRegion && (
@@ -167,18 +169,21 @@ export function Calculator() {
<StatsColumn
color={'#D375FF'}
percents={100}
label={'100'}
value={consultations}
title="Консультаций"
/>
<StatsColumn
color={calculated ? '#B1EC52' : '#37393B'}
percents={calculated ? 48 : 32}
label={`${calculated ? 48 : 30}`}
value={calculated ? reservation : oldReservation}
title="Забронировано"
/>
<StatsColumn
color={calculated ? '#798FFF' : '#37393B'}
percents={calculated ? 42 : 30}
percents={calculated ? 42 * 0.48 : 30 * 0.48}
label={`${calculated ? 42 : 30}`}
value={calculated ? sales : oldSales}
title="Продано"
/>
@@ -2,19 +2,21 @@ export function StatsColumn({
color,
title,
percents,
label,
value,
}: {
percents: number;
value: number;
title: string;
color: string;
label: string;
}) {
return (
<div className="lg:w-[204px] w-1/3 space-y-1">
<div className="flex items-center justify-center gap-1 select-none">
<p className="accent font-medium">{value}</p>
<p className="rounded-2xl px-2 p-[7px] bg-[#37393B99] btns font-medium">
{percents}%
{label}%
</p>
</div>
<div className="w-full">
+1 -1
View File
@@ -28,7 +28,7 @@ export function Clients() {
{companies?.map(
(company) =>
company.logo && (
<div className="group relative" key={company.id}>
<div className="relative" key={company.id}>
<Link
href={'/projects?companyId=' + company.id}
className="bg-[#232425] rounded-xl aspect-square flex justify-center items-center opacity-60 hover:opacity-100 transition-opacity p-5"
@@ -1,145 +1,49 @@
import { EmotionalIcon } from '@/components/icons/EmotionalIcon';
import { Flat1 } from '@/components/icons/Flat1';
import { Flat2 } from '@/components/icons/Flat2';
import { KidsIcon } from '@/components/icons/KidsIcon';
import { LocationIcon } from '@/components/icons/LocationIcon';
import { MailIcon } from '@/components/icons/MailIcon';
import { MetroIcon } from '@/components/icons/MetroIcon';
import { NatureIcon } from '@/components/icons/NatureIcon';
import { PhoneIcon } from '@/components/icons/PhoneIcon';
import { ShopIcon } from '@/components/icons/ShopIcon';
import { ClassNameWrapper } from '@/hocs/ClassNameWrapper';
import { Title } from '@/ui/Title';
import Image from 'next/image';
import { PropsWithChildren } from 'react';
export function InteractivePresentation() {
return (
<div className="pt-[100px] space-y-16 bg-[#0F1011]">
<Title>
Интерактивная презентация
<span className="text-gradient">
{' '}
улучшает опыт выбора недвижимости{' '}
</span>
и увеличивают темпы продаж квартир в жилом комплексе
</Title>
<div className="flex justify-between ">
<DoubleCard />
<CardContainer
title="Демонстрация инфраструктуры вокруг будущего комплекса"
text="Режим «Инфраструктура» знакомит пользователя с перспективной застройкой целого района. В зависимости от срока сдачи либо функциональной нагрузки того или иного блока можно ввести выделение цветом."
className="aspect-[460/560] w-[calc(460/1440*100vw)] max-w-[460px]"
>
<div className="grid grid-cols-2 gap-1 grid-rows">
<NatureIcon />
<KidsIcon />
<MetroIcon />
<ShopIcon />
</div>
</CardContainer>
<CardContainer
title="Интерактивная инсоляция"
text="Клиент может наблюдать, как световое пятно перемещается по квартире в зависимости от времени суток и сезона, поскольку солнечный свет имеет физическое воздействие."
className="aspect-[460/560] w-[calc(460/1440*100vw)] max-w-[460px]"
>
<div className="py-3 px-[43px] flex">
<SeasonCard
title="Лето"
src="/img/pages/home/interactivePresentation/summer.png"
className="left-14 bottom-[42px]"
/>
<SeasonCard
title="Зима"
src="/img/pages/home/interactivePresentation/winter.png"
className="z-[1]"
/>
<SeasonCard
title="Осень"
src="/img/pages/home/interactivePresentation/autumn.png"
className="top-[67px] right-14"
/>
</div>
</CardContainer>
<CardContainer
title="Интеграция с CRM-системой застройщика "
className="aspect-[412/560] w-[calc(412/1440*100vw)] max-w-[412px]"
>
<div className="space-y-10">
<div className="space-y-4">
<div className="flex">
<div className="rounded-lg bg-[#B1EC52] text-black font-medium w-12 h-12 rotate-[-4deg] content-center text-center z-[2] relative">
2K
</div>
<ClassNameWrapper className="relative right-1 z-[1]">
<Flat1 />
</ClassNameWrapper>
<ClassNameWrapper className="rotate-[-4deg] right-2 relative">
<Flat2 />
</ClassNameWrapper>
</div>
<p className="font-medium text1">
Клиент всегда видит актуальные данные об интересующем его лоте,
включая статус и стоимость.
</p>
</div>
<div className="space-y-4">
<div className="flex">
<Image
src={'/img/pages/home/interactivePresentation/vova.png'}
width={48}
height={48}
className="rotate-[-4deg] z-[2]"
alt="Вова"
sizes=""
/>
<div className="w-12 h-12 bg-[#37393B] rounded-lg flex justify-center items-center z-[1] relative right-1">
<ClassNameWrapper className="rotate-[4deg]">
<MailIcon />
</ClassNameWrapper>
</div>
<div className="w-12 h-12 bg-[#37393B] rounded-lg flex justify-center items-center rotate-[-4deg] relative right-2">
<PhoneIcon />
</div>
</div>
<p className="font-medium text1">
Клиент всегда видит актуальные данные об интересующем его лоте,
включая статус и стоимость.
</p>
</div>
</div>
</CardContainer>
</div>
<div className="space-y-10">
<Slide1 />
<Slide2 />
<Slide3 />
</div>
);
}
export function DoubleCard() {
return (
<div className="w-1/4 space-y-3">
<div className="space-y-3">
<CardContainer
title="Выбор квартиры на генплане"
className="aspect-[459/274] w-[calc(459/1440*100vw)] max-w-[459px]"
className="aspect-[459/274] w-[calc(459/1440*100vw)]"
>
<div className="space-y-4">
<div className="flex items-center gap-x-6">
<div className="gap-x-6 flex items-center">
<EmotionalIcon />
<p className="font-medium">
Эмоциональне вовлечение пользователя в выбор квартиры
</p>
</div>
<div className="flex items-center gap-x-6">
<div className="gap-x-6 flex items-center">
<LocationIcon />
<p className="font-medium">
Удобство выбора расположения и видовых характеристик
</p>
</div>
<div className="flex items-center gap-x-6"></div>
<div className="gap-x-6 flex items-center"></div>
</div>
</CardContainer>
<CardContainer
title="Поиск по параметрам"
className="aspect-[459/274] w-[calc(459/1440*100vw)] max-w-[459px]"
className="aspect-[459/274] w-[calc(459/1440*100vw)]"
>
<div className="flex flex-wrap gap-2">
{[
@@ -178,11 +82,11 @@ export function CardContainer({
text ? '' : ' justify-between'
}`}
>
<p className="font-medium heading2">{title}</p>
<p className="heading2 font-medium">{title}</p>
<div className={!!text ? 'flex-1 content-center m-auto' : ''}>
{children}
</div>
{text && <p className="font-medium text1">{text}</p>}
{text && <p className="text1 font-medium">{text}</p>}
</div>
);
}
@@ -198,7 +102,9 @@ export function SeasonCard({
}) {
return (
<div
className={'bg-[#37393B] px-1 pt-1 pb-3 rounded-xl relative ' + className}
className={`bg-[#37393B] px-1 pt-1 pb-3 rounded-xl relative${
className ? ' ' + className : ''
}`}
>
<div className="relative">
<Image
@@ -213,3 +119,74 @@ export function SeasonCard({
</div>
);
}
export function Slide1() {
return (
<div className="flex gap-3">
<DoubleCard />
<div className="flex-1">
<video
src="/videos/pages/home/interactive/1_search.mp4"
autoPlay
loop
muted
playsInline
className=""
/>
</div>
</div>
);
}
export function Slide2() {
return (
<div className="relative max-h-[560px] flex">
<video
src="/videos/pages/home/interactive/2_3dtour.mp4"
className="max-h-[560px] m-auto"
autoPlay
loop
playsInline
muted
/>
<div className="absolute bottom-[3px] bg-white h-[58px] w-[calc(810/1400*100%)] left-[50%] -translate-x-[50%]"></div>
</div>
);
}
export function Slide3() {
return (
<div className="flex gap-3">
<div className="flex-1">
<video
src="/videos/pages/home/interactive/3_infrastructure.mp4"
autoPlay
loop
muted
playsInline
/>
</div>
<div className="rounded-2xl p-6">
<p className="heading2 font-medium">
Демонстрация инфраструктуры вокруг будущего комплекса
</p>
<div className="flex h-full justify-center items-center">
<div className="grid grid-cols-2 grid-rows-2 gap-[5px]">
<ClassNameWrapper className="w-[98px] h-[98px]">
<NatureIcon />
</ClassNameWrapper>
<ClassNameWrapper className="w-[98px] h-[98px]">
<KidsIcon />
</ClassNameWrapper>
<ClassNameWrapper className="w-[98px] h-[98px]">
<MetroIcon />
</ClassNameWrapper>
<ClassNameWrapper className="w-[98px] h-[98px]">
<ShopIcon />
</ClassNameWrapper>
</div>
</div>
</div>
</div>
);
}
+11 -16
View File
@@ -8,6 +8,7 @@ import { useEffect, useRef, useState } from 'react';
export function Motivation() {
const ref = useRef<HTMLVideoElement>(null);
const videoRef = useRef<HTMLVideoElement>(null);
const [initTopOffset, setInitTopOffset] = useState(0);
@@ -19,12 +20,15 @@ export function Motivation() {
const { isLg } = useMediaQueries();
const videoRef = useRef<HTMLVideoElement>(null);
return (
<div className="lg:space-y-16 space-y-10">
<Title headerLevel={1} className="sm:max-lg:text-5xl text-center">
Помогаем девелоперам продавать недвижимость проще и&nbsp;
<Title
headerLevel={1}
className="sm:max-lg:text-5xl text-center 2xl:atext-[160px]"
>
Помогаем девелоперам
<br />
продавать недвижимость проще и&nbsp;
<span className="relative">
<span className="text-[#37393B]">быстрее</span>
<span className="absolute top-[55%] -left-[2.5%] 2xl:h-1.5 h-1 w-[105%] bg-white" />
@@ -37,7 +41,7 @@ export function Motivation() {
width: isLg
? `calc((100vw - 40px) * ${
1 +
(isLg && initTopOffset - scroll > 400 && scroll !== 0
(isLg && initTopOffset - scroll > 650 && scroll !== 0
? scroll >= 150
? Math.min(
(0.33 * (initTopOffset - scroll - 200)) /
@@ -104,17 +108,8 @@ export function Motivation() {
<p className="font-medium heading2 sm:max-w-[50%]">
Интеграция в&nbsp;офисы продаж
</p>
<div
className="sm:absolute relative lg:w-[calc(168/412*100%)] sm:w-[calc(168/362*100%)] w-[calc(134/166*100%)] sm:bottom-6 sm:right-6 self-center rounded-full aspect-square bg-white"
role="progressbar"
aria-valuenow={
((videoRef.current?.currentTime ?? 0) /
(videoRef.current?.duration ?? 1)) *
100
}
aria-valuemin={0}
aria-valuemax={100}
>
<div className="sm:absolute relative lg:w-[calc(168/412*100%)] sm:w-[calc(168/362*100%)] w-[calc(134/166*100%)] sm:bottom-6 sm:right-6 self-center">
{/* <CircularProgressbar value={ref.current?.currentTime/ref.current?.duration} /> */}
<video
ref={videoRef}
src="/videos/pages/home/story.mp4"
+2 -2
View File
@@ -43,7 +43,7 @@ export function Statistics() {
<p className="heading2 font-medium">
<span className="line1">4</span> раз
</p>
<div className="absolute w-[calc(103/338*100%)] sm:max-xl:w-[calc(103/380*100%)] sm:bottom-12 sm:right-16 bottom-12 right-14">
<div className="absolute w-[calc(103/338*100%)] sm:max-xl:w-[calc(103/380*100%)] sm:bottom-12 sm:right-16 bottom-12 right-14 xl:hidden">
<Image
src="/img/pages/home/stats/Forum_Zoolog_09-03(2).png"
fill
@@ -52,7 +52,7 @@ export function Statistics() {
sizes=""
/>
</div>
<div className="absolute w-[calc(103/338*100%)] sm:max-xl:w-[calc(103/380*100%)] sm:bottom-6 sm:right-6 bottom-6 right-4">
<div className="absolute w-[calc(103/338*100%)] sm:max-xl:w-[calc(103/380*100%)] sm:bottom-6 sm:right-6 bottom-6 right-4 xl:hidden">
<Image
src="/img/pages/home/stats/Forum_Zoolog_09-03.png"
fill
@@ -48,7 +48,6 @@ export function Streaming() {
const handleMouseMove = useCallback((e: MouseEvent) => {
if (!ref.current) return;
const { bottom, left, top, right } = ref.current.getBoundingClientRect();
ref.current?.getBoundingClientRect().right;
if (
ref.current &&
e.clientX < right &&
@@ -72,14 +71,15 @@ export function Streaming() {
}, []);
useEffect(() => {
ref.current?.addEventListener('mousemove', handleMouseMove);
const el = ref.current;
el?.addEventListener('mousemove', handleMouseMove);
animate();
return () => {
cancelAnimationFrame(requestRef.current!);
ref.current?.removeEventListener('mousemove', handleMouseMove);
el?.removeEventListener('mousemove', handleMouseMove);
};
}, []);
}, [animate, handleMouseMove]);
return (
<div className="lg:mt-[140px] mt-[100px] lg:space-y-16 sm:space-y-12 space-y-10">
@@ -96,13 +96,13 @@ export function Streaming() {
{data?.map((project) => (
<StreamingProject key={project.id} href="/" {...project} />
))}
<div className="border border-[#3D425C] rounded-2xl flex justify-center items-center p-6 sm:max-lg:min-w-[300px]">
<div className="border border-[#3D425C] rounded-2xl flex justify-center items-center p-6 sm:max-lg:min-w-[300px] group">
<div className="flex flex-col items-center space-y-6">
<p className="heading2 font-medium text-center">
Расскажем и покажем как это работает на&nbsp;созвоне
</p>
<Button
className="btnl px-6 py-4 rounded-lg"
className="btnl group-hover:scale-105 px-6 py-4 transition-transform rounded-lg"
onClick={() => setModal(<ModalWithFeedbackForm />, 'form')}
>
Оставить заявку
@@ -120,10 +120,10 @@ export function Streaming() {
className="lg:aspect-[1400/640] sm:aspect-[736/480] aspect-[340/600] rounded-2xl w-full h-full object-cover"
/>
<div className="absolute left-0 top-0 h-5/6 w-full z-[1]">
<div ref={ref} className="group relative w-full h-full">
<div ref={ref} className="relative w-full h-full">
<button
ref={btnRef}
className="bg-[#37393B99] p-[50px] backdrop-blur-[30.72px] rounded-full group-hover:opacity-100 transition-opacity group-hover:cursor-none opacity-0 fixed z-[1]a"
className="bg-[#37393B99] p-[50px] backdrop-blur-[30.72px] rounded-full in-hover:opacity-100 transition-opacity in-hover:cursor-none opacity-0 sticky z-[1]a"
style={{ left: point[0] - 64, top: point[1] - 64 }}
onClick={handleVideoClick}
>
@@ -16,9 +16,9 @@ export function StreamingProject({
const { isLg } = useMediaQueries();
return (
<div className="lg:aspect-[344/396] sm:aspect-[300/344] sm:max-lg:min-w-[300px] rounded-2xl p-4 flex group relative overflow-hidden">
<div className="lg:aspect-[344/396] sm:aspect-[300/344] sm:max-lg:min-w-[300px] rounded-2xl p-4 flex relative overflow-hidden group">
<div
className="absolute w-full h-full top-0 left-0 rounded-2xl group-hover:scale-110 transition-transform"
className="rounded-2xl group-hover:scale-110 absolute top-0 left-0 w-full h-full transition-transform"
style={{
background: `linear-gradient(to ${
isLg ? 'bottom' : 'top'
@@ -46,7 +46,7 @@ export function StreamingProject({
</div>
<Link
href={href}
className="hidden lg:group-hover:block absolute w-full h-full left-0 bottom-0 rounded-2xl font-medium bg-[radial-gradient(#000000CC,transparent)]a backdrop-blur-[3px] content-center text-center z-[2]"
className="hidden lg:group-hover:block absolute w-full h-full left-0 bottom-0 rounded-2xl font-medium backdrop-blur-[3px] content-center text-center z-[2]"
>
<p className="btnl flex justify-center gap-2">
Начать демонстрацию <ArrowMoreIcon />
+1 -1
View File
@@ -42,7 +42,7 @@ export function Button({
icon ? 'pr-4' : ''
} flex gap-1 items-center overflow-hidden w-${width} ${className} justify-between`}
>
<span className="group-hover:opacity-10 opacity-0 bg-black transition-opacity absolute top-0 left-0 w-full h-full"></span>
<span className="group-hover:opacity-10 absolute top-0 left-0 w-full h-full transition-opacity bg-black opacity-0"></span>
<span className={'relative font-medium' + (icon ? '' : ' m-auto')}>
{children}
</span>
+4 -2
View File
@@ -3,7 +3,7 @@ import Link from 'next/link';
export function HeaderLink({
href,
text,
className,
className = '',
}: {
href: string;
text: string;
@@ -12,7 +12,9 @@ export function HeaderLink({
return (
<Link
href={href}
className={`md:px-6 md:py-4 outline-none px-2 py-2 font-medium text-nowrap md:btnm accent hover:bg-[#37393B99] active:bg-white active:text-black rounded-2xl transition-colors flex items-center ${className}`}
className={`md:px-6 md:py-4 outline-none px-2 py-2 font-medium text-nowrap hover:bg-[#37393B99] active:bg-white active:text-black rounded-2xl transition-colors flex items-center${
className ? ' ' + className : ''
}`}
>
{text}
</Link>