update pay function
This commit is contained in:
@@ -1,144 +0,0 @@
|
||||
// src/components/Navbars/components/SecondaryNav/config.js
|
||||
// 二级导航配置数据
|
||||
|
||||
/**
|
||||
* 二级导航配置结构
|
||||
* - key: 匹配的路径前缀
|
||||
* - title: 导航组标题
|
||||
* - items: 导航项列表
|
||||
* - path: 路径
|
||||
* - label: 显示文本
|
||||
* - badges: 徽章列表 (可选)
|
||||
* - external: 是否外部链接 (可选)
|
||||
*/
|
||||
export const secondaryNavConfig = {
|
||||
'/community': {
|
||||
title: '高频跟踪',
|
||||
items: [
|
||||
{
|
||||
path: '/community',
|
||||
label: '事件中心',
|
||||
badges: [
|
||||
{ text: 'HOT', colorScheme: 'green' },
|
||||
{ text: 'NEW', colorScheme: 'red' }
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/concepts',
|
||||
label: '概念中心',
|
||||
badges: [{ text: 'NEW', colorScheme: 'red' }]
|
||||
},
|
||||
{
|
||||
path: '/data-browser',
|
||||
label: '数据浏览器',
|
||||
badges: [{ text: 'NEW', colorScheme: 'red' }]
|
||||
}
|
||||
]
|
||||
},
|
||||
'/concepts': {
|
||||
title: '高频跟踪',
|
||||
items: [
|
||||
{
|
||||
path: '/community',
|
||||
label: '事件中心',
|
||||
badges: [
|
||||
{ text: 'HOT', colorScheme: 'green' },
|
||||
{ text: 'NEW', colorScheme: 'red' }
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/concepts',
|
||||
label: '概念中心',
|
||||
badges: [{ text: 'NEW', colorScheme: 'red' }]
|
||||
},
|
||||
{
|
||||
path: '/data-browser',
|
||||
label: '数据浏览器',
|
||||
badges: [{ text: 'NEW', colorScheme: 'red' }]
|
||||
}
|
||||
]
|
||||
},
|
||||
'/data-browser': {
|
||||
title: '高频跟踪',
|
||||
items: [
|
||||
{
|
||||
path: '/community',
|
||||
label: '事件中心',
|
||||
badges: [
|
||||
{ text: 'HOT', colorScheme: 'green' },
|
||||
{ text: 'NEW', colorScheme: 'red' }
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/concepts',
|
||||
label: '概念中心',
|
||||
badges: [{ text: 'NEW', colorScheme: 'red' }]
|
||||
},
|
||||
{
|
||||
path: '/data-browser',
|
||||
label: '数据浏览器',
|
||||
badges: [{ text: 'NEW', colorScheme: 'red' }]
|
||||
}
|
||||
]
|
||||
},
|
||||
'/limit-analyse': {
|
||||
title: '行情复盘',
|
||||
items: [
|
||||
{
|
||||
path: '/limit-analyse',
|
||||
label: '涨停分析',
|
||||
badges: [{ text: 'FREE', colorScheme: 'blue' }]
|
||||
},
|
||||
{
|
||||
path: '/stocks',
|
||||
label: '个股中心',
|
||||
badges: [{ text: 'HOT', colorScheme: 'green' }]
|
||||
},
|
||||
{
|
||||
path: '/trading-simulation',
|
||||
label: '模拟盘',
|
||||
badges: [{ text: 'NEW', colorScheme: 'red' }]
|
||||
}
|
||||
]
|
||||
},
|
||||
'/stocks': {
|
||||
title: '行情复盘',
|
||||
items: [
|
||||
{
|
||||
path: '/limit-analyse',
|
||||
label: '涨停分析',
|
||||
badges: [{ text: 'FREE', colorScheme: 'blue' }]
|
||||
},
|
||||
{
|
||||
path: '/stocks',
|
||||
label: '个股中心',
|
||||
badges: [{ text: 'HOT', colorScheme: 'green' }]
|
||||
},
|
||||
{
|
||||
path: '/trading-simulation',
|
||||
label: '模拟盘',
|
||||
badges: [{ text: 'NEW', colorScheme: 'red' }]
|
||||
}
|
||||
]
|
||||
},
|
||||
'/trading-simulation': {
|
||||
title: '行情复盘',
|
||||
items: [
|
||||
{
|
||||
path: '/limit-analyse',
|
||||
label: '涨停分析',
|
||||
badges: [{ text: 'FREE', colorScheme: 'blue' }]
|
||||
},
|
||||
{
|
||||
path: '/stocks',
|
||||
label: '个股中心',
|
||||
badges: [{ text: 'HOT', colorScheme: 'green' }]
|
||||
},
|
||||
{
|
||||
path: '/trading-simulation',
|
||||
label: '模拟盘',
|
||||
badges: [{ text: 'NEW', colorScheme: 'red' }]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
@@ -1,138 +0,0 @@
|
||||
// src/components/Navbars/components/SecondaryNav/index.js
|
||||
// 二级导航栏组件 - 显示当前一级菜单下的所有二级菜单项
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Container,
|
||||
HStack,
|
||||
Text,
|
||||
Button,
|
||||
Flex,
|
||||
Badge,
|
||||
useColorModeValue
|
||||
} from '@chakra-ui/react';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useNavigationEvents } from '../../../../hooks/useNavigationEvents';
|
||||
import { secondaryNavConfig } from './config';
|
||||
|
||||
/**
|
||||
* 二级导航栏组件
|
||||
* 根据当前路径显示对应的二级菜单项
|
||||
*
|
||||
* @param {Object} props
|
||||
* @param {boolean} props.showCompletenessAlert - 是否显示完整性提醒(影响 sticky top 位置)
|
||||
*/
|
||||
const SecondaryNav = memo(({ showCompletenessAlert }) => {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
// 颜色模式
|
||||
const navbarBg = useColorModeValue('gray.50', 'gray.700');
|
||||
const itemHoverBg = useColorModeValue('white', 'gray.600');
|
||||
const borderColorValue = useColorModeValue('gray.200', 'gray.600');
|
||||
|
||||
// 导航埋点
|
||||
const navEvents = useNavigationEvents({ component: 'secondary_nav' });
|
||||
|
||||
// 找到当前路径对应的二级导航配置
|
||||
const currentConfig = Object.keys(secondaryNavConfig).find(key =>
|
||||
location.pathname.includes(key)
|
||||
);
|
||||
|
||||
// 如果没有匹配的二级导航,不显示
|
||||
if (!currentConfig) return null;
|
||||
|
||||
const config = secondaryNavConfig[currentConfig];
|
||||
|
||||
return (
|
||||
<Box
|
||||
bg={navbarBg}
|
||||
borderBottom="1px"
|
||||
borderColor={borderColorValue}
|
||||
py={2}
|
||||
position="sticky"
|
||||
top={showCompletenessAlert ? "120px" : "60px"}
|
||||
zIndex={100}
|
||||
>
|
||||
<Container maxW="container.xl" px={4}>
|
||||
<HStack spacing={1}>
|
||||
{/* 显示一级菜单标题 */}
|
||||
<Text fontSize="sm" color="gray.500" mr={2}>
|
||||
{config.title}:
|
||||
</Text>
|
||||
|
||||
{/* 二级菜单项 */}
|
||||
{config.items.map((item, index) => {
|
||||
const isActive = location.pathname.includes(item.path);
|
||||
|
||||
return item.external ? (
|
||||
<Button
|
||||
key={index}
|
||||
as="a"
|
||||
href={item.path}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
bg="transparent"
|
||||
color="inherit"
|
||||
fontWeight="normal"
|
||||
_hover={{ bg: itemHoverBg }}
|
||||
borderRadius="md"
|
||||
px={3}
|
||||
>
|
||||
<Flex align="center" gap={2}>
|
||||
<Text>{item.label}</Text>
|
||||
{item.badges && item.badges.length > 0 && (
|
||||
<HStack spacing={1}>
|
||||
{item.badges.map((badge, bIndex) => (
|
||||
<Badge key={bIndex} size="xs" colorScheme={badge.colorScheme}>
|
||||
{badge.text}
|
||||
</Badge>
|
||||
))}
|
||||
</HStack>
|
||||
)}
|
||||
</Flex>
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
key={index}
|
||||
onClick={() => {
|
||||
// 追踪侧边栏菜单点击
|
||||
navEvents.trackSidebarMenuClicked(item.label, item.path, 2, false);
|
||||
navigate(item.path);
|
||||
}}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
bg={isActive ? 'blue.50' : 'transparent'}
|
||||
color={isActive ? 'blue.600' : 'inherit'}
|
||||
fontWeight={isActive ? 'bold' : 'normal'}
|
||||
borderBottom={isActive ? '2px solid' : 'none'}
|
||||
borderColor="blue.600"
|
||||
borderRadius={isActive ? '0' : 'md'}
|
||||
_hover={{ bg: isActive ? 'blue.100' : itemHoverBg }}
|
||||
px={3}
|
||||
>
|
||||
<Flex align="center" gap={2}>
|
||||
<Text>{item.label}</Text>
|
||||
{item.badges && item.badges.length > 0 && (
|
||||
<HStack spacing={1}>
|
||||
{item.badges.map((badge, bIndex) => (
|
||||
<Badge key={bIndex} size="xs" colorScheme={badge.colorScheme}>
|
||||
{badge.text}
|
||||
</Badge>
|
||||
))}
|
||||
</HStack>
|
||||
)}
|
||||
</Flex>
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
</HStack>
|
||||
</Container>
|
||||
</Box>
|
||||
);
|
||||
});
|
||||
|
||||
SecondaryNav.displayName = 'SecondaryNav';
|
||||
|
||||
export default SecondaryNav;
|
||||
21
src/views/AgentChat/.gitignore
vendored
Normal file
21
src/views/AgentChat/.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Next.js 应用忽略文件
|
||||
neuratalk/node_modules/
|
||||
neuratalk/.next/
|
||||
neuratalk/.env.local
|
||||
neuratalk/.env.production
|
||||
neuratalk/out/
|
||||
neuratalk/build/
|
||||
|
||||
# 日志文件
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# IDE
|
||||
.idea
|
||||
.vscode
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,53 +0,0 @@
|
||||
// src/views/AgentChat/index.js
|
||||
// Agent聊天页面
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Box,
|
||||
Container,
|
||||
Heading,
|
||||
Text,
|
||||
VStack,
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import { ChatInterfaceV2 } from '../../components/ChatBot';
|
||||
|
||||
/**
|
||||
* Agent聊天页面
|
||||
* 提供基于MCP的AI助手对话功能
|
||||
*/
|
||||
const AgentChat = () => {
|
||||
const bgColor = useColorModeValue('gray.50', 'gray.900');
|
||||
const cardBg = useColorModeValue('white', 'gray.800');
|
||||
|
||||
return (
|
||||
<Box minH="calc(100vh - 200px)" bg={bgColor} py={8}>
|
||||
<Container maxW="container.xl" h="100%">
|
||||
<VStack spacing={6} align="stretch" h="100%">
|
||||
{/* 页面标题 */}
|
||||
<Box>
|
||||
<Heading size="lg" mb={2}>AI投资助手</Heading>
|
||||
<Text color="gray.600" fontSize="sm">
|
||||
基于MCP协议的智能投资顾问,支持股票查询、新闻搜索、概念分析等多种功能
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
{/* 聊天界面 */}
|
||||
<Box
|
||||
flex="1"
|
||||
bg={cardBg}
|
||||
borderRadius="xl"
|
||||
boxShadow="xl"
|
||||
overflow="hidden"
|
||||
h="calc(100vh - 300px)"
|
||||
minH="600px"
|
||||
>
|
||||
<ChatInterfaceV2 />
|
||||
</Box>
|
||||
</VStack>
|
||||
</Container>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default AgentChat;
|
||||
@@ -1,857 +0,0 @@
|
||||
// src/views/AgentChat/index_v3.js
|
||||
// Agent聊天页面 V3 - 带左侧会话列表和用户信息集成
|
||||
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
VStack,
|
||||
HStack,
|
||||
Text,
|
||||
Input,
|
||||
IconButton,
|
||||
Button,
|
||||
Avatar,
|
||||
Heading,
|
||||
Divider,
|
||||
Spinner,
|
||||
Badge,
|
||||
useColorModeValue,
|
||||
useToast,
|
||||
Progress,
|
||||
Fade,
|
||||
Collapse,
|
||||
useDisclosure,
|
||||
InputGroup,
|
||||
InputLeftElement,
|
||||
Menu,
|
||||
MenuButton,
|
||||
MenuList,
|
||||
MenuItem,
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
Tooltip,
|
||||
} from '@chakra-ui/react';
|
||||
import {
|
||||
FiSend,
|
||||
FiSearch,
|
||||
FiPlus,
|
||||
FiMessageSquare,
|
||||
FiTrash2,
|
||||
FiMoreVertical,
|
||||
FiRefreshCw,
|
||||
FiDownload,
|
||||
FiCpu,
|
||||
FiUser,
|
||||
FiZap,
|
||||
FiClock,
|
||||
} from 'react-icons/fi';
|
||||
import { useAuth } from '@contexts/AuthContext';
|
||||
import { PlanCard } from '@components/ChatBot/PlanCard';
|
||||
import { StepResultCard } from '@components/ChatBot/StepResultCard';
|
||||
import { logger } from '@utils/logger';
|
||||
import axios from 'axios';
|
||||
|
||||
/**
|
||||
* Agent消息类型
|
||||
*/
|
||||
const MessageTypes = {
|
||||
USER: 'user',
|
||||
AGENT_THINKING: 'agent_thinking',
|
||||
AGENT_PLAN: 'agent_plan',
|
||||
AGENT_EXECUTING: 'agent_executing',
|
||||
AGENT_RESPONSE: 'agent_response',
|
||||
ERROR: 'error',
|
||||
};
|
||||
|
||||
/**
|
||||
* Agent聊天页面 V3
|
||||
*/
|
||||
const AgentChatV3 = () => {
|
||||
const { user } = useAuth(); // 获取当前用户信息
|
||||
const toast = useToast();
|
||||
|
||||
// 会话相关状态
|
||||
const [sessions, setSessions] = useState([]);
|
||||
const [currentSessionId, setCurrentSessionId] = useState(null);
|
||||
const [isLoadingSessions, setIsLoadingSessions] = useState(true);
|
||||
|
||||
// 消息相关状态
|
||||
const [messages, setMessages] = useState([]);
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
const [currentProgress, setCurrentProgress] = useState(0);
|
||||
|
||||
// UI 状态
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const { isOpen: isSidebarOpen, onToggle: toggleSidebar } = useDisclosure({ defaultIsOpen: true });
|
||||
|
||||
// Refs
|
||||
const messagesEndRef = useRef(null);
|
||||
const inputRef = useRef(null);
|
||||
|
||||
// 颜色主题
|
||||
const bgColor = useColorModeValue('gray.50', 'gray.900');
|
||||
const sidebarBg = useColorModeValue('white', 'gray.800');
|
||||
const chatBg = useColorModeValue('white', 'gray.800');
|
||||
const inputBg = useColorModeValue('white', 'gray.700');
|
||||
const borderColor = useColorModeValue('gray.200', 'gray.600');
|
||||
const hoverBg = useColorModeValue('gray.100', 'gray.700');
|
||||
const activeBg = useColorModeValue('blue.50', 'blue.900');
|
||||
const userBubbleBg = useColorModeValue('blue.500', 'blue.600');
|
||||
const agentBubbleBg = useColorModeValue('white', 'gray.700');
|
||||
|
||||
// ==================== 会话管理函数 ====================
|
||||
|
||||
// 加载会话列表
|
||||
const loadSessions = async () => {
|
||||
if (!user?.id) return;
|
||||
|
||||
setIsLoadingSessions(true);
|
||||
try {
|
||||
const response = await axios.get('/mcp/agent/sessions', {
|
||||
params: { user_id: user.id, limit: 50 },
|
||||
});
|
||||
|
||||
if (response.data.success) {
|
||||
setSessions(response.data.data);
|
||||
logger.info('会话列表加载成功', response.data.data);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('加载会话列表失败', error);
|
||||
toast({
|
||||
title: '加载失败',
|
||||
description: '无法加载会话列表',
|
||||
status: 'error',
|
||||
duration: 3000,
|
||||
});
|
||||
} finally {
|
||||
setIsLoadingSessions(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 加载会话历史
|
||||
const loadSessionHistory = async (sessionId) => {
|
||||
if (!sessionId) return;
|
||||
|
||||
try {
|
||||
const response = await axios.get(`/mcp/agent/history/${sessionId}`, {
|
||||
params: { limit: 100 },
|
||||
});
|
||||
|
||||
if (response.data.success) {
|
||||
const history = response.data.data;
|
||||
|
||||
// 将历史记录转换为消息格式
|
||||
const formattedMessages = history.map((msg, idx) => ({
|
||||
id: `${sessionId}-${idx}`,
|
||||
type: msg.message_type === 'user' ? MessageTypes.USER : MessageTypes.AGENT_RESPONSE,
|
||||
content: msg.message,
|
||||
plan: msg.plan ? JSON.parse(msg.plan) : null,
|
||||
stepResults: msg.steps ? JSON.parse(msg.steps) : null,
|
||||
timestamp: msg.timestamp,
|
||||
}));
|
||||
|
||||
setMessages(formattedMessages);
|
||||
logger.info('会话历史加载成功', formattedMessages);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('加载会话历史失败', error);
|
||||
toast({
|
||||
title: '加载失败',
|
||||
description: '无法加载会话历史',
|
||||
status: 'error',
|
||||
duration: 3000,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 创建新会话
|
||||
const createNewSession = () => {
|
||||
setCurrentSessionId(null);
|
||||
setMessages([
|
||||
{
|
||||
id: Date.now(),
|
||||
type: MessageTypes.AGENT_RESPONSE,
|
||||
content: `你好${user?.nickname || ''}!我是价小前,北京价值前沿科技公司的AI投研助手。\n\n我会通过多步骤分析来帮助你深入了解金融市场。\n\n你可以问我:\n• 全面分析某只股票\n• 某个行业的投资机会\n• 今日市场热点\n• 某个概念板块的表现`,
|
||||
timestamp: new Date().toISOString(),
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
// 切换会话
|
||||
const switchSession = (sessionId) => {
|
||||
setCurrentSessionId(sessionId);
|
||||
loadSessionHistory(sessionId);
|
||||
};
|
||||
|
||||
// 删除会话(需要后端API支持)
|
||||
const deleteSession = async (sessionId) => {
|
||||
// TODO: 实现删除会话的后端API
|
||||
toast({
|
||||
title: '删除会话',
|
||||
description: '此功能尚未实现',
|
||||
status: 'info',
|
||||
duration: 2000,
|
||||
});
|
||||
};
|
||||
|
||||
// ==================== 消息处理函数 ====================
|
||||
|
||||
// 自动滚动到底部
|
||||
const scrollToBottom = () => {
|
||||
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
scrollToBottom();
|
||||
}, [messages]);
|
||||
|
||||
// 添加消息
|
||||
const addMessage = (message) => {
|
||||
setMessages((prev) => [...prev, { ...message, id: Date.now() }]);
|
||||
};
|
||||
|
||||
// 发送消息
|
||||
const handleSendMessage = async () => {
|
||||
if (!inputValue.trim() || isProcessing) return;
|
||||
|
||||
// 权限检查
|
||||
if (user?.id !== 'max') {
|
||||
toast({
|
||||
title: '权限不足',
|
||||
description: '「价小前投研」功能目前仅对特定用户开放。如需使用,请联系管理员。',
|
||||
status: 'warning',
|
||||
duration: 5000,
|
||||
isClosable: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const userMessage = {
|
||||
type: MessageTypes.USER,
|
||||
content: inputValue,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
|
||||
addMessage(userMessage);
|
||||
const userInput = inputValue;
|
||||
setInputValue('');
|
||||
setIsProcessing(true);
|
||||
setCurrentProgress(0);
|
||||
|
||||
let currentPlan = null;
|
||||
let stepResults = [];
|
||||
|
||||
try {
|
||||
// 1. 显示思考状态
|
||||
addMessage({
|
||||
type: MessageTypes.AGENT_THINKING,
|
||||
content: '正在分析你的问题...',
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
setCurrentProgress(10);
|
||||
|
||||
// 2. 调用后端API(非流式)
|
||||
const response = await axios.post('/mcp/agent/chat', {
|
||||
message: userInput,
|
||||
conversation_history: messages
|
||||
.filter((m) => m.type === MessageTypes.USER || m.type === MessageTypes.AGENT_RESPONSE)
|
||||
.map((m) => ({
|
||||
isUser: m.type === MessageTypes.USER,
|
||||
content: m.content,
|
||||
})),
|
||||
user_id: user?.id || 'anonymous',
|
||||
user_nickname: user?.nickname || '匿名用户',
|
||||
user_avatar: user?.avatar || '',
|
||||
session_id: currentSessionId,
|
||||
});
|
||||
|
||||
// 移除思考消息
|
||||
setMessages((prev) => prev.filter((m) => m.type !== MessageTypes.AGENT_THINKING));
|
||||
|
||||
if (response.data.success) {
|
||||
const data = response.data;
|
||||
|
||||
// 更新 session_id(如果是新会话)
|
||||
if (data.session_id && !currentSessionId) {
|
||||
setCurrentSessionId(data.session_id);
|
||||
}
|
||||
|
||||
// 显示执行计划
|
||||
if (data.plan) {
|
||||
currentPlan = data.plan;
|
||||
addMessage({
|
||||
type: MessageTypes.AGENT_PLAN,
|
||||
content: '已制定执行计划',
|
||||
plan: data.plan,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
setCurrentProgress(30);
|
||||
}
|
||||
|
||||
// 显示执行步骤
|
||||
if (data.steps && data.steps.length > 0) {
|
||||
stepResults = data.steps;
|
||||
addMessage({
|
||||
type: MessageTypes.AGENT_EXECUTING,
|
||||
content: '正在执行步骤...',
|
||||
plan: currentPlan,
|
||||
stepResults: stepResults,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
setCurrentProgress(70);
|
||||
}
|
||||
|
||||
// 移除执行中消息
|
||||
setMessages((prev) => prev.filter((m) => m.type !== MessageTypes.AGENT_EXECUTING));
|
||||
|
||||
// 显示最终结果
|
||||
addMessage({
|
||||
type: MessageTypes.AGENT_RESPONSE,
|
||||
content: data.final_answer || data.message || '处理完成',
|
||||
plan: currentPlan,
|
||||
stepResults: stepResults,
|
||||
metadata: data.metadata,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
setCurrentProgress(100);
|
||||
|
||||
// 重新加载会话列表
|
||||
loadSessions();
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Agent chat error', error);
|
||||
|
||||
// 移除思考/执行中消息
|
||||
setMessages((prev) =>
|
||||
prev.filter(
|
||||
(m) => m.type !== MessageTypes.AGENT_THINKING && m.type !== MessageTypes.AGENT_EXECUTING
|
||||
)
|
||||
);
|
||||
|
||||
const errorMessage = error.response?.data?.error || error.message || '处理失败';
|
||||
|
||||
addMessage({
|
||||
type: MessageTypes.ERROR,
|
||||
content: `处理失败:${errorMessage}`,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
toast({
|
||||
title: '处理失败',
|
||||
description: errorMessage,
|
||||
status: 'error',
|
||||
duration: 5000,
|
||||
isClosable: true,
|
||||
});
|
||||
} finally {
|
||||
setIsProcessing(false);
|
||||
setCurrentProgress(0);
|
||||
inputRef.current?.focus();
|
||||
}
|
||||
};
|
||||
|
||||
// 处理键盘事件
|
||||
const handleKeyPress = (e) => {
|
||||
if (e.key === 'Enter' && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
handleSendMessage();
|
||||
}
|
||||
};
|
||||
|
||||
// 清空对话
|
||||
const handleClearChat = () => {
|
||||
createNewSession();
|
||||
};
|
||||
|
||||
// 导出对话
|
||||
const handleExportChat = () => {
|
||||
const chatText = messages
|
||||
.filter((m) => m.type === MessageTypes.USER || m.type === MessageTypes.AGENT_RESPONSE)
|
||||
.map((msg) => `[${msg.type === MessageTypes.USER ? '用户' : '价小前'}] ${msg.content}`)
|
||||
.join('\n\n');
|
||||
|
||||
const blob = new Blob([chatText], { type: 'text/plain' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `chat_${new Date().toISOString().slice(0, 10)}.txt`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
|
||||
// ==================== 初始化 ====================
|
||||
|
||||
useEffect(() => {
|
||||
if (user) {
|
||||
loadSessions();
|
||||
createNewSession();
|
||||
}
|
||||
}, [user]);
|
||||
|
||||
// ==================== 渲染 ====================
|
||||
|
||||
// 快捷问题
|
||||
const quickQuestions = [
|
||||
'全面分析贵州茅台这只股票',
|
||||
'今日涨停股票有哪些亮点',
|
||||
'新能源概念板块的投资机会',
|
||||
'半导体行业最新动态',
|
||||
];
|
||||
|
||||
// 筛选会话
|
||||
const filteredSessions = sessions.filter(
|
||||
(session) =>
|
||||
!searchQuery ||
|
||||
session.last_message?.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex h="calc(100vh - 80px)" bg={bgColor}>
|
||||
{/* 左侧会话列表 */}
|
||||
<Collapse in={isSidebarOpen} animateOpacity>
|
||||
<Box
|
||||
w="300px"
|
||||
bg={sidebarBg}
|
||||
borderRight="1px"
|
||||
borderColor={borderColor}
|
||||
h="100%"
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
>
|
||||
{/* 侧边栏头部 */}
|
||||
<Box p={4} borderBottom="1px" borderColor={borderColor}>
|
||||
<Button
|
||||
leftIcon={<FiPlus />}
|
||||
colorScheme="blue"
|
||||
w="100%"
|
||||
onClick={createNewSession}
|
||||
size="sm"
|
||||
>
|
||||
新建对话
|
||||
</Button>
|
||||
|
||||
{/* 搜索框 */}
|
||||
<InputGroup mt={3} size="sm">
|
||||
<InputLeftElement pointerEvents="none">
|
||||
<FiSearch color="gray.300" />
|
||||
</InputLeftElement>
|
||||
<Input
|
||||
placeholder="搜索对话..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
/>
|
||||
</InputGroup>
|
||||
</Box>
|
||||
|
||||
{/* 会话列表 */}
|
||||
<VStack
|
||||
flex="1"
|
||||
overflowY="auto"
|
||||
spacing={0}
|
||||
align="stretch"
|
||||
css={{
|
||||
'&::-webkit-scrollbar': { width: '6px' },
|
||||
'&::-webkit-scrollbar-thumb': {
|
||||
background: '#CBD5E0',
|
||||
borderRadius: '3px',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{isLoadingSessions ? (
|
||||
<Flex justify="center" align="center" h="200px">
|
||||
<Spinner />
|
||||
</Flex>
|
||||
) : filteredSessions.length === 0 ? (
|
||||
<Flex justify="center" align="center" h="200px" direction="column">
|
||||
<FiMessageSquare size={32} color="gray" />
|
||||
<Text mt={2} fontSize="sm" color="gray.500">
|
||||
{searchQuery ? '没有找到匹配的对话' : '暂无对话记录'}
|
||||
</Text>
|
||||
</Flex>
|
||||
) : (
|
||||
filteredSessions.map((session) => (
|
||||
<Box
|
||||
key={session.session_id}
|
||||
p={3}
|
||||
cursor="pointer"
|
||||
bg={currentSessionId === session.session_id ? activeBg : 'transparent'}
|
||||
_hover={{ bg: hoverBg }}
|
||||
borderBottom="1px"
|
||||
borderColor={borderColor}
|
||||
onClick={() => switchSession(session.session_id)}
|
||||
>
|
||||
<Flex justify="space-between" align="start">
|
||||
<VStack align="start" spacing={1} flex="1">
|
||||
<Text fontSize="sm" fontWeight="medium" noOfLines={2}>
|
||||
{session.last_message || '新对话'}
|
||||
</Text>
|
||||
<HStack spacing={2} fontSize="xs" color="gray.500">
|
||||
<FiClock size={12} />
|
||||
<Text>
|
||||
{new Date(session.last_timestamp).toLocaleDateString('zh-CN', {
|
||||
month: 'numeric',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
})}
|
||||
</Text>
|
||||
<Badge colorScheme="blue" fontSize="xx-small">
|
||||
{session.message_count} 条
|
||||
</Badge>
|
||||
</HStack>
|
||||
</VStack>
|
||||
|
||||
<Menu>
|
||||
<MenuButton
|
||||
as={IconButton}
|
||||
icon={<FiMoreVertical />}
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
/>
|
||||
<MenuList>
|
||||
<MenuItem
|
||||
icon={<FiTrash2 />}
|
||||
color="red.500"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
deleteSession(session.session_id);
|
||||
}}
|
||||
>
|
||||
删除对话
|
||||
</MenuItem>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
</Flex>
|
||||
</Box>
|
||||
))
|
||||
)}
|
||||
</VStack>
|
||||
|
||||
{/* 用户信息 */}
|
||||
<Box p={4} borderTop="1px" borderColor={borderColor}>
|
||||
<HStack spacing={3}>
|
||||
<Avatar size="sm" name={user?.nickname} src={user?.avatar} />
|
||||
<VStack align="start" spacing={0} flex="1">
|
||||
<Text fontSize="sm" fontWeight="medium">
|
||||
{user?.nickname || '未登录'}
|
||||
</Text>
|
||||
<Text fontSize="xs" color="gray.500">
|
||||
{user?.id || 'anonymous'}
|
||||
</Text>
|
||||
</VStack>
|
||||
</HStack>
|
||||
</Box>
|
||||
</Box>
|
||||
</Collapse>
|
||||
|
||||
{/* 主聊天区域 */}
|
||||
<Flex flex="1" direction="column" h="100%">
|
||||
{/* 聊天头部 */}
|
||||
<Box bg={chatBg} borderBottom="1px" borderColor={borderColor} px={6} py={4}>
|
||||
<HStack justify="space-between">
|
||||
<HStack spacing={4}>
|
||||
<IconButton
|
||||
icon={<FiMessageSquare />}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
aria-label="切换侧边栏"
|
||||
onClick={toggleSidebar}
|
||||
/>
|
||||
<Avatar size="md" bg="blue.500" icon={<FiCpu fontSize="1.5rem" />} />
|
||||
<VStack align="start" spacing={0}>
|
||||
<Heading size="md">价小前投研</Heading>
|
||||
<HStack>
|
||||
<Badge colorScheme="green" fontSize="xs">
|
||||
<HStack spacing={1}>
|
||||
<FiZap size={10} />
|
||||
<span>智能分析</span>
|
||||
</HStack>
|
||||
</Badge>
|
||||
<Text fontSize="xs" color="gray.500">
|
||||
多步骤深度研究
|
||||
</Text>
|
||||
</HStack>
|
||||
</VStack>
|
||||
</HStack>
|
||||
|
||||
<HStack>
|
||||
<IconButton
|
||||
icon={<FiRefreshCw />}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
aria-label="清空对话"
|
||||
onClick={handleClearChat}
|
||||
/>
|
||||
<IconButton
|
||||
icon={<FiDownload />}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
aria-label="导出对话"
|
||||
onClick={handleExportChat}
|
||||
/>
|
||||
</HStack>
|
||||
</HStack>
|
||||
|
||||
{/* 进度条 */}
|
||||
{isProcessing && (
|
||||
<Progress
|
||||
value={currentProgress}
|
||||
size="xs"
|
||||
colorScheme="blue"
|
||||
mt={3}
|
||||
borderRadius="full"
|
||||
isAnimated
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* 消息列表 */}
|
||||
<Box
|
||||
flex="1"
|
||||
overflowY="auto"
|
||||
px={6}
|
||||
py={4}
|
||||
css={{
|
||||
'&::-webkit-scrollbar': { width: '8px' },
|
||||
'&::-webkit-scrollbar-thumb': {
|
||||
background: '#CBD5E0',
|
||||
borderRadius: '4px',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<VStack spacing={4} align="stretch">
|
||||
{messages.map((message) => (
|
||||
<Fade in key={message.id}>
|
||||
<MessageRenderer message={message} userAvatar={user?.avatar} />
|
||||
</Fade>
|
||||
))}
|
||||
<div ref={messagesEndRef} />
|
||||
</VStack>
|
||||
</Box>
|
||||
|
||||
{/* 快捷问题 */}
|
||||
{messages.length <= 2 && !isProcessing && (
|
||||
<Box px={6} py={3} bg={chatBg} borderTop="1px" borderColor={borderColor}>
|
||||
<Text fontSize="xs" color="gray.500" mb={2}>
|
||||
💡 试试这些问题:
|
||||
</Text>
|
||||
<Flex wrap="wrap" gap={2}>
|
||||
{quickQuestions.map((question, idx) => (
|
||||
<Button
|
||||
key={idx}
|
||||
size="sm"
|
||||
variant="outline"
|
||||
colorScheme="blue"
|
||||
fontSize="xs"
|
||||
onClick={() => {
|
||||
setInputValue(question);
|
||||
inputRef.current?.focus();
|
||||
}}
|
||||
>
|
||||
{question}
|
||||
</Button>
|
||||
))}
|
||||
</Flex>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* 输入框 */}
|
||||
<Box px={6} py={4} bg={chatBg} borderTop="1px" borderColor={borderColor}>
|
||||
<Flex>
|
||||
<Input
|
||||
ref={inputRef}
|
||||
value={inputValue}
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
onKeyPress={handleKeyPress}
|
||||
placeholder="输入你的问题,我会进行深度分析..."
|
||||
bg={inputBg}
|
||||
border="1px"
|
||||
borderColor={borderColor}
|
||||
_focus={{ borderColor: 'blue.500', boxShadow: '0 0 0 1px #3182CE' }}
|
||||
mr={2}
|
||||
disabled={isProcessing}
|
||||
size="lg"
|
||||
/>
|
||||
<IconButton
|
||||
icon={isProcessing ? <Spinner size="sm" /> : <FiSend />}
|
||||
colorScheme="blue"
|
||||
aria-label="发送"
|
||||
onClick={handleSendMessage}
|
||||
isLoading={isProcessing}
|
||||
disabled={!inputValue.trim() || isProcessing}
|
||||
size="lg"
|
||||
/>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 消息渲染器
|
||||
*/
|
||||
const MessageRenderer = ({ message, userAvatar }) => {
|
||||
const userBubbleBg = useColorModeValue('blue.500', 'blue.600');
|
||||
const agentBubbleBg = useColorModeValue('white', 'gray.700');
|
||||
const borderColor = useColorModeValue('gray.200', 'gray.600');
|
||||
|
||||
switch (message.type) {
|
||||
case MessageTypes.USER:
|
||||
return (
|
||||
<Flex justify="flex-end">
|
||||
<HStack align="flex-start" maxW="75%">
|
||||
<Box
|
||||
bg={userBubbleBg}
|
||||
color="white"
|
||||
px={4}
|
||||
py={3}
|
||||
borderRadius="lg"
|
||||
boxShadow="md"
|
||||
>
|
||||
<Text fontSize="sm" whiteSpace="pre-wrap">
|
||||
{message.content}
|
||||
</Text>
|
||||
</Box>
|
||||
<Avatar size="sm" src={userAvatar} icon={<FiUser fontSize="1rem" />} />
|
||||
</HStack>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
case MessageTypes.AGENT_THINKING:
|
||||
return (
|
||||
<Flex justify="flex-start">
|
||||
<HStack align="flex-start" maxW="75%">
|
||||
<Avatar size="sm" bg="purple.500" icon={<FiCpu fontSize="1rem" />} />
|
||||
<Box
|
||||
bg={agentBubbleBg}
|
||||
px={4}
|
||||
py={3}
|
||||
borderRadius="lg"
|
||||
borderWidth="1px"
|
||||
borderColor={borderColor}
|
||||
boxShadow="sm"
|
||||
>
|
||||
<HStack>
|
||||
<Spinner size="sm" color="purple.500" />
|
||||
<Text fontSize="sm" color="purple.600">
|
||||
{message.content}
|
||||
</Text>
|
||||
</HStack>
|
||||
</Box>
|
||||
</HStack>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
case MessageTypes.AGENT_PLAN:
|
||||
return (
|
||||
<Flex justify="flex-start">
|
||||
<HStack align="flex-start" maxW="85%">
|
||||
<Avatar size="sm" bg="blue.500" icon={<FiCpu fontSize="1rem" />} />
|
||||
<VStack align="stretch" flex="1">
|
||||
<PlanCard plan={message.plan} stepResults={[]} />
|
||||
</VStack>
|
||||
</HStack>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
case MessageTypes.AGENT_EXECUTING:
|
||||
return (
|
||||
<Flex justify="flex-start">
|
||||
<HStack align="flex-start" maxW="85%">
|
||||
<Avatar size="sm" bg="orange.500" icon={<FiCpu fontSize="1rem" />} />
|
||||
<VStack align="stretch" flex="1" spacing={3}>
|
||||
<PlanCard plan={message.plan} stepResults={message.stepResults} />
|
||||
{message.stepResults?.map((result, idx) => (
|
||||
<StepResultCard key={idx} stepResult={result} />
|
||||
))}
|
||||
</VStack>
|
||||
</HStack>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
case MessageTypes.AGENT_RESPONSE:
|
||||
return (
|
||||
<Flex justify="flex-start">
|
||||
<HStack align="flex-start" maxW="85%">
|
||||
<Avatar size="sm" bg="green.500" icon={<FiCpu fontSize="1rem" />} />
|
||||
<VStack align="stretch" flex="1" spacing={3}>
|
||||
{/* 最终总结 */}
|
||||
<Box
|
||||
bg={agentBubbleBg}
|
||||
px={4}
|
||||
py={3}
|
||||
borderRadius="lg"
|
||||
borderWidth="1px"
|
||||
borderColor={borderColor}
|
||||
boxShadow="md"
|
||||
>
|
||||
<Text fontSize="sm" whiteSpace="pre-wrap">
|
||||
{message.content}
|
||||
</Text>
|
||||
|
||||
{/* 元数据 */}
|
||||
{message.metadata && (
|
||||
<HStack mt={3} spacing={4} fontSize="xs" color="gray.500">
|
||||
<Text>总步骤: {message.metadata.total_steps}</Text>
|
||||
<Text>✓ {message.metadata.successful_steps}</Text>
|
||||
{message.metadata.failed_steps > 0 && (
|
||||
<Text>✗ {message.metadata.failed_steps}</Text>
|
||||
)}
|
||||
<Text>耗时: {message.metadata.total_execution_time?.toFixed(1)}s</Text>
|
||||
</HStack>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* 执行详情(可选) */}
|
||||
{message.plan && message.stepResults && message.stepResults.length > 0 && (
|
||||
<VStack align="stretch" spacing={2}>
|
||||
<Divider />
|
||||
<Text fontSize="xs" fontWeight="bold" color="gray.500">
|
||||
📊 执行详情(点击展开查看)
|
||||
</Text>
|
||||
{message.stepResults.map((result, idx) => (
|
||||
<StepResultCard key={idx} stepResult={result} />
|
||||
))}
|
||||
</VStack>
|
||||
)}
|
||||
</VStack>
|
||||
</HStack>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
case MessageTypes.ERROR:
|
||||
return (
|
||||
<Flex justify="flex-start">
|
||||
<HStack align="flex-start" maxW="75%">
|
||||
<Avatar size="sm" bg="red.500" icon={<FiCpu fontSize="1rem" />} />
|
||||
<Box
|
||||
bg="red.50"
|
||||
color="red.700"
|
||||
px={4}
|
||||
py={3}
|
||||
borderRadius="lg"
|
||||
borderWidth="1px"
|
||||
borderColor="red.200"
|
||||
>
|
||||
<Text fontSize="sm">{message.content}</Text>
|
||||
</Box>
|
||||
</HStack>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export default AgentChatV3;
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
41
src/views/AgentChat/neuratalk/.gitignore
vendored
Normal file
41
src/views/AgentChat/neuratalk/.gitignore
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/versions
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# env files (can opt-in for committing if needed)
|
||||
.env*
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
36
src/views/AgentChat/neuratalk/README.md
Normal file
36
src/views/AgentChat/neuratalk/README.md
Normal file
@@ -0,0 +1,36 @@
|
||||
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
First, run the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
||||
@@ -0,0 +1,5 @@
|
||||
import CheckEmailPage from "@/templates/Auth/CheckEmailPage";
|
||||
|
||||
export default function Page() {
|
||||
return <CheckEmailPage />;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import EnterCodePage from "@/templates/Auth/EnterCodePage";
|
||||
|
||||
export default function Page() {
|
||||
return <EnterCodePage />;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import ForgotPasswordPage from "@/templates/Auth/ForgotPasswordPage";
|
||||
|
||||
export default function Page() {
|
||||
return <ForgotPasswordPage />;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import ResetPasswordPage from "@/templates/Auth/ResetPasswordPage";
|
||||
|
||||
export default function Page() {
|
||||
return <ResetPasswordPage />;
|
||||
}
|
||||
5
src/views/AgentChat/neuratalk/app/auth/sign-in/page.tsx
Normal file
5
src/views/AgentChat/neuratalk/app/auth/sign-in/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import SignInPage from "@/templates/Auth/SignInPage";
|
||||
|
||||
export default function Page() {
|
||||
return <SignInPage />;
|
||||
}
|
||||
5
src/views/AgentChat/neuratalk/app/auth/sign-up/page.tsx
Normal file
5
src/views/AgentChat/neuratalk/app/auth/sign-up/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import SignUpPage from "@/templates/Auth/SignUpPage";
|
||||
|
||||
export default function Page() {
|
||||
return <SignUpPage />;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import DataAnalyticsPage from "@/templates/DataAnalyticsPage";
|
||||
|
||||
export default function Page() {
|
||||
return <DataAnalyticsPage />;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import DocumentGenerationPage from "@/templates/DocumentGenerationPage";
|
||||
|
||||
export default function Page() {
|
||||
return <DocumentGenerationPage />;
|
||||
}
|
||||
5
src/views/AgentChat/neuratalk/app/documents/page.tsx
Normal file
5
src/views/AgentChat/neuratalk/app/documents/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import DocumentsPage from "@/templates/DocumentsPage";
|
||||
|
||||
export default function Page() {
|
||||
return <DocumentsPage />;
|
||||
}
|
||||
BIN
src/views/AgentChat/neuratalk/app/favicon.ico
Normal file
BIN
src/views/AgentChat/neuratalk/app/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
5
src/views/AgentChat/neuratalk/app/generate-code/page.tsx
Normal file
5
src/views/AgentChat/neuratalk/app/generate-code/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import GenerateCodePage from "@/templates/GenerateCodePage";
|
||||
|
||||
export default function Page() {
|
||||
return <GenerateCodePage />;
|
||||
}
|
||||
411
src/views/AgentChat/neuratalk/app/globals.css
Normal file
411
src/views/AgentChat/neuratalk/app/globals.css
Normal file
@@ -0,0 +1,411 @@
|
||||
@import "tailwindcss";
|
||||
@plugin "tailwind-scrollbar";
|
||||
|
||||
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
|
||||
|
||||
:root {
|
||||
--static-white: #ffffff;
|
||||
--static-black: #0e121b;
|
||||
--white-0: #ffffff;
|
||||
--strong-950: #0e121b;
|
||||
--bg-weak-50: #f9fafc;
|
||||
--bg-surface-800: #222530;
|
||||
--bg-soft-200: #e1e4ea;
|
||||
--bg-sub-300: #cacfd8;
|
||||
--text-sub-600: #525866;
|
||||
--text-disabled-300: #cacfd8;
|
||||
--text-soft-400: #99a0ae;
|
||||
--faded-light: #e1e4ea;
|
||||
--faded-base: #717784;
|
||||
--faded-dark: #222530;
|
||||
--faded-lighter: #f2f5f8;
|
||||
--error-base: #fb3748;
|
||||
--error-light: #ffc0c5;
|
||||
--error-dark: #681219;
|
||||
--error-lighter: #ffebec;
|
||||
--warning-dark: #682f12;
|
||||
--warning-base: #ff8447;
|
||||
--warning-light: #ffd5c0;
|
||||
--warning-lighter: #fff1eb;
|
||||
--information-dark: #122368;
|
||||
--information-base: #335cff;
|
||||
--information-light: #c0d5ff;
|
||||
--information-lighter: #ebf1ff;
|
||||
--success-dark: #0b4627;
|
||||
--success-base: #1fc16b;
|
||||
--success-light: #c2f5da;
|
||||
--success-lighter: #e0faec;
|
||||
--away-dark: #624c18;
|
||||
--away-base: #f6b51e;
|
||||
--away-light: #ffecc0;
|
||||
--away-lighter: #fffaeb;
|
||||
--feature-dark: #351a75;
|
||||
--feature-base: #7d52f4;
|
||||
--feature-light: #cac0ff;
|
||||
--feature-lighter: #efebff;
|
||||
--verified-dark: #124b68;
|
||||
--verified-base: #47c2ff;
|
||||
--verified-light: #c0eaff;
|
||||
--verified-lighter: #ebf8ff;
|
||||
--highlighted-dark: #68123d;
|
||||
--highlighted-base: #fb4ba3;
|
||||
--highlighted-light: #ffc0df;
|
||||
--highlighted-lighter: #ffebf4;
|
||||
--stable-dark: #0b463e;
|
||||
--stable-base: #22d3bb;
|
||||
--stable-light: #c2f5ee;
|
||||
--stable-lighter: #e4fbf8;
|
||||
--stroke-soft-200: #e1e4ea;
|
||||
--stroke-strong-950: #0e121b;
|
||||
--stroke-white-0: #ffffff;
|
||||
--stroke-sub-300: #cacfd8;
|
||||
--icon-sub-600: #525866;
|
||||
--icon-strong-950: #0e121b;
|
||||
--icon-soft-400: #99a0ae;
|
||||
--icon-disabled-300: #cacfd8;
|
||||
--icon-white-0: #ffffff;
|
||||
--social-apple: #000000;
|
||||
--social-twitter: #010101;
|
||||
--social-github: #24292f;
|
||||
--social-notion: #1e2226;
|
||||
--social-tidal: #000000;
|
||||
--social-amazon: #353e47;
|
||||
--social-zendesk: #16140d;
|
||||
--illustration-strong-400: #99a0ae;
|
||||
--illustration-sub-300: #cacfd8;
|
||||
--illustration-soft-200: #e1e4ea;
|
||||
--illustration-weak-100: #f2f5f8;
|
||||
--illustration-white-0: #ffffff;
|
||||
--overlay: rgba(2, 13, 23, 0.24);
|
||||
--blue-50: #ebf1ff;
|
||||
--blue-100: #d5e2ff;
|
||||
--blue-200: #c0d5ff;
|
||||
--blue-300: #97baff;
|
||||
--blue-400: #6895ff;
|
||||
--blue-500: #335cff;
|
||||
--blue-600: #3559e9;
|
||||
--blue-700: #2547d0;
|
||||
--blue-800: #1f3bad;
|
||||
--blue-900: #182f8b;
|
||||
--blue-950: #122368;
|
||||
--green-50: #e0faec;
|
||||
--green-100: #d0fbe9;
|
||||
--green-200: #c2f5da;
|
||||
--green-300: #84ebb4;
|
||||
--green-400: #3ee089;
|
||||
--green-500: #1fc16b;
|
||||
--green-600: #1daf61;
|
||||
--green-700: #178c4e;
|
||||
--green-800: #1a7544;
|
||||
--green-900: #16643b;
|
||||
--green-950: #0b4627;
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--white-0: #0e121b;
|
||||
--strong-950: #ffffff;
|
||||
--bg-weak-50: #181b25;
|
||||
--bg-surface-800: #e1e4ea;
|
||||
--bg-soft-200: #2b303b;
|
||||
--bg-sub-300: #525866;
|
||||
--text-sub-600: #99a0ae;
|
||||
--text-disabled-300: #525866;
|
||||
--text-soft-400: #717784;
|
||||
--faded-light: rgba(153, 160, 174, 0.24);
|
||||
--faded-base: #717784;
|
||||
--faded-dark: #cacfd8;
|
||||
--faded-lighter: rgba(153, 160, 174, 0.16);
|
||||
--error-base: #e93544;
|
||||
--error-light: rgba(251, 55, 72, 0.24);
|
||||
--error-dark: #ff6875;
|
||||
--error-lighter: rgba(251, 55, 72, 0.16);
|
||||
--warning-dark: #ff9a68;
|
||||
--warning-base: #e97135;
|
||||
--warning-light: rgba(255, 145, 71, 0.24);
|
||||
--warning-lighter: rgba(255, 145, 71, 0.16);
|
||||
--information-dark: #6895ff;
|
||||
--information-base: #335cff;
|
||||
--information-light: rgba(71, 108, 255, 0.24);
|
||||
--information-lighter: rgba(71, 108, 255, 0.16);
|
||||
--success-dark: #3ee089;
|
||||
--success-base: #1daf61;
|
||||
--success-light: rgba(31, 193, 107, 0.16);
|
||||
--success-lighter: rgba(31, 193, 107, 0.1);
|
||||
--away-dark: #ffd268;
|
||||
--away-base: #e6a819;
|
||||
--away-light: rgba(251, 198, 75, 0.24);
|
||||
--away-lighter: rgba(251, 198, 75, 0.16);
|
||||
--feature-dark: #8c71f6;
|
||||
--feature-base: #7d52f4;
|
||||
--feature-light: rgba(120, 77, 239, 0.24);
|
||||
--feature-lighter: rgba(120, 77, 239, 0.16);
|
||||
--verified-dark: #68cdff;
|
||||
--verified-base: #35ade9;
|
||||
--verified-light: rgba(71, 194, 255, 0.24);
|
||||
--verified-lighter: rgba(71, 194, 255, 0.16);
|
||||
--highlighted-dark: #ff68b3;
|
||||
--highlighted-base: #e9358f;
|
||||
--highlighted-light: rgba(251, 75, 163, 0.24);
|
||||
--highlighted-lighter: rgba(251, 75, 163, 0.16);
|
||||
--stable-dark: #3fdec9;
|
||||
--stable-base: #1daf9c;
|
||||
--stable-light: rgba(34, 211, 187, 0.24);
|
||||
--stable-lighter: rgba(34, 211, 187, 0.16);
|
||||
--stroke-soft-200: #2b303b;
|
||||
--stroke-strong-950: #ffffff;
|
||||
--stroke-white-0: #0e121b;
|
||||
--stroke-sub-300: #525866;
|
||||
--icon-sub-600: #99a0ae;
|
||||
--icon-strong-950: #ffffff;
|
||||
--icon-soft-400: #717784;
|
||||
--icon-disabled-300: #525866;
|
||||
--icon-white-0: #0e121b;
|
||||
--social-apple: #ffffff;
|
||||
--social-twitter: #ffffff;
|
||||
--social-github: #ffffff;
|
||||
--social-notion: #ffffff;
|
||||
--social-tidal: #ffffff;
|
||||
--social-amazon: #ffffff;
|
||||
--social-zendesk: #ffffff;
|
||||
--illustration-strong-400: #525866;
|
||||
--illustration-sub-300: #2b303b;
|
||||
--illustration-soft-200: #222530;
|
||||
--illustration-weak-100: #181b25;
|
||||
--illustration-white-0: #0e121b;
|
||||
--overlay: rgba(82, 88, 102, 0.32);
|
||||
}
|
||||
|
||||
@theme {
|
||||
--breakpoint-*: initial;
|
||||
--breakpoint-sm: 480px;
|
||||
--breakpoint-md: 767px;
|
||||
--breakpoint-lg: 1023px;
|
||||
--breakpoint-xl: 1259px;
|
||||
--breakpoint-2xl: 1419px;
|
||||
--breakpoint-3xl: 1719px;
|
||||
--breakpoint-4xl: 1899px;
|
||||
--color-static-white: var(--static-white);
|
||||
--color-static-black: var(--static-black);
|
||||
--color-white-0: var(--white-0);
|
||||
--color-strong-950: var(--strong-950);
|
||||
--color-weak-50: var(--bg-weak-50);
|
||||
--color-surface-800: var(--bg-surface-800);
|
||||
--color-soft-200: var(--bg-soft-200);
|
||||
--color-sub-300: var(--bg-sub-300);
|
||||
--color-sub-600: var(--text-sub-600);
|
||||
--color-disabled-300: var(--text-disabled-300);
|
||||
--color-soft-400: var(--text-soft-400);
|
||||
--color-faded-light: var(--faded-light);
|
||||
--color-faded-base: var(--faded-base);
|
||||
--color-faded-dark: var(--faded-dark);
|
||||
--color-faded-lighter: var(--faded-lighter);
|
||||
--color-error-base: var(--error-base);
|
||||
--color-error-light: var(--error-light);
|
||||
--color-error-dark: var(--error-dark);
|
||||
--color-error-lighter: var(--error-lighter);
|
||||
--color-warning-dark: var(--warning-dark);
|
||||
--color-warning-base: var(--warning-base);
|
||||
--color-warning-light: var(--warning-light);
|
||||
--color-warning-lighter: var(--warning-lighter);
|
||||
--color-information-dark: var(--information-dark);
|
||||
--color-information-base: var(--information-base);
|
||||
--color-information-light: var(--information-light);
|
||||
--color-information-lighter: var(--information-lighter);
|
||||
--color-success-dark: var(--success-dark);
|
||||
--color-success-base: var(--success-base);
|
||||
--color-success-light: var(--success-light);
|
||||
--color-success-lighter: var(--success-lighter);
|
||||
--color-away-dark: var(--away-dark);
|
||||
--color-away-base: var(--away-base);
|
||||
--color-away-light: var(--away-light);
|
||||
--color-away-lighter: var(--away-lighter);
|
||||
--color-feature-dark: var(--feature-dark);
|
||||
--color-feature-base: var(--feature-base);
|
||||
--color-feature-light: var(--feature-light);
|
||||
--color-feature-lighter: var(--feature-lighter);
|
||||
--color-verified-dark: var(--verified-dark);
|
||||
--color-verified-base: var(--verified-base);
|
||||
--color-verified-light: var(--verified-light);
|
||||
--color-verified-lighter: var(--verified-lighter);
|
||||
--color-highlighted-dark: var(--highlighted-dark);
|
||||
--color-highlighted-base: var(--highlighted-base);
|
||||
--color-highlighted-light: var(--highlighted-light);
|
||||
--color-highlighted-lighter: var(--highlighted-lighter);
|
||||
--color-stable-dark: var(--stable-dark);
|
||||
--color-stable-base: var(--stable-base);
|
||||
--color-stable-light: var(--stable-light);
|
||||
--color-stable-lighter: var(--stable-lighter);
|
||||
--color-stroke-soft-200: var(--stroke-soft-200);
|
||||
--color-stroke-strong-950: var(--stroke-strong-950);
|
||||
--color-stroke-white-0: var(--stroke-white-0);
|
||||
--color-stroke-sub-300: var(--stroke-sub-300);
|
||||
--color-icon-sub-600: var(--icon-sub-600);
|
||||
--color-icon-strong-950: var(--icon-strong-950);
|
||||
--color-icon-soft-400: var(--icon-soft-400);
|
||||
--color-icon-disabled-300: var(--icon-disabled-300);
|
||||
--color-icon-white-0: var(--icon-white-0);
|
||||
--color-social-apple: var(--social-apple);
|
||||
--color-social-twitter: var(--social-twitter);
|
||||
--color-social-github: var(--social-github);
|
||||
--color-social-notion: var(--social-notion);
|
||||
--color-social-tidal: var(--social-tidal);
|
||||
--color-social-amazon: var(--social-amazon);
|
||||
--color-social-zendesk: var(--social-zendesk);
|
||||
--color-illustration-strong-400: var(--illustration-strong-400);
|
||||
--color-illustration-sub-300: var(--illustration-sub-300);
|
||||
--color-illustration-soft-200: var(--illustration-soft-200);
|
||||
--color-illustration-weak-100: var(--illustration-weak-100);
|
||||
--color-illustration-white-0: var(--illustration-white-0);
|
||||
--color-overlay: var(--overlay);
|
||||
--color-blue-50: var(--blue-50);
|
||||
--color-blue-100: var(--blue-100);
|
||||
--color-blue-200: var(--blue-200);
|
||||
--color-blue-300: var(--blue-300);
|
||||
--color-blue-400: var(--blue-400);
|
||||
--color-blue-500: var(--blue-500);
|
||||
--color-blue-600: var(--blue-600);
|
||||
--color-blue-700: var(--blue-700);
|
||||
--color-blue-800: var(--blue-800);
|
||||
--color-blue-900: var(--blue-900);
|
||||
--color-blue-950: var(--blue-950);
|
||||
--color-green-50: var(--green-50);
|
||||
--color-green-100: var(--green-100);
|
||||
--color-green-200: var(--green-200);
|
||||
--color-green-300: var(--green-300);
|
||||
--color-green-400: var(--green-400);
|
||||
--color-green-500: var(--green-500);
|
||||
--color-green-600: var(--green-600);
|
||||
--color-green-700: var(--green-700);
|
||||
--color-green-800: var(--green-800);
|
||||
--color-green-900: var(--green-900);
|
||||
--color-green-950: var(--green-950);
|
||||
--default-transition-duration: 0.2s;
|
||||
--font-satoshi: var(--font-satoshi);
|
||||
--font-inter: var(--font-inter);
|
||||
--font-inter-display: var(--font-inter-display);
|
||||
--text-0: 0;
|
||||
--text-h1: 4rem;
|
||||
--text-h1--line-height: 1.09;
|
||||
--text-h1--letter-spacing: -0.01em;
|
||||
--text-h1--font-weight: 700;
|
||||
--text-h3: 2.5rem;
|
||||
--text-h3--line-height: 1.2;
|
||||
--text-h3--letter-spacing: -0.01em;
|
||||
--text-h3--font-weight: 500;
|
||||
--text-h4: 2.25rem;
|
||||
--text-h4--line-height: 1.5;
|
||||
--text-h4--letter-spacing: -0.005em;
|
||||
--text-h4--font-weight: 500;
|
||||
--text-h5: 1.75rem;
|
||||
--text-h5--line-height: 1.5;
|
||||
--text-h5--letter-spacing: 0;
|
||||
--text-h5--font-weight: 700;
|
||||
--text-h6: 1.25rem;
|
||||
--text-h6--line-height: 1.5;
|
||||
--text-h6--letter-spacing: 0;
|
||||
--text-h6--font-weight: 500;
|
||||
--text-label-xl: 1.5rem;
|
||||
--text-label-xl--line-height: 1.33;
|
||||
--text-label-xl--letter-spacing: -0.015em;
|
||||
--text-label-xl--font-weight: 500;
|
||||
--text-label-lg: 1.125rem;
|
||||
--text-label-lg--line-height: 1.5;
|
||||
--text-label-lg--letter-spacing: -0.015em;
|
||||
--text-label-lg--font-weight: 500;
|
||||
--text-label-md: 1rem;
|
||||
--text-label-md--line-height: 1.5;
|
||||
--text-label-md--letter-spacing: -0.011em;
|
||||
--text-label-md--font-weight: 500;
|
||||
--text-label-sm: 0.875rem;
|
||||
--text-label-sm--line-height: 1.4;
|
||||
--text-label-sm--letter-spacing: -0.006em;
|
||||
--text-label-sm--font-weight: 500;
|
||||
--text-label-xs: 0.75rem;
|
||||
--text-label-xs--line-height: 1.33;
|
||||
--text-label-xs--letter-spacing: 0;
|
||||
--text-label-xs--font-weight: 500;
|
||||
--text-p-xl: 1.25rem;
|
||||
--text-p-xl--line-height: 1.5;
|
||||
--text-p-xl--letter-spacing: -0.015em;
|
||||
--text-p-xl--font-weight: 400;
|
||||
--text-p-lg: 1.125rem;
|
||||
--text-p-lg--line-height: 1.33;
|
||||
--text-p-lg--letter-spacing: -0.015em;
|
||||
--text-p-lg--font-weight: 400;
|
||||
--text-p-md: 1rem;
|
||||
--text-p-md--line-height: 1.5;
|
||||
--text-p-md--letter-spacing: -0.011em;
|
||||
--text-p-md--font-weight: 300;
|
||||
--text-p-sm: 0.875rem;
|
||||
--text-p-sm--line-height: 1.5;
|
||||
--text-p-sm--letter-spacing: -0.006em;
|
||||
--text-p-sm--font-weight: 400;
|
||||
--text-p-xs: 0.75rem;
|
||||
--text-p-xs--line-height: 1.33;
|
||||
--text-p-xs--letter-spacing: 0;
|
||||
--text-p-xs--font-weight: 400;
|
||||
--text-sub-md: 1rem;
|
||||
--text-sub-md--line-height: 1.5;
|
||||
--text-sub-md--letter-spacing: 0;
|
||||
--text-sub-md--font-weight: 700;
|
||||
--text-sub-sm: 0.875rem;
|
||||
--text-sub-sm--line-height: 1.4;
|
||||
--text-sub-sm--letter-spacing: 0.06em;
|
||||
--text-sub-sm--font-weight: 500;
|
||||
--text-sub-xs: 0.75rem;
|
||||
--text-sub-xs--line-height: 1.33;
|
||||
--text-sub-xs--letter-spacing: 0.04em;
|
||||
--text-sub-xs--font-weight: 500;
|
||||
--text-sub-2xs: 0.6875rem;
|
||||
--text-sub-2xs--line-height: 1.1;
|
||||
--text-sub-2xs--letter-spacing: 0.02em;
|
||||
--text-sub-2xs--font-weight: 500;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
button {
|
||||
@apply cursor-pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.text-h3 {
|
||||
@apply font-inter-display;
|
||||
}
|
||||
.text-label-xl,
|
||||
.text-p-lg,
|
||||
.text-sub-sm,
|
||||
.text-sub-xs,
|
||||
.text-sub-2xs {
|
||||
@apply font-inter;
|
||||
}
|
||||
.chat-wrapper {
|
||||
@apply flex flex-col h-[calc(100svh-8.25rem)] bg-white-0 rounded-3xl shadow-[0_0_1.25rem_0_rgba(0,0,0,0.03)] max-2xl:h-[calc(100svh-7.125rem)] max-lg:h-[calc(100svh-6.125rem)] max-md:h-[calc(100svh-5rem)] max-md:rounded-xl;
|
||||
}
|
||||
.content h3 {
|
||||
@apply mb-5 text-h3 max-2xl:text-[2rem] max-md:text-[1.6rem];
|
||||
}
|
||||
.content p {
|
||||
@apply text-label-md not-last:mb-4 max-md:text-p-sm max-md:not-last:mb-2;
|
||||
}
|
||||
.recharts-surface {
|
||||
@apply outline-none;
|
||||
}
|
||||
.recharts-sector {
|
||||
@apply stroke-transparent outline-none;
|
||||
}
|
||||
}
|
||||
|
||||
/* SVG Progress Animation */
|
||||
@keyframes progress {
|
||||
from {
|
||||
stroke-dashoffset: 100.48;
|
||||
}
|
||||
to {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-progress {
|
||||
animation: progress linear forwards;
|
||||
}
|
||||
5
src/views/AgentChat/neuratalk/app/history/page.tsx
Normal file
5
src/views/AgentChat/neuratalk/app/history/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import HistoryPage from "@/templates/HistoryPage";
|
||||
|
||||
export default function Page() {
|
||||
return <HistoryPage />;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import ImageGenerationPage from "@/templates/ImageGenerationPage";
|
||||
|
||||
export default function Page() {
|
||||
return <ImageGenerationPage />;
|
||||
}
|
||||
158
src/views/AgentChat/neuratalk/app/layout.tsx
Normal file
158
src/views/AgentChat/neuratalk/app/layout.tsx
Normal file
@@ -0,0 +1,158 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Inter } from "next/font/google";
|
||||
import localFont from "next/font/local";
|
||||
import Providers from "./providers";
|
||||
import "./globals.css";
|
||||
|
||||
const inter = Inter({
|
||||
variable: "--font-inter",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
const satoshi = localFont({
|
||||
src: [
|
||||
{
|
||||
path: "../public/fonts/Satoshi-Light.woff2",
|
||||
weight: "300",
|
||||
},
|
||||
{
|
||||
path: "../public/fonts/Satoshi-Regular.woff2",
|
||||
weight: "400",
|
||||
},
|
||||
{
|
||||
path: "../public/fonts/Satoshi-Medium.woff2",
|
||||
weight: "500",
|
||||
},
|
||||
{
|
||||
path: "../public/fonts/Satoshi-Bold.woff2",
|
||||
weight: "700",
|
||||
},
|
||||
],
|
||||
variable: "--font-satoshi",
|
||||
});
|
||||
|
||||
const interDisplay = localFont({
|
||||
src: [
|
||||
{
|
||||
path: "../public/fonts/InterDisplay-Medium.woff2",
|
||||
weight: "500",
|
||||
},
|
||||
],
|
||||
variable: "--font-inter-display",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "NeuraTalk",
|
||||
description: "NeuraTalk: Coded AI Chat Companion",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html
|
||||
className="text-[calc(0.7rem+0.35vw)] max-[2300px]:text-[calc(0.7rem+0.32vw)] max-[2150px]:text-[calc(0.7rem+0.28vw)] max-4xl:text-[1rem]"
|
||||
lang="en"
|
||||
suppressHydrationWarning
|
||||
>
|
||||
<head>
|
||||
{/* Description no longer than 155 characters */}
|
||||
<meta
|
||||
name="description"
|
||||
content="NeuraTalk: Coded AI Chat Companion"
|
||||
/>
|
||||
|
||||
{/* NeuraTalk: Coded AI Chat Companion */}
|
||||
<meta
|
||||
name="product-name"
|
||||
content="NeuraTalk: Coded AI Chat Companion"
|
||||
/>
|
||||
|
||||
{/* Twitter Card data */}
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:site" content="@ui8" />
|
||||
<meta
|
||||
name="twitter:title"
|
||||
content="NeuraTalk: Coded AI Chat Companion"
|
||||
/>
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content="A powerful coded AI chat experience"
|
||||
/>
|
||||
<meta name="twitter:creator" content="@ui8" />
|
||||
{/* Twitter Summary card images must be at least 120x120px */}
|
||||
<meta
|
||||
name="twitter:image"
|
||||
content="https://neuratalk-tau.vercel.app/twitter-card.png"
|
||||
/>
|
||||
|
||||
{/* Open Graph data for Facebook */}
|
||||
<meta
|
||||
property="og:title"
|
||||
content="NeuraTalk: Coded AI Chat Companion"
|
||||
/>
|
||||
<meta property="og:type" content="Article" />
|
||||
<meta
|
||||
property="og:url"
|
||||
content="https://ui8.net/odyssey-agency-d2aaee/products/neuratalk-your-smart-ai-chat-companion-coded"
|
||||
/>
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://neuratalk-tau.vercel.app/fb-og-image.png"
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content="A powerful coded AI chat experience"
|
||||
/>
|
||||
<meta
|
||||
property="og:site_name"
|
||||
content="NeuraTalk: Coded AI Chat Companion"
|
||||
/>
|
||||
<meta property="fb:admins" content="132951670226590" />
|
||||
|
||||
{/* Open Graph data for LinkedIn */}
|
||||
<meta
|
||||
property="og:title"
|
||||
content="NeuraTalk: Coded AI Chat Companion"
|
||||
/>
|
||||
<meta
|
||||
property="og:url"
|
||||
content="https://ui8.net/odyssey-agency-d2aaee/products/neuratalk-your-smart-ai-chat-companion-coded"
|
||||
/>
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://neuratalk-tau.vercel.app/linkedin-og-image.png"
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content="A powerful coded AI chat experience"
|
||||
/>
|
||||
|
||||
{/* Open Graph data for Pinterest */}
|
||||
<meta
|
||||
property="og:title"
|
||||
content="NeuraTalk: Coded AI Chat Companion"
|
||||
/>
|
||||
<meta
|
||||
property="og:url"
|
||||
content="https://ui8.net/slabdsgn/products/elitefinancial---fintech-html--react--tailwind"
|
||||
/>
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://neuratalk-tau.vercel.app/pinterest-og-image.png"
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content="A powerful coded AI chat experience"
|
||||
/>
|
||||
</head>
|
||||
<body
|
||||
className={`${satoshi.variable} ${inter.variable} ${interDisplay.variable} bg-weak-50 font-satoshi text-p-sm text-strong-950 antialiased`}
|
||||
>
|
||||
<Providers>{children}</Providers>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
15
src/views/AgentChat/neuratalk/app/page.tsx
Normal file
15
src/views/AgentChat/neuratalk/app/page.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
// 可以选择使用原始主页或直接进入聊天
|
||||
// import HomePage from "@/templates/HomePage";
|
||||
import MCPChat from "@/components/Chat/MCPChat";
|
||||
|
||||
export default function Page() {
|
||||
// 直接显示聊天界面
|
||||
return (
|
||||
<main className="h-screen">
|
||||
<MCPChat />
|
||||
</main>
|
||||
);
|
||||
|
||||
// 或者使用原始主页
|
||||
// return <HomePage />;
|
||||
}
|
||||
13
src/views/AgentChat/neuratalk/app/providers.tsx
Normal file
13
src/views/AgentChat/neuratalk/app/providers.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "next-themes";
|
||||
|
||||
const Providers = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<ThemeProvider defaultTheme="light" disableTransitionOnChange>
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default Providers;
|
||||
5
src/views/AgentChat/neuratalk/app/research/page.tsx
Normal file
5
src/views/AgentChat/neuratalk/app/research/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import ResearchPage from "@/templates/ResearchPage";
|
||||
|
||||
export default function Page() {
|
||||
return <ResearchPage />;
|
||||
}
|
||||
5
src/views/AgentChat/neuratalk/app/templates/page.tsx
Normal file
5
src/views/AgentChat/neuratalk/app/templates/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import TemplatesPage from "@/templates/TemplatesPage";
|
||||
|
||||
export default function Page() {
|
||||
return <TemplatesPage />;
|
||||
}
|
||||
5
src/views/AgentChat/neuratalk/app/write-copy/page.tsx
Normal file
5
src/views/AgentChat/neuratalk/app/write-copy/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import WriteCopyPage from "@/templates/WriteCopyPage";
|
||||
|
||||
export default function Page() {
|
||||
return <WriteCopyPage />;
|
||||
}
|
||||
47
src/views/AgentChat/neuratalk/components/Actions/index.tsx
Normal file
47
src/views/AgentChat/neuratalk/components/Actions/index.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react";
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
classNameButton?: string;
|
||||
items: {
|
||||
name: string;
|
||||
onClick: () => void;
|
||||
}[];
|
||||
};
|
||||
|
||||
const Actions = ({ className, classNameButton, items }: Props) => {
|
||||
return (
|
||||
<Menu className={`${className || ""}`} as="div">
|
||||
<MenuButton
|
||||
className={`group flex rounded-sm outline-0 transition-colors data-[open]:bg-weak-50 ${
|
||||
classNameButton || ""
|
||||
}`}
|
||||
>
|
||||
<Icon
|
||||
className="fill-icon-sub-600 transition-colors group-hover:fill-strong-950 group-[[data-open]]:fill-strong-950"
|
||||
name="dots"
|
||||
/>
|
||||
</MenuButton>
|
||||
<MenuItems
|
||||
className="[--anchor-gap:0.5rem] [--anchor-offset:0.5rem] z-20 flex flex-col w-40 p-1 border border-stroke-soft-200 rounded-xl outline-0 bg-white-0 shadow-xl transition duration-200 ease-out origin-top data-closed:scale-95 data-closed:opacity-0"
|
||||
anchor="bottom end"
|
||||
transition
|
||||
modal={false}
|
||||
>
|
||||
{items.map((item, index) => (
|
||||
<MenuItem
|
||||
className="group flex items-center gap-3 h-8 px-3 rounded-lg text-label-sm text-soft-600 transition-colors hover:bg-weak-50 hover:text-strong-950"
|
||||
key={index}
|
||||
onClick={() => item.onClick()}
|
||||
as="button"
|
||||
>
|
||||
{item.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuItems>
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
||||
export default Actions;
|
||||
25
src/views/AgentChat/neuratalk/components/Answer/index.tsx
Normal file
25
src/views/AgentChat/neuratalk/components/Answer/index.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import Image from "@/components/Image";
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
const Answer = ({ children }: Props) => (
|
||||
<div className="flex">
|
||||
<div className="shrink-0">
|
||||
<Image
|
||||
className="size-9 opacity-100 rounded-full object-cover"
|
||||
src="/images/avatar-chat.svg"
|
||||
width={36}
|
||||
height={36}
|
||||
alt="Avatar"
|
||||
/>
|
||||
</div>
|
||||
<div className="w-[calc(100%-2.25rem)] pl-3">
|
||||
<div className="mb-1 text-label-sm">Odyssey AI</div>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Answer;
|
||||
@@ -0,0 +1,70 @@
|
||||
import { useState } from "react";
|
||||
import Chat from "@/components/Chat";
|
||||
import Question from "@/components/Question";
|
||||
import Answer from "@/components/Answer";
|
||||
import CodeEditor from "@/components/CodeEditor";
|
||||
|
||||
const ApiIntegrator = () => {
|
||||
const [code, setCode] = useState(`{
|
||||
"location": "Paris",
|
||||
"temperature": 18,
|
||||
"condition": "Partly Cloudy"
|
||||
}`);
|
||||
|
||||
return (
|
||||
<Chat>
|
||||
<Question>
|
||||
<div className="mb-1">
|
||||
Use the API to get the current weather in Paris.
|
||||
</div>
|
||||
<a
|
||||
className="text-label-sm text-[#7D52F4] transition-colors hover:text-[#8c71f6]"
|
||||
href="https://api.weatherly.ai/v1/current"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
https://api.weatherly.ai/v1/current
|
||||
</a>
|
||||
</Question>
|
||||
<Answer>
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="">
|
||||
<p>
|
||||
Absolutely! Here's the result for the API
|
||||
setup, for the current weather in paris.
|
||||
</p>
|
||||
<br />
|
||||
<p className="text-label-md">🔧 API Example</p>
|
||||
<ul className="list-disc list-inside">
|
||||
<li>API Name: Weatherly API</li>
|
||||
<li>
|
||||
Endpoint: https://api.weatherly.ai/v1/current
|
||||
</li>
|
||||
<li>Method: GET</li>
|
||||
<li>
|
||||
Query Params:
|
||||
<ul className="ml-5 list-disc list-inside">
|
||||
<li>city=Paris</li>
|
||||
<li>unit=celsius</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Response Example:</li>
|
||||
</ul>
|
||||
</div>
|
||||
<CodeEditor
|
||||
title="Json"
|
||||
language="json"
|
||||
initialCode={code}
|
||||
onCodeChange={setCode}
|
||||
/>
|
||||
<div className="">
|
||||
It’s currently 18°C and partly cloudy in Paris. A lovely
|
||||
day to be outside!
|
||||
</div>
|
||||
</div>
|
||||
</Answer>
|
||||
</Chat>
|
||||
);
|
||||
};
|
||||
|
||||
export default ApiIntegrator;
|
||||
53
src/views/AgentChat/neuratalk/components/Article/index.tsx
Normal file
53
src/views/AgentChat/neuratalk/components/Article/index.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import Icon from "@/components/Icon";
|
||||
import Button from "@/components/Button";
|
||||
|
||||
type Props = {
|
||||
content: React.ReactNode;
|
||||
onEdit: () => void;
|
||||
};
|
||||
|
||||
const Article = ({ content, onEdit }: Props) => (
|
||||
<div className="bg-white-0 border border-stroke-soft-200 rounded-xl p-4 pb-0 overflow-hidden max-md:p-0 ">
|
||||
<div className="flex items-center gap-2 mb-5 max-md:mb-0 max-md:p-3">
|
||||
<div className="flex items-center gap-2 mr-auto text-[1rem]">
|
||||
<Icon className="fill-strong-950" name="document-check" />
|
||||
Document
|
||||
</div>
|
||||
<Button
|
||||
className="max-md:shrink-0 max-md:w-10 max-md:h-10 max-md:p-0 max-md:gap-0 max-md:text-0"
|
||||
isStroke
|
||||
>
|
||||
<svg
|
||||
className="size-5 fill-strong-950"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M10.838 11.042c0-.46-.373-.833-.833-.833s-.833.373-.833.833v3.75h-.495c-.146 0-.326 0-.473.018H8.2c-.105.013-.585.073-.814.544s.022.889.077.979l.002.003c.077.128.189.27.281.387l.02.025.881 1.043c.158.163.339.33.532.463.171.118.463.287.822.287s.651-.169.822-.287a3.67 3.67 0 0 0 .532-.463c.317-.326.635-.729.881-1.043l.02-.025.281-.387.002-.003c.055-.09.306-.507.077-.979s-.709-.531-.814-.544h-.003c-.147-.018-.327-.018-.473-.018h-.485v-3.75z"
|
||||
/>
|
||||
<path
|
||||
opacity=".4"
|
||||
d="M1.041 10.417c0-2.201 1.484-4.056 3.507-4.617.163-.045.245-.068.292-.116s.068-.13.109-.293a5.21 5.21 0 0 1 10.227.693c.023.204.034.307.086.366s.154.084.356.133c1.917.465 3.34 2.192 3.34 4.252 0 2.416-1.959 4.375-4.375 4.375h-.05c-.183 0-.274 0-.337-.042s-.106-.144-.191-.348c-.105-.251-.262-.486-.469-.687-.276-.268-.608-.445-.957-.53-.259-.063-.388-.095-.442-.163s-.053-.178-.053-.397v-2c0-1.151-.933-2.083-2.083-2.083s-2.083.933-2.083 2.083v2c0 .219 0 .329-.053.397s-.183.1-.442.163c-.349.085-.681.262-.957.53-.208.203-.384.438-.502.691-.097.208-.146.312-.214.352s-.153.032-.324.018c-2.455-.207-4.383-2.266-4.383-4.774z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Donwload Article</span>
|
||||
</Button>
|
||||
<Button
|
||||
className="max-md:shrink-0 max-md:w-10 max-md:h-10 max-md:p-0 max-md:gap-0 max-md:text-0"
|
||||
icon="edit"
|
||||
isBlack
|
||||
onClick={onEdit}
|
||||
>
|
||||
Edit Article
|
||||
</Button>
|
||||
</div>
|
||||
<div className="content max-h-96 bg-white-0 px-18 py-16 rounded-xl shadow-[0_4px_3.4rem_0_rgba(14,18,27,0.10)] overflow-y-auto scrollbar-none max-2xl:p-12 max-xl:p-8 max-md:px-3 max-md:py-4 dark:shadow-[0_0.25rem_3.4rem_0_rgba(255,255,255,0.10)]">
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Article;
|
||||
18
src/views/AgentChat/neuratalk/components/Browser/content.tsx
Normal file
18
src/views/AgentChat/neuratalk/components/Browser/content.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
export const content = [
|
||||
{
|
||||
id: 0,
|
||||
title: "The STAUD – A Creative Powerhouse",
|
||||
description:
|
||||
"Key features: Smooth animations, seamless navigation, and intuitive user flow.",
|
||||
link: "http://webflow.com/theSTAUD.com",
|
||||
image: "/images/browser-pic-1.jpg",
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: "New Horizon – Connecting you to faith",
|
||||
description:
|
||||
"Key features: Smooth animations, seamless navigation, and intuitive user flow.",
|
||||
link: "http://webflow.com/newHorizon.com",
|
||||
image: "/images/browser-pic-2.jpg",
|
||||
},
|
||||
];
|
||||
71
src/views/AgentChat/neuratalk/components/Browser/index.tsx
Normal file
71
src/views/AgentChat/neuratalk/components/Browser/index.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import Chat from "@/components/Chat";
|
||||
import Question from "@/components/Question";
|
||||
import Answer from "@/components/Answer";
|
||||
import Image from "@/components/Image";
|
||||
import Icon from "@/components/Icon";
|
||||
import Actions from "@/components/Actions";
|
||||
|
||||
import { content } from "./content";
|
||||
|
||||
const actions = [
|
||||
{ name: "Edit", onClick: () => {} },
|
||||
{ name: "Delete", onClick: () => {} },
|
||||
{ name: "Copy", onClick: () => {} },
|
||||
];
|
||||
|
||||
const Browser = () => {
|
||||
return (
|
||||
<Chat>
|
||||
<Question>
|
||||
what is the most beatiful website made using{" "}
|
||||
<span className="font-medium">webflow</span>
|
||||
</Question>
|
||||
<Answer>
|
||||
<div className="mb-6 max-md:mb-4">
|
||||
If you're searching for the most beautiful websites
|
||||
built with Webflow, there are several standout examples that
|
||||
showcase the platform's capabilities in design,
|
||||
interactivity, and storytelling. Here are some notable ones:
|
||||
</div>
|
||||
<div className="flex flex-col gap-6 max-md:gap-4">
|
||||
{content.map((item, index) => (
|
||||
<div key={item.id}>
|
||||
<div className="text-label-sm">
|
||||
🌟 {index + 1}. {item.title}
|
||||
</div>
|
||||
<div>{item.description}</div>
|
||||
<a
|
||||
className="text-label-sm text-blue-500 transition-colors hover:text-blue-400"
|
||||
href={item.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{item.link}
|
||||
</a>
|
||||
<div className="relative max-w-92 mt-1">
|
||||
<Image
|
||||
className="w-full rounded-lg"
|
||||
src={item.image}
|
||||
alt={item.title}
|
||||
width={366}
|
||||
height={216}
|
||||
/>
|
||||
<div className="absolute top-2 right-3.5 flex items-center gap-3 h-9 px-2.5 bg-white-0 border border-stroke-soft-200 rounded-xl max-md:right-2">
|
||||
<button className="group text-0">
|
||||
<Icon
|
||||
className="!size-4 fill-icon-sub-600 transition-colors group-hover:fill-strong-950"
|
||||
name="share-1"
|
||||
/>
|
||||
</button>
|
||||
<Actions items={actions} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Answer>
|
||||
</Chat>
|
||||
);
|
||||
};
|
||||
|
||||
export default Browser;
|
||||
88
src/views/AgentChat/neuratalk/components/Button/index.tsx
Normal file
88
src/views/AgentChat/neuratalk/components/Button/index.tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import React from "react";
|
||||
import Link, { LinkProps } from "next/link";
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
type CommonProps = {
|
||||
className?: string;
|
||||
icon?: string;
|
||||
children?: React.ReactNode;
|
||||
isBlack?: boolean;
|
||||
isWhite?: boolean;
|
||||
isRed?: boolean;
|
||||
isBlue?: boolean;
|
||||
isStroke?: boolean;
|
||||
isCircle?: boolean;
|
||||
};
|
||||
|
||||
type ButtonAsButton = {
|
||||
as?: "button";
|
||||
} & React.ButtonHTMLAttributes<HTMLButtonElement>;
|
||||
|
||||
type ButtonAsAnchor = {
|
||||
as: "a";
|
||||
} & React.AnchorHTMLAttributes<HTMLAnchorElement>;
|
||||
|
||||
type ButtonAsLink = {
|
||||
as: "link";
|
||||
} & LinkProps;
|
||||
|
||||
type ButtonProps = CommonProps &
|
||||
(ButtonAsButton | ButtonAsAnchor | ButtonAsLink);
|
||||
|
||||
const Button: React.FC<ButtonProps> = ({
|
||||
className,
|
||||
icon,
|
||||
children,
|
||||
isBlack,
|
||||
isWhite,
|
||||
isRed,
|
||||
isBlue,
|
||||
isStroke,
|
||||
isCircle,
|
||||
as = "button",
|
||||
...props
|
||||
}) => {
|
||||
const isLink = as === "link";
|
||||
const Component: React.ElementType = isLink ? Link : as;
|
||||
|
||||
return (
|
||||
<Component
|
||||
className={`inline-flex items-center justify-center gap-2 h-11 px-4 border rounded-full text-label-sm transition-all cursor-pointer disabled:pointer-events-none ${
|
||||
isBlack
|
||||
? "bg-strong-950 border-transparent text-white-0 fill-white-0 hover:bg-strong-950/90"
|
||||
: ""
|
||||
} ${
|
||||
isWhite
|
||||
? "bg-white-0 border-transparent text-strong-950 fill-strong-950 hover:bg-soft-200"
|
||||
: ""
|
||||
} ${
|
||||
isStroke
|
||||
? "border-soft-200 bg-white-0 text-sub-600 fill-sub-600 hover:border-stroke-sub-300 hover:text-strong-950 hover:fill-strong-950"
|
||||
: ""
|
||||
} ${
|
||||
isRed
|
||||
? "bg-[#FB3748] border-transparent text-static-white fill-static-white hover:bg-[#FB3748]/90"
|
||||
: ""
|
||||
} ${
|
||||
isBlue
|
||||
? "bg-gradient-to-r from-blue-500 to-blue-300 border-stroke-soft-200 text-static-white fill-static-white hover:opacity-90"
|
||||
: ""
|
||||
} ${
|
||||
isCircle ? "!gap-0 !w-11 !px-0 max-md:!w-10 max-md:!h-10" : ""
|
||||
} ${className || ""}`}
|
||||
{...(isLink ? (props as LinkProps) : props)}
|
||||
>
|
||||
{icon && (
|
||||
<Icon
|
||||
className={`fill-inherit ${
|
||||
isCircle ? "!size-6 max-md:!size-5" : ""
|
||||
}`}
|
||||
name={icon}
|
||||
/>
|
||||
)}
|
||||
{children}
|
||||
</Component>
|
||||
);
|
||||
};
|
||||
|
||||
export default Button;
|
||||
@@ -0,0 +1,42 @@
|
||||
import Chat from "@/components/Chat";
|
||||
import Question from "@/components/Question";
|
||||
import Answer from "@/components/Answer";
|
||||
|
||||
const Calculator = () => {
|
||||
return (
|
||||
<Chat>
|
||||
<Question>
|
||||
solve this problem for me:
|
||||
<br />
|
||||
Find the derivative of f(x) = x³ + 2x² - 7
|
||||
</Question>
|
||||
<Answer>
|
||||
<div className="mb-1">Sure here is the response:</div>
|
||||
<div className="">
|
||||
<p className="text-label-sm">✅ Step-by-step solution:</p>
|
||||
<br />
|
||||
<p>We’ll differentiate f(x) term by term:</p>
|
||||
<ol className="list-decimal list-inside">
|
||||
<li>
|
||||
Derivative of x³ is: <br />
|
||||
→ 3x²
|
||||
</li>
|
||||
<li>
|
||||
Derivative of 2x² is: <br />
|
||||
→ 2 × 2x = 4x
|
||||
</li>
|
||||
<li>
|
||||
Derivative of constant -7 is: <br />
|
||||
→ 0
|
||||
</li>
|
||||
</ol>
|
||||
<br />
|
||||
<p className="text-label-sm">🎯 Final Answer:</p>
|
||||
<p>f'(x) = 3x² + 4x</p>
|
||||
</div>
|
||||
</Answer>
|
||||
</Chat>
|
||||
);
|
||||
};
|
||||
|
||||
export default Calculator;
|
||||
30
src/views/AgentChat/neuratalk/components/Chart/data.tsx
Normal file
30
src/views/AgentChat/neuratalk/components/Chart/data.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
export const data = [
|
||||
{
|
||||
name: "Oct 16",
|
||||
tp: 32456,
|
||||
},
|
||||
{
|
||||
name: "Oct 17",
|
||||
tp: 52456,
|
||||
},
|
||||
{
|
||||
name: "Oct 18",
|
||||
tp: 21456,
|
||||
},
|
||||
{
|
||||
name: "Oct 19",
|
||||
tp: 27456,
|
||||
},
|
||||
{
|
||||
name: "Oct 20",
|
||||
tp: 52456,
|
||||
},
|
||||
{
|
||||
name: "Oct 21",
|
||||
tp: 22456,
|
||||
},
|
||||
{
|
||||
name: "Oct 22",
|
||||
tp: 32456,
|
||||
},
|
||||
];
|
||||
162
src/views/AgentChat/neuratalk/components/Chart/index.tsx
Normal file
162
src/views/AgentChat/neuratalk/components/Chart/index.tsx
Normal file
@@ -0,0 +1,162 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
ResponsiveContainer,
|
||||
AreaChart,
|
||||
Area,
|
||||
XAxis,
|
||||
YAxis,
|
||||
CartesianGrid,
|
||||
Tooltip,
|
||||
} from "recharts";
|
||||
import millify from "millify";
|
||||
import Select from "@/components/Select";
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
import { data } from "./data";
|
||||
|
||||
const durationOptions = [
|
||||
{ id: 1, name: "Last 7 days" },
|
||||
{ id: 2, name: "Last 14 days" },
|
||||
{ id: 3, name: "Last 21 days" },
|
||||
];
|
||||
|
||||
const Chart = ({}) => {
|
||||
const [duration, setDuration] = useState(durationOptions[0]);
|
||||
|
||||
const formatterYAxis = (value: number) => {
|
||||
if (value === 0) {
|
||||
return "$0";
|
||||
}
|
||||
return `$${millify(value, {
|
||||
lowercase: false,
|
||||
})}`;
|
||||
};
|
||||
|
||||
const CustomTooltip = ({ payload }: { payload: { value: number }[] }) => {
|
||||
if (payload && payload.length) {
|
||||
return (
|
||||
<div className="p-1.5 bg-strong-950 rounded-md text-label-xs text-white-0">
|
||||
Bitcoin : ${payload[0].value}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<div className="border border-soft-200 px-4.5 py-3 rounded-lg max-md:px-3">
|
||||
<div className="flex items-center mb-2">
|
||||
<div className="mr-auto text-h6">Bitcoin</div>
|
||||
<div className="flex">
|
||||
<Select
|
||||
className=""
|
||||
classButton="rounded-r-none max-md:rounded-lg"
|
||||
value={duration}
|
||||
onChange={setDuration}
|
||||
options={durationOptions}
|
||||
/>
|
||||
<div className="flex items-center gap-2 pl-2 pr-4 border-l-0 rounded-r-xl border border-stroke-soft-200 text-label-sm text-sub-600 max-md:hidden">
|
||||
<Icon className="fill-sub-600" name="calendar" />
|
||||
Oct 16 - Oct 22 2025
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<div className="text-h5 max-md:text-[1.5rem]">$94,112</div>
|
||||
<div className="flex items-center text-label-xs text-[#009934]">
|
||||
<Icon
|
||||
className="-rotate-90 !size-4 fill-[#009934]"
|
||||
name="arrow"
|
||||
/>
|
||||
12%
|
||||
</div>
|
||||
<div className="text-label-sm text-soft-400 max-md:hidden">
|
||||
vs last Week
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-44 -ml-3">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<AreaChart
|
||||
width={730}
|
||||
height={250}
|
||||
data={data}
|
||||
margin={{ top: 10, right: 5, left: 0, bottom: 0 }}
|
||||
>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id="color"
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="0"
|
||||
y2="1"
|
||||
>
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor="#335CFF"
|
||||
stopOpacity={0.12}
|
||||
/>
|
||||
<stop
|
||||
offset="95%"
|
||||
stopColor="#335CFF"
|
||||
stopOpacity={0}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<CartesianGrid
|
||||
vertical={false}
|
||||
strokeDasharray="5 2"
|
||||
stroke="var(--stroke-soft-200)"
|
||||
strokeOpacity={0.5}
|
||||
/>
|
||||
<XAxis
|
||||
dataKey="name"
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
tick={{
|
||||
fontSize: "0.875rem",
|
||||
fill: "var(--text-soft-400)",
|
||||
}}
|
||||
height={32}
|
||||
dy={8}
|
||||
/>
|
||||
<YAxis
|
||||
tickFormatter={formatterYAxis}
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
tick={{
|
||||
fontSize: "0.875rem",
|
||||
fill: "var(--text-soft-400)",
|
||||
}}
|
||||
/>
|
||||
<Tooltip
|
||||
content={<CustomTooltip payload={[]} />}
|
||||
cursor={{
|
||||
stroke: "var(--strong-950)",
|
||||
strokeDasharray: "5 5",
|
||||
}}
|
||||
/>
|
||||
<Area
|
||||
type="linear"
|
||||
dataKey="tp"
|
||||
stroke="#335CFF"
|
||||
strokeWidth={2}
|
||||
fillOpacity={1}
|
||||
fill="url(#color)"
|
||||
dot={false}
|
||||
activeDot={{
|
||||
r: 5,
|
||||
fill: "var(--strong-950)",
|
||||
stroke: "var(--white-0)",
|
||||
strokeWidth: 2,
|
||||
}}
|
||||
/>
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Chart;
|
||||
62
src/views/AgentChat/neuratalk/components/Chat/Head/index.tsx
Normal file
62
src/views/AgentChat/neuratalk/components/Chat/Head/index.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import { useState } from "react";
|
||||
import Icon from "@/components/Icon";
|
||||
import ModalShare from "@/components/ModalShare";
|
||||
import Actions from "@/components/Actions";
|
||||
|
||||
const actions = [
|
||||
{ name: "New chat", onClick: () => {} },
|
||||
{ name: "Move to folder", onClick: () => {} },
|
||||
{ name: "Clear chat", onClick: () => {} },
|
||||
{ name: "Delete chat", onClick: () => {} },
|
||||
];
|
||||
|
||||
type ButtonProps = {
|
||||
icon: string;
|
||||
onClick: () => void;
|
||||
};
|
||||
|
||||
const Button = ({ icon, onClick }: ButtonProps) => (
|
||||
<button className="group text-0" onClick={onClick}>
|
||||
<Icon
|
||||
className="fill-strong-950 transition-colors group-hover:fill-blue-500"
|
||||
name={icon}
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
|
||||
type Props = {
|
||||
title?: React.ReactNode;
|
||||
};
|
||||
|
||||
const Head = ({ title }: Props) => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex items-center shrink-0 h-13 px-3 border-b border-stroke-soft-200">
|
||||
{title ? (
|
||||
title
|
||||
) : (
|
||||
<div className="flex items-center gap-2 mr-auto">
|
||||
<Icon className="fill-strong-950" name="chat" />
|
||||
<div className="text-label-sm">Ask your AI</div>
|
||||
<div className="px-3 py-0.5 bg-strong-950 rounded-md text-label-xs text-white-0">
|
||||
Beta
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center gap-2 ml-auto">
|
||||
<Button icon="share" onClick={() => setVisible(true)} />
|
||||
<Button icon="link-1" onClick={() => {}} />
|
||||
<Actions
|
||||
classNameButton="[&_svg]:fill-strong-950"
|
||||
items={actions}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<ModalShare open={visible} onClose={() => setVisible(false)} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Head;
|
||||
288
src/views/AgentChat/neuratalk/components/Chat/MCPChat.tsx
Normal file
288
src/views/AgentChat/neuratalk/components/Chat/MCPChat.tsx
Normal file
@@ -0,0 +1,288 @@
|
||||
// components/Chat/MCPChat.tsx - 集成 MCP 的聊天组件
|
||||
'use client';
|
||||
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { mcpService } from '../../services/mcp-real';
|
||||
import { useAuth } from '../../hooks/useAuth';
|
||||
import styles from './MCPChat.module.css';
|
||||
|
||||
interface Message {
|
||||
id: string;
|
||||
role: 'user' | 'assistant' | 'system';
|
||||
content: string;
|
||||
timestamp: Date;
|
||||
isStreaming?: boolean;
|
||||
}
|
||||
|
||||
export default function MCPChat() {
|
||||
const [messages, setMessages] = useState<Message[]>([]);
|
||||
const [input, setInput] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [streamingMessage, setStreamingMessage] = useState('');
|
||||
const [tools, setTools] = useState<any[]>([]);
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const { user, isAuthenticated, canAccessChat, loading: authLoading } = useAuth();
|
||||
|
||||
// 加载可用工具
|
||||
useEffect(() => {
|
||||
if (isAuthenticated && canAccessChat) {
|
||||
loadTools();
|
||||
}
|
||||
}, [isAuthenticated, canAccessChat]);
|
||||
|
||||
// 自动滚动到底部
|
||||
useEffect(() => {
|
||||
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
||||
}, [messages, streamingMessage]);
|
||||
|
||||
const loadTools = async () => {
|
||||
try {
|
||||
const availableTools = await mcpService.getTools();
|
||||
setTools(availableTools);
|
||||
console.log('Available tools:', availableTools);
|
||||
} catch (error) {
|
||||
console.error('Failed to load tools:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSend = async () => {
|
||||
if (!input.trim() || isLoading) return;
|
||||
|
||||
const userMessage: Message = {
|
||||
id: Date.now().toString(),
|
||||
role: 'user',
|
||||
content: input,
|
||||
timestamp: new Date(),
|
||||
};
|
||||
|
||||
setMessages(prev => [...prev, userMessage]);
|
||||
setInput('');
|
||||
setIsLoading(true);
|
||||
setStreamingMessage('');
|
||||
|
||||
try {
|
||||
// 创建助手消息占位符
|
||||
const assistantMessage: Message = {
|
||||
id: (Date.now() + 1).toString(),
|
||||
role: 'assistant',
|
||||
content: '',
|
||||
timestamp: new Date(),
|
||||
isStreaming: true,
|
||||
};
|
||||
|
||||
setMessages(prev => [...prev, assistantMessage]);
|
||||
|
||||
// 流式接收回复
|
||||
let fullContent = '';
|
||||
for await (const chunk of mcpService.streamMessage(input)) {
|
||||
fullContent += chunk;
|
||||
setStreamingMessage(fullContent);
|
||||
}
|
||||
|
||||
// 更新最终消息
|
||||
setMessages(prev =>
|
||||
prev.map(msg =>
|
||||
msg.id === assistantMessage.id
|
||||
? { ...msg, content: fullContent, isStreaming: false }
|
||||
: msg
|
||||
)
|
||||
);
|
||||
setStreamingMessage('');
|
||||
} catch (error) {
|
||||
console.error('Send message error:', error);
|
||||
setMessages(prev => [
|
||||
...prev,
|
||||
{
|
||||
id: Date.now().toString(),
|
||||
role: 'system',
|
||||
content: '抱歉,发送消息时出错了。请稍后重试。',
|
||||
timestamp: new Date(),
|
||||
},
|
||||
]);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleToolCall = async (toolName: string) => {
|
||||
// 示例:调用工具
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const result = await mcpService.callTool(toolName, {});
|
||||
console.log('Tool result:', result);
|
||||
|
||||
// 显示工具结果
|
||||
setMessages(prev => [
|
||||
...prev,
|
||||
{
|
||||
id: Date.now().toString(),
|
||||
role: 'system',
|
||||
content: `工具 ${toolName} 执行结果:${JSON.stringify(result.result, null, 2)}`,
|
||||
timestamp: new Date(),
|
||||
},
|
||||
]);
|
||||
} catch (error) {
|
||||
console.error('Tool call error:', error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 权限检查
|
||||
if (authLoading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-screen">
|
||||
<div className="text-lg">加载中...</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-screen">
|
||||
<h2 className="text-2xl mb-4">请先登录</h2>
|
||||
<a
|
||||
href={`${process.env.NEXT_PUBLIC_MAIN_APP_URL}/auth/sign-in?redirect=/chat`}
|
||||
className="bg-blue-600 text-white px-6 py-2 rounded hover:bg-blue-700"
|
||||
>
|
||||
前往登录
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!canAccessChat) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-screen">
|
||||
<h2 className="text-2xl mb-4">需要订阅才能使用 AI 助手</h2>
|
||||
<p className="text-gray-600 mb-6">升级到高级版解锁所有功能</p>
|
||||
<a
|
||||
href={`${process.env.NEXT_PUBLIC_MAIN_APP_URL}/subscription`}
|
||||
className="bg-green-600 text-white px-6 py-2 rounded hover:bg-green-700"
|
||||
>
|
||||
查看订阅方案
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-screen bg-gray-50 dark:bg-gray-900">
|
||||
{/* 侧边栏 - 工具列表 */}
|
||||
<div className="w-64 bg-white dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700 p-4">
|
||||
<h3 className="font-semibold mb-4">可用工具</h3>
|
||||
<div className="space-y-2">
|
||||
{tools.map(tool => (
|
||||
<button
|
||||
key={tool.name}
|
||||
onClick={() => handleToolCall(tool.name)}
|
||||
disabled={isLoading}
|
||||
className="w-full text-left p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50"
|
||||
>
|
||||
<div className="font-medium">{tool.name}</div>
|
||||
<div className="text-sm text-gray-600 dark:text-gray-400">
|
||||
{tool.description}
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 用户信息 */}
|
||||
<div className="mt-auto pt-4 border-t border-gray-200 dark:border-gray-700">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center text-white">
|
||||
{user?.username?.[0]?.toUpperCase()}
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-medium">{user?.username}</div>
|
||||
<div className="text-xs text-gray-500">{user?.subscription_tier}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 主聊天区域 */}
|
||||
<div className="flex-1 flex flex-col">
|
||||
{/* 消息列表 */}
|
||||
<div className="flex-1 overflow-y-auto p-4 space-y-4">
|
||||
{messages.map(msg => (
|
||||
<div
|
||||
key={msg.id}
|
||||
className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}
|
||||
>
|
||||
<div
|
||||
className={`max-w-2xl px-4 py-2 rounded-lg ${
|
||||
msg.role === 'user'
|
||||
? 'bg-blue-600 text-white'
|
||||
: msg.role === 'system'
|
||||
? 'bg-yellow-100 text-yellow-800'
|
||||
: 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100'
|
||||
}`}
|
||||
>
|
||||
{msg.isStreaming ? (
|
||||
<div>
|
||||
{streamingMessage || (
|
||||
<span className="inline-block animate-pulse">思考中...</span>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="whitespace-pre-wrap">{msg.content}</div>
|
||||
)}
|
||||
<div className="text-xs mt-1 opacity-70">
|
||||
{msg.timestamp.toLocaleTimeString()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div ref={messagesEndRef} />
|
||||
</div>
|
||||
|
||||
{/* 输入区域 */}
|
||||
<div className="border-t border-gray-200 dark:border-gray-700 p-4">
|
||||
<div className="flex space-x-2">
|
||||
<input
|
||||
type="text"
|
||||
value={input}
|
||||
onChange={e => setInput(e.target.value)}
|
||||
onKeyPress={e => e.key === 'Enter' && handleSend()}
|
||||
disabled={isLoading}
|
||||
placeholder="输入消息..."
|
||||
className="flex-1 px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-800 dark:text-white"
|
||||
/>
|
||||
<button
|
||||
onClick={handleSend}
|
||||
disabled={!input.trim() || isLoading}
|
||||
className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{isLoading ? '发送中...' : '发送'}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* 快捷操作 */}
|
||||
<div className="flex space-x-2 mt-2">
|
||||
<button
|
||||
onClick={() => setInput('/help')}
|
||||
className="text-sm text-blue-600 hover:underline"
|
||||
>
|
||||
帮助
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setInput('/tools')}
|
||||
className="text-sm text-blue-600 hover:underline"
|
||||
>
|
||||
查看工具
|
||||
</button>
|
||||
<button
|
||||
onClick={() => mcpService.clearHistory()}
|
||||
className="text-sm text-red-600 hover:underline"
|
||||
>
|
||||
清空历史
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// CSS 模块文件需要单独创建
|
||||
26
src/views/AgentChat/neuratalk/components/Chat/index.tsx
Normal file
26
src/views/AgentChat/neuratalk/components/Chat/index.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import PanelMessage from "@/components/PanelMessage";
|
||||
import Head from "./Head";
|
||||
|
||||
type Props = {
|
||||
titleHead?: React.ReactNode;
|
||||
hidePanelMessage?: boolean;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
const Chat = ({ titleHead, hidePanelMessage, children }: Props) => {
|
||||
return (
|
||||
<div className="chat-wrapper">
|
||||
<Head title={titleHead} />
|
||||
<div
|
||||
className={`flex flex-col gap-4.5 grow p-7.5 overflow-auto scrollbar-none max-md:gap-3 max-md:p-4 max-md:pb-8 ${
|
||||
hidePanelMessage ? "" : "-mb-3 pb-10"
|
||||
}`}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
{!hidePanelMessage && <PanelMessage />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Chat;
|
||||
107
src/views/AgentChat/neuratalk/components/CodeEditor/index.tsx
Normal file
107
src/views/AgentChat/neuratalk/components/CodeEditor/index.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
import { useState } from "react";
|
||||
import { useTheme } from "next-themes";
|
||||
import Editor from "@monaco-editor/react";
|
||||
import Icon from "@/components/Icon";
|
||||
import Button from "@/components/Button";
|
||||
|
||||
interface CodeEditorProps {
|
||||
title?: string;
|
||||
language?: string;
|
||||
initialCode?: string;
|
||||
onCodeChange?: (code: string) => void;
|
||||
onGenerate?: () => void;
|
||||
isGenerating?: boolean;
|
||||
}
|
||||
|
||||
const CodeEditor = ({
|
||||
title = "Code Editor",
|
||||
language = "python",
|
||||
initialCode = "",
|
||||
onCodeChange,
|
||||
onGenerate,
|
||||
isGenerating = false,
|
||||
}: CodeEditorProps) => {
|
||||
const [code, setCode] = useState(initialCode);
|
||||
const { theme } = useTheme();
|
||||
|
||||
const handleEditorChange = (value: string | undefined) => {
|
||||
const newCode = value || "";
|
||||
setCode(newCode);
|
||||
onCodeChange?.(newCode);
|
||||
};
|
||||
|
||||
const handleCopyCode = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(code);
|
||||
console.log("Code copied to clipboard!");
|
||||
} catch (err) {
|
||||
console.error("Failed to copy code: ", err);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-white-0 rounded-xl border border-stroke-soft-200 overflow-hidden">
|
||||
<div className="flex items-center gap-2 p-4 font-[1rem] leading-[1.25rem]">
|
||||
<Icon className="fill-strong-950" name="ai-programming" />
|
||||
{title}
|
||||
<Button
|
||||
className="!h-9 ml-auto !px-3 rounded-lg text-sub-600 max-md:hidden"
|
||||
isStroke
|
||||
onClick={handleCopyCode}
|
||||
>
|
||||
Copy Code
|
||||
<svg
|
||||
className="size-3.25 fill-icon-soft-400"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="13"
|
||||
height="13"
|
||||
viewBox="0 0 13 13"
|
||||
>
|
||||
<path
|
||||
opacity=".4"
|
||||
d="M9.108 4.32l1.94.068c.523.07.964.221 1.314.571s.501.791.571 1.314C13 6.776 13 7.417 13 8.212h0v.645h0l-.068 1.94c-.07.523-.221.964-.571 1.314s-.791.501-1.314.571c-.504.068-1.145.068-1.94.068h0-.645 0c-.795 0-1.436 0-1.94-.068-.523-.07-.964-.221-1.314-.571s-.5-.791-.571-1.314c-.068-.504-.068-1.145-.068-1.94h0v-.645h0l.068-1.94c.07-.523.221-.964.571-1.314s.791-.5 1.314-.571c.504-.068 1.145-.068 1.94-.068h0 .645 0z"
|
||||
/>
|
||||
<path d="M3.698 8.161l.076-2.005c.083-.62.279-1.275.818-1.814s1.195-.735 1.814-.818c.562-.076 1.253-.076 2.005-.076h1.3c.172 0 .258 0 .31-.056s.046-.14.033-.307l-.042-.413c-.075-.558-.226-1.021-.546-1.412a2.76 2.76 0 0 0-.383-.383C8.671.539 8.178.39 7.578.319 6.995.25 6.257.25 5.325.25h-.057c-.932 0-1.67 0-2.253.069-.599.071-1.093.22-1.505.558a2.76 2.76 0 0 0-.383.383c-.338.412-.487.906-.558 1.505C.5 3.349.5 4.087.5 5.018v.057l.069 2.253c.071.599.22 1.093.558 1.505a2.76 2.76 0 0 0 .383.383c.391.321.854.471 1.412.546l.413.042c.168.012.251.019.307-.033s.056-.138.056-.31v-1.3z" />
|
||||
</svg>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="h-64">
|
||||
<Editor
|
||||
height="100%"
|
||||
language={language}
|
||||
value={code}
|
||||
onChange={handleEditorChange}
|
||||
theme={theme === "light" ? "vs-light" : "vs-dark"}
|
||||
options={{
|
||||
minimap: { enabled: false },
|
||||
scrollBeyondLastLine: false,
|
||||
fontSize: 14,
|
||||
lineNumbers: "on",
|
||||
roundedSelection: false,
|
||||
scrollbar: {
|
||||
vertical: "auto",
|
||||
horizontal: "auto",
|
||||
},
|
||||
automaticLayout: true,
|
||||
padding: { top: 4, bottom: 0 },
|
||||
fontFamily:
|
||||
"'Monaco', 'Menlo', 'Ubuntu Mono', monospace",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{onGenerate && (
|
||||
<div className="py-4 text-center">
|
||||
<Button
|
||||
isStroke
|
||||
onClick={onGenerate}
|
||||
disabled={isGenerating}
|
||||
>
|
||||
{isGenerating ? "Generating Code..." : "Generate Code"}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CodeEditor;
|
||||
149
src/views/AgentChat/neuratalk/components/EditorArticle/index.tsx
Normal file
149
src/views/AgentChat/neuratalk/components/EditorArticle/index.tsx
Normal file
@@ -0,0 +1,149 @@
|
||||
import Icon from "@/components/Icon";
|
||||
import Button from "@/components/Button";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
|
||||
type Props = {
|
||||
content: React.ReactNode;
|
||||
onBack: () => void;
|
||||
};
|
||||
|
||||
const EditorArticle = ({ content, onBack }: Props) => {
|
||||
const [isTextSelected, setIsTextSelected] = useState(false);
|
||||
const [selectionPosition, setSelectionPosition] = useState({
|
||||
top: 0,
|
||||
left: 0,
|
||||
});
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const handleTextSelection = () => {
|
||||
const selection = window.getSelection();
|
||||
if (selection && selection.toString().trim().length > 0) {
|
||||
const range = selection.getRangeAt(0);
|
||||
const rect = range.getBoundingClientRect();
|
||||
const contentRect = contentRef.current?.getBoundingClientRect();
|
||||
|
||||
if (contentRect) {
|
||||
setSelectionPosition({
|
||||
top: rect.top - contentRect.top - 50,
|
||||
left: rect.left - contentRect.left + rect.width / 2 - 100,
|
||||
});
|
||||
setIsTextSelected(true);
|
||||
}
|
||||
} else {
|
||||
setIsTextSelected(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleFormatText = (format: string) => {
|
||||
const selection = window.getSelection();
|
||||
if (selection && selection.rangeCount > 0) {
|
||||
const range = selection.getRangeAt(0);
|
||||
const selectedText = selection.toString();
|
||||
|
||||
if (selectedText) {
|
||||
let formattedText = selectedText;
|
||||
|
||||
switch (format) {
|
||||
case "bold":
|
||||
formattedText = `<strong>${selectedText}</strong>`;
|
||||
break;
|
||||
case "italic":
|
||||
formattedText = `<em>${selectedText}</em>`;
|
||||
break;
|
||||
case "underline":
|
||||
formattedText = `<u>${selectedText}</u>`;
|
||||
break;
|
||||
case "strikethrough":
|
||||
formattedText = `<s>${selectedText}</s>`;
|
||||
break;
|
||||
}
|
||||
|
||||
range.deleteContents();
|
||||
const tempDiv = document.createElement("div");
|
||||
tempDiv.innerHTML = formattedText;
|
||||
const fragment = document.createDocumentFragment();
|
||||
while (tempDiv.firstChild) {
|
||||
fragment.appendChild(tempDiv.firstChild);
|
||||
}
|
||||
range.insertNode(fragment);
|
||||
|
||||
selection.removeAllRanges();
|
||||
setIsTextSelected(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener("selectionchange", handleTextSelection);
|
||||
return () => {
|
||||
document.removeEventListener(
|
||||
"selectionchange",
|
||||
handleTextSelection
|
||||
);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="chat-wrapper p-5 max-md:p-0">
|
||||
<div className="flex justify-between items-center mb-5 max-md:mb-0 max-md:p-3">
|
||||
<button
|
||||
className="group flex items-center gap-2 text-label-sm max-md:text-0"
|
||||
onClick={onBack}
|
||||
>
|
||||
<div className="flex justify-center items-center size-9 bg-weak-50 rounded-lg transition-colors group-hover:bg-soft-200">
|
||||
<Icon
|
||||
className="rotate-90 fill-strong-950"
|
||||
name="chevron"
|
||||
/>
|
||||
</div>
|
||||
Non-Disclosure Agreement Document
|
||||
</button>
|
||||
<Button className="!h-8" isBlack onClick={onBack}>
|
||||
Save Document
|
||||
</Button>
|
||||
</div>
|
||||
<div
|
||||
ref={contentRef}
|
||||
className="relative content grow bg-white-0 px-18 py-16 rounded-xl shadow-[0_4px_3.4rem_0_rgba(14,18,27,0.10)] overflow-y-auto scrollbar-none max-2xl:p-12 max-xl:p-8 max-md:px-3 max-md:py-4 dark:shadow-[0_0.25rem_3.4rem_0_rgba(255,255,255,0.10)]"
|
||||
>
|
||||
{content}
|
||||
{isTextSelected && (
|
||||
<div
|
||||
className="absolute z-10 bg-white-0 border border-soft-200 rounded-lg shadow-lg p-1 flex items-center gap-1"
|
||||
style={{
|
||||
top: `${selectionPosition.top}px`,
|
||||
left: `${selectionPosition.left}px`,
|
||||
}}
|
||||
>
|
||||
<button
|
||||
onClick={() => handleFormatText("bold")}
|
||||
className="flex justify-center items-center size-7 hover:bg-soft-200 rounded transition-colors"
|
||||
>
|
||||
<span className="font-bold text-sm">B</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleFormatText("italic")}
|
||||
className="flex justify-center items-center size-7 hover:bg-soft-200 rounded transition-colors"
|
||||
>
|
||||
<span className="italic text-sm">I</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleFormatText("underline")}
|
||||
className="flex justify-center items-center size-7 hover:bg-soft-200 rounded transition-colors"
|
||||
>
|
||||
<span className="underline text-sm">U</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleFormatText("strikethrough")}
|
||||
className="flex justify-center items-center size-7 hover:bg-soft-200 rounded transition-colors"
|
||||
>
|
||||
<span className="line-through text-sm">S</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditorArticle;
|
||||
89
src/views/AgentChat/neuratalk/components/Field/index.tsx
Normal file
89
src/views/AgentChat/neuratalk/components/Field/index.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import { useState } from "react";
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
type FieldProps = {
|
||||
className?: string;
|
||||
classInput?: string;
|
||||
label?: string;
|
||||
textarea?: boolean;
|
||||
type?: string;
|
||||
required?: boolean;
|
||||
isSmall?: boolean;
|
||||
};
|
||||
|
||||
const Field = ({
|
||||
className,
|
||||
classInput,
|
||||
label,
|
||||
textarea,
|
||||
type,
|
||||
required,
|
||||
isSmall,
|
||||
...inputProps
|
||||
}: FieldProps &
|
||||
React.InputHTMLAttributes<HTMLInputElement> &
|
||||
React.TextareaHTMLAttributes<HTMLTextAreaElement>) => {
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
|
||||
const error = false;
|
||||
|
||||
return (
|
||||
<div className={`${className || ""}`}>
|
||||
{label && (
|
||||
<div className="mb-1 text-label-md">
|
||||
{label}
|
||||
{required && <span className="text-[#E93544]">*</span>}
|
||||
</div>
|
||||
)}
|
||||
<div className={`relative ${textarea ? "flex" : ""}`}>
|
||||
{textarea ? (
|
||||
<textarea
|
||||
className={`w-full border border-stroke-soft-200 text-strong-950 transition-colors resize-none outline-0 focus:!border-blue-500 ${
|
||||
error ? "!border-[#E93544]" : ""
|
||||
} ${
|
||||
isSmall
|
||||
? "h-30 p-2 rounded-lg text-label-sm"
|
||||
: "h-37.5 p-4 rounded-xl text-label-md"
|
||||
} ${classInput || ""}`}
|
||||
{...inputProps}
|
||||
></textarea>
|
||||
) : (
|
||||
<input
|
||||
className={`w-full border border-stroke-soft-200 text-strong-950 transition-colors outline-0 focus:!border-blue-500 ${
|
||||
error ? "!border-[#E93544]" : ""
|
||||
} ${
|
||||
isSmall
|
||||
? "h-9 px-2.5 rounded-lg text-label-sm"
|
||||
: "h-12 px-4 rounded-xl text-label-md"
|
||||
} ${classInput || ""}`}
|
||||
type={
|
||||
type === "password"
|
||||
? showPassword
|
||||
? "text"
|
||||
: "password"
|
||||
: type || "text"
|
||||
}
|
||||
{...inputProps}
|
||||
/>
|
||||
)}
|
||||
{type === "password" && (
|
||||
<button
|
||||
className={`group text-0 absolute right-3 top-1/2 -translate-y-1/2 outline-0 before:absolute before:top-1/2 before:left-1/2 before:w-5.5 before:h-0.75 before:border-t before:border-weak-50 before:-translate-1/2 before:-rotate-45 before:transition-all before:bg-soft-400 hover:before:bg-strong-950 ${
|
||||
showPassword
|
||||
? "before:opacity-0"
|
||||
: "before:opacity-100"
|
||||
}`}
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
>
|
||||
<Icon
|
||||
className="fill-soft-400 transition-colors group-hover:fill-strong-950"
|
||||
name="eye"
|
||||
/>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Field;
|
||||
@@ -0,0 +1,44 @@
|
||||
import { FadeLoader } from "react-spinners";
|
||||
import Image from "@/components/Image";
|
||||
|
||||
const Converter = ({}) => {
|
||||
return (
|
||||
<div className="border border-stroke-soft-200 rounded-xl p-3.5">
|
||||
<div className="flex items-center gap-3 p-1.25 shadow-[0_0_3px_0_rgba(0,0,0,0.14)] rounded-xl">
|
||||
<div className="relative size-[46px] rounded-lg bg-weak-50 max-4xl:size-[36px]">
|
||||
<div className="absolute -top-[7px] -left-[4px] scale-55 max-4xl:-top-[12px] max-4xl:-left-[10px] max-4xl:scale-35">
|
||||
<FadeLoader color="var(--strong-950)" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-label-md max-md:text-label-sm">
|
||||
Converting your file .....
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-3.5 p-3 rounded-xl bg-weak-50">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex justify-center items-center size-7 rounded-sm bg-blue-50">
|
||||
<Image
|
||||
src="/images/xls-type.svg"
|
||||
className="w-4.25 opacity-100"
|
||||
width={15}
|
||||
height={14}
|
||||
alt="File"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-label-sm">Docment res.XLS</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 mt-3">
|
||||
<div className="relative grow h-1.5 bg-soft-200 rounded-full">
|
||||
<div
|
||||
className="absolute top-0 left-0 bottom-0 rounded-full bg-linear-to-r from-[#7D52F4] to-blue-500"
|
||||
style={{ width: "80%" }}
|
||||
></div>
|
||||
</div>
|
||||
<div className="text-sub-600">80%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Converter;
|
||||
@@ -0,0 +1,28 @@
|
||||
import Image from "@/components/Image";
|
||||
|
||||
type Props = {
|
||||
name: string;
|
||||
size: string;
|
||||
};
|
||||
|
||||
const File = ({ name, size }: Props) => (
|
||||
<div className="flex items-center gap-3 max-w-97 h-12 border border-stroke-soft-200 bg-weak-50 rounded-lg px-3.5">
|
||||
<div className="flex justify-center items-center size-7 rounded-sm bg-blue-50">
|
||||
<Image
|
||||
src="/images/doc-type.svg"
|
||||
className="w-4.25 opacity-100"
|
||||
width={15}
|
||||
height={14}
|
||||
alt="File"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-label-sm">{name}</div>
|
||||
<div className="flex items-center ml-auto text-soft-400">
|
||||
<div className="text-p-xs">PDF</div>
|
||||
<div className="size-0.75 mx-1 rounded-full bg-soft-400"></div>
|
||||
<div className="text-label-xs">{size}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default File;
|
||||
@@ -0,0 +1,26 @@
|
||||
import Chat from "@/components/Chat";
|
||||
import Question from "@/components/Question";
|
||||
import Answer from "@/components/Answer";
|
||||
import File from "./File";
|
||||
import Converter from "./Converter";
|
||||
|
||||
const FileConverter = () => {
|
||||
return (
|
||||
<Chat>
|
||||
<Question>
|
||||
<div className="mb-1">
|
||||
Convert this file from DOC to XLS please
|
||||
</div>
|
||||
<File name="Docment res.Doc" size="2.1 Mb" />
|
||||
</Question>
|
||||
<Answer>
|
||||
<div className="mb-2">
|
||||
Sure converting your document to xls now:
|
||||
</div>
|
||||
<Converter />
|
||||
</Answer>
|
||||
</Chat>
|
||||
);
|
||||
};
|
||||
|
||||
export default FileConverter;
|
||||
@@ -0,0 +1,54 @@
|
||||
import { useState } from "react";
|
||||
import Image from "@/components/Image";
|
||||
import ModalView from "@/components/ModalView";
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
image: string;
|
||||
index: number;
|
||||
};
|
||||
|
||||
const Preview = ({ className, image, index }: Props) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={`absolute cursor-pointer overflow-hidden rounded-xl ${
|
||||
className || ""
|
||||
}`}
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
<Image
|
||||
className="object-cover scale-101"
|
||||
src={image}
|
||||
fill
|
||||
alt=""
|
||||
/>
|
||||
{index === 0 && (
|
||||
<div className="absolute inset-0 rounded-xl bg-overlay backdrop-blur-2xl">
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex justify-center items-center gap-1.5 w-full">
|
||||
<Image
|
||||
className="w-6 opacity-100"
|
||||
src="/images/stars-white.svg"
|
||||
width={24}
|
||||
height={24}
|
||||
alt=""
|
||||
/>
|
||||
<div className="text-label-sm text-static-white max-md:text-label-xs">
|
||||
Generating...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<ModalView
|
||||
open={open}
|
||||
onClose={() => setOpen(false)}
|
||||
image={image}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Preview;
|
||||
22
src/views/AgentChat/neuratalk/components/Gallery/index.tsx
Normal file
22
src/views/AgentChat/neuratalk/components/Gallery/index.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import Preview from "./Preview";
|
||||
|
||||
const Gallery = ({}) => {
|
||||
return (
|
||||
<div className="relative h-160 max-4xl:h-106 max-md:h-60">
|
||||
{[
|
||||
"/images/image-2.jpg",
|
||||
"/images/image-3.jpg",
|
||||
"/images/image-4.jpg",
|
||||
].map((image, index) => (
|
||||
<Preview
|
||||
className="w-[calc(50%-0.25rem)] first:top-0 first:left-0 first:bottom-0 not-first:h-[calc(50%-0.25rem)] not-first:right-0 nth-2:top-0 nth-3:bottom-0"
|
||||
image={image}
|
||||
key={index}
|
||||
index={index}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Gallery;
|
||||
@@ -0,0 +1,47 @@
|
||||
import { useState } from "react";
|
||||
import Button from "@/components/Button";
|
||||
import Modal from "@/components/Modal";
|
||||
import ModalPlan from "@/components/ModalPlan";
|
||||
|
||||
const SpecialOffer = ({}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [openModalPlan, setOpenModalPlan] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
icon="gift"
|
||||
isStroke
|
||||
isCircle
|
||||
onClick={() => setOpen(true)}
|
||||
/>
|
||||
<Modal
|
||||
classWrapper="max-w-100"
|
||||
open={open}
|
||||
onClose={() => setOpen(false)}
|
||||
>
|
||||
<div className="mb-2 text-center text-h5">Special Offer</div>
|
||||
<div className="mb-6 text-p-md text-center text-sub-600">
|
||||
Upgrade today and get 20% off your first month.
|
||||
</div>
|
||||
<Button
|
||||
className="w-full h-12"
|
||||
isBlack
|
||||
icon="gift"
|
||||
onClick={() => {
|
||||
setOpen(false);
|
||||
setOpenModalPlan(true);
|
||||
}}
|
||||
>
|
||||
Claim Offer
|
||||
</Button>
|
||||
</Modal>
|
||||
<ModalPlan
|
||||
open={openModalPlan}
|
||||
onClose={() => setOpenModalPlan(false)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SpecialOffer;
|
||||
57
src/views/AgentChat/neuratalk/components/Header/index.tsx
Normal file
57
src/views/AgentChat/neuratalk/components/Header/index.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import { useState } from "react";
|
||||
import Button from "@/components/Button";
|
||||
import ModalPlan from "@/components/ModalPlan";
|
||||
import Icon from "@/components/Icon";
|
||||
import SpecialOffer from "./SpecialOffer";
|
||||
|
||||
type Props = {
|
||||
onOpenSidebar: () => void;
|
||||
onToggleTools: () => void;
|
||||
};
|
||||
|
||||
const Header = ({ onOpenSidebar, onToggleTools }: Props) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex items-center gap-4 mb-3.5 max-md:gap-2 max-md:mb-3">
|
||||
<button
|
||||
className="hidden size-10 mr-2 justify-center items-center max-lg:flex max-md:mr-0"
|
||||
onClick={onOpenSidebar}
|
||||
>
|
||||
<Icon className="!size-6 fill-strong-950" name="burger" />
|
||||
</button>
|
||||
<div className="grow">
|
||||
<div className="text-label-xl max-md:text-label-md">
|
||||
Chat With AI
|
||||
</div>
|
||||
<div className="mt-1 line-clamp-1 text-label-md text-sub-600 max-lg:hidden">
|
||||
Break down lengthy texts into concise summaries to
|
||||
grasp.
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex shrink-0 gap-1.5">
|
||||
<Button
|
||||
className="max-md:hidden"
|
||||
icon="flash"
|
||||
isBlack
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
Upgrade
|
||||
</Button>
|
||||
<Button icon="help-circle" isStroke isCircle />
|
||||
<SpecialOffer />
|
||||
<Button
|
||||
icon="wrench"
|
||||
isStroke
|
||||
isCircle
|
||||
onClick={onToggleTools}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<ModalPlan open={open} onClose={() => setOpen(false)} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
||||
116
src/views/AgentChat/neuratalk/components/Icon/index.tsx
Normal file
116
src/views/AgentChat/neuratalk/components/Icon/index.tsx
Normal file
@@ -0,0 +1,116 @@
|
||||
type IconsType = {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
const icons: IconsType = {
|
||||
"add-team":
|
||||
"M7.082 2.71c1.956 0 3.542 1.586 3.542 3.542S9.038 9.793 7.082 9.793 3.54 8.208 3.54 6.252 5.126 2.71 7.082 2.71zm4.166 0c1.956 0 3.542 1.586 3.542 3.542s-1.586 3.542-3.542 3.542c-.345 0-.625-.28-.625-.625s.28-.625.625-.625a2.29 2.29 0 1 0 0-4.583c-.345 0-.625-.28-.625-.625s.28-.625.625-.625zM7.082 3.96a2.29 2.29 0 1 0 0 4.583 2.29 2.29 0 1 0 0-4.583zm1.548 7.083a4.69 4.69 0 0 1 2.678.825c.284.197.354.586.157.87s-.586.354-.87.157c-.56-.388-1.243-.603-1.965-.603H5.534c-1.802 0-3.244 1.331-3.244 2.946 0 .432.402.804.923.804h7.738c.345 0 .625.28.625.625s-.28.625-.625.625H3.213c-1.189 0-2.173-.908-2.173-2.054 0-2.329 2.023-4.196 4.494-4.196h3.095zm7.202 0c.345 0 .625.28.625.625v1.875h1.875c.314 0 .574.231.618.533l.007.092c0 .345-.28.625-.625.625h-1.875v1.875c0 .314-.231.574-.533.618l-.092.007c-.345 0-.625-.28-.625-.625v-1.875h-1.875c-.314 0-.574-.231-.618-.533l-.007-.092c0-.345.28-.625.625-.625h1.875v-1.875c0-.314.231-.574.533-.618l.092-.007z",
|
||||
"ai-chat":
|
||||
"M11.859 1.56c3.818.251 6.856 3.304 7.106 7.131a16.83 16.83 0 0 1 0 2.17c-.25 3.828-3.288 6.88-7.106 7.131-1.222.08-2.497.08-3.718 0-.487-.032-1-.147-1.441-.327l-.465-.183.025.009-.008.008c-.038.031-.107.08-.201.148l-.075.054c-.75.547-1.603.822-2.69.796-.933-.022-1.163-.066-1.434-.525-.277-.468-.206-.665.309-1.631.401-.752.501-1.355.307-1.706-.841-1.251-1.35-2.497-1.433-3.774a16.84 16.84 0 0 1 0-2.17c.25-3.828 3.288-6.88 7.106-7.131a28.68 28.68 0 0 1 3.718 0zM8.224 2.801c-3.186.21-5.727 2.762-5.936 5.97-.043.662-.043 1.348 0 2.01.067 1.03.496 2.08 1.252 3.209.474.851.309 1.847-.269 2.932l-.147.278-.025.047.014.001.093.003.11.003c.804.019 1.386-.168 1.914-.554.552-.404.617-.445.879-.476s.323-.013 1.068.291a3.48 3.48 0 0 0 1.046.236c1.165.077 2.385.077 3.551 0 3.186-.21 5.727-2.762 5.936-5.971a15.6 15.6 0 0 0 0-2.01c-.209-3.208-2.75-5.761-5.936-5.97a27.41 27.41 0 0 0-3.551 0zm.102 4.089c.52 0 .982.33 1.147.819l1.542 4.582a.62.62 0 0 1-.397.787.63.63 0 0 1-.794-.393l-.416-1.233H7.244l-.414 1.233a.63.63 0 0 1-.704.416l-.09-.023a.62.62 0 0 1-.397-.787L7.18 7.709c.165-.489.626-.819 1.147-.819zm4.605 0c.347 0 .628.278.628.622v4.976c0 .343-.281.622-.628.622s-.628-.278-.628-.622V7.512c0-.343.281-.622.628-.622zM8.326 8.235l-.664 1.972H8.99l-.664-1.972z",
|
||||
"ai-programming":
|
||||
"M9.582 4.373c.345 0 .625.28.625.625s-.28.625-.625.625c-4.469 0-5.51.118-6.355.829-.782.658-.929 1.454-.937 4.892v.64c.008 3.438.155 4.234.937 4.892.823.693 1.831.823 6.009.829h.691c4.178-.006 5.186-.136 6.009-.829.805-.678.937-1.503.937-5.212v-.473l-.023-1.766-.01-.23c-.017-.345.249-.638.593-.655s.638.249.655.593l.035 2.046v.485c0 4.147-.158 5.138-1.382 6.168-1.155.973-2.244 1.117-6.811 1.123h-.698c-4.567-.006-5.656-.15-6.811-1.123-1.19-1.002-1.372-1.966-1.381-5.83v-.338c0-4.147.158-5.138 1.382-6.168 1.184-.997 2.299-1.123 7.16-1.123zm1.031 4.199c.327.109.504.463.395.791l-1.667 5c-.109.327-.463.504-.791.395s-.504-.463-.395-.791l1.667-5c.109-.327.463-.504.791-.395zm2.711.953l1.022.881c.722.622.862.78.862 1.259s-.14.637-.862 1.259l-1.022.881c-.261.225-.656.196-.881-.065s-.196-.656.065-.881l1.022-.881.346-.299.018-.013-.018-.014-.248-.214-.098-.085-1.022-.881c-.261-.225-.291-.62-.065-.881s.62-.291.881-.065zm-6.602.065c.225.261.196.656-.065.881l-1.022.881-.346.299-.019.014.019.013.248.214.098.085 1.022.881c.261.225.291.62.065.881s-.62.291-.881.065l-1.022-.881c-.721-.622-.862-.78-.862-1.259s.14-.637.861-1.259l1.022-.881c.261-.225.656-.196.881.065zm9.28-8.142l.215.581c.315.853.405 1.044.556 1.195s.343.241 1.195.556l.581.215c.544.201.544.971 0 1.172l-.581.215c-.853.315-1.044.405-1.195.556s-.241.342-.556 1.195l-.215.581c-.201.544-.971.544-1.172 0l-.215-.581-.336-.852c-.079-.167-.144-.267-.221-.343-.152-.152-.343-.241-1.195-.556l-.581-.215c-.544-.201-.544-.971 0-1.172l.581-.215c.853-.316 1.044-.405 1.195-.556.076-.076.142-.176.221-.343s.147-.341.336-.852l.215-.581c.201-.544.971-.544 1.172 0zm-.588 1.954l-.004.011c-.136.288-.279.506-.468.695-.178.178-.336.296-.603.426l-.102.047.102.048c.234.114.383.218.537.362l.066.064c.189.189.332.406.468.695l.004.011.049-.103a2 2 0 0 1 .362-.537l.064-.066c.178-.178.336-.296.603-.426l.101-.048-.101-.047a2 2 0 0 1-.536-.362l-.066-.064c-.178-.178-.296-.335-.426-.603l-.049-.103z",
|
||||
"ai-search":
|
||||
"M9.168 3.123c.345 0 .625.28.625.625s-.28.625-.625.625A5.21 5.21 0 0 0 3.96 9.582a5.21 5.21 0 0 0 5.208 5.208 5.21 5.21 0 0 0 5.208-5.208c0-.345.28-.625.625-.625s.625.28.625.625a6.43 6.43 0 0 1-1.472 4.104l2.955 2.954c.244.244.244.64 0 .884s-.64.244-.884 0l-2.955-2.954a6.43 6.43 0 0 1-4.103 1.471A6.46 6.46 0 0 1 2.71 9.582a6.46 6.46 0 0 1 6.458-6.458zm4.337-.425l.215.581c.315.853.405 1.044.556 1.195s.343.241 1.195.556l.581.215c.544.201.544.971 0 1.172l-.581.215c-.853.316-1.044.405-1.195.556s-.241.342-.556 1.195l-.215.581c-.201.544-.971.544-1.172 0l-.215-.581-.336-.852c-.079-.167-.144-.267-.221-.343-.152-.152-.343-.241-1.195-.556l-.581-.215c-.544-.201-.544-.971 0-1.172l.581-.215c.853-.316 1.044-.405 1.195-.556s.241-.343.556-1.195l.215-.581c.201-.544.971-.544 1.172 0zm-.587 1.955l-.047.102c-.13.267-.248.424-.426.603s-.336.296-.603.426l-.102.047.102.048c.234.114.383.218.537.362l.066.064c.189.189.332.406.468.695l.004.011.049-.103a2 2 0 0 1 .362-.537l.064-.066c.178-.178.335-.296.603-.426l.101-.048-.101-.047a2 2 0 0 1-.537-.362l-.066-.064c-.178-.178-.296-.335-.426-.603l-.048-.102z",
|
||||
"alert-circle":
|
||||
"M10 1a9 9 0 1 1 0 18 9 9 0 1 1 0-18zm0 1.256c-4.277 0-7.744 3.467-7.744 7.744S5.723 17.744 10 17.744s7.744-3.467 7.744-7.744S14.277 2.256 10 2.256zm-.008 9.419a.84.84 0 0 1 .847.837c0 .462-.375.837-.837.837a.84.84 0 0 1-.847-.837c0-.462.375-.837.837-.837zm.007-5.651a.63.63 0 0 1 .628.628V10a.63.63 0 0 1-.628.628.63.63 0 0 1-.628-.628V6.651a.63.63 0 0 1 .628-.628z",
|
||||
analytic:
|
||||
"M10.366 1.5c4.542.008 5.645.182 6.798 1.336C18.348 4.02 18.5 5.15 18.5 10v.366c-.008 4.542-.182 5.645-1.335 6.798C15.98 18.348 14.85 18.5 10 18.5h-.366c-4.542-.008-5.645-.182-6.798-1.336S1.508 14.905 1.5 10.348v-.714c.008-4.542.182-5.645 1.336-6.798S5.095 1.508 9.652 1.5h.714zM10 2.744c-4.434 0-5.45.137-6.285.972S2.744 5.566 2.744 10s.137 5.449.972 6.285 1.85.972 6.285.972h.352c4.137-.008 5.12-.159 5.932-.971.835-.835.971-1.851.971-6.285v-.352c-.008-4.137-.159-5.12-.971-5.932-.835-.835-1.851-.972-6.285-.972zm-4.146 9.951a.62.62 0 0 1 .622.622v1.658a.62.62 0 1 1-1.244 0v-1.658a.62.62 0 0 1 .622-.622zM10 11.866a.62.62 0 0 1 .622.622v2.488a.62.62 0 1 1-1.244 0v-2.488a.62.62 0 0 1 .622-.622zm4.146-1.658a.62.62 0 0 1 .622.622v4.146a.62.62 0 1 1-1.244 0v-4.146a.62.62 0 0 1 .622-.622zm.194-5.07l.411 1.359a.62.62 0 0 1-1.191.36l-.13-.431-.118.168c-1.953 2.665-4.861 3.648-7.999 3.61l-.315-.007a.62.62 0 1 1 .041-1.243c2.868.096 5.503-.727 7.24-3.056l.084-.118-.611.099a.62.62 0 0 1-.689-.417l-.024-.098a.62.62 0 0 1 .515-.713l1.576-.253c.47-.06 1.023.248 1.21.741z",
|
||||
archive:
|
||||
"M16.971 2.199C18 3.229 18.13 4.194 18.13 8.332v3.333c0 4.137-.13 5.103-1.159 6.132-1.001 1.001-1.941 1.151-5.795 1.159H8.834c-3.854-.008-4.794-.158-5.795-1.159s-1.151-1.941-1.159-5.795V8.332c0-4.137.13-5.103 1.159-6.132C4.04 1.198 4.981 1.048 8.834 1.04h2.004c4.137 0 5.103.13 6.132 1.159zm-.091 8.424H3.13v1.363c.007 3.448.134 4.269.793 4.928s1.479.786 4.928.793h2.308c3.448-.007 4.269-.134 4.928-.793.679-.679.793-1.529.793-5.248v-1.042zm-4.375 2.917c.345 0 .625.28.625.625s-.28.625-.625.625h-5c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h5zM11.159 2.29H8.851c-3.448.007-4.269.134-4.928.793s-.786 1.479-.793 4.928v1.362h13.75V8.332c0-3.719-.114-4.569-.793-5.248-.639-.639-1.43-.778-4.621-.792l-.306-.001zm1.346 2.916c.345 0 .625.28.625.625s-.28.625-.625.625h-5c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h5z",
|
||||
arrow: "M12.953 5.127l.684.529 1.499 1.248.708.648C16.922 8.581 17.5 9.332 17.5 10s-.578 1.419-1.656 2.448l-.708.648-1.499 1.248-.684.529c-.286.214-.688.152-.899-.138a.66.66 0 0 1 .136-.912l.655-.507 1.447-1.204.67-.613.809-.847H3.143c-.355 0-.643-.292-.643-.652s.288-.652.643-.652h12.63a11.94 11.94 0 0 0-.81-.847l-.67-.613-1.447-1.204-.655-.507a.66.66 0 0 1-.136-.912c.211-.29.613-.352.899-.138z",
|
||||
api: "M17.201 2.802c1.161 1.161 1.334 2.27 1.342 6.849v.7c-.008 4.579-.181 5.688-1.342 6.849s-2.27 1.334-6.849 1.342h-.7c-4.579-.008-5.688-.181-6.849-1.342s-1.334-2.27-1.342-6.849v-.35c0-4.874.153-6.009 1.342-7.199 1.161-1.161 2.27-1.334 6.849-1.342h.35c4.874 0 6.009.153 7.199 1.342zm-6.863-.092h-.672c-4.172.007-5.162.158-5.979.976-.839.839-.976 1.859-.976 6.315v.336c.007 4.172.158 5.162.976 5.979s1.807.969 5.979.976h.672c4.172-.007 5.162-.158 5.979-.976s.969-1.807.976-5.979v-.672c-.007-4.172-.158-5.162-.976-5.979-.796-.796-1.755-.96-5.657-.975l-.323-.001zM6.829 7.261l1.562 3.75.521 1.25c.133.319-.018.685-.337.817s-.685-.018-.817-.337l-.361-.865H5.451l-.273.823c-.098.295-.395.468-.692.42l-.099-.024c-.327-.109-.504-.463-.395-.791l.417-1.25 1.25-3.75c.183-.548.948-.576 1.17-.043zm5.257-.385c1.035 0 1.875.839 1.875 1.875s-.84 1.875-1.875 1.875h-1.042v1.875c0 .314-.231.574-.533.618l-.092.007c-.345 0-.625-.28-.625-.625V8.085c0-.278.004-.343.051-.488a1.04 1.04 0 0 1 .669-.669c.146-.047.211-.051.488-.051h1.083zm3.333 0c.345 0 .625.28.625.625v5c0 .345-.28.625-.625.625s-.625-.28-.625-.625v-5c0-.345.28-.625.625-.625zM6.316 9.283l-.448 1.344h1.008l-.56-1.344zm5.77-1.156h-1.042v1.25h1.042c.345 0 .625-.28.625-.625s-.28-.625-.625-.625z",
|
||||
bell: "M10.005 1.04c1.085 0 1.875.517 1.875 1.563 0 .389-.112.787-.306 1.135 2.625.668 4.608 2.98 4.756 5.804l.017.38.005.12c.053 1.276.206 1.8.759 2.214.641.481 1.018 1.235 1.018 2.037 0 1.185-.938 2.164-2.125 2.164h-2.938c-.29 1.426-1.551 2.5-3.062 2.5s-2.773-1.073-3.062-2.5H4.005c-1.187 0-2.125-.98-2.125-2.164 0-.801.377-1.556 1.018-2.037.553-.415.706-.939.759-2.214l.005-.12.017-.38c.149-2.824 2.131-5.136 4.757-5.805-.194-.347-.307-.744-.307-1.133 0-1.045.79-1.562 1.875-1.562zm1.768 15.417H8.237c.257.728.952 1.25 1.768 1.25s1.511-.522 1.768-1.25zM10.019 4.79h-.014l-.014-.001-.21.006c-2.602.113-4.715 2.187-4.853 4.812l-.016.364-.005.122c-.068 1.626-.309 2.45-1.258 3.163-.326.245-.518.629-.518 1.037 0 .506.391.914.875.914h12c.484 0 .875-.408.875-.914 0-.408-.192-.792-.518-1.037-.95-.712-1.191-1.536-1.258-3.163l-.005-.122-.016-.364c-.142-2.696-2.365-4.81-5.063-4.817zm-.014-2.5c-.478 0-.625.096-.625.313 0 .435.366.93.619.937l.012-.001.054-.008c.248-.068.565-.524.565-.929 0-.216-.147-.312-.625-.312z",
|
||||
browser:
|
||||
"M17.201 2.802c1.161 1.161 1.334 2.27 1.342 6.849v.7c-.008 4.579-.181 5.688-1.342 6.849s-2.27 1.334-6.849 1.342h-.7c-4.579-.008-5.688-.181-6.849-1.342s-1.334-2.27-1.342-6.849v-.35c0-4.874.153-6.009 1.342-7.199 1.161-1.161 2.27-1.334 6.849-1.342h.35c4.874 0 6.009.153 7.199 1.342zm.08 5.323L2.723 8.125l-.013 1.876v.336c.007 4.172.158 5.162.976 5.979s1.807.969 5.979.976h.672c4.172-.007 5.162-.158 5.979-.976s.969-1.807.976-5.979v-.672l-.012-1.54zM10.338 2.71h-.672c-4.172.007-5.162.158-5.979.976-.592.592-.835 1.274-.926 3.189l14.483.001c-.092-1.915-.334-2.597-.926-3.189-.796-.796-1.755-.96-5.657-.975l-.323-.001zM5.842 4.168c.46 0 .833.373.833.833s-.373.833-.833.833c-.468 0-.841-.373-.841-.833s.373-.833.833-.833zm3.334 0c.46 0 .833.373.833.833s-.373.833-.833.833c-.468 0-.841-.373-.841-.833s.373-.833.833-.833z",
|
||||
build: "M11.841 17H3.25 1.614C1.275 17 1 16.723 1 16.382s.275-.618.614-.618h1.023v-10.5c0-.546.196-1.072.549-1.482l.11-.119C3.717 3.239 4.29 3 4.886 3h5.318c.597 0 1.169.239 1.591.663s.659 1.001.659 1.601V6.5h2.659a2.24 2.24 0 0 1 1.472.552l.119.111c.422.425.659 1.001.659 1.601v7h1.023c.311 0 .567.232.608.534l.006.084c0 .341-.275.618-.614.618H16.75h-4.909zm.614-1.235h3.682v-7c0-.234-.079-.46-.223-.641l-.077-.087a1.02 1.02 0 0 0-.723-.302h-2.659v8.029zm-2.25-11.529H4.886a1.02 1.02 0 0 0-.723.302c-.192.193-.3.455-.3.728v10.5h7.364V7.118 5.265c0-.273-.108-.535-.3-.728a1.02 1.02 0 0 0-.723-.302zm-1.636 6.176c.339 0 .614.277.614.618s-.275.618-.614.618H6.523c-.339 0-.614-.277-.614-.618s.275-.618.614-.618h2.045zm0-3.294c.339 0 .614.277.614.618s-.275.618-.614.618H6.523c-.339 0-.614-.277-.614-.618s.275-.618.614-.618h2.045z",
|
||||
burger: "M3.333 5c-.46 0-.833.373-.833.833s.373.833.833.833h13.333c.46 0 .833-.373.833-.833S17.127 5 16.667 5H3.333zm0 4.167c-.46 0-.833.373-.833.833s.373.833.833.833h13.333c.46 0 .833-.373.833-.833s-.373-.833-.833-.833H3.333zm0 4.167c-.46 0-.833.373-.833.833s.373.833.833.833h13.333c.46 0 .833-.373.833-.833s-.373-.833-.833-.833H3.333z",
|
||||
calendar:
|
||||
"M13.333.66a1 1 0 0 1 .974.771l.01.063.683-.001a3.5 3.5 0 0 1 3.495 3.308l.005.192v2.5 8.333a3.5 3.5 0 0 1-3.5 3.5H5a3.5 3.5 0 0 1-3.5-3.5V7.493v-2.5a3.5 3.5 0 0 1 3.5-3.5l.682.001.011-.063A1 1 0 0 1 6.55.667L6.667.66a1 1 0 0 1 .974.771l.011.063h4.697l.012-.063a1 1 0 0 1 .857-.764l.117-.007zM16.5 8.493h-13v7.334a1.5 1.5 0 0 0 1.356 1.493l.144.007h10a1.5 1.5 0 0 0 1.5-1.5V8.493zm-2.193-4.937a1 1 0 0 1-1.947 0l-.012-.063H7.651l-.011.063a1 1 0 0 1-.857.764l-.117.007a1 1 0 0 1-.974-.771l-.011-.063H5a1.5 1.5 0 0 0-1.493 1.356l-.007.144v1.5h13v-1.5A1.5 1.5 0 0 0 15.144 3.5L15 3.493h-.683l-.01.063z",
|
||||
calculator:
|
||||
"M17.177 2.664c1.21 1.089 1.366 2.132 1.366 6.546v1.583c0 4.414-.156 5.457-1.366 6.546-1.158 1.042-2.254 1.197-6.826 1.204h-.699c-4.572-.007-5.668-.162-6.826-1.204-1.179-1.061-1.357-2.077-1.366-6.205V9.21c0-4.414.156-5.457 1.366-6.546C3.984 1.622 5.08 1.467 9.652 1.46h.349c4.866 0 5.989.136 7.175 1.204zm-6.839.046h-.673c-4.18.007-5.182.144-6.003.883S2.71 5.227 2.71 9.21v1.908c.008 3.708.156 4.576.952 5.292.821.738 1.823.876 6.003.883h.673c4.18-.007 5.182-.144 6.003-.883s.952-1.634.952-5.617V9.21c0-3.983-.134-4.88-.952-5.617-.799-.719-1.77-.869-5.679-.882l-.323-.001zm-1.647 8.444l.087.072c.244.244.244.64 0 .884l-1.017 1.016 1.017 1.017c.217.217.241.554.072.797l-.072.087c-.244.244-.64.244-.884 0L6.877 14.01l-1.016 1.017c-.217.217-.554.241-.797.072l-.087-.072c-.244-.244-.244-.64 0-.884l1.016-1.017-1.016-1.016c-.217-.217-.241-.554-.072-.797l.072-.087c.244-.244.64-.244.884 0l1.016 1.016 1.017-1.016c.217-.217.554-.241.797-.072zm6.311 2.806c.345 0 .625.28.625.625s-.28.625-.625.625h-3.333c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h3.333zm0-2.5c.345 0 .625.28.625.625s-.28.625-.625.625h-3.333c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h3.333zm-1.667-7.083c.345 0 .625.28.625.625l-.001 1.041h1.042c.314 0 .574.231.618.533l.007.092c0 .345-.28.625-.625.625H13.96l.001 1.042c0 .314-.231.574-.533.618l-.092.007c-.345 0-.625-.28-.625-.625l-.001-1.042h-1.041c-.314 0-.574-.231-.618-.533l-.007-.092c0-.345.28-.625.625-.625h1.041l.001-1.041c0-.314.231-.574.533-.618l.092-.007zm-5 1.667c.345 0 .625.28.625.625s-.28.625-.625.625H5.002c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h3.333z",
|
||||
chat: "M12.998 9.454l1.4.824v4.506c0 1.839-1.522 3.346-3.419 3.346a3.44 3.44 0 0 1-2.579-1.149l.056-.031 4.219-2.39a.48.48 0 0 0 .242-.408l.081-4.698zm-9.957 2.674l.074.043 4.219 2.39a.48.48 0 0 0 .464.004l4.195-2.285-.027 1.584-3.981 2.255c-1.64.929-3.734.374-4.676-1.226-.514-.874-.581-1.88-.268-2.764zm9.395-5.715l3.987 2.259c1.635.926 2.188 2.97 1.25 4.565a3.41 3.41 0 0 1-2.32 1.617v-.034-4.814a.48.48 0 0 0-.236-.412l-4.095-2.411 1.413-.769zm-7.78-1.255l-.001 4.848a.48.48 0 0 0 .235.412l2.42 1.425.032.019 1.644.968-1.413.77-3.987-2.259c-1.635-.926-2.188-2.97-1.25-4.565a3.41 3.41 0 0 1 2.32-1.617zm5.388 2.558l2.007 1.181-.039 2.283-2.047 1.115-1.919-1.13V8.803l1.998-1.088zM9.031 1.88a3.44 3.44 0 0 1 2.578 1.148l-.057.032-4.218 2.39a.48.48 0 0 0-.242.416v4.737l-1.479-.871V5.226c0-1.839 1.522-3.346 3.419-3.346zm7.667 3.238c.514.874.581 1.879.268 2.764l-.072-.042-4.219-2.39a.48.48 0 0 0-.464-.004L8.047 7.715V6.144l3.976-2.252c1.64-.929 3.734-.374 4.676 1.226z",
|
||||
check: "M15.377 4.75l.904.863-8.75 9.167-.442.463-.452-.452-2.917-2.917.884-.884 2.464 2.464z",
|
||||
chevron:
|
||||
"M10.003 10.782l3.712-3.712 1.06 1.06-4.773 4.773L5.23 8.131l1.061-1.06z",
|
||||
"chevron-circle":
|
||||
"M10 1a9 9 0 1 1 0 18 9 9 0 1 1 0-18zm0 1.256c-4.277 0-7.744 3.467-7.744 7.744S5.723 17.744 10 17.744s7.744-3.467 7.744-7.744S14.277 2.256 10 2.256zm-.816 3.947l.126.126.279.286c.302.314.603.642.886.969a16.53 16.53 0 0 1 .42.505c.639.802.989 1.398.989 1.911s-.35 1.109-.989 1.911a16.53 16.53 0 0 1-.42.505c-.283.327-.584.655-.886.969l-.279.286-.126.126a.63.63 0 0 1-.888-.008.63.63 0 0 1 .008-.888l.116-.116.263-.27a23.74 23.74 0 0 0 .841-.92 15.29 15.29 0 0 0 .388-.466c.447-.561.715-1.018.715-1.129s-.268-.567-.715-1.129c-.119-.149-.249-.305-.388-.466-.267-.309-.554-.621-.841-.92l-.263-.27-.116-.116a.63.63 0 0 1-.008-.888.63.63 0 0 1 .888-.008z",
|
||||
close: "M3.684 3.684a.63.63 0 0 1 .89 0l5.425 5.427 5.427-5.427a.63.63 0 0 1 .802-.073l.087.073a.63.63 0 0 1 0 .89l-5.427 5.425 5.427 5.427a.63.63 0 0 1 .073.802l-.073.087a.63.63 0 0 1-.89 0l-5.427-5.427-5.425 5.427a.63.63 0 0 1-.802.073l-.087-.073a.63.63 0 0 1 0-.89l5.427-5.427-5.427-5.425a.63.63 0 0 1-.073-.802l.073-.087z",
|
||||
comment:
|
||||
"M17.797 2.599c1.001 1.001 1.152 1.941 1.159 5.795v1.092c-.008 3.854-.158 4.794-1.159 5.795-1.029 1.03-1.995 1.159-6.118 1.159-.449.01-.773.044-1.078.113-.618.142-1.145.365-2.181.88l-.2.1-.227.113-.059.029-.037.018c-1.947.95-2.345 1.078-3.009.595-.531-.395-.671-.987-.575-1.784l.022-.168-.114-.022c-.755-.166-1.379-.459-1.865-.885l-.157-.147C1.198 14.28 1.048 13.339 1.04 9.486v-.754c0-4.137.13-5.103 1.159-6.132C3.2 1.598 4.141 1.448 7.994 1.44h3.671c4.137 0 5.103.13 6.132 1.159zm-5.811.091H8.011c-3.448.007-4.269.134-4.928.793s-.786 1.479-.793 4.928v1.058c.007 3.448.134 4.269.793 4.928.314.314.758.543 1.342.681l.196.041.009-.031.063-.223.02-.07.09-.356c.069-.338.4-.556.738-.487s.556.4.487.738l-.11.439-.134.475-.148.582c-.142.647-.113 1.015-.006 1.095.057.041.412-.074 1.72-.712l.514-.254c1.121-.558 1.713-.808 2.459-.98.397-.09.803-.133 1.343-.145 3.719 0 4.569-.114 5.248-.793.659-.659.786-1.479.793-4.928V8.411c-.007-3.448-.134-4.269-.793-4.928-.639-.639-1.43-.778-4.621-.792l-.306-.001zm1.346 7.916c.345 0 .625.28.625.625s-.28.625-.625.625H6.665c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h6.667zM9.998 6.44c.345 0 .625.28.625.625s-.28.625-.625.625H6.665c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h3.333z",
|
||||
database:
|
||||
"M10.002 1.04c3.911 0 7.135 1.174 7.286 2.991l.006.134v11.667c0 1.893-3.285 3.125-7.292 3.125S2.71 17.725 2.71 15.832V4.165c0-1.893 3.285-3.125 7.292-3.125zm0 12.083a17.49 17.49 0 0 1-2.707-.202l.001 1.244c0 .345-.28.625-.625.625s-.625-.28-.625-.625l-.001-1.502c-.824-.215-1.535-.5-2.086-.845l.001 4.014c0 .868 2.685 1.875 6.042 1.875s6.042-1.007 6.042-1.875l.001-4.014c-1.314.824-3.538 1.305-6.043 1.305zm6.043-7.139c-1.314.824-3.537 1.305-6.043 1.305a17.49 17.49 0 0 1-2.707-.202l.001 1.244c0 .345-.28.625-.625.625s-.625-.28-.625-.625L6.045 6.83c-.824-.215-1.535-.5-2.085-.845l-.001 4.013c.001.869 2.686 1.875 6.043 1.875s6.042-1.007 6.042-1.875h.001V5.985zM10.002 2.29c-3.357 0-6.042 1.007-6.042 1.875S6.644 6.04 10.002 6.04s6.042-1.007 6.042-1.875-2.684-1.875-6.042-1.875z",
|
||||
document:
|
||||
"M16.517 2.199c1.001 1.001 1.151 1.941 1.159 5.795v.754c0 .345-.28.625-.625.625s-.625-.28-.625-.625v-.737c-.007-3.448-.134-4.269-.793-4.928s-1.479-.786-4.928-.793H9.231c-3.448.007-4.269.134-4.928.793s-.786 1.479-.793 4.928v4.377c.006 2.984.106 3.709.614 4.329.113.137.238.263.375.376.641.526 1.393.615 4.635.615.345 0 .625.28.625.625s-.28.625-.625.625c-3.607 0-4.455-.1-5.428-.899-.2-.165-.384-.348-.549-.549-.773-.942-.891-1.767-.898-5.097v-4.08c0-4.137.13-5.103 1.159-6.132C4.42 1.198 5.361 1.048 9.214 1.04h1.171c4.137 0 5.103.13 6.132 1.159zm-1.966 8.841c1.671 0 3.125 1.53 3.125 3.125v2.5c0 .345-.28.625-.625.625s-.625-.28-.625-.625v-2.5c0-.918-.909-1.875-1.875-1.875s-1.875.957-1.875 1.875v2.917c0 .345.28.625.625.625s.625-.28.625-.625v-2.917c0-.345.28-.625.625-.625s.625.28.625.625v2.917c0 1.035-.84 1.875-1.875 1.875s-1.875-.84-1.875-1.875v-2.917c0-1.595 1.454-3.125 3.125-3.125zm-3.333-1.667c.345 0 .625.28.625.625s-.28.625-.625.625h-5c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h5zm2.5-4.167c.345 0 .625.28.625.625s-.28.625-.625.625h-7.5c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h7.5z",
|
||||
"document-check":
|
||||
"M8.354 1.06c.345.015.613.306.598.651s-.306.613-.651.598c-1-.042-1.963-.012-2.834.064l-.785.086C3.253 2.562 2.3 3.443 2.3 5.804v.825.295l-.001.632-.001.701-.001.4-.001.423v.163l-.004 2.069-.001.91v.201.373.087l.001.555v.142l.001.263.008.945c0 1.33.812 2.721 2.146 2.799 2.742.16 7.29.17 9.284 0 .964-.054 1.976-.712 2.125-1.995.167-1.437.209-2.545.197-3.686l-.002-.166v-.06c0-.345.28-.625.625-.625s.625.28.625.625v.052l.002.161c.013 1.189-.032 2.347-.206 3.843-.233 2-1.794 3.014-3.278 3.097-2.044.175-6.649.164-9.446.001-2.148-.125-3.323-2.138-3.323-4.039l-.008-.946-.001-.264v-.07l-.001-1.289.001-.912.001-.526.003-1.549v-.163l.001-.423.001-.399.001-.7.001-.631v-.149l.001-.97c0-3.061 1.497-4.445 3.495-4.586l.813-.09a23.28 23.28 0 0 1 2.996-.068zm4.128 12.495c.345 0 .625.28.625.625s-.28.625-.625.625H5.815c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h6.667zm-3.333-3.333c.345 0 .625.28.625.625s-.28.625-.625.625H5.815c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h3.333zm5.011-9.167c2.648 0 4.796 2.145 4.796 4.792s-2.147 4.792-4.796 4.792-4.796-2.145-4.796-4.792 2.147-4.792 4.796-4.792zm0 1.25c-1.958 0-3.546 1.586-3.546 3.542s1.587 3.542 3.546 3.542 3.546-1.586 3.546-3.542-1.587-3.542-3.546-3.542zm2.244 2.083c.115.325-.055.683-.38.798-.073.026-.155.065-.244.118-.305.183-.657.503-1.022.919a10.85 10.85 0 0 0-.66.836l-.255.373c-.261.41-.869.379-1.087-.056a5.52 5.52 0 0 0-.514-.842l-.202-.245c-.244-.244-.244-.64 0-.884s.64-.244.884 0a3.8 3.8 0 0 1 .387.466l.054.08.197-.249.257-.304c.444-.505.883-.906 1.32-1.167.156-.093.312-.169.468-.224.325-.115.683.055.798.38z",
|
||||
dots: "M10.005 8.96a1.04 1.04 0 1 1 0 2.083c-.583 0-1.049-.466-1.049-1.042A1.04 1.04 0 0 1 9.998 8.96h.008zm-.006 5a1.04 1.04 0 1 1 0 2.083c-.583 0-1.049-.466-1.049-1.042a1.04 1.04 0 0 1 1.042-1.042h.008zm.013-10a1.04 1.04 0 1 1 0 2.083c-.583 0-1.049-.466-1.049-1.042a1.04 1.04 0 0 1 1.042-1.042h.008z",
|
||||
edit: "M4.998 11.873c.345 0 .625.28.625.625s-.28.625-.625.625H3.123c-.46 0-.833.373-.833.833s.373.833.833.833h7.917c1.151 0 2.083.933 2.083 2.083s-.933 2.083-2.083 2.083H9.165c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h1.875c.46 0 .833-.373.833-.833s-.373-.833-.833-.833H3.123c-1.151 0-2.083-.933-2.083-2.083s.933-2.083 2.083-2.083h1.875zM16.597 1.218l.125.06c.268.143.429.281.94.788l.274.274c.566.57.707.742.845 1.061a2.17 2.17 0 0 1 0 1.719c-.148.343-.3.516-.983 1.199l-4.185 4.185c-1.108 1.108-1.434 1.41-1.914 1.721a3.84 3.84 0 0 1-.453.254c-.537.254-1.079.37-2.112.484l-.916.094-.657.065c-.392.039-.722-.291-.683-.683l.065-.657.094-.916c.114-1.033.23-1.575.484-2.112.311-.657.627-1.019 1.975-2.367l4.32-4.319c.51-.508.671-.645.94-.788l.125-.06a2.17 2.17 0 0 1 1.719 0zm-1.224 1.148l-.033.016c-.12.064-.248.176-.659.585L10.2 7.447c-1.08 1.084-1.339 1.391-1.551 1.84-.179.379-.271.81-.371 1.714l-.075.732-.008.068.069-.006.566-.057.166-.018c.905-.1 1.335-.192 1.714-.371.104-.049.204-.105.306-.172.375-.243.678-.524 1.711-1.557l4.185-4.185c.54-.54.663-.68.719-.811a.92.92 0 0 0 0-.728c-.052-.121-.16-.249-.602-.693l-.237-.237c-.411-.408-.539-.521-.659-.585l-.033-.016a.92.92 0 0 0-.728 0z",
|
||||
exchange:
|
||||
"M5.838 3.143h.017l.034.003.042.004.014.002.015.003.029.008.03.006.013.005.02.007.026.011.024.009.017.01.021.009.016.011.023.013.019.014.023.016.016.014.011.008.018.018.029.027.003.005.012.012c.038.044.07.093.095.147l.031.082.005.016.008.042.008.032v.009l.003.013v.028l.003.042v2.904c0 .345-.28.625-.625.625s-.625-.28-.625-.625V5.076l-.073.07C3.936 6.351 3.206 7.974 3.136 9.727l-.006.278c0 3.797 3.078 6.875 6.875 6.875.519 0 1.031-.058 1.529-.17.337-.076.671.135.748.471s-.135.671-.471.748c-.588.133-1.192.201-1.805.201-4.487 0-8.125-3.638-8.125-8.125 0-2.059.772-3.987 2.102-5.455l.147-.158-1.207.001c-.314 0-.574-.231-.618-.533l-.007-.092c0-.345.28-.625.625-.625h2.917zm4.167-1.263c4.487 0 8.125 3.638 8.125 8.125 0 2.065-.777 3.999-2.115 5.469l-.148.156h1.221c.314 0 .574.231.618.533l.007.092c0 .345-.28.625-.625.625h-2.936l-.018-.001h-.01l-.022-.003-.042-.003-.022-.005-.029-.006-.037-.008-.021-.009-.014-.003-.023-.011-.025-.009-.021-.012-.019-.008-.016-.011-.021-.012-.027-.02-.017-.011-.013-.012-.013-.009-.037-.037-.01-.009-.006-.007-.008-.009-.042-.054-.007-.01a.64.64 0 0 1-.046-.083l-.013-.035-.018-.047-.004-.013-.008-.035-.008-.041-.002-.012-.001-.012-.002-.042-.002-.026v-2.917c0-.345.28-.625.625-.625s.625.28.625.625v1.614l.044-.04c1.235-1.211 1.986-2.859 2.054-4.639l.005-.268c0-3.797-3.078-6.875-6.875-6.875a6.9 6.9 0 0 0-1.528.17c-.337.076-.671-.135-.748-.471s.135-.671.471-.748a8.15 8.15 0 0 1 1.805-.201z",
|
||||
"eye-hide":
|
||||
"M2.94 2.063l15 15c.244.244.244.64 0 .884s-.64.244-.884 0l-2.768-2.767c-1.358.826-2.793 1.283-4.29 1.283-3.415 0-6.275-2.233-8.462-5.3-.395-.554-.496-.748-.496-1.159s.101-.604.496-1.159c.865-1.213 1.911-2.365 3.124-3.296L2.057 2.947c-.244-.244-.244-.64 0-.884s.64-.244.884 0zm-.387 7.509c-.238.334-.264.383-.264.433s.026.099.264.433c1.974 2.768 4.545 4.775 7.444 4.775 1.157 0 2.285-.332 3.378-.947l-1.686-1.685c-.507.353-1.114.549-1.751.549-1.693 0-3.066-1.373-3.066-3.066 0-.637.196-1.245.549-1.752l-1.87-1.87c-1.158.864-2.17 1.967-2.999 3.129zm7.444-6.025c3.415 0 6.275 2.232 8.462 5.3.395.554.496.748.496 1.159s-.101.604-.496 1.159c-.518.726-1.127 1.461-1.823 2.151-.245.243-.641.242-.884-.003s-.242-.641.003-.884a15.49 15.49 0 0 0 1.686-1.989c.238-.334.264-.383.264-.433s-.026-.099-.264-.433c-1.974-2.768-4.545-4.775-7.445-4.775-.661 0-1.314.109-1.958.318-.328.107-.681-.073-.788-.401s.073-.681.401-.788c.766-.249 1.549-.379 2.345-.379zm-1.875 6.518c0 1.003.813 1.816 1.816 1.816a1.81 1.81 0 0 0 .843-.207L8.33 9.221a1.81 1.81 0 0 0-.207.843z",
|
||||
flash: "M9.691 1.575c.841-1.08 2.429-.403 2.429.943v5.794c0 .138.074.221.124.221h2.837c1.194 0 1.785 1.477 1.055 2.414l-5.832 7.486c-.841 1.08-2.429.403-2.429-.943v-5.794c0-.138-.074-.221-.124-.221H4.915c-1.194 0-1.785-1.477-1.055-2.414l5.832-7.486zm1.179.943c0-.214-.122-.266-.193-.175L4.845 9.829c-.122.156-.026.396.069.396h2.837c.777 0 1.374.674 1.374 1.471v5.794c0 .214.122.266.193.175l5.832-7.486c.122-.156.026-.396-.069-.396h-2.837c-.777 0-1.374-.674-1.374-1.471V2.518z",
|
||||
folder: "M16.971 2.199C18 3.229 18.13 4.194 18.13 8.332v3.333c0 4.137-.13 5.103-1.159 6.132-1.001 1.001-1.941 1.152-5.795 1.159H8.834c-3.854-.008-4.794-.158-5.795-1.159s-1.151-1.941-1.159-5.795V8.332c0-4.137.13-5.103 1.159-6.132C4.04 1.198 4.981 1.048 8.834 1.04h2.004c4.137 0 5.103.13 6.132 1.159zm-.091 8.424H3.13v1.363c.007 3.448.134 4.269.793 4.928s1.479.786 4.928.793h2.308c3.448-.007 4.269-.134 4.928-.793.679-.679.793-1.529.793-5.248v-1.042zm-4.375 2.917c.345 0 .625.28.625.625s-.28.625-.625.625h-5c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h5zM11.159 2.29H8.851c-3.448.007-4.269.134-4.928.793s-.786 1.479-.793 4.928v1.362h13.75V8.332c0-3.719-.114-4.569-.793-5.248-.639-.639-1.43-.778-4.621-.792l-.306-.001zm1.346 2.916c.345 0 .625.28.625.625s-.28.625-.625.625h-5c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h5z",
|
||||
folders:
|
||||
"M5.865 2a2.31 2.31 0 0 1 1.786.841l1.328 1.621 4.61.001c1.294.004 1.692.04 2.143.249l.085.041a2.69 2.69 0 0 1 1.185 1.165c.25.483.291.84.295 2.192l.001.598c.685.132 1.022.381 1.344.846.618.894.46 1.545-.688 4.355l-.249.609c-.821 2.011-1.078 2.482-1.787 2.952s-1.25.528-3.46.528H5.435c-2.832-.007-3.482-.127-4.079-.99-.303-.439-.42-.819-.324-1.425l.001-9.491c.003-1.376.039-1.741.253-2.231.316-.725.903-1.302 1.64-1.613.5-.211.869-.246 2.281-.249h.657zm8.398 7.795H7.541c-1.91 0-2.353.048-2.761.318s-.617.654-1.326 2.391l-.249.609c-.934 2.288-1.068 2.837-.814 3.205s.827.452 3.345.452h6.975c1.699-.004 2.12-.06 2.509-.318.407-.27.617-.654 1.326-2.391l.249-.609c.934-2.288 1.068-2.837.814-3.205s-.827-.452-3.345-.452zM5.865 3.231h-.648c-1.203.003-1.514.03-1.796.149a1.86 1.86 0 0 0-.984.968c-.121.278-.149.588-.152 1.78l-.001 5.938.009-.021c.821-2.011 1.078-2.482 1.787-2.952.679-.451 1.205-.523 3.192-.528h7.292l1.483.024v-.229c0-1.312-.026-1.626-.159-1.883a1.45 1.45 0 0 0-.638-.628c-.246-.123-.543-.153-1.689-.156H5.83a.62.62 0 0 1-.626-.615.62.62 0 0 1 .626-.615h1.542l-.694-.848c-.17-.207-.413-.34-.678-.374l-.134-.008z",
|
||||
gift: "M6.835 1c1.325 0 2.49.695 3.165 1.748C10.674 1.695 11.84 1 13.165 1h.293c1.149 0 2.081.95 2.081 2.123 0 .78-.264 1.497-.705 2.064l.5-.001c1.076 0 1.325.018 1.694.192a1.76 1.76 0 0 1 .691.57c.255.361.281.596.281 1.54s-.026 1.179-.281 1.539a1.73 1.73 0 0 1-.539.49v2.994c0 3.663-.113 4.519-1.021 5.446S14.411 19 10.821 19H9.179c-3.59 0-4.429-.115-5.338-1.042-.881-.899-1.014-1.731-1.021-5.121l-.001-3.32-.01-.006a1.73 1.73 0 0 1-.528-.484C2.044 8.693 2.005 8.466 2 7.68v-.192c0-.943.026-1.179.281-1.54a1.76 1.76 0 0 1 .691-.57c.345-.162.585-.189 1.49-.192l.705.001c-.442-.567-.705-1.284-.705-2.064C4.462 1.95 5.393 1 6.542 1h.293zM4.05 9.786l.002 2.997c.006 3.014.113 3.728.661 4.286.563.575 1.289.674 4.467.674h.205V9.79H4.462l-.412-.004zm11.9 0l-.412.004h-4.923v7.954h.206c3.179 0 3.904-.099 4.467-.674.545-.556.654-1.267.661-4.252l.002-3.032zm-.617-3.344h.16H4.507c-.709.002-.896.019-1.018.077-.094.044-.165.103-.21.165-.033.047-.049.183-.049.805v.135c.002.507.017.626.048.67.044.063.116.121.21.165.121.057.307.074 1.007.076h10.837c.841 0 1.047-.015 1.178-.077.094-.044.165-.103.209-.165.033-.047.049-.183.049-.805s-.015-.757-.049-.805c-.044-.062-.116-.121-.209-.165-.131-.062-.336-.077-1.178-.077zM6.835 2.256h-.293c-.469 0-.85.388-.85.867 0 1.139.905 2.063 2.022 2.063h1.67l-.001-.338C9.385 3.47 8.321 2.336 6.98 2.26l-.145-.004zm6.623 0h-.293c-1.408 0-2.549 1.165-2.549 2.601v.329h1.67c1.072 0 1.949-.851 2.018-1.927l.004-.136c0-.479-.38-.867-.85-.867z",
|
||||
history:
|
||||
"M9.998 1.04a8.96 8.96 0 0 1 8.958 8.958 8.96 8.96 0 0 1-8.958 8.958c-.345 0-.625-.28-.625-.625s.28-.625.625-.625a7.71 7.71 0 0 0 7.708-7.708A7.71 7.71 0 0 0 9.998 2.29c-3.018 0-5.678 1.751-6.929 4.396l-.085.187h1.181c.314 0 .574.231.618.533l.007.092c0 .345-.28.625-.625.625H2.081c-.422 0-.723-.41-.596-.812C2.65 3.601 6.063 1.04 9.998 1.04zM6.925 17.436a7.41 7.41 0 0 0 .769.301c.328.108.506.461.399.789s-.461.506-.789.399a8.66 8.66 0 0 1-.898-.352c-.314-.144-.452-.514-.308-.828s.514-.452.828-.308zm-2.443-1.775c.236.254.488.493.754.713s.303.614.083.88-.614.303-.88.083c-.308-.255-.6-.531-.873-.825-.235-.253-.22-.648.033-.883s.648-.22.883.033zm-1.653-2.679a8.27 8.27 0 0 0 .399.894c.159.306.039.684-.267.843s-.684.039-.843-.267a9.52 9.52 0 0 1-.459-1.029c-.122-.323.042-.684.365-.805s.684.042.805.365zM9.998 6.04c.345 0 .625.28.625.625V9.74l1.484 1.483c.217.217.241.554.072.797l-.072.087c-.244.244-.64.244-.884 0L9.556 10.44c-.117-.117-.183-.276-.183-.442V6.665c0-.345.28-.625.625-.625zM1.665 9.373c.345 0 .625.28.625.625 0 .261.012.52.035.777.031.344-.222.648-.566.679s-.648-.222-.679-.566c-.027-.294-.04-.591-.04-.89 0-.345.28-.625.625-.625z",
|
||||
"help-circle":
|
||||
"M10 1a9 9 0 1 1 0 18 9 9 0 1 1 0-18zm0 1.256c-4.277 0-7.744 3.467-7.744 7.744S5.723 17.744 10 17.744s7.744-3.467 7.744-7.744S14.277 2.256 10 2.256zm.001 11.093c.462 0 .837.375.837.837s-.375.837-.837.837a.84.84 0 0 1-.845-.837c0-.462.375-.837.837-.837zM10 5.186c1.272 0 2.302 1.031 2.302 2.302 0 .447-.128.876-.365 1.245a5.9 5.9 0 0 1-.307.428l-.277.346c-.543.673-.726.993-.726 1.33v.419a.63.63 0 0 1-.628.628.63.63 0 0 1-.628-.628v-.419c0-.731.279-1.221 1.005-2.119l.262-.327a4.71 4.71 0 0 0 .243-.337 1.04 1.04 0 0 0 .165-.565c0-.578-.469-1.047-1.047-1.047s-1.047.469-1.047 1.047a.63.63 0 0 1-.628.628.63.63 0 0 1-.628-.628c0-1.272 1.031-2.302 2.302-2.302z",
|
||||
envelope:
|
||||
"M12.445 2.53c3.479.085 4.336.229 5.33 1.196.973.946 1.139 1.817 1.207 4.852l.001.063.002.087.001.064v2.419l-.001.064-.002.087-.001.063c-.068 3.035-.234 3.906-1.207 4.852s-1.893 1.11-5.058 1.189l-.272.007c-1.635.04-3.254.04-4.889 0l-.272-.007c-3.165-.078-4.088-.246-5.058-1.189s-1.139-1.817-1.207-4.852l-.001-.063-.002-.086-.001-.064V8.791c.072-3.283.219-4.1 1.212-5.065s1.851-1.111 5.33-1.196h4.889zm5.154 3.728L12.894 8.84c-2.326 1.276-3.462 1.276-5.788 0L2.402 6.258c-.073.588-.107 1.394-.133 2.558v2.367l.001.064.002.086.001.062c.06 2.7.192 3.389.841 4.02s1.383.762 4.2.831l.272.007h4.826l.272-.007c2.817-.07 3.555-.204 4.2-.831s.781-1.32.841-4.02l.001-.063.002-.086.001-.064V8.817l-.001-.064-.002-.086-.001-.063-.128-2.346zM7.587 3.746c-3.11.076-3.809.193-4.472.838a2.12 2.12 0 0 0-.372.465l4.982 2.734c1.942 1.065 2.608 1.065 4.55 0l4.98-2.733c-.1-.174-.221-.321-.37-.465-.663-.645-1.362-.762-4.472-.838a98.85 98.85 0 0 0-4.826 0z",
|
||||
eye: "M10 2.5c3.235 0 6.246 1.833 8.323 5.008.903 1.376.903 3.607.001 4.983C16.246 15.667 13.235 17.5 10 17.5s-6.246-1.833-8.323-5.008c-.903-1.376-.903-3.607-.001-4.983C3.754 4.333 6.765 2.5 10 2.5zm0 1.247c-2.767 0-5.387 1.595-7.243 4.432-.635.967-.635 2.675.001 3.643 1.855 2.836 4.475 4.431 7.242 4.431s5.387-1.595 7.242-4.432c.635-.967.635-2.675-.001-3.643C15.387 5.342 12.767 3.747 10 3.747zm.001 2.659c2.045 0 3.699 1.609 3.699 3.598s-1.654 3.598-3.699 3.598-3.699-1.609-3.699-3.598 1.654-3.598 3.699-3.598zm0 1.247c-1.338 0-2.418 1.051-2.418 2.352s1.08 2.352 2.418 2.352 2.418-1.051 2.418-2.352-1.08-2.352-2.418-2.352z",
|
||||
image: "M17.201 2.802c1.161 1.161 1.334 2.27 1.342 6.849v.7c-.008 4.579-.181 5.688-1.342 6.849s-2.27 1.334-6.849 1.342h-.7c-4.579-.008-5.688-.181-6.849-1.342s-1.334-2.27-1.342-6.849v-.35c0-4.874.153-6.009 1.342-7.199 1.161-1.161 2.27-1.334 6.849-1.342h.35c4.874 0 6.009.153 7.199 1.342zM3.347 12.296c-.206 0-.411.004-.616.015.063 2.553.286 3.338.955 4.007.818.818 1.807.969 5.979.976h.672l1.929-.02c-.591-1.218-1.524-2.301-2.727-3.148-1.739-1.223-3.93-1.873-6.192-1.829zm11.974 1.664c-1.064-.004-2.126.295-3.152.89a8.99 8.99 0 0 1 1.441 2.365c1.554-.109 2.168-.358 2.707-.898.456-.456.705-.966.837-2.052a5.67 5.67 0 0 0-1.833-.305zM10.338 2.71h-.672c-4.172.007-5.162.158-5.979.976-.839.839-.976 1.859-.976 6.315v.336l.003.722-.253.014.875-.028c2.511-.049 4.963.678 6.923 2.057.363.255.705.53 1.025.823 1.288-.806 2.655-1.22 4.04-1.215.647-.001 1.292.091 1.927.274l.044-2.646v-.672c-.007-4.172-.158-5.162-.976-5.979-.796-.796-1.755-.96-5.657-.975l-.323-.001zm3.414 1.666c1.036 0 1.875.839 1.875 1.875s-.839 1.875-1.875 1.875-1.875-.839-1.875-1.875.839-1.875 1.875-1.875zm0 1.25c-.345 0-.625.28-.625.625s.28.625.625.625.625-.28.625-.625-.28-.625-.625-.625z",
|
||||
"image-1":
|
||||
"M18.268 2.336c.672.526.732 1.056.732 3.865v7.598c0 2.809-.06 3.339-.732 3.865-.696.546-1.248.447-4.323-.442a14.23 14.23 0 0 0-7.89 0c-3.076.889-3.627.988-4.323.442-.627-.491-.721-.985-.731-3.333L1 5.919c.005-2.563.083-3.074.732-3.582.696-.546 1.247-.447 4.323.442a14.23 14.23 0 0 0 7.89 0c3.076-.889 3.627-.987 4.323-.442zm-15.75.956c-.198.155-.262.722-.262 2.909v7.598c0 2.187.064 2.754.262 2.909.165.129.771.028 2.86-.569l-.021-.021 1.242-1.289c4.195-4.328 7.214-5.809 11.145-3.864l-.001-5.017c-.005-1.977-.072-2.505-.262-2.654-.173-.135-.832-.018-3.181.661-2.806.811-5.797.811-8.603 0-2.349-.679-3.008-.797-3.181-.661zm5.03 12.341l.398-.059a15.52 15.52 0 0 1 6.356.472c2.349.679 3.008.797 3.181.661.198-.155.262-.722.262-2.909v-1.438c-3.577-2.042-6.163-.879-10.196 3.273zM6.23 5.3c1.04 0 1.884.823 1.884 1.839S7.27 8.978 6.23 8.978s-1.884-.823-1.884-1.839S5.189 5.3 6.23 5.3zm0 1.226a.62.62 0 0 0-.628.613.62.62 0 0 0 .628.613.62.62 0 0 0 .628-.613.62.62 0 0 0-.628-.613z",
|
||||
language:
|
||||
"M17.201 2.802c1.161 1.161 1.334 2.27 1.342 6.849v.7c-.008 4.579-.181 5.688-1.342 6.849s-2.27 1.334-6.849 1.342h-.7c-4.579-.008-5.688-.181-6.849-1.342s-1.334-2.27-1.342-6.849v-.35c0-4.874.153-6.009 1.342-7.199 1.161-1.161 2.27-1.334 6.849-1.342h.35c4.874 0 6.009.153 7.199 1.342zm-6.863-.092h-.672c-4.172.007-5.162.158-5.979.976-.839.839-.976 1.859-.976 6.315v.336c.007 4.172.158 5.162.976 5.979s1.807.969 5.979.976h.672c4.172-.007 5.162-.158 5.979-.976s.969-1.807.976-5.979v-.672c-.007-4.172-.158-5.162-.976-5.979-.796-.796-1.755-.96-5.657-.975l-.323-.001zm-.753 2.5c.345 0 .625.28.625.625v.524h1.875 2.083c.345 0 .625.28.625.625s-.28.625-.625.625h-1.624l-.086.252c-.39 1.061-.984 2.119-1.756 3.175l-.202.269 1.232 1.281c.215.224.231.567.05.808l-.067.076c-.249.239-.644.232-.884-.017l-1.125-1.168-.257.296-1.595 1.641-.435.407c-.254.234-.649.217-.883-.037s-.217-.649.037-.883c.848-.779 1.609-1.556 2.284-2.352l.264-.32-.257.31-.108-.136c-.446-.57-.876-1.187-1.086-1.58l-.061-.122c-.146-.313-.01-.685.302-.831s.685-.01.831.302c.117.25.48.782.877 1.301l.044.056.022-.028c.629-.86 1.126-1.712 1.473-2.553l.057-.148H9.585h-3.75c-.345 0-.625-.28-.625-.625s.28-.625.625-.625H8.96v-.524c0-.314.231-.574.533-.618l.092-.007z",
|
||||
"language-1":
|
||||
"M11.623 1.5c3.539.366 6.07 2.646 7.005 5.283 1.116 5.32-.324 8.502-3.713 10.349-2.052 1.254-7.047 1.303-9.342.236l-.166-.084-3.35 1.174a.71.71 0 0 1-.926-.835l.034-.099L2.4 14.568l-.114-.184C-.911 9.087 2.177 2.136 7.97 1.596l.261-.02.022-.001 3.37-.075zm-.05 1.24l-3.277.078-.218.017C3.1 3.31.469 9.569 3.626 14.153l.191.278-.13.311-.896 2.139 2.468-.865.294-.103.26.17c1.605 1.046 6.655 1.082 8.469-.025 2.929-1.597 4.121-4.232 3.139-8.941-.76-2.132-2.91-4.067-5.848-4.376zm-.907 3.553l-.001.814h2.692v1.244h-.723l-.08.231c-.34.916-.849 1.828-1.505 2.738l-.187.252 1.055 1.104-.912.855-.935-.979-.282.323c-.388.432-.802.858-1.243 1.282l-.449.424-.857-.909c.728-.674 1.383-1.343 1.966-2.03l.266-.324-.242.293-.138-.178c-.363-.473-.704-.97-.884-1.302l-.067-.132 1.141-.519c.098.211.397.654.732 1.097l.012.017.033-.044c.482-.675.871-1.343 1.157-2.004l.079-.198H6.72V7.108h2.69l.001-.814h1.256z",
|
||||
link: "M15.037 2.46a4.85 4.85 0 0 1 0 6.855l-.032.033a4.85 4.85 0 0 1-.801 5.801l-2.388 2.388a4.85 4.85 0 0 1-6.855 0 4.85 4.85 0 0 1 0-6.855l.032-.033a4.85 4.85 0 0 1 .801-5.801L8.181 2.46a4.85 4.85 0 0 1 6.855 0zm-5.971.884L6.677 5.732a3.6 3.6 0 0 0 0 5.087 3.6 3.6 0 0 0 5.087 0l.172-.172c.244-.244.64-.244.884 0s.244.64 0 .884l-.172.172a4.85 4.85 0 0 1-6.855 0l-.041-.042-.053.058a3.6 3.6 0 0 0 5.233 4.934l2.389-2.389a3.6 3.6 0 0 0 0-5.087 3.6 3.6 0 0 0-5.087 0l-.172.172c-.244.244-.64.244-.884 0s-.244-.64 0-.884l.172-.172a4.85 4.85 0 0 1 6.855 0l.039.042.055-.058a3.6 3.6 0 0 0-.145-4.934 3.6 3.6 0 0 0-5.087 0z",
|
||||
"link-1":
|
||||
"M6.408 7.388c.244.244.244.64 0 .884l-2.175 2.175a3.77 3.77 0 0 0 0 5.329 3.77 3.77 0 0 0 5.329 0l2.175-2.174c.244-.244.64-.244.884 0s.244.64 0 .884l-2.175 2.174a5.02 5.02 0 0 1-7.097 0 5.02 5.02 0 0 1 0-7.097l2.175-2.175c.244-.244.64-.244.884 0zM16.66 3.35a5.02 5.02 0 0 1 0 7.097l-2.175 2.175c-.244.244-.64.244-.884 0s-.244-.64 0-.884l2.175-2.175a3.77 3.77 0 0 0 0-5.329 3.77 3.77 0 0 0-5.329 0L8.272 6.408c-.244.244-.64.244-.884 0s-.244-.64 0-.884L9.563 3.35a5.02 5.02 0 0 1 7.097 0zm-4.13 4.13c.244.244.244.64 0 .884L8.364 12.53c-.244.244-.64.244-.884 0s-.244-.64 0-.884l4.167-4.167c.244-.244.64-.244.884 0z",
|
||||
plus: "M10.002 2.71c.345 0 .625.28.625.625l-.001 6.041 6.042.001c.314 0 .574.231.618.533l.007.092c0 .345-.28.625-.625.625l-6.042-.001.001 6.042c0 .314-.231.574-.533.618l-.092.007c-.345 0-.625-.28-.625-.625l-.001-6.042-6.041.001c-.314 0-.574-.231-.618-.533l-.007-.092c0-.345.28-.625.625-.625l6.041-.001.001-6.041c0-.314.231-.574.533-.618l.092-.007z",
|
||||
profile:
|
||||
"M9.999 10.841c2.968 0 5.385 1.767 6.381 4.509.489 1.345-.587 2.65-1.998 2.65H5.618c-1.412 0-2.486-1.304-1.998-2.65.994-2.74 3.413-4.507 6.38-4.507h-.031l.031-.001zm.018 1.262l-.018.002c-2.441 0-4.401 1.432-5.217 3.682-.167.462.234.95.836.95h8.764c.601 0 1.003-.488.836-.948-.818-2.253-2.777-3.684-5.219-3.684h.018zM10 2c.986 0 1.932.399 2.629 1.11s1.089 1.675 1.089 2.68a3.85 3.85 0 0 1-.283 1.45c-.187.46-.461.878-.806 1.229s-.755.631-1.206.821a3.66 3.66 0 0 1-2.846 0c-.451-.19-.861-.47-1.206-.821s-.619-.77-.806-1.229a3.85 3.85 0 0 1-.283-1.45c0-1.005.392-1.969 1.089-2.68S9.013 2 10 2zm0 1.263c-.658 0-1.288.266-1.753.74a2.55 2.55 0 0 0-.726 1.786 2.57 2.57 0 0 0 .189.967 2.53 2.53 0 0 0 .537.82c.23.235.504.421.804.548a2.44 2.44 0 0 0 1.897 0c.301-.127.574-.313.804-.548a2.53 2.53 0 0 0 .537-.82c.125-.306.189-.635.189-.967a2.55 2.55 0 0 0-.726-1.786c-.465-.474-1.095-.74-1.753-.74z",
|
||||
python: "M12.529 2.266a2.29 2.29 0 0 1 .632.632c.347.52.386.903.386 2.523v1.041l1.287.001c1.336.004 1.741.051 2.196.334l.081.052a2.29 2.29 0 0 1 .632.632c.329.492.381.862.386 2.277v.491c-.005 1.415-.057 1.785-.386 2.277a2.29 2.29 0 0 1-.632.632c-.492.329-.863.381-2.278.386h-1.287v1.042c0 1.535-.035 1.96-.334 2.442l-.052.081a2.29 2.29 0 0 1-.632.632c-.52.347-.903.386-2.523.386s-2.004-.039-2.523-.386a2.29 2.29 0 0 1-.632-.632c-.329-.492-.381-.862-.386-2.277v-1.288H5.176c-1.336-.004-1.741-.051-2.196-.334l-.081-.052a2.29 2.29 0 0 1-.632-.632c-.329-.492-.381-.862-.386-2.277v-.246c0-1.62.039-2.004.386-2.523a2.29 2.29 0 0 1 .632-.632c.492-.329.862-.381 2.277-.386l1.288-.001V5.176c.004-1.336.051-1.741.334-2.196l.052-.081a2.29 2.29 0 0 1 .632-.632c.492-.329.862-.381 2.277-.386h.246c1.62 0 2.004.039 2.523.386zM7.714 14.809c.004 1.121.039 1.405.175 1.608a1.04 1.04 0 0 0 .287.287c.216.144.523.176 1.829.176s1.613-.031 1.829-.176a1.04 1.04 0 0 0 .287-.288c.136-.203.171-.487.175-1.608v-1.263l-2.29.001c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h4.802c1.122-.004 1.405-.039 1.609-.175a1.04 1.04 0 0 0 .287-.287c.136-.203.171-.487.175-1.608v-.441c-.004-1.122-.039-1.405-.175-1.608a1.04 1.04 0 0 0-.287-.287c-.203-.136-.487-.172-1.608-.175l-1.261-.001v2.292c0 .345-.28.625-.625.625l-5.208-.001-.001 4.179zm3.126-.02c.345 0 .625.28.625.625 0 .353-.28.633-.625.633s-.625-.28-.625-.625c0-.353.28-.633.625-.633zM5.201 7.714c-1.121.004-1.405.039-1.608.175a1.04 1.04 0 0 0-.287.287c-.136.203-.171.487-.175 1.608v.441c.004 1.121.039 1.405.175 1.608a1.04 1.04 0 0 0 .287.287c.203.136.487.172 1.608.175h1.263l.001-2.291c0-.345.28-.625.625-.625l5.208-.001V7.102v-1.9c-.004-1.121-.039-1.405-.175-1.608a1.04 1.04 0 0 0-.287-.287c-.191-.127-.452-.167-1.408-.174l-.201-.001h-.441c-1.122.004-1.405.039-1.608.175a1.04 1.04 0 0 0-.287.287c-.136.203-.171.487-.175 1.608v1.262h2.293c.345 0 .625.28.625.625s-.28.625-.625.625H5.201zm3.973-3.751c.345 0 .625.28.625.625 0 .354-.28.633-.625.633s-.625-.28-.625-.625c0-.354.28-.633.625-.633z",
|
||||
rocket: "M2.974 13.902a2.39 2.39 0 0 1 2.604.517 2.39 2.39 0 0 1 .518 2.604A2.39 2.39 0 0 1 3.889 18.5H2.99a1.49 1.49 0 0 1-1.49-1.49v-.899a2.39 2.39 0 0 1 1.474-2.208zM16.987 1.505c.202-.017.406.011.596.08s.364.18.507.323.254.316.324.507a1.39 1.39 0 0 1 .081.594c-.242 3.064-1.703 5.603-4.43 8.102l.206-.193.001 2.952a2.34 2.34 0 0 1-.242 1.037l-.086.158a2.34 2.34 0 0 1-.892.861l-2.536 1.383a1.49 1.49 0 0 1-1.474-.026 1.49 1.49 0 0 1-.73-1.281l-.001-1.377-2.937-2.937H4a1.49 1.49 0 0 1-.6-.126l-.138-.069a1.49 1.49 0 0 1-.753-1.269 1.49 1.49 0 0 1 .182-.74l1.382-2.538A2.34 2.34 0 0 1 6.13 5.726h2.951l.066-.07c2.33-2.457 4.71-3.819 7.526-4.122l.315-.029zM4.106 15.019a1.11 1.11 0 0 0-1.142.473 1.11 1.11 0 0 0-.187.618v.899c0 .056.022.111.062.151s.094.062.15.062h.899c.219 0 .434-.066.618-.188a1.11 1.11 0 0 0 .473-1.142 1.11 1.11 0 0 0-.874-.874zm8.889-3.056l-3.406 2.705v1.332c0 .025.004.049.013.072l.015.033c.018.032.044.059.076.078s.068.029.105.03.073-.008.106-.026l2.536-1.383c.168-.092.308-.227.406-.391s.149-.352.149-.543l-.001-1.907zm4.096-9.185c-2.705.213-4.963 1.513-7.261 4.019l.017-.02-3.353 4.223 2.506 2.506 4.223-3.355.244-.227c2.247-2.131 3.458-4.243 3.729-6.729l.027-.288c.001-.017-.001-.034-.007-.051s-.015-.031-.028-.043-.027-.022-.043-.027-.034-.008-.054-.007zM5.33 10.41l2.704-3.406H6.129c-.153 0-.304.033-.442.096l-.101.053c-.165.097-.3.238-.391.405l-1.383 2.538c-.018.033-.027.069-.026.106s.011.073.03.105.046.058.078.076.069.028.106.028H5.33z",
|
||||
search: "M9.165 1.04c4.487 0 8.125 3.638 8.125 8.125 0 2.019-.736 3.865-1.955 5.286l3.438 3.439c.244.244.244.64 0 .884s-.64.244-.884 0l-3.438-3.439c-1.421 1.219-3.268 1.955-5.287 1.955-4.487 0-8.125-3.638-8.125-8.125S4.678 1.04 9.165 1.04zm0 1.25c-3.797 0-6.875 3.078-6.875 6.875s3.078 6.875 6.875 6.875 6.875-3.078 6.875-6.875S12.962 2.29 9.165 2.29z",
|
||||
security:
|
||||
"M9.992 1.04c1.421 0 2.442.379 4.181 1.335l.381.21.372.201c.518.274.92.454 1.312.579 1.162.371 1.351.445 1.605.727.197.219.29.458.371.847l.077.407c1.081 5.993-1.442 11.226-6.73 13.251-.76.291-1.023.36-1.566.36s-.806-.069-1.566-.36C3.14 16.572.615 11.338 1.696 5.346c.141-.783.196-.973.448-1.253s.443-.356 1.605-.727c.393-.125.795-.306 1.313-.58l.371-.2.38-.209C7.55 1.419 8.571 1.04 9.992 1.04zm0 1.25c-1.153 0-2.011.319-3.577 1.181l-.382.21-.387.209c-.578.306-1.042.515-1.518.666-.792.253-1.033.347-1.056.372s-.056.138-.147.639c-.979 5.431 1.256 10.064 5.95 11.862.627.24.769.277 1.119.277s.492-.037 1.119-.277c4.693-1.797 6.927-6.43 5.947-11.861l-.07-.373c-.04-.19-.064-.252-.076-.266-.023-.025-.264-.12-1.056-.372-.475-.151-.939-.36-1.516-.665l-.388-.21-.383-.211c-1.567-.862-2.426-1.181-3.579-1.181zm.002 2.917c2.646 0 4.792 2.145 4.792 4.792S12.64 14.79 9.994 14.79s-4.792-2.145-4.792-4.792 2.145-4.792 4.792-4.792zm0 1.25c-1.956 0-3.542 1.586-3.542 3.542s1.586 3.542 3.542 3.542 3.542-1.586 3.542-3.542-1.586-3.542-3.542-3.542zm2.256 2.083c.115.325-.055.683-.38.798-.073.026-.155.066-.244.118-.305.183-.657.503-1.022.919a10.85 10.85 0 0 0-.66.836 8.85 8.85 0 0 0-.255.373c-.261.41-.869.379-1.087-.056-.136-.272-.261-.422-.361-.489-.012-.008.018.001.086.001-.345 0-.625-.28-.625-.625s.28-.625.625-.625c.259 0 .541.114.813.366l.015.015.252-.318.257-.304c.444-.505.883-.905 1.32-1.167.156-.093.312-.169.468-.224.325-.115.683.055.798.38z",
|
||||
settings:
|
||||
"M13.744 1.945l1.437.816c.559.318.667.394.796.699.132.312.113.42-.089 1.197-.331 1.276.48 2.641 1.781 2.992.76.205.866.243 1.071.511.183.239.211.37.215.872v1.936c-.004.502-.031.633-.214.871-.126.165-.285.262-.499.342-.13.049-.237.08-.573.17-1.301.351-2.111 1.716-1.78 2.992.201.775.22.885.089 1.197-.129.305-.237.382-.796.7l-1.437.816c-.55.312-.671.365-.996.321-.333-.045-.419-.117-.969-.666-.973-.971-2.591-.971-3.564 0-.55.549-.636.621-.968.666-.326.044-.447-.01-.996-.321l-1.437-.816c-.559-.317-.667-.394-.796-.7-.132-.312-.113-.42.089-1.197.331-1.276-.48-2.641-1.781-2.992l-.573-.17c-.214-.08-.373-.176-.499-.341-.183-.239-.211-.369-.214-.871V9.194c0-.639.014-.771.215-1.034.205-.268.311-.306 1.072-.511 1.302-.351 2.113-1.716 1.782-2.992-.202-.777-.22-.885-.089-1.197.129-.305.237-.382.796-.699l1.437-.816c.55-.312.671-.365.997-.321.332.045.418.117.968.666.972.97 2.589.97 3.561 0 .551-.549.636-.621.968-.666.326-.044.447.009.996.321zm-.824.968l-.026.031-.158.158-.074.073c-1.46 1.456-3.867 1.456-5.327 0l-.231-.231-.027-.031-.018.012-.188.107-1.437.816-.193.109-.022.01.015.046.036.136.023.09.027.104c.505 1.945-.708 3.985-2.667 4.513l-.321.087-.043.008.002.024V9v1.968.057l-.002.017.027.008.225.063.112.03c1.958.528 3.171 2.568 2.665 4.513l-.085.33-.015.045.022.011.114.064.079.045 1.437.816.188.107.017.011.028-.03.158-.158.074-.073c1.461-1.458 3.869-1.458 5.33 0l.074.073.158.158.026.03.02-.011.111-.063.077-.044 1.437-.816.193-.109.021-.011-.014-.044-.059-.226-.027-.104c-.506-1.945.706-3.985 2.664-4.513l.337-.094.025-.008v-.017-2.05l.001-.023-.042-.009-.219-.059-.102-.028c-1.958-.528-3.171-2.568-2.665-4.513l.049-.194.036-.136.014-.046-.021-.01-.114-.064-.079-.045-1.437-.816-.188-.107-.019-.012zM9.998 6.458c1.956 0 3.542 1.586 3.542 3.542s-1.586 3.542-3.542 3.542-3.542-1.586-3.542-3.542 1.586-3.542 3.542-3.542zm0 1.25a2.29 2.29 0 1 0 0 4.583 2.29 2.29 0 1 0 0-4.583z",
|
||||
share: "M8.804 1.46c.345-.001.626.279.626.624s-.279.626-.624.626c-3.639.007-4.745.185-5.538.976-.819.818-.971 1.807-.978 5.979v.672c.007 4.172.159 5.161.978 5.979s1.812.969 5.993.977h.674c4.181-.007 5.173-.158 5.993-.976.619-.618.871-1.533.946-3.423.014-.345.304-.613.649-.6s.613.304.6.649c-.086 2.178-.412 3.36-1.312 4.258-1.163 1.16-2.274 1.334-6.862 1.342h-.701c-4.588-.008-5.699-.181-6.862-1.342s-1.337-2.27-1.345-6.85v-.35c0-4.874.153-6.01 1.345-7.2C3.514 1.675 4.799 1.467 8.804 1.46zm4.97 1.667l.15.014c.338.05.63.212.998.508l1.024.893 1.456 1.264c1.062.922 1.306 1.171 1.475 1.649a1.37 1.37 0 0 1 0 .92c-.169.477-.413.727-1.475 1.649l-1.456 1.264-.878.792c-.32.282-.55.444-.817.542a1.41 1.41 0 0 1-.925.019c-.692-.211-.931-.82-.953-1.662l.001-.299.001-.058-.024-.001-.314-.007-.188-.005-.868-.018c-1.099-.013-1.881.042-2.593.21-.784.185-1.407.5-2.602 1.242l-.446.276c-.431.264-.967-.035-.967-.524 0-3.494 1.675-5.918 5.228-6.495.594-.097 1.199-.126 2.023-.119l.605.009.146.003-.001-.043-.003-.151.002-.148c.022-.842.261-1.451.953-1.662.099-.03.199-.049.298-.057l.15-.003zm-.033 1.25c-.014-.002-.026-.001-.051.006-.002.001-.059.145-.068.499a5.89 5.89 0 0 0 .016.538l.02.404c0 .345-.28.625-.625.625-.23 0-.411-.003-.827-.01l-.593-.009c-.759-.007-1.302.02-1.811.103-2.452.399-3.752 1.802-4.089 4.005l-.013.092.192-.113c.779-.452 1.346-.708 2.007-.884l.201-.051c.831-.197 1.704-.258 2.895-.244l.886.019 1.151.02c.345 0 .625.28.625.625 0 .093.001.075-.02.404l-.016.538c.009.354.066.499.068.499.062.019.089.018.128.004.085-.031.211-.12.424-.307l.885-.798 1.456-1.264c.832-.723 1.055-.95 1.116-1.121.006-.017.008-.03.008-.044s-.002-.026-.008-.044c-.06-.171-.283-.398-1.116-1.121l-1.456-1.264-1.385-1.108z",
|
||||
"share-1":
|
||||
"M9.259 2c.34-.001.616.274.616.614s-.274.616-.614.616c-3.377.006-4.401.172-5.13.901-.774.774-.901 1.722-.901 5.868v.379c.008 3.826.151 4.739.901 5.489.774.774 1.722.901 5.867.901h.379c3.825-.008 4.738-.151 5.488-.901.729-.729.895-1.753.901-5.131.001-.34.277-.615.616-.614s.615.277.614.617c-.007 3.738-.201 4.939-1.261 5.999C15.618 17.857 14.556 18 9.999 18h-.405c-4.216-.009-5.248-.176-6.333-1.261-1.09-1.09-1.254-2.127-1.261-6.395V10c0-4.557.143-5.619 1.261-6.738C4.321 2.201 5.522 2.007 9.259 2zm5.999.073c1.178.059 1.853.171 2.197.515.317.317.437.917.499 1.935l.015.263.025 1.963c-.005.34-.284.611-.624.607s-.611-.284-.607-.624l.003-.238v-.477l-.057-1.718-.006-.086-7.048 7.09c-.213.214-.545.239-.785.073l-.085-.071c-.241-.24-.242-.629-.003-.87l7.055-7.096-.093-.006-1.715-.057h-.477l-.237.003c-.34.005-.619-.267-.624-.607s.267-.619.607-.624l1.96.025z",
|
||||
team: "M13.659 12.12l.097.058.856.527c.639.423 1.086.831 1.339 1.317.372.713.235 1.476-.423 2.133-.878.877-1.77 1.345-2.826 1.345H7.297c-1.055 0-1.947-.468-2.826-1.345-.658-.657-.795-1.42-.423-2.133.253-.486.7-.894 1.339-1.317l.477-.298.21-.127.266-.159a6.91 6.91 0 0 1 7.319 0zM7.01 13.214c.016-.01-.703.419-.925.566-.473.313-.783.596-.91.84-.104.2-.077.352.192.621.661.66 1.258.973 1.93.973h5.407c.672 0 1.269-.313 1.93-.973.269-.269.296-.42.192-.621-.127-.244-.437-.527-.91-.84l-.925-.566c-1.829-1.142-4.15-1.142-5.979 0zm8.895-2.998l.094.002c.802.073 1.576.386 2.254.913-.03-.023.471.349.645.493 1.083.893 1.5 1.887.64 2.956-.625.778-1.282 1.207-2.091 1.207a.64.64 0 1 1 0-1.286c.351 0 .694-.224 1.102-.732.28-.348.155-.646-.457-1.15l-.617-.47a3.04 3.04 0 0 0-1.592-.651.64.64 0 0 1-.577-.698.64.64 0 0 1 .597-.584zm-11.214.584a.64.64 0 0 1-.577.698 3.04 3.04 0 0 0-1.592.651 26.62 26.62 0 0 0-.617.47c-.612.504-.736.802-.457 1.15.408.507.751.732 1.102.732a.64.64 0 1 1 0 1.286c-.809 0-1.465-.429-2.091-1.207-.859-1.069-.443-2.063.64-2.956l.645-.493c.678-.528 1.452-.84 2.254-.913a.64.64 0 0 1 .691.582zm10.402-6.585c1.524 0 2.759 1.247 2.759 2.786s-1.235 2.786-2.759 2.786a.64.64 0 1 1 0-1.286c.82 0 1.486-.672 1.486-1.5s-.665-1.5-1.486-1.5a.64.64 0 0 1-.637-.643.64.64 0 0 1 .637-.643zm-10.611 0a.64.64 0 0 1 .637.643.64.64 0 0 1-.637.643c-.82 0-1.486.672-1.486 1.5s.665 1.5 1.486 1.5a.64.64 0 1 1 0 1.286C2.958 9.786 1.723 8.539 1.723 7s1.235-2.786 2.759-2.786zM10 2.5c1.993 0 3.608 1.631 3.608 3.643S11.993 9.786 10 9.786 6.392 8.155 6.392 6.143 8.007 2.5 10 2.5zm0 1.286c-1.289 0-2.335 1.055-2.335 2.357S8.711 8.5 10 8.5s2.335-1.055 2.335-2.357S11.289 3.786 10 3.786z",
|
||||
template:
|
||||
"M16.134 2.199c1.03 1.03 1.159 1.995 1.159 6.132v2.786c0 .948-.018 1.191-.174 1.567-.145.35-.292.534-.849 1.095l-4.219 4.219c-.469.465-.627.594-.918.733a2.31 2.31 0 0 1-.226.094c-.303.107-.505.128-1.167.13h-.518c-3.287-.006-4.102-.122-5.038-.877-.22-.177-.42-.377-.597-.597-.755-.936-.87-1.751-.877-5.038V8.332c0-4.137.13-5.103 1.159-6.132C4.87 1.198 5.811 1.048 9.664 1.04h.338c4.137 0 5.103.13 6.132 1.159zm-5.811.091h-.642c-3.448.007-4.269.134-4.928.793s-.786 1.479-.793 4.928v4.41c.006 2.945.103 3.662.6 4.278.121.15.258.287.409.408.616.497 1.332.594 4.278.6h.455l.437-.007.071-.004.001-.197c0-3.05.093-3.842.836-4.628l.079-.081c.789-.789 1.505-.908 4.402-.915l.501-.001.003-.025.012-.566v-2.95c0-3.719-.114-4.569-.793-5.248-.639-.639-1.43-.778-4.621-.792l-.306-.001zm4.835 10.835l-.106.001c-2.081.018-2.625.129-3.042.546s-.528.961-.546 3.042l-.001.104 3.695-3.694zM10.002 8.54c.345 0 .625.28.625.625s-.28.625-.625.625H6.669c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h3.333zm3.333-3.333c.345 0 .625.28.625.625s-.28.625-.625.625H6.669c-.345 0-.625-.28-.625-.625s.28-.625.625-.625h6.667z",
|
||||
quill: "M17.295 1.35v.625c0 1.198-.269 2.683-.883 3.96-.527 1.097-1.415 1.885-2.451 2.265l-.164.055.797.815c.219.419.239.457.052.786l-.062.108c-1.692 1.66-2.665 2.439-3.764 3.074l-.37.208-.777.422c-1.023.561-3.772 1.359-5.02 1.515a8.76 8.76 0 0 0-.692 3.454H2.71c0-1.477.3-2.835.849-4.076-.017-.122-.025-.263-.029-.42a9.61 9.61 0 0 1 .071-1.196c.09-.832.261-1.891.424-2.669.473-2.261 2.353-4.979 4.326-6.401 2.476-1.784 5.494-2.528 8.319-2.527h.625zm-1.28 1.265l-.088.004c-2.365.119-4.824.816-6.845 2.272-1.729 1.246-3.427 3.7-3.833 5.643l-.301 1.735c.265-.339.551-.665.856-.98.67-.693 1.386-1.28 2.104-1.766.434-.294.777-.491.983-.594l.558 1.118c-.159.079-.454.249-.84.511-.65.44-1.3.974-1.906 1.6-.492.508-.926 1.047-1.296 1.617 1.146-.263 2.759-.758 3.523-1.128l.144-.074.777-.421.345-.194c.892-.516 1.702-1.144 3.022-2.407l.05-.049-1.187-1.215c-.373-.378-.141-.996.352-1.071l.095-.007c1.144-.006 2.21-.672 2.759-1.815.38-.791.609-1.698.706-2.528l.024-.251z",
|
||||
"web-design":
|
||||
"M17.84 10.724a2.71 2.71 0 0 1 .599.599c.444.611.512 1.096.517 3.002v.513c-.005 1.906-.073 2.391-.517 3.002a2.71 2.71 0 0 1-.599.599c-.611.444-1.096.512-3.002.517h-4.423c-2.12 0-2.621-.054-3.259-.517a2.71 2.71 0 0 1-.599-.599c-.444-.611-.512-1.096-.517-3.002v-.257c0-2.12.054-2.621.517-3.259a2.71 2.71 0 0 1 .599-.599c.611-.444 1.096-.512 3.002-.517h4.423c2.12 0 2.621.054 3.259.517zm-3.024.733H10.18c-1.588.004-1.982.056-2.289.278a1.46 1.46 0 0 0-.323.323c-.223.307-.274.701-.278 2.289v.47c.004 1.588.055 1.982.278 2.289a1.46 1.46 0 0 0 .323.323c.307.223.701.274 2.289.278h4.402c1.786 0 2.203-.045 2.524-.278a1.46 1.46 0 0 0 .323-.323c.223-.307.274-.701.278-2.289v-.47c-.004-1.588-.056-1.982-.278-2.289a1.46 1.46 0 0 0-.323-.323c-.292-.212-.663-.269-2.07-.277l-.219-.001zm-.661 1.401l.767.661c.587.506.7.634.7 1.063a.9.9 0 0 1-.059.32c-.099.261-.194.357-.641.743l-.767.661c-.261.225-.656.196-.881-.065s-.196-.656.065-.881l.767-.661.078-.068.054-.048-.056-.05-.076-.066-.767-.661c-.261-.225-.291-.62-.065-.881s.62-.291.881-.065zm-2.435.065c.225.261.196.656-.065.881l-.767.661-.076.066-.057.05.055.048.078.068.767.661c.261.225.291.62.065.881s-.62.291-.881.065l-.767-.661c-.447-.385-.542-.481-.641-.743a.9.9 0 0 1-.059-.32c0-.429.113-.556.7-1.063l.767-.661c.261-.225.656-.196.881.065zm4.413-10.705c1.026 1.043 1.156 2.021 1.156 6.22 0 .345-.28.625-.625.625s-.625-.28-.625-.625l-.05-2.816H2.34L2.29 8.112v.653c.007 3.508.134 4.344.796 5.017.292.297.665.485 1.213.607.337.075.55.408.475.745s-.408.55-.745.475c-.771-.171-1.36-.468-1.834-.95-.998-1.014-1.148-1.966-1.156-5.877v-.343c0-4.199.129-5.177 1.156-6.22 1.001-1.017 1.944-1.17 5.798-1.178h2.004c4.138 0 5.106.132 6.136 1.179zm-5.815.072H8.011c-3.447.007-4.266.136-4.924.805-.305.31-.496.654-.615 1.278h13.386c-.119-.624-.31-.968-.615-1.278-.659-.669-1.477-.798-4.924-.805z",
|
||||
wrench: "M14.664 1.5c.978-.004 1.47 1.178.779 1.869l-2.25 2.25a.84.84 0 1 0 1.187 1.189l2.25-2.249c.691-.691 1.873-.199 1.869.776l-.001 1.264c-.008 3.289-.1 3.757-.767 4.574-.102.124-.217.249-.361.393-.991.99-2.059 1.132-5.824 1.13H11.5l-4.934 4.936a2.97 2.97 0 0 1-4.197 0 2.97 2.97 0 0 1 0-4.197l4.936-4.936V8.16c.006-3.529.166-4.567 1.13-5.532l.393-.361c.817-.667 1.285-.759 4.575-.767l1.261-.001zM7.52 10.041l-4.272 4.273c-.673.673-.673 1.764 0 2.438s1.764.673 2.438 0l4.272-4.271c-1.14-.394-2.044-1.298-2.438-2.439zm-2.903 4.52a.83.83 0 0 1 .829.829.83.83 0 0 1-.829.829.83.83 0 0 1-.837-.829.83.83 0 0 1 .829-.829zm9.691-11.817h-.861c-2.939.007-3.327.075-3.831.487-.088.072-.184.16-.3.277-.641.64-.768 1.599-.766 4.943v.304c.001 1.488 1.208 2.696 2.694 2.696h.585c3.119-.006 4.041-.143 4.663-.766l.277-.3c.412-.504.48-.892.487-3.83v-.863L15.26 7.687c-.779.778-2.02.812-2.839.101l-.109-.102c-.814-.814-.813-2.134.001-2.948l1.995-1.996z",
|
||||
voice: "M17.221 2.822c1.161 1.161 1.334 2.27 1.342 6.849v.7c-.008 4.579-.181 5.688-1.342 6.849s-2.27 1.334-6.849 1.342h-.7c-4.579-.008-5.688-.181-6.849-1.342s-1.334-2.27-1.342-6.849v-.35c0-4.874.153-6.009 1.342-7.199 1.161-1.161 2.27-1.334 6.849-1.342h.35c4.874 0 6.009.153 7.199 1.342zm-6.863-.092h-.672c-4.172.007-5.162.158-5.979.976-.839.839-.976 1.859-.976 6.315v.336c.007 4.172.158 5.162.976 5.979s1.807.969 5.979.976h.672c4.172-.007 5.162-.158 5.979-.976s.969-1.807.976-5.979v-.672c-.007-4.172-.158-5.162-.976-5.979-.796-.796-1.755-.96-5.657-.975l-.323-.001zm-.336 3.333c.345 0 .625.28.625.625v6.667c0 .345-.28.625-.625.625s-.625-.28-.625-.625V6.688c0-.345.28-.625.625-.625zm-2.5 1.667c.345 0 .625.28.625.625v3.333c0 .345-.28.625-.625.625s-.625-.28-.625-.625V8.355c0-.345.28-.625.625-.625zm5 0c.345 0 .625.28.625.625v3.333c0 .345-.28.625-.625.625s-.625-.28-.625-.625V8.355c0-.345.28-.625.625-.625zm-7.5.833c.345 0 .625.28.625.625v1.667c0 .345-.28.625-.625.625s-.625-.28-.625-.625V9.188c0-.345.28-.625.625-.625zm10 0c.345 0 .625.28.625.625v1.667c0 .345-.28.625-.625.625s-.625-.28-.625-.625V9.188c0-.345.28-.625.625-.625z",
|
||||
volume: "M6.941 5.311c2.58-2.681 3.131-3.112 4.203-2.651 1.062.457 1.158 1.162 1.158 4.942v5.13c-.006 3.487-.128 4.163-1.158 4.607-1.072.462-1.623.031-4.203-2.65-.818-.85-1.191-1.007-2.378-1.007-1.628 0-2.015-.041-2.538-.404-.75-.521-1.003-1.285-1.023-2.4L1 10.786v-.194l.003-.262.003-.226v-.208l-.003-.226L1 9.408v-.194l.001-.092c.021-1.115.273-1.879 1.023-2.4.523-.363.91-.404 2.538-.404 1.187 0 1.56-.157 2.378-1.007zm3.714-1.473c-.284-.122-.838.311-2.817 2.368-1.056 1.097-1.753 1.391-3.275 1.391-1.309 0-1.615.032-1.831.182-.331.23-.462.626-.475 1.368l-.001.081v.177l.003.246.003.237v.226l-.003.237-.003.246v.177l.001.081c.014.742.145 1.138.475 1.368.215.15.522.182 1.831.182 1.522 0 2.219.293 3.275 1.391 1.979 2.056 2.533 2.49 2.817 2.368.294-.126.391-.845.391-3.765V7.308c-.007-2.674-.108-3.349-.391-3.471zm3.15 3.098a.62.62 0 0 1 .88.12A4.9 4.9 0 0 1 15.651 10a4.9 4.9 0 0 1-.966 2.944.62.62 0 0 1-.88.12c-.276-.214-.329-.615-.118-.896.455-.607.709-1.366.709-2.169s-.253-1.561-.709-2.169c-.21-.281-.157-.682.118-.896zm2.469-1.667a.62.62 0 0 1 .887.04C18.341 6.62 19 8.264 19 10s-.659 3.38-1.839 4.692a.62.62 0 0 1-.887.04c-.256-.238-.273-.643-.039-.903.973-1.082 1.51-2.42 1.51-3.829s-.536-2.747-1.51-3.829c-.234-.26-.217-.665.039-.903z",
|
||||
zsh: "M16.155 2.795a4.79 4.79 0 0 1 1.06 1.06c.811 1.116.915 2.076.915 6.15s-.104 5.033-.915 6.15a4.79 4.79 0 0 1-1.06 1.06c-1.116.811-2.076.915-6.15.915s-5.033-.104-6.15-.915a4.79 4.79 0 0 1-1.06-1.06c-.787-1.084-.908-2.02-.915-5.798v-.351c0-4.073.104-5.033.915-6.15a4.79 4.79 0 0 1 1.06-1.06c1.084-.787 2.02-.908 5.798-.915h.351c4.073 0 5.033.104 6.15.915zm-5.818.335h-.664c-3.46.006-4.307.112-5.083.676a3.54 3.54 0 0 0-.784.784c-.564.776-.67 1.623-.676 5.083v.664c.006 3.46.112 4.307.676 5.083a3.54 3.54 0 0 0 .784.783c.8.581 1.676.676 5.415.676s4.615-.095 5.415-.676a3.54 3.54 0 0 0 .784-.784c.581-.8.676-1.676.676-5.415s-.095-4.615-.676-5.415a3.54 3.54 0 0 0-.784-.784c-.752-.546-1.571-.663-4.766-.675l-.317-.001zm3.392 2.22c.27.216.313.609.098.878L7.16 14.562c-.216.27-.609.313-.878.098s-.313-.609-.098-.878l6.667-8.333c.216-.27.609-.313.878-.098z",
|
||||
};
|
||||
|
||||
type IconProps = {
|
||||
className?: string;
|
||||
name: string;
|
||||
fill?: string;
|
||||
};
|
||||
|
||||
const Icon = ({ className, name, fill }: IconProps) => (
|
||||
<svg
|
||||
className={`inline-flex size-5 ${className || ""}`}
|
||||
width={20}
|
||||
height={20}
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path fill={fill} d={icons[name]}></path>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default Icon;
|
||||
18
src/views/AgentChat/neuratalk/components/Image/index.tsx
Normal file
18
src/views/AgentChat/neuratalk/components/Image/index.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { useState } from "react";
|
||||
import { default as NextImage, ImageProps } from "next/image";
|
||||
|
||||
const Image = ({ className, ...props }: ImageProps) => {
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
|
||||
return (
|
||||
<NextImage
|
||||
className={`inline-block align-top opacity-0 transition-opacity ${
|
||||
loaded && "opacity-100"
|
||||
} ${className || ""}`}
|
||||
onLoad={() => setLoaded(true)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Image;
|
||||
@@ -0,0 +1,45 @@
|
||||
import Chat from "@/components/Chat";
|
||||
import Question from "@/components/Question";
|
||||
import Answer from "@/components/Answer";
|
||||
import Button from "@/components/Button";
|
||||
|
||||
const LanguageTranslator = () => {
|
||||
return (
|
||||
<Chat>
|
||||
<Question>
|
||||
<div className="mb-1">Translate this text to frensh:</div>
|
||||
<div className="">
|
||||
Beneath the quiet hum of a late-night city, a single
|
||||
streetlamp flickered like it was holding on to its last
|
||||
breath. Somewhere nearby, the scent of fresh rain clung to
|
||||
the pavement, mixing with the soft sound of footsteps
|
||||
echoing between empty buildings. It was the kind of night
|
||||
where time felt slower, and the world seemed to hold its
|
||||
breath, waiting for something unspoken to happen.
|
||||
</div>
|
||||
</Question>
|
||||
<Answer>
|
||||
<div className="mb-4">Sure here is the text in frensh:</div>
|
||||
<div className="text-label-sm">
|
||||
Sous le doux bourdonnement d'une ville tard dans la
|
||||
nuit, un seul lampadaire vacillait comme s'il
|
||||
s'accrochait à son dernier souffle. Non loin de là,
|
||||
l'odeur de la pluie fraîche s'accrochait au
|
||||
bitume, se mêlant au léger bruit de pas résonnant entre les
|
||||
immeubles vides. C’était le genre de nuit où le temps
|
||||
semblait ralentir, et où le monde retenait son souffle,
|
||||
attendant que quelque chose d’indicible se produise.
|
||||
</div>
|
||||
<Button
|
||||
className="!h-9 mt-6 !rounded-lg !bg-weak-50 max-md:mt-4"
|
||||
icon="language-1"
|
||||
isStroke
|
||||
>
|
||||
Change text language
|
||||
</Button>
|
||||
</Answer>
|
||||
</Chat>
|
||||
);
|
||||
};
|
||||
|
||||
export default LanguageTranslator;
|
||||
79
src/views/AgentChat/neuratalk/components/Layout/index.tsx
Normal file
79
src/views/AgentChat/neuratalk/components/Layout/index.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import { useState } from "react";
|
||||
import Sidebar from "@/components/Sidebar";
|
||||
import Tools from "@/components/Tools";
|
||||
import Header from "@/components/Header";
|
||||
import PythonRunner from "@/components/PythonRunner";
|
||||
import Calculator from "@/components/Calculator";
|
||||
import Browser from "@/components/Browser";
|
||||
import WebDesign from "@/components/WebDesign";
|
||||
import FileConverter from "@/components/FileConverter";
|
||||
import LanguageTranslator from "@/components/LanguageTranslator";
|
||||
import ApiIntegrator from "@/components/ApiIntegrator";
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
const Layout = ({ children }: Props) => {
|
||||
const [activeId, setActiveId] = useState<string | null>(null);
|
||||
const [visibleTools, setVisibleTools] = useState(true);
|
||||
const [visibleSidebar, setVisibleSidebar] = useState(false);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`pl-90 overflow-hidden transition-all max-3xl:pl-75 max-lg:pl-5 max-md:pl-4 ${
|
||||
visibleTools
|
||||
? "pr-90 max-3xl:pr-75 max-2xl:pr-5 max-md:pr-4"
|
||||
: "pr-5 max-md:pr-4"
|
||||
}`}
|
||||
>
|
||||
<Sidebar
|
||||
visible={visibleSidebar}
|
||||
onClose={() => setVisibleSidebar(false)}
|
||||
onClickNewChat={() => setActiveId(null)}
|
||||
/>
|
||||
<div className="pt-9.5 pb-5 max-2xl:pt-5 max-md:pt-3 max-md:pb-4">
|
||||
<Header
|
||||
onOpenSidebar={() => setVisibleSidebar(true)}
|
||||
onToggleTools={() => setVisibleTools(!visibleTools)}
|
||||
/>
|
||||
{activeId === "python" ? (
|
||||
<PythonRunner />
|
||||
) : activeId === "calculator" ? (
|
||||
<Calculator />
|
||||
) : activeId === "browser" ? (
|
||||
<Browser />
|
||||
) : activeId === "web-design" ? (
|
||||
<WebDesign />
|
||||
) : activeId === "exchange" ? (
|
||||
<FileConverter />
|
||||
) : activeId === "language" ? (
|
||||
<LanguageTranslator />
|
||||
) : activeId === "api" ? (
|
||||
<ApiIntegrator />
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</div>
|
||||
<Tools
|
||||
activeId={activeId}
|
||||
setActiveId={setActiveId}
|
||||
visible={visibleTools}
|
||||
onClose={() => setVisibleTools(!visibleTools)}
|
||||
/>
|
||||
<div
|
||||
className={`fixed inset-0 z-10 hidden bg-overlay backdrop-blur-sm transition-all max-lg:block max-md:hidden ${
|
||||
visibleSidebar || !visibleTools
|
||||
? "visible opacity-100"
|
||||
: "invisible opacity-0"
|
||||
}`}
|
||||
onClick={() => {
|
||||
setVisibleSidebar(false);
|
||||
setVisibleTools(true);
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
@@ -0,0 +1,105 @@
|
||||
import { Swiper, SwiperSlide } from "swiper/react";
|
||||
import { items } from "./items";
|
||||
import Image from "@/components/Image";
|
||||
import { useState } from "react";
|
||||
|
||||
import "swiper/css";
|
||||
import "swiper/css/effect-fade";
|
||||
import { Autoplay } from "swiper/modules";
|
||||
|
||||
const SLIDE_DURATION = 3000;
|
||||
|
||||
const Slider = ({}) => {
|
||||
const [currentSlide, setCurrentSlide] = useState(0);
|
||||
|
||||
return (
|
||||
<div className="absolute bottom-15 left-10 right-10 z-2 max-2xl:bottom-8 max-2xl:left-8 max-2xl:right-8">
|
||||
<Swiper
|
||||
className="mySwiper !overflow-visible"
|
||||
spaceBetween={56}
|
||||
modules={[Autoplay]}
|
||||
autoplay={{
|
||||
delay: SLIDE_DURATION,
|
||||
disableOnInteraction: false,
|
||||
}}
|
||||
onSlideChange={(swiper) => setCurrentSlide(swiper.activeIndex)}
|
||||
speed={500}
|
||||
>
|
||||
{items.map((item, index) => (
|
||||
<SwiperSlide
|
||||
className="relative p-5.5 pl-45 border border-stroke-soft-200 rounded-[1.125rem] bg-[#99A0AE]/24 backdrop-blur-[0.625rem] max-xl:pl-5.5"
|
||||
key={item.id}
|
||||
>
|
||||
<div className="absolute -left-1 bottom-3 max-xl:hidden">
|
||||
<Image
|
||||
className="w-46.5"
|
||||
src={item.image}
|
||||
width={186}
|
||||
height={170}
|
||||
alt={item.author}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-3 mb-2 text-label-lg">
|
||||
<div className="border border-stroke-soft-200 rounded-xl overflow-hidden rotate-[-10deg]">
|
||||
<Image
|
||||
className="w-10 h-9.5 object-cover"
|
||||
src={item.avatar}
|
||||
width={40}
|
||||
height={38}
|
||||
alt={item.author}
|
||||
/>
|
||||
</div>
|
||||
{item.author}
|
||||
<div className="ml-auto text-label-lg">
|
||||
{index + 1}/{items.length}
|
||||
</div>
|
||||
<div className="w-6.5 h-6.5">
|
||||
<svg
|
||||
className="w-full h-full transform -rotate-90"
|
||||
viewBox="0 0 36 36"
|
||||
>
|
||||
<circle
|
||||
cx="18"
|
||||
cy="18"
|
||||
r="16"
|
||||
fill="none"
|
||||
stroke="rgba(255, 255, 255, 0.2)"
|
||||
strokeWidth="3"
|
||||
/>
|
||||
<circle
|
||||
cx="18"
|
||||
cy="18"
|
||||
r="16"
|
||||
fill="none"
|
||||
stroke="white"
|
||||
strokeWidth="3"
|
||||
strokeDasharray={`${2 * Math.PI * 16}`}
|
||||
strokeDashoffset={`${2 * Math.PI * 16}`}
|
||||
strokeLinecap="round"
|
||||
className={`${
|
||||
index === currentSlide
|
||||
? "animate-progress"
|
||||
: "opacity-50"
|
||||
}`}
|
||||
style={{
|
||||
animationDuration: `${SLIDE_DURATION}ms`,
|
||||
animationPlayState:
|
||||
index === currentSlide
|
||||
? "running"
|
||||
: "paused",
|
||||
}}
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div className="min-h-12 line-clamp-2 text-label-sm text-[#CACFD8]">
|
||||
{item.content}
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Slider;
|
||||
@@ -0,0 +1,34 @@
|
||||
export const items = [
|
||||
{
|
||||
id: 0,
|
||||
author: "Suzana Marie",
|
||||
avatar: "/images/avatar-6.jpg",
|
||||
content:
|
||||
"People with link will be able to view conversations and ideas in this board.Changes you make after creating the link will remain private.",
|
||||
image: "/images/slider-pic-1.png",
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
author: "Tyson Martine",
|
||||
avatar: "/images/avatar-2.png",
|
||||
content:
|
||||
"My ideas are in a great place. All the content is well organized and it's easy to find what I need.",
|
||||
image: "/images/slider-pic-1.png",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
author: "Terrence Jaskolski",
|
||||
avatar: "/images/avatar-3.jpg",
|
||||
content:
|
||||
"I'm amazed at how quickly and easily I can create new ideas with this tool. It's a game-changer!",
|
||||
image: "/images/slider-pic-1.png",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
author: "Suzana Marie",
|
||||
avatar: "/images/avatar-6.jpg",
|
||||
content:
|
||||
"People with link will be able to view conversations and ideas in this board.Changes you make after creating the link will remain private.",
|
||||
image: "/images/slider-pic-1.png",
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,87 @@
|
||||
import Link from "next/link";
|
||||
import Image from "@/components/Image";
|
||||
import Button from "@/components/Button";
|
||||
import Icon from "@/components/Icon";
|
||||
import Slider from "./Slider";
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
title: string;
|
||||
description: React.ReactNode;
|
||||
};
|
||||
|
||||
const LayoutLogin = ({ title, description, children }: Props) => (
|
||||
<div className="p-5">
|
||||
<div className="flex min-h-[calc(100svh-2.5rem)]">
|
||||
<div className="relative w-1/2 text-static-white overflow-hidden max-lg:hidden">
|
||||
<Image
|
||||
className="object-cover rounded-3xl"
|
||||
src="/images/auth-pic.jpg"
|
||||
fill
|
||||
sizes="(max-width: 1023px) 100vw, 50vw"
|
||||
alt=""
|
||||
/>
|
||||
<div className="absolute top-19 left-10 right-10 max-2xl:top-8 max-2xl:left-8 max-2xl:right-8">
|
||||
<div className="mb-4 text-h1 max-2xl:text-h3">
|
||||
AI Generative Anything you can imagine
|
||||
</div>
|
||||
<div className="text-p-lg max-2xl:text-p-md">
|
||||
Generate your ideas in to reality fast & quick !
|
||||
</div>
|
||||
</div>
|
||||
<Slider />
|
||||
</div>
|
||||
<div className="flex flex-col w-1/2 pl-12 max-lg:w-full max-lg:pl-0">
|
||||
<div className="flex justify-between items-center mb-auto">
|
||||
<div className="">
|
||||
<div className="text-[1.125rem] font-bold">Website</div>
|
||||
<div className="-mt-1 text-soft-400">
|
||||
Visite Our website
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
className="!h-10 !gap-3 bg-white-0 rounded-xl"
|
||||
isStroke
|
||||
>
|
||||
LoopiBot.com
|
||||
<Icon className="!size-4.5" name="chevron-circle" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="w-full max-w-89 mx-auto my-6">
|
||||
<div className="mb-7 text-center max-md:mb-4">
|
||||
<Link className="inline-flex mb-6 max-md:mb-4" href="/">
|
||||
<Image
|
||||
className="w-18 opacity-100 max-md:w-14"
|
||||
src="/images/logo-auth.svg"
|
||||
width={68}
|
||||
height={68}
|
||||
alt=""
|
||||
/>
|
||||
</Link>
|
||||
<div className="text-h3 max-md:text-[1.6rem]">
|
||||
{title}
|
||||
</div>
|
||||
<div className="mt-1.5 text-h6 max-md:text-label-md">
|
||||
{description}
|
||||
</div>
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
<div className="flex justify-between items-center h-15 mt-auto max-2xl:h-auto">
|
||||
<div className="text-label-sm text-sub-600">
|
||||
©LoopiBot.io
|
||||
</div>
|
||||
<button className="group flex items-center gap-2 text-label-sm text-sub-600 transition-colors hover:text-strong-950">
|
||||
<Icon
|
||||
className="!size-4.5 fill-sub-600 transition-colors group-hover:fill-strong-950"
|
||||
name="envelope"
|
||||
/>
|
||||
LoopiBot@chat.io
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default LayoutLogin;
|
||||
40
src/views/AgentChat/neuratalk/components/Modal/index.tsx
Normal file
40
src/views/AgentChat/neuratalk/components/Modal/index.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import {
|
||||
Dialog,
|
||||
DialogPanel,
|
||||
DialogBackdrop,
|
||||
CloseButton,
|
||||
} from "@headlessui/react";
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
type ModalProps = {
|
||||
classWrapper?: string;
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
const Modal = ({ classWrapper, open, onClose, children }: ModalProps) => {
|
||||
return (
|
||||
<Dialog className="relative z-50" open={open} onClose={onClose}>
|
||||
<DialogBackdrop
|
||||
className="fixed inset-0 bg-overlay backdrop-blur-sm duration-300 ease-out data-[closed]:opacity-0"
|
||||
transition
|
||||
/>
|
||||
<div className="fixed inset-0 flex p-4 overflow-y-auto max-lg:py-12">
|
||||
<DialogPanel
|
||||
className={`relative w-full m-auto p-5.5 shadow-[0_0_1.25rem_0_rgba(0,0,0,0.02)] rounded-2xl bg-white-0 duration-300 ease-out data-[closed]:opacity-0 max-md:px-4 ${
|
||||
classWrapper || ""
|
||||
}`}
|
||||
transition
|
||||
>
|
||||
{children}
|
||||
<CloseButton className="absolute left-[calc(100%+0.75rem)] top-0 z-15 size-8 bg-strong-950 rounded-full text-0 transition-colors hover:bg-strong-950/90 max-lg:top-auto max-lg:left-auto max-lg:right-0 max-lg:bottom-[calc(100%+0.5rem)]">
|
||||
<Icon className="!size-4 fill-white-0" name="close" />
|
||||
</CloseButton>
|
||||
</DialogPanel>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default Modal;
|
||||
104
src/views/AgentChat/neuratalk/components/ModalPlan/index.tsx
Normal file
104
src/views/AgentChat/neuratalk/components/ModalPlan/index.tsx
Normal file
@@ -0,0 +1,104 @@
|
||||
import Modal from "@/components/Modal";
|
||||
import Button from "@/components/Button";
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
import { plans } from "./plans";
|
||||
|
||||
type GalleryProps = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const ModalPlan = ({ open, onClose }: GalleryProps) => (
|
||||
<Modal classWrapper="max-w-200" open={open} onClose={onClose}>
|
||||
<div className="mb-4 pb-1.5 border-b border-stroke-soft-200">
|
||||
<div className="text-label-xl">Plans</div>
|
||||
<div className="text-label-md text-sub-600">
|
||||
Manage your billing and payment details.
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-3 max-md:gap-1.5 max-md:-mx-4 max-md:px-4 max-md:overflow-auto max-md:scrollbar-none">
|
||||
{plans.map((plan) => (
|
||||
<div
|
||||
className={`relative flex-1 p-3 rounded-2xl overflow-hidden max-md:shrink-0 max-md:flex-auto max-md:w-60 ${
|
||||
plan.name === "Premium Plan"
|
||||
? "bg-weak-50 before:absolute before:-top-15 before:-right-32 before:size-60 before:bg-[#476CFF]/5 before:rounded-full before:blur-[3rem]"
|
||||
: ""
|
||||
}`}
|
||||
key={plan.id}
|
||||
>
|
||||
<div className="relative z-2">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<Icon
|
||||
className="!size-6 fill-strong-950"
|
||||
name={plan.icon}
|
||||
/>
|
||||
{plan.name === "Premium Plan" && (
|
||||
<div className="flex items-center gap-1 h-6.5 px-2 rounded-full bg-[#476CFF]/10 text-label-xs text-blue-500">
|
||||
<Icon
|
||||
className="!size-3.25 fill-blue-500"
|
||||
name="flash"
|
||||
/>
|
||||
Most Popular
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="mb-1 text-label-lg">{plan.name}</div>
|
||||
<div className="min-h-10.5 mb-3 text-soft-400">
|
||||
{plan.description}
|
||||
</div>
|
||||
<div className="font-satoshi font-bold text-h5">
|
||||
{plan.price}
|
||||
</div>
|
||||
<div className="mb-6 text-sub-600">{plan.details}</div>
|
||||
<button
|
||||
className={`flex justify-center items-center gap-1.5 w-full h-10 mb-6 rounded-[0.625rem] text-label-md transition-opacity hover:opacity-90 ${
|
||||
plan.name === "Basic Plan"
|
||||
? "bg-weak-50 [&_svg]:fill-strong-950"
|
||||
: plan.name === "Premium Plan"
|
||||
? "border border-blue-500 text-blue-600"
|
||||
: "bg-blue-600 text-static-white [&_svg]:fill-static-white"
|
||||
}`}
|
||||
>
|
||||
{plan.name === "Basic Plan"
|
||||
? "Buy now"
|
||||
: plan.name === "Premium Plan"
|
||||
? "Switch to this plan"
|
||||
: "Contact Us"}
|
||||
{plan.name !== "Premium Plan" && (
|
||||
<Icon className="-rotate-45" name="arrow" />
|
||||
)}
|
||||
</button>
|
||||
<div className="">
|
||||
{plan.features.map((feature, index) => (
|
||||
<div
|
||||
className="flex items-center gap-2 py-4 border-t border-stroke-soft-200 text-label-sm"
|
||||
key={index}
|
||||
>
|
||||
<svg
|
||||
className="shrink-0 fill-strong-950"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path d="M16.611 5.124c.16.431-.06.911-.491 1.071-.882.327-1.85 1.009-2.83 1.909-.971.892-1.906 1.954-2.727 2.985l-2.004 2.739-.569.868-.149.237-.037.06-.009.015-.002.003c-.153.252-.429.406-.724.402s-.566-.164-.713-.42c-.791-1.384-1.444-2.008-1.838-2.283a1.49 1.49 0 0 0-.387-.208l-.03-.009c-.431-.032-.772-.392-.772-.831 0-.46.373-.833.833-.833.098.007.331.033.474.085.228.072.512.203.837.43.466.327 1.014.85 1.61 1.689l.092-.137 2.082-2.846c.852-1.07 1.847-2.204 2.903-3.174 1.047-.962 2.202-1.808 3.378-2.244.431-.16.911.06 1.071.491z" />
|
||||
</svg>
|
||||
{feature}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex justify-end gap-3 mt-4.5">
|
||||
<Button className="!bg-weak-50" isStroke onClick={onClose}>
|
||||
Discard
|
||||
</Button>
|
||||
<Button isBlack>Upgrade Membership</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
export default ModalPlan;
|
||||
44
src/views/AgentChat/neuratalk/components/ModalPlan/plans.tsx
Normal file
44
src/views/AgentChat/neuratalk/components/ModalPlan/plans.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
export const plans = [
|
||||
{
|
||||
id: 0,
|
||||
name: "Basic Plan",
|
||||
icon: "profile",
|
||||
description: "per user/email month billed annually",
|
||||
price: "$9.99",
|
||||
details: "one-time payment + Local Taxes",
|
||||
features: [
|
||||
"1 Image generation",
|
||||
"File Sharing",
|
||||
"Limited Integration",
|
||||
"Limited templates",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: "Premium Plan",
|
||||
icon: "rocket",
|
||||
description: "per user/email month billed annually",
|
||||
price: "$19.99",
|
||||
details: "one-time payment + Local Taxes",
|
||||
features: [
|
||||
"30 Image generation",
|
||||
"File Sharing",
|
||||
"10 Integration",
|
||||
"20 templates",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Professional Plan",
|
||||
icon: "build",
|
||||
description: "per user/email month billed annually",
|
||||
price: "Custom",
|
||||
details: "one-time payment + Local Taxes",
|
||||
features: [
|
||||
"unlimited Image generation",
|
||||
"File Sharing",
|
||||
"unlimited Integration",
|
||||
"unlimited Integration",
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,63 @@
|
||||
import { useState } from "react";
|
||||
import Switch from "@/components/Switch";
|
||||
import Button from "@/components/Button";
|
||||
|
||||
const DataControls = ({}) => {
|
||||
const [improve, setImprove] = useState(true);
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<div className="flex justify-between gap-6 mb-3 pb-3 border-b border-stroke-soft-200">
|
||||
<div className="max-w-101">
|
||||
<div className="text-label-md">
|
||||
Improve the model for everyone
|
||||
</div>
|
||||
<div className="text-sub-600">
|
||||
Allow your content to be used to train our models, which
|
||||
makes AI better for you and everyone who uses it. We
|
||||
take steps to protect your privacy.{" "}
|
||||
<button className="underline text-blue-500 hover:no-underline">
|
||||
Learn more
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<Switch checked={improve} onChange={setImprove} isSmall />
|
||||
</div>
|
||||
<div className="flex justify-between items-center gap-6 mb-3 pb-3 border-b border-stroke-soft-200">
|
||||
<div className="text-label-md">Export Data</div>
|
||||
<Button
|
||||
className="!h-10 !rounded-[0.625rem] !bg-weak-50"
|
||||
isStroke
|
||||
>
|
||||
Export
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex justify-between items-center gap-6 mb-3 pb-3 border-b border-stroke-soft-200">
|
||||
<div className="text-label-md">Shared Links</div>
|
||||
<Button
|
||||
className="!h-10 !rounded-[0.625rem] !bg-weak-50"
|
||||
isStroke
|
||||
>
|
||||
Manage
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex justify-between items-center gap-6 mb-3 pb-3 border-b border-stroke-soft-200">
|
||||
<div className="text-label-md">Archive all chats</div>
|
||||
<Button
|
||||
className="!h-10 !rounded-[0.625rem] !bg-weak-50"
|
||||
isStroke
|
||||
>
|
||||
Archive all
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex justify-between items-center gap-6">
|
||||
<div className="text-label-md">Delete Account</div>
|
||||
<Button className="!h-10 !rounded-[0.625rem]" isRed>
|
||||
Delete Account
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DataControls;
|
||||
@@ -0,0 +1,76 @@
|
||||
import { useState, useRef } from "react";
|
||||
import Image from "@/components/Image";
|
||||
import Button from "@/components/Button";
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
const UploadImage = ({}) => {
|
||||
const [preview, setPreview] = useState<string | null>(
|
||||
"/images/avatar-1.png"
|
||||
);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = e.target.files?.[0];
|
||||
if (file) {
|
||||
const objectUrl = URL.createObjectURL(file);
|
||||
setPreview(objectUrl);
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemove = () => {
|
||||
setPreview(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="relative flex justify-center items-center bg-soft-200 size-11.5 rounded-full overflow-hidden">
|
||||
{preview ? (
|
||||
<Image
|
||||
className="size-full opacity-100"
|
||||
src={preview}
|
||||
width={48}
|
||||
height={48}
|
||||
alt="avatar"
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
className="size-6 fill-strong-950"
|
||||
name="profile"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="relative">
|
||||
<input
|
||||
className="absolute inset-0 opacity-0 cursor-pointer z-10 object-cover"
|
||||
ref={inputRef}
|
||||
type="file"
|
||||
onChange={handleChange}
|
||||
accept="image/*"
|
||||
/>
|
||||
<Button className="!h-9 rounded-lg" isStroke>
|
||||
Upload image
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
className="!w-9 !h-9 !px-0 rounded-lg"
|
||||
isStroke
|
||||
onClick={handleRemove}
|
||||
>
|
||||
<Image
|
||||
className="size-6 opacity-100"
|
||||
src="/images/trash.svg"
|
||||
width={24}
|
||||
height={24}
|
||||
alt=""
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-1.5 text-soft-400 max-md:text-p-xs">
|
||||
We only support JPG, JPEG, or ,PNG file. 1MB max.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default UploadImage;
|
||||
@@ -0,0 +1,80 @@
|
||||
import { useState } from "react";
|
||||
import Field from "@/components/Field";
|
||||
import Icon from "@/components/Icon";
|
||||
import Button from "@/components/Button";
|
||||
import UploadImage from "./UploadImage";
|
||||
|
||||
const General = ({}) => {
|
||||
const [fullName, setFullName] = useState("");
|
||||
const [email, setEmail] = useState("");
|
||||
const [phoneNumber, setPhoneNumber] = useState("");
|
||||
|
||||
return (
|
||||
<div className="-mt-5 max-md:mt-0">
|
||||
<div className="flex items-center mb-3 pb-3 border-b border-stroke-soft-200 max-md:flex-col max-md:items-start max-md:gap-3">
|
||||
<div className="mr-auto">
|
||||
<div className="text-label-md">Avatar</div>
|
||||
<div className="text-sub-600">Update full name</div>
|
||||
</div>
|
||||
<UploadImage />
|
||||
</div>
|
||||
<div className="mb-3 pb-3 border-b border-stroke-soft-200">
|
||||
<div className="mb-3">
|
||||
<div className="text-label-md">Personal Information</div>
|
||||
<div className="text-sub-600">
|
||||
Edit your personal information
|
||||
</div>
|
||||
</div>
|
||||
<Field
|
||||
className="mb-3"
|
||||
label="Full name"
|
||||
placeholder="Enter full name"
|
||||
value={fullName}
|
||||
onChange={(e) => setFullName(e.target.value)}
|
||||
required
|
||||
isSmall
|
||||
/>
|
||||
<Field
|
||||
className="mb-1"
|
||||
label="Email"
|
||||
placeholder="Enter email"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
isSmall
|
||||
/>
|
||||
<button className="inline-flex items-center gap-2 text-label-xs text-sub-600 transition-opacity hover:opacity-80">
|
||||
<Icon className="!size-4" name="plus" />
|
||||
Add another
|
||||
</button>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<div className="mb-3">
|
||||
<div className="text-label-md">Phone number</div>
|
||||
<div className="text-sub-600">Update your phone number</div>
|
||||
</div>
|
||||
<Field
|
||||
className=""
|
||||
label="Phone number"
|
||||
placeholder="Enter phone number"
|
||||
type="tel"
|
||||
value={phoneNumber}
|
||||
onChange={(e) => setPhoneNumber(e.target.value)}
|
||||
required
|
||||
isSmall
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-end gap-3">
|
||||
<Button className="!h-10 !px-4.5 !bg-weak-50" isStroke>
|
||||
Discard
|
||||
</Button>
|
||||
<Button className="!h-10 !px-4.5" isBlack>
|
||||
Save Changes
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default General;
|
||||
@@ -0,0 +1,34 @@
|
||||
import { useState } from "react";
|
||||
import Switch from "@/components/Switch";
|
||||
|
||||
const Speech = ({}) => {
|
||||
const [responses, setResponses] = useState(true);
|
||||
const [push, setPush] = useState(true);
|
||||
const [email, setEmail] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<div className="flex items-center mb-3 pb-3 border-b border-stroke-soft-200">
|
||||
<div className="mr-auto">
|
||||
<div className="text-label-md">Responses</div>
|
||||
<div className="text-sub-600">Ai response Push</div>
|
||||
</div>
|
||||
<Switch checked={responses} onChange={setResponses} isSmall />
|
||||
</div>
|
||||
<div className="flex items-center mb-3 pb-3 border-b border-stroke-soft-200">
|
||||
<div className="mr-auto">
|
||||
<div className="text-label-md">Push</div>
|
||||
</div>
|
||||
<Switch checked={push} onChange={setPush} isSmall />
|
||||
</div>
|
||||
<div className="flex items-center mb-3 pb-3 border-b border-stroke-soft-200">
|
||||
<div className="mr-auto">
|
||||
<div className="text-label-md">Email</div>
|
||||
</div>
|
||||
<Switch checked={email} onChange={setEmail} isSmall />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Speech;
|
||||
@@ -0,0 +1,47 @@
|
||||
import { useState } from "react";
|
||||
import Switch from "@/components/Switch";
|
||||
import Button from "@/components/Button";
|
||||
|
||||
const Security = ({}) => {
|
||||
const [authentication, setAuthentication] = useState(true);
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<div className="flex justify-between gap-6 mb-3 pb-3 border-b border-stroke-soft-200">
|
||||
<div className="max-w-101">
|
||||
<div className="text-label-md">
|
||||
Mlti-factor authentication
|
||||
</div>
|
||||
<div className="text-sub-600">
|
||||
Require an extra security challenge when logging in. If
|
||||
you are unable to pass this challenge, you will have the
|
||||
option to recover your account via email.
|
||||
</div>
|
||||
</div>
|
||||
<Switch
|
||||
checked={authentication}
|
||||
onChange={setAuthentication}
|
||||
isSmall
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-between gap-6 max-md:flex-col max-md:gap-3">
|
||||
<div className="max-w-101">
|
||||
<div className="text-label-md">Log out of all devices</div>
|
||||
<div className="text-sub-600">
|
||||
Log out of all active sessions across all devices,
|
||||
including your current session. It may take up to 30
|
||||
minutes for other devices to be logged out.
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
className="shrink-0 !h-10 !rounded-[0.625rem] !bg-weak-50"
|
||||
isStroke
|
||||
>
|
||||
Log out all
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Security;
|
||||
@@ -0,0 +1,62 @@
|
||||
import { useState } from "react";
|
||||
import Button from "@/components/Button";
|
||||
import Icon from "@/components/Icon";
|
||||
import Select from "@/components/Select";
|
||||
|
||||
const voiceOptions = [
|
||||
{ id: 1, name: "Default" },
|
||||
{ id: 2, name: "Echo" },
|
||||
{ id: 3, name: "Tempo" },
|
||||
];
|
||||
|
||||
const languages = [
|
||||
{ id: 1, name: "English" },
|
||||
{ id: 2, name: "French" },
|
||||
{ id: 3, name: "Spanish" },
|
||||
];
|
||||
|
||||
const Notifications = ({}) => {
|
||||
const [voice, setVoice] = useState(voiceOptions[0]);
|
||||
const [language, setLanguage] = useState(languages[0]);
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<div className="flex items-center mb-3 pb-3 border-b border-stroke-soft-200">
|
||||
<div className="mr-auto">
|
||||
<div className="text-label-md">Voice</div>
|
||||
<div className="text-sub-600">Choose your ai voice.</div>
|
||||
</div>
|
||||
<div className="flex gap-1.5">
|
||||
<Button
|
||||
className="w-10 !h-10 !px-0 !rounded-[0.625rem] !bg-weak-50"
|
||||
isStroke
|
||||
>
|
||||
<Icon className="fill-icon-sub-600" name="volume" />
|
||||
</Button>
|
||||
<Select
|
||||
classButton="h-10 bg-weak-50 rounded-[0.625rem]"
|
||||
value={voice}
|
||||
onChange={setVoice}
|
||||
options={voiceOptions}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="mr-auto">
|
||||
<div className="text-label-md">Main Language</div>
|
||||
<div className="text-sub-600">
|
||||
For best results, select the language you mainly speak.
|
||||
</div>
|
||||
</div>
|
||||
<Select
|
||||
classButton="h-10 bg-weak-50 rounded-[0.625rem]"
|
||||
value={language}
|
||||
onChange={setLanguage}
|
||||
options={languages}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Notifications;
|
||||
@@ -0,0 +1,97 @@
|
||||
import { useTheme } from "next-themes";
|
||||
import Image from "@/components/Image";
|
||||
|
||||
const Theme = ({}) => {
|
||||
const { theme, setTheme } = useTheme();
|
||||
|
||||
const themes = [
|
||||
{
|
||||
id: 1,
|
||||
name: "Light mode",
|
||||
image: "/images/theme-light.png",
|
||||
value: "light",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Dark mode",
|
||||
image: "/images/theme-dark.png",
|
||||
value: "dark",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "System Preference",
|
||||
image: "/images/theme-preference.png",
|
||||
value: "system",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<div className="text-label-md">Themes</div>
|
||||
<div className="mb-3 text-sub-600">
|
||||
Choose your style or customize your theme
|
||||
</div>
|
||||
<div className="flex gap-3 max-md:flex-col">
|
||||
{themes.map((button) => (
|
||||
<div
|
||||
className={`flex flex-col flex-1 border rounded-lg bg-white-0 overflow-hidden cursor-pointer transition-colors hover:border-blue-500 ${
|
||||
theme === button.value
|
||||
? "border-blue-500 dark:text-static-black"
|
||||
: "border-stroke-soft-200"
|
||||
}`}
|
||||
key={button.id}
|
||||
onClick={() => setTheme(button.value)}
|
||||
>
|
||||
<div className="p-2.5 py-4">
|
||||
<div className="border border-stroke-soft-200 rounded-lg overflow-hidden">
|
||||
<Image
|
||||
className="w-full opacity-100"
|
||||
src={button.image}
|
||||
width={152}
|
||||
height={95}
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={`flex items-center grow gap-2.5 h-11 px-3 transition-colors ${
|
||||
theme === button.value
|
||||
? "bg-blue-50"
|
||||
: "bg-weak-50"
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`flex justify-center items-center size-4.5 rounded-full border ${
|
||||
theme === button.value
|
||||
? "border-blue-500 bg-blue-500"
|
||||
: "border-stroke-soft-200 bg-white-0"
|
||||
}`}
|
||||
>
|
||||
<svg
|
||||
className={`fill-static-white transition-opacity ${
|
||||
theme === button.value
|
||||
? "opacity-100"
|
||||
: "opacity-0"
|
||||
}`}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="9"
|
||||
height="8"
|
||||
fill="none"
|
||||
viewBox="0 0 9 8"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M8.252 2.16a.79.79 0 1 0-1.167-1.07l-3.795 4.14-1.394-1.394a.79.79 0 1 0-1.12 1.12l1.979 1.979a.79.79 0 0 0 1.143-.025l4.354-4.75z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="text-label-sm">{button.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Theme;
|
||||
@@ -0,0 +1,90 @@
|
||||
import { useState } from "react";
|
||||
import Modal from "@/components/Modal";
|
||||
import Icon from "@/components/Icon";
|
||||
import General from "./General";
|
||||
import Notifications from "./Notifications";
|
||||
import Speech from "./Speech";
|
||||
import Theme from "./Theme";
|
||||
import Security from "./Security";
|
||||
import DataControls from "./DataControls";
|
||||
|
||||
import { menu } from "./menu";
|
||||
|
||||
type Props = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const Settings = ({ open, onClose }: Props) => {
|
||||
const [activeId, setActiveId] = useState(0);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
classWrapper="flex flex-col max-w-199.5 min-h-180 max-md:min-h-[calc(100svh-6rem)]"
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
>
|
||||
<div className="mb-4.5 pb-2 border-b border-stroke-soft-200 max-md:mb-3">
|
||||
<div className="text-label-xl max-md:text-label-lg">
|
||||
Settings
|
||||
</div>
|
||||
<div className="mt-2 text-label-md text-sub-600 max-md:hidden">
|
||||
People with link will be able to view conversations and
|
||||
ideas in this board.Changes you make after creating the
|
||||
link will remain private.
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex grow max-md:block">
|
||||
<div className="flex flex-col gap-2 shrink-0 w-50 pr-4 border-r border-stroke-soft-200 max-lg:w-40 max-md:flex-row max-md:gap-4 max-md:w-auto max-md:mb-4 max-md:overflow-auto max-md:scrollbar-none max-md:-mx-4 max-md:px-4 max-md:border-0">
|
||||
{menu.map((item) => (
|
||||
<button
|
||||
className={`group flex items-center gap-2 h-10 transition-colors hover:text-strong-950 max-md:shrink-0 ${
|
||||
activeId === item.id
|
||||
? "!text-blue-500"
|
||||
: "text-sub-600"
|
||||
}`}
|
||||
onClick={() => setActiveId(item.id)}
|
||||
key={item.id}
|
||||
>
|
||||
<Icon
|
||||
className={`transition-colors group-hover:fill-strong-950 ${
|
||||
activeId === item.id
|
||||
? "!fill-blue-500"
|
||||
: "fill-sub-600"
|
||||
}`}
|
||||
name={item.icon}
|
||||
/>
|
||||
{item.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="grow pl-4 max-md:pl-0">
|
||||
{menu
|
||||
.filter((item) => item.id === activeId)
|
||||
.map((item) => (
|
||||
<div
|
||||
className="flex items-center gap-2.5 mb-8 text-label-lg max-md:hidden"
|
||||
key={item.id}
|
||||
>
|
||||
<Icon
|
||||
className="!size-7 fill-strong-950"
|
||||
name={item.icon}
|
||||
/>
|
||||
{item.name}
|
||||
</div>
|
||||
))}
|
||||
{activeId === 0 && <General />}
|
||||
{activeId === 1 && <Notifications />}
|
||||
{activeId === 2 && <Speech />}
|
||||
{activeId === 3 && <Theme />}
|
||||
{activeId === 4 && <Security />}
|
||||
{activeId === 5 && <DataControls />}
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Settings;
|
||||
@@ -0,0 +1,32 @@
|
||||
export const menu = [
|
||||
{
|
||||
id: 0,
|
||||
name: "General",
|
||||
icon: "folder",
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: "Notifications",
|
||||
icon: "bell",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Speech",
|
||||
icon: "voice",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "Theme",
|
||||
icon: "document",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "Security",
|
||||
icon: "security",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "Data Controls",
|
||||
icon: "database",
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,56 @@
|
||||
import { useState } from "react";
|
||||
import Image from "@/components/Image";
|
||||
|
||||
const tabs = [
|
||||
{ id: 0, name: "Generate Images" },
|
||||
{ id: 1, name: "3 Media" },
|
||||
];
|
||||
|
||||
const Images = ({}) => {
|
||||
const [activeTab, setActiveTab] = useState(1);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="absolute bottom-[calc(100%-0.75rem)] left-1/2 -translate-x-1/2">
|
||||
{(activeTab === 0
|
||||
? ["/images/image-5.jpg"]
|
||||
: [
|
||||
"/images/image-6.jpg",
|
||||
"/images/image-5.jpg",
|
||||
"/images/image-7.jpg",
|
||||
]
|
||||
).map((image, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="relative w-17 rounded-lg overflow-hidden first:z-3 not-first:absolute not-first:bottom-1.5 nth-2:right-1/4 nth-2:-rotate-15 nth-3:left-1/4 nth-3:rotate-15"
|
||||
>
|
||||
<Image
|
||||
className="w-full scale-105 opacity-100"
|
||||
src={image}
|
||||
width={68}
|
||||
height={94}
|
||||
alt="Image"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex justify-center mb-4.5">
|
||||
<div className="flex justify-center gap-2 p-0.25 bg-weak-50 rounded-lg border border-stroke-soft-200">
|
||||
{tabs.map((tab) => (
|
||||
<button
|
||||
className={`p-2 rounded-lg text-label-xs transition-colors ${
|
||||
activeTab === tab.id ? "bg-soft-200" : ""
|
||||
}`}
|
||||
key={tab.id}
|
||||
onClick={() => setActiveTab(tab.id)}
|
||||
>
|
||||
{tab.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Images;
|
||||
@@ -0,0 +1,68 @@
|
||||
import Modal from "@/components/Modal";
|
||||
import Button from "@/components/Button";
|
||||
import Images from "./Images";
|
||||
|
||||
type Props = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const ModalShare = ({ open, onClose }: Props) => {
|
||||
const link =
|
||||
"Https://AIchat.ai/share/board/2ca927-2028c-2028-20nc-AA2ca927-2028c-2028-20nc-AA";
|
||||
|
||||
const handleCopyCode = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(link);
|
||||
console.log("Code copied to clipboard!");
|
||||
} catch (err) {
|
||||
console.error("Failed to copy code: ", err);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal classWrapper="max-w-138" open={open} onClose={onClose}>
|
||||
<Images />
|
||||
<div className="mb-2 text-center text-label-xl">Share Board</div>
|
||||
<div className="mb-4.5 text-center text-label-md text-sub-600 max-md:text-label-sm">
|
||||
People with link will be able to view conversations and ideas in
|
||||
this board.Changes you make after creating the link will remain
|
||||
private.
|
||||
</div>
|
||||
<div className="flex items-center gap-2 p-2 pl-3 border border-stroke-soft-200 rounded-lg bg-weak-50">
|
||||
<div className="truncate">{link}</div>
|
||||
<button
|
||||
className="group flex justify-center items-center shrink-0 size-9 border border-stroke-soft-200 rounded-lg"
|
||||
onClick={handleCopyCode}
|
||||
>
|
||||
<svg
|
||||
className="size-4.5 fill-icon-soft-400 transition-colors group-hover:fill-strong-950"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="13"
|
||||
height="13"
|
||||
viewBox="0 0 13 13"
|
||||
>
|
||||
<path
|
||||
opacity=".4"
|
||||
d="M9.108 4.32l1.94.068c.523.07.964.221 1.314.571s.501.791.571 1.314C13 6.776 13 7.417 13 8.212h0v.645h0l-.068 1.94c-.07.523-.221.964-.571 1.314s-.791.501-1.314.571c-.504.068-1.145.068-1.94.068h0-.645 0c-.795 0-1.436 0-1.94-.068-.523-.07-.964-.221-1.314-.571s-.5-.791-.571-1.314c-.068-.504-.068-1.145-.068-1.94h0v-.645h0l.068-1.94c.07-.523.221-.964.571-1.314s.791-.5 1.314-.571c.504-.068 1.145-.068 1.94-.068h0 .645 0z"
|
||||
/>
|
||||
<path d="M3.698 8.161l.076-2.005c.083-.62.279-1.275.818-1.814s1.195-.735 1.814-.818c.562-.076 1.253-.076 2.005-.076h1.3c.172 0 .258 0 .31-.056s.046-.14.033-.307l-.042-.413c-.075-.558-.226-1.021-.546-1.412a2.76 2.76 0 0 0-.383-.383C8.671.539 8.178.39 7.578.319 6.995.25 6.257.25 5.325.25h-.057c-.932 0-1.67 0-2.253.069-.599.071-1.093.22-1.505.558a2.76 2.76 0 0 0-.383.383c-.338.412-.487.906-.558 1.505C.5 3.349.5 4.087.5 5.018v.057l.069 2.253c.071.599.22 1.093.558 1.505a2.76 2.76 0 0 0 .383.383c.391.321.854.471 1.412.546l.413.042c.168.012.251.019.307-.033s.056-.138.056-.31v-1.3z" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex justify-between items-center mt-4.5">
|
||||
<button
|
||||
className="text-label-md text-strong-950 transition-colors hover:text-blue-500"
|
||||
onClick={onClose}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<Button className="px-6.5" isBlack onClick={handleCopyCode}>
|
||||
Update & Copy Link
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModalShare;
|
||||
64
src/views/AgentChat/neuratalk/components/ModalView/index.tsx
Normal file
64
src/views/AgentChat/neuratalk/components/ModalView/index.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import Modal from "@/components/Modal";
|
||||
import Image from "@/components/Image";
|
||||
import Button from "@/components/Button";
|
||||
|
||||
type GalleryProps = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
image: string;
|
||||
};
|
||||
|
||||
const ModalView = ({ open, onClose, image }: GalleryProps) => (
|
||||
<Modal classWrapper="max-w-220" open={open} onClose={onClose}>
|
||||
<div className="flex items-center gap-3 mb-4.5 p-3 bg-weak-50 rounded-xl max-md:flex-wrap">
|
||||
<div className="flex justify-center items-center shrink-0 size-9 rounded-lg bg-white-0">
|
||||
<Image
|
||||
className="w-4.5 opacity-100"
|
||||
src="/images/stars.svg"
|
||||
width={18}
|
||||
height={18}
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div className="grow">
|
||||
<div className="text-label-sm">
|
||||
You Are still on the free plan
|
||||
</div>
|
||||
<div className="mt-1 text-p-xs">
|
||||
Upgrade your free plan into premium plan. Get premium Ai
|
||||
features now and generate multiple Images !
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
className="shrink-0 !h-10 px-7 text-p-xs max-md:w-full"
|
||||
isBlack
|
||||
>
|
||||
Go Premium
|
||||
</Button>
|
||||
</div>
|
||||
<div className="relative h-110 rounded-xl overflow-hidden max-md:h-60">
|
||||
<Image className="object-cover scale-101" src={image} fill alt="" />
|
||||
<Button
|
||||
className="absolute right-3.5 bottom-4.5 max-md:right-2 max-md:bottom-2 max-md:gap-0 max-md:w-10 max-md:h-10 max-md:px-0 max-md:text-0"
|
||||
isWhite
|
||||
>
|
||||
<svg
|
||||
className="!size-5 fill-strong-950"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path d="M10.84 11.042c0-.46-.373-.833-.833-.833s-.833.373-.833.833v3.75h-.495c-.146 0-.326 0-.473.018h-.003c-.105.013-.585.073-.814.544s.022.889.077.979l.002.003a4.16 4.16 0 0 0 .281.387l.02.025.881 1.043c.158.163.339.33.532.463.171.118.463.287.822.287s.651-.169.822-.287c.192-.132.373-.3.532-.463.317-.326.635-.729.881-1.043l.02-.025.281-.387.002-.003c.054-.09.306-.507.077-.979s-.709-.531-.814-.544h-.003c-.147-.018-.327-.018-.473-.018h-.486v-3.75z" />
|
||||
<path
|
||||
opacity=".4"
|
||||
d="M1.043 10.417c0-2.201 1.484-4.056 3.507-4.617.163-.045.245-.068.292-.116s.068-.13.109-.293a5.21 5.21 0 0 1 10.227.693c.023.204.034.307.086.366s.153.084.356.133c1.917.465 3.34 2.192 3.34 4.252 0 2.416-1.959 4.375-4.375 4.375h-.05c-.183 0-.274 0-.337-.042s-.106-.144-.191-.348c-.105-.251-.262-.486-.469-.687-.276-.268-.608-.445-.957-.53-.259-.063-.389-.095-.442-.163s-.053-.178-.053-.397v-2c0-1.151-.933-2.083-2.083-2.083s-2.083.933-2.083 2.083v2c0 .219 0 .329-.053.397s-.183.1-.442.163c-.349.085-.681.262-.957.53-.208.203-.384.438-.502.691-.097.208-.146.312-.214.352s-.153.032-.324.018c-2.455-.207-4.383-2.266-4.383-4.774z"
|
||||
/>
|
||||
</svg>
|
||||
Download Image
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
export default ModalView;
|
||||
@@ -0,0 +1,53 @@
|
||||
import Image from "@/components/Image";
|
||||
|
||||
const HotKeys = ({}) => (
|
||||
<div className="flex items-center gap-3 py-3.5 border-b border-stroke-soft-200 text-label-sm max-md:hidden">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div className="">
|
||||
<Image
|
||||
className="w-5 opacity-100"
|
||||
src="/images/key-square-arrow-down.svg"
|
||||
width={20}
|
||||
height={20}
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div className="rotate-180">
|
||||
<Image
|
||||
className="w-5 opacity-100"
|
||||
src="/images/key-square-arrow-down.svg"
|
||||
width={20}
|
||||
height={20}
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
To Navigate
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 mr-auto">
|
||||
<div className="rotate-180">
|
||||
<Image
|
||||
className="w-5 opacity-100"
|
||||
src="/images/key-square-enter.svg"
|
||||
width={20}
|
||||
height={20}
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
To Select
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div className="rotate-180">
|
||||
<Image
|
||||
className="w-5 opacity-100"
|
||||
src="/images/key-square-enter.svg"
|
||||
width={20}
|
||||
height={20}
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
To Close
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default HotKeys;
|
||||
@@ -0,0 +1,75 @@
|
||||
import { useState, useRef } from "react";
|
||||
import TextareaAutosize from "react-textarea-autosize";
|
||||
import { motion } from "framer-motion";
|
||||
import { useClickAway } from "react-use";
|
||||
import Icon from "@/components/Icon";
|
||||
import HotKeys from "./HotKeys";
|
||||
|
||||
import { items } from "./items";
|
||||
|
||||
const Menu = ({}) => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [message, setMessage] = useState("");
|
||||
|
||||
const ref = useRef(null);
|
||||
useClickAway(ref, () => {
|
||||
setVisible(false);
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="flex" ref={ref}>
|
||||
<button className="group" onClick={() => setVisible(!visible)}>
|
||||
<Icon
|
||||
className={`transition-colors group-hover:fill-blue-500 ${
|
||||
visible ? "fill-blue-500" : "fill-icon-soft-400"
|
||||
}`}
|
||||
name="zsh"
|
||||
/>
|
||||
</button>
|
||||
{visible && (
|
||||
<motion.div
|
||||
className="absolute -left-0.5 bottom-[calc(100%+0.75rem)] -right-0.5 px-3.5 shadow-[0_0_4.6rem_0_rgba(0,0,0,0.17)] bg-white-0 rounded-xl border border-stroke-soft-200"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{
|
||||
delay: 0.2,
|
||||
}}
|
||||
>
|
||||
<HotKeys />
|
||||
<div className="py-2">
|
||||
{items.map((item, index) => (
|
||||
<div
|
||||
className="flex items-center gap-2 px-3 py-2 rounded-xl transition-colors cursor-pointer hover:bg-weak-50"
|
||||
key={index}
|
||||
>
|
||||
<Icon
|
||||
className="shrink-0 fill-strong-950"
|
||||
name="arrow"
|
||||
/>
|
||||
<div className="grow">
|
||||
<div className="text-label-sm">
|
||||
{item.title}
|
||||
</div>
|
||||
<div className="text-soft-400">
|
||||
{item.description}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="-mx-3.5 px-3.5 py-3 bg-weak-50 rounded-b-xl border-t border-stroke-soft-200">
|
||||
<TextareaAutosize
|
||||
className="w-full text-p-md text-strong-950 outline-none resize-none placeholder:text-sub-600"
|
||||
maxRows={5}
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
placeholder="Ask a question about this answer"
|
||||
/>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default Menu;
|
||||
@@ -0,0 +1,18 @@
|
||||
export const items = [
|
||||
{
|
||||
title: "Ask",
|
||||
description: "Ask the AI anything (general chat)",
|
||||
},
|
||||
{
|
||||
title: "Summarize",
|
||||
description: "Summarize pasted text or a document",
|
||||
},
|
||||
{
|
||||
title: "/Rewrite",
|
||||
description: "Rewrite a sentence for clarity or tone",
|
||||
},
|
||||
{
|
||||
title: "/Call-api",
|
||||
description: "Call a connected external API and show the result",
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,25 @@
|
||||
import { useState } from "react";
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
const Note = ({}) => {
|
||||
const [isVisible, setIsVisible] = useState(true);
|
||||
|
||||
return isVisible ? (
|
||||
<div className="flex items-center gap-1.5 min-h-8 px-3 py-1.5 rounded-t-xl bg-blue-50 border-b border-stroke-soft-200 text-label-xs text-blue-500">
|
||||
<div className="shrink-0 text-0">
|
||||
<Icon className="!size-4 fill-blue-500" name="alert-circle" />
|
||||
</div>
|
||||
<div className="grow">
|
||||
By select a feature, it will make you goal easily to achieve
|
||||
</div>
|
||||
<button className="group" onClick={() => setIsVisible(false)}>
|
||||
<Icon
|
||||
className="!size-4 fill-strong-950 transition-colors group-hover:fill-red-500"
|
||||
name="close"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
) : null;
|
||||
};
|
||||
|
||||
export default Note;
|
||||
@@ -0,0 +1,144 @@
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import { FadeLoader } from "react-spinners";
|
||||
import { useClickAway } from "react-use";
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
import { items } from "./items";
|
||||
|
||||
const Search = ({}) => {
|
||||
const [itemStates, setItemStates] = useState<
|
||||
Array<"pending" | "loading" | "active">
|
||||
>(new Array(items.length).fill("pending"));
|
||||
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
const ref = useRef(null);
|
||||
useClickAway(ref, () => {
|
||||
setVisible(false);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!visible) {
|
||||
setItemStates(new Array(items.length).fill("pending"));
|
||||
return;
|
||||
}
|
||||
|
||||
const timeouts: NodeJS.Timeout[] = [];
|
||||
|
||||
const animateItems = () => {
|
||||
items.forEach((_, index) => {
|
||||
const loadingTimeout = setTimeout(() => {
|
||||
setItemStates((prev) => {
|
||||
const newStates = [...prev];
|
||||
newStates[index] = "loading";
|
||||
return newStates;
|
||||
});
|
||||
}, 3000 * index);
|
||||
|
||||
const activeTimeout = setTimeout(() => {
|
||||
setItemStates((prev) => {
|
||||
const newStates = [...prev];
|
||||
newStates[index] = "active";
|
||||
return newStates;
|
||||
});
|
||||
}, 3000 * index + 3000);
|
||||
|
||||
timeouts.push(loadingTimeout, activeTimeout);
|
||||
});
|
||||
};
|
||||
|
||||
animateItems();
|
||||
|
||||
// Cleanup function - очищаємо всі таймери при зміні visible або unmount
|
||||
return () => {
|
||||
timeouts.forEach((timeout) => clearTimeout(timeout));
|
||||
};
|
||||
}, [visible]);
|
||||
|
||||
return (
|
||||
<div className="flex mr-auto" ref={ref}>
|
||||
<button className="group" onClick={() => setVisible(!visible)}>
|
||||
<Icon
|
||||
className={`transition-colors group-hover:fill-blue-500 ${
|
||||
visible ? "fill-blue-500" : "fill-icon-soft-400"
|
||||
}`}
|
||||
name="ai-search"
|
||||
/>
|
||||
</button>
|
||||
{visible && (
|
||||
<motion.div
|
||||
className="absolute -left-0.5 bottom-[calc(100%+0.75rem)] -right-0.5 p-3.5 shadow-[0_0_4.6rem_0_rgba(0,0,0,0.17)] bg-white-0 rounded-xl border border-stroke-soft-200"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{
|
||||
delay: 0.2,
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center p-1.25 pr-3 rounded-xl shadow-[0_0_0.1875rem_0_rgba(0,0,0,0.14)]">
|
||||
<div className="flex items-center gap-3 mr-auto text-label-md">
|
||||
<div className="flex justify-center items-center size-9 rounded-lg bg-weak-50">
|
||||
<Icon className="fill-strong-950" name="chat" />
|
||||
</div>
|
||||
Results
|
||||
</div>
|
||||
<button className="group flex items-center gap-1.5 text-sub-600 transition-colors hover:text-strong-950">
|
||||
<Icon
|
||||
className="fill-sub-600 transition-colors group-hover:fill-strong-950"
|
||||
name="eye-hide"
|
||||
/>
|
||||
Hide Steps
|
||||
</button>
|
||||
</div>
|
||||
<div className="mt-3.5 p-3 bg-weak-50 rounded-xl">
|
||||
{items.map((item, index) => {
|
||||
const state = itemStates[index];
|
||||
const isPending = state === "pending";
|
||||
const isLoading = state === "loading";
|
||||
const isActive = state === "active";
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`flex items-center gap-2 not-last:mb-3 ${
|
||||
isPending
|
||||
? "opacity-28"
|
||||
: isLoading
|
||||
? "opacity-100 text-blue-500"
|
||||
: isActive
|
||||
? "opacity-100"
|
||||
: "opacity-28"
|
||||
}`}
|
||||
key={index}
|
||||
>
|
||||
<div className="relative shrink-0 size-[20px] text-0">
|
||||
{isLoading ? (
|
||||
<div className="absolute -top-[20px] -left-[18px] scale-40">
|
||||
<FadeLoader color="var(--blue-500)" />
|
||||
</div>
|
||||
) : (
|
||||
<Icon
|
||||
className="!size-[20px] fill-strong-950"
|
||||
name={item.icon}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-label-sm">
|
||||
{item.title}
|
||||
{isActive && (
|
||||
<Icon
|
||||
className="-my-0.5 ml-2 fill-[#1DAF61]"
|
||||
name="check"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default Search;
|
||||
@@ -0,0 +1,14 @@
|
||||
export const items = [
|
||||
{
|
||||
title: "Searching for examples and definitions",
|
||||
icon: "search",
|
||||
},
|
||||
{
|
||||
title: "Considering Sources",
|
||||
icon: "archive",
|
||||
},
|
||||
{
|
||||
title: "Writing and running query",
|
||||
icon: "quill",
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,28 @@
|
||||
import { useState } from "react";
|
||||
import Image from "@/components/Image";
|
||||
import { Switch as HeadlessSwitch } from "@headlessui/react";
|
||||
|
||||
const Speed = ({}) => {
|
||||
const [checked, setChecked] = useState(false);
|
||||
|
||||
return (
|
||||
<HeadlessSwitch
|
||||
className="relative group inline-flex w-16 h-6 p-0.75 rounded-full bg-soft-200 overflow-hidden"
|
||||
checked={checked}
|
||||
onChange={setChecked}
|
||||
>
|
||||
<Image
|
||||
className="absolute top-0 left-0 w-full opacity-100"
|
||||
src="/images/bg-toggle.png"
|
||||
width={64}
|
||||
height={24}
|
||||
alt="Speed"
|
||||
/>
|
||||
<span className="relative z-2 flex items-center justify-center w-12 h-4.5 bg-white-0 rounded-full text-p-xs text-sub-600 transition-transform group-data-[checked]:translate-x-2.5">
|
||||
Speed
|
||||
</span>
|
||||
</HeadlessSwitch>
|
||||
);
|
||||
};
|
||||
|
||||
export default Speed;
|
||||
@@ -0,0 +1,73 @@
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import TextareaAutosize from "react-textarea-autosize";
|
||||
import Icon from "@/components/Icon";
|
||||
import Image from "@/components/Image";
|
||||
import Note from "./Note";
|
||||
import Speed from "./Speed";
|
||||
import Search from "./Search";
|
||||
import Menu from "./Menu";
|
||||
|
||||
type ButtonProps = {
|
||||
className?: string;
|
||||
icon: string;
|
||||
onClick: () => void;
|
||||
};
|
||||
|
||||
const Button = ({ className, icon, onClick }: ButtonProps) => {
|
||||
return (
|
||||
<button className={`group text-0 ${className || ""}`} onClick={onClick}>
|
||||
<Icon
|
||||
className="fill-icon-soft-400 transition-colors group-hover:fill-blue-500"
|
||||
name={icon}
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
const PanelMessage = ({}) => {
|
||||
const [message, setMessage] = useState("");
|
||||
|
||||
return (
|
||||
<div className="relative z-3 mx-7.5 mb-5.5 shrink-0 rounded-xl border border-stroke-soft-200 bg-white-0 max-md:m-0">
|
||||
<Note />
|
||||
<div className="px-3 py-3.5 max-md:px-4 max-md:py-2.5">
|
||||
<div className="min-h-12 text-0 mb-3">
|
||||
<TextareaAutosize
|
||||
className="w-full h-12 text-p-md text-strong-950 outline-none resize-none placeholder:text-soft-400"
|
||||
maxRows={5}
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
placeholder="Write your message ..."
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-2.5">
|
||||
<Speed />
|
||||
<div className="w-0.25 h-5 bg-stroke-soft-200"></div>
|
||||
<Menu />
|
||||
<Button icon="link" onClick={() => {}} />
|
||||
<Search />
|
||||
<Button icon="image" onClick={() => {}} />
|
||||
<Link className="group text-0" href="/research">
|
||||
<Icon
|
||||
className="fill-icon-soft-400 transition-colors group-hover:fill-blue-500"
|
||||
name="voice"
|
||||
/>
|
||||
</Link>
|
||||
<div className="w-0.25 h-5 bg-stroke-soft-200"></div>
|
||||
<button className="group text-0" onClick={() => {}}>
|
||||
<Image
|
||||
className="w-5 opacity-100"
|
||||
src="/images/sent.svg"
|
||||
width={20}
|
||||
height={20}
|
||||
alt="Sent"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PanelMessage;
|
||||
@@ -0,0 +1,61 @@
|
||||
import { useState } from "react";
|
||||
import Chat from "@/components/Chat";
|
||||
import Question from "@/components/Question";
|
||||
import Answer from "@/components/Answer";
|
||||
import CodeEditor from "@/components/CodeEditor";
|
||||
|
||||
const PythonRunner = () => {
|
||||
const [isGenerating, setIsGenerating] = useState(false);
|
||||
const [code, setCode] = useState(`# Def
|
||||
def is_prime(n):
|
||||
# condition
|
||||
if n <= 1:
|
||||
return False
|
||||
# for
|
||||
for i in range(2, int(n**0.5) + 1):
|
||||
if n % i == 0:
|
||||
return False
|
||||
return True`);
|
||||
|
||||
const handleGenerateCode = async () => {
|
||||
setIsGenerating(true);
|
||||
setTimeout(() => {
|
||||
setCode(`# Def
|
||||
def is_prime(n):
|
||||
# condition
|
||||
if n <= 1:
|
||||
return False
|
||||
# for
|
||||
for i in range(2, int(n**0.5) + 1):
|
||||
if n % i == 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
# Test the function
|
||||
print(is_prime(17)) # True
|
||||
print(is_prime(15)) # False`);
|
||||
setIsGenerating(false);
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
return (
|
||||
<Chat>
|
||||
<Question>
|
||||
Write a Python function that checks if a number is prime.
|
||||
</Question>
|
||||
<Answer>
|
||||
<div className="mb-1">Sure here is the response:</div>
|
||||
<CodeEditor
|
||||
title="Contact Form"
|
||||
language="python"
|
||||
initialCode={code}
|
||||
onCodeChange={setCode}
|
||||
onGenerate={handleGenerateCode}
|
||||
isGenerating={isGenerating}
|
||||
/>
|
||||
</Answer>
|
||||
</Chat>
|
||||
);
|
||||
};
|
||||
|
||||
export default PythonRunner;
|
||||
28
src/views/AgentChat/neuratalk/components/Question/index.tsx
Normal file
28
src/views/AgentChat/neuratalk/components/Question/index.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import Image from "@/components/Image";
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
const Question = ({ children }: Props) => (
|
||||
<div className="flex">
|
||||
<div className="shrink-0">
|
||||
<Image
|
||||
className="size-9 opacity-100 rounded-full object-cover"
|
||||
src="/images/avatar-2.png"
|
||||
width={36}
|
||||
height={36}
|
||||
alt="Avatar"
|
||||
/>
|
||||
</div>
|
||||
<div className="w-[calc(100%-2.25rem)] pl-3">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<div className="text-label-sm">James Brown</div>
|
||||
<div className="-mb-0.75 text-p-xs text-soft-400">1min ago</div>
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Question;
|
||||
67
src/views/AgentChat/neuratalk/components/Select/index.tsx
Normal file
67
src/views/AgentChat/neuratalk/components/Select/index.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import {
|
||||
Listbox,
|
||||
ListboxButton,
|
||||
ListboxOption,
|
||||
ListboxOptions,
|
||||
} from "@headlessui/react";
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
type SelectOption = {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
|
||||
type SelectProps = {
|
||||
className?: string;
|
||||
classButton?: string;
|
||||
value: SelectOption;
|
||||
onChange: (value: SelectOption) => void;
|
||||
options: SelectOption[];
|
||||
};
|
||||
|
||||
const Select = ({
|
||||
className,
|
||||
classButton,
|
||||
value,
|
||||
onChange,
|
||||
options,
|
||||
}: SelectProps) => {
|
||||
return (
|
||||
<Listbox
|
||||
className={`${className || ""}`}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
as="div"
|
||||
>
|
||||
<ListboxButton
|
||||
className={`group flex justify-between items-center w-full h-10 pl-4 pr-3 border border-stroke-soft-200 rounded-xl text-label-sm text-sub-600 fill-sub-600 transition-all outline-0 data-[hover]:border-stroke-sub-300 data-[hover]:text-strong-950 data-[hover]:fill-strong-950 data-[open]:fill-strong-950 data-[open]:text-strong-950 data-[open]:border-stroke-sub-300 ${
|
||||
classButton || ""
|
||||
}`}
|
||||
>
|
||||
{value.name}
|
||||
<Icon
|
||||
className="shrink-0 ml-2 fill-inherit transition-transform group-[[data-open]]:rotate-180"
|
||||
name="chevron"
|
||||
/>
|
||||
</ListboxButton>
|
||||
<ListboxOptions
|
||||
className="z-100 [--anchor-gap:0.25rem] w-[var(--button-width)] bg-white-0 border border-stroke-soft-200 shadow-lg rounded-xl overflow-hidden origin-top transition duration-200 ease-out outline-none data-[closed]:scale-95 data-[closed]:opacity-0"
|
||||
anchor="bottom"
|
||||
transition
|
||||
modal={false}
|
||||
>
|
||||
{options.map((option) => (
|
||||
<ListboxOption
|
||||
className="group relative px-4 py-2 truncate text-label-sm text-strong-950 cursor-pointer transition-colors data-[focus]:bg-weak-50 data-[selected]:bg-weak-50 not-last:mb-0.25"
|
||||
key={option.id}
|
||||
value={option}
|
||||
>
|
||||
{option.name}
|
||||
</ListboxOption>
|
||||
))}
|
||||
</ListboxOptions>
|
||||
</Listbox>
|
||||
);
|
||||
};
|
||||
|
||||
export default Select;
|
||||
@@ -0,0 +1,24 @@
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
icon: string;
|
||||
onClick: () => void;
|
||||
};
|
||||
|
||||
const Button = ({ title, icon, onClick }: Props) => {
|
||||
return (
|
||||
<button
|
||||
className="group relative flex items-center shrink-0 gap-2 w-full h-10 px-3 text-label-sm transition-colors text-sub-600 hover:text-strong-950 not-last:mb-2"
|
||||
onClick={onClick}
|
||||
>
|
||||
<Icon
|
||||
className="fill-sub-600 transition-colors group-hover:fill-strong-950"
|
||||
name={icon}
|
||||
/>
|
||||
{title}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default Button;
|
||||
@@ -0,0 +1,34 @@
|
||||
export const folders = [
|
||||
{
|
||||
id: 0,
|
||||
name: "Business plan",
|
||||
items: [
|
||||
{
|
||||
id: 0,
|
||||
name: "Buiness analysis",
|
||||
type: "analytic",
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: "Journey map",
|
||||
type: "voice",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: "Images Ideas",
|
||||
items: [
|
||||
{
|
||||
id: 0,
|
||||
name: "Images Generations",
|
||||
type: "image",
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: "3 ideas for gallery",
|
||||
type: "voice",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,89 @@
|
||||
import { useState } from "react";
|
||||
import AnimateHeight from "react-animate-height";
|
||||
import Icon from "@/components/Icon";
|
||||
import Actions from "@/components/Actions";
|
||||
|
||||
const actions = [
|
||||
{ name: "Rename", onClick: () => {} },
|
||||
{ name: "Delete", onClick: () => {} },
|
||||
{ name: "Copy", onClick: () => {} },
|
||||
];
|
||||
|
||||
import { folders } from "./folders";
|
||||
|
||||
const Folders = ({}) => {
|
||||
const [active, setActive] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="mb-2">
|
||||
<div
|
||||
className={`group flex items-center gap-2 h-10 px-3 text-label-sm transition-colors cursor-pointer hover:text-strong-950 ${
|
||||
active ? "!text-blue-500" : "text-sub-600"
|
||||
}`}
|
||||
onClick={() => setActive(!active)}
|
||||
>
|
||||
<Icon
|
||||
className={`group-hover:fill-strong-950 transition-colors ${
|
||||
active ? "!fill-blue-500" : "fill-sub-600"
|
||||
}`}
|
||||
name="folder"
|
||||
/>
|
||||
Folders
|
||||
<Icon
|
||||
className={`ml-auto transition-transform ${
|
||||
active ? "rotate-180 fill-blue-500" : "fill-strong-950"
|
||||
}`}
|
||||
name="chevron"
|
||||
/>
|
||||
</div>
|
||||
<AnimateHeight duration={500} height={active ? "auto" : 0}>
|
||||
<div className="pl-5">
|
||||
{folders.map((folder) => (
|
||||
<div className="" key={folder.id}>
|
||||
<div className="flex items-center gap-2 h-9 text-sub-600">
|
||||
<Icon
|
||||
className="fill-icon-sub-600"
|
||||
name="folders"
|
||||
/>
|
||||
{folder.name}
|
||||
</div>
|
||||
<div className="relative pt-2 pl-5 before:absolute before:top-0 before:left-0.5 before:bottom-4 before:w-0.25 before:bg-stroke-soft-200">
|
||||
{folder.items.map((item) => (
|
||||
<div
|
||||
className="flex items-center h-8 gap-2 text-sub-600 [&_svg]:fill-icon-sub-600 not-last:mb-2 max-md:pr-3"
|
||||
key={item.id}
|
||||
>
|
||||
{item.type === "analytic" ? (
|
||||
<div className="flex items-center">
|
||||
<Icon name="template" />
|
||||
<Icon
|
||||
className="!size-3"
|
||||
name="plus"
|
||||
/>
|
||||
<Icon name="analytic" />
|
||||
</div>
|
||||
) : item.type === "image" ? (
|
||||
<Icon name="image-1" />
|
||||
) : (
|
||||
<Icon name="voice" />
|
||||
)}
|
||||
<div className="truncate transition-colors cursor-pointer hover:text-strong-950">
|
||||
{item.name}
|
||||
</div>
|
||||
<Actions
|
||||
className="ml-auto"
|
||||
classNameButton="rotate-90"
|
||||
items={actions}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</AnimateHeight>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Folders;
|
||||
@@ -0,0 +1,31 @@
|
||||
import { useState } from "react";
|
||||
import Field from "@/components/Field";
|
||||
import Button from "@/components/Button";
|
||||
|
||||
const InvitePeople = ({}) => {
|
||||
const [email, setEmail] = useState("");
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-2 text-center text-h5">Invite people</div>
|
||||
<div className="mb-4 text-p-md text-center text-sub-600">
|
||||
Send an invite to your teammates and start collaborating
|
||||
together.
|
||||
</div>
|
||||
<Field
|
||||
className="mb-6"
|
||||
label="Email"
|
||||
placeholder="Enter email"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<Button className="w-full h-12" isBlack icon="plus">
|
||||
Invite
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default InvitePeople;
|
||||
@@ -0,0 +1,50 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Listbox,
|
||||
ListboxButton,
|
||||
ListboxOption,
|
||||
ListboxOptions,
|
||||
} from "@headlessui/react";
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
const options = [
|
||||
{ id: 1, name: "My Workspace" },
|
||||
{ id: 2, name: "Team Workspace" },
|
||||
{ id: 3, name: "Sandbox" },
|
||||
];
|
||||
|
||||
const MyWorkspace = ({}) => {
|
||||
const [value, setValue] = useState(options[0]);
|
||||
return (
|
||||
<Listbox value={value} onChange={setValue}>
|
||||
<ListboxButton className="group flex items-center gap-2 w-full p-1.25 pr-3 rounded-xl cursor-pointer outline-0 max-lg:w-[calc(100%-1.75rem)] dark:shadow-[0_0_0.1875rem_0_rgba(255,255,255,0.16)]">
|
||||
<div className="flex justify-center items-center bg-weak-50 rounded-lg size-8.75 font-medium">
|
||||
P
|
||||
</div>
|
||||
<div className="truncate text-label-sm">{value.name}</div>
|
||||
<Icon
|
||||
className="shrink-0 ml-auto fill-strong-950 transition-transform group-[[data-open]]:rotate-180"
|
||||
name="chevron"
|
||||
/>
|
||||
</ListboxButton>
|
||||
<ListboxOptions
|
||||
className="z-100 [--anchor-gap:0.25rem] w-[var(--button-width)] bg-white-0 border border-stroke-soft-200 shadow-lg rounded-xl origin-top overflow-hidden transition duration-200 ease-out outline-none data-[closed]:scale-95 data-[closed]:opacity-0"
|
||||
anchor="bottom"
|
||||
transition
|
||||
modal={false}
|
||||
>
|
||||
{options.map((option) => (
|
||||
<ListboxOption
|
||||
className="group relative px-4 py-2 truncate text-label-sm text-strong-950 cursor-pointer transition-colors data-[focus]:bg-weak-50 data-[selected]:bg-weak-50 not-last:mb-0.25"
|
||||
key={option.id}
|
||||
value={option}
|
||||
>
|
||||
{option.name}
|
||||
</ListboxOption>
|
||||
))}
|
||||
</ListboxOptions>
|
||||
</Listbox>
|
||||
);
|
||||
};
|
||||
|
||||
export default MyWorkspace;
|
||||
@@ -0,0 +1,38 @@
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
type Props = {
|
||||
href: string;
|
||||
title: string;
|
||||
icon: string;
|
||||
};
|
||||
|
||||
const NavLink = ({ href, title, icon }: Props) => {
|
||||
const pathname = usePathname();
|
||||
const isActive = pathname === href;
|
||||
|
||||
return (
|
||||
<Link
|
||||
className={`group relative flex items-center shrink-0 gap-2 h-10 px-3 text-label-sm transition-colors hover:text-strong-950 not-last:mb-2 ${
|
||||
isActive ? "!text-blue-500" : "text-sub-600"
|
||||
}`}
|
||||
href={href}
|
||||
>
|
||||
<Icon
|
||||
className={`transition-colors group-hover:fill-strong-950 ${
|
||||
isActive ? "!fill-blue-500" : "fill-sub-600"
|
||||
}`}
|
||||
name={icon}
|
||||
/>
|
||||
<div className="">{title}</div>
|
||||
{title === "Templates" && (
|
||||
<div className="ml-auto px-2 py-0.5 bg-strong-950 rounded-md text-[0.6875rem] leading-[1rem] text-white-0">
|
||||
Beta
|
||||
</div>
|
||||
)}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default NavLink;
|
||||
@@ -0,0 +1,53 @@
|
||||
import { useState } from "react";
|
||||
import Image from "@/components/Image";
|
||||
import Icon from "@/components/Icon";
|
||||
import ModalPlan from "@/components/ModalPlan";
|
||||
|
||||
const Upgrade = ({}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mt-8 max-md:mt-6">
|
||||
<div className="">
|
||||
<Image
|
||||
className="w-full opacity-100 dark:hidden"
|
||||
src="/images/upgrade-pic-light.png"
|
||||
width={220}
|
||||
height={140}
|
||||
alt="Upgrade"
|
||||
priority
|
||||
/>
|
||||
<Image
|
||||
className="!hidden w-full opacity-100 dark:!block"
|
||||
src="/images/upgrade-pic-dark.png"
|
||||
width={220}
|
||||
height={140}
|
||||
alt="Upgrade"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
<div className="p-3 rounded-b-xl dark:shadow-[inset_0_0_0.1875rem_0_rgba(255,255,255,0.16)]">
|
||||
<div
|
||||
className="group flex items-center gap-1 text-label-md cursor-pointer"
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
Upgrade to Premium{" "}
|
||||
<Icon
|
||||
className="fill-blue-500 transition-transform group-hover:translate-x-0.5"
|
||||
name="arrow"
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-0.75 text-label-xs text-sub-600">
|
||||
Want to reach{" "}
|
||||
<span className="text-strong-950">more features</span>{" "}
|
||||
and grow much bigger?
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ModalPlan open={open} onClose={() => setOpen(false)} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Upgrade;
|
||||
@@ -0,0 +1,30 @@
|
||||
import Link from "next/link";
|
||||
import Image from "@/components/Image";
|
||||
import Icon from "@/components/Icon";
|
||||
|
||||
const User = ({}) => (
|
||||
<Link
|
||||
className="group flex items-center shrink-0 gap-2 mx-5 pt-3 px-3 pb-5 border-t border-stroke-soft-200"
|
||||
href="/auth/sign-in"
|
||||
>
|
||||
<div className="">
|
||||
<Image
|
||||
className="size-10 rounded-full opacity-100"
|
||||
src="/images/avatar-1.png"
|
||||
width={40}
|
||||
height={40}
|
||||
alt="User"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-label-sm">
|
||||
<div className="">Emillia Caitin</div>
|
||||
<div className="text-sub-600">hey@agency.com</div>
|
||||
</div>
|
||||
<Icon
|
||||
className="ml-auto fill-sub-600 -rotate-90 transition-transform group-hover:translate-x-0.5"
|
||||
name="chevron"
|
||||
/>
|
||||
</Link>
|
||||
);
|
||||
|
||||
export default User;
|
||||
131
src/views/AgentChat/neuratalk/components/Sidebar/index.tsx
Normal file
131
src/views/AgentChat/neuratalk/components/Sidebar/index.tsx
Normal file
@@ -0,0 +1,131 @@
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import Icon from "@/components/Icon";
|
||||
import Modal from "@/components/Modal";
|
||||
import ModalShare from "@/components/ModalShare";
|
||||
import ModalSettings from "@/components/ModalSettings";
|
||||
import NavLink from "./NavLink";
|
||||
import MyWorkspace from "./MyWorkspace";
|
||||
import Upgrade from "./Upgrade";
|
||||
import Button from "./Button";
|
||||
import User from "./User";
|
||||
import Folders from "./Folders";
|
||||
import InvitePeople from "./InvitePeople";
|
||||
|
||||
type Props = {
|
||||
visible: boolean;
|
||||
onClose: () => void;
|
||||
onClickNewChat: () => void;
|
||||
};
|
||||
|
||||
const Sidebar = ({ visible, onClose, onClickNewChat }: Props) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [openModalShare, setOpenModalShare] = useState(false);
|
||||
const [openModalInvite, setOpenModalInvite] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={`fixed top-5 left-5 bottom-5 flex flex-col w-80 bg-white-0 rounded-3xl shadow-[0_0_1.25rem_0_rgba(0,0,0,0.03)] max-3xl:w-65 max-lg:top-0 max-lg:left-0 max-lg:bottom-0 max-lg:z-20 max-lg:w-75 max-lg:shadow-2xl max-lg:rounded-none max-lg:transition-transform max-md:w-full max-md:p-4 ${
|
||||
visible
|
||||
? "max-lg:translate-x-0"
|
||||
: "max-lg:-translate-x-full"
|
||||
}`}
|
||||
>
|
||||
<div className="grow overflow-auto scrollbar-none p-5">
|
||||
<div className="flex items-center gap-2 mb-5 max-lg:pr-2 max-md:mb-3">
|
||||
<MyWorkspace />
|
||||
<button
|
||||
className="group hidden ml-4 max-lg:flex"
|
||||
onClick={onClose}
|
||||
>
|
||||
<Icon
|
||||
className="text-label-sm fill-strong-950 transition-colors group-hover:fill-blue-500"
|
||||
name="close"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<Link
|
||||
className="group relative flex items-center shrink-0 gap-2 h-10 px-3 rounded-xl text-label-sm transition-colors hover:text-blue-500 not-last:mb-2 dark:shadow-[0_0_0.1875rem_0_rgba(255,255,255,0.16)]"
|
||||
href="/"
|
||||
onClick={onClickNewChat}
|
||||
>
|
||||
<Icon
|
||||
className="fill-strong-950 transition-colors group-hover:fill-blue-500"
|
||||
name="chat"
|
||||
/>
|
||||
Chat With AI
|
||||
</Link>
|
||||
<div className="mb-auto">
|
||||
<div className="mb-2 text-label-xs text-soft-400">
|
||||
Today
|
||||
</div>
|
||||
<Link
|
||||
className="flex items-center gap-2 h-10 mb-2 px-3 rounded-xl bg-weak-50 dark:shadow-[0_0_0.1875rem_0_rgba(255,255,255,0.16)]"
|
||||
href="/write-copy"
|
||||
>
|
||||
<Icon className="fill-strong-950" name="document" />
|
||||
<div className="text-label-sm">
|
||||
mental health problems
|
||||
</div>
|
||||
</Link>
|
||||
<Folders />
|
||||
<NavLink
|
||||
href="/documents"
|
||||
title="Documents"
|
||||
icon="document"
|
||||
/>
|
||||
<Button
|
||||
title="Shared With Me"
|
||||
icon="share"
|
||||
onClick={() => setOpenModalShare(true)}
|
||||
/>
|
||||
<NavLink
|
||||
href="/templates"
|
||||
title="Templates"
|
||||
icon="template"
|
||||
/>
|
||||
<NavLink
|
||||
href="/history"
|
||||
title="History"
|
||||
icon="history"
|
||||
/>
|
||||
</div>
|
||||
<Upgrade />
|
||||
<div className="mt-7 max-md:mt-4">
|
||||
<Button
|
||||
title="Feedback"
|
||||
icon="comment"
|
||||
onClick={() => {}}
|
||||
/>
|
||||
<Button
|
||||
title="Invite People"
|
||||
icon="add-team"
|
||||
onClick={() => setOpenModalInvite(true)}
|
||||
/>
|
||||
<Button
|
||||
title="Settings"
|
||||
icon="settings"
|
||||
onClick={() => setOpen(true)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<User />
|
||||
</div>
|
||||
<ModalSettings open={open} onClose={() => setOpen(false)} />
|
||||
<ModalShare
|
||||
open={openModalShare}
|
||||
onClose={() => setOpenModalShare(false)}
|
||||
/>
|
||||
<Modal
|
||||
classWrapper="max-w-100"
|
||||
open={openModalInvite}
|
||||
onClose={() => setOpenModalInvite(false)}
|
||||
>
|
||||
<InvitePeople />
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Sidebar;
|
||||
28
src/views/AgentChat/neuratalk/components/SoloImage/index.tsx
Normal file
28
src/views/AgentChat/neuratalk/components/SoloImage/index.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { useState } from "react";
|
||||
import Image from "@/components/Image";
|
||||
import ModalView from "@/components/ModalView";
|
||||
|
||||
const SoloImage = ({}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="cursor-pointer" onClick={() => setOpen(true)}>
|
||||
<Image
|
||||
className="w-full rounded-xl"
|
||||
src="/images/image-1.jpg"
|
||||
width={731}
|
||||
height={418}
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<ModalView
|
||||
open={open}
|
||||
onClose={() => setOpen(false)}
|
||||
image="/images/image-1.jpg"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SoloImage;
|
||||
28
src/views/AgentChat/neuratalk/components/Switch/index.tsx
Normal file
28
src/views/AgentChat/neuratalk/components/Switch/index.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Switch as HeadlessSwitch } from "@headlessui/react";
|
||||
|
||||
type SwitchProps = {
|
||||
className?: string;
|
||||
checked: boolean;
|
||||
onChange: (checked: boolean) => void;
|
||||
isSmall?: boolean;
|
||||
};
|
||||
|
||||
const Switch = ({ className, checked, onChange, isSmall }: SwitchProps) => (
|
||||
<HeadlessSwitch
|
||||
className={`group shrink-0 inline-flex p-0.5 rounded-full bg-soft-200 data-[checked]:!bg-blue-500 ${
|
||||
isSmall ? "w-7 h-4" : "w-9 h-5"
|
||||
} ${className || ""}`}
|
||||
checked={checked}
|
||||
onChange={onChange}
|
||||
>
|
||||
<span
|
||||
className={`relative rounded-full bg-white-0 shadow-[0_0.0625rem_0.125rem_0_rgba(16,24,40,0.06),0_0.0625rem_0.125rem_0_rgba(16,24,40,0.10)] transition-transform ${
|
||||
isSmall
|
||||
? "size-3 group-data-[checked]:translate-x-3 before:absolute before:inset-1 before:rounded-full before:transition-colors before:bg-soft-200 group-data-[checked]:before:bg-blue-500 dark:bg-static-white"
|
||||
: "size-4 group-data-[checked]:translate-x-4"
|
||||
}`}
|
||||
/>
|
||||
</HeadlessSwitch>
|
||||
);
|
||||
|
||||
export default Switch;
|
||||
44
src/views/AgentChat/neuratalk/components/Tabs/index.tsx
Normal file
44
src/views/AgentChat/neuratalk/components/Tabs/index.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
type TabItem = {
|
||||
id: number;
|
||||
name: string;
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
items: TabItem[];
|
||||
value: TabItem;
|
||||
setValue: (value: TabItem) => void;
|
||||
};
|
||||
|
||||
const Tabs = ({ className, items, value, setValue }: Props) => {
|
||||
return (
|
||||
<div className={`p-1 bg-weak-50 rounded-full ${className || ""}`}>
|
||||
<div className="relative flex">
|
||||
<div
|
||||
className={`absolute top-0 left-0 bottom-0 rounded-full bg-white-0 transition-transform ${
|
||||
items.length === 3 ? "w-1/3" : "w-1/2"
|
||||
} ${value.id === items[1].id ? "translate-x-full" : ""}`}
|
||||
></div>
|
||||
{items.map((item) => (
|
||||
<button
|
||||
className={`relative z-1 flex-1 h-9 text-label-sm transition-colors hover:text-strong-950 ${
|
||||
value.id === item.id
|
||||
? "text-strong-950"
|
||||
: "text-sub-600"
|
||||
}`}
|
||||
key={item.id}
|
||||
onClick={() => {
|
||||
setValue(item);
|
||||
item.onClick?.();
|
||||
}}
|
||||
>
|
||||
{item.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Tabs;
|
||||
3
src/views/AgentChat/neuratalk/components/Test/index.tsx
Normal file
3
src/views/AgentChat/neuratalk/components/Test/index.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
const Test = ({}) => <div className=""></div>;
|
||||
|
||||
export default Test;
|
||||
@@ -0,0 +1,60 @@
|
||||
import Icon from "@/components/Icon";
|
||||
import Switch from "@/components/Switch";
|
||||
|
||||
type Props = {
|
||||
group: {
|
||||
id: string;
|
||||
title: string;
|
||||
items: {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
icon: string;
|
||||
}[];
|
||||
};
|
||||
activeId: string | null;
|
||||
setActiveId: (id: string | null) => void;
|
||||
};
|
||||
|
||||
const Group = ({ group, activeId, setActiveId }: Props) => {
|
||||
return (
|
||||
<div
|
||||
className="not-last:mb-5 not-last:pb-5 not-last:border-b border-stroke-soft-200"
|
||||
key={group.id}
|
||||
>
|
||||
<div className="mb-2 py-1 text-label-xs text-soft-400 max-md:mb-1">
|
||||
{group.title}
|
||||
</div>
|
||||
<div className="">
|
||||
{group.items.map((item) => (
|
||||
<div
|
||||
className="py-2 not-last:mb-1 max-md:py-1.5"
|
||||
key={item.id}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Icon
|
||||
className="fill-strong-950"
|
||||
name={item.icon}
|
||||
/>
|
||||
<div className="text-label-md">{item.title}</div>
|
||||
<Switch
|
||||
className="ml-auto"
|
||||
checked={activeId === item.id}
|
||||
onChange={() => {
|
||||
setActiveId(
|
||||
activeId === item.id ? null : item.id
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-0.5 text-sub-600">
|
||||
{item.description}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Group;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user