Compare commits

...

2 Commits

50 changed files with 1962 additions and 1034 deletions
BIN
View File
Binary file not shown.
+1
View File
@@ -16,6 +16,7 @@
"@tanstack/react-query": "^5.62.7",
"@tanstack/react-query-devtools": "^5.64.2",
"@tinymce/tinymce-react": "^5.1.1",
"clsx": "^2.1.1",
"countries-phone-masks": "^1.1.0",
"date-fns": "^3.6.0",
"effector": "^23.3.0",
+21 -18
View File
@@ -1,38 +1,41 @@
"use client";
import CloseIcon from "@/components/icons/CloseIcon";
import { useBodyScrollLock } from "@/hooks/useBodyScrollLock";
import { useLenis } from "@/hooks/useLenis";
import { closeLegalModalNavigation } from "@/utils/closeLegalModalNavigation";
import ReactLenis from "lenis/react";
function PrivacyPolicyLayout({ children }: { children: React.ReactNode }) {
function handleClose() {
try {
window.close();
} catch {
// Если не удалось закрыть, пытаемся вернуться назад в истории
if (window.history.length > 1) {
window.history.back();
} else {
// Если и это не работает, перенаправляем на главную страницу
window.location.href = "/";
}
}
closeLegalModalNavigation();
}
const lenis = useLenis();
useBodyScrollLock(true);
return (
<section className="fixed inset-0 bg-[#0F101199] [backdrop-filter:blur(16px)] z-[14]">
<ReactLenis
ref={lenis}
className="fixed inset-0 z-[14] overflow-y-auto bg-[#0F101199] lg:py-10 [backdrop-filter:blur(16px)] [&>div]:relative [&>div]:left-1/2 [&>div]:w-full [&>div]:-translate-x-1/2 [&>div]:lg:w-[66.25vw]"
>
<button
className="fixed inset-0 cursor-pointer"
type="button"
className="fixed inset-0 z-[1] cursor-pointer bg-transparent"
onClick={handleClose}
></button>
{children}
aria-label="Close"
/>
<div className="relative z-[2]">{children}</div>
<button
type="button"
onClick={handleClose}
className="fixed lg:right-[1.389vw] lg:top-[1.389vw] right-5 top-5 lg:rounded-[1.111vw] rounded-2xl bg-[#37393B99] lg:p-[1.111vw] p-4 cursor-pointer backdrop-blur-2xl"
className="fixed right-5 top-5 z-[3] cursor-pointer rounded-2xl bg-[#37393B99] p-4 backdrop-blur-2xl lg:right-[1.389vw] lg:top-[1.389vw] lg:rounded-[1.111vw] lg:p-[1.111vw]"
>
<div className="text-white lg:size-[1.111vw] size-4">
<div className="size-4 text-white lg:size-[1.111vw]">
<CloseIcon />
</div>
</button>
</section>
</ReactLenis>
);
}
+298 -304
View File
@@ -1,319 +1,313 @@
"use client";
import { useLenis } from "@/hooks/useLenis";
import { useLenis } from "lenis/react";
import ArrowUpIcon from "@/components/icons/ArrowUpIcon";
import ReactLenis from "lenis/react";
function PrivacyPolicyPage() {
const lenis = useLenis();
return (
<div className="absolute left-1/2 -translate-x-1/2 lg:w-[66.25vw] w-full overflow-y-auto max-h-dvh h-full">
<ReactLenis ref={lenis} className="overflow-y-scroll h-full">
<div className="bg-gradient lg:px-[5.208vw] md:max-lg:px-4 px-2.5 lg:pt-[14.514vw] md:max-lg:pt-[157px] pt-[169px] lg:pb-[1.667vw] md:max-lg:pb-6 pb-4 lg:rounded-t-[1.944vw]">
<h1 className="heading1 font-medium">Privacy Policy</h1>
</div>
<div className="bg-[#232425] lg:px-[5.208vw] md:max-lg:px-4 px-2.5 lg:pt-[2.778vw] md:max-lg:pt-10 pt-8">
<div className="lg:max-w-[38.889vw] md:max-lg:max-w-[66.667vw] lg:space-y-[2.778vw] md:max-lg:space-y-10 space-y-8">
<div className="lg:space-y-[0.833vw] space-y-3 text2">
<p>
This Privacy Policy together with any other policies or notices
made available to you when we collect Personal Information from
you and our Terms of Service apply to your use of our Services.
</p>
<p>
When we refer to Personal Information, we mean any information
about an individual from which that person can be identified. It
does not include data where the identity has been removed, which
is referred to as anonymous data.
</p>
<p>
Our Services are not intended for children and we do not
knowingly collect Personal Information relating to children.
</p>
<p>
In the event of any inconsistency or conflict between our Terms
of Service and this Privacy Policy, this Privacy Policy shall
prevail.
</p>
<p>Personal Information that we collect and why we collect it</p>
<>
<div className="bg-gradient-saturated lg:px-[5.208vw] md:max-lg:px-4 px-2.5 lg:pt-[14.514vw] md:max-lg:pt-[157px] pt-[169px] lg:pb-[1.667vw] md:max-lg:pb-6 pb-4 lg:rounded-t-[1.944vw]">
<h1 className="heading1 font-medium">Privacy Policy</h1>
</div>
<div className="bg-[#232425] lg:px-[5.208vw] md:max-lg:px-4 px-2.5 lg:pt-[2.778vw] md:max-lg:pt-10 pt-8">
<div className="lg:max-w-[38.889vw] md:max-lg:max-w-[66.667vw] lg:space-y-[2.778vw] md:max-lg:space-y-10 space-y-8">
<div className="lg:space-y-[0.833vw] space-y-3 text2">
<p>
This Privacy Policy together with any other policies or notices
made available to you when we collect Personal Information from
you and our Terms of Service apply to your use of our Services.
</p>
<p>
When we refer to Personal Information, we mean any information
about an individual from which that person can be identified. It
does not include data where the identity has been removed, which
is referred to as anonymous data.
</p>
<p>
Our Services are not intended for children and we do not knowingly
collect Personal Information relating to children.
</p>
<p>
In the event of any inconsistency or conflict between our Terms of
Service and this Privacy Policy, this Privacy Policy shall
prevail.
</p>
<p>Personal Information that we collect and why we collect it</p>
</div>
<div className="lg:space-y-[0.833vw] space-y-3 text2">
<div>
<span className="font-bold">
We use different methods to collect Personal Information from
and about you including through:
</span>
<ul className="list-disc list-inside">
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
direct interactions with you, such as during the registration
process for Future ID;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
automated technologies or interactions website;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
third parties or publicly available sources.
</li>
</ul>
</div>
<div className="lg:space-y-[0.833vw] space-y-3 text2">
<p>
<span className="font-bold">
We use different methods to collect Personal Information from
and about you including through:
</span>
<ul className="list-disc list-inside">
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
direct interactions with you, such as during the
registration process for Future ID;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
automated technologies or interactions website;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
third parties or publicly available sources.
</li>
</ul>
</p>
<p>
We may collect, store, process, use and transfer different kinds
of Personal Information about you which we have grouped together
as follows:
</p>
</div>
<div className="lg:space-y-[0.833vw] space-y-3 text2 grid grid-cols-[1fr_2fr] lg:gap-[0.833vw] gap-3">
<p className="font-bold">Сategory of data</p>
<p className="font-bold">
Includes the following types of Personal Information
</p>
<p>Identity Data</p>
<p>
Name, username or similar identifier, title, date of birth,
profile picture, nationality, location, gender, role/job title,
education history, personal biography description, tagline and
descriptive tags.
</p>
<p>Contact Data</p>
<p>
Delivery addresses, email addresses, social networking
profile(s), telephone numbers and contact information.
</p>
<p>Technical and Location Data</p>
<p>
Internet protocol (IP) address, device type, your login data,
browser type and version, time zone setting, browser plug-in
types and versions, operating system and platform and other
technology on the devices you use to access this Website, unique
device identification numbers, broad geographic location (e.g.
country or city-level location) and other technical information
from your device. Some services or functions of our Services may
make use of location-based information pursuant to which we may
collect information about the Wi-Fi routers closest to you and
the cell IDs of the towers closest to you.
</p>
<p>Usage Data</p>
<p>Information about how you use our Services.</p>
<p>Marketing and Communications Data</p>
<p>
Your preferences in receiving marketing from us and our third
parties and your communication preferences.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<p className="text2">
Some of this information may be collected using cookies and
similar tracking technology, as explained further under the
section titled Cookies.
</p>
<p className="text2">
<span className="font-bold">
We use Personal Information collected:
</span>
<ul className="list-disc list-inside">
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to contact you, including providing you with communications
in relation to any applications to our Services and to
inform you of any relevant upcoming Services, opportunities
and offers;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to send related updates, if applicable;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to provide you goods, documentation or other materials in
the course of providing our Services;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to provide you with promotional/informative content based on
your preferences;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to respond to any questions and/or concerns that you submit
to us;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to allow other users of our Services to search and find any
public profile you may maintain when using our Services;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to compile relevant statistics and to monitor the
performance of our Services;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to identify and better understand the users of our Services,
where they come from, and what part of our Services
interests them, for internal analytics and statistical
purposes and to improve the relevance of content on our
Services;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to refine and develop our systems and analytics and to
increase quality assurance and standards for our Services.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
for such other uses you authorise and/or consent to from
time to time.
</li>
</ul>
</p>
<p className="text2">
Where we need to collect personal data by law, or under the
terms of a contract we have with you, and you fail to provide
that data when requested, we may have to suspend or terminate
your access to part or all of our Services.
</p>
<p className="text2">
If you share any personal data of a third party with us, please
ensure that you have the express consent from that third party
which permits you to share their personal data with us (and we
will assume that you have such consent prior to sharing their
personal data with us). We strongly advise you to keep a record
of their consent and provide them with a copy of, or link to,
this Privacy Policy. You acknowledge and agree that you shall
remain fully responsible and liable for obtaining the relevant
consent from that third party and for sharing their personal
data with us.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">Security</h2>
<p className="text2">
The security of your Personal Information is important to us. We
follow generally accepted industry standards to protect the
Personal Information formation submitted to us, both during
transmission and once we receive it. Our Services use
appropriate technical and organisational security measures to
protect your Personal Information. The measures used are
designed to provide a level of security appropriate to the risk
of unauthorised or unlawful processing of your Personal
Information.
</p>
<p className="text2">
Unfortunately, the transmission of Personal Information via the
internet is not completely secure. Although we will do our best
to protect your Personal Information, we cannot guarantee the
security of your Personal Information transmitted to us through
our Services.  Any transmission is at your own risk.  Once we
have received your Personal Information, we will use strict
procedures and security features to try to prevent unauthorised
access.  Please note that no website or online service can ever
be guaranteed as 100% secure and you should take reasonable
precautions to protect your Personal Information (for example,
by sharing Personal Information only with operators of websites
and other digital platforms that you trust, by keeping any login
details secure and confidential and by using antivirus software
on your devices).
</p>
<p className="text2">
We will retain your Personal Information for as long as we deem
necessary or appropriate, including to comply with our legal
obligations, resolve disputes and enforce our agreements. If you
wish to request that we no longer use your Personal Information,
please contact us via our Reach Us page.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">
International data transfers
</h2>
<p className="text2">
Personal Information submitted through our Services may be
hosted, transferred to, and processed in, countries other than
the country in which you are resident.  These countries may have
data protection laws that are different to the laws of your
country. However, we have taken appropriate safeguards to
require that your Personal Information will remain protected in
accordance with this Privacy Policy.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">Third Party Links</h2>
<p className="text2">
Our Services may include links to third-party websites, digital
platforms, plug-ins and applications. Clicking on those links or
enabling those connections may allow third parties to collect or
share information about you. We do not control these third-party
websites or digital platforms and we are not responsible for
their privacy statements. When you transition to other digital
platforms, whether directly or redirected from our own, we
encourage you to read the privacy policy and terms and
conditions of use/service for such digital platforms.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">
Correcting and Updating Your Personal Information
</h2>
<p className="text2">
To review or update your Personal Information to ensure it is
accurate, please contact us via our Reach Us page.
</p>
<p className="text2">
You may review, update or delete Personal Information from your
Future ID profile, or delete your Future ID, at any time through
the settings page that is accessible when logged in to your
Future ID.
</p>
<p className="text2">
When we have no ongoing legitimate business need to process your
Personal Information, we will either delete or anonymise it or,
if this is not possible (for example, because your Personal
Information has been stored in backup archives), then we will
securely store your Personal Information and isolate it from any
further processing until deletion is possible.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">
Notification of Privacy Policy Changes
</h2>
<p className="text2">
We may update this Privacy Policy to reflect changes to our
information practices or any relevant statute, regulations
and/or policy. We encourage you to periodically review this page
for the latest information on our privacy practices.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">Contact</h2>
<p className="text2">
You can contact us about this Privacy Policy or in order to
exercise your data protection rights via our Reach Us page.  We
will respond to all requests we receive from individuals wishing
to exercise their data protection rights in accordance with
applicable data protection laws.
</p>
<p>
We may collect, store, process, use and transfer different kinds
of Personal Information about you which we have grouped together
as follows:
</p>
</div>
<div className="lg:space-y-[0.833vw] space-y-3 text2 grid grid-cols-[1fr_2fr] lg:gap-[0.833vw] gap-3">
<p className="font-bold">Сategory of data</p>
<p className="font-bold">
Includes the following types of Personal Information
</p>
<p>Identity Data</p>
<p>
Name, username or similar identifier, title, date of birth,
profile picture, nationality, location, gender, role/job title,
education history, personal biography description, tagline and
descriptive tags.
</p>
<p>Contact Data</p>
<p>
Delivery addresses, email addresses, social networking profile(s),
telephone numbers and contact information.
</p>
<p>Technical and Location Data</p>
<p>
Internet protocol (IP) address, device type, your login data,
browser type and version, time zone setting, browser plug-in types
and versions, operating system and platform and other technology
on the devices you use to access this Website, unique device
identification numbers, broad geographic location (e.g. country or
city-level location) and other technical information from your
device. Some services or functions of our Services may make use of
location-based information pursuant to which we may collect
information about the Wi-Fi routers closest to you and the cell
IDs of the towers closest to you.
</p>
<p>Usage Data</p>
<p>Information about how you use our Services.</p>
<p>Marketing and Communications Data</p>
<p>
Your preferences in receiving marketing from us and our third
parties and your communication preferences.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<p className="text2">
Some of this information may be collected using cookies and
similar tracking technology, as explained further under the
section titled Cookies.
</p>
<div className="text2">
<span className="font-bold">
We use Personal Information collected:
</span>
<ul className="list-disc list-inside">
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to contact you, including providing you with communications in
relation to any applications to our Services and to inform you
of any relevant upcoming Services, opportunities and offers;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to send related updates, if applicable;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to provide you goods, documentation or other materials in the
course of providing our Services;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to provide you with promotional/informative content based on
your preferences;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to respond to any questions and/or concerns that you submit to
us;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to allow other users of our Services to search and find any
public profile you may maintain when using our Services;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to compile relevant statistics and to monitor the performance
of our Services;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to identify and better understand the users of our Services,
where they come from, and what part of our Services interests
them, for internal analytics and statistical purposes and to
improve the relevance of content on our Services;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to refine and develop our systems and analytics and to
increase quality assurance and standards for our Services.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
for such other uses you authorise and/or consent to from time
to time.
</li>
</ul>
</div>
<p className="text2">
Where we need to collect personal data by law, or under the terms
of a contract we have with you, and you fail to provide that data
when requested, we may have to suspend or terminate your access to
part or all of our Services.
</p>
<p className="text2">
If you share any personal data of a third party with us, please
ensure that you have the express consent from that third party
which permits you to share their personal data with us (and we
will assume that you have such consent prior to sharing their
personal data with us). We strongly advise you to keep a record of
their consent and provide them with a copy of, or link to, this
Privacy Policy. You acknowledge and agree that you shall remain
fully responsible and liable for obtaining the relevant consent
from that third party and for sharing their personal data with us.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">Security</h2>
<p className="text2">
The security of your Personal Information is important to us. We
follow generally accepted industry standards to protect the
Personal Information formation submitted to us, both during
transmission and once we receive it. Our Services use appropriate
technical and organisational security measures to protect your
Personal Information. The measures used are designed to provide a
level of security appropriate to the risk of unauthorised or
unlawful processing of your Personal Information.
</p>
<p className="text2">
Unfortunately, the transmission of Personal Information via the
internet is not completely secure. Although we will do our best to
protect your Personal Information, we cannot guarantee the
security of your Personal Information transmitted to us through
our Services.  Any transmission is at your own risk.  Once we have
received your Personal Information, we will use strict procedures
and security features to try to prevent unauthorised access. 
Please note that no website or online service can ever be
guaranteed as 100% secure and you should take reasonable
precautions to protect your Personal Information (for example, by
sharing Personal Information only with operators of websites and
other digital platforms that you trust, by keeping any login
details secure and confidential and by using antivirus software on
your devices).
</p>
<p className="text2">
We will retain your Personal Information for as long as we deem
necessary or appropriate, including to comply with our legal
obligations, resolve disputes and enforce our agreements. If you
wish to request that we no longer use your Personal Information,
please contact us via our Reach Us page.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">
International data transfers
</h2>
<p className="text2">
Personal Information submitted through our Services may be hosted,
transferred to, and processed in, countries other than the country
in which you are resident.  These countries may have data
protection laws that are different to the laws of your country.
However, we have taken appropriate safeguards to require that your
Personal Information will remain protected in accordance with this
Privacy Policy.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">Third Party Links</h2>
<p className="text2">
Our Services may include links to third-party websites, digital
platforms, plug-ins and applications. Clicking on those links or
enabling those connections may allow third parties to collect or
share information about you. We do not control these third-party
websites or digital platforms and we are not responsible for their
privacy statements. When you transition to other digital
platforms, whether directly or redirected from our own, we
encourage you to read the privacy policy and terms and conditions
of use/service for such digital platforms.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">
Correcting and Updating Your Personal Information
</h2>
<p className="text2">
To review or update your Personal Information to ensure it is
accurate, please contact us via our Reach Us page.
</p>
<p className="text2">
You may review, update or delete Personal Information from your
Future ID profile, or delete your Future ID, at any time through
the settings page that is accessible when logged in to your Future
ID.
</p>
<p className="text2">
When we have no ongoing legitimate business need to process your
Personal Information, we will either delete or anonymise it or, if
this is not possible (for example, because your Personal
Information has been stored in backup archives), then we will
securely store your Personal Information and isolate it from any
further processing until deletion is possible.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">
Notification of Privacy Policy Changes
</h2>
<p className="text2">
We may update this Privacy Policy to reflect changes to our
information practices or any relevant statute, regulations and/or
policy. We encourage you to periodically review this page for the
latest information on our privacy practices.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">Contact</h2>
<p className="text2">
You can contact us about this Privacy Policy or in order to
exercise your data protection rights via our Reach Us page.  We
will respond to all requests we receive from individuals wishing
to exercise their data protection rights in accordance with
applicable data protection laws.
</p>
</div>
</div>
<div className="lg:pl-[5.208vw] md:max-lg:pl-4 px-2.5 lg:py-[2.778vw] md:max-lg:py-10 py-8 w-full bg-[#232425] lg:rounded-b-[1.944vw]">
<button
onClick={() => lenis.current?.lenis?.scrollTo(0)}
className="lg:max-w-[38.889vw] md:max-lg:max-w-[66.667vw] w-full cursor-pointer flex items-center justify-center lg:gap-[0.556vw] gap-2 lg:py-[1.111vw] py-4 lg:rounded-[1.111vw] rounded-2xl bg-[#37393B99]"
>
<p className="btnm font-medium">Top</p>
<div className="text-white lg:size-[1.111vw] size-4">
<ArrowUpIcon />
</div>
</button>
</div>
</ReactLenis>
</div>
</div>
<div className="lg:pl-[5.208vw] md:max-lg:pl-4 px-2.5 lg:py-[2.778vw] md:max-lg:py-10 py-8 w-full bg-[#232425] lg:rounded-b-[1.944vw]">
<button
type="button"
onClick={() => lenis?.scrollTo(0)}
className="lg:max-w-[38.889vw] md:max-lg:max-w-[66.667vw] w-full cursor-pointer flex items-center justify-center lg:gap-[0.556vw] gap-2 lg:py-[1.111vw] py-4 lg:rounded-[1.111vw] rounded-2xl bg-[#37393B99]"
>
<p className="btnm font-medium">Top</p>
<div className="text-white lg:size-[1.111vw] size-4">
<ArrowUpIcon />
</div>
</button>
</div>
</>
);
}
+29 -24
View File
@@ -1,6 +1,10 @@
"use client";
import CloseIcon from "@/components/icons/CloseIcon";
import { useBodyScrollLock } from "@/hooks/useBodyScrollLock";
import { useLenis } from "@/hooks/useLenis";
import { closeLegalModalNavigation } from "@/utils/closeLegalModalNavigation";
import ReactLenis from "lenis/react";
export default function TermConditionsLayout({
children,
@@ -8,34 +12,35 @@ export default function TermConditionsLayout({
children: React.ReactNode;
}) {
function handleClose() {
try {
window.close();
} catch {
// Если не удалось закрыть, пытаемся вернуться назад в истории
if (window.history.length > 1) {
window.history.back();
} else {
// Если и это не работает, перенаправляем на главную страницу
window.location.href = "/";
}
}
closeLegalModalNavigation();
}
const lenis = useLenis();
useBodyScrollLock(true);
return (
<section className="fixed inset-0 bg-[#0F101199] [backdrop-filter:blur(16px)] z-[14]">
<button
className="fixed inset-0 cursor-pointer"
onClick={handleClose}
></button>
{children}
<button
onClick={handleClose}
className="fixed lg:right-[1.389vw] lg:top-[1.389vw] right-5 top-5 lg:rounded-[1.111vw] rounded-2xl bg-[#37393B99] lg:p-[1.111vw] p-4 cursor-pointer backdrop-blur-2xl"
<section className="fixed inset-0 h-dvh z-[14]">
<ReactLenis
ref={lenis}
className="fixed inset-0 z-[14] overflow-y-auto bg-[#0F101199] lg:py-10 [backdrop-filter:blur(16px)] [&>div]:relative [&>div]:left-1/2 [&>div]:w-full [&>div]:-translate-x-1/2 [&>div]:lg:w-[66.25vw]"
>
<div className="text-white lg:size-[1.111vw] size-4">
<CloseIcon />
</div>
</button>
{children}
<button
type="button"
onClick={handleClose}
className="fixed right-5 top-5 z-[3] cursor-pointer rounded-2xl bg-[#37393B99] p-4 backdrop-blur-2xl lg:right-[1.389vw] lg:top-[1.389vw] lg:rounded-[1.111vw] lg:p-[1.111vw]"
>
<div className="size-4 text-white lg:size-[1.111vw]">
<CloseIcon />
</div>
</button>
</ReactLenis>
<button
type="button"
className="fixed inset-0 bg-transparent cursor-pointer"
onClick={handleClose}
aria-label="Close"
/>
</section>
);
}
File diff suppressed because it is too large Load Diff
-1
View File
@@ -1,4 +1,3 @@
import { InProcess } from "@/components/pages/InProcess";
import WebMain from "@/components/pages/WebPage/WebMain";
export default function WebPage() {
+1
View File
@@ -0,0 +1 @@
export { default } from "../(main)/privacypolicy/layout";
+314
View File
@@ -0,0 +1,314 @@
"use client";
import { useLenis } from "lenis/react";
import ArrowUpIcon from "@/components/icons/ArrowUpIcon";
function PrivacyPolicyPage() {
const lenis = useLenis();
return (
<>
<div className="bg-gradient-saturated lg:px-[5.208vw] md:max-lg:px-4 px-2.5 lg:pt-[14.514vw] md:max-lg:pt-[157px] pt-[169px] lg:pb-[1.667vw] md:max-lg:pb-6 pb-4 lg:rounded-t-[1.944vw]">
<h1 className="heading1 font-medium">Privacy Policy</h1>
</div>
<div className="bg-[#232425] lg:px-[5.208vw] md:max-lg:px-4 px-2.5 lg:pt-[2.778vw] md:max-lg:pt-10 pt-8">
<div className="lg:max-w-[38.889vw] md:max-lg:max-w-[66.667vw] lg:space-y-[2.778vw] md:max-lg:space-y-10 space-y-8">
<div className="lg:space-y-[0.833vw] space-y-3 text2">
<p>
This Privacy Policy together with any other policies or notices
made available to you when we collect Personal Information from
you and our Terms of Service apply to your use of our Services.
</p>
<p>
When we refer to Personal Information, we mean any information
about an individual from which that person can be identified. It
does not include data where the identity has been removed, which
is referred to as anonymous data.
</p>
<p>
Our Services are not intended for children and we do not knowingly
collect Personal Information relating to children.
</p>
<p>
In the event of any inconsistency or conflict between our Terms of
Service and this Privacy Policy, this Privacy Policy shall
prevail.
</p>
<p>Personal Information that we collect and why we collect it</p>
</div>
<div className="lg:space-y-[0.833vw] space-y-3 text2">
<div>
<span className="font-bold">
We use different methods to collect Personal Information from
and about you including through:
</span>
<ul className="list-disc list-inside">
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
direct interactions with you, such as during the registration
process for Future ID;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
automated technologies or interactions website;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
third parties or publicly available sources.
</li>
</ul>
</div>
<p>
We may collect, store, process, use and transfer different kinds
of Personal Information about you which we have grouped together
as follows:
</p>
</div>
<div className="lg:space-y-[0.833vw] space-y-3 text2 grid grid-cols-[1fr_2fr] lg:gap-[0.833vw] gap-3">
<p className="font-bold">Сategory of data</p>
<p className="font-bold">
Includes the following types of Personal Information
</p>
<p>Identity Data</p>
<p>
Name, username or similar identifier, title, date of birth,
profile picture, nationality, location, gender, role/job title,
education history, personal biography description, tagline and
descriptive tags.
</p>
<p>Contact Data</p>
<p>
Delivery addresses, email addresses, social networking profile(s),
telephone numbers and contact information.
</p>
<p>Technical and Location Data</p>
<p>
Internet protocol (IP) address, device type, your login data,
browser type and version, time zone setting, browser plug-in types
and versions, operating system and platform and other technology
on the devices you use to access this Website, unique device
identification numbers, broad geographic location (e.g. country or
city-level location) and other technical information from your
device. Some services or functions of our Services may make use of
location-based information pursuant to which we may collect
information about the Wi-Fi routers closest to you and the cell
IDs of the towers closest to you.
</p>
<p>Usage Data</p>
<p>Information about how you use our Services.</p>
<p>Marketing and Communications Data</p>
<p>
Your preferences in receiving marketing from us and our third
parties and your communication preferences.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<p className="text2">
Some of this information may be collected using cookies and
similar tracking technology, as explained further under the
section titled Cookies.
</p>
<div className="text2">
<span className="font-bold">
We use Personal Information collected:
</span>
<ul className="list-disc list-inside">
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to contact you, including providing you with communications in
relation to any applications to our Services and to inform you
of any relevant upcoming Services, opportunities and offers;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to send related updates, if applicable;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to provide you goods, documentation or other materials in the
course of providing our Services;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to provide you with promotional/informative content based on
your preferences;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to respond to any questions and/or concerns that you submit to
us;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to allow other users of our Services to search and find any
public profile you may maintain when using our Services;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to compile relevant statistics and to monitor the performance
of our Services;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to identify and better understand the users of our Services,
where they come from, and what part of our Services interests
them, for internal analytics and statistical purposes and to
improve the relevance of content on our Services;
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
to refine and develop our systems and analytics and to
increase quality assurance and standards for our Services.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
for such other uses you authorise and/or consent to from time
to time.
</li>
</ul>
</div>
<p className="text2">
Where we need to collect personal data by law, or under the terms
of a contract we have with you, and you fail to provide that data
when requested, we may have to suspend or terminate your access to
part or all of our Services.
</p>
<p className="text2">
If you share any personal data of a third party with us, please
ensure that you have the express consent from that third party
which permits you to share their personal data with us (and we
will assume that you have such consent prior to sharing their
personal data with us). We strongly advise you to keep a record of
their consent and provide them with a copy of, or link to, this
Privacy Policy. You acknowledge and agree that you shall remain
fully responsible and liable for obtaining the relevant consent
from that third party and for sharing their personal data with us.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">Security</h2>
<p className="text2">
The security of your Personal Information is important to us. We
follow generally accepted industry standards to protect the
Personal Information formation submitted to us, both during
transmission and once we receive it. Our Services use appropriate
technical and organisational security measures to protect your
Personal Information. The measures used are designed to provide a
level of security appropriate to the risk of unauthorised or
unlawful processing of your Personal Information.
</p>
<p className="text2">
Unfortunately, the transmission of Personal Information via the
internet is not completely secure. Although we will do our best to
protect your Personal Information, we cannot guarantee the
security of your Personal Information transmitted to us through
our Services.  Any transmission is at your own risk.  Once we have
received your Personal Information, we will use strict procedures
and security features to try to prevent unauthorised access. 
Please note that no website or online service can ever be
guaranteed as 100% secure and you should take reasonable
precautions to protect your Personal Information (for example, by
sharing Personal Information only with operators of websites and
other digital platforms that you trust, by keeping any login
details secure and confidential and by using antivirus software on
your devices).
</p>
<p className="text2">
We will retain your Personal Information for as long as we deem
necessary or appropriate, including to comply with our legal
obligations, resolve disputes and enforce our agreements. If you
wish to request that we no longer use your Personal Information,
please contact us via our Reach Us page.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">
International data transfers
</h2>
<p className="text2">
Personal Information submitted through our Services may be hosted,
transferred to, and processed in, countries other than the country
in which you are resident.  These countries may have data
protection laws that are different to the laws of your country.
However, we have taken appropriate safeguards to require that your
Personal Information will remain protected in accordance with this
Privacy Policy.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">Third Party Links</h2>
<p className="text2">
Our Services may include links to third-party websites, digital
platforms, plug-ins and applications. Clicking on those links or
enabling those connections may allow third parties to collect or
share information about you. We do not control these third-party
websites or digital platforms and we are not responsible for their
privacy statements. When you transition to other digital
platforms, whether directly or redirected from our own, we
encourage you to read the privacy policy and terms and conditions
of use/service for such digital platforms.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">
Correcting and Updating Your Personal Information
</h2>
<p className="text2">
To review or update your Personal Information to ensure it is
accurate, please contact us via our Reach Us page.
</p>
<p className="text2">
You may review, update or delete Personal Information from your
Future ID profile, or delete your Future ID, at any time through
the settings page that is accessible when logged in to your Future
ID.
</p>
<p className="text2">
When we have no ongoing legitimate business need to process your
Personal Information, we will either delete or anonymise it or, if
this is not possible (for example, because your Personal
Information has been stored in backup archives), then we will
securely store your Personal Information and isolate it from any
further processing until deletion is possible.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">
Notification of Privacy Policy Changes
</h2>
<p className="text2">
We may update this Privacy Policy to reflect changes to our
information practices or any relevant statute, regulations and/or
policy. We encourage you to periodically review this page for the
latest information on our privacy practices.
</p>
</div>
<div className="lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">Contact</h2>
<p className="text2">
You can contact us about this Privacy Policy or in order to
exercise your data protection rights via our Reach Us page.  We
will respond to all requests we receive from individuals wishing
to exercise their data protection rights in accordance with
applicable data protection laws.
</p>
</div>
</div>
</div>
<div className="lg:pl-[5.208vw] md:max-lg:pl-4 px-2.5 lg:py-[2.778vw] md:max-lg:py-10 py-8 w-full bg-[#232425] lg:rounded-b-[1.944vw]">
<button
type="button"
onClick={() => lenis?.scrollTo(0)}
className="lg:max-w-[38.889vw] md:max-lg:max-w-[66.667vw] w-full cursor-pointer flex items-center justify-center lg:gap-[0.556vw] gap-2 lg:py-[1.111vw] py-4 lg:rounded-[1.111vw] rounded-2xl bg-[#37393B99]"
>
<p className="btnm font-medium">Top</p>
<div className="text-white lg:size-[1.111vw] size-4">
<ArrowUpIcon />
</div>
</button>
</div>
</>
);
}
export default PrivacyPolicyPage;
+1
View File
@@ -0,0 +1 @@
export { default } from "../(main)/terms-conditions/layout";
+526
View File
@@ -0,0 +1,526 @@
"use client";
import { useLenis } from "lenis/react";
import ArrowUpIcon from "@/components/icons/ArrowUpIcon";
function TermsConditionsPage() {
const lenis = useLenis();
return (
<>
<div className="bg-gradient-saturated lg:px-[5.208vw] md:max-lg:px-4 px-2.5 lg:pt-[14.514vw] md:max-lg:pt-[157px] pt-[169px] lg:pb-[1.667vw] md:max-lg:pb-6 pb-4 lg:rounded-t-[1.944vw]">
<h1 className="heading1 font-medium">Terms & Conditions</h1>
</div>
<div className="bg-[#232425] lg:px-[5.208vw] md:max-lg:px-4 px-2.5 lg:pt-[2.778vw] md:max-lg:pt-10 pt-8">
<div className="lg:max-w-[38.889vw] md:max-lg:max-w-[66.667vw] lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3">
<h2 className="heading2 font-medium">
Please read these Terms & Conditions carefully. These are the
general Terms & Conditions governing your access and use of this
website (Site).
</h2>
<h2 className="heading2 font-medium">
Acceptance of the Terms and Conditions
</h2>
<div className="lg:space-y-[0.833vw] md:max-lg:space-y-6 space-y-3">
<p className="text2">
This website is owned and operated by GRAFF interactive FZCO
(which term includes all subsidiaries of GRAFF interactive)
(GRAFF interactive Company, we or us). The following terms
and conditions entered into with the Company in respect of which
this website is used together with any documents they expressly
incorporate by reference (collectively, these Terms and
Conditions), govern your access to and use of
https://graffestate.ae/ (the “Website”), including any content,
functionality and services offered on or through the Website
whether as a guest or a registered user
</p>
<p className="text2">
Please read the Terms and Conditions carefully before you start to
use the Website. By using the Website or, where applicable, by
clicking to accept or agree to the Terms and Conditions when this
option is made available to you, you accept and agree to be bound
and abide by these Terms and Conditions and our Privacy Policy,
found at https://graffestate.ae/privacypolicy/, incorporated
herein by reference. If you do not want to agree to these Terms
and Conditions or the Privacy Policy, you must not access or use
the Website.
</p>
</div>
</div>
<div className="lg:max-w-[38.889vw] md:max-lg:max-w-[66.667vw] lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3 lg:pt-[2.778vw] md:max-lg:pt-10 pt-8">
<h2 className="heading2 font-medium">
Changes to the Terms and Conditions
</h2>
<div className="lg:space-y-[0.833vw] md:max-lg:space-y-6 space-y-3">
<p className="text2">
We may revise and update these Terms and Conditions from time to
time in our sole discretion. All changes are effective immediately
when we post them, and apply to all access to and use of the
Website thereafter.
</p>
<p className="text2">
Your continued use of the Website following the posting of revised
Terms and Conditions means that you accept and agree to the
changes. You are expected to check this page from time to time so
you are aware of any changes, as they are binding on you.
</p>
</div>
</div>
<div className="lg:max-w-[38.889vw] md:max-lg:max-w-[66.667vw] lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3 lg:pt-[2.778vw] md:max-lg:pt-10 pt-8">
<h2 className="heading2 font-medium">
Accessing the Website and Account Security
</h2>
<div className="lg:space-y-[0.833vw] md:max-lg:space-y-6 space-y-3">
<p className="text2">
We reserve the right to withdraw or amend the Website, and any
service or material we provide on the Website, in our sole
discretion without notice. We will not be liable if for any reason
all or any part of the Website is unavailable at any time or for
any period. From time to time, we may restrict access to some
parts of the Website, or the entire Website, to any user,
including registered users.
</p>
<p className="text2 whitespace-pre-line">
{`You are responsible for:
Making all arrangements necessary for you to have access to the Website.
Ensuring that all persons who access the Website through your internet connection are aware of these Terms and Conditions and comply with them.`}
</p>
</div>
</div>
<div className="lg:max-w-[38.889vw] md:max-lg:max-w-[66.667vw] lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3 lg:pt-[2.778vw] md:max-lg:pt-10 pt-8">
<h2 className="heading2 font-medium">Intellectual Property Rights</h2>
<div className="lg:space-y-[0.833vw] md:max-lg:space-y-6 space-y-3">
<p className="text2">
The Website and its entire contents, features and functionality
(including but not limited to all information, software, text,
displays, images, video and audio, and the design, selection and
arrangement thereof), are owned by the Company, its licensors or
other providers of such material and are protected by
international copyright, trademark, patent, trade secret and other
intellectual property or proprietary rights laws.
</p>
<p className="text2 whitespace-pre-line">
Your computer may temporarily store copies of such materials in
RAM incidental to your accessing and viewing those materials.
</p>
<p className="text2 whitespace-pre-line">
You may store files that are automatically cached by your Web
browser for display enhancement purposes.
</p>
<p className="text2 whitespace-pre-line">
You may print or download one copy of a reasonable number of pages
of the Website for your own personal, non-commercial use and not
for further reproduction, publication or distribution.
</p>
<p className="text2 whitespace-pre-line">
If we provide desktop, mobile or other applications for download,
you may download a single copy to your computer or mobile device
solely for your own personal, non-commercial use, provided you
agree to be bound by our end user license agreement for such
applications.
</p>
<p className="text2">
If we provide social media features with certain content, you may
take such actions as are enabled by such features.
</p>
<div className="text2">
<span className="font-bold">You must not:</span>
<ul className="list-disc list-inside">
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Modify copies of any materials from this site.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Republish any part of the Website on another website, in any
other medium (print, electronic or otherwise) or as part of
any commercial service.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Use any illustrations, photographs, video or audio sequences
or any graphics separately from the accompanying text.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Delete or alter any copyright, trademark or other proprietary
rights notices from copies of materials from this site.
</li>
</ul>
</div>
<p className="text2">
No right, title or interest in or to the Website or any content on
the site is transferred to you, and all rights not expressly
granted are reserved by the Company. Any use of the Website not
expressly permitted by these Terms and Conditions is a breach of
these Terms and Conditions and may violate copyright, trademark
and other laws.
</p>
</div>
</div>
<div className="lg:max-w-[38.889vw] md:max-lg:max-w-[66.667vw] lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3 lg:pt-[2.778vw] md:max-lg:pt-10 pt-8 lg:pb-[3.056vw] md:max-lg:pb-12 pb-6">
<h2 className="heading2 font-medium">Trademarks </h2>
<div className="">
<p className="text2">
The Companys names, brand names, the Companys logos and all
related names, logos, product and service names, designs and
slogans are trademarks of the Company or its affiliates or
licensors. You must not use such marks without the prior written
permission of the Company. All other names, logos, product and
service names, designs and slogans on this Website are the
trademarks of their respective owners.
</p>
</div>
</div>
<div className="lg:max-w-[38.889vw] md:max-lg:max-w-[66.667vw] lg:space-y-[1.667vw] md:max-lg:space-y-6 space-y-3 lg:pt-[2.778vw] md:max-lg:pt-10 pt-8">
<h2 className="heading2 font-medium">Prohibited Uses</h2>
<div className="lg:space-y-[0.833vw] md:max-lg:space-y-6 space-y-3">
<p className="text2">
You may use the Website only for lawful purposes and in accordance
with these Terms and Conditions.
</p>
<div className="text2 whitespace-pre-line">
<span className="font-bold">
You agree not to use the Website:
</span>
<ul className="list-disc list-inside text-left">
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
In any way that violates any applicable federal, local or
international law or regulation.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
To transmit, or procure the sending of, any advertising or
promotional material, including any junk mail, chain
letter or spam or any other similar solicitation.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
To impersonate or attempt to impersonate the Company, a
Company employee, another user or any other person or entity
(including, without limitation, by using e-mail addresses or
screen names associated with any of the foregoing).
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
To engage in any other conduct that restricts or inhibits
anyones use or enjoyment of the Website, or which, as
determined by us, may harm the Company or users of the Website
or expose them to liability.
</li>
</ul>
</div>
<div className="text2 whitespace-pre-line">
<span className="font-bold">Additionally, you agree not to:</span>
<ul className="list-disc list-inside text-left">
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Use the Website in any manner that could disable, overburden,
damage, or impair the Website or interfere with any other
partys use of the Website, including their ability to engage
in real time activities through the Website.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Use any robot, spider or other automatic device, process or
means to access the Website for any purpose, including
monitoring or copying any of the material on the Website.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Use any manual process to monitor or copy any of the material
on the Website or for any other unauthorized purpose without
our prior written consent.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Use any device, software or routine that interferes with the
proper working of the Website.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Introduce any viruses, trojan horses, worms, logic bombs or
other material which is malicious or technologically harmful.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Attempt to gain unauthorized access to, interfere with, damage
or disrupt any parts of the Website, the server on which the
Website is stored, or any server, computer or database
connected to the Website.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Attack the Website via a denial-of-service attack or a
distributed denial-of-service attack.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Otherwise attempt to interfere with the proper working of the
Website.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Reliance on Information Posted
</li>
</ul>
</div>
<p className="text2">
The information presented on or through the Website is made
available solely for general information purposes. We do not
warrant the accuracy, completeness or usefulness of this
information. Any reliance you place on such information is
strictly at your own risk. We disclaim all liability and
responsibility arising from any reliance placed on such materials
by you or any other visitor to the Website, or by anyone who may
be informed of any of its contents.
</p>
<p className="text2">
GRAFF interactive reserves the absolute right, without any
liability whatsoever, to amend vary or extend at any time the
information mentioned on or through the Website.
</p>
<p className="text2">
<span className="font-bold">Update of the Website</span>
<br />
<br />
We may update the content on the Website from time to time, but
its content is not necessarily complete or up-to-date. Any of the
material on the Website may be out of date at any given time, and
we are under no obligation to update such material.
</p>
<p className="text2">
<span className="font-bold">
Information About You and Your Visits to the Website
</span>
<br />
<br />
All information we collect on this Website is subject to our
Privacy Policy. By using the Website, you consent to all actions
taken by us with respect to your information in compliance with
the Privacy Policy.
</p>
<p className="text2">
<span className="font-bold">
Online Purchases and Other Terms and Conditions
</span>
<br />
<br />
All purchases through our site or other transactions for the sale
of services formed through the Website or as a result of visits
made by you are governed by these Terms and Conditions.
</p>
<p className="text2">
Additional terms and conditions may also apply to specific
portions, services or features of the Website. All such additional
terms and conditions are hereby incorporated by this reference
into these Terms and Conditions.
</p>
<p className="text2">
<span className="font-bold">
Linking to the Website and Social Media Features
</span>
<br />
<br />
You may link to any page, provided you do so in a way that is fair
and legal and does not damage our reputation or take advantage of
it, but you must not establish a link in such a way as to suggest
any form of association, approval or endorsement on our part.
</p>
<div className="text2 whitespace-pre-line">
<span className="font-bold">
This Website may provide certain social media features that
enable you to:
</span>
<ul className="list-disc list-inside text-left">
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Link from your own or certain third-party websites to certain
content on this Website.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Send e-mails or other communications with certain content, or
links to certain content, on this Website.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Cause limited portions of content on this Website to be
displayed or appear to be displayed on your own or certain
third-party websites.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
You may use these features solely as they are provided by us,
solely with respect to the content they are displayed with and
otherwise in accordance with any additional terms and
conditions we provide with respect to such features.
</li>
</ul>
</div>
<div className="text2 whitespace-pre-line">
<span className="font-bold">
Subject to the foregoing, you must not:
</span>
<ul className="list-disc list-inside text-left">
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Establish a link from any website that is not owned by you.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
Otherwise take any action with respect to the materials on
this Website that is inconsistent with any other provision of
these Terms and Conditions.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
You agree to cooperate with us in causing any unauthorized
framing or linking immediately to cease. We reserve the right
to withdraw linking permission without notice.
</li>
<br />
<li className="lg:pl-10 lg:-indent-7 md:max-lg:pl-5 md:max-lg:-indent-4.5 pl-4 -indent-4">
We may disable all or any social media features and any links
at any time without notice in our discretion.
</li>
</ul>
</div>
<p className="text2">
<span className="font-bold">Links From the Website</span>
<br />
<br />
If the Website contains links to other sites and resources
provided by third parties, these links are provided for your
convenience only. We have no control over the contents of those
sites or resources, and accept no responsibility for them or for
any loss or damage that may arise from your use of them. If you
decide to access any of the third party websites linked to this
Website, you do so entirely at your own risk and subject to the
terms and conditions of use for such websites.
</p>
<p className="text2">
<span className="font-bold">Disclaimer of Warranties</span>
<br />
<br />
You understand that we cannot and do not guarantee or warrant that
the Website will be free of viruses or other destructive code. You
are responsible for implementing sufficient procedures and
checkpoints to satisfy your particular requirements for anti-virus
protection and accuracy of data input and output, and for
maintaining a means external to our Website for any reconstruction
of any lost data.
</p>
<p className="text2">
We will not be liable for any loss or damage caused by a
distributed denial-of-service attack, viruses or other
technologically harmful material that may infect your computer
equipment, computer programs, data or other proprietary material
due to your use of the website or any services or items obtained
through the website or to your downloading of any material posted
on it, or on any website linked to it.
</p>
<p className="text2">
Your use of the website, its content and any services or items
obtained through the website is at your own risk. The website, its
content and any services or items obtained through the website are
provided on an as is and as available basis, without any
warranties of any kind, either express or implied. Neither the
company nor any person associated with the company makes any
warranty or representation with respect to the completeness,
security, reliability, quality, accuracy or availability of the
website. Without limiting the foregoing, neither the company nor
anyone associated with the company represents or warrants that the
website, its content or any services or items obtained through the
website will be accurate, reliable, error-free or uninterrupted,
that defects will be corrected, that our site or the server that
makes it available are free of viruses or other harmful components
or that the website or any services will otherwise meet your needs
or expectations.
</p>
<p className="text2">
The company hereby disclaims all warranties of any kind, whether
express or implied, statutory or otherwise, including but not
limited to any warranties of non-infringement.
</p>
<p className="text2">
The foregoing does not affect any warranties which cannot be
excluded or limited under applicable law.
</p>
<p className="text2">
<span className="font-bold">Indemnification</span>
<br />
<br />
You agree to defend, indemnify and hold harmless the Company, its
affiliates, licensors and service providers, and its and their
respective officers, directors, employees, contractors, agents,
licensors, suppliers, successors and assigns from and against any
claims, liabilities, damages, judgments, awards, losses, costs,
expenses or fees (including reasonable attorneys fees) arising
out of or relating to your violation of these Terms and Conditions
or your use of the Website and, any use of the Websites content,
services and products other than as expressly authorized in these
Terms and Conditions or your use of any information obtained from
the Website.
</p>
<p className="text2 whitespace-pre-line">
<span className="font-bold">Waiver and Severability</span>
<br />
<br />
{`No waiver of by the Company of any term or condition set forth in these Terms and Conditions shall be deemed a further or continuing waiver of such term or condition or a waiver of any other term or condition, and any failure of the Company to assert a right or provision under these Terms and Conditions shall not constitute a waiver of such right or provision.
If any provision of these Terms and Conditions is held by a court or other tribunal of competent jurisdiction to be invalid, illegal or unenforceable for any reason, such provision shall be eliminated or limited to the minimum extent such that the remaining provisions of the Terms and Conditions will continue in full force and effect.`}
</p>
<p className="text2 whitespace-pre-line">
<span className="font-bold">Entire Agreement</span>
<br />
<br />
The Terms and Conditions, our Privacy Policy constitute the sole
and entire agreement between you and the Company with respect to
the Website and supersede all prior and contemporaneous
understandings, agreements, representations and warranties, both
written and oral, with respect to the Website.
</p>
<p className="text2 whitespace-pre-line">
<span className="font-bold">Your Comments and Concerns</span>
<br />
<br />
This website is operated and owned by the Company. In respect of
requests for technical support and other communications relating
to the Website, you can contact us by using our website contact
form, or by emailing us at info@graff.tech For feedback or
suggestions, please contact us through the Get in Touch form on
the Website.
</p>
<p className="text2">
You understand and accept that by using this Website in updating,
changing or altering your personal information, address(es) or
contact details, you are accepting that the Company or any of its
affiliates may, at their discretion, use such information as an
alternative information to send legal notices under these Terms
and Conditions. It is your obligation to immediately inform the
Company of any changes to such information.
</p>
</div>
</div>
</div>
<div className="lg:pl-[5.208vw] md:max-lg:pl-4 px-2.5 lg:py-[2.778vw] md:max-lg:py-10 py-8 w-full bg-[#232425] lg:rounded-b-[1.944vw]">
<button
type="button"
onClick={() => lenis?.scrollTo(0)}
className="lg:max-w-[38.889vw] md:max-lg:max-w-[66.667vw] w-full cursor-pointer flex items-center justify-center lg:gap-[0.556vw] gap-2 lg:py-[1.111vw] py-4 lg:rounded-[1.111vw] rounded-2xl bg-[#37393B99]"
>
<p className="btnm font-medium">Top</p>
<div className="text-white lg:size-[1.111vw] size-4">
<ArrowUpIcon />
</div>
</button>
</div>
</>
);
}
export default TermsConditionsPage;
+11
View File
@@ -112,9 +112,20 @@ html {
-webkit-text-fill-color: transparent;
}
.text-gradient-saturated {
background: linear-gradient(45deg, #7a55ff 0%, #c932e8 75%, #ff79d2 95%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.bg-gradient {
background: linear-gradient(87deg, #798fff 15%, #d375ff 100%);
}
.bg-gradient-saturated {
background: linear-gradient(45deg, #7a55ff 0%, #c932e8 75%, #ff79d2 95%);
}
}
@theme {
+30 -2
View File
@@ -54,8 +54,36 @@ export default function RootLayout({
);
return (
<html>
<body className="min-h-screen flex flex-col justify-between">
<html lang="en">
<head>
{/* <Script id="gtm" strategy="beforeInteractive">
{`(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-5XDXJ497');`}
</Script> */}
<Script
src="https://www.googletagmanager.com/gtag/js?id=G-40GLSG8HYM"
strategy="beforeInteractive"
/>
<Script id="google-analytics" strategy="beforeInteractive">
{`window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-40GLSG8HYM');`}
</Script>
</head>
<body className="flex flex-col justify-between min-h-screen">
{/* <noscript>
<iframe
src="https://www.googletagmanager.com/ns.html?id=GTM-5XDXJ497"
height="0"
width="0"
style={{ display: "none", visibility: "hidden" }}
title="Google Tag Manager"
/>
</noscript> */}
<QueryProvider>
<LenisProvider>
<LocaleLayout>
+2 -2
View File
@@ -33,7 +33,7 @@ function CookiesPopup() {
>
<div className="bg-[#37393B]/60 rounded-2xl p-4 flex flex-col gap-5 backdrop-blur-sm">
<div className="flex flex-col gap-2">
<div className="flex items-center gap-2">
<div className="flex gap-2 items-center">
<img
src="/img/components/popups/cookies.png"
alt="popup"
@@ -57,7 +57,7 @@ function CookiesPopup() {
</div>
<Button
onClick={handlePopupClick}
className="flex items-center gap-x-1 w-full justify-center btns bg-gradient rounded-xl 2xl:py-[0.556vw] py-2 hover:opacity-80 transition-opacity cursor-pointer"
className="flex items-center gap-x-1 w-full justify-center btns bg-gradient-saturated rounded-xl 2xl:py-[0.556vw] py-2 hover:opacity-80 transition-opacity cursor-pointer"
>
Accept
</Button>
+3 -3
View File
@@ -105,7 +105,7 @@ export function FeedbackForm() {
mask={"+971 59 999 9999"}
placeholder={"+971 5 X XXX XXXX"}
value={form.watch("phone")}
className="placeholder:btnl placeholder:font-medium placeholder:select-none peer btnl w-full h-full transition-all bg-transparent rounded-none outline-none"
className="placeholder:btnl placeholder:font-medium placeholder:select-none peer btnl w-full h-full bg-transparent rounded-none transition-all outline-none"
/>
<div className="bottom-0 absolute w-full border-b border-[#37393B] peer-focus:border-white -mb-2" />
</div> */}
@@ -159,8 +159,8 @@ export function FeedbackForm() {
</FormProvider>
) : (
<div className="bg-[#37393B99] aspect-[643/480] w-full rounded-2xl flex justify-center items-center">
<div className="flex items-center justify-center gap-3">
<div className="bg-gradient p-3 rounded-full">
<div className="flex gap-3 justify-center items-center">
<div className="bg-gradient-saturated p-3 rounded-full">
<div className="text-white lg:size-[1.667vw] size-6">
<CheckIcon />
</div>
+1 -1
View File
@@ -126,7 +126,7 @@ export function Header() {
<div className="md:justify-end flex flex-1 justify-center">
<Link
href={"#footer"}
className="btnm bg-gradient font-medium lg:px-[1.667vw] lg:py-[1.181vw] py-[17px] px-6 text-nowrap lg:rounded-[1.111vw] rounded-2xl flex items-center"
className="btnm bg-gradient-saturated font-medium lg:px-[1.667vw] lg:py-[1.181vw] py-[17px] px-6 text-nowrap lg:rounded-[1.111vw] rounded-2xl flex items-center"
>
{t("submit_request")}
</Link>
@@ -42,7 +42,7 @@ export function ArticleButtonLinkInput({
{link && title && (
<Link
href={link}
className="rounded-2xl bg-gradient px-6 py-4 flex gap-2 items-center btnm font-medium w-fit"
className="bg-gradient-saturated btnm w-fit flex gap-2 items-center px-6 py-4 font-medium rounded-2xl"
>
{title ?? "Название кнопки"}
<div className="text-white lg:size-[1.111vw] size-4">
@@ -50,7 +50,7 @@ export function ArticleButtonLinkInput({
</div>
</Link>
)}
<div className="flex gap-4 justify-stretch">
<div className="justify-stretch flex gap-4">
<TextInput
name={`blocks.${index}.title`}
placeholder="Название кнопки"
@@ -58,7 +58,7 @@ export function ArticleButtonLinkInput({
<TextInput name={`blocks.${index}.link`} placeholder="Ссылка" />
</div>
<button
className="p-1 absolute top-2 right-2 cursor-pointer"
className="absolute top-2 right-2 p-1 cursor-pointer"
onClick={() => remove(index)}
>
<div className="text-white lg:size-[1.111vw] size-4">
+1 -1
View File
@@ -17,7 +17,7 @@ export function ArticleFormActions({
<>
<div className="space-y-2 absolute left-7 top-5 z-[2]">
<button
className="flex items-center gap-2 lg:py-[0.556vw] lg:px-[0.833vw] py-2 px-3 bg-gradient disabled:bg-[#232425] group disabled:bg-none lg:rounded-[0.833vw] rounded-xl cursor-pointer"
className="flex items-center gap-2 lg:py-[0.556vw] lg:px-[0.833vw] py-2 px-3 bg-gradient-saturated disabled:bg-[#232425] group disabled:bg-none lg:rounded-[0.833vw] rounded-xl cursor-pointer"
disabled={disabled}
onClick={() => handleSave(false)}
>
+2 -2
View File
@@ -27,8 +27,8 @@ function FeedbackModal({ id }: { id: string }) {
return (
<div className="fixed top-[50%] translate-y-[-50%] flex md:flex-row flex-col md:max-w-[695px] max-w-[422px] max-[360px]:max-w-[340px] z-[15] md:p-[48px] p-[32px] max-[360px]:p-[24px] bg-[#37393B99] backdrop-blur-xl backdrop-opacity-60 rounded-2xl">
<div className="flex md:flex-col flex-row md:justify-center items-center md:max-w-[200px] md:gap-y-[16px] gap-x-[24px]">
<div className="p-3 rounded-full bg-gradient translate-x-[4px]">
<div className="z-10 absolute top-[-4px] left-[-4.3px] w-[56px] h-[56px] rounded-full bg-gradient-to-r from-[#6078F299] to-[#C868F599]" />
<div className="p-3 rounded-full bg-gradient-saturated translate-x-[4px]">
<div className="z-10 absolute top-[-4px] left-[-4.3px] w-[56px] h-[56px] rounded-full bg-gradient-saturated" />
<div className="text-white lg:size-[1.389vw] size-4 relative z-20">
<CheckIcon />
</div>
+1 -1
View File
@@ -11,7 +11,7 @@ export function FormModalHeader({
return (
<div className="flex justify-end top-4 right-4 h-[60px] w-full items-end absolute z-[1]">
<button
className="disabled:bg-transparent bg-gradient disabled:bg-none rounded-2xl flex items-center gap-2 p-4 cursor-pointer"
className="disabled:bg-transparent bg-gradient-saturated disabled:bg-none flex gap-2 items-center p-4 rounded-2xl cursor-pointer"
disabled={disabled}
onClick={submitHandler}
>
+1 -1
View File
@@ -170,7 +170,7 @@ export default function QuestionFormModal({
) : (
<div className="bg-[#37393B99] aspect-[643/480] w-full rounded-2xl flex justify-center items-center">
<div className="flex gap-3 justify-center items-center">
<div className="bg-gradient p-3 rounded-full">
<div className="bg-gradient-saturated p-3 rounded-full">
<div className="text-white lg:size-[1.667vw] size-6">
<CheckIcon />
</div>
@@ -84,7 +84,7 @@ export function ArticleSyncPage({ slug }: { slug: string }) {
) : block.type === "ButtonLink" ? (
<Link
href={block.link}
className="bg-gradient btnm w-fit flex gap-3 items-center px-6 py-4 rounded-2xl"
className="bg-gradient-saturated btnm w-fit flex gap-3 items-center px-6 py-4 rounded-2xl"
>
{block.title}
<div className="text-white lg:size-[1.111vw] size-4">
@@ -133,10 +133,10 @@ export function Clients({ showTitle = true }: { showTitle?: boolean }) {
}`}
ref={ref}
>
<div className="flex items-center justify-between">
<div className="flex justify-between items-center">
{showTitle && (
<Title className="mx-auto">
<span className="text-gradient">
<span className="text-gradient-saturated">
{count !== undefined && getCompaniesCount(count, locale)}
</span>{" "}
{t("title")}
-58
View File
@@ -1,58 +0,0 @@
// "use client";
// import { cities, mobileCities } from "@/consts/cities";
// import { useGetMapProjects } from "@/queries/getMapPointByCity";
// import { useCityPointStore } from "@/stores/useCityPointStore";
// import { useState } from "react";
// import { CityPoint } from "./CityPoint";
// import { Slider } from "./Slider";
// import { useMediaQueries } from "@/hooks/useMediaQueries";
// import { Icon } from "@/ui/Icon";
// import { useTranslations } from "next-intl";
// export function Map() {
// const { cityPoint } = useCityPointStore();
// const [currentHovered, setCurrentHovered] = useState<number | undefined>();
// const { data: mapPoint } = useGetMapProjects();
// const { isLg } = useMediaQueries();
// const t = useTranslations("map");
// return (
// <div className="relative">
// <div className="max-lg:overflow-x-auto overflow-y-visible h-full scrollbar-hide max-lg:aspect-[340/620] md:max-lg:-mx-4 max-md:-mx-2.5 mt-16 relative">
// <div className="lg:bg-[url(/img/pages/home/stats/map2.0.png)] bg-[url(/img/pages/home/stats/map_mobile.png)] -mt-19 bg-no-repeat bg-contain lg:aspect-[1432.4/731.98] h-full aspect-[1068.86/586.76] relative">
// {(isLg ? cities : mobileCities).map((point, index) => (
// <CityPoint
// key={point.title}
// {...point}
// active={
// (currentHovered === index && isLg) ||
// (!!cityPoint &&
// point.title === cityPoint.title &&
// (currentHovered === undefined || !isLg))
// }
// index={index}
// setCurrentHovered={setCurrentHovered}
// />
// ))}
// <Slider />
// </div>
// </div>
// <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]" }}
// />
// </div>
// <p className="caption leading-[120%] font-medium select-none">
// {t("instruction")}
// </p>
// </div>
// </div>
// );
// }
+1 -1
View File
@@ -135,7 +135,7 @@ export function Slider() {
<motion.div
animate={{ x: -sliderOffset + "vw" }}
transition={{ bounce: "none" }}
className="flex flex-nowrap items-center relative lg:gap-[0.278vw] gap-1 lg:left-1 left-10"
className="flex flex-nowrap items-center relative lg:gap-[0.278vw] gap-1 lg:left-1 left-10a"
>
{mapProjects?.map(({ company }, index) => (
<button
@@ -7,7 +7,8 @@ function NewStreaming() {
return (
<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-saturated">remote demonstration</span>{" "}
technology allows presenting an object to a customer from anywhere in
the world
</Title>
@@ -31,7 +32,7 @@ function NewStreaming() {
"https://stream.graff.tech/?build=upsideTowersDev&location=a1&lang=en"
}
target="_blank"
className="w-[20.833vw] h-[4.167vw] bg-gradient self-center rounded-2xl lg:rounded-[1.111vw] font-medium [backdrop-filter:blur(3px)] content-center text-center z-[1] max-lg:w-[300px] max-lg:h-[60px]"
className="w-[20.833vw] h-[4.167vw] bg-gradient-saturated self-center rounded-2xl lg:rounded-[1.111vw] font-medium [backdrop-filter:blur(3px)] content-center text-center z-[1] max-lg:w-[300px] max-lg:h-[60px]"
>
<div className="btnl flex gap-2 justify-center">
Start demonstration
@@ -33,7 +33,8 @@ export function PresentationDesktop() {
return (
<div className="mt-[100px] mb-[240px] max-lg:hidden relative">
<Title className="mb-16">
{t("title")} <span className="text-gradient">{t("experience")}</span>{" "}
{t("title")}{" "}
<span className="text-gradient-saturated">{t("experience")}</span>{" "}
{t("increase")}
</Title>
<div className="relative h-[233.334vw]" ref={container}>
@@ -71,7 +72,7 @@ export function PresentationDesktop() {
))}
</div>
</div>
<div ref={target} className="h-full absolute top-0" />
<div ref={target} className="absolute top-0 h-full" />
</div>
</div>
);
@@ -63,13 +63,13 @@ export function PresentationMini() {
return (
<div className="mt-[100px] mb-[240px] lg:hidden space-y-10">
<div
className="md:space-y-12 max-xs:top-0 xs:max-md:top-20 top-10 sticky space-y-5"
className="md:space-y-12 max-xs:top-0 xs:max-md:top-20 sticky top-10 space-y-5"
ref={root}
>
<div ref={titleContainer}>
<Title>
{t("title")}{" "}
<span className="text-gradient">{t("experience")}</span>{" "}
<span className="text-gradient-saturated">{t("experience")}</span>{" "}
{/* и&nbsp;увеличивает темпы продаж
<span className="max-sm:hidden">
{' '}
+5 -2
View File
@@ -3,6 +3,7 @@
import { useGetProjectsQuery } from "@/queries/getProjects";
import { Title } from "@/ui/Title";
import { getProjectsCount } from "@/utils/getProjectsCount";
import { sortProjectsForMainPage } from "@/utils/projectDisplayOrder";
import { ProjectsSection } from "../ProjectsPage/ProjectsSection";
import { useLocale, useTranslations } from "next-intl";
@@ -18,14 +19,16 @@ export function Projects() {
<div className="lg:flex sm:space-y-12 space-y-10">
<Title>
{t("title1")}{" "}
<span className="text-gradient">
<span className="text-gradient-saturated">
{projects && getProjectsCount(projects.length, locale)}{" "}
{t("title2")}
</span>{" "}
{t("title3")}
</Title>
</div>
{projects && <ProjectsSection projects={projects.slice(0, 4)} />}
{projects && (
<ProjectsSection projects={sortProjectsForMainPage(projects)} />
)}
</div>
);
}
+1 -1
View File
@@ -23,7 +23,7 @@ export function Statistics() {
<div className="lg:space-y-[4.444vw] md:max-lg:space-y-[6.25vw] space-y-[11.111vw] lg:mt-40 mt-[100px]">
<Title>
{t("title1")}
<span className="text-gradient">{t("title2")}</span>
<span className="text-gradient-saturated">{t("title2")}</span>
{t("title3")} {count !== undefined && getCompaniesCount(count, locale)}
</Title>
<div
@@ -70,7 +70,7 @@ function CategoryModal({
<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`}
>
<div className="h-12 flex justify-between items-center">
<div className="flex justify-between items-center h-12">
<h1
className={`text-[24px] leading-[0.85] tracking-[-0.04em] w-fit md:text-3xl`}
>
@@ -99,7 +99,7 @@ function CategoryModal({
e.preventDefault();
}}
variants={variantsAnimations}
className="absolute top-20 left-1/2 -translate-x-1/2 w-full flex flex-col items-center md:top-25"
className="md:top-25 flex absolute top-20 left-1/2 flex-col items-center w-full -translate-x-1/2"
>
{description[page].type === "video" ? (
<video
@@ -130,7 +130,7 @@ function CategoryModal({
</p>
</div>
<div className="mt-[32px] flex gap-2">
<div className="btns w-fit px-3 py-[7px] rounded-[17px] bg-gradient-to-r from-[#6078F2] via-[#7583f3] to-[#C868F5]">
<div className="btns w-fit px-3 py-[7px] rounded-[17px] bg-gradient-saturated">
{description[page].package}
</div>
{description[page].isOption && (
@@ -1,19 +1,19 @@
import { PropsWithChildren } from 'react';
import { useUnit } from 'effector-react';
import { PropsWithChildren } from "react";
import { useUnit } from "effector-react";
import {
$configurationStore,
setEquipment,
setDesign,
toggleOption,
toggleSeason,
} from '@/stores/configurator-store/configurationStore';
} from "@/stores/configurator-store/configurationStore";
import {
Design,
Equipment,
ExtraSeasons,
OptionFeatures,
OptionTitles,
} from '@/types/IConfigurator';
} from "@/types/IConfigurator";
function CheckboxItem<T extends keyof OptionTitles, V extends OptionTitles[T]>({
titleCategory,
@@ -29,16 +29,16 @@ function CheckboxItem<T extends keyof OptionTitles, V extends OptionTitles[T]>({
const { opts } = configurator[titleCategory];
function handleCheck(item: V[number]) {
if (typeof opts === 'number') {
if (typeof opts === "number") {
return;
}
if (titleCategory === 'Оборудование') {
if (titleCategory === "Оборудование") {
setEquipment(item as Equipment);
} else if (titleCategory === 'Дизайн интерьеров') {
} else if (titleCategory === "Дизайн интерьеров") {
setDesign(item as Design);
} else if (titleCategory === 'Опции') {
} else if (titleCategory === "Опции") {
toggleOption(item as OptionFeatures);
} else if (titleCategory === 'Сезонность') {
} else if (titleCategory === "Сезонность") {
toggleSeason(item as ExtraSeasons);
}
}
@@ -46,33 +46,33 @@ function CheckboxItem<T extends keyof OptionTitles, V extends OptionTitles[T]>({
return (
<label
className={`relative p-3 bg-[#37393B99] rounded-2xl flex-shrink-0 flex flex-col items-start justify-between snap-always ${className} ${
titleCategory === 'Оборудование'
? 'w-[167px] h-[154px] md:aspect-[242/100] md:flex-1'
: 'w-[160px] h-[154px] md:w-full'
titleCategory === "Оборудование"
? "w-[167px] h-[154px] md:aspect-[242/100] md:flex-1"
: "w-[160px] h-[154px] md:w-full"
}
md:cursor-pointer`}
>
{item === 'Лето' ? (
<div className='text-[10px] bg-gradient px-2 py-0.5 rounded-[30px]'>
{item === "Лето" ? (
<div className="text-[10px] bg-gradient-saturated px-2 py-0.5 rounded-[30px]">
уже в пакете
</div>
) : (
<input
type='checkbox'
type="checkbox"
className={`absolute w-4 h-4 rounded-[4px] appearance-none border border-gray-500
checked:bg-gradient checked:shadow-[0px_0px_2px_0px_#7874F3]
checked:bg-gradient-saturated checked:shadow-[0px_0px_2px_0px_#7874F3]
checked:before:content-[""] checked:before:absolute checked:before:w-full checked:before:h-full
checked:before:bg-[url(/icons/check.svg)] before:bg-[length:14px] checked:before:bg-center checked:before:bg-no-repeat
checked:scale-110 transition-transform
${
titleCategory === 'Сезонность'
? 'pointer-events-none bg-white outline-none border-transparent'
: ''
titleCategory === "Сезонность"
? "pointer-events-none bg-white outline-none border-transparent"
: ""
}`}
checked={
Array.isArray(opts) &&
(titleCategory === ('Опции' as const) ||
titleCategory === ('Сезонность' as const))
(titleCategory === ("Опции" as const) ||
titleCategory === ("Сезонность" as const))
? opts.includes(item as OptionFeatures & ExtraSeasons)
: opts === item
}
@@ -80,11 +80,11 @@ function CheckboxItem<T extends keyof OptionTitles, V extends OptionTitles[T]>({
/>
)}
{children}
<div className='flex flex-col gap-1'>
{<p className='btns text-wrap '>{item.split('.')[0]}</p>}
{titleCategory === 'Дизайн интерьеров' && (
<p className='text-[10px] leading-[120%] text-[#7A7A7A] break-words whitespace-normal'>
{item.split('.')[1]}
<div className="flex flex-col gap-1">
{<p className="btns text-wrap">{item.split(".")[0]}</p>}
{titleCategory === "Дизайн интерьеров" && (
<p className="text-[10px] leading-[120%] text-[#7A7A7A] break-words whitespace-normal">
{item.split(".")[1]}
</p>
)}
</div>
@@ -1,23 +1,33 @@
'use client';
"use client";
import { useGetProjectsQuery } from '@/queries/getProjects';
import { ProjectsSection } from './ProjectsSection';
import { TagsFilters } from './TagsFilters';
import { useSearchParams } from 'next/navigation';
import { useGetProjectsQuery } from "@/queries/getProjects";
import { sortProjectsForProjectsPage } from "@/utils/projectDisplayOrder";
import { useSearchParams } from "next/navigation";
import { useMemo } from "react";
import { ProjectsSection } from "./ProjectsSection";
import { TagsFilters } from "./TagsFilters";
export function ProjectsList() {
const searchParams = useSearchParams();
const tags = searchParams.getAll("tags");
const { data: projects } = useGetProjectsQuery(searchParams.getAll('tags'));
const { data: projects } = useGetProjectsQuery(tags);
const tagKey = tags.join(",");
const orderedProjects = useMemo(() => {
if (!projects?.length) return projects;
return sortProjectsForProjectsPage(projects);
}, [projects, tagKey]);
return (
<div className='grid lg:grid-cols-[1fr_4fr_1fr] items-end gap-x-[34px] relative'>
<TagsFilters tags={searchParams.getAll('tags')} type='project' />
<div className='lg:col-start-2 lg:max-xl:col-end-4 self-start'>
{projects && projects.length ? (
<ProjectsSection projects={projects} />
<div className="grid lg:grid-cols-[1fr_4fr_1fr] items-end gap-x-[34px] relative">
<TagsFilters tags={tags} type="project" />
<div className="lg:col-start-2 lg:max-xl:col-end-4 self-start">
{orderedProjects && orderedProjects.length ? (
<ProjectsSection projects={orderedProjects} />
) : (
<p className='h3 font-medium text-center h-screen'>
<p className="h3 h-screen text-center font-medium">
Projects not found
</p>
)}
@@ -63,7 +63,7 @@ export function TagsFilters({
))}
</div>
<div
className="lg:hidden bottom-6 flex w-full justify-center items-center fixed z-10"
className="lg:hidden flex fixed bottom-6 z-10 justify-center items-center w-full"
ref={ref}
>
{open ? (
@@ -85,7 +85,7 @@ export function TagsFilters({
)}
<button
onClick={handleApplyClick}
className="bg-gradient rounded-2xl btnm flex items-center gap-2 pl-6 py-4 pr-4 font-medium z-[11] -mb-5 mt-5 cursor-pointer"
className="bg-gradient-saturated rounded-2xl btnm flex items-center gap-2 pl-6 py-4 pr-4 font-medium z-[11] -mb-5 mt-5 cursor-pointer"
>
{t("apply")}
<div className="text-white lg:size-[1.111vw] size-4">
@@ -28,7 +28,7 @@ export default function FAQ() {
};
return (
<div className="md:max-lg:mt-[13.021vw] max-md:mt-[27.778vw]">
<div className="mt-[9.722vw] md:max-lg:mt-[13.021vw] max-md:mt-[2.778vw]">
<h2 className="font-medium text-[4.444vw] leading-[95%] tracking-[-0.02em] max-md:text-[8.889vw] mb-[4.444vw]">
Frequently asked questions
</h2>
@@ -49,7 +49,7 @@ export default function FAQ() {
/>
<button
onClick={() => setModal(<QuestionFormModal />)}
className="w-full bg-gradient rounded-[1.111vw] btn-l py-[1.111vw] text-[1.111vw] mt-[0.556vw]
className="w-full bg-gradient-saturated rounded-[1.111vw] btn-l py-[1.111vw] text-[1.111vw] mt-[0.556vw]
md:max-lg:text-[2.083vw] md:max-lg:rounded-[2.083vw] md:max-lg:py-[3.125vw] md:max-lg:mt-[1.302vw]
max-md:text-[4.444vw] max-md:py-[5.556vw] max-md:rounded-[4.444vw] max-md:mt-[2.222vw]"
>
@@ -16,10 +16,10 @@ const Clients = dynamic(
export default function MapAndClients() {
const { data: count } = useGetProjectsCountQuery();
return (
<div className="gap-y-[4.444vw] flex flex-col mt-[9.722vw] md:max-lg:mt-[13.021vw] max-md:mt-[27.778vw]">
<h2 className="font-medium text-[4.444vw] leading-[95%] tracking-[-0.02em] max-md:text-[8.889vw] bg-gradient-to-r from-[#6078F2] to-[#C868F5] bg-clip-text">
<div className="gap-y-[4.444vw] flex flex-col mt-[9.722vw] md:max-lg:mt-[13.021vw] max-md:mt-[27.778vw]">
<h2 className="font-medium text-[4.444vw] leading-[95%] tracking-[-0.02em] max-md:text-[8.889vw]">
Over 15 years of work, we have completed{" "}
<span className="text-transparent bg-clip-text">
<span className="text-gradient-saturated">
{count && getProjectsCount(count, "en")} for real estate developers
</span>{" "}
in the field of interactive technologies
@@ -14,11 +14,11 @@ export default function Slider() {
return (
<div>
<h2
className="mt-[9.722vw] md:max-lg:mt-[13.021vw] max-md:mt-[27.778vw] font-medium text-[4.444vw] leading-[95%] tracking-[-0.02em] text-start mb-[4.444vw] bg-gradient-to-r from-[#7A55FF] via-[#C932E8] to-[#FF79D2] bg-clip-text
className="mt-[9.722vw] md:max-lg:mt-[13.021vw] max-md:mt-[27.778vw] font-medium text-[4.444vw] leading-[95%] tracking-[-0.02em] text-start mb-[4.444vw]
md:max-lg:text-[5.208vw] md:max-lg:mb-[3.125vw]
max-md:text-[8.889vw] max-md:mb-[6.667vw] max-md:leading-[100%]"
>
<span className="text-transparent bg-clip-text">
<span className="text-gradient-saturated">
Immerse your client in your project <br />
</span>{" "}
by a holistic presentation of all key benefits
@@ -24,7 +24,7 @@ const cloudsAnimationStyles = `
}
`;
const VIRTUAL_TOUR_SRC = "/virtualTour/index.html";
const VIRTUAL_TOUR_SRC = `${process.env.NEXT_PUBLIC_S3_BUCKET}graff-estate-irth-vrt/index.html`;
export default function WebDemo() {
const [demoActive, setDemoActive] = useState(false);
@@ -108,11 +108,11 @@ export default function WebDemo() {
return (
<>
<h2
className=" mt-[9.722vw] md:max-lg:mt-[13.021vw] max-md:mt-[27.778vw] font-medium text-[4.444vw] leading-[95%] tracking-[-0.02em] text-start mb-[4.444vw] bg-gradient-to-r from-[#7A55FF] via-[#C932E8] to-[#FF79D2] bg-clip-text
className=" mt-[9.722vw] md:max-lg:mt-[13.021vw] max-md:mt-[27.778vw] font-medium text-[4.444vw] leading-[95%] tracking-[-0.02em] text-start mb-[4.444vw]
md:max-lg:text-[5.208vw] md:max-lg:mb-[3.125vw]
max-md:text-[8.889vw] max-md:mb-[6.667vw] max-md:leading-[100%]"
>
<span className="text-transparent bg-clip-text">
<span className="text-gradient-saturated">
A showroom isn&apos;t the only stage for a great project.
</span>{" "}
With GRAFF.estate Web you can launch your project online using a 360°
@@ -152,7 +152,7 @@ export default function WebDemo() {
<img
src="/img/pages/web/tour-poster.webp"
alt="Tour Poster"
className="w-full h-full object-cover absolute top-0 left-0 opacity-35"
className="opacity-35 object-cover absolute top-0 left-0 w-full h-full"
/>
<span className="line2 font-medium text-center whitespace-pre-line z-[2]">
{`Try the 3D\u2011tour
@@ -160,7 +160,7 @@ export default function WebDemo() {
</span>
<button
onClick={() => setDemoActive(true)}
className="z-[2] bg-gradient btn-l py-[1.389vw] px-[2.778vw] rounded-[1.111vw] mt-[2.778vw] text-[1.111vw]
className="z-[2] bg-gradient-saturated btn-l py-[1.389vw] px-[2.778vw] rounded-[1.111vw] mt-[2.778vw] text-[1.111vw]
md:max-lg:rounded-[2.083vw] md:max-lg:text-[2.083vw] md:max-lg:py-[2.604vw] md:max-lg:px-[5.208vw] md:max-lg:mt-[5.208vw]
max-md:rounded-[4.444vw] max-md:text-[4.444vw] max-md:py-[2.778vw] max-md:px-[5.556vw] max-md:mt-[5.556vw]"
>
@@ -208,8 +208,8 @@ export default function WebDemo() {
Through the interactive website
</p>
<h2 className="line2 font-medium md:max-lg:text-[5.208vw] max-md:text-[8.889vw] max-md:mb-[calc(11.111vw-6.667vw)]">
Offer the client a look at <br className="block max-md:hidden" />{" "}
the completed vision. <br className="block max-md:hidden" /> Today.
Offer the client a look at <br className="max-md:hidden block" />{" "}
the completed vision. <br className="max-md:hidden block" /> Today.
</h2>
<DisplacementCardsWrapper>
@@ -255,7 +255,7 @@ export default function WebDemo() {
className="lg:bottom-0 lg:left-[8.194vw]"
>
<style>{cloudsAnimationStyles}</style>
<div className="cloud-animation flex absolute top-0 h-full ">
<div className="cloud-animation flex absolute top-0 h-full">
<img
draggable={false}
src={"/img/pages/web/demo/clouds.webp"}
@@ -292,7 +292,7 @@ export default function WebDemo() {
</DisplacementCard>
<DisplacementCard index={3} className="lg:top-0 lg:right-[8.194vw]">
<div className="aspect-square flex w-full h-full mix-blend-screen overflow-hidden">
<div className="aspect-square flex overflow-hidden w-full h-full mix-blend-screen">
<video
src="/videos/pages/web/demo/building.mp4"
muted
@@ -13,11 +13,11 @@ export default function WebExperience() {
return (
<div>
<h2
className=" mt-[9.722vw] md:max-lg:mt-[13.021vw] max-md:mt-[27.778vw] font-medium text-[4.444vw] leading-[95%] tracking-[-0.02em] text-start mb-[4.444vw] bg-gradient-to-r from-[#7A55FF] via-[#C932E8] to-[#FF79D2] bg-clip-text
className=" mt-[9.722vw] md:max-lg:mt-[13.021vw] max-md:mt-[27.778vw] font-medium text-[4.444vw] leading-[95%] tracking-[-0.02em] text-start mb-[4.444vw]
md:max-lg:text-[5.208vw] md:max-lg:mb-[8.333vw]
max-md:text-[8.889vw] max-md:mb-[6.667vw] max-md:leading-[100%]"
>
<span className="text-transparent bg-clip-text">
<span className="text-gradient-saturated">
People from around the globe{" "}
</span>
will be able to personally explore and experience your Residential
@@ -45,7 +45,7 @@ export default function WebExperience() {
</span>
<img
src="/img/pages/web/experience/genplan.webp"
className="md:max-lg:h-full absolute top-0 left-0 z-0 h-full object-cover object-left"
className="md:max-lg:h-full object-cover object-left absolute top-0 left-0 z-0 h-full"
alt=""
/>
<div className="absolute inset-0 bg-gradient-to-b from-[#00000099]" />
@@ -119,7 +119,7 @@ export default function WebExperience() {
<img
src="/img/pages/web/experience/parking.webp"
alt=""
className="absolute top-0 left-0 z-0 h-full object-cover "
className="object-cover absolute top-0 left-0 z-0 h-full"
/>
<div className="absolute inset-0 bg-gradient-to-b from-[#00000099]" />
</motion.div>
@@ -100,7 +100,7 @@ export default function InfiniteSlider() {
<div className="flex gap-[0.833vw] absolute left-1/2 bottom-0 -translate-x-1/2 z-10">
<button
aria-label="Previous slide"
className="lg:rounded-[1.111vw] rounded-2xl text-white bg-gradient lg:p-[1.111vw] p-4"
className="lg:rounded-[1.111vw] rounded-2xl text-white bg-gradient-saturated lg:p-[1.111vw] p-4"
onClick={() => moveSlide("left")}
>
<div className="lg:size-[1.111vw] size-4">
@@ -109,7 +109,7 @@ export default function InfiniteSlider() {
</button>
<button
aria-label="Next slide"
className="lg:rounded-[1.111vw] rounded-2xl text-white bg-gradient lg:p-[1.111vw] p-4"
className="lg:rounded-[1.111vw] rounded-2xl text-white bg-gradient-saturated lg:p-[1.111vw] p-4"
onClick={() => moveSlide("right")}
>
<div className="lg:size-[1.111vw] size-4">
+15
View File
@@ -0,0 +1,15 @@
import { useEffect } from "react";
export function useBodyScrollLock(enabled = true) {
useEffect(() => {
if (!enabled) return;
const html = document.documentElement;
const prev = html.style.overflow;
html.style.overflow = "hidden";
return () => {
html.style.overflow = prev;
};
}, [enabled]);
}
+1 -7
View File
@@ -11,12 +11,6 @@ export const queryProjectsOptions = queryOptions({
});
export function useGetProjectsQuery(tags?: string | string[]) {
const tagsTranslation = {
'Interactive presentation': 'Интерактивная презентация',
'Remote showcase': 'Удаленная демонстрация',
'Architectural rendering': 'Архитектурная визуализация',
'Development of websites and 360° Web Tours.': 'Создание сайтов',
}
const { data: auth } = useCheckAuthQuery();
return useQuery(
@@ -28,7 +22,7 @@ export function useGetProjectsQuery(tags?: string | string[]) {
.get(
`projects?locale=en&${
Array.isArray(tags)
? tags.map((tag) => `tags=${tagsTranslation[tag as keyof typeof tagsTranslation]}`).join("&")
? tags.map((tag) => `tags=${tag}`).join("&")
: "tags=" + tags
}`
)
+1
View File
@@ -17,4 +17,5 @@ export interface IProject {
releaseDate: string;
tags: Product[];
enHidden: boolean;
en_order?: number | string | null;
}
+13 -13
View File
@@ -1,22 +1,22 @@
import { ReactNode } from 'react';
import { ReactNode } from "react";
interface ButtonProps {
children: ReactNode;
icon?: JSX.Element;
color?: 'primary' | 'secondary';
width?: 'fit' | 'full';
color?: "primary" | "secondary";
width?: "fit" | "full";
disabled?: boolean;
className?: string;
onClick?: () => void;
type?: 'submit' | 'reset' | 'button';
type?: "submit" | "reset" | "button";
rounded?: string;
}
export function Button({
children,
color = 'primary',
color = "primary",
icon,
width = 'fit',
width = "fit",
disabled = false,
className,
onClick,
@@ -28,20 +28,20 @@ export function Button({
type={type}
disabled={disabled}
onClick={(e) => {
if (type !== 'submit') e.preventDefault();
if (type !== "submit") e.preventDefault();
onClick?.();
}}
className={`group cursor-pointer relative px-6 py-2${
rounded ? ' rounded-' + rounded : ''
rounded ? " rounded-" + rounded : ""
} min-w-fit ${
(color === 'primary' ? 'bg-gradient' : '') ||
(color === 'secondary' ? ' outline-1 outline-[#3D425C]' : '')
(color === "primary" ? "bg-gradient-saturated" : "") ||
(color === "secondary" ? " outline-1 outline-[#3D425C]" : "")
} ${
icon ? 'pr-4' : ''
icon ? "pr-4" : ""
} flex gap-1 items-center overflow-hidden w-${width} ${className} justify-between`}
>
<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')}>
<span className="group-hover:opacity-10 absolute top-0 left-0 w-full h-full bg-black opacity-0 transition-opacity"></span>
<span className={"relative font-medium" + (icon ? "" : " m-auto")}>
{children}
</span>
<span className="relative">{icon}</span>
+5 -3
View File
@@ -1,6 +1,7 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { useEffect, useState } from "react";
import CheckIcon from "@/components/icons/CheckIcon";
import clsx from "clsx";
function CustomCheckbox({
value,
@@ -22,9 +23,10 @@ function CustomCheckbox({
className="flex gap-x-[10px] items-center hover:cursor-pointer"
>
<div
className={`${
checked ? "bg-gradient" : "bg-[#37393B]"
} w-[20px] h-[20px] radius-[5px] rounded relative`}
className={clsx(
"w-[20px] h-[20px] radius-[5px] rounded relative",
checked ? "bg-gradient-saturated" : "bg-[#37393B]"
)}
>
{checked && (
<div className="text-white lg:size-[1.389vw] size-4 absolute top-0">
+9 -9
View File
@@ -1,4 +1,5 @@
import { PropsWithChildren } from 'react';
import { PropsWithChildren } from "react";
import clsx from "clsx";
export function GradientButton({
children,
@@ -14,22 +15,21 @@ export function GradientButton({
<button
onClick={onClick}
className={`outline-none lg:p-[0.069vw] md:max-lg:p-[0.13vw] p-px rounded-full cursor-pointer${
className ? ' ' + className : ''
className ? " " + className : ""
}`}
>
<div
className={`lg:p-[0.556vw] p-1 [1.111vw] bg-[#0f1011] rounded-full${
active
? ' [animation:custom-ping_2s_cubic-bezier(0,0,0.25,1)_infinite_both_running]'
: ''
? " [animation:custom-ping_2s_cubic-bezier(0,0,0.25,1)_infinite_both_running]"
: ""
}`}
>
<div
className={`lg:p-[0.972vw] p-[14px] rounded-full bg-[#37393B99] active:bg-gradient-to-r${
active
? ' [background:linear-gradient(to_bottom_left,#BE69F5,#798FFF)]'
: ''
}`}
className={clsx(
`lg:p-[0.972vw] p-[14px] rounded-full bg-[#37393B99] active:bg-gradient-saturated`,
active && "bg-gradient-saturated"
)}
>
{children}
</div>
+6 -4
View File
@@ -1,3 +1,5 @@
import clsx from "clsx";
export function PostTag({
text,
active = false,
@@ -7,10 +9,10 @@ export function PostTag({
}) {
return (
<div
className={
'lg:px-[0.833vw] px-3 lg:py-[0.486vw] py-[7px] lg:rounded-[1.181vw] rounded-[17px] btns font-medium ' +
(active ? 'bg-gradient' : 'bg-[#37393B99]')
}
className={clsx(
"lg:px-[0.833vw] px-3 lg:py-[0.486vw] py-[7px] lg:rounded-[1.181vw] rounded-[17px] btns font-medium",
active ? "bg-gradient-saturated" : "bg-[#37393B99]"
)}
>
{text}
</div>
+2 -2
View File
@@ -20,10 +20,10 @@ export function StoriesButton() {
{stories?.slice(-3).map(({ id, text, preview }, index) => (
<button
onClick={() => setModal(<StoriesModal startIndex={index} />)}
className="cursor-pointer outline-none rounded-full aspect-square first:translate-x-2 last:-translate-x-2 w-full"
className="aspect-square first:translate-x-2 last:-translate-x-2 w-full rounded-full cursor-pointer outline-none"
key={id}
>
<div className="lg:p-[0.069vw] p-px bg-gradient rounded-full relative aspect-square">
<div className="lg:p-[0.069vw] p-px bg-gradient-saturated rounded-full relative aspect-square">
<img
src={process.env.NEXT_PUBLIC_S3_BUCKET + preview}
alt={text}
+8
View File
@@ -0,0 +1,8 @@
export function closeLegalModalNavigation(): void {
if (typeof window === "undefined") return;
if (window.history.length > 1) {
window.history.back();
} else {
window.location.assign("/");
}
}
+79
View File
@@ -0,0 +1,79 @@
import type { IProject } from "@/types/IProject";
/** Первые 4: главная и начало страницы /projects */
const PRIORITY_MAIN: readonly string[] = [
"HQ by Rove Marasi Bay",
"Al Ain",
"BARAHA TOWN",
"West Bani Yas",
];
/** Следующие на странице /projects после первых четырёх */
const PRIORITY_SECOND: readonly string[] = [
"Rove Home Dubai Marina",
"Al Bahia",
"Rove Home Marasi Drive",
"Al Sader",
"North Bani Yas",
];
function displayTitle(p: IProject): string {
return (p.englishTitle || p.title || "").trim();
}
function normalizeTitle(s: string): string {
return s
.toLowerCase()
.replace(/[\u2013\u2014]/g, "-")
.replace(/\s+/g, " ")
.trim();
}
function matchesExpected(p: IProject, expected: string): boolean {
const t = normalizeTitle(displayTitle(p));
const e = normalizeTitle(expected);
if (t === e) return true;
if (e.length <= 10) return false;
return t.includes(e);
}
function pickInOrder(
all: IProject[],
labels: readonly string[],
used: Set<string>
): IProject[] {
const out: IProject[] = [];
for (const label of labels) {
const found = all.find((p) => !used.has(p.id) && matchesExpected(p, label));
if (found) {
used.add(found.id);
out.push(found);
}
}
return out;
}
function orderValue(p: IProject): number {
const v = p.en_order;
if (v == null) return Number.MAX_SAFE_INTEGER;
return typeof v === "number" ? v : Number(v) || Number.MAX_SAFE_INTEGER;
}
function byEnOrder(a: IProject, b: IProject): number {
return orderValue(a) - orderValue(b);
}
/** Полный порядок для страницы /projects */
export function sortProjectsForProjectsPage(projects: IProject[]): IProject[] {
const used = new Set<string>();
const first = pickInOrder(projects, PRIORITY_MAIN, used);
const second = pickInOrder(projects, PRIORITY_SECOND, used);
const rest = projects.filter((p) => !used.has(p.id)).sort(byEnOrder);
return [...first, ...second, ...rest];
}
/** Только блок из 4 карточек на главной */
export function sortProjectsForMainPage(projects: IProject[]): IProject[] {
const used = new Set<string>();
return pickInOrder(projects, PRIORITY_MAIN, used);
}