@@ -7,15 +7,23 @@ export interface IShortModel {
slug: string
image: string
blocked: boolean
+ tags: IModelTag[]
actual_stat: {
generation_time: string
tokens_cost: string
}
}
+export interface IModelTag {
+ title: string
+ icon: string
+ color: string
+}
+
export interface IModel {
uid: string
title: string
+ blocked: boolean
description: string
slug: string
image: string
@@ -23,6 +31,7 @@ export interface IModel {
parameters: IModelParams[]
versions: IModelVersions[]
inputs: IModelInputs[]
+ tags: IModelTag[]
}
export interface IModelParams {
name: string
@@ -4,19 +4,34 @@ import Link from 'next/link'
import styles from '@/src/shared/styles/chats-bot-pages.module.scss'
-export default function Title(props: any) {
+export interface TitleProps {
+ type: string
+ title: string
+ linkBack?: string
+ rightSlot?: React.ReactNode
+}
+
+export default function Title(props: TitleProps) {
return (
-
+
{' '}
{props.type} •{' '}
- {props.title}
+
+ {props.title}
+
-
- {props.title}
-
+
+
+ {props.title}
+
+
{props.rightSlot}
+
)
}
@@ -30,6 +30,18 @@
}
}
+@keyframes fadein {
+ 0% {
+ opacity: 0;
+ }
+ 50% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
+
.blocked {
display: flex;
align-items: center;
@@ -39,14 +51,40 @@
right: 20px;
background-color: white;
border-radius: 100px;
- padding-right: 20px;
- padding: 8px 12px;
+ // padding-right: 20px;
+ width: 50px;
+ height: 50px;
+ transition: width 0.3s ease-in-out;
- span {
+ &__icon {
+ }
+
+ &:hover {
+ width: 60%;
+ padding: 12px;
+ // height: unset;
+
+ .blocked__icon {
+ animation: fadein 0.6s ease-in-out;
+ }
+
+ .blocked__text {
+ opacity: 1;
+ position: static;
+ animation: fadein 0.6s ease-in-out;
+ display: block;
+ }
+ }
+
+ &__text {
+ position: absolute;
color: #ff2372;
font-weight: 500;
padding-left: 10px;
font-size: 14px;
+ opacity: 0;
+ display: none;
+ min-width: max-content !important;
}
}
@@ -7,6 +7,9 @@ import BlockedSvg from '@/src/assets/svg/blocked.svg?react'
import styles from './card.module.scss'
import { useThemeAndDevice } from '@/src/shared/lib/hooks'
+import { c } from '@/src/shared/lib/helpers'
+import { IModelTag } from '@/src/entities/model-entity'
+import { SvgIcon } from '@/src/shared/ui/svg'
export type CardProps = {
title: string
@@ -15,10 +18,11 @@ export type CardProps = {
uid: string
blocked?: boolean
slug: string
+ tags?: IModelTag[]
accessed_models?: string[] | null
}
-const ChatCard = ({ text, icon, title, uid, slug, accessed_models, blocked }: CardProps) => {
+const ChatCard = ({ text, icon, title, uid, slug, accessed_models, blocked, tags }: CardProps) => {
const link = useMemo(() => {
return accessed_models && !accessed_models.includes(slug)
? '/account?scope=subscribe'
@@ -41,17 +45,51 @@ const ChatCard = ({ text, icon, title, uid, slug, accessed_models, blocked }: Ca
{text}
+ {tags &&
+ tags.map((tag, index) => (
+
+
+
+
+ {tag.title}
+
+
+ ))}
+
{blocked ? (
-
+
Модель недоступна
@@ -23,6 +23,7 @@ function Chat({
deleteMessage,
modelTitle,
currentVersion,
+ blocked,
deviceOs,
}: ChatProps) {
const desktop = device === 'desktop'
@@ -98,6 +99,7 @@ function Chat({
desktop={desktop}
sendMessage={sendMessage}
image={file}
+ blocked={blocked}
unpinImage={clearImage}
imageLoad={onLoadImage}
/>
@@ -26,6 +26,7 @@ interface Input {
// setImage: React.Dispatch>
styles: 'images' | 'chats' | 'audio'
input_types?: IModelInputs[]
+ blocked?: boolean
viewMobileSettings: () => void
currentVersion: string
resendValue?: string
@@ -43,6 +44,7 @@ export const UniqInput: FC = ({
viewMobileSettings,
currentVersion,
resendValue,
+ blocked,
}: Input) => {
const theme = useAppSelector((state) => state.theme.theme)
const [disabled, setDisabled] = React.useState(true)
@@ -94,7 +96,7 @@ export const UniqInput: FC = ({
= ({
},
'& ::placeholder': {
fontSize: '16px',
+ color: theme === 'light' ? '#bbbbbb !important' : 'white !important',
},
'& .Mui-disabled': {
- webkitTextFillColor:
- theme === 'light' ? '#bbbbbb !important' : '#646464 !important',
+ WebkitTextFillColor: theme === 'light' ? '#bbbbbb !important' : '#7d7d7d !important',
fontSize: '16px',
letterSpacing: '0.05px',
fontWeight: '600',
@@ -154,7 +156,7 @@ export const UniqInput: FC = ({
}
}}
// onPaste={(e:ClipboardEvent) => handlePaste(e)}
- value={disabled ? 'Ввод текста недоступен для этой модели' : value}
+ value={disabled || blocked ? 'Ввод текста недоступен для этой модели' : value}
onChange={(e) => {
setValue(e.target.value)
}}
@@ -191,7 +193,7 @@ export const UniqInput: FC = ({
/>
>
)}
- {!disabled && (
+ {!disabled && !blocked && (
{
const deviceType = getTypeDevice(context)
@@ -50,6 +55,8 @@ const Page: React.FC = ({ deviceType, deviceOs }) => {
const { data } = useSession()
const router = useRouter()
+ const { theme } = useThemeAndDevice()
+
const {
chats,
currentChat,
@@ -211,7 +218,97 @@ const Page: React.FC = ({ deviceType, deviceOs }) => {
title={botParams?.title}
>
-
+
+
+ {botParams?.blocked && (
+
+
+
+ Модель недоступна
+
+
+ )}
+
+ {botParams &&
+ botParams.tags.map((tag) => (
+
+
+
+
+ {tag.title}
+
+
+ ))}
+
+ }
+ type={'Чат-боты'}
+ linkBack={'/chat-bot'}
+ />
+
= ({ deviceType, deviceOs }) => {
input_types={botParams?.inputs}
setFile={setFile}
file={file}
+ blocked={botParams?.blocked}
getMessagesPagination={getMessagesPagination}
sendMessage={onSendMessage}
deleteMessage={deleteMessageMemo}
@@ -247,27 +345,31 @@ const Page: React.FC = ({ deviceType, deviceOs }) => {
handleClickChatSetting={handleClickChatSetting}
/>
{desktop && (
-
- {botParams?.versions && botParams.versions?.length !== 0 && (
- <>
-
- ВЕРСИИ
-
-
- >
- )}
+
+ {botParams?.versions &&
+ botParams.versions?.length !== 0 && (
+ <>
+
+ ВЕРСИИ
+
+
+ >
+ )}
{botParams && botParams.parameters?.length > 0 && (
= ({ deviceType, deviceOs }) => {
onClose={hideMobileSettings}
>
- {botParams?.versions && botParams.versions?.length !== 0 && (
- <>
-
- ВЕРСИИ
-
-
- >
- )}
+ {botParams?.versions &&
+ botParams.versions?.length !== 0 && (
+ <>
+
+ ВЕРСИИ
+
+
+ >
+ )}
{botParams && botParams.parameters?.length > 0 ? (
<>
= ({ deviceType }) => {
accessed_models={user.payment_plan.plan.accessed_models}
uid={item.uid}
key={idx}
+ tags={item.tags}
blocked={item.blocked}
title={item.title}
icon={item.image}
@@ -50,6 +50,7 @@ export const Images: React.FC = ({ deviceType }) => {
uid={item.uid}
key={idx}
slug={item.slug}
+ tags={item.tags}
blocked={item.blocked}
text={item.description}
title={item.title}
@@ -1,8 +1,7 @@
import axios from 'axios'
-import { IModel } from '@/src/shared/api/models/models'
import { API_URL } from '@/src/shared/lib/constants'
-import { IShortModel } from '@/src/entities/model-entity'
+import { IModel, IShortModel } from '@/src/entities/model-entity'
const model_api = {
async getBots(token?: string): Promise {
@@ -29,6 +29,18 @@
}
}
+@keyframes fadein {
+ 0% {
+ opacity: 0;
+ }
+ 50% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
+
.blocked {
display: flex;
align-items: center;
@@ -38,16 +50,43 @@
right: 20px;
background-color: white;
border-radius: 100px;
- padding-right: 20px;
- padding: 8px 12px;
+ // padding-right: 20px;
+ width: 50px;
+ height: 50px;
+ transition: width 0.3s ease-in-out;
- span {
+ &__icon {
+ }
+
+ &:hover {
+ width: 60%;
+ padding: 12px;
+ // height: unset;
+
+ .blocked__icon {
+ animation: fadein 0.6s ease-in-out;
+ }
+
+ .blocked__text {
+ opacity: 1;
+ position: static;
+ animation: fadein 0.6s ease-in-out;
+ display: block;
+ }
+ }
+
+ &__text {
+ position: absolute;
color: #ff2372;
font-weight: 500;
padding-left: 10px;
font-size: 14px;
+ opacity: 0;
+ display: none;
+ min-width: max-content !important;
}
}
+
.locked {
display: flex;
align-items: center;
@@ -7,6 +7,9 @@ import BlockedSvg from '@/src/assets/svg/blocked.svg?react'
import styles from './card.module.scss'
import { useThemeAndDevice } from '../lib/hooks'
+import { IModelTag } from '@/src/entities/model-entity'
+import { SvgIcon } from '../ui/svg'
+import { c } from '../lib/helpers'
interface IProps {
text: string
@@ -14,11 +17,12 @@ interface IProps {
title: string
slug: string
uid: string
+ tags?: IModelTag[]
blocked: boolean
accessed_models?: string[] | null
}
-export const Card = ({ text, icon, title, blocked, slug, accessed_models }: IProps) => {
+export const Card = ({ text, icon, title, blocked, slug, accessed_models, tags }: IProps) => {
const link = useMemo(() => {
return accessed_models && !accessed_models.includes(slug)
? '/account?scope=subscribe'
@@ -45,17 +49,51 @@ export const Card = ({ text, icon, title, blocked, slug, accessed_models }: IPro
{text}
+ {tags &&
+ tags.map((tag, index) => (
+
+
+
+
+ {tag.title}
+
+
+ ))}
+
{blocked ? (
-
+
Модель недоступна
@@ -33,6 +33,7 @@ export type ChatProps = {
deviceOs?: DeviceOs
modelType: string
messages: Message[]
+ blocked?: boolean
sendMessage: (message: string, required: (string | null)[]) => boolean
openMobileFilters: () => void
setting?: T
@@ -1,44 +1,68 @@
.main {
- width: 100%;
- display: flex;
- justify-content: flex-start;
- gap: 20px;
- margin-bottom: 24px;
-
- .chatWindow {
- width: 70%;
- }
-
- .settings {
- width: 25%;
- }
-
- @media (max-width:768px) {
- width: 100%;
- display: flex;
-
- flex-direction: column-reverse;
-
- .chatWindow {
- width: 100%;
- }
-
- .settings {
- width: 100%;
- }
- }
+ width: 100%;
+ display: flex;
+ justify-content: flex-start;
+ gap: 20px;
+ margin-bottom: 24px;
+
+ .chatWindow {
+ width: 70%;
+ }
+
+ .settings {
+ width: 25%;
+ }
+
+ @media (max-width: 768px) {
+ width: 100%;
+ display: flex;
+
+ flex-direction: column-reverse;
+
+ .chatWindow {
+ width: 100%;
+ }
+
+ .settings {
+ width: 100%;
+ }
+ }
}
-.wrapModelTitle{
- margin-bottom: 20px;
- margin-top: 15px;
- @media (max-width:768px) {
- margin: 0;
- margin-top: 15px;
- }
- .bigTitle {
- @media (max-width:768px) {
- display: none;
- overflow: hidden;
- }
- }
+.wrapModelTitle {
+ margin-bottom: 20px;
+ margin-top: 15px;
+ @media (max-width: 768px) {
+ margin: 0;
+ margin-top: 15px;
+ }
+ .bigTitle {
+ @media (max-width: 768px) {
+ display: none;
+ overflow: hidden;
+ }
+ }
}
+
+
+.blocked {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: white;
+ border-radius: 100px;
+ padding-right: 20px;
+ padding: 8px 12px;
+ width: max-content;
+
+ span {
+ color: #ff2372;
+ font-weight: 500;
+ padding-left: 10px;
+ font-size: 14px;
+ width: max-content;
+ }
+}
+
+.icon{
+
+}
\ No newline at end of file
@@ -0,0 +1,35 @@
+import axios from 'axios'
+import { useState, useEffect, HtmlHTMLAttributes } from 'react'
+
+export interface SvgIconProps extends HtmlHTMLAttributes {
+ width?: string | number
+ height?: string | number
+ color?: string
+ url: string
+}
+
+export function SvgIcon({ url, color, width, height, ...props }: SvgIconProps) {
+ const [svgContent, setSvgContent] = useState('')
+
+ async function onFetch() {
+ const response = await axios.get(url)
+
+ if (response.status === 200) {
+ setSvgContent(response.data)
+ }
+ }
+
+ useEffect(() => {
+ onFetch()
+ }, [])
+
+ return (
+
+ )
+}
@@ -0,0 +1 @@
+export * from './dynamic-svg'
\ No newline at end of file
@@ -0,0 +1 @@
+export * from './ui'
\ No newline at end of file
@@ -15,3 +15,26 @@
z-index: 100;
}
}
+
+.blocked {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: white;
+ border-radius: 100px;
+ padding-right: 20px;
+ padding: 8px 12px;
+ width: max-content;
+
+ span {
+ color: #ff2372;
+ font-weight: 500;
+ padding-left: 10px;
+ font-size: 14px;
+ width: max-content;
+ }
+}
+
+.icon{
+
+}
\ No newline at end of file
@@ -20,8 +20,10 @@ import { useRouter } from 'next/router'
import { useEffect } from 'react'
import { c, getDeviceType, getOs } from '@/src/shared/lib/helpers'
import { Device, DeviceOs } from '@/src/shared/lib/types/entities'
+import BlockedSvg from '@/src/assets/svg/blocked.svg?react'
import styles from './image-model.module.scss'
+import { SvgIcon } from '@/src/shared/ui/svg'
export interface ImageModelPageProps {
deviceType: Device
@@ -41,7 +43,7 @@ const ImageModelPage = ({ deviceType, deviceOs }: ImageModelPageProps) => {
setVersion,
} = useImageBot(query.slug as string)
- const { ios, desktop } = useThemeAndDevice(deviceType, deviceOs)
+ const { ios, desktop, theme } = useThemeAndDevice(deviceType, deviceOs)
const { error, showError } = useShowData()
@@ -84,7 +86,7 @@ const ImageModelPage = ({ deviceType, deviceOs }: ImageModelPageProps) => {
useEffect(() => {
if (!session) return
- console.log('useEffect')
+ console.log('useEffect')
onFetch()
onObserverMounted()
}, [session?.access])
@@ -96,6 +98,84 @@ const ImageModelPage = ({ deviceType, deviceOs }: ImageModelPageProps) => {
title={botParams ? botParams.title : 'Загрузка...'}
type={'Изображения'}
linkBack={'/images'}
+ rightSlot={
+
+ {botParams?.blocked && (
+
+
+
+ Модель недоступна
+
+
+ )}
+
+ {botParams &&
+ botParams.tags.map((tag) => (
+
+
+
+
+ {tag.title}
+
+
+ ))}
+
+ }
/>