showPassword((x) => !x)}
+ style={{
+ cursor: 'pointer',
+ display: 'flex',
+ alignItems: 'center',
+ }}
+ >
{passwordShowed ? (
) : (
@@ -183,16 +193,39 @@ export const RegisterEmailForm: React.FC
= ({ successLo
})}
/>
+
+ setSubscribedToEmails(e.target.checked)}
+ size='medium'
+ sx={{
+ color: '#7F7DF3',
+ paddingTop: 0,
+ '&.Mui-checked': { color: '#7F7DF3' },
+ }}
+ />
+
+ Хочу получать полезные материалы про ИИ, обновления моделей и маркетинговые сообщения на email
+
+
{loading ? (
-
+
) : (
)}
-
+
Регистрируясь, вы соглашаетесь с условиями
-
+
Политики обработки персональных данных
и
-
+
Публичной офертой
@@ -232,7 +265,13 @@ export const RegisterEmailForm: React.FC = ({ successLo
}}
>
Есть аккаунт?{' '}
-
+
Войти
@@ -1,16 +1,15 @@
import { Button } from '@mui/material'
import { signIn } from 'next-auth/react'
import Image from 'next/image'
-import React from 'react'
+import React, { useState } from 'react'
-import styles from './yandex-auth-button.module.scss'
+export const YandexAuthButton = ({ children = 'Войти с Яндекс ID' }: { children?: React.ReactNode }) => {
+ const [hovered, setHovered] = useState(false)
-interface YandexAuthButtonProps {}
-
-export const YandexAuthButton = ({}: YandexAuthButtonProps) => {
return (
)
}
@@ -0,0 +1,18 @@
+.root {
+ width: 100%;
+ color: #80808e;
+ font-weight: 400;
+ text-align: center;
+ letter-spacing: -0.01em;
+ line-height: 100%;
+}
+
+.desktop {
+ margin-top: 6px;
+ font-size: 11px;
+}
+
+.mobile {
+ margin-top: 6px;
+ font-size: 10px;
+}
@@ -0,0 +1,13 @@
+import { c } from '#/shared'
+
+import styles from './chat-disclaimer.module.scss'
+
+export const ChatDisclaimer = ({ desktop }: { desktop: boolean }) => {
+ return (
+
+ ИИ может делать ошибки, перепроверяйте результат.
+ {desktop ? ' ' :
}
+ Не вводите личные данные других людей без их согласия.
+
+ )
+}
@@ -120,7 +120,7 @@ const Register: NextPageWithLayout = () => {
{referral === '' && isReferral && (
<>
-
+ Зарегистрироваться с Яндекс ID
или email
@@ -1,72 +0,0 @@
-import { Box, LinearProgress, linearProgressClasses, Stack, styled, Typography } from '@mui/material'
-
-import { commaSeparated } from '#/shared'
-import { formatPlanPrice } from '#/shared/lib/helpers/format-plan-price'
-import { declineToken } from '#/shared/lib/helpers/get-token'
-
-import styles from '../subscription.module.scss'
-
-const BorderLinearProgress = styled(LinearProgress)(() => ({
- height: 18,
- borderRadius: 6,
- [`&.${linearProgressClasses.colorPrimary}`]: {
- backgroundColor: '#EFF0F2',
- },
- [`& .${linearProgressClasses.bar}`]: {
- borderRadius: 6,
- backgroundColor: '#8280FF',
- },
-}))
-
-interface CurrentPlanAndBalanceLegacyProps {
- balance: number
- planTokenLimit: string
- planPrice: string
- isIndividual: boolean
-}
-
-export const CurrentPlanAndBalanceLegacy = ({
- balance,
- planTokenLimit,
- planPrice,
- isIndividual,
-}: CurrentPlanAndBalanceLegacyProps) => {
- const formatterdPlanPrice = formatPlanPrice(planPrice, isIndividual)
- const planTokenLimitNumber = Number(planTokenLimit)
- const percentage = planTokenLimitNumber > 0 ? Math.min(100, Math.max(0, (balance / planTokenLimitNumber) * 100)) : 0
-
- return (
-
-
-
- Последняя оплата
-
-
-
- {commaSeparated(Math.round(Number(planTokenLimit)))} токенов
-
-
- {formatterdPlanPrice}
-
-
-
-
- Мой баланс
-
- {declineToken(balance.toString())}
- {Math.round(percentage)} %
-
-
-
-
- )
-}
@@ -1,93 +0,0 @@
-import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'
-import { Box, MenuItem, Select, SelectChangeEvent, Stack, Typography } from '@mui/material'
-
-import { IFeatures } from '../../api'
-import { categoryIconMap } from '../../lib/category-icon-map'
-import { formatFeatureValue } from '../../lib/format-feature-value'
-
-import styles from '../subscription.module.scss'
-
-interface FeaturesSectionLegacyProps {
- currentTokenLimitUID: string
- onCurrentTokenLimitUIDChange: (limit: string) => void
- features: IFeatures[] | null
- tokenLimits: Array<{ value: string; label: string }>
-}
-
-export const FeaturesSectionLegacy = ({
- currentTokenLimitUID,
- onCurrentTokenLimitUIDChange,
- features,
- tokenLimits,
-}: FeaturesSectionLegacyProps) => {
- return (
-
-
-
-
-
-
- {features?.map((featureGroup, idx) => (
-
-
- {categoryIconMap[featureGroup.name] && (
- {categoryIconMap[featureGroup.name]}
- )}
- {featureGroup.name}
-
-
-
- {featureGroup.features.map((feature, featureIdx) => {
- let { number, unit, more } = formatFeatureValue(feature.quantity, feature.measurement_unit)
-
- return (
-
- {feature.name}
-
-
- {number == '-' ? (
-
- ) : (
- <>
- {' '}
- {more} {number}
- {unit}
- >
- )}
-
-
-
- )
- })}
-
-
- ))}
-
-
-
- Для каждой отдельной модели указано примерное количество генераций, как если бы вы пользовались{' '}
- только ей.
- Количество генераций может варьироваться в зависимости от используемых параметров каждой конкретной модели.
-
-
- )
-}
@@ -1,101 +0,0 @@
-import React from 'react'
-import { Box } from '@mui/material'
-import Router from 'next/router'
-import { useSession } from 'next-auth/react'
-
-import LightningSvg from '#/assets/svg/lightning.svg?react'
-import { accountApi } from '#/shared/api/account-endpoints'
-import { commaSeparated } from '#/shared/lib/helpers'
-import { useShowDataStore } from '#/shared/lib/hooks/use-show-data'
-import { IFeatures, IOffer, formatFeatureValue } from '#/views/subscription'
-
-import styles from '../offer.module.scss'
-
-interface IOfferLegacyProps extends IOffer {
- device: 'desktop' | 'mobile'
- isCurrentSubscription?: boolean
- index?: number
-}
-
-const OfferLegacy: React.FC = ({ uid, tokens_per_plan, price, grouped_features, isCurrentSubscription, index }) => {
- const { data } = useSession()
- const { showMessage } = useShowDataStore()
-
- const unitMap: Record = {
- Изображения: 'изображений',
- 'Чат-боты': 'страниц текста',
- Видео: 'видео',
- Аудио: 'аудиозаписей',
- }
-
- const formatFeatures = (groupedFeatures: IFeatures[] | undefined): string[] => {
- if (!groupedFeatures || !Array.isArray(groupedFeatures)) {
- return []
- }
-
- return groupedFeatures.flatMap((group) => {
- if (!group?.features || !Array.isArray(group.features)) {
- return []
- }
-
- const limit = group.name === 'Изображения' ? 2 : 1
- const featuresToShow = group.features.slice(0, limit)
-
- return featuresToShow
- .filter((feature) => feature.quantity !== 0)
- .map((feature) => {
- const groupName = unitMap[group.name] || group.name
- const { number, more } = formatFeatureValue(feature.quantity, feature.measurement_unit)
- return `${more ? more + ' ' : ''}${number} ${groupName} в ${feature.name}`
- })
- })
- }
-
- const formattedFeatures = formatFeatures(grouped_features)
-
- const pay = async (planUid: string) => {
- try {
- const urlForPay = await accountApi.payProduct(data!.access, planUid)
- if (urlForPay) await Router.push(urlForPay)
- } catch (err) {
- const message = err instanceof Error ? err.message : 'Ошибка оплаты'
- showMessage(message)
- }
- }
-
- return (
-
-
-
-
-
- {commaSeparated(Math.round(Number(tokens_per_plan)))} токенов
-
-
-
-
-
- {formattedFeatures.map((feature, idx) => (
- -
- {feature}
-
- ))}
-
-
-
- {commaSeparated(parseInt(price) ?? 0)} ₽
- {
- e.stopPropagation()
- pay(uid)
- }}
- >
- Оплатить
-
-
-
- )
-}
-
-export default OfferLegacy
@@ -1,32 +0,0 @@
-import { Box } from '@mui/material'
-
-import { IOffer } from '../../api'
-
-import OfferLegacy from './offer-legacy'
-
-import styles from '../subscription.module.scss'
-
-interface PlansSectionLegacyProps {
- offers: IOffer[] | null
- currentOfferUID: string
-}
-
-export const PlansSectionLegacy = ({ offers, currentOfferUID: _currentOfferUID }: PlansSectionLegacyProps) => {
- return (
-
-
- {offers?.map((offer, idx) => {
- return (
-
- )
- })}
-
-
- )
-}
@@ -1,84 +0,0 @@
-import { useEffect, useState } from 'react'
-import { Box, Typography } from '@mui/material'
-import { useSession } from 'next-auth/react'
-
-import { useAppSelector } from '#/app/store/store'
-import { commaSeparated } from '#/shared'
-import { accountApi } from '#/shared/api/account-endpoints'
-import { balanceSelector } from '#/shared/lib/selectors'
-
-import { IFeatures, IOffer } from '../../api'
-
-import { FaqSection } from '../faq-section'
-import { CurrentPlanAndBalanceLegacy } from './current-plan-and-balance-legacy'
-import { FeaturesSectionLegacy } from './features-section-legacy'
-import { PlansSectionLegacy } from './plans-section-legacy'
-
-import styles from '../subscription.module.scss'
-
-export const SubscriptionLegacyPage = () => {
- const [offers, setOffers] = useState(null)
- const [currentTokenLimitUID, setCurrentTokenLimitUID] = useState('')
- const [tokenLimits, setTokenLimits] = useState>([])
- const [currentFeatures, setCurrentFeatures] = useState([])
- const {
- uid: paymentPlanUid,
- tokens_per_plan: planTokenLimit,
- price: planPrice,
- individual: isIndividual,
- } = useAppSelector((state) => state.user.payment_plan.plan)
- const balance = useAppSelector(balanceSelector)
- const { data } = useSession()
-
- useEffect(() => {
- if (data?.access) {
- accountApi.getPaymentsPlans(data?.access).then((res) => {
- if (res) {
- setOffers(res)
- setCurrentTokenLimitUID(res[0].uid)
- setTokenLimits(
- res.map((offer) => ({
- value: offer.uid,
- label: `${commaSeparated(Math.round(Number(offer.tokens_per_plan)))} токенов`,
- }))
- )
- }
- })
- }
- }, [data?.access])
-
- useEffect(() => {
- if (offers && currentTokenLimitUID) {
- const foundOffer = offers.find((offer) => offer.uid === currentTokenLimitUID)
- if (foundOffer) {
- setCurrentFeatures(foundOffer.grouped_features)
- }
- }
- }, [currentTokenLimitUID, offers])
-
- return (
-
-
- Оплата
-
-
-
-
-
-
-
-
-
-
- )
-}
@@ -5,7 +5,7 @@ import { useShowDataStore } from '#/shared/lib/hooks/use-show-data'
import styles from './individual-subscription-notice.module.scss'
-export const IndividualSubscriptionNotice = ({ contactEmail = 't.bikbov@air.fail' }: { contactEmail?: string }) => {
+export const IndividualSubscriptionNotice = ({ contactEmail = 'help@air.fail' }: { contactEmail?: string }) => {
const { showMessage } = useShowDataStore()
const copyEmail = useCallback(async () => {
@@ -1,19 +1,9 @@
import { NextPageWithLayout } from '#/pages/_app'
-import { useFeatureFlag } from '#/shared/lib/hooks/use-feature-flag'
-
-import { SubscriptionLegacyPage } from './legacy/subscription-legacy'
import { SubscriptionRecurrentPage } from './subscription-recurrent'
-const RECURRENT_PAYMENTS_FLAG = 'recurrent-payments-enabled'
const SubscriptionPage: NextPageWithLayout = () => {
- const recurrentPaymentsEnabled = useFeatureFlag(RECURRENT_PAYMENTS_FLAG)
-
- if (recurrentPaymentsEnabled) {
return
- }
-
- return
}
export default SubscriptionPage