Binary files /dev/null and b/public/images/promo-cards/grok-image.png differ
@@ -496,8 +496,8 @@ button {
@media (max-width: 599px) {
.MuiSnackbar-root {
- left: 50% !important;
- right: auto !important;
- transform: translateX(-50%) !important;
+ left: 20px !important;
+ right: 20px !important;
+ transform: none !important;
}
}
\ No newline at end of file
@@ -0,0 +1,93 @@
+.banner {
+ position: fixed;
+ z-index: 9999;
+ background: #1d1d21;
+ border: 1px solid rgba(164, 170, 181, 0.1);
+ border-radius: 16px;
+ padding: 20px;
+ display: flex;
+ flex-direction: column;
+ gap: 24px;
+}
+
+.desktop {
+ right: 24px;
+ bottom: 24px;
+ width: 450px;
+}
+
+.mobile {
+ left: 50%;
+ bottom: 16px;
+ transform: translateX(-50%);
+ width: calc(100% - 32px);
+ max-width: 335px;
+}
+
+.content {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.title {
+ font-size: 24px;
+ font-weight: 600;
+ color: #fff;
+ line-height: 1;
+}
+
+.text {
+ font-size: 14px;
+ color: #a4aab5;
+ line-height: 1.4;
+}
+
+.link {
+ color: #8280ff;
+ text-decoration: underline;
+}
+
+.actions {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+}
+
+.row {
+ display: flex;
+ gap: 10px;
+}
+
+.btnPrimary {
+ flex: 1;
+ height: 40px;
+ border-radius: 10px;
+ background: #fff;
+ color: #000;
+ font-size: 14px;
+ font-weight: 500;
+ cursor: pointer;
+}
+
+.btnOutline {
+ width: 100%;
+ height: 40px;
+ border: 1px solid #a4aab5;
+ border-radius: 10px;
+ background: transparent;
+ color: #fff;
+ font-size: 14px;
+ font-weight: 500;
+ cursor: pointer;
+}
+
+.mobile .row {
+ flex-direction: column;
+}
+
+.mobile .btnPrimary,
+.mobile .btnOutline {
+ width: 100%;
+ flex: none;
+}
@@ -0,0 +1,73 @@
+import React from 'react'
+import Link from 'next/link'
+import { useSession } from 'next-auth/react'
+
+import { useAppSelector } from '#/app/store/store'
+import { getDeviceType } from '#/shared/lib/helpers'
+import { initYandexMetrika, stopYandexMetrika } from '#/shared/lib/yandex-metrika'
+
+import styles from './cookie-consent.module.scss'
+
+function getConsent(): string | null {
+ if (typeof window === 'undefined') return null
+ const value = localStorage.getItem('cookie-consent')
+ if (value === 'all' || value === 'necessary' || value === 'declined') return value
+ return null
+}
+
+export function CookieConsent() {
+ const { status } = useSession()
+ const account_type = useAppSelector((state) => state.user.account_type)
+ const meStatus = useAppSelector((state) => state.user.status)
+ const [consent, setConsent] = React.useState(undefined)
+ const desktop = getDeviceType() === 'desktop'
+
+ React.useEffect(() => {
+ if (meStatus !== 'succeeded') return
+ if (account_type.startsWith('business')) {
+ stopYandexMetrika()
+ return
+ }
+ const stored = getConsent()
+ setConsent(stored)
+ if (stored === 'all') initYandexMetrika()
+ }, [account_type, meStatus])
+
+ const choose = (value: string) => {
+ localStorage.setItem('cookie-consent', value)
+ setConsent(value)
+ if (value === 'all') initYandexMetrika()
+ }
+
+ if (status !== 'authenticated' || meStatus !== 'succeeded') return null
+ if (account_type.startsWith('business') || consent !== null) return null
+
+ return (
+
+
+
Cookies и аналитика
+
+ Мы используем технические cookies для работы сайта и аналитические cookies для улучшения
+ сервиса. Подробнее — в{' '}
+
+ Политике обработки персональных данных
+
+ .
+
+
+
+
+ choose('all')}>
+ Принять все
+
+ choose('necessary')}>
+ Принять необходимые
+
+
+
choose('declined')}>
+ Отклонить
+
+
+
+ )
+}
@@ -15,6 +15,7 @@ import { pingFangFont } from '#/shared/lib/constants/font/font'
import { getDeviceType } from '#/shared/lib/helpers'
import { useBlockTelegram } from '#/shared/lib/hooks/use-block-telegram'
import { useEnv } from '#/shared/lib/hooks/use-env'
+import { CookieConsent } from '#/features/cookie-consent/ui/cookie-consent'
import { Providers } from '#/widgets/providers'
import { setupAxios } from '#/shared/api/axios-interceptors'
@@ -70,6 +71,7 @@ function AppContent({
{Component.getLayout ? Component.getLayout( ) : }
+
@@ -3,37 +3,9 @@ import { Head, Html, Main, NextScript } from 'next/document'
export default function Document() {
return (
-
-
-
+
-
-
-
-
-
@@ -0,0 +1,35 @@
+export function stopYandexMetrika() {
+ if (typeof window === 'undefined') return
+ delete (window as any).__ymInited
+ delete (window as any).ym
+ document.querySelectorAll('script[src*="mc.yandex.ru"]').forEach((s) => s.remove())
+}
+
+export function initYandexMetrika() {
+ if (typeof window === 'undefined' || (window as any).__ymInited) return
+ ;(window as any).__ymInited = true
+
+ ;(function (m: any, e: Document, t: string, r: string, i: string) {
+ m[i] =
+ m[i] ||
+ function (...args: unknown[]) {
+ ;(m[i].a = m[i].a || []).push(args)
+ }
+ m[i].l = 1 * new Date().getTime()
+ for (let j = 0; j < e.scripts.length; j++) {
+ if (e.scripts[j].src === r) return
+ }
+ const k = e.createElement(t) as HTMLScriptElement
+ const a = e.getElementsByTagName(t)[0]
+ k.async = true
+ k.src = r
+ a.parentNode?.insertBefore(k, a)
+ })(window, document, 'script', 'https://mc.yandex.ru/metrika/tag.js', 'ym')
+
+ ;(window as any).ym(93475901, 'init', {
+ clickmap: true,
+ trackLinks: true,
+ accurateTrackBounce: true,
+ webvisor: true,
+ })
+}
@@ -5,6 +5,14 @@
.errorSnackbar {
z-index: 100000;
max-width: 335px;
+
+ @media (max-width: 599px) {
+ max-width: none;
+
+ :global(.MuiAlert-root) {
+ width: 100%;
+ }
+ }
}
.errorSnackbarDesktop {
@@ -84,6 +84,7 @@
line-height: 1.6;
margin-bottom: auto;
max-width: 80%;
+ white-space: pre-line;
}
.card[data-desktop='true'] .description {
@@ -74,4 +74,3 @@ export const PromoCard: React.FC = ({ card, isDesktop, flex = 1
)
}
-
@@ -28,10 +28,10 @@ const Home: NextPageWithLayout = () => {
const promoCards: PromoCardType[] = [
{
- title: 'Flux 1.1',
- image: '/images/promo-cards/flux.png',
+ title: 'Grok Image',
+ image: '/images/promo-cards/grok-image.png',
description:
- 'Современная нейросеть, способная анализировать данные, обрабатывать информацию и генерировать уникальный контент для различных задач.',
+ 'Современная нейросеть, способная анализировать данные,\nобрабатывать информацию и генерировать уникальный \nконтент для различных задач.',
routerlink: '/images/flux',
buttonText: 'Попробовать',
},
@@ -46,7 +46,7 @@ const Home: NextPageWithLayout = () => {
title: 'ChatGPT',
image: '/images/promo-cards/gpt.png',
description: 'Чат-бот, при помощи которого вы сможете найти любой ответ на ваш запрос.',
- routerlink: '/chat-bot/chatgpt',
+ routerlink: '/chat-bot/chatgpt_5_5',
buttonText: 'Попробовать',
},
{
@@ -52,7 +52,3 @@
height: auto;
width: 100%;
}
-
-.footerInputWrap {
- margin-top: 28px;
-}
@@ -39,18 +39,6 @@ export function VoiceCloneMobile() {
))}
-
-
- false}
- styles='chats'
- viewMobileSettings={() => {}}
- currentVersion=''
- input_types={inputTypes}
- />
-
@@ -71,7 +71,18 @@
width: 100%;
max-width: 100%;
gap: 4px;
+ flex-direction: column;
overflow-x: hidden;
+
+ > *:first-child {
+ min-width: 0;
+ max-width: 100%;
+
+ > div:first-child {
+ white-space: normal !important;
+ flex-wrap: wrap !important;
+ }
+ }
}
}
@keyframes fadein {
@@ -86,15 +97,13 @@
}
}
-.icon {
-}
.tags {
display: flex;
gap: 8px;
align-items: center;
- justify-content: flex-end;
+ justify-content: flex-start;
@media screen and (max-width: 768px) {
overflow-x: auto;