refactor: enhance localization strings and standardize component formatting across multiple files
This commit is contained in:
@@ -13,9 +13,9 @@
|
||||
"develope": "We help developers sell",
|
||||
"easier": "real estate easier and ",
|
||||
"faster": "faster",
|
||||
"cheaper": "cheaper",
|
||||
"expensive": "more expensive ",
|
||||
"integration": "Integration in sales offices",
|
||||
"remote_demo": "Remote demo"
|
||||
"remote_demo": "Remote demonstrations"
|
||||
},
|
||||
"integrations": {
|
||||
"title": "Integration in sales offices",
|
||||
@@ -33,7 +33,7 @@
|
||||
},
|
||||
"interactive_presentation": {
|
||||
"title": "Interactive presentation",
|
||||
"experience": "enhances property selection",
|
||||
"experience": "enhances property selection experience",
|
||||
"increase": "and boosts apartment sales in a residential complex"
|
||||
},
|
||||
"search_and_select": {
|
||||
@@ -50,7 +50,7 @@
|
||||
"three_d_tour": {
|
||||
"title": "Virtual tour of a residential complex",
|
||||
"court": "Courtyard",
|
||||
"mop": "CUA",
|
||||
"mop": "Common areas",
|
||||
"flats": "Apartments",
|
||||
"parking": "Parking",
|
||||
"office": "Commercial"
|
||||
|
||||
@@ -223,7 +223,7 @@ export function Header() {
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
{pathname.startsWith("/projects") && (
|
||||
{/* {pathname.startsWith("/projects") && (
|
||||
<Link
|
||||
href={"https://dprofile.ru/graff.estate"}
|
||||
className="max-xl:hidden rounded-[20px] bg-[#37393B99] backdrop-blur-[20px] hover:bg-[#232425] py-5 pl-[63px] pr-[33px] right-5 fixed z-[2] top-5 overflow-clip bg-[url(/img/components/header/dp.png)] bg-no-repeat bg-right-bottom"
|
||||
@@ -237,7 +237,7 @@ export function Header() {
|
||||
/>
|
||||
<p className="btnm font-medium">{t("case")}</p>
|
||||
</Link>
|
||||
)}
|
||||
)} */}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Title } from '@/ui/Title';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Slider } from './Slider';
|
||||
import { CityPoint } from './CityPoint';
|
||||
import { enCities, enCitiesMobile } from '@/consts/cities';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useMediaQueries } from '@/hooks/useMediaQueries';
|
||||
import { useCityPointStore } from '@/stores/useCityPointStore';
|
||||
import { useGetMapPointByCity } from '@/queries/getMapPointByCity';
|
||||
import { enMapProject } from '@/consts/mockEnMapProject';
|
||||
import { Icon } from "@/ui/Icon";
|
||||
import { Title } from "@/ui/Title";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { Slider } from "./Slider";
|
||||
import { CityPoint } from "./CityPoint";
|
||||
import { enCities, enCitiesMobile } from "@/consts/cities";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useMediaQueries } from "@/hooks/useMediaQueries";
|
||||
import { useCityPointStore } from "@/stores/useCityPointStore";
|
||||
import { useGetMapPointByCity } from "@/queries/getMapPointByCity";
|
||||
import { enMapProject } from "@/consts/mockEnMapProject";
|
||||
|
||||
function NewMap() {
|
||||
const t = useTranslations('map');
|
||||
const t = useTranslations("map");
|
||||
|
||||
const [currentHovered, setCurrentHovered] = useState<number | undefined>();
|
||||
|
||||
@@ -24,14 +24,14 @@ function NewMap() {
|
||||
const { isLg } = useMediaQueries();
|
||||
|
||||
return (
|
||||
<div className='relative mt-[140px] flex flex-col lg:gap-16 max-lg:gap-2'>
|
||||
<div className="relative mt-[140px] flex flex-col lg:gap-16 max-lg:gap-2">
|
||||
<Title>
|
||||
Over 15 years of work, we have completed{' '}
|
||||
<span className='text-gradient'>49 projects for developers</span> in the
|
||||
field of interactive technologies.
|
||||
Over 15 years of work, we have completed{" "}
|
||||
<span className="text-gradient">49 projects for developers</span> in the
|
||||
field of interactive technologies
|
||||
</Title>
|
||||
<div className='max-lg:overflow-x-auto overflow-y-visible h-full scrollbar-hide md:max-lg:-mx-4 max-md:-mx-2.5 mt-16 relative'>
|
||||
<div className='bg-[url(/img/pages/home/stats/en_map1.png)] max-lg:w-[90vw] max-lg:h-[100vw] bg-no-repeat bg-contain w-[62.967vw] h-[50vw] relative lg:left-[23.194vw]'>
|
||||
<div className="max-lg:overflow-x-auto overflow-y-visible h-full scrollbar-hide md:max-lg:-mx-4 max-md:-mx-2.5 mt-16 relative">
|
||||
<div className="bg-[url(/img/pages/home/stats/en_map1.png)] max-lg:w-[90vw] max-lg:h-[100vw] bg-no-repeat bg-contain w-[62.967vw] h-[50vw] relative lg:left-[23.194vw]">
|
||||
{(isLg ? enCities : enCitiesMobile).map((point, index) => (
|
||||
<CityPoint
|
||||
key={point.title}
|
||||
@@ -56,15 +56,15 @@ function NewMap() {
|
||||
}
|
||||
/>
|
||||
|
||||
<div className='lg:hidden absolute left-[50vw] bottom-[4.444vw] translate-y-1/2 -translate-x-1/2 w-[68.611vw] aspect-[247/56] rounded-[4.444vw] bg-[#37393B99] px-[4.167vw] py-[4.444vw] flex gap-[2.222vw] justify-between items-center'>
|
||||
<div className='w-[6.667vw] h-[6.667vw]'>
|
||||
<div className="lg:hidden absolute left-[50vw] bottom-[4.444vw] translate-y-1/2 -translate-x-1/2 w-[68.611vw] aspect-[247/56] rounded-[4.444vw] bg-[#37393B99] px-[4.167vw] py-[4.444vw] flex gap-[2.222vw] justify-between items-center">
|
||||
<div className="w-[6.667vw] h-[6.667vw]">
|
||||
<Icon
|
||||
name='finger_print'
|
||||
svgProp={{ className: 'w-[6.667vw] h-[6.667vw]' }}
|
||||
name="finger_print"
|
||||
svgProp={{ className: "w-[6.667vw] h-[6.667vw]" }}
|
||||
/>
|
||||
</div>
|
||||
<p className='caption leading-[120%] font-medium select-none'>
|
||||
{t('instruction')}
|
||||
<p className="caption leading-[120%] font-medium select-none">
|
||||
{t("instruction")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import { StoriesModal } from '@/components/modals/StoriesModal';
|
||||
import { useModalStore } from '@/stores/useModalStore';
|
||||
import { Title } from '@/ui/Title';
|
||||
import { useInView } from 'framer-motion';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { CircularProgressbar } from 'react-circular-progressbar';
|
||||
import { StoriesModal } from "@/components/modals/StoriesModal";
|
||||
import { useModalStore } from "@/stores/useModalStore";
|
||||
import { Title } from "@/ui/Title";
|
||||
import { useInView } from "framer-motion";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { CircularProgressbar } from "react-circular-progressbar";
|
||||
|
||||
export function Motivation() {
|
||||
const ref = useRef<HTMLVideoElement>(null);
|
||||
@@ -21,66 +21,67 @@ export function Motivation() {
|
||||
const timeUpdateHandler = () =>
|
||||
setProgress((video.currentTime / video.duration) * 100);
|
||||
|
||||
videoRef.current.addEventListener('timeupdate', timeUpdateHandler);
|
||||
return () => video.removeEventListener('timeupdate', timeUpdateHandler);
|
||||
videoRef.current.addEventListener("timeupdate", timeUpdateHandler);
|
||||
return () => video.removeEventListener("timeupdate", timeUpdateHandler);
|
||||
}, []);
|
||||
|
||||
const isInView = useInView(ref, {
|
||||
margin: '100% 0px -85% 0px',
|
||||
margin: "100% 0px -95% 0px",
|
||||
});
|
||||
|
||||
const { setModal } = useModalStore();
|
||||
|
||||
const t = useTranslations('motivation');
|
||||
const t = useTranslations("motivation");
|
||||
|
||||
return (
|
||||
<div className='lg:space-y-[4.444vw] md:max-lg:space-y-[6.25vw] max-md:space-y-[11.111vw]'>
|
||||
<div className="lg:space-y-[4.444vw] md:max-lg:space-y-[6.25vw] max-md:space-y-[11.111vw]">
|
||||
<Title
|
||||
headerLevel={1}
|
||||
className='text-center min-[2560px]:max-w-2/3 min-[2560px]:mx-auto'
|
||||
className="text-center min-[2560px]:max-w-2/3 min-[2560px]:mx-auto"
|
||||
>
|
||||
{t('develope')}
|
||||
<span className='max-lg:hidden'> </span>
|
||||
<span className='lg:hidden'> </span>
|
||||
{t('easier')}
|
||||
<span className='relative'>
|
||||
<span className='text-[#37393B]'>{t('faster')}</span>
|
||||
<span className='absolute top-[55%] -left-[2.5%] 2xl:h-1.5 h-1 w-[105%] bg-white' />
|
||||
</span>{' '}
|
||||
{t('cheaper')}
|
||||
{t("develope")}
|
||||
<span className="max-lg:hidden"> </span>
|
||||
<span className="lg:hidden"> </span>
|
||||
{t("easier")}
|
||||
<span className="relative">
|
||||
<span className="text-[#37393B]">{t("faster")}</span>
|
||||
<span className="absolute top-[55%] -left-[2.5%] 2xl:h-1.5 h-1 w-[105%] bg-white" />
|
||||
</span>
|
||||
<br />
|
||||
{t("expensive")}
|
||||
</Title>
|
||||
<div className='grid lg:gap-[0.833vw] md:max-lg:gap-[1.563vw] gap-[2.222vw]'>
|
||||
<div className="grid lg:gap-[0.833vw] md:max-lg:gap-[1.563vw] gap-[2.222vw]">
|
||||
<div
|
||||
className={`col-start-1 lg:row-span-2 max-lg:col-span-2 duration-300 transition-all ${
|
||||
isInView
|
||||
? 'lg:w-[97.222vw] lg:h-[50.972vw]'
|
||||
: 'lg:w-[67.986vw] lg:h-[35.556vw]'
|
||||
? "lg:w-[97.222vw] lg:h-[50.972vw]"
|
||||
: "lg:w-[67.986vw] lg:h-[35.556vw]"
|
||||
}`}
|
||||
>
|
||||
<video
|
||||
ref={ref}
|
||||
src='/videos/pages/home/showreel.mp4'
|
||||
poster='/img/pages/home/motivation/showreel_poster.jpg'
|
||||
src="/videos/pages/home/showreel.mp4"
|
||||
poster="/img/pages/home/motivation/showreel_poster.jpg"
|
||||
autoPlay
|
||||
loop
|
||||
muted
|
||||
playsInline
|
||||
className='lg:rounded-[1.111vw] rounded-2xl h-full w-full object-cover'
|
||||
className="lg:rounded-[1.111vw] rounded-2xl h-full w-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
// onClick={() => setModal(<StoriesModal />)}
|
||||
className='flex flex-col justify-between lg:w-[28.611vw] md:max-lg:w-[47.135vw] lg:h-[15.694vw] md:max-lg:h-[29.427vw] w-[46.111vw] h-[61.111vw] lg:p-[1.667vw] p-4 lg:col-start-2 lg:row-start-1 row-start-2 bg-[radial-gradient(ellipse_at_bottom_right,#7A7A7A50,transparent)] lg:rounded-[1.111vw] rounded-2xl relative outline-none'
|
||||
className="flex flex-col justify-between lg:w-[28.611vw] md:max-lg:w-[47.135vw] lg:h-[15.694vw] md:max-lg:h-[29.427vw] w-[46.111vw] h-[61.111vw] lg:p-[1.667vw] p-4 lg:col-start-2 lg:row-start-1 row-start-2 bg-[radial-gradient(ellipse_at_bottom_right,#7A7A7A50,transparent)] lg:rounded-[1.111vw] rounded-2xl relative outline-none"
|
||||
>
|
||||
<p className='font-medium heading2 lg:max-w-[51%] md:max-lg:max-w-[19.271vw] self-start text-left'>
|
||||
{t('integration')}
|
||||
<p className="font-medium heading2 lg:max-w-[51%] md:max-lg:max-w-[19.271vw] self-start text-left">
|
||||
{t("integration")}
|
||||
</p>
|
||||
<div className='lg:w-[11.667vw] md:max-lg:w-[21.875vw] w-[37.222vw] aspect-square md:absolute relative lg:right-[1.667vw] lg:bottom-[0.903vw] md:max-lg:right-[3.125vw] md:max-lg:bottom-[1.693vw]'>
|
||||
<div className="lg:w-[11.667vw] md:max-lg:w-[21.875vw] w-[37.222vw] aspect-square md:absolute relative lg:right-[1.667vw] lg:bottom-[0.903vw] md:max-lg:right-[3.125vw] md:max-lg:bottom-[1.693vw]">
|
||||
<video
|
||||
ref={videoRef}
|
||||
src='/videos/pages/home/story.mp4'
|
||||
poster='/img/pages/home/motivation/stories_poster.jpg'
|
||||
className='aspect-square object-cover w-full h-full rounded-full'
|
||||
src="/videos/pages/home/story.mp4"
|
||||
poster="/img/pages/home/motivation/stories_poster.jpg"
|
||||
className="aspect-square object-cover w-full h-full rounded-full"
|
||||
loop
|
||||
playsInline
|
||||
autoPlay
|
||||
@@ -94,24 +95,24 @@ export function Motivation() {
|
||||
? {}
|
||||
: {
|
||||
path: {
|
||||
stroke: 'white',
|
||||
strokeLinecap: 'round',
|
||||
transition: 'linear',
|
||||
transitionDuration: '0.3s',
|
||||
stroke: "white",
|
||||
strokeLinecap: "round",
|
||||
transition: "linear",
|
||||
transitionDuration: "0.3s",
|
||||
},
|
||||
}
|
||||
}
|
||||
className='absolute top-0 text-white rounded-full'
|
||||
className="absolute top-0 text-white rounded-full"
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
<div className='relative lg:w-[28.611vw] lg:h-[19.028vw] md:max-lg:w-[47.135vw] md:max-lg:h-[29.427vw] overflow-hidden w-[46.111vw] h-[61.111vw] bg-[radial-gradient(ellipse_at_bottom_right,#7A7A7A50,transparent)] col-start-2 row-start-2 lg:p-[1.667vw] p-4 lg:rounded-[1.111vw] rounded-2xl flex flex-col lg:gap-[1.944vw] md:max-lg:gap-[3.125vw] gap-[3.333vw]'>
|
||||
<p className='heading2 font-medium'>{t('remote_demo')}</p>
|
||||
<div className='relative lg:w-[19.583vw] md:max-lg:w-[40.885vw] lg:rounded-[0.556vw] rounded-lg w-[73.333vw] md:self-center max-md:-bottom-0.5'>
|
||||
<div className="relative lg:w-[28.611vw] lg:h-[19.028vw] md:max-lg:w-[47.135vw] md:max-lg:h-[29.427vw] overflow-hidden w-[46.111vw] h-[61.111vw] bg-[radial-gradient(ellipse_at_bottom_right,#7A7A7A50,transparent)] col-start-2 row-start-2 lg:p-[1.667vw] p-4 lg:rounded-[1.111vw] rounded-2xl flex flex-col lg:gap-[1.944vw] md:max-lg:gap-[3.125vw] gap-[3.333vw]">
|
||||
<p className="heading2 font-medium">{t("remote_demo")}</p>
|
||||
<div className="relative lg:w-[19.583vw] md:max-lg:w-[40.885vw] lg:rounded-[0.556vw] rounded-lg w-[73.333vw] md:self-center max-md:-bottom-0.5">
|
||||
<img
|
||||
src='/img/pages/home/motivation/remote_demo.png'
|
||||
alt='remote demo'
|
||||
className='!relative lg:rounded-[0.556vw] rounded-lg object-[-1px_-1px] object-contain lg:w-[19.583vw] md:max-lg:w-[40.885vw] w-[73.333vw]'
|
||||
src="/img/pages/home/motivation/remote_demo.png"
|
||||
alt="remote demo"
|
||||
className="!relative lg:rounded-[0.556vw] rounded-lg object-[-1px_-1px] object-contain lg:w-[19.583vw] md:max-lg:w-[40.885vw] w-[73.333vw]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
import { Title } from '@/ui/Title';
|
||||
import Link from 'next/link';
|
||||
import ArrowMoreIcon from '../../../../public/icons/arrow_more.svg';
|
||||
import { VideoPlayer } from '@/ui/VideoPlayer';
|
||||
import { Title } from "@/ui/Title";
|
||||
import Link from "next/link";
|
||||
import ArrowMoreIcon from "../../../../public/icons/arrow_more.svg";
|
||||
import { VideoPlayer } from "@/ui/VideoPlayer";
|
||||
|
||||
function NewStreaming() {
|
||||
return (
|
||||
<div className='lg:mt-[140px] max-lg:mt-[100px] flex flex-col gap-16'>
|
||||
<div className="lg:mt-[140px] max-lg:mt-[100px] flex flex-col gap-16">
|
||||
<Title>
|
||||
Our unique <span className='text-gradient'>remote demonstration</span>{' '}
|
||||
Our unique <span className="text-gradient">remote demonstration</span>{" "}
|
||||
technology allows presenting an object to a customer from anywhere in
|
||||
the world.
|
||||
the world
|
||||
</Title>
|
||||
<div className='flex gap-3 max-lg:flex-col'>
|
||||
<div className='px-4 pt-4 pb-4 w-[31.875vw] bg-[#232425] rounded-2xl flex flex-col gap-3 max-lg:w-full max-lg:max-h-[500px] max-lg:justify-between'>
|
||||
<div className='flex flex-col gap-2'>
|
||||
<p className='heading1 font-medium'>«Upside Towers»</p>
|
||||
<div className='flex gap-2'>
|
||||
<div className='px-2 py-1.5 flex lg:gap-[0.278vw] gap-1 items-center lg:rounded-[1.181vw] rounded-2xl [backdrop-filter:blur(12px)] bg-[#37393B99] btns'>
|
||||
<div className='lg:w-[0.556vw] lg:h-[0.556vw] w-2 h-2 rounded-full m-1 bg-[#90C141]' />
|
||||
<div className="flex gap-3 max-lg:flex-col">
|
||||
<div className="px-4 pt-4 pb-4 w-[31.875vw] bg-[#232425] rounded-2xl flex flex-col gap-3 max-lg:w-full max-lg:max-h-[500px] max-lg:justify-between">
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="heading1 font-medium">«Upside Towers»</p>
|
||||
<div className="flex gap-2">
|
||||
<div className="px-2 py-1.5 flex lg:gap-[0.278vw] gap-1 items-center lg:rounded-[1.181vw] rounded-2xl [backdrop-filter:blur(12px)] bg-[#37393B99] btns">
|
||||
<div className="lg:w-[0.556vw] lg:h-[0.556vw] w-2 h-2 rounded-full m-1 bg-[#90C141]" />
|
||||
<div>Upside Development</div>
|
||||
</div>
|
||||
<div className='px-3 py-1.5 flex lg:gap-[0.278vw] gap-1 items-center lg:rounded-[1.181vw] rounded-2xl [backdrop-filter:blur(12px)] bg-[#37393B99] btns'>
|
||||
<div className="px-3 py-1.5 flex lg:gap-[0.278vw] gap-1 items-center lg:rounded-[1.181vw] rounded-2xl [backdrop-filter:blur(12px)] bg-[#37393B99] btns">
|
||||
Moscow
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='bg-[url(/img/components/products/streaming-notebook.png)] bg-contain bg-center bg-no-repeat w-[28.542vw] h-[24.514vw] rounded-2xl max-lg:w-full max-lg:h-[300px]'></div>
|
||||
<div className="bg-[url(/img/components/products/streaming-notebook.png)] bg-contain bg-center bg-no-repeat w-[28.542vw] h-[24.514vw] rounded-2xl max-lg:w-full max-lg:h-[300px]"></div>
|
||||
<Link
|
||||
href={
|
||||
'https://stream.graff.tech/?build=upsideTowersDev&location=a1&lang=en'
|
||||
"https://stream.graff.tech/?build=upsideTowersDev&location=a1&lang=en"
|
||||
}
|
||||
target='_blank'
|
||||
className='transition-opacity duration-500 w-[20.833vw] h-[4.167vw] bg-gradient self-center md:max-lg:rounded-2xl rounded-xl font-medium [backdrop-filter:blur(3px)] content-center text-center z-1 max-lg:w-[300px] max-lg:h-[60px]'
|
||||
target="_blank"
|
||||
className="transition-opacity duration-500 w-[20.833vw] h-[4.167vw] bg-gradient self-center md:max-lg:rounded-2xl rounded-xl font-medium [backdrop-filter:blur(3px)] content-center text-center z-1 max-lg:w-[300px] max-lg:h-[60px]"
|
||||
>
|
||||
<p className='btnl flex justify-center gap-2'>
|
||||
<p className="btnl flex justify-center gap-2">
|
||||
Start demonstration
|
||||
<ArrowMoreIcon className='text-white w-[1.389vw] h-[1.389vw] max-lg:w-[20px] max-lg:h-[20px]' />
|
||||
<ArrowMoreIcon className="text-white w-[1.389vw] h-[1.389vw] max-lg:w-[20px] max-lg:h-[20px]" />
|
||||
</p>
|
||||
</Link>
|
||||
</div>
|
||||
<div className='max-lg:h-[400px]'>
|
||||
<VideoPlayer src={'/videos/pages/home/streaming.mp4'} showMutingBtn>
|
||||
<p className='accent font-medium absolute top-6 left-6 w-[39.861vw] max-lg:w-[90vw] max-lg:text-[20px] '>
|
||||
<div className="max-lg:h-[400px]">
|
||||
<VideoPlayer src={"/videos/pages/home/streaming.mp4"} showMutingBtn>
|
||||
<p className="accent font-medium absolute top-6 left-6 w-[39.861vw] max-lg:w-[90vw] max-lg:text-[20px] ">
|
||||
Graff.estate stream is available on any device — all you need for
|
||||
a demo is an internet connection.
|
||||
</p>
|
||||
|
||||
@@ -1,38 +1,40 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import {
|
||||
queryProjectsOptions,
|
||||
useGetProjectsQuery,
|
||||
} from '@/queries/getProjects';
|
||||
import { Title } from '@/ui/Title';
|
||||
import { getProjectsCount } from '@/utils/getProjectsCount';
|
||||
import { ProjectsSection } from '../ProjectsPage/ProjectsSection';
|
||||
import { queryOptions, useQuery } from '@tanstack/react-query';
|
||||
import { useLocale, useTranslations } from 'next-intl';
|
||||
} from "@/queries/getProjects";
|
||||
import { Title } from "@/ui/Title";
|
||||
import { getProjectsCount } from "@/utils/getProjectsCount";
|
||||
import { ProjectsSection } from "../ProjectsPage/ProjectsSection";
|
||||
import { queryOptions, useQuery } from "@tanstack/react-query";
|
||||
import { useLocale, useTranslations } from "next-intl";
|
||||
|
||||
export function Projects() {
|
||||
// const { data: projects } = useGetProjectsQuery();
|
||||
const { data: projects } = useQuery(queryProjectsOptions);
|
||||
const t = useTranslations("projects");
|
||||
const locale = useLocale()
|
||||
const locale = useLocale();
|
||||
|
||||
return (
|
||||
<div className="lg:space-y-16 sm:space-y-12 space-y-10 lg:mt-40 mt-[100px]">
|
||||
<div className="lg:flex sm:space-y-12 space-y-10">
|
||||
<Title>
|
||||
{t('title1')}{' '}
|
||||
{t("title1")}{" "}
|
||||
<span className="text-gradient">
|
||||
{projects && getProjectsCount(projects?.length, locale)}{' '}
|
||||
{t('title2')}
|
||||
</span>{' '}
|
||||
{t('title3')}
|
||||
{projects && getProjectsCount(projects?.length, locale)}{" "}
|
||||
{t("title2")}
|
||||
</span>{" "}
|
||||
{t("title3")}
|
||||
</Title>
|
||||
</div>
|
||||
{projects && (
|
||||
<ProjectsSection
|
||||
projects={projects
|
||||
.filter((project) => project.stage !== 6)
|
||||
.slice(0, 6)}
|
||||
projects={projects.filter(
|
||||
(project) =>
|
||||
project.englishCity === "Dubai" ||
|
||||
project.englishCity === "Abu Dhabi"
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,47 +1,50 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import { IProject } from '@/types/IProject';
|
||||
import { motion } from 'framer-motion';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import ArrowRightIcon from '../../../../public/icons/arrow_right.svg';
|
||||
import { AwardsCard } from './AwardsCard';
|
||||
import { ProjectCard } from './ProjectCard';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { IProject } from "@/types/IProject";
|
||||
import { motion } from "framer-motion";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import ArrowRightIcon from "../../../../public/icons/arrow_right.svg";
|
||||
import { AwardsCard } from "./AwardsCard";
|
||||
import { ProjectCard } from "./ProjectCard";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export function ProjectsSection({ projects }: { projects: IProject[] }) {
|
||||
const pathname = usePathname();
|
||||
const t = useTranslations("projects");
|
||||
|
||||
useEffect(() => {
|
||||
console.log(projects);
|
||||
}, [projects]);
|
||||
return (
|
||||
<div
|
||||
className={`grid ${
|
||||
pathname.startsWith('/projects') ? 'lg:grid-cols-3' : 'lg:grid-cols-4'
|
||||
pathname.startsWith("/projects") ? "lg:grid-cols-3" : "lg:grid-cols-4"
|
||||
} md:max-lg:grid-cols-2 gap-3`}
|
||||
>
|
||||
{projects.map((project) => (
|
||||
<ProjectCard key={project.id} {...project} />
|
||||
))}
|
||||
{pathname.startsWith('/projects') && (
|
||||
{pathname.startsWith("/projects") && (
|
||||
<AwardsCard className="sm:col-start-2 sm:row-start-2 row-start-3" />
|
||||
)}
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
whileInView={{ opacity: 1 }}
|
||||
viewport={{ once: true, margin: '-100px' }}
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
transition={{
|
||||
duration: 1,
|
||||
ease: [0.58, 0.12, 0.27, 0.98],
|
||||
delay: 0.2,
|
||||
}}
|
||||
>
|
||||
{pathname === '/' && (
|
||||
{pathname === "/" && (
|
||||
<Link
|
||||
href={'/projects'}
|
||||
href={"/projects"}
|
||||
scroll={false}
|
||||
className="lg:rounded-[1.111vw] rounded-2xl bg-[#232425] hover:bg-[#23242599] transition-colors aspect-square self-center p-5 flex items-center justify-center btnl font-medium gap-2"
|
||||
>
|
||||
{t('watch')}
|
||||
{t("watch")}
|
||||
<ArrowRightIcon className="lg:w-[1.389vw] lg:h-[1.389vw] md:max-lg:w-[2.604vw] md:max-lg:h-[2.604vw] w-5 h-5 text-white" />
|
||||
</Link>
|
||||
)}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
export function getCompaniesCount(count: number, locale: string) {
|
||||
if (locale === 'en') {
|
||||
return `${count}\xa0developer${count === 1 ? '' : 's'}`;
|
||||
if (locale === "en") {
|
||||
return `${count}\xa0real estate developer${count === 1 ? "" : "s"}`;
|
||||
}
|
||||
|
||||
return `${count}\xa0застройщик${
|
||||
count > 10 && count < 15
|
||||
? 'ов'
|
||||
? "ов"
|
||||
: count % 10 === 1
|
||||
? ''
|
||||
? ""
|
||||
: count % 10 === 2 || count % 10 === 3 || count % 10 === 4
|
||||
? 'а'
|
||||
: 'ов'
|
||||
? "а"
|
||||
: "ов"
|
||||
}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user