feat: add new popups and new cookies page

This commit is contained in:
2025-05-28 19:24:46 +05:00
parent ba23078579
commit 646bffdf87
10 changed files with 202 additions and 20 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

+12
View File
@@ -0,0 +1,12 @@
import { Metadata } from 'next';
import { PropsWithChildren } from 'react';
export const metadata: Metadata = {
title: 'Политика использования Cookies',
};
function CookiesLayout({ children }: PropsWithChildren) {
return <section>{children}</section>;
}
export default CookiesLayout;
+39
View File
@@ -0,0 +1,39 @@
import { cookies } from '@/consts/cookies';
function CookiesPage() {
return (
<div className='flex flex-col gap-10'>
<div className='flex flex-col gap-4'>
<p className='heading1 font-medium'>Политика использования Cookies</p>
<p className='text2 w-3/4 max-lg:w-full'>
ООО &quot;ГРАФФИНТЕРАКТИВ&quot; (далее ГРАФФИНТЕРАКТИВ) обрабатывает
данные, указанные в настоящем документе (далее Политика), собранные
в процессе использования посетителями нашего веб-сайта. При нажатии
кнопки «Принять» в окне-уведомлении об обработке Cookies, Вы даете
свое согласие на обработку Ваших Cookies. Вы также можете отказаться
от обработки Cookies в соответствии с пунктом 5 настоящей Политики.
</p>
</div>
<div>
{cookies.map(({ content, title }, index) => (
<CookieItem title={title} content={content} key={index} />
))}
</div>
</div>
);
}
function CookieItem({ title, content }: { title: string; content: string[] }) {
return (
<div className='col-span-full grid grid-cols-4 py-6 border-t border-[#3D425C] last:border-b gap-x-2'>
<p className='heading2 font-medium w-full max-lg:col-span-2'>{title}</p>
<p className='space-y-4 col-start-2 col-end-4 col-span-2 text2 w-full max-lg:col-span-2'>
{content.map((item, index) => (
<p key={index}>{item}</p>
))}
</p>
</div>
);
}
export default CookiesPage;
+4 -2
View File
@@ -5,6 +5,7 @@ import './globals.css';
import { QueryProvider } from '@/lib/QueryProvider';
import { LenisProvider } from '@/lib/LenisProvider';
import PopupModal from '@/components/modals/PopupModal';
import CookiesPopup from '@/components/modals/CookiesPopup';
export const metadata: Metadata = {
title: 'Интерактивные решения для застройщиков',
@@ -44,15 +45,16 @@ export default function RootLayout({
}>) {
return (
<html>
<body className="min-h-screen flex flex-col justify-between">
<body className='min-h-screen flex flex-col justify-between'>
<QueryProvider>
<LenisProvider>
<PopupModal />
<CookiesPopup />
{children}
<ModalContainer />
</LenisProvider>
</QueryProvider>
<Script id="metrika-counter" strategy="afterInteractive">
<Script id='metrika-counter' strategy='afterInteractive'>
{`(function (m, e, t, r, i, k, a) {
m[i] =
m[i] ||
+69
View File
@@ -0,0 +1,69 @@
/* eslint-disable @next/next/no-img-element */
'use client';
import { usePopupStore } from '@/stores/usePopupStore';
import { motion } from 'framer-motion';
import Link from 'next/link';
import { useEffect } from 'react';
function CookiesPopup() {
const { isShowCookiesPopup, setIsShowCookiesPopup } = usePopupStore();
function handlePopupClick() {
setIsShowCookiesPopup(false);
}
useEffect(() => {
if (usePopupStore.getState().isShowPopup === undefined) {
const timeout = setTimeout(() => {
setIsShowCookiesPopup(true);
}, 500);
return () => clearTimeout(timeout);
}
}, [setIsShowCookiesPopup]);
return (
<>
{isShowCookiesPopup && (
<motion.div
animate={{ y: -40 }}
transition={{ type: 'spring' }}
className='fixed bottom-0 sm:left-10 left-1/2 max-md:-translate-x-1/2 z-30 w-[350px] lg:w-[23.611vw] p-px lg:p-[0.069vw] rounded-2xl'
>
<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'>
<img
src='/img/components/popups/cookies.png'
alt='popup'
className='w-[2.222vw] h-[2.222vw] object-cover'
/>
<p className='heading2 font-medium'>
Мы используем 
<Link
href='/cookies'
className='underline underline-offset-2'
onClick={handlePopupClick}
>
cookie
</Link>
</p>
</div>
<p className='text-[0.972vw] leading-[135%] w-full'>
Они помогают нам понять, как вы взаимодействуете с нашим сайтом
и сделать его удобнее и лучше.
</p>
</div>
<div
onClick={handlePopupClick}
className='flex items-center gap-x-1 w-full justify-center btns bg-gradient rounded-xl py-[0.556vw] hover:opacity-80 transition-opacity cursor-pointer'
>
Хорошо
</div>
</div>
</motion.div>
)}
</>
);
}
export default CookiesPopup;
+29 -15
View File
@@ -1,3 +1,4 @@
/* eslint-disable @next/next/no-img-element */
'use client';
/* eslint-disable react-hooks/exhaustive-deps */
@@ -9,48 +10,61 @@ import Link from 'next/link';
import { usePopupStore } from '@/stores/usePopupStore';
function Popup() {
const { isShowPopup, setIsShowPopup } = usePopupStore();
const { isShowPopup, setIsShowPopup, isShowCookiesPopup } = usePopupStore();
function handlePopupClick() {
setIsShowPopup(false);
}
useEffect(() => {
if (usePopupStore.getState().isShowPopup === undefined) {
if (
usePopupStore.getState().isShowPopup === undefined &&
!isShowCookiesPopup
) {
const timeout = setTimeout(() => {
setIsShowPopup(true);
}, 10000);
return () => clearTimeout(timeout);
}
}, []);
}, [isShowCookiesPopup]);
return (
<>
{isShowPopup && (
{isShowPopup && !isShowCookiesPopup && (
<motion.div
animate={{ y: -40 }}
transition={{ type: 'spring' }}
className="fixed bottom-0 sm:left-10 left-1/2 max-md:-translate-x-1/2 z-30 w-[320px] lg:w-[22.222vw] p-px lg:p-[0.069vw] rounded-2xl bg-gradient"
className='fixed bottom-0 sm:left-10 left-1/2 max-md:-translate-x-1/2 z-30 w-[350px] lg:w-[23.611vw] p-px lg:p-[0.069vw] rounded-2xl'
>
<div className="bg-[#14161F] rounded-2xl p-4 flex flex-col gap-y-5 lg:gap-y-10">
<p className="btns font-medium leading-[15.4px]">
Новости разработки интерактивных решений для девелоперов в нашем
телеграм канале
</p>
<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'>
<img
src='/img/components/popups/tg.png'
alt='popup'
className='w-[2.222vw] h-[2.222vw] object-cover'
/>
<p className='heading2 font-medium'>GRAFF.estate</p>
</div>
<p className='text-[0.972vw] leading-[135%] w-full'>
Новости разработки интерактивных решений для девелоперов в нашем
телеграм канале
</p>
</div>
<Link
href={'https://t.me/graffestate'}
target="_blank"
target='_blank'
onClick={handlePopupClick}
className="flex items-center gap-x-1 w-full justify-center font-semibold btns bg-gradient rounded-full py-2 hover:opacity-80 transition-opacity"
className='flex items-center gap-x-1 w-full justify-center btns bg-gradient rounded-xl py-[0.556vw] hover:opacity-80 transition-opacity'
>
<TelegramIcon className="lg:w-[1.667vw] lg:h-[1.667vw] w-4 h-4" />
Перейти
</Link>
<button
className="absolute top-2 right-2 hover:bg-white rounded-full flex p-px hover:bg-opacity-10 group transition-colors"
className='absolute top-2 right-2 hover:bg-white rounded-full flex p-px hover:bg-opacity-10 group transition-colors cursor-pointer'
onClick={handlePopupClick}
>
<CloseIcon className="lg:w-[1.111vw] lg:h-[1.111vw] w-4 h-4 m-auto group-hover:text-black transition-colors" />
<CloseIcon className='lg:w-[1.111vw] lg:h-[1.111vw] w-4 h-4 m-auto group-hover:text-black transition-colors' />
</button>
</div>
</motion.div>
+37
View File
@@ -0,0 +1,37 @@
import { ICookies } from '@/types/ICookies';
export const cookies: ICookies[] = [
{
title: 'Cookies: что это?',
content: [
'Файлы cookies — это небольшая часть данных, который веб-сайт запрашивает у браузера, применяемого на вашем компьютере или мобильном устройстве. Cookies содержат сведения о ваших действиях на сайте, а еще могут включать информацию о вашем оборудовании, дате и времени сессии. Файлы cookies хранятся локально на вашем компьютере или мобильном устройстве.',
],
},
{
title: 'Как мы используем Cookies?',
content: [
'Файлы cookie применяются ГРАФФИНТЕРАКТИВ для улучшения и обеспечения надлежащей функциональности веб-сайта, равно как и для совершенствования продуктов ГРАФФИНТЕРАКТИВ — в том числе, посредством установления Ваших предпочтений для предоставления Вам целевой информации по подобным продуктам и услугам.',
],
},
{
title: 'Как мы обрабатываем Cookies?',
content: [
'Мы обрабатываем полученные данные, в том числе, с использованием метрических программ и системы аналитики Яндекс.Метрика.',
],
},
{
title: 'Какие виды Cookies используются?',
content: [
'Сессионные - эти данные позволяют запоминать сведения о Вашем выборе на предыдущей странице, чтобы избежать нужды повторного ввода данных. Они находятся исключительно в оперативной памяти в течение времени, пока пользователь пребывает на странице веб-сайта. Как правило, такие данные стираются после закрытия окна веб-сайта.',
'Постоянные - позволяют идентифицировать Вас как уникального пользователя и вспомнить ранее совершенные Вами действиях при возвращении на веб-сайт. Такие cookies хранятся на Вашем компьютере или мобильном девайсе и не удаляются при закрытии браузера.',
'Аналитические - нужны для того, чтобы улучшить функционал веб-сайта и Ваш пользовательский опыт при его применении. С помощью них мы можем показывать полезную для Вас целевую информацию по продуктам, услугам и сервисам. Такие данные содержат информацию о том, как именно Вы используете веб-сайт, по каким ссылкам переходите, на какие кнопки нажимаете.',
],
},
{
title:
'Не хочу, чтобы мои данные собирали: как отказаться от обработки Сookies?',
content: [
'Вы можете отказаться от сохранения и использования Cookies на своем устройстве или удалить уже сохраненные Cookies в настройках Вашего браузера. Тогда, если Вы откажитесь от обработки Cookies, наш веб-сайт будет использовать только обязательные Cookies.',
],
},
];
+8 -3
View File
@@ -4,16 +4,21 @@ import { persist } from 'zustand/middleware';
interface IPopupStore {
isShowPopup: boolean | undefined;
setIsShowPopup: (isShowPopup: boolean) => void;
isShowCookiesPopup: boolean | undefined;
setIsShowCookiesPopup: (isShowCookiesPopup: boolean) => void;
}
export const usePopupStore = create<IPopupStore>()(
persist(
set => ({
(set) => ({
isShowPopup: undefined,
setIsShowPopup: (isShowPopup: boolean) => set({ isShowPopup }),
isShowCookiesPopup: undefined,
setIsShowCookiesPopup: (isShowCookiesPopup: boolean) =>
set({ isShowCookiesPopup }),
}),
{
name: 'popup',
},
),
}
)
);
+4
View File
@@ -0,0 +1,4 @@
export interface ICookies {
title: string;
content: string[];
}