Initial commit

This commit is contained in:
2025-10-11 11:55:25 +08:00
parent 467dad8449
commit 8107dee8d3
2879 changed files with 610575 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
type ArrowsProps = {
className?: string;
prevClassName?: string;
nextClassName?: string;
onPrev?: () => void;
onNext?: () => void;
};
const Arrows = ({
className,
prevClassName,
nextClassName,
onPrev,
onNext,
}: ArrowsProps) => (
<div className={`splide__arrows relative z-10 flex ${className || ""}`}>
<button
className={`splide__arrow splide__arrow--prev ${
prevClassName || ""
}`}
onClick={onPrev}
>
<svg className="w-4 h-4 fill-n-4">
<path d="M8.707 1.707a1 1 0 0 0 0-1.414 1 1 0 0 0-1.414 0l-7 7a1 1 0 0 0 0 1.414l7 7a1 1 0 0 0 1.414-1.414L3.414 9H15a1 1 0 1 0 0-2H3.414l5.293-5.293z" />
</svg>
</button>
<button
className={`splide__arrow splide__arrow--next ${
nextClassName || ""
}`}
onClick={onNext}
>
<svg className="w-4 h-4 fill-n-4">
<path d="M7.293 1.707a1 1 0 0 1 0-1.414 1 1 0 0 1 1.414 0l7 7a1 1 0 0 1 0 1.414l-7 7a1 1 0 0 1-1.414-1.414L12.586 9H1a1 1 0 1 1 0-2h11.586L7.293 1.707z" />
</svg>
</button>
</div>
);
export default Arrows;

View File

@@ -0,0 +1,40 @@
import { Link } from "react-router-dom";
import { svgs } from "./svgs";
const Button = ({
className,
href,
onClick,
children,
px,
white,
}) => {
const classes = `button relative inline-flex items-center justify-center h-11 ${
px || "px-7"
} ${white ? "text-n-8" : "text-n-1"} transition-colors hover:text-color-1 ${
className || ""
}`;
const spanClasses = `relative z-10`;
return href ? (
href.startsWith("mailto:") ? (
<a href={href} className={classes}>
<span className={spanClasses}>{children}</span>
{svgs(white)}
</a>
) : (
<Link href={href} className={classes}>
<span className={spanClasses}>{children}</span>
{svgs(white)}
</Link>
)
) : (
<button className={classes} onClick={onClick}>
<span className={spanClasses}>{children}</span>
{svgs(white)}
</button>
);
};
export default Button;

View File

@@ -0,0 +1,58 @@
export const svgs = (white: boolean | undefined) => (
<>
<svg
className="absolute top-0 left-0"
width="21"
height="44"
viewBox="0 0 21 44"
>
<path
fill={white ? "white" : "none"}
stroke={white ? "white" : "url(#btn-left)"}
strokeWidth="2"
d="M21,43.00005 L8.11111,43.00005 C4.18375,43.00005 1,39.58105 1,35.36365 L1,8.63637 C1,4.41892 4.18375,1 8.11111,1 L21,1"
/>
</svg>
<svg
className="absolute top-0 left-[1.3125rem] w-[calc(100%-2.625rem)]"
height="44"
viewBox="0 0 100 44"
preserveAspectRatio="none"
fill={white ? "white" : "none"}
>
{white ? (
<polygon
fill="white"
fillRule="nonzero"
points="100 0 100 44 0 44 0 0"
/>
) : (
<>
<polygon
fill="url(#btn-top)"
fillRule="nonzero"
points="100 42 100 44 0 44 0 42"
/>
<polygon
fill="url(#btn-bottom)"
fillRule="nonzero"
points="100 0 100 2 0 2 0 0"
/>
</>
)}
</svg>
<svg
className="absolute top-0 right-0"
width="21"
height="44"
viewBox="0 0 21 44"
>
<path
fill={white ? "white" : "none"}
stroke={white ? "white" : "url(#btn-right)"}
strokeWidth="2"
d="M0,43.00005 L5.028,43.00005 L12.24,43.00005 C16.526,43.00005 20,39.58105 20,35.36365 L20,16.85855 C20,14.59295 18.978,12.44425 17.209,10.99335 L7.187,2.77111 C5.792,1.62675 4.034,1 2.217,1 L0,1"
/>
</svg>
</>
);

View File

@@ -0,0 +1,52 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import React from 'react';
import FullCalendar from '@fullcalendar/react'; // must go before plugins
import dayGridPlugin from '@fullcalendar/daygrid'; // a plugin!
import interactionPlugin from '@fullcalendar/interaction'; // needed for dayClick
function EventCalendar(props) {
const {
calendarData,
initialDate,
onDateClick,
onEventClick,
contentHeight = 'auto',
height = '100%',
dayMaxEvents = true,
headerToolbar = false,
} = props;
return (
<FullCalendar
plugins={[dayGridPlugin, interactionPlugin]}
headerToolbar={headerToolbar}
initialView='dayGridMonth'
initialDate={initialDate}
contentHeight={contentHeight}
height={height}
dayMaxEvents={dayMaxEvents}
events={calendarData}
editable={true}
dateClick={onDateClick}
eventClick={onEventClick}
/>
);
}
export default EventCalendar;

View File

@@ -0,0 +1,29 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import { Box, useStyleConfig } from "@chakra-ui/react";
function Card(props) {
const { variant, children, ...rest } = props;
const styles = useStyleConfig("Card", { variant });
return (
<Box __css={styles} {...rest}>
{children}
</Box>
);
}
export default Card;

View File

@@ -0,0 +1,29 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import { Box, useStyleConfig } from "@chakra-ui/react";
function CardBody(props) {
const { variant, children, ...rest } = props;
const styles = useStyleConfig("CardBody", { variant });
return (
<Box __css={styles} {...rest}>
{children}
</Box>
);
}
export default CardBody;

View File

@@ -0,0 +1,29 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import { Box, useStyleConfig } from "@chakra-ui/react";
function CardHeader(props) {
const { variant, children, ...rest } = props;
const styles = useStyleConfig("CardHeader", { variant });
return (
<Box __css={styles} {...rest}>
{children}
</Box>
);
}
export default CardHeader;

View File

@@ -0,0 +1,50 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import React, { Component } from "react";
import Chart from "react-apexcharts";
class BarChart extends Component {
constructor(props) {
super(props);
this.state = {
chartData: [],
chartOptions: {},
};
}
componentDidMount() {
this.setState({
chartData: this.props.chartData,
chartOptions: this.props.chartOptions,
});
}
render() {
return (
<Chart
options={this.state.chartOptions}
series={this.state.chartData}
type="bar"
width="100%"
height="100%"
/>
);
}
}
export default BarChart;

View File

@@ -0,0 +1,50 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import React, { Component } from "react";
import Chart from "react-apexcharts";
class BubbleChart extends Component {
constructor(props) {
super(props);
this.state = {
chartData: [],
chartOptions: {},
};
}
componentDidMount() {
this.setState({
chartData: this.props.chartData,
chartOptions: this.props.chartOptions,
});
}
render() {
return (
<Chart
options={this.state.chartOptions}
series={this.state.chartData}
type="bubble"
width="100%"
height="100%"
/>
);
}
}
export default BubbleChart;

View File

@@ -0,0 +1,51 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import React from "react";
import ReactApexChart from "react-apexcharts";
class DonutChart extends React.Component {
constructor(props) {
super(props);
this.state = {
chartData: [],
chartOptions: {},
};
}
componentDidMount() {
this.setState({
chartData: this.props.chartData,
chartOptions: this.props.chartOptions,
});
}
render() {
return (
<ReactApexChart
options={this.state.chartOptions}
series={this.state.chartData}
type="donut"
width="100%"
height="100%"
/>
);
}
}
export default DonutChart;

View File

@@ -0,0 +1,50 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import React, { Component } from "react";
import Chart from "react-apexcharts";
class LineBarChart extends Component {
constructor(props) {
super(props);
this.state = {
chartData: [],
chartOptions: {},
};
}
componentDidMount() {
this.setState({
chartData: this.props.chartData,
chartOptions: this.props.chartOptions,
});
}
render() {
return (
<Chart
options={this.state.chartOptions}
series={this.state.chartData}
type="line"
width="100%"
height="100%"
/>
);
}
}
export default LineBarChart;

View File

@@ -0,0 +1,51 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import React from "react";
import ReactApexChart from "react-apexcharts";
class LineChart extends React.Component {
constructor(props) {
super(props);
this.state = {
chartData: [],
chartOptions: {},
};
}
componentDidMount() {
this.setState({
chartData: this.props.chartData,
chartOptions: this.props.chartOptions,
});
}
render() {
return (
<ReactApexChart
options={this.state.chartOptions}
series={this.state.chartData}
type="area"
width="100%"
height="100%"
/>
);
}
}
export default LineChart;

View File

@@ -0,0 +1,51 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import React from "react";
import ReactApexChart from "react-apexcharts";
class PieChart extends React.Component {
constructor(props) {
super(props);
this.state = {
chartData: [],
chartOptions: {},
};
}
componentDidMount() {
this.setState({
chartData: this.props.chartData,
chartOptions: this.props.chartOptions,
});
}
render() {
return (
<ReactApexChart
options={this.state.chartOptions}
series={this.state.chartData}
type="pie"
width="100%"
height="100%"
/>
);
}
}
export default PieChart;

View File

@@ -0,0 +1,51 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import React from "react";
import ReactApexChart from "react-apexcharts";
class PolarChart extends React.Component {
constructor(props) {
super(props);
this.state = {
chartData: [],
chartOptions: {},
};
}
componentDidMount() {
this.setState({
chartData: this.props.chartData,
chartOptions: this.props.chartOptions,
});
}
render() {
return (
<ReactApexChart
options={this.state.chartOptions}
series={this.state.chartData}
type="polarArea"
width="100%"
height="100%"
/>
);
}
}
export default PolarChart;

View File

@@ -0,0 +1,51 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import React from "react";
import ReactApexChart from "react-apexcharts";
class RadarChart extends React.Component {
constructor(props) {
super(props);
this.state = {
chartData: [],
chartOptions: {},
};
}
componentDidMount() {
this.setState({
chartData: this.props.chartData,
chartOptions: this.props.chartOptions,
});
}
render() {
return (
<ReactApexChart
options={this.state.chartOptions}
series={this.state.chartData}
type="radar"
width="100%"
height="100%"
/>
);
}
}
export default RadarChart;

View File

@@ -0,0 +1,202 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
// Chakra Imports
// Chakra Imports
import {
Box,
Button,
Drawer,
DrawerBody,
DrawerCloseButton,
DrawerContent,
DrawerHeader,
Flex,
Icon,
Link,
Switch,
Text,
useColorMode,
useColorModeValue,
} from "@chakra-ui/react";
import GitHubButton from "react-github-btn";
import { HSeparator } from "components/Separator/Separator";
import PropTypes from "prop-types";
import React, { useState } from "react";
import { FaTwitter, FaFacebook } from "react-icons/fa";
export default function Configurator(props) {
const {
sidebarVariant,
setSidebarVariant,
secondary,
isOpen,
onClose,
fixed,
...rest
} = props;
const [switched, setSwitched] = useState(props.isChecked);
const { colorMode, toggleColorMode } = useColorMode();
let bgButton = useColorModeValue(
"linear-gradient(81.62deg, #313860 2.25%, #151928 79.87%)",
"white"
);
let colorButton = useColorModeValue("white", "gray.700");
const secondaryButtonBg = useColorModeValue("white", "transparent");
const secondaryButtonBorder = useColorModeValue("gray.700", "white");
const secondaryButtonColor = useColorModeValue("gray.700", "white");
const bgDrawer = useColorModeValue("white", "navy.800");
const settingsRef = React.useRef();
return (
<>
<Drawer
isOpen={props.isOpen}
onClose={props.onClose}
placement={document.documentElement.dir === "rtl" ? "left" : "right"}
finalFocusRef={settingsRef}
blockScrollOnMount={false}>
<DrawerContent bg={bgDrawer}>
<DrawerHeader pt='24px' px='24px'>
<DrawerCloseButton />
<Text fontSize='xl' fontWeight='bold' mt='16px'>
Argon Chakra Configurator
</Text>
<Text fontSize='md' mb='16px'>
See your dashboard options.
</Text>
<HSeparator />
</DrawerHeader>
<DrawerBody w='340px' ps='24px' pe='40px'>
<Flex flexDirection='column'>
<Flex justifyContent='space-between ' mb='16px'>
<Text fontSize='md' fontWeight='600' mb='4px'>
Navbar Fixed
</Text>
<Switch
colorScheme='blue'
isChecked={switched}
onChange={() => {
if (switched === true) {
props.onSwitch(false);
setSwitched(false);
} else {
props.onSwitch(true);
setSwitched(true);
}
}}
/>
</Flex>
<Flex
justifyContent='space-between'
alignItems='center'
mb='24px'>
<Text fontSize='md' fontWeight='600' mb='4px'>
Dark/Light
</Text>
<Button onClick={toggleColorMode} color={secondaryButtonColor}>
Toggle {colorMode === "light" ? "Dark" : "Light"}
</Button>
</Flex>
<HSeparator />
<Box mt='24px'>
<Box>
<Link
href='https://www.creative-tim.com/product/argon-dashboard-chakra'
w='100%'
mb='16px'>
<Button
w='100%'
mb='16px'
bg={bgButton}
color={colorButton}
fontSize='xs'
variant='no-effects'
px='30px'>
Free Download
</Button>
</Link>
<Link
href='https://demos.creative-tim.com/docs-argon-dashboard-chakra'
w='100%'>
<Button
w='100%'
bg={secondaryButtonBg}
border='1px solid'
borderColor={secondaryButtonBorder}
color={secondaryButtonColor}
fontSize='xs'
variant='no-effects'
px='20px'
mb='16px'>
<Text textDecorationColor='none'>Documentation</Text>
</Button>
</Link>
</Box>
<Flex
justifyContent='center'
alignItems='center'
w='100%'
mb='16px'>
<GitHubButton
href='https://github.com/creativetimofficial/ct-argon-dashboard-chakra-pro'
data-icon='octicon-star'
data-show-count='true'
aria-label='Star creativetimofficial/ct-argon-dashboard-chakra-pro on GitHub'>
Star
</GitHubButton>
</Flex>
<Box w='100%'>
<Text mb='6px' textAlign='center'>
Thank you for sharing!
</Text>
<Flex justifyContent='center' alignContent='center'>
<Link
isExternal='true'
href='https://twitter.com/intent/tweet?url=https://www.creative-tim.com/product/argon-dashboard-chakra-pro/&text=Check%20Argon%20Dashboard%20Chakra%20PRO%20made%20by%20@simmmple_web%20and%20@CreativeTim'>
<Button
colorScheme='twitter'
leftIcon={<FaTwitter />}
me='10px'>
<Text>Tweet</Text>
</Button>
</Link>
<Link
isExternal='true'
href='https://www.facebook.com/sharer/sharer.php?u=https://www.creative-tim.com/product/argon-dashboard-chakra-pro/'>
<Button colorScheme='facebook' leftIcon={<FaFacebook />}>
<Text>Share</Text>
</Button>
</Link>
</Flex>
</Box>
</Box>
</Flex>
</DrawerBody>
</DrawerContent>
</Drawer>
</>
);
}
Configurator.propTypes = {
secondary: PropTypes.bool,
isOpen: PropTypes.bool,
onClose: PropTypes.func,
fixed: PropTypes.bool,
};

View File

@@ -0,0 +1,139 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
// Chakra imports
import { Box, Button, useColorModeValue } from '@chakra-ui/react';
import React from 'react';
import ReactQuill from 'react-quill';
const CustomToolbar = () => (
<Box bg={useColorModeValue('transparent', 'navy.900')}>
<Box
id='toolbar'
borderTopStartRadius='8px'
borderTopEndRadius='8px'
borderBottom='0px solid transparent !important'
>
<select
className='ql-header'
defaultValue={''}
onChange={(e) => e.persist()}
>
<option value='1'></option>
<option value='2'></option>
</select>
<Button
display='flex !important'
justifyContent='center !important'
alignItems='center !important'
me='5px !important'
className='ql-bold'
></Button>
<Button
display='flex !important'
justifyContent='center !important'
alignItems='center !important'
me='5px !important'
className='ql-italic'
></Button>
<Button
display='flex !important'
justifyContent='center !important'
alignItems='center !important'
me='5px !important'
className='ql-underline'
></Button>
<Button
display='flex !important'
justifyContent='center !important'
alignItems='center !important'
me='5px !important'
className='ql-list'
value='ordered'
></Button>
<Button
display='flex !important'
justifyContent='center !important'
alignItems='center !important'
className='ql-list'
value='bullet'
></Button>
</Box>
</Box>
);
export default class Editor extends React.Component {
constructor(props) {
super(props);
this.state = { editorHtml: '' };
this.handleChange = this.handleChange.bind(this);
}
handleChange(html) {
this.setState({ editorHtml: html });
}
render() {
return (
<div className='text-editor'>
<CustomToolbar />
<ReactQuill
onChange={this.handleChange}
placeholder={this.props.placeholder}
modules={Editor.modules}
/>
</div>
);
}
}
Editor.modules = {
toolbar: [
[{ size: [] }],
['bold', 'italic', 'underline'],
[{ list: 'ordered' }, { list: 'bullet' }, 'link'],
],
clipboard: {
matchVisual: false,
},
};
Editor.modules = {
toolbar: {
container: '#toolbar',
},
clipboard: {
matchVisual: false,
},
};
Editor.formats = [
'header',
'font',
'size',
'bold',
'italic',
'underline',
'strike',
'blockquote',
'list',
'bullet',
'indent',
'link',
'image',
'color',
];

View File

@@ -0,0 +1,80 @@
import React from 'react';
import {
Box,
Alert,
AlertIcon,
AlertTitle,
AlertDescription,
Button,
VStack,
Container
} from '@chakra-ui/react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null, errorInfo: null };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
this.setState({
error: error,
errorInfo: errorInfo
});
}
render() {
if (this.state.hasError) {
return (
<Container maxW="lg" py={20}>
<VStack spacing={6}>
<Alert status="error" borderRadius="lg" p={6}>
<AlertIcon boxSize="24px" />
<Box>
<AlertTitle fontSize="lg" mb={2}>
页面出现错误
</AlertTitle>
<AlertDescription>
页面加载时发生了未预期的错误请尝试刷新页面
</AlertDescription>
</Box>
</Alert>
{process.env.NODE_ENV === 'development' && (
<Box
w="100%"
bg="gray.50"
p={4}
borderRadius="lg"
fontSize="sm"
overflow="auto"
maxH="200px"
>
<Box fontWeight="bold" mb={2}>错误详情:</Box>
<Box as="pre" whiteSpace="pre-wrap">
{this.state.error && this.state.error.toString()}
{this.state.errorInfo.componentStack}
</Box>
</Box>
)}
<Button
colorScheme="blue"
onClick={() => window.location.reload()}
>
重新加载页面
</Button>
</VStack>
</Container>
);
}
return this.props.children;
}
}
export

View File

@@ -0,0 +1,63 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
// Chakra Imports
import { Button, useColorModeValue } from "@chakra-ui/react";
// Custom Icons
import { SettingsIcon } from "components/Icons/Icons";
import PropTypes from "prop-types";
import React from "react";
export default function FixedPlugin(props) {
const { secondary, onChange, onSwitch, fixed, ...rest } = props;
// Chakra Color Mode
let navbarIcon = useColorModeValue("gray.500", "gray.200");
let bgButton = useColorModeValue("white", "gray.600");
const settingsRef = React.useRef();
return (
<>
<Button
h="52px"
w="52px"
onClick={props.onOpen}
bg={bgButton}
position="fixed"
variant="no-effects"
left={document.documentElement.dir === "rtl" ? "35px" : ""}
right={document.documentElement.dir === "rtl" ? "" : "35px"}
bottom="30px"
borderRadius="50px"
boxShadow="0 2px 12px 0 rgb(0 0 0 / 16%)"
>
<SettingsIcon
cursor="pointer"
ref={settingsRef}
color={navbarIcon}
w="20px"
h="20px"
/>
</Button>
</>
);
}
FixedPlugin.propTypes = {
fixed: PropTypes.bool,
onChange: PropTypes.func,
onSwitch: PropTypes.func,
};

View File

@@ -0,0 +1,127 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
/*eslint-disable*/
import React from "react";
import { Flex, Link, List, ListItem, Text, VStack, HStack } from "@chakra-ui/react";
export default function Footer() {
return (
<Flex
flexDirection={{
base: "column",
xl: "row",
}}
alignItems={{
base: "center",
xl: "start",
}}
justifyContent='space-between'
px='30px'
pb='20px'>
<Text
color='gray.400'
textAlign={{
base: "center",
xl: "start",
}}
mb={{ base: "20px", xl: "0px" }}>
&copy; {1900 + new Date().getYear()},{" "}
<Text as='span'>
{document.documentElement.dir === "rtl"
? " مصنوع من ❤️ بواسطة"
: "Made with ❤️ by "}
</Text>
<Link
color='blue.400'
href='https://www.creative-tim.com'
target='_blank'>
{document.documentElement.dir === "rtl"
? " توقيت الإبداعية"
: "Creative Tim "}
</Link>
&
<Link color='blue.400' href='https://www.simmmple.com' target='_blank'>
{document.documentElement.dir === "rtl" ? "سيممبل " : " Simmmple"}
</Link>
{document.documentElement.dir === "rtl"
? "للحصول على ويب أفضل"
: " for a better web"}
</Text>
{/* 添加备案信息 */}
<VStack spacing={1} align={{base: "center", xl: "start"}} mb={{base: "20px", xl: "0px"}}>
<HStack spacing={4} flexWrap="wrap" justify={{base: "center", xl: "start"}}>
<Link
color='gray.400'
href='https://beian.mps.gov.cn/#/query/webSearch?code=11010802046286'
target='_blank'
rel='noreferrer'
fontSize='xs'
_hover={{color: 'gray.300'}}
>
京公网安备11010802046286号
</Link>
<Text color='gray.400' fontSize='xs'>
京ICP备2025107343号-1
</Text>
</HStack>
</VStack>
<List display='flex'>
<ListItem
me={{
base: "20px",
md: "44px",
}}>
<Link color='gray.400' href='https://www.creative-tim.com'>
{document.documentElement.dir === "rtl"
? "توقيت الإبداعية"
: "Creative Tim"}
</Link>
</ListItem>
<ListItem
me={{
base: "20px",
md: "44px",
}}>
<Link color='gray.400' href='https://www.simmmple.com'>
{document.documentElement.dir === "rtl" ? "سيممبل" : "Simmmple"}
</Link>
</ListItem>
<ListItem
me={{
base: "20px",
md: "44px",
}}>
<Link
color='gray.400'
href='https://creative-tim.com/blog'>
{document.documentElement.dir === "rtl" ? "مدونة" : "Blog"}
</Link>
</ListItem>
<ListItem>
<Link
color='gray.400'
href='https://www.creative-tim.com/license'>
{document.documentElement.dir === "rtl" ? "رخصة" : "License"}
</Link>
</ListItem>
</List>
</Flex>
);
}

View File

@@ -0,0 +1,52 @@
import Section from "../Section/index.tsx";
import Logo from "../Logo/index.js";
const Footer = () => (
<Section
className="pt-11 pb-6 px-5 lg:pt-[6.5rem] lg:px-7.5 lg:pb-12 xl:px-10"
crosses
customPaddings
>
<div className="flex items-center justify-center h-[6.5rem] mb-6 border-b border-n-6 lg:justify-start">
<Logo />
<nav className="hidden lg:flex items-center justify-center ml-auto">
<a
className="text-n-1/50 font-code text-xs font-bold uppercase tracking-wider transition-colors hover:text-n-1 mr-10"
href="/features"
>
特性功能
</a>
<a
className="text-n-1/50 font-code text-xs font-bold uppercase tracking-wider transition-colors hover:text-n-1 mr-10"
href="/pricing"
>
定价方案
</a>
<a
className="text-n-1/50 font-code text-xs font-bold uppercase tracking-wider transition-colors hover:text-n-1"
href="/how-to-use"
>
使用指南
</a>
</nav>
</div>
<div className="flex flex-col items-center space-y-2">
<p className="caption text-n-4 lg:block">
© 2024 价值前沿. 保留所有权利.
</p>
<div className="flex flex-col sm:flex-row items-center space-y-1 sm:space-y-0 sm:space-x-4 text-xs text-n-4">
<a
href="https://beian.mps.gov.cn/#/query/webSearch?code=11010802046286"
rel="noreferrer"
target="_blank"
className="hover:text-n-1 transition-colors"
>
京公网安备11010802046286号
</a>
<span className="text-n-4">京ICP备2025107343号-1</span>
</div>
</div>
</Section>
);
export default Footer;

View File

@@ -0,0 +1,20 @@
import Image from "../Image";
const Generating = ({ className }) => (
<div
className={`flex items-center h-[3.375rem] px-6 bg-n-8/80 rounded-[1.6875rem] ${
className || ""
} text-base`}
>
<Image
className="w-5 h-5 mr-4"
src="/images/loading.png"
width={20}
height={20}
alt="Loading"
/>
AI is generating|
</div>
);
export default Generating;

View File

@@ -0,0 +1,125 @@
import { useState } from "react";
import { useLocation } from "react-router-dom";
// import { disablePageScroll, enablePageScroll } from "scroll-lock";
import Button from "../Button/index.tsx";
import Logo from "../Logo/index.js";
import Image from "../Image/index.tsx";
// 简化版导航数据
const navigation = [
{ id: "0", title: "Features", url: "/features" },
{ id: "1", title: "Pricing", url: "/pricing" },
{ id: "2", title: "How to use", url: "/how-to-use" },
{ id: "3", title: "Roadmap", url: "/roadmap" },
];
const Header = () => {
const [openNavigation, setOpenNavigation] = useState(false);
const location = useLocation();
const toggleNavigation = () => {
setOpenNavigation(!openNavigation);
// if (openNavigation) {
// enablePageScroll();
// } else {
// disablePageScroll();
// }
};
const handleClick = () => {
setOpenNavigation(false);
};
return (
<div
className={`fixed top-0 left-0 z-50 w-full ${
openNavigation ? "bg-n-8" : " bg-n-8/90 backdrop-blur-sm"
} border-b border-n-6 lg:bg-n-8/90 lg:backdrop-blur-sm`}
>
<div className="flex items-center h-[4.75rem] px-5 lg:h-[5.25rem] lg:px-7.5 xl:px-10">
<Logo className="xl:mr-8" />
<nav
className={`${
openNavigation ? "flex" : "hidden"
} fixed top-[4.8125rem] left-0 right-0 bottom-0 bg-n-8 lg:static lg:flex lg:mx-auto lg:bg-transparent`}
>
<div className="relative z-2 flex flex-col items-center justify-center m-auto lg:flex-row">
{navigation.map((item) => (
<a
className={`block relative font-code text-2xl uppercase text-n-1 transition-colors hover:text-color-1 px-6 py-6 md:py-8 lg:-mr-0.25 lg:text-xs lg:font-semibold ${
item.url === location.pathname
? "z-2 lg:text-n-1"
: "lg:text-n-1/50"
} lg:leading-5 lg:hover:text-n-1 xl:px-12`}
href={item.url}
onClick={handleClick}
key={item.id}
>
{item.title}
<div
className={`hidden absolute left-0 bottom-0 w-0.25 h-1.5 bg-n-6 lg:block ${
location.pathname === item.url
? "lg:h-3 lg:bg-n-1"
: ""
}`}
></div>
<div
className={`hidden absolute right-0 bottom-0 w-0.25 h-1.5 bg-n-6 lg:block ${
location.pathname === item.url
? "lg:h-3 lg:bg-n-1"
: ""
}`}
></div>
</a>
))}
</div>
</nav>
<a
className="button hidden mr-8 text-n-1/50 transition-colors hover:text-n-1 lg:block"
href="/login"
>
注册账号
</a>
<Button className="hidden lg:flex" href="/login">
登录
</Button>
<Button
className="ml-auto lg:hidden"
onClick={toggleNavigation}
px="px-3"
>
<svg
className="overflow-visible"
width="20"
height="12"
viewBox="0 0 20 12"
>
<rect
className="transition-all origin-center"
y={openNavigation ? "5" : "0"}
width="20"
height="2"
rx="1"
fill="white"
transform={`rotate(${openNavigation ? "45" : "0"})`}
/>
<rect
className="transition-all origin-center"
y={openNavigation ? "5" : "10"}
width="20"
height="2"
rx="1"
fill="white"
transform={`rotate(${
openNavigation ? "-45" : "0"
})`}
/>
</svg>
</Button>
</div>
</div>
);
};
export default Header;

View File

@@ -0,0 +1,32 @@
import Tagline from "../Tagline/index.js";
const Heading = ({
className,
textAlignClassName,
tagClassName,
tag,
titleLarge,
title,
textLarge,
text,
children,
}) => (
<div
className={`max-w-[50rem] mx-auto mb-12 ${
textAlignClassName || "md:text-center"
} lg:mb-20 ${className || ""}`}
>
{tag && (
<Tagline className={`mb-4 md:justify-center ${tagClassName || ""}`}>
{tag}
</Tagline>
)}
{titleLarge && <h1 className="h1 text-n-1">{titleLarge}</h1>}
{title && <h2 className="h2 text-n-1">{title}</h2>}
{textLarge && <p className="h5 mt-6 text-n-2">{textLarge}</p>}
{text && <p className="body-2 mt-4 text-n-2">{text}</p>}
{children}
</div>
);
export default Heading;

View File

@@ -0,0 +1,34 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import React from "react";
import { Flex } from "@chakra-ui/react";
export default function IconBox(props) {
const { children, ...rest } = props;
return (
<Flex
alignItems={"center"}
justifyContent={"center"}
borderRadius={"8px"}
{...rest}
>
{children}
</Flex>
);
}

View File

@@ -0,0 +1,736 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import { createIcon } from '@chakra-ui/icons';
export const AdobexdLogo = createIcon({
displayName: 'AdobexdLogo',
viewBox: '0 0 24 24',
path: (
<g clipPath='url(#clip0)'>
<path
d='M4.042 0h12.916A3.539 3.539 0 0120.5 3.542v12.416a3.539 3.539 0 01-3.542 3.542H4.042A3.539 3.539 0 01.5 15.958V3.542A3.539 3.539 0 014.042 0z'
fill='#470137'
/>
<path
d='M11.017 5.124l-2.5 4.125 2.666 4.375a.143.143 0 01.017.1c-.008.034-.042.009-.092.017H9.2c-.133 0-.225-.008-.283-.092-.175-.35-.359-.691-.534-1.041a33.608 33.608 0 00-.566-1.05c-.2-.359-.4-.717-.6-1.084H7.2c-.175.359-.367.717-.558 1.075-.192.359-.384.717-.567 1.067-.192.35-.383.708-.575 1.05-.033.083-.1.092-.192.092H3.475c-.033 0-.058.016-.058-.025a.116.116 0 01.016-.092l2.592-4.25L3.5 5.116c-.025-.033-.033-.067-.017-.083.017-.025.05-.034.084-.034h1.891c.042 0 .084.009.117.017a.236.236 0 01.083.075c.159.358.342.717.534 1.075.2.358.391.708.6 1.058.2.35.383.7.558 1.059h.017c.175-.367.358-.725.541-1.075.184-.35.375-.7.567-1.05.192-.35.375-.709.558-1.05.009-.034.025-.067.05-.084a.159.159 0 01.109-.016h1.758a.077.077 0 01.091.058c.009.008-.008.042-.024.058zM14.866 13.917a4.144 4.144 0 01-1.791-.375 2.906 2.906 0 01-1.259-1.134c-.308-.508-.458-1.141-.458-1.9a3.423 3.423 0 011.783-3.05c.584-.325 1.284-.483 2.109-.483.041 0 .1 0 .175.008.075.009.158.009.258.017V4.367c0-.059.025-.092.083-.092h1.692c.042-.008.075.025.083.058v7.95c0 .15.009.317.017.5.017.175.025.342.033.484 0 .058-.025.108-.083.133a6.365 6.365 0 01-1.358.4 7.35 7.35 0 01-1.284.117zm.817-1.667V8.583c-.075-.016-.15-.033-.225-.041-.092-.009-.183-.017-.275-.017-.325 0-.65.067-.942.217-.283.141-.525.35-.708.616-.183.267-.275.625-.275 1.059-.008.291.042.583.142.858.083.225.208.425.375.592.158.15.35.266.566.333.225.075.459.108.692.108.125 0 .242-.008.35-.016a.73.73 0 00.3-.042z'
fill='#FF61F6'
/>
</g>
),
});
export const AtlassianLogo = createIcon({
displayName: 'AtlassianLogo',
viewBox: '0 0 24 24',
path: (
<g>
<path
d='M6.427 9.239a.57.57 0 00-.798-.108.591.591 0 00-.167.209l-4.9 9.803a.586.586 0 00.524.847h6.827a.562.562 0 00.523-.324c1.474-3.043.58-7.67-2.01-10.427z'
fill='#2684FF'
/>
<path
d='M10.028.318a12.932 12.932 0 00-.755 12.765l3.292 6.583a.586.586 0 00.523.324h6.826a.583.583 0 00.586-.585c0-.091-.02-.18-.06-.262L11.024.315a.552.552 0 00-.997 0v.003z'
fill='#2684FF'
/>
</g>
),
});
export const CartIcon = createIcon({
displayName: 'CartIcon',
viewBox: '0 0 24 24',
path: (
<path
fill='currentColor'
d='M7.984 19.937a1.406 1.406 0 100-2.812 1.406 1.406 0 000 2.812zM17.828 19.937a1.406 1.406 0 100-2.812 1.406 1.406 0 000 2.812zM20.324 5.558a1.051 1.051 0 00-.815-.386H6.134l-.27-1.528a.703.703 0 00-.692-.581H2.359a.703.703 0 000 1.406h2.223L6.59 15.841a.703.703 0 00.692.581h11.25a.703.703 0 100-1.406H7.871l-.248-1.406h10.62a1.057 1.057 0 001.035-.848l1.266-6.328a1.055 1.055 0 00-.22-.876z'
/>
),
});
export const ClockIcon = createIcon({
displayName: 'ClockIcon',
viewBox: '0 0 24 24',
path: (
<g>
<g>
<rect fill='none' height='24' width='24' />
</g>
<g>
<g>
<g>
<path
fill='currentColor'
d='M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M16.2,16.2L11,13V7h1.5v5.2l4.5,2.7L16.2,16.2z'
/>
</g>
</g>
</g>
</g>
),
});
export const CreativeTimLogo = createIcon({
displayName: 'CreativeTimLogo',
viewBox: '0 0 100 100',
path: (
<g
xmlns='http://www.w3.org/2000/svg'
width='50px'
height='50px'
version='1.1'
>
<g
id='logo-creative-tim-black'
stroke='none'
strokeWidth='1'
fill='none'
fillRule='evenodd'
>
<g
id='icon'
transform='translate(15.000000, 19.000000)'
fill='currentColor'
fillRule='nonzero'
>
<path
d='M66.4346744,1.49018376e-13 L3.56968951,1.49018376e-13 C1.59820443,1.49018376e-13 -2.98036753e-13,1.59820443 -2.98036753e-13,3.56968951 L-2.98036753e-13,33.5035241 C-2.98036753e-13,35.4750091 1.59820443,37.0732136 3.56968951,37.0732136 L16.4677598,37.0732136 L16.4677598,66.4346744 C16.4666001,67.3810129 16.8417189,68.288989 17.5104719,68.9585615 C18.1792249,69.628134 19.0867408,70.0043639 20.03308,70.0043639 L49.9669146,70.0043639 C51.9383997,70.0043639 53.5366041,68.4061595 53.5366041,66.4346744 L53.5366041,37.0863214 L66.4346744,37.0863214 C67.3810136,37.0863221 68.2885296,36.7100915 68.9572826,36.0405189 C69.6260355,35.3709464 70.0011544,34.4629704 70,33.5166319 L70,3.56968951 C70.0011544,2.62335099 69.6260355,1.71537495 68.9572826,1.04580242 C68.2885296,0.37622988 67.3810136,1.49018376e-13 66.4346744,1.49018376e-13 Z M4.13769396,4.14206323 L32.9311503,4.14206323 L32.9311503,32.9355196 L4.13769396,32.9355196 L4.13769396,4.14206323 Z M49.3989102,65.86667 L20.6054538,65.86667 L20.6054538,37.0863214 L49.3989102,37.0863214 L49.3989102,65.86667 Z M65.8623007,32.9355196 L37.0688443,32.9355196 L37.0688443,4.14206323 L65.8623007,4.14206323 L65.8623007,32.9355196 Z'
id='Shape'
/>
<path
d='M23.6988934,23.3056595 C24.5142794,24.0708897 25.7898859,24.0506562 26.5805917,23.2599503 C27.3712976,22.4692445 27.3915311,21.193638 26.6263009,20.378252 L20.015603,13.767554 C19.2050095,12.9645312 17.8987889,12.9645312 17.0881954,13.767554 L10.4600204,20.378252 C9.90907005,20.8953125 9.68342943,21.6713831 9.87125954,22.4032422 C10.0590897,23.1351013 10.6305787,23.7065903 11.3624377,23.8944204 C12.0942968,24.0822505 12.8703675,23.8566099 13.387428,23.3056595 L18.5344222,18.1586654 L23.6988934,23.3056595 Z'
id='Path'
/>
<path
d='M46.3185783,23.3056595 L51.4655725,18.1586654 L56.6125667,23.3056595 C57.4279526,24.0708897 58.7035592,24.0506562 59.494265,23.2599503 C60.2849709,22.4692445 60.3052044,21.193638 59.5399742,20.378252 L52.9292763,13.767554 C52.1186828,12.9645312 50.8124622,12.9645312 50.0018687,13.767554 L43.3911708,20.378252 C42.6259406,21.193638 42.6461741,22.4692445 43.43688,23.2599503 C44.2275858,24.0506562 45.5031924,24.0708897 46.3185783,23.3056595 L46.3185783,23.3056595 Z'
id='Path'
/>
<path
d='M29.8508185,46.6987044 C29.0342976,45.9346441 27.7586832,45.9567597 26.9691385,46.7486649 C26.1795937,47.54057 26.1612859,48.8162446 26.9277802,49.6304812 L33.5384782,56.2368099 C33.9262423,56.6258256 34.452915,56.8444779 35.002182,56.8444779 C35.5514489,56.8444779 36.0781217,56.6258256 36.4658857,56.2368099 L43.0765837,49.6304812 C43.6002952,49.1075502 43.8052442,48.3449453 43.6142284,47.6299323 C43.4232126,46.9149194 42.8652519,46.3561259 42.1505246,46.1640439 C41.4357974,45.971962 40.6728876,46.1757734 40.1491761,46.6987044 L35.002182,51.8500678 L29.8508185,46.6987044 Z'
id='Path'
/>
</g>
</g>
</g>
),
});
export const CreditIcon = createIcon({
displayName: 'CreditIcon',
viewBox: '0 0 24 24',
path: (
<path
fill='currentColor'
d='M1.406 17.023a2.461 2.461 0 002.461 2.46h14.766a2.461 2.461 0 002.46-2.46v-6.768H1.407v6.768zm2.9-3.34a1.318 1.318 0 011.319-1.318h2.11a1.318 1.318 0 011.318 1.318v.879a1.318 1.318 0 01-1.319 1.318H5.625a1.318 1.318 0 01-1.318-1.318v-.879zM18.633 4.014H3.867a2.46 2.46 0 00-2.46 2.461v1.143h19.687V6.475a2.46 2.46 0 00-2.461-2.46z'
/>
),
});
export const DashboardLogo = createIcon({
displayName: 'DashboardLogo',
viewBox: '0 0 1000 257',
path: (
<g width='998' height='257' viewBox='0 0 998 257' fill='none'>
<g clipPath='url(#clip0)'>
<path
d='M388.5 115.302C406.112 115.302 413.966 126.726 416.584 136.96L441.336 127.916C436.576 109.352 419.44 89.836 388.262 89.836C354.942 89.836 329 115.54 329 151.24C329 186.464 354.942 212.882 388.976 212.882C419.44 212.882 436.814 193.128 442.288 175.04L418.012 166.234C415.394 175.04 407.064 187.654 388.976 187.654C371.602 187.654 356.608 174.564 356.608 151.24C356.608 127.916 371.602 115.302 388.5 115.302Z'
fill='currentColor'
/>
<path
d='M484.894 141.244C485.37 126.488 493.7 115.064 508.932 115.064C526.306 115.064 532.732 126.488 532.732 140.768V209.312H560.34V136.008C560.34 110.542 546.536 90.074 517.976 90.074C505.838 90.074 492.748 94.358 484.894 104.592V37H457.286V209.312H484.894V141.244Z'
fill='currentColor'
/>
<path
d='M577.29 177.896C577.29 196.222 592.284 212.882 616.56 212.882C635.362 212.882 646.786 203.362 652.26 194.556C652.26 203.838 653.212 208.598 653.45 209.312H679.154C678.916 208.122 677.726 201.22 677.726 190.748V133.152C677.726 110.066 664.16 89.836 628.46 89.836C599.9 89.836 581.812 107.686 579.67 127.678L604.898 133.39C606.088 121.728 614.18 112.446 628.698 112.446C643.93 112.446 650.594 120.3 650.594 130.058C650.594 134.104 648.69 137.436 642.026 138.388L612.276 142.91C592.522 145.766 577.29 157.19 577.29 177.896ZM621.796 191.224C610.848 191.224 604.898 184.084 604.898 176.23C604.898 166.71 611.8 161.95 620.368 160.522L650.594 156V161.236C650.594 183.846 637.266 191.224 621.796 191.224Z'
fill='currentColor'
/>
<path
d='M810.108 93.406H773.456L728.95 140.292V37H701.58V209.312H728.95V176.944L743.23 161.95L777.264 209.312H811.06L762.508 142.434L810.108 93.406Z'
fill='currentColor'
/>
<path
d='M889.349 92.692C888.159 92.454 885.303 91.978 881.971 91.978C866.739 91.978 853.887 99.356 848.413 111.97V93.406H821.519V209.312H849.127V154.096C849.127 132.438 858.885 120.062 880.305 120.062C883.161 120.062 886.255 120.3 889.349 120.776V92.692Z'
fill='currentColor'
/>
<path
d='M895.968 177.896C895.968 196.222 910.962 212.882 935.238 212.882C954.04 212.882 965.464 203.362 970.938 194.556C970.938 203.838 971.89 208.598 972.128 209.312H997.832C997.594 208.122 996.404 201.22 996.404 190.748V133.152C996.404 110.066 982.838 89.836 947.138 89.836C918.578 89.836 900.49 107.686 898.348 127.678L923.576 133.39C924.766 121.728 932.858 112.446 947.376 112.446C962.608 112.446 969.272 120.3 969.272 130.058C969.272 134.104 967.368 137.436 960.704 138.388L930.954 142.91C911.2 145.766 895.968 157.19 895.968 177.896ZM940.474 191.224C929.526 191.224 923.576 184.084 923.576 176.23C923.576 166.71 930.478 161.95 939.046 160.522L969.272 156V161.236C969.272 183.846 955.944 191.224 940.474 191.224Z'
fill='currentColor'
/>
<rect width='257' height='257' rx='128.5' fill='#4FD1C5' />
<path
d='M69.5584 133.985L157.15 46.9959C158.787 45.3708 161.42 47.3484 160.315 49.3729L127.714 109.125C126.987 110.457 127.951 112.083 129.47 112.083H185.809C187.624 112.083 188.501 114.306 187.174 115.545L88.4456 207.687C86.6753 209.339 84.0405 207.011 85.4617 205.051L132.197 140.578C133.156 139.256 132.211 137.404 130.578 137.404H70.9677C69.1826 137.404 68.2917 135.243 69.5584 133.985Z'
fill='white'
/>
</g>
<defs>
<linearGradient
id='paint0_linear'
x1='128.5'
y1='0'
x2='128.5'
y2='257'
gradientUnits='userSpaceOnUse'
>
<stop stopColor='#7BCBD4' />
<stop offset='1' stopColor='#29C6B7' />
</linearGradient>
<clipPath id='clip0'>
<rect width='997.832' height='257' fill='white' />
</clipPath>
</defs>
</g>
),
});
export const DashboardLogoWhite = createIcon({
displayName: 'DashboardLogo',
viewBox: '0 0 163.5 42',
path: (
<g fill='none'>
<path
d='M63.452 19.292c2.877 0 4.16 1.911 4.587 3.623l4.043-1.513c-.777-3.106-3.576-6.371-8.668-6.371-5.443 0-9.68 4.3-9.68 10.274 0 5.893 4.237 10.313 9.796 10.313 4.976 0 7.813-3.305 8.707-6.331l-3.965-1.473c-.427 1.473-1.788 3.583-4.742 3.583-2.837 0-5.286-2.19-5.286-6.092 0-3.903 2.449-6.013 5.208-6.013zM79.196 23.632c.078-2.469 1.438-4.38 3.926-4.38 2.838 0 3.887 1.911 3.887 4.3v11.47h4.51V22.755c0-4.26-2.255-7.685-6.92-7.685-1.982 0-4.12.716-5.403 2.429V6.19h-4.509v28.831h4.51V23.632zM94.287 29.765c0 3.066 2.449 5.853 6.414 5.853 3.071 0 4.936-1.592 5.83-3.066 0 1.553.156 2.35.195 2.47h4.198c-.039-.2-.233-1.355-.233-3.107v-9.637c0-3.862-2.216-7.247-8.047-7.247-4.664 0-7.619 2.986-7.968 6.332l4.12.955c.194-1.951 1.516-3.504 3.887-3.504 2.488 0 3.576 1.314 3.576 2.947 0 .677-.311 1.234-1.399 1.393l-4.859.757c-3.226.478-5.714 2.39-5.714 5.854zm7.269 2.23c-1.788 0-2.76-1.195-2.76-2.509 0-1.593 1.127-2.39 2.527-2.628l4.936-.757v.876c0 3.783-2.176 5.018-4.703 5.018zM132.312 15.628h-5.986l-7.269 7.845V6.191h-4.47v28.83h4.47v-5.416l2.332-2.508 5.559 7.924h5.52l-7.93-11.19 7.774-8.203zM145.254 15.509a6.3 6.3 0 00-1.205-.12c-2.487 0-4.587 1.235-5.481 3.345v-3.106h-4.392v19.393h4.509v-9.238c0-3.624 1.594-5.695 5.092-5.695.467 0 .972.04 1.477.12v-4.7zM146.335 29.765c0 3.066 2.449 5.853 6.414 5.853 3.071 0 4.937-1.592 5.831-3.066 0 1.553.156 2.35.194 2.47h4.199c-.039-.2-.234-1.355-.234-3.107v-9.637c0-3.862-2.215-7.247-8.046-7.247-4.665 0-7.619 2.986-7.969 6.332l4.121.955c.194-1.951 1.516-3.504 3.887-3.504 2.488 0 3.576 1.314 3.576 2.947 0 .677-.311 1.234-1.399 1.393l-4.859.757c-3.227.478-5.715 2.39-5.715 5.854zm7.269 2.23c-1.788 0-2.759-1.195-2.759-2.509 0-1.593 1.127-2.39 2.526-2.628l4.937-.757v.876c0 3.783-2.177 5.018-4.704 5.018zM41.975 21.5C41.975 9.626 32.578 0 20.987 0 9.398 0 0 9.626 0 21.5S9.396 43 20.988 43c11.59 0 20.987-9.626 20.987-21.5z'
fill='#fff'
/>
<path
d='M11.36 22.418L25.668 7.863c.267-.272.697.06.517.398l-5.325 9.997c-.119.223.039.495.287.495h9.202c.296 0 .44.372.223.58L14.446 34.748c-.29.277-.72-.113-.488-.44l7.633-10.788c.157-.221.003-.531-.264-.531H11.59c-.292 0-.437-.362-.23-.572z'
fill='#3BCBBE'
/>
</g>
),
});
export const DocumentIcon = createIcon({
displayName: 'DocumentIcon',
viewBox: '0 0 24 24',
path: (
<g>
<path
fill='currentColor'
d='M18.809 10.344h-6.153a2.11 2.11 0 01-2.11-2.11V2.083a.176.176 0 00-.175-.176H6.328A2.812 2.812 0 003.516 4.72v14.063a2.812 2.812 0 002.812 2.812h9.844a2.812 2.812 0 002.812-2.813V10.52a.176.176 0 00-.175-.176z'
/>
<path
fill='currentColor'
d='M18.423 8.789l-6.32-6.32a.088.088 0 00-.15.062v5.705a.703.703 0 00.703.703h5.705a.088.088 0 00.062-.15z'
/>
</g>
),
});
export const GlobeIcon = createIcon({
displayName: 'GlobeIcon',
viewBox: '0 0 24 24',
path: (
<g>
<path
stroke='currentColor'
fill='transparent'
d='M11.25 2.109a9.14 9.14 0 100 18.281 9.14 9.14 0 000-18.281z'
strokeWidth='.75'
strokeMiterlimit='10'
/>
<path
stroke='currentColor'
fill='transparent'
d='M11.25 2.109C8.698 2.109 6.3 6.2 6.3 11.249c0 5.048 2.4 9.14 4.951 9.14 2.552 0 4.951-4.092 4.951-9.14 0-5.048-2.399-9.14-4.95-9.14z'
strokeWidth='.75'
strokeMiterlimit='10'
/>
<path
stroke='currentColor'
fill='transparent'
d='M5.156 5.156C6.836 6.349 8.952 7.06 11.25 7.06c2.298 0 4.414-.711 6.094-1.904'
/>
<path
stroke='currentColor'
fill='transparent'
d='M5.156 5.156C6.836 6.349 8.952 7.06 11.25 7.06c2.298 0 4.414-.711 6.094-1.904M17.344 17.344c-1.68-1.193-3.796-1.904-6.094-1.904-2.298 0-4.413.711-6.094 1.904'
strokeWidth='.75'
strokeLinecap='round'
strokeLinejoin='round'
/>
<path
stroke='currentColor'
fill='transparent'
d='M11.25 2.109v18.28M20.39 11.249H2.11'
strokeWidth='.75'
strokeMiterlimit='10'
/>
</g>
),
});
export const HelpIcon = createIcon({
displayName: 'HelpIcon',
viewBox: '0 0 24 24',
path: (
<path
fill='currentColor'
d='M11.25 0C5.04 0 0 5.04 0 11.25S5.04 22.5 11.25 22.5 22.5 17.46 22.5 11.25 17.46 0 11.25 0zm-.352 17.813a1.172 1.172 0 110-2.344 1.172 1.172 0 010 2.344zm1.96-5.977c-.95.637-1.08 1.222-1.08 1.758a.82.82 0 11-1.641 0c0-1.284.59-2.305 1.806-3.121 1.13-.758 1.768-1.239 1.768-2.295 0-.718-.41-1.264-1.26-1.668-.199-.095-.644-.187-1.191-.18-.687.008-1.22.172-1.63.503-.775.623-.84 1.302-.84 1.312a.821.821 0 11-1.642-.08c.007-.142.106-1.425 1.452-2.507.698-.562 1.585-.854 2.636-.866.745-.01 1.444.117 1.918.34 1.418.672 2.198 1.79 2.198 3.146 0 1.982-1.325 2.872-2.494 3.658z'
/>
),
});
export const HomeIcon = createIcon({
displayName: 'HomeIcon',
viewBox: '0 0 24 24',
path: (
<g>
<path
fill='currentColor'
d='M11.494 4.951a.351.351 0 00-.486 0l-8.09 7.729a.352.352 0 00-.109.254v7.254a1.406 1.406 0 001.405 1.406h4.223a.703.703 0 00.704-.703v-5.976a.351.351 0 01.351-.352h3.516a.351.351 0 01.351.352v5.976a.703.703 0 00.704.703h4.22a1.407 1.407 0 001.407-1.406v-7.254a.35.35 0 00-.108-.254L11.494 4.95z'
/>
<path
fill='currentColor'
d='M21.574 11.23l-3.287-3.144V3.314a.703.703 0 00-.703-.703h-2.11a.703.703 0 00-.703.703V4.72l-2.545-2.434c-.239-.24-.593-.378-.976-.378-.38 0-.734.138-.972.379L.93 11.23a.717.717 0 00-.058.983.703.703 0 001.018.046l9.119-8.713a.352.352 0 01.486 0l9.12 8.713a.703.703 0 00.992-.019c.27-.28.248-.74-.033-1.01z'
/>
</g>
),
});
export const InvisionLogo = createIcon({
displayName: 'InvisionLogo',
viewBox: '0 0 24 24',
path: (
<g clipPath='url(#clip0)'>
<path
d='M18.687 0H2.313A1.813 1.813 0 00.5 1.811v16.374C.5 19.188 1.312 20 2.313 20h16.374a1.813 1.813 0 001.813-1.813V1.812A1.813 1.813 0 0018.687 0z'
fill='#DC395F'
/>
<path
d='M7.184 6.293c.665 0 1.222-.522 1.222-1.204 0-.683-.557-1.204-1.222-1.204-.665 0-1.222.521-1.222 1.204 0 .682.557 1.204 1.222 1.204zM4.65 12.739a4.134 4.134 0 00-.108.905c0 1.06.575 1.764 1.797 1.764 1.013 0 1.834-.602 2.426-1.573l-.361 1.449h2.012l1.15-4.612c.287-1.168.844-1.774 1.689-1.774.665 0 1.078.413 1.078 1.096 0 .197-.018.413-.09.646l-.593 2.12c-.09.306-.126.611-.126.899 0 1.006.593 1.742 1.833 1.742 1.06 0 1.904-.682 2.371-2.317l-.79-.305c-.395 1.095-.737 1.293-1.006 1.293-.27 0-.414-.18-.414-.538 0-.162.037-.342.09-.558l.575-2.065c.144-.485.198-.915.198-1.31 0-1.546-.934-2.352-2.066-2.352-1.06 0-2.138.956-2.677 1.962l.395-1.806H8.962L8.53 8.996h1.438l-.885 3.544c-.695 1.545-1.972 1.57-2.132 1.534-.264-.06-.432-.159-.432-.5 0-.198.036-.482.126-.823l1.348-5.346H4.579l-.431 1.591h1.419L4.65 12.74'
fill='#fff'
/>
</g>
),
});
export const JiraLogo = createIcon({
displayName: 'JiraLogo',
viewBox: '0 0 24 24',
path: (
<g clipPath='url(#clip0)'>
<path
d='M20.26 10.42l-8.863-8.93-.86-.865-6.67 6.722L.814 10.42a.827.827 0 000 1.162l6.096 6.14 3.627 3.654 6.67-6.722.105-.104 2.947-2.964a.824.824 0 000-1.166zm-9.722 3.649L7.493 11l3.045-3.068L13.582 11l-3.044 3.068z'
fill='#2684FF'
/>
<path
d='M10.537 7.932a5.184 5.184 0 01-1.502-3.637A5.185 5.185 0 0110.515.65L3.852 7.36l3.626 3.654 3.06-3.082z'
fill='url(#paint0_linear)'
/>
<path
d='M13.59 10.992l-3.053 3.076a5.186 5.186 0 011.502 3.653c0 1.37-.54 2.683-1.502 3.652l6.682-6.728-3.63-3.653z'
fill='url(#paint1_linear)'
/>
</g>
),
});
export const MastercardIcon = createIcon({
displayName: 'MastercardIcon',
viewBox: '0 0 24 24',
path: (
<svg
width='24'
height='20'
viewBox='0 0 21 15'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<circle cx='6.63158' cy='7.49999' r='6.63158' fill='#EB001B' />
<circle cx='14.3686' cy='7.49999' r='6.63158' fill='#F79E1B' />
</svg>
),
});
export const PayPalIcon = createIcon({
displayName: 'PayPalIcon',
viewBox: '0 0 24 24',
path: (
<g>
<path
fill='currentColor'
d='M16.179 2.532C15.142 1.357 13.265.854 10.863.854H3.895a.997.997 0 00-.986.834L.007 19.945a.595.595 0 00.591.686H4.9l1.08-6.8-.033.215a.993.993 0 01.983-.834h2.044c4.017 0 7.16-1.619 8.08-6.3.027-.14.07-.406.07-.406.262-1.732-.001-2.907-.945-3.974z'
/>
<path
fill='currentColor'
d='M18.213 7.393c-.998 4.61-4.184 7.048-9.24 7.048H7.142L5.773 23.1h2.973a.87.87 0 00.862-.731l.035-.184.684-4.297.044-.237a.87.87 0 01.86-.731h.544c3.514 0 6.264-1.416 7.068-5.51.322-1.644.166-3.021-.63-4.017z'
/>
</g>
),
});
export const PersonIcon = createIcon({
displayName: 'PersonIcon',
viewBox: '0 0 24 24',
path: (
<path
fill='currentColor'
d='M14.618 3.338c-.855-.924-2.05-1.432-3.368-1.432-1.325 0-2.524.505-3.375 1.423-.86.928-1.28 2.188-1.181 3.55.195 2.686 2.239 4.87 4.556 4.87s4.358-2.184 4.556-4.87c.1-1.349-.322-2.607-1.188-3.541zM18.984 21.592H3.515a1.363 1.363 0 01-1.063-.489 1.552 1.552 0 01-.316-1.279c.371-2.058 1.529-3.786 3.348-5 1.616-1.076 3.664-1.67 5.766-1.67s4.15.594 5.765 1.67c1.82 1.214 2.977 2.942 3.348 5 .085.471-.03.937-.315 1.279a1.362 1.362 0 01-1.064.49z'
/>
),
});
export const ProfileIcon = createIcon({
displayName: 'ProfileIcon',
viewBox: '0 0 24 24',
path: (
<g>
<path d='M0 0h24v24H0V0z' fill='transparent' />
<path
fill='currentColor'
d='M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v1c0 .55.45 1 1 1h14c.55 0 1-.45 1-1v-1c0-2.66-5.33-4-8-4z'
/>
</g>
),
});
export const RocketIcon = createIcon({
displayName: 'RocketIcon',
viewBox: '0 0 24 24',
path: (
<g>
<path
fill='currentColor'
d='M20.99 2.182a.209.209 0 00-.156-.16c-2.574-.63-8.521 1.613-11.743 4.833a13.93 13.93 0 00-1.566 1.85c-.994-.087-1.987-.014-2.834.355-2.39 1.052-3.085 3.796-3.279 4.976a.424.424 0 00.464.492l3.837-.423c.002.29.02.578.052.866.02.2.108.386.25.527l1.486 1.482a.86.86 0 00.528.25c.286.033.573.05.86.053l-.42 3.832a.424.424 0 00.492.464c1.178-.19 3.927-.885 4.972-3.274.37-.847.445-1.836.36-2.824a13.96 13.96 0 001.855-1.567c3.232-3.216 5.462-9.03 4.842-11.732zm-8.067 7.896a2.11 2.11 0 112.983-2.984 2.11 2.11 0 01-2.983 2.984z'
/>
<path
fill='currentColor'
d='M7.4 18.054c-.24.241-.627.335-1.092.416-1.044.178-1.967-.725-1.779-1.78.072-.401.283-.962.415-1.094a.192.192 0 00-.16-.328 2.636 2.636 0 00-1.544.753c-1.033 1.034-1.13 4.87-1.13 4.87s3.838-.097 4.872-1.13c.417-.417.682-.961.752-1.546.017-.184-.207-.293-.334-.16z'
/>
</g>
),
});
export const SettingsIcon = createIcon({
displayName: 'SettingsIcon',
viewBox: '0 0 24 24',
// path can also be an array of elements, if you have multiple paths, lines, shapes, etc.
path: (
<g>
<path d='M0,0h24v24H0V0z' fill='none' />
<path
fill='currentColor'
d='M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z'
/>
</g>
),
});
export const SlackLogo = createIcon({
displayName: 'SlackLogo',
viewBox: '0 0 24 24',
path: (
<g clipPath='url(#clip0)' fillRule='evenodd' clipRule='evenodd'>
<path
d='M7.832.5c-1.105 0-2 .919-1.999 2.05 0 1.13.895 2.048 2 2.05h2V2.55c.001-1.13-.894-2.048-2-2.05zm0 5.467H2.5c-1.106 0-2.001.918-2 2.05-.002 1.13.894 2.048 2 2.05h5.332c1.106-.001 2.002-.919 2-2.05.002-1.132-.894-2.05-2-2.05z'
fill='#36C5F0'
/>
<path
d='M20.5 8.016c0-1.13-.895-2.048-2-2.05-1.106.002-2.002.92-2 2.05v2.05h2c1.105 0 2-.918 2-2.05zm-5.334 0V2.55c.001-1.13-.893-2.048-2-2.05-1.105 0-2 .919-2 2.05v5.466c-.001 1.131.894 2.049 2 2.05 1.106 0 2.001-.918 2-2.05z'
fill='#2EB67D'
/>
<path
d='M13.166 21c1.106 0 2.001-.919 2-2.05.001-1.13-.894-2.048-2-2.05h-2v2.05c-.001 1.13.894 2.048 2 2.05zm0-5.467h5.333c1.106-.001 2.002-.92 2-2.05.002-1.131-.893-2.049-1.999-2.05h-5.333c-1.106 0-2.001.918-2 2.05-.001 1.13.893 2.049 1.999 2.05z'
fill='#ECB22E'
/>
<path
d='M.5 13.483c-.001 1.13.895 2.049 2 2.05 1.106-.001 2.001-.92 2-2.05v-2.05h-2c-1.105.001-2.001.919-2 2.05zm5.333 0v5.467c-.001 1.13.894 2.048 2 2.05 1.105 0 2-.919 2-2.05v-5.465c.002-1.131-.894-2.05-2-2.05-1.106 0-2 .917-2 2.048z'
fill='#E01E5A'
/>
</g>
),
});
export const SpotifyLogo = createIcon({
displayName: 'SpotifyLogo',
viewBox: '0 0 24 24',
path: (
<g clipPath='url(#clip0)'>
<path
d='M10.5 0C4.977 0 .5 4.477.5 10s4.477 10 10 10 10-4.477 10-10c0-5.522-4.477-10-10-10zm4.586 14.422a.623.623 0 01-.857.208c-2.348-1.435-5.304-1.76-8.785-.964a.623.623 0 11-.277-1.216c3.808-.87 7.076-.495 9.712 1.115.294.181.387.564.207.857zm1.223-2.722a.78.78 0 01-1.072.257c-2.687-1.652-6.786-2.13-9.965-1.166a.78.78 0 01-.973-.519.781.781 0 01.52-.972c3.632-1.102 8.147-.569 11.233 1.329a.78.78 0 01.258 1.072zm.106-2.835C13.19 6.95 7.875 6.775 4.797 7.708a.935.935 0 11-.543-1.79c3.533-1.072 9.404-.865 13.115 1.338a.935.935 0 01-.954 1.609z'
fill='#2EBD59'
/>
</g>
),
});
export const SupportIcon = createIcon({
// Doesn't display the full icon without w and h being specified
displayName: 'BuildIcon',
viewBox: '0 0 24 24',
path: (
<path
fill='currentColor'
d='M20.885 5.547a.703.703 0 00-1.122-.176l-2.7 2.702a.708.708 0 01-.995 0l-1.167-1.169a.702.702 0 010-.994l2.689-2.69a.704.704 0 00-.21-1.138c-2.031-.908-4.566-.435-6.164 1.152-1.358 1.348-1.763 3.455-1.11 5.78a.698.698 0 01-.197.703L2.593 16.4a2.82 2.82 0 103.981 3.983l6.754-7.332a.699.699 0 01.693-.2 7.885 7.885 0 002.03.279c1.469 0 2.757-.475 3.686-1.39 1.72-1.695 1.983-4.57 1.148-6.192zM4.623 19.901a1.407 1.407 0 11-.305-2.797 1.407 1.407 0 01.305 2.797z'
/>
),
});
export const StatsIcon = createIcon({
displayName: 'StatsIcon',
viewBox: '0 0 24 24',
path: (
<path
fill='currentColor'
d='M4.57 22.297H3.164a1.055 1.055 0 01-1.055-1.054v-6.328a1.055 1.055 0 011.055-1.055H4.57a1.055 1.055 0 011.055 1.055v6.328a1.055 1.055 0 01-1.055 1.054zM14.414 22.296h-1.406a1.055 1.055 0 01-1.055-1.055V10.695a1.055 1.055 0 011.055-1.055h1.406a1.055 1.055 0 011.055 1.055V21.24a1.055 1.055 0 01-1.055 1.055zM19.336 22.297H17.93a1.055 1.055 0 01-1.055-1.055V5.773A1.055 1.055 0 0117.93 4.72h1.406a1.055 1.055 0 011.055 1.054v15.47a1.055 1.055 0 01-1.055 1.054zM9.492 22.297H8.086a1.055 1.055 0 01-1.055-1.055V2.257a1.055 1.055 0 011.055-1.054h1.406a1.055 1.055 0 011.055 1.054v18.985a1.055 1.055 0 01-1.055 1.055z'
/>
),
});
export const WalletIcon = createIcon({
displayName: 'WalletIcon',
viewBox: '0 0 24 24',
path: (
<g>
<path
fill='currentColor'
d='M4.447 4.818h14.062c.164 0 .328.01.491.031a2.9 2.9 0 00-3.406-2.441L4.03 4.382h-.013a2.9 2.9 0 00-1.805 1.149 3.848 3.848 0 012.236-.713zM18.51 5.875H4.446a2.816 2.816 0 00-2.813 2.812v8.438a2.816 2.816 0 002.813 2.812h14.062a2.815 2.815 0 002.813-2.812V8.687a2.815 2.815 0 00-2.813-2.812zm-2.088 8.437a1.406 1.406 0 110-2.811 1.406 1.406 0 010 2.811z'
/>
<path
fill='currentColor'
d='M1.656 11.651V7.28c0-.952.528-2.549 2.358-2.895 1.553-.291 3.091-.291 3.091-.291s1.011.703.176.703-.813 1.077 0 1.077 0 1.032 0 1.032L4.007 10.62l-2.35 1.032z'
/>
</g>
),
});
export const VisaIcon = createIcon({
displayName: 'VisaIcon',
viewBox: '0 0 24 24',
path: (
<svg
width='26'
height='20'
viewBox='0 0 30 9'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M12.6708 2.96349C12.6568 4.15055 13.653 4.81298 14.4034 5.20684C15.1744 5.61099 15.4333 5.87013 15.4304 6.23147C15.4245 6.78459 14.8153 7.02862 14.2452 7.03812C13.2505 7.05475 12.6723 6.74889 12.2125 6.51753L11.8542 8.32341C12.3155 8.55247 13.1696 8.75217 14.0554 8.76087C16.1345 8.76087 17.4947 7.65543 17.5021 5.94145C17.5102 3.76625 14.7087 3.64579 14.7278 2.67348C14.7344 2.37871 14.9956 2.06408 15.568 1.98406C15.8512 1.94368 16.6332 1.91274 17.5198 2.35252L17.8677 0.605286C17.391 0.418253 16.7782 0.239136 16.0153 0.239136C14.0583 0.239136 12.6819 1.35962 12.6708 2.96349ZM21.2115 0.389687C20.8319 0.389687 20.5118 0.628245 20.3691 0.99433L17.3991 8.63249H19.4767L19.8901 7.40183H22.429L22.6689 8.63249H24.5L22.9021 0.389687H21.2115ZM21.5021 2.61641L22.1016 5.7116H20.4596L21.5021 2.61641ZM10.1518 0.389687L8.51418 8.63249H10.4939L12.1308 0.389687H10.1518ZM7.22303 0.389687L5.16233 6.00003L4.32878 1.22966C4.23097 0.697187 3.84472 0.389687 3.41579 0.389687H0.0471011L0 0.629037C0.691574 0.790671 1.47729 1.0514 1.95326 1.33033C2.24457 1.50067 2.32775 1.64964 2.42336 2.05458L4.00214 8.63249H6.0945L9.3021 0.389687H7.22303Z'
fill='#4318FF'
/>
</svg>
),
});
export const ArgonLogoDark = createIcon({
displayName: 'ArgonLogoDark',
viewBox: '0 0 74 27',
path: (
<svg width='74' height='27' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M2.72 15.552.465 11.643 3.1 7.1l5.254-.01 2.256 3.908 4.208.002 2.603 4.507-2.651 4.518-4.194.024-2.117 3.62-5.239.036-2.602-4.507 2.103-3.645Zm11.178 2.96 1.772-3.003-1.745-3.022-3.487.033-1.585 2.721 1.896 3.283 3.149-.011Zm-6.312 3.644 1.585-2.72-1.895-3.284-3.15.012-1.772 3.003L4.1 22.19l3.487-.034Zm-.153-7.553 1.772-3.004L7.46 8.577l-3.487.033L2.2 11.613l1.745 3.023 3.488-.034Z'
fill='#1A202C'
/>
<path
d='M29.076 10.956c-2.088 0-3.78 1.044-4.356 2.664l2.322 1.116c.288-.882 1.08-1.44 2.034-1.44.9 0 1.512.486 1.512 1.224v.324l-3.078.648c-1.998.414-3.15 1.368-3.15 2.826 0 1.638 1.404 2.898 3.636 2.898 1.134 0 2.034-.342 2.772-1.116v.9h2.52v-6.48c0-2.106-1.71-3.564-4.212-3.564Zm-.666 8.28c-.774 0-1.26-.36-1.26-.954 0-.45.288-.792.846-.918l2.592-.576v.468c0 1.098-.954 1.98-2.178 1.98Zm11.14-8.172c-1.206 0-2.16.36-2.664 1.584v-1.476h-2.52V21h2.7v-5.292c0-1.458.9-2.304 2.214-2.304h1.296v-2.34H39.55Zm9.023.108v1.044c-.684-.792-1.692-1.26-2.97-1.26-2.502 0-4.842 1.782-4.842 4.752 0 2.898 2.232 4.806 4.896 4.806 1.098 0 2.052-.342 2.736-.99v.954c0 1.278-1.008 2.088-2.358 2.088-1.188 0-2.016-.63-2.322-1.692l-2.304 1.134c.576 1.8 2.376 2.988 4.626 2.988 2.736 0 5.058-1.764 5.058-4.518v-9.306h-2.52ZM46 18.066c-1.386 0-2.448-.954-2.448-2.322 0-1.404 1.098-2.358 2.448-2.358 1.35 0 2.394.954 2.394 2.358 0 1.368-1.008 2.322-2.394 2.322Zm11.242 3.15c2.916 0 5.256-2.16 5.256-5.13 0-2.97-2.34-5.13-5.256-5.13-2.916 0-5.256 2.16-5.256 5.13 0 2.97 2.34 5.13 5.256 5.13Zm0-2.43c-1.476 0-2.466-1.116-2.466-2.7 0-1.566.99-2.7 2.466-2.7 1.476 0 2.466 1.134 2.466 2.7 0 1.584-.99 2.7-2.466 2.7Zm11.43-7.83c-1.242 0-2.25.45-2.754 1.404v-1.188h-2.52V21h2.7v-5.742c0-1.134.739-1.872 1.8-1.872 1.063 0 1.8.738 1.8 1.872V21h2.7v-6.318c0-2.232-1.512-3.726-3.726-3.726Z'
fill='#1A202C'
/>
</svg>
),
});
export const ArgonLogoLight = createIcon({
displayName: 'ArgonLogoLight',
viewBox: '0 0 74 27',
path: (
<svg width='74' height='27' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M2.256 15.552 0 11.643 2.636 7.1l5.253-.01 2.256 3.908 4.209.002 2.602 4.507-2.65 4.518-4.194.024-2.118 3.62-5.238.036-2.602-4.507 2.102-3.645Zm11.177 2.96 1.773-3.003-1.745-3.022-3.488.033-1.584 2.721 1.895 3.283 3.15-.011Zm-6.311 3.644 1.585-2.72-1.896-3.284-3.149.012-1.772 3.003 1.745 3.023 3.487-.034Zm-.154-7.553 1.773-3.004-1.745-3.022-3.488.033-1.772 3.003 1.745 3.023 3.487-.034Z'
fill='#fff'
/>
<path
d='M28.612 10.956c-2.088 0-3.78 1.044-4.356 2.664l2.322 1.116c.288-.882 1.08-1.44 2.034-1.44.9 0 1.512.486 1.512 1.224v.324l-3.078.648c-1.998.414-3.15 1.368-3.15 2.826 0 1.638 1.404 2.898 3.636 2.898 1.134 0 2.034-.342 2.772-1.116v.9h2.52v-6.48c0-2.106-1.71-3.564-4.212-3.564Zm-.666 8.28c-.774 0-1.26-.36-1.26-.954 0-.45.288-.792.846-.918l2.592-.576v.468c0 1.098-.954 1.98-2.178 1.98Zm11.14-8.172c-1.206 0-2.16.36-2.664 1.584v-1.476h-2.52V21h2.7v-5.292c0-1.458.9-2.304 2.214-2.304h1.296v-2.34h-1.026Zm9.023.108v1.044c-.684-.792-1.692-1.26-2.97-1.26-2.502 0-4.842 1.782-4.842 4.752 0 2.898 2.232 4.806 4.896 4.806 1.098 0 2.052-.342 2.736-.99v.954c0 1.278-1.008 2.088-2.358 2.088-1.188 0-2.016-.63-2.322-1.692l-2.304 1.134c.576 1.8 2.376 2.988 4.626 2.988 2.736 0 5.058-1.764 5.058-4.518v-9.306h-2.52Zm-2.574 6.894c-1.386 0-2.448-.954-2.448-2.322 0-1.404 1.098-2.358 2.448-2.358 1.35 0 2.394.954 2.394 2.358 0 1.368-1.008 2.322-2.394 2.322Zm11.242 3.15c2.916 0 5.256-2.16 5.256-5.13 0-2.97-2.34-5.13-5.256-5.13-2.916 0-5.256 2.16-5.256 5.13 0 2.97 2.34 5.13 5.256 5.13Zm0-2.43c-1.476 0-2.466-1.116-2.466-2.7 0-1.566.99-2.7 2.466-2.7 1.476 0 2.466 1.134 2.466 2.7 0 1.584-.99 2.7-2.466 2.7Zm11.43-7.83c-1.242 0-2.25.45-2.754 1.404v-1.188h-2.52V21h2.7v-5.742c0-1.134.738-1.872 1.8-1.872s1.8.738 1.8 1.872V21h2.7v-6.318c0-2.232-1.512-3.726-3.726-3.726Z'
fill='#fff'
/>
</svg>
),
});
export const ChakraLogoDark = createIcon({
displayName: 'ChakraLogoDark',
viewBox: '0 0 82 21',
path: (
<svg width='82' height='21' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
d='M31.92 9.422c1.448 0 2.093.933 2.308 1.77l2.034-.74c-.391-1.517-1.8-3.111-4.36-3.111-2.739 0-4.87 2.1-4.87 5.017 0 2.878 2.131 5.037 4.928 5.037 2.503 0 3.93-1.614 4.38-3.092l-1.994-.72c-.215.72-.9 1.75-2.386 1.75-1.428 0-2.66-1.069-2.66-2.975 0-1.906 1.232-2.936 2.62-2.936Zm7.92 2.119c.04-1.205.724-2.139 1.976-2.139 1.427 0 1.956.934 1.956 2.1v5.601h2.268v-5.99c0-2.08-1.134-3.753-3.48-3.753-.998 0-2.074.35-2.72 1.186V3.023h-2.268v14.08h2.269v-5.562Zm7.593 2.995c0 1.498 1.232 2.859 3.226 2.859 1.545 0 2.484-.778 2.934-1.497 0 .758.078 1.147.097 1.205h2.112c-.02-.097-.117-.66-.117-1.517V10.88c0-1.886-1.115-3.54-4.048-3.54-2.347 0-3.833 1.46-4.009 3.093l2.073.467c.098-.953.763-1.712 1.956-1.712 1.251 0 1.799.642 1.799 1.44 0 .33-.157.602-.704.68l-2.445.37c-1.623.233-2.874 1.166-2.874 2.858Zm3.656 1.09c-.9 0-1.388-.584-1.388-1.226 0-.778.567-1.167 1.271-1.283l2.484-.37v.428c0 1.847-1.096 2.45-2.367 2.45Zm15.473-7.994H63.55l-3.656 3.832v-8.44h-2.25v14.08h2.25v-2.645l1.173-1.226 2.796 3.87h2.777l-3.99-5.464 3.912-4.007Zm6.511-.058a3.265 3.265 0 0 0-.606-.058c-1.252 0-2.308.603-2.758 1.633V7.632H67.5v9.471h2.269v-4.512c0-1.77.802-2.78 2.562-2.78.234 0 .489.019.743.058V7.574Zm.544 6.962c0 1.498 1.232 2.859 3.226 2.859 1.545 0 2.484-.778 2.934-1.497 0 .758.078 1.147.097 1.205h2.112c-.02-.097-.117-.66-.117-1.517V10.88c0-1.886-1.115-3.54-4.048-3.54-2.347 0-3.833 1.46-4.009 3.093l2.073.467c.098-.953.763-1.712 1.956-1.712 1.251 0 1.799.642 1.799 1.44 0 .33-.157.602-.704.68l-2.445.37c-1.623.233-2.874 1.166-2.874 2.858Zm3.656 1.09c-.899 0-1.388-.584-1.388-1.226 0-.778.567-1.167 1.271-1.283l2.484-.37v.428c0 1.847-1.095 2.45-2.367 2.45Z'
fill='#374152'
/>
<path
d='M21.116 10.5C21.116 4.701 16.39 0 10.558 0 4.727 0 0 4.701 0 10.5S4.727 21 10.558 21c5.831 0 10.558-4.701 10.558-10.5Z'
fill='url(#Group__a)'
/>
<path
d='m5.715 10.948 7.197-7.108c.134-.133.35.029.26.194l-2.679 4.883c-.06.109.02.242.145.242h4.629c.149 0 .221.181.112.282l-8.112 7.53c-.145.134-.362-.056-.245-.216l3.84-5.268a.163.163 0 0 0-.133-.26H5.83a.163.163 0 0 1-.116-.279Z'
fill='#fff'
/>
<defs>
<linearGradient
id='Group__a'
x1='10.558'
y1='0'
x2='10.558'
y2='21'
gradientUnits='userSpaceOnUse'
>
<stop stopColor='#7BCBD4' />
<stop offset='1' stopColor='#29C6B7' />
</linearGradient>
</defs>
</svg>
),
});
export const ChakraLogoLight = createIcon({
displayName: 'ChakraLogoLight',
viewBox: '0 0 82 21',
path: (
<svg width='82' height='21' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
d='M31.92 9.422c1.448 0 2.093.933 2.308 1.77l2.034-.74c-.391-1.517-1.799-3.111-4.36-3.111-2.738 0-4.87 2.1-4.87 5.017 0 2.878 2.132 5.037 4.928 5.037 2.503 0 3.93-1.614 4.38-3.092l-1.994-.72c-.215.72-.9 1.75-2.386 1.75-1.428 0-2.66-1.069-2.66-2.975 0-1.906 1.232-2.936 2.62-2.936Zm7.921 2.119c.04-1.205.724-2.139 1.975-2.139 1.428 0 1.956.934 1.956 2.1v5.601h2.268v-5.99c0-2.08-1.134-3.753-3.48-3.753-.998 0-2.074.35-2.719 1.186V3.023h-2.268v14.08h2.268v-5.562Zm7.592 2.995c0 1.498 1.232 2.859 3.226 2.859 1.545 0 2.484-.778 2.934-1.497 0 .758.078 1.147.097 1.205h2.112c-.02-.097-.117-.66-.117-1.517V10.88c0-1.886-1.115-3.54-4.048-3.54-2.347 0-3.833 1.46-4.009 3.093l2.073.467c.098-.953.763-1.712 1.956-1.712 1.251 0 1.799.642 1.799 1.44 0 .33-.157.602-.704.68l-2.445.37c-1.623.233-2.874 1.166-2.874 2.858Zm3.656 1.09c-.9 0-1.388-.584-1.388-1.226 0-.778.567-1.167 1.271-1.283l2.484-.37v.428c0 1.847-1.096 2.45-2.367 2.45Zm15.473-7.994h-3.011l-3.657 3.832v-8.44h-2.25v14.08h2.25v-2.646l1.173-1.225 2.796 3.87h2.777l-3.989-5.465 3.911-4.006Zm6.511-.058a3.265 3.265 0 0 0-.606-.058c-1.252 0-2.308.603-2.758 1.633V7.632H67.5v9.471h2.269v-4.512c0-1.77.802-2.78 2.562-2.78.234 0 .489.019.743.058V7.574Zm.544 6.962c0 1.498 1.231 2.859 3.226 2.859 1.545 0 2.484-.778 2.933-1.497 0 .758.079 1.147.098 1.205h2.112c-.02-.097-.117-.66-.117-1.517V10.88c0-1.886-1.115-3.54-4.048-3.54-2.347 0-3.833 1.46-4.009 3.093l2.073.467c.098-.953.763-1.712 1.956-1.712 1.251 0 1.799.642 1.799 1.44 0 .33-.157.602-.704.68l-2.445.37c-1.623.233-2.874 1.166-2.874 2.858Zm3.656 1.09c-.9 0-1.388-.584-1.388-1.226 0-.778.567-1.167 1.271-1.283l2.483-.37v.428c0 1.847-1.094 2.45-2.366 2.45ZM21.116 10.5C21.116 4.701 16.39 0 10.558 0 4.727 0 0 4.701 0 10.5S4.727 21 10.558 21c5.831 0 10.558-4.701 10.558-10.5Z'
fill='#fff'
/>
<path
d='m5.715 10.948 7.197-7.108c.135-.133.351.029.26.194l-2.678 4.883a.163.163 0 0 0 .144.241h4.629c.149 0 .221.182.112.283l-8.112 7.53c-.145.134-.362-.056-.245-.216l3.84-5.268a.163.163 0 0 0-.133-.26H5.83a.163.163 0 0 1-.116-.279Z'
fill='#111C44'
/>
</svg>
),
});
export const ChakraLogoBlue = createIcon({
displayName: 'ChakraLogoBlue',
viewBox: '0 0 82 21',
path: (
<svg width='82' height='21' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
d='M31.92 9.421c1.448 0 2.093.934 2.308 1.77l2.034-.739c-.391-1.517-1.799-3.111-4.36-3.111-2.738 0-4.87 2.1-4.87 5.017 0 2.878 2.132 5.037 4.928 5.037 2.503 0 3.93-1.614 4.38-3.092l-1.994-.72c-.215.72-.9 1.75-2.386 1.75-1.428 0-2.66-1.07-2.66-2.975 0-1.906 1.232-2.937 2.62-2.937Zm7.921 2.12c.04-1.205.724-2.139 1.975-2.139 1.428 0 1.956.934 1.956 2.1v5.601h2.268v-5.99c0-2.08-1.134-3.753-3.48-3.753-.998 0-2.074.35-2.719 1.187V3.023h-2.268v14.08h2.268v-5.562Zm7.592 2.995c0 1.498 1.232 2.859 3.226 2.859 1.545 0 2.484-.778 2.934-1.497 0 .758.078 1.147.097 1.205h2.112c-.02-.097-.117-.661-.117-1.517V10.88c0-1.886-1.115-3.54-4.048-3.54-2.347 0-3.833 1.46-4.009 3.093l2.073.466c.098-.952.763-1.71 1.956-1.71 1.251 0 1.799.64 1.799 1.438 0 .33-.157.603-.704.68l-2.445.37c-1.623.234-2.874 1.167-2.874 2.86Zm3.656 1.09c-.9 0-1.388-.584-1.388-1.226 0-.778.567-1.167 1.271-1.284l2.484-.369v.428c0 1.847-1.096 2.45-2.367 2.45Zm15.473-7.994h-3.011l-3.657 3.832v-8.44h-2.25v14.08h2.25v-2.645l1.173-1.226 2.796 3.87h2.777l-3.989-5.464 3.911-4.007Zm6.511-.058a3.265 3.265 0 0 0-.606-.058c-1.252 0-2.308.602-2.758 1.633V7.632H67.5v9.471h2.269v-4.512c0-1.77.802-2.78 2.562-2.78.234 0 .489.019.743.058V7.574Zm.544 6.962c0 1.498 1.231 2.859 3.226 2.859 1.545 0 2.484-.778 2.933-1.497 0 .758.079 1.147.098 1.205h2.112c-.02-.097-.117-.661-.117-1.517V10.88c0-1.886-1.115-3.54-4.048-3.54-2.347 0-3.833 1.46-4.009 3.093l2.073.466c.098-.952.763-1.71 1.956-1.71 1.251 0 1.799.64 1.799 1.438 0 .33-.157.603-.704.68l-2.445.37c-1.623.234-2.874 1.167-2.874 2.86Zm3.656 1.09c-.9 0-1.388-.584-1.388-1.226 0-.778.567-1.167 1.271-1.284l2.483-.369v.428c0 1.847-1.094 2.45-2.366 2.45ZM21.116 10.5C21.116 4.701 16.39 0 10.558 0 4.727 0 0 4.701 0 10.5S4.727 21 10.558 21c5.831 0 10.558-4.701 10.558-10.5Z'
fill='#fff'
/>
<path
d='m5.715 10.948 7.197-7.108c.135-.133.351.03.26.194l-2.678 4.883a.163.163 0 0 0 .144.242h4.629c.149 0 .221.181.112.283L7.267 16.97c-.145.135-.362-.056-.245-.216l3.84-5.268a.163.163 0 0 0-.133-.26H5.83a.163.163 0 0 1-.116-.279Z'
fill='#3182CE'
/>
</svg>
),
});
export const BitcoinLogo = createIcon({
displayName: 'BitcoinLogo',
viewBox: '0 0 67 14',
path: (
<svg width='67' height='14' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
d='M13.779 8.694A6.993 6.993 0 1 1 .209 5.308a6.992 6.992 0 1 1 13.57 3.386Z'
fill='#F7931A'
/>
<path
d='M10.078 6.004c.14-.932-.57-1.433-1.539-1.767l.315-1.261-.768-.192-.306 1.229c-.202-.05-.409-.098-.615-.145l.309-1.237-.768-.191-.314 1.26a25.67 25.67 0 0 1-.49-.115v-.004l-1.058-.264-.204.82s.57.13.558.139c.31.077.367.283.357.446L5.197 6.16c.021.005.05.013.08.025l-.081-.02-.502 2.014c-.038.094-.135.236-.352.182.008.011-.558-.14-.558-.14l-.38.88.998.249.547.141-.317 1.276.766.192.315-1.263c.21.057.412.11.611.16l-.313 1.256.767.191.318-1.274c1.309.248 2.293.148 2.707-1.036.334-.954-.016-1.504-.705-1.863.501-.116.88-.446.98-1.127Zm-1.754 2.46c-.237.954-1.842.438-2.362.31l.422-1.692c.52.13 2.188.388 1.94 1.382Zm.238-2.474c-.217.867-1.552.427-1.986.318l.383-1.533c.433.108 1.828.31 1.603 1.215Zm11.936-1.754c.568 0 1.058.102 1.47.302.413.201.755.473 1.029.815.27.343.471.744.6 1.204.13.462.195.958.195 1.489 0 .815-.15 1.586-.451 2.312a5.995 5.995 0 0 1-1.23 1.896 5.786 5.786 0 0 1-1.842 1.274 5.617 5.617 0 0 1-2.3.47c-.107 0-.295-.003-.56-.008a8.166 8.166 0 0 1-.91-.08 10.687 10.687 0 0 1-1.09-.213 5.458 5.458 0 0 1-1.089-.39L17.383.428l2.744-.425-1.097 4.57a4.19 4.19 0 0 1 .707-.247c.237-.06.49-.09.761-.09Zm-2.3 7.584c.412 0 .802-.101 1.167-.301.367-.2.684-.47.949-.806a4.07 4.07 0 0 0 .628-1.143 3.9 3.9 0 0 0 .23-1.33c0-.567-.094-1.009-.283-1.329-.189-.318-.538-.478-1.045-.478-.166 0-.38.032-.645.088a1.61 1.61 0 0 0-.718.373l-1.168 4.854c.07.012.133.024.186.035a1.918 1.918 0 0 0 .38.037h.318Zm8.439 1.932h-2.62l2.212-9.318h2.638l-2.23 9.317Zm1.275-10.454c-.366 0-.698-.109-.992-.327-.297-.217-.443-.551-.443-1.001 0-.248.05-.48.15-.7A1.87 1.87 0 0 1 27.6.323c.219-.094.452-.14.7-.14.366 0 .695.108.99.326.295.22.443.554.443 1.002 0 .248-.05.481-.15.7a1.844 1.844 0 0 1-.974.947c-.219.096-.45.141-.698.141Zm3.252-1.186 2.744-.425-.674 2.746h2.94l-.531 2.16H32.72l-.778 3.26a3.69 3.69 0 0 0-.124.761c-.013.237.017.44.088.612a.77.77 0 0 0 .38.398c.184.095.445.143.788.143.283 0 .558-.027.825-.08.264-.053.533-.126.804-.222l.196 2.02c-.355.13-.738.242-1.151.337a6.62 6.62 0 0 1-1.47.14c-.814 0-1.445-.12-1.895-.361-.449-.243-.766-.574-.956-.994-.187-.418-.271-.9-.248-1.442a9.351 9.351 0 0 1 .248-1.72l1.736-7.333Zm4.894 7.918c0-.802.13-1.559.39-2.267A5.58 5.58 0 0 1 37.563 5.9a5.215 5.215 0 0 1 1.762-1.257c.689-.306 1.46-.46 2.31-.46.531 0 1.006.05 1.424.15.42.102.8.234 1.143.399l-.904 2.056a8.454 8.454 0 0 0-.734-.257 3.194 3.194 0 0 0-.93-.116c-.874 0-1.566.302-2.08.903-.513.602-.77 1.412-.77 2.428 0 .602.129 1.09.39 1.462.259.372.738.558 1.433.558a4.841 4.841 0 0 0 1.842-.372l.196 2.108a9.48 9.48 0 0 1-1.098.347c-.402.098-.88.149-1.435.149-.732 0-1.352-.107-1.859-.319a3.54 3.54 0 0 1-1.256-.859 3.24 3.24 0 0 1-.717-1.268 5.205 5.205 0 0 1-.223-1.522Zm11.641 3.969c-.626 0-1.17-.096-1.63-.284a3.009 3.009 0 0 1-1.141-.797 3.443 3.443 0 0 1-.682-1.214 4.903 4.903 0 0 1-.229-1.548c0-.71.114-1.42.345-2.128a6.032 6.032 0 0 1 1.018-1.912 5.441 5.441 0 0 1 1.646-1.393c.648-.359 1.392-.54 2.23-.54.613 0 1.154.096 1.62.285a3.03 3.03 0 0 1 1.152.797c.299.343.527.746.68 1.214.154.465.23.983.23 1.55a7.06 7.06 0 0 1-.336 2.126 6.143 6.143 0 0 1-.991 1.913 5.198 5.198 0 0 1-1.637 1.39c-.655.36-1.414.54-2.275.54Zm1.31-7.582c-.39 0-.733.112-1.027.335a2.894 2.894 0 0 0-.743.851 4.202 4.202 0 0 0-.453 1.125 4.87 4.87 0 0 0-.149 1.16c0 .591.095 1.052.283 1.383.19.33.53.496 1.027.496.39 0 .731-.112 1.027-.337.293-.224.542-.508.743-.85.2-.342.352-.718.453-1.126.099-.406.15-.794.15-1.16 0-.59-.096-1.051-.285-1.382-.189-.33-.531-.495-1.027-.495Zm6.784 7.335h-2.622l2.212-9.318h2.64l-2.23 9.317Zm1.273-10.454c-.365 0-.697-.109-.99-.327-.296-.217-.444-.551-.444-1.001 0-.248.051-.48.151-.7.1-.218.233-.406.399-.566.164-.16.358-.286.575-.382.218-.094.45-.14.698-.14.367 0 .698.108.992.326.295.22.444.554.444 1.002 0 .248-.053.481-.152.7a1.837 1.837 0 0 1-.972.947 1.73 1.73 0 0 1-.7.141Zm2.845 1.559c.2-.058.422-.128.663-.204a9.764 9.764 0 0 1 1.824-.371c.372-.043.795-.063 1.265-.063 1.382 0 2.335.402 2.86 1.205.526.804.617 1.902.276 3.295l-1.205 5.032h-2.638l1.168-4.926c.072-.307.127-.604.169-.895a2.12 2.12 0 0 0-.01-.761.911.911 0 0 0-.326-.532c-.173-.136-.434-.204-.789-.204a5.32 5.32 0 0 0-1.044.108l-1.717 7.21h-2.639l2.143-8.894Z'
fill='#fff'
/>
</svg>
),
});
export const ArgonLogoMinifiedDark = createIcon({
displayName: 'ArgonLogoMinifiedDark',
viewBox: '0 0 36 36',
path: (
<svg width='36' height='36' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M4.79 18.336 0 9.869 5.596.023 16.75 0l4.79 8.467 8.935.004L36 18.237l-5.628 9.789-8.904.052-4.495 7.842L5.85 36 .326 26.234l4.464-7.898Zm23.73 6.415 3.763-6.507-3.705-6.548-7.403.072-3.365 5.896 4.025 7.113 6.685-.026Zm-13.4 7.895 3.365-5.896-4.024-7.113-6.686.026-3.763 6.507 3.705 6.548 7.404-.072Zm-.326-16.366 3.763-6.507-3.704-6.549-7.404.072-3.763 6.507 3.705 6.549 7.403-.072Z'
fill='#1A202C'
/>
</svg>
),
});
export const ArgonLogoMinifiedLight = createIcon({
displayName: 'ArgonLogoMinifiedLight',
viewBox: '0 0 36 36',
path: (
<svg width='36' height='36' fill='none' xmlns='http://www.w3.org/2000/svg'>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M4.79 18.336 0 9.869 5.596.023 16.75 0l4.79 8.467 8.935.004L36 18.237l-5.628 9.789-8.904.052-4.495 7.842L5.85 36 .326 26.234l4.464-7.898Zm23.73 6.415 3.763-6.507-3.705-6.548-7.403.072-3.365 5.896 4.025 7.113 6.685-.026Zm-13.4 7.895 3.365-5.896-4.024-7.113-6.686.026-3.763 6.507 3.705 6.548 7.404-.072Zm-.326-16.366 3.763-6.507-3.704-6.549-7.404.072-3.763 6.507 3.705 6.549 7.403-.072Z'
fill='#fff'
/>
</svg>
),
});
export const WechatPayIcon = createIcon({
displayName: 'WechatPayIcon',
viewBox: '0 0 24 24',
path: (
<g>
<path
d='M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.17 4.203 3.002 5.55a.59.59 0 01.213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 00.167-.054l1.903-1.114a.864.864 0 01.717-.098 10.16 10.16 0 002.837.403c.276 0 .543-.027.811-.05-.857-2.578.157-5.523 2.619-7.21C11.923 8.507 11.695 8.5 11.465 8.5c-1.66 0-3.274.374-4.774 1.061-.276-.651-.43-1.353-.43-2.081C6.261 4.824 7.321 2.188 8.691 2.188zM18.639 11.698c-4.118 0-7.45 2.649-7.45 5.918 0 3.27 3.332 5.918 7.45 5.918.858 0 1.676-.109 2.435-.304.276-.097.574-.074.858.098l1.549.904c.065.035.13.054.167.054.163 0 .276-.132.276-.295a.516.516 0 00-.035-.195l-.325-1.235a.59.59 0 01.177-.665c1.543-1.235 2.524-2.982 2.524-4.98 0-3.269-3.332-5.918-7.45-5.918h-.176z'
fill='#00D924'
/>
<circle cx='5.5' cy='7.5' r='1' fill='white' />
<circle cx='8.5' cy='7.5' r='1' fill='white' />
<circle cx='11.5' cy='7.5' r='1' fill='white' />
<circle cx='15.5' cy='15.5' r='0.8' fill='white' />
<circle cx='18' cy='15.5' r='0.8' fill='white' />
<circle cx='20.5' cy='15.5' r='0.8' fill='white' />
</g>
),
});
export const QRCodeIcon = createIcon({
displayName: 'QRCodeIcon',
viewBox: '0 0 24 24',
path: (
<g fill='currentColor'>
<rect x='1' y='1' width='6' height='6' rx='1' stroke='currentColor' strokeWidth='1.5' fill='none' />
<rect x='17' y='1' width='6' height='6' rx='1' stroke='currentColor' strokeWidth='1.5' fill='none' />
<rect x='1' y='17' width='6' height='6' rx='1' stroke='currentColor' strokeWidth='1.5' fill='none' />
<rect x='3' y='3' width='2' height='2' />
<rect x='19' y='3' width='2' height='2' />
<rect x='3' y='19' width='2' height='2' />
<rect x='9' y='1' width='2' height='2' />
<rect x='13' y='1' width='2' height='2' />
<rect x='9' y='5' width='2' height='2' />
<rect x='13' y='5' width='2' height='2' />
<rect x='1' y='9' width='2' height='2' />
<rect x='5' y='9' width='2' height='2' />
<rect x='1' y='13' width='2' height='2' />
<rect x='5' y='13' width='2' height='2' />
<rect x='9' y='9' width='6' height='6' rx='1' stroke='currentColor' strokeWidth='1.5' fill='none' />
<rect x='11' y='11' width='2' height='2' />
<rect x='17' y='9' width='2' height='2' />
<rect x='21' y='9' width='2' height='2' />
<rect x='17' y='13' width='2' height='2' />
<rect x='21' y='13' width='2' height='2' />
<rect x='9' y='17' width='2' height='2' />
<rect x='13' y='17' width='2' height='2' />
<rect x='9' y='21' width='2' height='2' />
<rect x='13' y='21' width='2' height='2' />
<rect x='17' y='17' width='6' height='2' />
<rect x='17' y='21' width='6' height='2' />
</g>
),
});

View File

@@ -0,0 +1,17 @@
import { useState } from "react";
const Image = ({ className, ...props }) => {
const [loaded, setLoaded] = useState(false);
return (
<img
className={`inline-block align-top opacity-0 transition-opacity ${
loaded && "opacity-100"
} ${className}`}
onLoad={() => setLoaded(true)}
{...props}
/>
);
};
export default Image;

View File

@@ -0,0 +1,73 @@
import Section from "@/components/Section";
import Image from "@/components/Image";
import Button from "@/components/Button";
type JoinProps = {};
const Join = ({}: JoinProps) => (
<Section crosses>
<div className="container">
<div className="relative max-w-[43.125rem] mx-auto py-8 md:py-14 xl:py-0">
<div className="relative z-1 text-center">
<h1 className="h1 mb-6">
Be part of the future of{" "}
<span className="inline-block relative">
Brainwave
<Image
className="absolute top-full left-0 w-full"
src="/images/curve.png"
width={624}
height={28}
alt="Curve"
/>
</span>
</h1>
<p className="body-1 mb-8 text-n-4">
Unleash the power of AI within Brainwave. Upgrade your
productivity with Brainwave, the open AI chat app.
</p>
<Button href="/pricing" white>
Get started
</Button>
</div>
<div className="absolute top-1/2 left-1/2 w-[46.5rem] h-[46.5rem] border border-n-2/5 rounded-full -translate-x-1/2 -translate-y-1/2 pointer-events-none">
<div className="absolute top-1/2 left-1/2 w-[39.25rem] h-[39.25rem] border border-n-2/10 rounded-full -translate-x-1/2 -translate-y-1/2"></div>
<div className="absolute top-1/2 left-1/2 w-[30.625rem] h-[30.625rem] border border-n-2/10 rounded-full -translate-x-1/2 -translate-y-1/2"></div>
<div className="absolute top-1/2 left-1/2 w-[21.5rem] h-[21.5rem] border border-n-2/10 rounded-full -translate-x-1/2 -translate-y-1/2"></div>
<div className="absolute top-1/2 left-1/2 w-[13.75rem] h-[13.75rem] border border-n-2/10 rounded-full -translate-x-1/2 -translate-y-1/2"></div>
</div>
<div className="absolute top-1/2 left-1/2 w-[46.5rem] h-[46.5rem] border border-n-2/5 rounded-full -translate-x-1/2 -translate-y-1/2 opacity-60 mix-blend-color-dodge pointer-events-none">
<div className="absolute top-1/2 left-1/2 w-[58.85rem] h-[58.85rem] -translate-x-3/4 -translate-y-1/2">
<Image
className="w-full"
src="/images/gradient.png"
width={942}
height={942}
alt="Gradient"
/>
</div>
</div>
</div>
</div>
<div className="absolute -top-[5.75rem] left-[18.5rem] -z-1 w-[19.8125rem] pointer-events-none lg:-top-15 lg:left-[5.5rem]">
<Image
className="w-full"
src="/images/join/shapes-1.svg"
width={317}
height={293}
alt="Shapes 1"
/>
</div>
<div className="absolute right-[15rem] -bottom-[7rem] -z-1 w-[28.1875rem] pointer-events-none lg:right-7 lg:-bottom-[5rem]">
<Image
className="w-full"
src="/images/join/shapes-2.svg"
width={451}
height={266}
alt="Shapes 2"
/>
</div>
</Section>
);
export default Join;

View File

@@ -0,0 +1,12 @@
import { Box, useStyleConfig } from '@chakra-ui/react';
function MainPanel(props) {
const { variant, children, ...rest } = props;
const styles = useStyleConfig('MainPanel', { variant });
return (
<Box __css={styles} minH='100vh' {...rest}>
{children}
</Box>
);
}
export default MainPanel;

View File

@@ -0,0 +1,12 @@
import { Box, useStyleConfig } from "@chakra-ui/react";
function PanelContainer(props) {
const { variant, children, ...rest } = props;
const styles = useStyleConfig("PanelContainer", { variant });
return (
<Box __css={styles} minH="100vh" {...rest}>
{children}
</Box>
);
}
export default PanelContainer;

View File

@@ -0,0 +1,29 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import { Box, useStyleConfig } from "@chakra-ui/react";
function PanelContent(props) {
const { variant, children, ...rest } = props;
const styles = useStyleConfig("PanelContent", { variant });
return (
<Box __css={styles} minH="100vh" {...rest}>
{children}
</Box>
);
}
export default PanelContent;

View File

@@ -0,0 +1,12 @@
import Header from "../Header/index.js";
import Footer from "../Footer/index.js";
const Layout = ({ hideFooter, children }) => (
<div className="pt-[4.75rem] lg:pt-[5.25rem] overflow-hidden">
<Header />
{children}
{hideFooter ? null : <Footer />}
</div>
);
export default Layout;

View File

@@ -0,0 +1,16 @@
import { Link } from "react-router-dom";
import Image from "../Image/index.tsx";
const Logo = ({ className }) => (
<Link className={`block w-[11.875rem] ${className || ""}`} to="/">
<Image
className=""
src="/images/brainwave.svg"
width={190}
height={40}
alt="价值前沿"
/>
</Link>
);
export default Logo;

View File

@@ -0,0 +1,53 @@
import Image from "../Image";
const Logos = ({ className }) => (
<div className={className}>
<h5 className="tagline mb-6 text-center text-n-1/50">
Helping people create beautiful content at
</h5>
<ul className="flex">
<li className="flex items-center justify-center flex-1 h-[8.5rem]">
<Image
src="/images/yourlogo.svg"
width={134}
height={28}
alt="Logo 3"
/>
</li>
<li className="flex items-center justify-center flex-1 h-[8.5rem]">
<Image
src="/images/yourlogo.svg"
width={134}
height={28}
alt="Logo 3"
/>
</li>
<li className="flex items-center justify-center flex-1 h-[8.5rem]">
<Image
src="/images/yourlogo.svg"
width={134}
height={28}
alt="Logo 3"
/>
</li>
<li className="flex items-center justify-center flex-1 h-[8.5rem]">
<Image
src="/images/yourlogo.svg"
width={134}
height={28}
alt="Logo 3"
/>
</li>
<li className="flex items-center justify-center flex-1 h-[8.5rem]">
<Image
src="/images/yourlogo.svg"
width={134}
height={28}
alt="Logo 3"
/>
</li>
</ul>
</div>
);
export default Logos;

View File

@@ -0,0 +1,3 @@
.leaflet-container {
height: 300px;
}

28
src/components/Map/Map.js Normal file
View File

@@ -0,0 +1,28 @@
import { MapContainer, TileLayer, } from 'react-leaflet';
import "./Map.css";
function MapPlaceholder() {
return (
<p>
Map of London.{' '}
<noscript>You need to enable JavaScript to see this map.</noscript>
</p>
)
}
function Map() {
return (
<MapContainer
center={[51.505, -0.09]}
zoom={13}
scrollWheelZoom={true}
placeholder={<MapPlaceholder />}>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</MapContainer>
)
}
export default Map;

View File

@@ -0,0 +1,52 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
// chakra imports
import { Avatar, Flex, Text, useColorModeValue } from "@chakra-ui/react";
import { ClockIcon } from "components/Icons/Icons";
import React from "react";
export function ItemContent(props) {
const navbarIcon = useColorModeValue("gray.500", "gray.200");
const notificationColor = useColorModeValue("gray.700", "white");
const spacing = " ";
return (
<>
<Avatar
name={props.aName}
src={props.aSrc}
borderRadius="12px"
me="16px"
/>
<Flex flexDirection="column">
<Text fontSize="14px" mb="5px" color={notificationColor}>
<Text fontWeight="bold" fontSize="14px" as="span">
{props.boldInfo}
{spacing}
</Text>
{props.info}
</Text>
<Flex alignItems="center">
<ClockIcon color={navbarIcon} w="13px" h="13px" me="3px" />
<Text fontSize="xs" lineHeight="100%" color={navbarIcon}>
{props.time}
</Text>
</Flex>
</Flex>
</>
);
}

View File

@@ -0,0 +1,222 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
// Chakra Imports
import {
Box,
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
Flex,
Link,
useColorModeValue,
} from "@chakra-ui/react";
import { SidebarContext } from "contexts/SidebarContext";
import PropTypes from "prop-types";
import React, { useState, useEffect, useContext } from "react";
import AdminNavbarLinks from "./AdminNavbarLinks";
import { HamburgerIcon } from "@chakra-ui/icons";
export default function AdminNavbar(props) {
const [scrolled, setScrolled] = useState(false);
const {
sidebarWidth,
setSidebarWidth,
toggleSidebar,
setToggleSidebar,
} = useContext(SidebarContext);
useEffect(() => {
window.addEventListener("scroll", changeNavbar);
return () => {
window.removeEventListener("scroll", changeNavbar);
};
});
const {
variant,
children,
fixed,
secondary,
brandText,
onOpen,
...rest
} = props;
// Here are all the props that may change depending on navbar's type or state.(secondary, variant, scrolled)
let mainText =
fixed && scrolled
? useColorModeValue("gray.700", "gray.200")
: useColorModeValue("white", "gray.200");
let secondaryText =
fixed && scrolled
? useColorModeValue("gray.700", "gray.200")
: useColorModeValue("white", "gray.200");
let navbarPosition = "absolute";
let navbarFilter = "none";
let navbarBackdrop = "blur(20px)";
let navbarShadow = "none";
let navbarBg = "none";
let navbarBorder = "transparent";
let secondaryMargin = "0px";
let paddingX = "15px";
if (props.fixed === true)
if (scrolled === true) {
navbarPosition = "fixed";
navbarShadow = useColorModeValue(
"0px 7px 23px rgba(0, 0, 0, 0.05)",
"none"
);
navbarBg = useColorModeValue(
"linear-gradient(112.83deg, rgba(255, 255, 255, 0.82) 0%, rgba(255, 255, 255, 0.8) 110.84%)",
"linear-gradient(112.83deg, rgba(255, 255, 255, 0.21) 0%, rgba(255, 255, 255, 0) 110.84%)"
);
navbarBorder = useColorModeValue("#FFFFFF", "rgba(255, 255, 255, 0.31)");
navbarFilter = useColorModeValue(
"none",
"drop-shadow(0px 7px 23px rgba(0, 0, 0, 0.05))"
);
}
if (props.secondary) {
navbarBackdrop = "none";
navbarPosition = "absolute";
mainText = "white";
secondaryText = "white";
secondaryMargin = "22px";
paddingX = "30px";
}
const changeNavbar = () => {
if (window.scrollY > 1) {
setScrolled(true);
} else {
setScrolled(false);
}
};
return (
<Flex
position={navbarPosition}
boxShadow={navbarShadow}
bg={navbarBg}
borderColor={navbarBorder}
filter={navbarFilter}
backdropFilter={navbarBackdrop}
borderWidth="1.5px"
borderStyle="solid"
transitionDelay="0s, 0s, 0s, 0s"
transitionDuration=" 0.25s, 0.25s, 0.25s, 0s"
transition-property="box-shadow, background-color, filter, border"
transitionTimingFunction="linear, linear, linear, linear"
alignItems={{ xl: "center" }}
borderRadius="16px"
display="flex"
minH="75px"
justifyContent={{ xl: "center" }}
lineHeight="25.6px"
mx="auto"
mt={secondaryMargin}
pb="8px"
left={document.documentElement.dir === "rtl" ? "30px" : ""}
right={document.documentElement.dir === "rtl" ? "" : "30px"}
px={{
sm: paddingX,
md: "30px",
}}
ps={{
xl: "12px",
}}
pt="8px"
top="18px"
w={{ sm: "calc(100vw - 30px)", xl: "calc(100vw - 75px - 275px)" }}
>
<Flex
w="100%"
flexDirection={{
sm: "column",
md: "row",
}}
alignItems={{ xl: "center" }}
>
<Box mb={{ sm: "8px", md: "0px" }}>
<Breadcrumb>
<BreadcrumbItem color={mainText}>
<BreadcrumbLink href="#" color={secondaryText}>
Pages
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem color={mainText}>
<BreadcrumbLink href="#" color={mainText}>
{brandText}
</BreadcrumbLink>
</BreadcrumbItem>
</Breadcrumb>
{/* Here we create navbar brand, based on route name */}
<Link
color={mainText}
href="#"
bg="inherit"
borderRadius="inherit"
fontWeight="bold"
_hover={{ color: { mainText } }}
_active={{
bg: "inherit",
transform: "none",
borderColor: "transparent",
}}
_focus={{
boxShadow: "none",
}}
>
{brandText}
</Link>
</Box>
<HamburgerIcon
w="100px"
h="20px"
ms="20px"
color="#fff"
cursor="pointer"
display={{ sm: "none", xl: "block" }}
onClick={() => {
setSidebarWidth(sidebarWidth === 275 ? 120 : 275);
setToggleSidebar(!toggleSidebar);
}}
/>
<Box ms="auto" w={{ sm: "100%", md: "unset" }}>
<AdminNavbarLinks
onOpen={props.onOpen}
logoText={props.logoText}
secondary={props.secondary}
fixed={props.fixed}
scrolled={scrolled}
/>
</Box>
</Flex>
</Flex>
);
}
AdminNavbar.propTypes = {
brandText: PropTypes.string,
variant: PropTypes.string,
secondary: PropTypes.bool,
fixed: PropTypes.bool,
onOpen: PropTypes.func,
};

View File

@@ -0,0 +1,253 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
// Chakra Icons
import { BellIcon } from "@chakra-ui/icons";
// Chakra Imports
import {
Button,
Flex,
Menu,
MenuButton,
MenuItem,
MenuList,
Text,
Stack,
Box,
useColorMode,
useColorModeValue,
Avatar,
HStack,
Divider,
} from "@chakra-ui/react";
// Assets
import avatar1 from "assets/img/avatars/avatar1.png";
import avatar2 from "assets/img/avatars/avatar2.png";
import avatar3 from "assets/img/avatars/avatar3.png";
// Custom Icons
import { ProfileIcon, SettingsIcon } from "components/Icons/Icons";
// Custom Components
import { ItemContent } from "components/Menu/ItemContent";
import { SearchBar } from "components/Navbars/SearchBar/SearchBar";
import { SidebarResponsive } from "components/Sidebar/Sidebar";
import PropTypes from "prop-types";
import React from "react";
import { NavLink, useNavigate } from "react-router-dom";
import routes from "routes.js";
import {
ArgonLogoDark,
ChakraLogoDark,
ArgonLogoLight,
ChakraLogoLight,
} from "components/Icons/Icons";
import { useAuth } from "contexts/AuthContext";
export default function HeaderLinks(props) {
const {
variant,
children,
fixed,
scrolled,
secondary,
onOpen,
...rest
} = props;
const { colorMode } = useColorMode();
const { user, isAuthenticated, logout } = useAuth();
const navigate = useNavigate();
// Chakra Color Mode
let navbarIcon =
fixed && scrolled
? useColorModeValue("gray.700", "gray.200")
: useColorModeValue("white", "gray.200");
let menuBg = useColorModeValue("white", "navy.800");
if (secondary) {
navbarIcon = "white";
}
const handleLogout = () => {
logout();
navigate("/auth/signin");
};
return (
<Flex
pe={{ sm: "0px", md: "16px" }}
w={{ sm: "100%", md: "auto" }}
alignItems="center"
flexDirection="row"
>
<SearchBar me="18px" />
{/* 用户认证状态 */}
{isAuthenticated ? (
// 已登录用户 - 显示用户菜单
<Menu>
<MenuButton>
<HStack spacing={2} cursor="pointer">
<Avatar
size="sm"
name={user?.name}
src={user?.avatar}
bg="blue.500"
/>
<Text
display={{ sm: "none", md: "flex" }}
color={navbarIcon}
fontSize="sm"
fontWeight="medium"
>
{user?.name || user?.email}
</Text>
</HStack>
</MenuButton>
<MenuList p="16px 8px" bg={menuBg}>
<Flex flexDirection="column">
<MenuItem borderRadius="8px" mb="10px" onClick={() => navigate("/admin/profile")}>
<HStack spacing={3}>
<Avatar size="sm" name={user?.name} src={user?.avatar} />
<Box>
<Text fontWeight="bold" fontSize="sm">{user?.name}</Text>
<Text fontSize="xs" color="gray.500">{user?.email}</Text>
</Box>
</HStack>
</MenuItem>
<Divider my={2} />
<MenuItem borderRadius="8px" mb="10px" onClick={() => navigate("/admin/profile")}>
<Text>个人资料</Text>
</MenuItem>
<MenuItem borderRadius="8px" mb="10px" onClick={() => navigate("/admin/settings")}>
<Text>设置</Text>
</MenuItem>
<Divider my={2} />
<MenuItem borderRadius="8px" onClick={handleLogout}>
<Text color="red.500">退出登录</Text>
</MenuItem>
</Flex>
</MenuList>
</Menu>
) : (
// 未登录用户 - 显示登录按钮
<NavLink to="/auth/signin">
<Button
ms="0px"
px="0px"
me={{ sm: "2px", md: "16px" }}
color={navbarIcon}
variant="no-effects"
rightIcon={
document.documentElement.dir ? (
""
) : (
<ProfileIcon color={navbarIcon} w="22px" h="22px" me="0px" />
)
}
leftIcon={
document.documentElement.dir ? (
<ProfileIcon color={navbarIcon} w="22px" h="22px" me="0px" />
) : (
""
)
}
>
<Text display={{ sm: "none", md: "flex" }}>登录</Text>
</Button>
</NavLink>
)}
<SidebarResponsive
logo={
<Stack direction="row" spacing="12px" align="center" justify="center">
{colorMode === "dark" ? (
<ArgonLogoLight w="74px" h="27px" />
) : (
<ArgonLogoDark w="74px" h="27px" />
)}
<Box
w="1px"
h="20px"
bg={colorMode === "dark" ? "white" : "gray.700"}
/>
{colorMode === "dark" ? (
<ChakraLogoLight w="82px" h="21px" />
) : (
<ChakraLogoDark w="82px" h="21px" />
)}
</Stack>
}
colorMode={colorMode}
secondary={props.secondary}
routes={routes}
{...rest}
/>
<SettingsIcon
cursor="pointer"
ms={{ base: "16px", xl: "0px" }}
me="16px"
onClick={props.onOpen}
color={navbarIcon}
w="18px"
h="18px"
/>
<Menu>
<MenuButton>
<BellIcon color={navbarIcon} w="18px" h="18px" />
</MenuButton>
<MenuList p="16px 8px" bg={menuBg}>
<Flex flexDirection="column">
<MenuItem borderRadius="8px" mb="10px">
<ItemContent
time="13 minutes ago"
info="from Alicia"
boldInfo="New Message"
aName="Alicia"
aSrc={avatar1}
/>
</MenuItem>
<MenuItem borderRadius="8px" mb="10px">
<ItemContent
time="2 days ago"
info="by Josh Henry"
boldInfo="New Album"
aName="Josh Henry"
aSrc={avatar2}
/>
</MenuItem>
<MenuItem borderRadius="8px">
<ItemContent
time="3 days ago"
info="Payment succesfully completed!"
boldInfo=""
aName="Kara"
aSrc={avatar3}
/>
</MenuItem>
</Flex>
</MenuList>
</Menu>
</Flex>
);
}
HeaderLinks.propTypes = {
variant: PropTypes.string,
fixed: PropTypes.bool,
secondary: PropTypes.bool,
onOpen: PropTypes.func,
};

View File

@@ -0,0 +1,675 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
// Chakra imports
import {
Box,
Button,
Flex,
Grid,
HStack,
Icon,
Link,
Menu,
MenuItem,
MenuList,
MenuButton,
Stack,
Text,
useColorModeValue,
useColorMode,
useDisclosure,
} from '@chakra-ui/react';
import bgCard from 'assets/img/background-card-reports.png';
import IconBox from 'components/Icons/IconBox';
import {
CreativeTimLogo,
RocketIcon,
ChakraLogoDark,
ChakraLogoLight,
ArgonLogoDark,
ArgonLogoLight,
ChakraLogoBlue,
} from 'components/Icons/Icons';
import { SidebarResponsive } from 'components/Sidebar/Sidebar';
import PropTypes from 'prop-types';
import { Fragment } from 'react';
import { AiFillStar } from 'react-icons/ai';
import { GoChevronDown, GoChevronRight } from 'react-icons/go';
import { NavLink } from 'react-router-dom';
import { SidebarContext } from 'contexts/SidebarContext';
import routes from 'routes.js';
export default function AuthNavbar(props) {
const { logo, logoText, secondary, sidebarWidth, ...rest } = props;
const { colorMode } = useColorMode();
// Menu States
const {
isOpen: isOpenPages,
onOpen: onOpenPages,
onClose: onClosePages,
} = useDisclosure();
const {
isOpen: isOpenAuth,
onOpen: onOpenAuth,
onClose: onCloseAuth,
} = useDisclosure();
const {
isOpen: isOpenApplication,
onOpen: onOpenApplication,
onClose: onCloseApplication,
} = useDisclosure();
const {
isOpen: isOpenEcommerce,
onOpen: onOpenEcommerce,
onClose: onCloseEcommerce,
} = useDisclosure();
// Menus
let authObject = {};
routes.forEach((route) => {
if (route.items) {
authObject = route.items.find((link) => link.name === 'Authentication');
}
});
let applicationsObject = {};
routes.forEach((route) => {
if (route.items) {
applicationsObject = route.items.find(
(link) => link.name === 'Applications'
);
}
});
let ecommerceObject = {};
routes.forEach((route) => {
if (route.items) {
ecommerceObject = route.items.find((link) => link.name === 'Ecommerce');
}
});
let extraArr = [];
routes.forEach((route) => {
route.items.forEach((item) => {
if (item.items && item.name === 'Pages') {
extraArr = item.items.filter((link) => !link.collapse);
}
});
});
// Chakra color mode
let brand = (
<Link
href={`${process.env.PUBLIC_URL}/#/`}
target='_blank'
display='flex'
lineHeight='100%'
fontWeight='bold'
justifyContent='center'
alignItems='center'
color={mainText}
>
<Stack direction='row' spacing='12px' align='center' justify='center'>
<ArgonLogoLight w='74px' h='27px' />
<Box w='1px' h='20px' bg={'white'} />
<ChakraLogoBlue w='82px' h='21px' />
</Stack>
<Text fontSize='sm' mt='3px'>
{logoText}
</Text>
</Link>
);
const textColor = useColorModeValue('gray.700', '#fff');
let menuBg = useColorModeValue('white', 'navy.900');
let mainText = '#fff';
let navbarBg = 'none';
let navbarShadow = 'initial';
let bgButton = useColorModeValue('white', 'navy.900');
let colorButton = useColorModeValue('gray.700', 'white');
let navbarPosition = 'absolute';
if (props.secondary === true) {
brand = (
<Link
href={`${process.env.PUBLIC_URL}/#/`}
target='_blank'
display='flex'
lineHeight='100%'
fontWeight='bold'
justifyContent='center'
alignItems='center'
color={mainText}
>
<Stack direction='row' spacing='12px' align='center' justify='center'>
{colorMode === 'light' ? (
<ArgonLogoDark w='74px' h='27px' />
) : (
<ArgonLogoLight w='74px' h='27px' />
)}
<Box w='1px' h='20px' bg={useColorModeValue('gray.700', 'white')} />
{colorMode === 'light' ? (
<ChakraLogoDark w='82px' h='21px' />
) : (
<ChakraLogoLight w='82px' h='21px' />
)}
</Stack>
<Text fontSize='sm' mt='3px'>
{logoText}
</Text>
</Link>
);
mainText = useColorModeValue('gray.700', 'gray.200');
navbarBg = useColorModeValue('white', 'navy.800');
navbarShadow = useColorModeValue(
'0px 7px 23px rgba(0, 0, 0, 0.05)',
'none'
);
bgButton = useColorModeValue('gray.700', 'white');
colorButton = useColorModeValue('white', 'gray.700');
navbarPosition = 'fixed';
}
const createPagesLinks = (routes) => {
return routes.map((link, key) => {
if (
link.name === 'Applications' ||
link.name === 'Ecommerce' ||
link.name === 'Authentication' ||
link.name === 'RTL' ||
link.name === 'Widgets' ||
link.name === 'Charts' ||
link.name === 'Alerts'
) {
return;
}
if (link.name === 'Pricing Page') {
return (
<Stack key={key} direction='column'>
<Stack
direction='row'
spacing='6px'
align='center'
mb='6px'
cursor='default'
>
<IconBox bg='blue.500' color='white' h='30px' w='30px'>
<RocketIcon color='inherit' />
</IconBox>
<Text fontWeight='bold' fontSize='sm' color={textColor}>
Extra
</Text>
</Stack>
{createExtraLinks(extraArr)}
</Stack>
);
}
if (link.authIcon) {
return (
<Stack key={key} direction='column'>
<Stack
direction='row'
spacing='6px'
align='center'
mb='6px'
cursor='default'
>
<IconBox bg='blue.500' color='white' h='30px' w='30px'>
{link.authIcon}
</IconBox>
<Text fontWeight='bold' fontSize='sm' color={textColor}>
{link.name}
</Text>
</Stack>
{createPagesLinks(link.items)}
</Stack>
);
} else {
if (link.component) {
return (
<NavLink key={key} to={link.layout + link.path}>
<MenuItem
ps='36px'
py='0px'
_hover={{ boxShadow: 'none', bg: 'none' }}
borderRadius='12px'
>
<Text color='gray.400' fontSize='sm' fontWeight='normal'>
{link.name}
</Text>
</MenuItem>
</NavLink>
);
} else {
return <Fragment key={key}>{createPagesLinks(link.items)}</Fragment>;
}
}
});
};
const createExtraLinks = (routes) => {
return routes.map((link, key) => {
return (
<NavLink key={key} to={link.layout + link.path}>
<MenuItem
ps='36px'
py='0px'
_hover={{ boxShadow: 'none', bg: 'none' }}
borderRadius='12px'
>
<Text color='gray.400' fontSize='sm' fontWeight='normal'>
{link.name}
</Text>
</MenuItem>
</NavLink>
);
});
};
const createAuthLinks = (routes) => {
return routes.map((link, key) => {
if (link.authIcon && link.collapse == true) {
return (
<Stack key={key} direction='column' my='auto'>
<Menu placement='right'>
<MenuButton
p='5px'
ps='10px'
borderRadius='8px'
_hover={{
bg: useColorModeValue('gray.200', 'whiteAlpha.200'),
}}
>
<Stack
direction='row'
spacing='0px'
align='center'
cursor='default'
>
<Text
fontWeight='bold'
fontSize='sm'
me='auto'
color={textColor}
>
{link.name}
</Text>
<Icon
as={GoChevronRight}
color={mainText}
w='14px'
h='14px'
fontWeight='2000'
/>
</Stack>
</MenuButton>
<MenuList bg={menuBg}>{createAuthLinks(link.items)}</MenuList>
</Menu>
</Stack>
);
} else {
return (
<NavLink key={key} to={link.layout + link.path}>
<MenuItem ps='36px' py='5px' borderRadius='12px'>
<Text color='gray.400' fontSize='sm' fontWeight='normal'>
{link.name}
</Text>
</MenuItem>
</NavLink>
);
}
});
};
const createApplicationLinks = (routes) => {
return routes.map((link, key) => {
return (
<NavLink key={key} to={link.layout + link.path}>
<Stack direction='row' spacing='12px' align='center' cursor='pointer'>
<IconBox bg='blue.500' color='white' h='30px' w='30px'>
{link.authIcon}
</IconBox>
<Text fontWeight='bold' fontSize='sm' color={textColor}>
{link.name}
</Text>
</Stack>
</NavLink>
);
});
};
const createEcommerceLinks = (routes) => {
return routes.map((link, key) => {
if (link.authIcon) {
return (
<Stack key={key} direction='column'>
<Stack
direction='row'
spacing='6px'
align='center'
mb='6px'
cursor='default'
>
<IconBox bg='blue.500' color='white' h='30px' w='30px'>
{link.authIcon}
</IconBox>
<Text fontWeight='bold' fontSize='sm' color={textColor}>
{link.name}
</Text>
</Stack>
{createPagesLinks(link.items)}
</Stack>
);
} else {
if (link.component) {
return (
<NavLink key={key} to={link.layout + link.path}>
<MenuItem
ps='36px'
py='0px'
_hover={{ boxShadow: 'none', bg: 'none' }}
borderRadius='12px'
>
<Text color='gray.400' fontSize='sm' fontWeight='normal'>
{link.name}
</Text>
</MenuItem>
</NavLink>
);
} else {
return <>{createPagesLinks(link.items)}</>;
}
}
});
};
const linksAuth = (
<HStack display={{ sm: 'none', lg: 'flex' }} spacing='12px'>
<Stack
direction='row'
spacing='4px'
align='center'
color='#fff'
fontWeight='bold'
onMouseEnter={onOpenPages}
onMouseLeave={onClosePages}
cursor='pointer'
position='relative'
>
<Text fontSize='sm' color={mainText}>
Pages
</Text>
<Icon
as={GoChevronDown}
color={mainText}
w='14px'
h='14px'
fontWeight='2000'
/>
<Menu isOpen={isOpenPages}>
<MenuList
bg={menuBg}
p='22px'
minW='550px'
cursor='default'
borderRadius='15px'
position='absolute'
top='30px'
left='-10px'
>
<Grid templateColumns='repeat(3, 1fr)' gap='16px'>
{createPagesLinks(routes)}
</Grid>
</MenuList>
</Menu>
</Stack>
<Stack
direction='row'
spacing='4px'
align='center'
color='#fff'
fontWeight='bold'
onMouseEnter={onOpenAuth}
onMouseLeave={onCloseAuth}
cursor='pointer'
position='relative'
>
<Text fontSize='sm' color={mainText}>
Authentications
</Text>
<Icon
as={GoChevronDown}
color={mainText}
w='14px'
h='14px'
fontWeight='2000'
/>
<Menu isOpen={isOpenAuth}>
<MenuList
bg={menuBg}
p='22px'
minW='450px'
cursor='default'
borderRadius='15px'
position='absolute'
top='30px'
left='-10px'
>
<Stack direction='row' spacing='24px'>
<Flex
direction='column'
justify='center'
align='center'
bgImage={bgCard}
minW='200px'
maxW='200px'
minH='230px'
borderRadius='15px'
>
<IconBox
bg='white'
color='white'
borderRadius='50%'
h='50px'
w='50px'
mb='12px'
>
<Icon as={AiFillStar} w='25px' h='25px' color='blue.500' />
</IconBox>
<Text
fontSize='xl'
fontWeight='bold'
color='#fff'
maxW='80%'
textAlign='center'
>
Explore our utilities pages
</Text>
</Flex>
<Grid templateColumns='1fr' width='100%'>
{createAuthLinks(authObject.items)}
</Grid>
</Stack>
</MenuList>
</Menu>
</Stack>
<Stack
direction='row'
spacing='4px'
align='center'
color='#fff'
fontWeight='bold'
onMouseEnter={onOpenApplication}
onMouseLeave={onCloseApplication}
cursor='pointer'
position='relative'
>
<Text fontSize='sm' color={mainText}>
Application
</Text>
<Icon
as={GoChevronDown}
color={mainText}
w='14px'
h='14px'
fontWeight='2000'
/>
<Menu isOpen={isOpenApplication}>
<MenuList
bg={menuBg}
p='22px'
cursor='default'
borderRadius='15px'
position='absolute'
top='30px'
left='-10px'
>
<Grid templateColumns='1fr' gap='16px'>
{createApplicationLinks(applicationsObject.items)}
</Grid>
</MenuList>
</Menu>
</Stack>
<Stack
direction='row'
spacing='4px'
align='center'
color='#fff'
fontWeight='bold'
onMouseEnter={onOpenEcommerce}
onMouseLeave={onCloseEcommerce}
cursor='pointer'
position='relative'
>
<Text fontSize='sm' color={mainText}>
Ecommerce
</Text>
<Icon
as={GoChevronDown}
color={mainText}
w='14px'
h='14px'
fontWeight='2000'
/>
<Menu isOpen={isOpenEcommerce}>
<MenuList
bg={menuBg}
p='22px'
minW='350px'
cursor='default'
borderRadius='15px'
position='absolute'
top='30px'
left='-10px'
>
<Grid templateColumns='repeat(2, 1fr)' gap='16px'>
{createEcommerceLinks(ecommerceObject.items)}
</Grid>
</MenuList>
</Menu>
</Stack>
</HStack>
);
return (
<SidebarContext.Provider value={{ sidebarWidth }}>
<Flex
position={navbarPosition}
top='16px'
left='50%'
transform='translate(-50%, 0px)'
background={navbarBg}
boxShadow={navbarShadow}
borderRadius='15px'
px='16px'
py='22px'
mx='auto'
width='1044px'
maxW='90%'
alignItems='center'
zIndex='3'
>
<Flex w='100%' justifyContent={{ sm: 'start', lg: 'space-between' }}>
{brand}
<Box
ms={{ base: 'auto', lg: '0px' }}
display={{ base: 'flex', lg: 'none' }}
justifyContent='center'
alignItems='center'
>
<SidebarResponsive
logo={
<Stack
direction='row'
spacing='12px'
align='center'
justify='center'
>
{colorMode === 'dark' ? (
<ArgonLogoLight w='74px' h='27px' />
) : (
<ArgonLogoDark w='74px' h='27px' />
)}
<Box
w='1px'
h='20px'
bg={colorMode === 'dark' ? 'white' : 'gray.700'}
/>
{colorMode === 'dark' ? (
<ChakraLogoLight w='82px' h='21px' />
) : (
<ChakraLogoDark w='82px' h='21px' />
)}
</Stack>
}
logoText={props.logoText}
secondary={props.secondary}
routes={routes}
{...rest}
/>
</Box>
{linksAuth}
<Link href='https://www.creative-tim.com/product/argon-dashboard-chakra-pro'>
<Button
bg={bgButton}
color={colorButton}
fontSize='xs'
variant='no-effects'
px='30px'
display={{
sm: 'none',
lg: 'flex',
}}
>
Free Download
</Button>
</Link>
</Flex>
</Flex>
</SidebarContext.Provider>
);
}
AuthNavbar.propTypes = {
color: PropTypes.oneOf(['primary', 'info', 'success', 'warning', 'danger']),
brandText: PropTypes.string,
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
import React from "react";
import {
IconButton,
Input,
InputGroup,
InputLeftElement,
useColorModeValue,
} from "@chakra-ui/react";
import { SearchIcon } from "@chakra-ui/icons";
export function SearchBar(props) {
// Pass the computed styles into the `__css` prop
const { variant, children, ...rest } = props;
// Chakra Color Mode
const searchIconColor = useColorModeValue("gray.700", "gray.200");
const inputBg = useColorModeValue("white", "navy.800");
return (
<InputGroup borderRadius='8px' w='200px' {...rest}>
<InputLeftElement
children={
<IconButton
bg='inherit'
borderRadius='inherit'
_hover={{}}
_active={{
bg: "inherit",
transform: "none",
borderColor: "transparent",
}}
_focus={{
boxShadow: "none",
}}
icon={
<SearchIcon color={searchIconColor} w='15px' h='15px' />
}></IconButton>
}
/>
<Input
variant='search'
fontSize='xs'
bg={inputBg}
placeholder='Type here...'
/>
</InputGroup>
);
}

View File

@@ -0,0 +1,71 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import {
Button,
Drawer,
DrawerBody,
DrawerCloseButton,
DrawerContent,
DrawerFooter,
DrawerHeader,
Input,
useColorModeValue,
useDisclosure,
} from "@chakra-ui/react";
import { SettingsIcon } from "components/Icons/Icons";
import React from "react";
export function SettingsBar() {
const { isOpen, onOpen, onClose } = useDisclosure();
// Chakra Color Mode
const navbarIcon = useColorModeValue("gray.500", "gray.200");
const settingsRef = React.useRef();
return (
<>
<SettingsIcon
ref={settingsRef}
onClick={onOpen}
color={navbarIcon}
w="18px"
h="18px"
/>
<Drawer
isOpen={isOpen}
placement="right"
onClose={onClose}
finalFocusRef={settingsRef}
>
<DrawerContent>
<DrawerCloseButton />
<DrawerHeader>Create your account</DrawerHeader>
<DrawerBody>
<Input variant="main" placeholder="Type here..." />
</DrawerBody>
<DrawerFooter>
<Button variant="outline" me={3} onClick={onClose}>
Cancel
</Button>
<Button colorScheme="blue">Save</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
</>
);
}

View File

@@ -0,0 +1,49 @@
import Image from "../Image";
const Notification = ({ className, title }) => (
<div
className={`flex items-center p-4 pr-6 bg-[#474060]/40 backdrop-blur border border-n-1/10 rounded-2xl ${
className || ""
}`}
>
<div className="mr-5">
<Image
className="w-full rounded-xl"
src="/images/notification/image-1.png"
width={52}
height={52}
alt="Image"
/>
</div>
<div className="flex-1">
<h6 className="mb-1 font-semibold text-base">{title}</h6>
<div className="flex items-center justify-between">
<ul className="flex -m-0.5">
{[
"/images/notification/image-4.png",
"/images/notification/image-3.png",
"/images/notification/image-2.png",
].map((item, index) => (
<li
className={`flex w-6 h-6 border-2 border-[#2E2A41] rounded-full overflow-hidden ${
index !== 0 ? "-ml-2" : ""
}`}
key={index}
>
<Image
className="w-full"
src={item}
width={20}
height={20}
alt={item}
/>
</li>
))}
</ul>
<div className="body-2 text-[#6C7275]">1m ago</div>
</div>
</div>
</div>
);
export default Notification;

View File

@@ -0,0 +1,91 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import { useColorMode } from '@chakra-ui/react';
import { PinInput } from 'react-input-pin-code';
export function PinInputLight(props) {
const { variant, children, ...rest } = props;
const { colorMode } = useColorMode();
return (
<>
{colorMode == 'light' ? (
<PinInput
length={4}
values={[]}
initialValue=''
inputStyle={{ background: 'white' }}
onChange={() => {}}
type={'number'}
inputMode='number'
style={{ padding: '10px' }}
autoSelect={true}
regexCriteria={/^[ A-Za-z0-9_@./#&+-]*$/}
/>
) : (
<PinInput
length={4}
values={[]}
initialValue=''
inputStyle={{ background: '#1B254B' }}
onChange={() => {}}
type={'number'}
inputMode='number'
style={{ padding: '10px' }}
autoSelect={true}
regexCriteria={/^[ A-Za-z0-9_@./#&+-]*$/}
/>
)}
</>
);
}
export function PinInputDark(props) {
const { variant, children, ...rest } = props;
const { colorMode } = useColorMode();
return (
<>
{colorMode === 'light' ? (
<PinInput
length={4}
values={[]}
initialValue={''}
inputStyle={{ background: 'white' }}
onChange={() => {}}
type={'number'}
inputMode='number'
style={{ padding: '10px' }}
autoSelect={true}
regexCriteria={/^[ A-Za-z0-9_@./#&+-]*$/}
/>
) : (
<PinInput
length={4}
initialValue=''
values={[]}
inputStyle={{ background: '#111C44' }}
onChange={() => {}}
type={'number'}
inputMode='number'
style={{ padding: '10px' }}
autoSelect={true}
regexCriteria={/^[ A-Za-z0-9_@./#&+-]*$/}
/>
)}
</>
);
}

View File

@@ -0,0 +1,138 @@
import { useRef, useState } from "react";
import { Splide, SplideTrack, SplideSlide } from "@splidejs/react-splide";
import Button from "@/components/Button";
import Image from "@/components/Image";
import { pricing } from "@/mocks/pricing";
type PricingListProps = {
monthly?: boolean;
};
const PricingList = ({ monthly = true }: PricingListProps) => {
const [activeIndex, setActiveIndex] = useState<number>(0);
const ref = useRef<any>(null);
const handleClick = (index: number) => {
setActiveIndex(index);
ref.current?.go(index);
};
return (
<Splide
className="splide-pricing splide-visible"
options={{
mediaQuery: "min",
autoWidth: true,
pagination: false,
arrows: false,
gap: "1rem",
breakpoints: {
1024: {
destroy: true,
},
},
}}
onMoved={(e, newIndex) => setActiveIndex(newIndex)}
hasTrack={false}
ref={ref}
>
<SplideTrack>
{pricing.map((item, index) => (
<SplideSlide
className={`${index === 1 ? "" : "py-3"}`}
key={item.id}
>
<div
className={`w-[19rem] h-full px-6 ${
index === 1 ? "py-12" : "py-8"
} bg-n-8 border border-n-6 rounded-[2rem] lg:w-auto`}
key={item.id}
>
<h4
className={`h4 mb-4 ${
index === 0 ? "text-color-2" : ""
} ${index === 1 ? "text-color-1" : ""} ${
index === 2 ? "text-color-3" : ""
}`}
>
{item.title}
</h4>
<p className="body-2 min-h-[4rem] mb-3 text-n-1/50">
{item.description}
</p>
<div className="flex items-center h-[5.5rem] mb-6">
{item.price && (
<>
<div className="h3">$</div>
<div className="text-[5.5rem] leading-none font-bold">
{monthly
? item.price
: item.price !== "0"
? (
+item.price *
12 *
0.9
).toFixed(1)
: item.price}
</div>
</>
)}
</div>
<Button
className="w-full mb-6"
href={
item.price
? "/pricing"
: "mailto:info@ui8.net"
}
white={!!item.price}
>
{item.price ? "Get started" : "Contact us"}
</Button>
<ul>
{item.features.map((feature, index) => (
<li
className="flex items-start py-5 border-t border-n-6"
key={index}
>
<Image
src="/images/check.svg"
width={24}
height={24}
alt="Check"
/>
<p className="body-2 ml-4">{feature}</p>
</li>
))}
</ul>
</div>
</SplideSlide>
))}
</SplideTrack>
<div className="flex justify-center mt-8 -mx-2 md:mt-15 lg:hidden">
{pricing.map((item, index) => (
<button
className="relative w-6 h-6 mx-2"
onClick={() => handleClick(index)}
key={item.id}
>
<span
className={`absolute inset-0 bg-conic-gradient rounded-full transition-opacity ${
index === activeIndex
? "opacity-100"
: "opacity-0"
}`}
></span>
<span className="absolute inset-0.25 bg-n-8 rounded-full">
<span className="absolute inset-2 bg-n-1 rounded-full"></span>
</span>
</button>
))}
</div>
</Splide>
);
};
export default PricingList;

View File

@@ -0,0 +1,272 @@
import React from "react";
import {
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalBody,
ModalCloseButton,
Text,
Box,
VStack,
Divider,
useColorModeValue
} from "@chakra-ui/react";
const PrivacyPolicyModal = ({ isOpen, onClose }) => {
const modalBg = useColorModeValue("white", "gray.800");
const headingColor = useColorModeValue("gray.800", "white");
const textColor = useColorModeValue("gray.600", "gray.300");
return (
<Modal
isOpen={isOpen}
onClose={onClose}
size="full"
scrollBehavior="inside"
isCentered
>
<ModalOverlay bg="blackAlpha.600" />
<ModalContent
maxW="95vw"
maxH="95vh"
bg={modalBg}
borderRadius="xl"
boxShadow="2xl"
mx={4}
>
<ModalHeader
fontSize="2xl"
fontWeight="bold"
color={headingColor}
borderBottom="1px solid"
borderColor="gray.200"
borderRadius="xl xl 0 0"
py={6}
>
隐私政策
</ModalHeader>
<ModalCloseButton
size="lg"
_hover={{ bg: "gray.100" }}
/>
<ModalBody py={8} px={8}>
<VStack spacing={6} align="stretch">
<Box bg="blue.50" p={4} borderRadius="md" border="1px solid" borderColor="blue.100">
<Text fontSize="md" color="blue.600" mb={2} fontWeight="semibold">
生效日期2025年1月20日
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.8" mb={4}>
北京价值前沿科技有限公司以下简称"我们"深知个人信息对您的重要性并会尽全力保护您的个人信息安全可靠我们致力于维持您对我们的信任恪守以下原则保护您的个人信息权责一致原则目的明确原则选择同意原则最少够用原则确保安全原则主体参与原则公开透明原则等同时我们承诺我们将按业界成熟的安全标准采取相应的安全保护措施来保护您的个人信息
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.8" fontWeight="medium">
请在使用我们的产品或服务仔细阅读并了解本隐私政策
</Text>
</Box>
<Divider />
<Box>
<Text fontSize="xl" fontWeight="bold" color={headingColor} mb={4}>
我们如何收集和使用您的个人信息
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
根据信息安全技术个人信息安全规范GB/T 352732020个人信息是指以电子或者其他方式记录的能够单独或者与其他信息结合识别特定自然人身份或者反映特定自然人活动情况的各种信息本隐私政策中涉及的个人信息包括基本信息包括性别地址地区个人电话号码电子邮箱个人身份信息包括身份证护照相关身份证明等网络身份标识信息包括系统账号IP地址口令个人上网记录包括登录记录浏览记录个人常用设备信息包括硬件型号操作系统类型应用安装列表运行中进程信息设备MAC地址软件列表设备识别码如IMEI/android ID/IDFA/IMSI 在内的描述个人常用设备基本情况的信息个人位置信息包括精准定位信息经纬度等
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
个人敏感信息是指一旦泄露非法提供或滥用可能危害人身和财产安全极易导致个人名誉身心健康受到损害或歧视性待遇等的个人信息本隐私政策中涉及的个人敏感信息包括个人身份信息包括身份证护照相关身份证明等网络身份识别信息包括账户名账户昵称用户头像与前述有关的密码其他信息包括个人电话号码浏览记录精准定位信息对于个人敏感信息我们将在本政策中进行显著标识请您仔细阅读
</Text>
</Box>
<Box pl={4} borderLeft="3px solid" borderColor="green.300" bg="green.50" p={4} borderRadius="md">
<Text fontSize="xl" fontWeight="semibold" color="green.700" mb={2}>
手机号注册/登录
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.8" mb={4}>
当您使用手机号注册/登录服务时我们会收集您的手机号码验证码匹配结果手机系统平台等信息用于保存您的登录信息使您在使用不同设备登录时能够同步您的数据
</Text>
</Box>
<Box pl={4} borderLeft="3px solid" borderColor="purple.300" bg="purple.50" p={4} borderRadius="md">
<Text fontSize="xl" fontWeight="semibold" color="purple.700" mb={2}>
第三方登录
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.8" mb={4}>
当您使用微信/QQ等第三方登录时我们会收集您第三方的唯一标识头像昵称用于保存您的登录信息使您在使用不同设备登录时能够同步您的数据
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.8" mb={4}>
当您使用微信,微博QQ 进行三方分享的时候我们的产品可能会集成第三方的SDK或其他类似的应用程序用于三方登录以及分享内容到三方平台您可以登陆以下网址了解相关隐私政策
</Text>
<VStack align="start" spacing={2} pl={4}>
<Text fontSize="md" color="blue.600" lineHeight="1.6">
新浪微博微博个人信息保护政策https://m.weibo.cn/c/privacy
</Text>
<Text fontSize="md" color="blue.600" lineHeight="1.6">
微信微信开放平台开发者服务协议https://open.weixin.qq.com/cgi-bin/frame?t=news/protocol_developer_tmpl
</Text>
<Text fontSize="md" color="blue.600" lineHeight="1.6">
QQQQ互联SDK隐私保护声明https://wiki.connect.qq.com/qq互联sdk隐私保护声明
</Text>
</VStack>
</Box>
<Box pl={4} borderLeft="3px solid" borderColor="orange.300" bg="orange.50" p={4} borderRadius="md">
<Text fontSize="xl" fontWeight="semibold" color="orange.700" mb={2}>
第三方支付
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.8" mb={4}>
当您使用 微信 支付宝 华为 进行三方支付的时候我们的产品可能会集成第三方的SDK或其他类似的应用程序帮助用户在应用内使用三方支付
</Text>
<VStack align="start" spacing={2} pl={4}>
<Text fontSize="md" color="blue.600" lineHeight="1.6">
支付宝客户端 SDK 隐私说明https://opendocs.alipay.com/open/01g6qm
</Text>
<Text fontSize="md" color="blue.600" lineHeight="1.6">
微信支付微信支付服务协议https://pay.weixin.qq.com/index.php/public/apply_sign/protocol_v2
</Text>
<Text fontSize="md" color="blue.600" lineHeight="1.6">
华为支付SDK数据安全说明https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/sdk-data-security-0000001050044906
</Text>
</VStack>
</Box>
<Divider />
<Box>
<Text fontSize="xl" fontWeight="bold" color={headingColor} mb={4}>
我们如何使用 Cookie 和同类技术
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
为确保网站正常运转我们会在您的计算机或移动设备上存储名为 Cookie 的小数据文件Cookie 通常包含标识符站点名称以及一些号码和字符借助于 Cookie网站能够存储您的偏好或购物篮内的商品等数据
</Text>
</Box>
<Divider />
<Box>
<Text fontSize="xl" fontWeight="bold" color={headingColor} mb={4}>
我们如何共享转让公开披露您的个人信息
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
我们不会向其他任何公司组织和个人分享您的个人信息但以下情况除外
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={2}>
1在获取明确同意的情况下共享获得您的明确同意后我们会与其他方共享您的个人信息
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={2}>
2我们可能会根据法律法规规定或按政府主管部门的强制性要求对外共享您的个人信息
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
3与我们的关联公司共享您的个人信息可能会与我们关联公司共享我们只会共享必要的个人信息且受本隐私政策中所声明目的的约束关联公司如要改变个人信息的处理目的将再次征求您的授权同意
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
我们的关联公司包括北京价值经纬咨询有限责任公司等
</Text>
</Box>
<Divider />
<Box>
<Text fontSize="xl" fontWeight="bold" color={headingColor} mb={4}>
我们如何保护您的个人信息
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
我们已使用符合业界标准的安全防护措施保护您提供的个人信息防止数据遭到未经授权访问公开披露使用修改损坏或丢失我们会采取一切合理可行的措施保护您的个人信息例如在您的浏览器与"服务"之间交换数据如信用卡信息时受 SSL 加密保护我们同时对我们网站提供 https 安全浏览方式我们会使用加密技术确保数据的保密性我们会使用受信赖的保护机制防止数据遭到恶意攻击我们会部署访问控制机制确保只有授权人员才可访问个人信息以及我们会举办安全和隐私保护培训课程加强员工对于保护个人信息重要性的认识
</Text>
</Box>
<Divider />
<Box>
<Text fontSize="xl" fontWeight="bold" color={headingColor} mb={4}>
您的权利
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
按照中国相关的法律法规标准以及其他国家地区的通行做法我们保障您对自己的个人信息行使以下权利
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={2}>
访问您的个人信息
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={2}>
更正您的个人信息
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={2}>
删除您的个人信息
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
约束信息系统自动决策
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
如果您无法通过上述链接更正这些个人信息您可以随时使用我们的 Web 表单联系或发送电子邮件至admin@valuefrontier.cn我们将在30天内回复您的更正请求
</Text>
</Box>
<Divider />
<Box>
<Text fontSize="xl" fontWeight="bold" color={headingColor} mb={4}>
我们如何处理儿童的个人信息
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
我们的产品网站和服务主要面向成人如果没有父母或监护人的同意儿童不得创建自己的用户账户
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
对于经父母同意而收集儿童个人信息的情况我们只会在受到法律允许父母或监护人明确同意或者保护儿童所必要的情况下使用或公开披露此信息
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
尽管当地法律和习俗对儿童的定义不同但我们将不满 14 周岁的任何人均视为儿童
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
如果我们发现自己在未事先获得可证实的父母同意的情况下收集了儿童的个人信息则会设法尽快删除相关数据
</Text>
</Box>
<Divider />
<Box>
<Text fontSize="xl" fontWeight="bold" color={headingColor} mb={4}>
本隐私政策如何更新
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
我们可能适时会对本隐私政策进行调整或变更本隐私政策的任何更新将在用户启动应用时以弹窗形式提醒用户更新内容并提示查看最新的隐私政策提醒用户重新确认是否同意隐私政策条款除法律法规或监管规定另有强制性规定外经调整或变更的内容一经用户确认后将即时生效
</Text>
</Box>
<Divider />
<Box>
<Text fontSize="xl" fontWeight="bold" color={headingColor} mb={4}>
如何联系我们
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
如果您对本隐私政策有任何疑问意见或建议通过以下方式与我们联系
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
邮箱admin@valuefrontier.cn
</Text>
</Box>
<Divider />
<Box>
<Text fontSize="xl" fontWeight="bold" color={headingColor} mb={4}>
未成年人保护方面
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
1若您是未满18周岁的未成年人您应在您的监护人监护指导下并获得监护人同意的情况下认真阅读并同意本协议后方可使用价值前沿app及相关服务若您未取得监护人的同意监护人可以通过联系价值前沿官方公布的客服联系方式通知价值前沿处理相关账号价值前沿有权对相关账号的功能使用进行限制包括但不限于浏览发布信息互动交流等功能
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
2价值前沿重视对未成年人个人信息的保护未成年用户在填写个人信息时请加强个人保护意识并谨慎对待并应在取得监护人的同意以及在监护人指导下正确使用价值前沿app及相关服务
</Text>
<Text fontSize="xl" color={textColor} lineHeight="1.6" mb={4}>
3未成年人用户及其监护人理解并确认如您违反法律法规本协议内容则您及您的监护人应依照法律规定承担因此而可能导致的全部法律责任
</Text>
</Box>
</VStack>
</ModalBody>
</ModalContent>
</Modal>
);
};
export default PrivacyPolicyModal;

View File

@@ -0,0 +1,41 @@
// src/components/ProtectedRoute.js - Session版本
import React from 'react';
import { Navigate } from 'react-router-dom';
import { Box, VStack, Spinner, Text } from '@chakra-ui/react';
import { useAuth } from '../contexts/AuthContext';
const ProtectedRoute = ({ children }) => {
const { isAuthenticated, isLoading, user } = useAuth();
// 显示加载状态
if (isLoading) {
return (
<Box
height="100vh"
display="flex"
alignItems="center"
justifyContent="center"
bg="gray.50"
>
<VStack spacing={4}>
<Spinner size="xl" color="blue.500" thickness="4px" />
<Text fontSize="lg" color="gray.600">正在验证登录状态...</Text>
</VStack>
</Box>
);
}
// 检查是否已登录
if (!isAuthenticated || !user) {
// 记录当前路径,登录后可以回到这里
const currentPath = window.location.pathname + window.location.search;
const redirectUrl = `/auth/signin?redirect=${encodeURIComponent(currentPath)}`;
return <Navigate to={redirectUrl} replace />;
}
// 已登录,渲染子组件
return children;
};
export default ProtectedRoute;

View File

@@ -0,0 +1,30 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import { CacheProvider } from "@emotion/react";
import createCache from "@emotion/cache";
import rtl from "stylis-plugin-rtl";
// NB: A unique `key` is important for it to work!
const options = {
rtl: { key: "css-ar", stylisPlugins: [rtl] },
ltr: { key: "css-en" },
};
export function RtlProvider({ children }) {
const dir = document.documentElement.dir == "ar" ? "rtl" : "ltr";
const cache = createCache(options[dir]);
return <CacheProvider value={cache} children={children} />;
}

View File

@@ -0,0 +1,108 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import React from "react";
export const renderTrack = ({ style, ...props }) => {
const trackStyle = {
position: "absolute",
maxWidth: "100%",
width: 6,
transition: "opacity 200ms ease 0s",
opacity: 0,
bottom: 2,
top: 2,
borderRadius: 3,
right: 0,
};
return <div style={{ ...style, ...trackStyle }} {...props} />;
};
export const renderTrackRTL = ({ style, ...props }) => {
const trackStyle = {
position: "absolute",
width: 6,
transition: "opacity 200ms ease 0s",
opacity: 0,
bottom: 2,
top: 2,
borderRadius: 3,
right: "unset",
left: 0,
};
return <div style={{ ...style, ...trackStyle }} {...props} />;
};
export const renderThumbDark = ({ style, ...props }) => {
const thumbStyle = {
borderRadius: 15,
background: "rgba(222, 222, 222, .1)",
};
return <div style={{ ...style, ...thumbStyle }} {...props} />;
};
export const renderThumbLight = ({ style, ...props }) => {
const thumbStyle = {
borderRadius: 15,
background: "rgba(48, 48, 48, .1)",
};
return <div style={{ ...style, ...thumbStyle }} {...props} />;
};
export const renderView = ({ style, ...props }) => {
const viewStyle = {
marginRight: -25,
};
return <div style={{ ...style, ...viewStyle }} {...props} />;
};
export const renderViewRTL = ({ style, ...props }) => {
const viewStyle = {
marginRight: "unset",
marginLeft: -15,
};
return <div style={{ ...style, ...viewStyle }} {...props} />;
};
export const kanbanRenderTrack = ({ style, ...props }) => {
const trackStyle = {
width: 6,
transition: "opacity 200ms ease 0s",
opacity: 0,
bottom: 2,
top: 2,
borderRadius: 3,
right: 0,
};
return <div style={{ ...style, ...trackStyle }} {...props} />;
};
export const kanbanRenderThumbDark = ({ style, ...props }) => {
const thumbStyle = {
borderRadius: 15,
background: "rgba(222, 222, 222, .1)",
};
return <div style={{ ...style, ...thumbStyle }} {...props} />;
};
export const kanbanRenderThumbLight = ({ style, ...props }) => {
const thumbStyle = {
borderRadius: 15,
background: "rgba(48, 48, 48, .1)",
};
return <div style={{ ...style, ...thumbStyle }} {...props} />;
};
export const kanbanRenderView = ({ style, ...props }) => {
const viewStyle = {
position: "relative",
marginRight: -15,
};
return <div style={{ ...style, ...viewStyle }} {...props} />;
};

View File

@@ -0,0 +1,57 @@
const Section = ({
className,
crosses,
crossesOffset,
customPaddings,
children,
}) => (
<div
className={`relative ${
customPaddings ||
`py-10 lg:py-16 xl:py-20 ${crosses ? "lg:py-32 xl:py-40" : ""}`
} ${className || ""}`}
>
{children}
<div className="hidden absolute top-0 left-5 w-0.25 h-full bg-stroke-1 pointer-events-none md:block lg:left-7.5 xl:left-10"></div>
<div className="hidden absolute top-0 right-5 w-0.25 h-full bg-stroke-1 pointer-events-none md:block lg:right-7.5 xl:right-10"></div>
{crosses && (
<>
<div
className={`hidden absolute top-0 left-7.5 right-7.5 h-0.25 bg-stroke-1 ${
crossesOffset && crossesOffset
} pointer-events-none lg:block xl:left-10 right-10`}
></div>
<svg
className={`hidden absolute -top-[0.3125rem] left-[1.5625rem] ${
crossesOffset && crossesOffset
} pointer-events-none lg:block xl:left-[2.1875rem]`}
xmlns="http://www.w3.org/2000/svg"
width="11"
height="11"
fill="none"
>
<path
d="M7 1a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h2a1 1 0 0 1 1 1v2a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1V8a1 1 0 0 1 1-1h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H8a1 1 0 0 1-1-1V1z"
fill="#ada8c4"
/>
</svg>
<svg
className={`hidden absolute -top-[0.3125rem] right-[1.5625rem] ${
crossesOffset && crossesOffset
} pointer-events-none lg:block xl:right-[2.1875rem]`}
xmlns="http://www.w3.org/2000/svg"
width="11"
height="11"
fill="none"
>
<path
d="M7 1a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h2a1 1 0 0 1 1 1v2a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1V8a1 1 0 0 1 1-1h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H8a1 1 0 0 1-1-1V1z"
fill="#ada8c4"
/>
</svg>
</>
)}
</div>
);
export default Section;

View File

@@ -0,0 +1,42 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import React from "react";
import { Flex } from "@chakra-ui/react";
export function HSeparator(props) {
const { variant, children, ...rest } = props;
return (
<Flex
h="1px"
w="100%"
bg="linear-gradient(90deg, rgba(224, 225, 226, 0) 0%, #E0E1E2 49.52%, rgba(224, 225, 226, 0) 100%)"
{...rest}
></Flex>
);
}
export function VSeparator(props) {
const { variant, children, ...rest } = props;
return (
<Flex
w="1px"
bg="linear-gradient(0deg, rgba(224, 225, 226, 0) 0%, #E0E1E2 49.52%, rgba(224, 225, 226, 0.15625) 99.04%)"
{...rest}
></Flex>
);
}

View File

@@ -0,0 +1,195 @@
import Section from "@/components/Section";
import Generating from "@/components/Generating";
import Image from "@/components/Image";
import Heading from "@/components/Heading";
type ServicesProps = {
containerClassName?: string;
};
const Services = ({ containerClassName }: ServicesProps) => (
<Section>
<div className={`container ${containerClassName || ""}`}>
<Heading
title="Generative AI made for creators."
text="Brainwave unlocks the potential of AI-powered applications"
/>
<div className="relative">
<div className="relative z-1 flex items-center h-[38.75rem] mb-5 p-8 border border-n-1/10 rounded-3xl overflow-hidden lg:h-[38.75rem] lg:p-20 xl:h-[45.75rem]">
<div className="absolute top-0 left-0 w-full h-full pointer-events-none md:w-3/5 xl:w-auto">
<Image
className="w-full h-full object-cover md:object-right"
src="/images/services/service-1.png"
width={797}
height={733}
alt="Smartest AI"
/>
</div>
<div className="relative z-1 max-w-[17rem] ml-auto">
<h4 className="h4 mb-4">Smartest AI</h4>
<p className="bpdy-2 mb-[3.125rem] text-n-3">
Brainwave unlocks the potential of AI-powered
applications
</p>
<ul className="body-2">
{[
"Photo generating",
"Photo enhance",
"Seamless Integration",
].map((item, index) => (
<li
className="flex items-start py-4 border-t border-n-6"
key={index}
>
<Image
src="/images/check.svg"
width={24}
height={24}
alt="Check"
/>
<p className="ml-4">{item}</p>
</li>
))}
</ul>
</div>
<Generating className="absolute left-4 right-4 bottom-4 border border-n-1/10 lg:left-1/2 lg-right-auto lg:bottom-8 lg:-translate-x-1/2" />
</div>
<div className="relative z-1 grid gap-5 lg:grid-cols-2">
<div className="relative min-h-[38.75rem] border border-n-1/10 rounded-3xl overflow-hidden">
<div className="absolute inset-0">
<Image
className="w-full h-full object-cover"
src="/images/services/service-2.png"
width={630}
height={748}
alt="Smartest AI"
/>
</div>
<div className="absolute inset-0 flex flex-col justify-end p-8 bg-gradient-to-b from-n-8/0 to-n-8/90 lg:p-15">
<h4 className="h4 mb-4">Photo editing</h4>
<p className="body-2 text-n-3">
{`Automatically enhance your photos using our AI app's
photo editing feature. Try it now!`}
</p>
</div>
<div className="absolute top-8 right-8 max-w-[17.5rem] py-6 px-8 bg-black rounded-t-xl rounded-bl-xl font-code text-base lg:top-16 lg:right-[8.75rem] lg:max-w-[17.5rem]">
Hey Brainwave, enhance this photo
<svg
className="absolute left-full bottom-0"
xmlns="http://www.w3.org/2000/svg"
width="26"
height="37"
>
<path d="M21.843 37.001c3.564 0 5.348-4.309 2.829-6.828L3.515 9.015A12 12 0 0 1 0 .53v36.471h21.843z" />
</svg>
</div>
</div>
<div className="p-4 bg-n-7 rounded-3xl overflow-hidden lg:min-h-[45.75rem]">
<div className="py-12 px-4 xl:px-8">
<h4 className="h4 mb-4">Video generation</h4>
<p className="body-2 mb-[2.25rem] text-n-3">
The worlds most powerful AI photo and video art
generation engine.What will you create?
</p>
<ul className="flex items-center justify-between">
{[
"/images/icons/recording-03.svg",
"/images/icons/recording-01.svg",
"/images/icons/disc-02.svg",
"/images/icons/chrome-cast.svg",
"/images/icons/sliders-04.svg",
].map((item, index) => (
<li
className={`flex items-center justify-center ${
index === 2
? "w-[3rem] h-[3rem] p-0.25 bg-conic-gradient rounded-2xl md:w-[4.5rem] md:h-[4.5rem]"
: "flex w-10 h-10 bg-n-6 rounded-2xl md:w-15 md:h-15"
}`}
key={index}
>
<div
className={
index === 2
? "flex items-center justify-center w-full h-full bg-n-7 rounded-[0.9375rem]"
: ""
}
>
<Image
src={item}
width={24}
height={24}
alt={item}
/>
</div>
</li>
))}
</ul>
</div>
<div className="relative h-[20.5rem] bg-n-8 rounded-xl overflow-hidden md:h-[25rem]">
<Image
className="w-full h-full object-cover"
src="/images/services/service-3.png"
width={517}
height={400}
alt="Smartest AI"
/>
<div className="absolute top-8 left-[3.125rem] w-full max-w-[14rem] pt-2.5 pr-2.5 pb-7 pl-5 bg-n-6 rounded-t-xl rounded-br-xl font-code text-base md:max-w-[17.5rem]">
Video generated!
<div className="absolute left-5 -bottom-[1.125rem] flex items-center justify-center w-[2.25rem] h-[2.25rem] bg-color-1 rounded-[0.75rem]">
<Image
src="/images/brainwave-symbol-white.svg"
width={26}
height={26}
alt="Brainwave"
/>
</div>
<div className="tagline absolute right-2.5 bottom-1 text-[0.625rem] text-n-3 uppercase">
just now
</div>
<svg
className="absolute right-full bottom-0 -scale-x-100"
xmlns="http://www.w3.org/2000/svg"
width="26"
height="37"
>
<path
className="fill-n-6"
d="M21.843 37.001c3.564 0 5.348-4.309 2.829-6.828L3.515 9.015A12 12 0 0 1 0 .53v36.471h21.843z"
/>
</svg>
</div>
<div className="absolute left-0 bottom-0 w-full flex items-center p-6">
<svg
className="mr-3"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="none"
>
<path
d="M8.006 2.802l.036.024 10.549 7.032.805.567c.227.183.494.437.648.808a2 2 0 0 1 0 1.532c-.154.371-.421.625-.648.808-.217.175-.5.364-.805.567L8.006 21.198l-.993.627c-.285.154-.676.331-1.132.303a2 2 0 0 1-1.476-.79c-.276-.365-.346-.788-.375-1.111S4 19.502 4 19.054V4.99v-.043l.029-1.174c.03-.323.1-.746.375-1.11a2 2 0 0 1 1.476-.79c.456-.027.847.149 1.132.304s.62.378.993.627z"
fill="#fff"
/>
</svg>
<div className="flex-1 bg-[#D9D9D9]">
<div className="w-1/2 h-0.5 bg-color-1"></div>
</div>
</div>
</div>
</div>
</div>
<div className="absolute top-0 -left-[10rem] w-[56.625rem] h-[56.625rem] opacity-50 mix-blend-color-dodge pointer-events-none">
<Image
className="absolute top-1/2 left-1/2 w-[79.5625rem] max-w-[79.5625rem] h-[88.5625rem] -translate-x-1/2 -translate-y-1/2"
src="/images/gradient.png"
width={1417}
height={1417}
alt="Gradient"
/>
</div>
</div>
</div>
</Section>
);
export default Services;

View File

@@ -0,0 +1,719 @@
/* eslint-disable */
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import { HamburgerIcon } from '@chakra-ui/icons';
// chakra imports
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Box,
Drawer,
DrawerBody,
DrawerCloseButton,
DrawerContent,
DrawerOverlay,
Flex,
HStack,
Icon,
List,
ListItem,
Stack,
Text,
useColorModeValue,
useDisclosure
} from '@chakra-ui/react';
import IconBox from 'components/Icons/IconBox';
import {
renderThumbDark,
renderThumbLight,
renderTrack,
renderTrackRTL,
renderView,
renderViewRTL
} from 'components/Scrollbar/Scrollbar';
import { HSeparator } from 'components/Separator/Separator';
import { SidebarContext } from 'contexts/SidebarContext';
import React from 'react';
import { Scrollbars } from 'react-custom-scrollbars-2';
import { FaCircle } from 'react-icons/fa';
import { NavLink, useLocation } from 'react-router-dom';
import SidebarDocs from './SidebarDocs';
// FUNCTIONS
function Sidebar(props) {
// to check for active links and opened collapses
let location = useLocation();
const { routes, landing } = props;
// this is for the rest of the collapses
const { sidebarWidth, setSidebarWidth, toggleSidebar } = React.useContext(SidebarContext);
let variantChange = '0.2s linear';
// verifies if routeName is the one active (in browser input)
const activeRoute = (routeName) => {
return location.pathname.includes(routeName);
};
// this function creates the links and collapses that appear in the sidebar (left menu)
const createLinks = (routes) => {
// Chakra Color Mode
let activeBg = 'blue.500';
let inactiveBg = useColorModeValue('transparent', 'navy.700');
let activeColor = useColorModeValue('gray.700', 'white');
let inactiveColor = useColorModeValue('gray.400', 'gray.400');
let sidebarActiveShadow = '0px 7px 11px rgba(0, 0, 0, 0.04)';
let activeAccordionBg = useColorModeValue('white', 'navy.700');
let activeColorIcon = 'white';
let inactiveColorIcon = 'blue.500';
if (landing) {
activeBg = 'white';
inactiveBg = 'transparent';
activeColor = 'white';
inactiveColor = 'white';
sidebarActiveShadow = '0px 7px 11px rgba(0, 0, 0, 0.04)';
activeAccordionBg = 'rgba(255, 255, 255, 0.11)';
activeColorIcon = 'blue.500';
inactiveColorIcon = 'white';
}
return routes.map((prop, key) => {
if (prop.category) {
return (
<Box key={key}>
<Text
fontSize={sidebarWidth === 275 ? 'md' : 'xs'}
color={activeColor}
fontWeight='bold'
mx='auto'
ps={{
sm: '10px',
xl: '16px'
}}
pt='18px'
pb='12px'
key={key}>
{prop.name}
</Text>
{createLinks(prop.items)}
</Box>
);
}
if (prop.collapse) {
return (
<Accordion key={key} allowToggle>
<AccordionItem border='none'>
<AccordionButton
display='flex'
align='center'
justify='center'
boxShadow={activeRoute(prop.path) && prop.icon ? sidebarActiveShadow : null}
_hover={{
boxShadow: activeRoute(prop.path) && prop.icon ? sidebarActiveShadow : null
}}
_focus={{
boxShadow: 'none'
}}
borderRadius='8px'
w={{
sm: sidebarWidth === 275 ? '100%' : '77%',
xl: sidebarWidth === 275 ? '90%' : '70%',
'2xl': sidebarWidth === 275 ? '95%' : '77%'
}}
px={prop.icon ? null : '0px'}
py={prop.icon ? '12px' : null}
bg={activeRoute(prop.path) && prop.icon ? activeAccordionBg : 'transparent'}
ms={sidebarWidth !== 275 ? !prop.icon ? '12px' : '8px' : null}>
{activeRoute(prop.path) ? (
<Flex
fontWeight='bold'
boxSize='initial'
justifyContent='flex-start'
alignItems='center'
bg='transparent'
transition={variantChange}
mx={{
xl: 'auto'
}}
px='0px'
borderRadius='8px'
w='100%'
_hover={{}}
_active={{
bg: 'inherit',
transform: 'none',
borderColor: 'transparent',
border: 'none'
}}
_focus={{
transform: 'none',
borderColor: 'transparent',
border: 'none'
}}>
{prop.icon ? (
<Flex justify={sidebarWidth === 275 ? 'flex-start' : 'center'}>
<IconBox
bg={activeBg}
color={activeColorIcon}
h='30px'
w='30px'
me={sidebarWidth === 275 ? '12px' : '0px'}
transition={variantChange}>
{prop.icon}
</IconBox>
<Text
color={activeColor}
my='auto'
fontSize='sm'
display={sidebarWidth === 275 ? 'block' : 'none'}>
{prop.name}
</Text>
</Flex>
) : (
<HStack
spacing={sidebarWidth === 275 ? '22px' : '0px'}
ps={sidebarWidth === 275 ? '10px' : '0px'}
ms={sidebarWidth === 275 ? '0px' : '8px'}>
<Icon
as={FaCircle}
w='10px'
color='blue.500'
display={sidebarWidth === 275 ? 'block' : 'none'}
/>
<Text color={activeColor} my='auto' fontSize='sm'>
{sidebarWidth === 275 ? prop.name : prop.name[0]}
</Text>
</HStack>
)}
</Flex>
) : (
<Flex
fontWeight='bold'
boxSize='initial'
justifyContent='flex-start'
alignItems='center'
bg='transparent'
mx={{
xl: 'auto'
}}
px='0px'
borderRadius='8px'
w='100%'
_hover={{}}
_active={{
bg: 'inherit',
transform: 'none',
borderColor: 'transparent'
}}
_focus={{
borderColor: 'transparent',
boxShadow: 'none'
}}>
{prop.icon ? (
<Flex justify={sidebarWidth === 275 ? 'flex-start' : 'center'}>
<IconBox
bg={inactiveBg}
color={inactiveColorIcon}
h='30px'
w='30px'
me={sidebarWidth === 275 ? '12px' : '0px'}
transition={variantChange}>
{prop.icon}
</IconBox>
<Text
color={inactiveColor}
my='auto'
fontSize='sm'
display={sidebarWidth === 275 ? 'block' : 'none'}>
{prop.name}
</Text>
</Flex>
) : (
<HStack
spacing={sidebarWidth === 275 ? '26px' : '0px'}
ps={sidebarWidth === 275 ? '10px' : '0px'}
ms={sidebarWidth === 275 ? '0px' : '8px'}>
<Icon
as={FaCircle}
w='6px'
color={landing ? 'white' : 'blue.500'}
display={sidebarWidth === 275 ? 'block' : 'none'}
/>
<Text color={inactiveColor} my='auto' fontSize='md' fontWeight='normal'>
{sidebarWidth === 275 ? prop.name : prop.name[0]}
</Text>
</HStack>
)}
</Flex>
)}
<AccordionIcon
color={landing ? 'white' : 'gray.400'}
display={
prop.icon ? sidebarWidth === 275 ? (
'block'
) : (
'none'
) : sidebarWidth === 275 ? (
'block'
) : (
'none'
)
}
transform={prop.icon ? null : sidebarWidth === 275 ? null : 'translateX(-70%)'}
/>
</AccordionButton>
<AccordionPanel
pe={prop.icon ? null : '0px'}
pb='8px'
ps={prop.icon ? null : sidebarWidth === 275 ? null : '8px'}>
<List>
{prop.icon ? (
createLinks(prop.items) // for bullet accordion links
) : (
createAccordionLinks(prop.items)
) // for non-bullet accordion links
}
</List>
</AccordionPanel>
</AccordionItem>
</Accordion>
);
} else {
return (
<NavLink key={key} to={prop.layout + prop.path}>
{prop.icon ? (
<Box>
<HStack spacing='14px' py='15px' px='15px'>
<IconBox bg='blue.500' color='white' h='30px' w='30px' transition={variantChange}>
{prop.icon}
</IconBox>
<Text
color={activeRoute(prop.path.toLowerCase()) ? activeColor : inactiveColor}
fontWeight={activeRoute(prop.name) ? 'bold' : 'normal'}
fontSize='sm'>
{prop.name}
</Text>
</HStack>
</Box>
) : (
<ListItem key={key} ms={sidebarWidth === 275 ? null : '10px'}>
<HStack
spacing={
sidebarWidth === 275 ? activeRoute(prop.path.toLowerCase()) ? (
'22px'
) : (
'26px'
) : (
'8px'
)
}
py='5px'
px={sidebarWidth === 275 ? '10px' : '0px'}>
<Icon
as={FaCircle}
w={activeRoute(prop.path.toLowerCase()) ? '10px' : '6px'}
color={landing ? 'white' : 'blue.500'}
display={sidebarWidth === 275 ? 'block' : 'none'}
/>
<Text
color={activeRoute(prop.path.toLowerCase()) ? activeColor : inactiveColor}
fontWeight={activeRoute(prop.path.toLowerCase()) ? 'bold' : 'normal'}>
{sidebarWidth === 275 ? prop.name : prop.name[0]}
</Text>
</HStack>
</ListItem>
)}
</NavLink>
);
}
});
};
const createAccordionLinks = (routes) => {
let inactiveColor = useColorModeValue('gray.400', 'gray.400');
let activeColor = useColorModeValue('gray.700', 'white');
if (landing) {
inactiveColor = 'white';
activeColor = 'white';
}
return routes.map((prop, key) => {
return (
<NavLink key={key} to={prop.layout + prop.path}>
<ListItem key={key} pt='5px' ms={sidebarWidth === 275 ? '26px' : '12px'}>
<Text
mb='4px'
color={activeRoute(prop.path.toLowerCase()) ? activeColor : inactiveColor}
fontWeight={activeRoute(prop.path.toLowerCase()) ? 'bold' : 'normal'}
fontSize='sm'>
{sidebarWidth === 275 ? prop.name : prop.name[0]}
</Text>
</ListItem>
</NavLink>
);
});
};
let isWindows = navigator.platform.startsWith('Win');
let links = <Box>{createLinks(routes)}</Box>;
// BRAND
// Chakra Color Mode
let sidebarBg = useColorModeValue('white', 'navy.800');
let sidebarRadius = '20px';
let sidebarMargins = '0px';
var brand = (
<Flex align='center' direction='column' pt={'25px'}>
{props.logo}
<HSeparator my='20px' />
</Flex>
);
let sidebarContent = (
<Box>
<Box>{brand}</Box>
<Stack direction='column' mb='40px'>
<Box>{links}</Box>
</Stack>
<SidebarDocs landing={landing} />
</Box>
);
// SIDEBAR
return (
<Box
onMouseEnter={toggleSidebar ? () => setSidebarWidth(sidebarWidth === 120 ? 275 : 120) : null}
onMouseLeave={toggleSidebar ? () => setSidebarWidth(sidebarWidth === 275 ? 120 : 275) : null}>
<Box display={{ sm: 'none', xl: 'block' }} position='fixed'>
<Box
bg={landing ? 'transparent' : sidebarBg}
transition={variantChange}
w={`${sidebarWidth}px`}
ms={{
sm: '16px'
}}
my={{
sm: '16px'
}}
h='calc(100vh - 32px)'
ps='20px'
pe='20px'
m={sidebarMargins}
borderRadius={sidebarRadius}>
<Scrollbars
autoHide
renderTrackVertical={document.documentElement.dir === 'rtl' ? renderTrackRTL : renderTrack}
renderThumbVertical={useColorModeValue(renderThumbLight, renderThumbDark)}
renderView={document.documentElement.dir === 'rtl' ? renderViewRTL : renderView}>
{sidebarContent}
</Scrollbars>
</Box>
</Box>
</Box>
);
}
// FUNCTIONS
export function SidebarResponsive(props) {
// to check for active links and opened collapses
let location = useLocation();
let variantChange = '0.2s linear';
// verifies if routeName is the one active (in browser input)
const activeRoute = (routeName) => {
return location.pathname.includes(routeName);
};
// Chakra Color Mode
let activeBg = 'blue.500';
let inactiveBg = useColorModeValue('transparent', 'navy.700');
let activeColor = useColorModeValue('gray.700', 'white');
let inactiveColor = useColorModeValue('gray.400', 'gray.400');
let activeAccordionBg = useColorModeValue('white', 'navy.700');
let sidebarActiveShadow = useColorModeValue('0px 7px 11px rgba(0, 0, 0, 0.04)', 'none');
let activeColorIcon = 'white';
let inactiveColorIcon = 'blue.500';
let sidebarBackgroundColor = useColorModeValue('white', 'navy.900');
// this function creates the links and collapses that appear in the sidebar (left menu)
const createLinks = (routes) => {
return routes.map((prop, key) => {
if (prop.category) {
return (
<Box key={key}>
<Text
fontSize={'md'}
color={activeColor}
fontWeight='bold'
mx='auto'
ps={{
sm: '10px',
xl: '16px'
}}
py='12px'
key={key}>
{prop.name}
</Text>
{createLinks(prop.items)}
</Box>
);
}
if (prop.collapse) {
return (
<Accordion key={key} allowToggle>
<AccordionItem border='none'>
<AccordionButton
as='div'
display='flex'
align='center'
justify='center'
key={key}
borderRadius='8px'
px={prop.icon ? null : '0px'}
py={prop.icon ? '12px' : null}
boxShadow={activeRoute(prop.path) && prop.icon ? sidebarActiveShadow : 'none'}
bg={activeRoute(prop.path) && prop.icon ? activeAccordionBg : 'transparent'}>
{activeRoute(prop.path) ? (
<Flex
fontWeight='bold'
boxSize='initial'
justifyContent='flex-start'
alignItems='center'
bg='transparent'
transition={variantChange}
mx={{
xl: 'auto'
}}
px='0px'
borderRadius='8px'
_hover={{}}
w='100%'
_active={{
bg: 'inherit',
transform: 'none',
borderColor: 'transparent'
}}>
{prop.icon ? (
<Flex>
<IconBox
bg={activeBg}
color={activeColorIcon}
h='30px'
w='30px'
me='12px'
transition={variantChange}>
{prop.icon}
</IconBox>
<Text color={activeColor} my='auto' fontSize='sm' display={'block'}>
{prop.name}
</Text>
</Flex>
) : (
<HStack spacing={'22px'} ps='10px' ms='0px'>
<Icon as={FaCircle} w='10px' color='blue.500' />
<Text as='span' color={activeColor} my='auto' fontSize='sm'>
{prop.name}
</Text>
</HStack>
)}
</Flex>
) : (
<Text
as='span'
fontWeight='bold'
boxSize='initial'
justifyContent='flex-start'
alignItems='center'
bg='transparent'
mx={{
xl: 'auto'
}}
px='0px'
borderRadius='8px'
_hover={{}}
w='100%'
_active={{
bg: 'inherit',
transform: 'none',
borderColor: 'transparent'
}}
_focus={{
boxShadow: 'none'
}}>
{prop.icon ? (
<Flex>
<IconBox
bg={inactiveBg}
color={inactiveColorIcon}
h='30px'
w='30px'
me='12px'
transition={variantChange}>
{prop.icon}
</IconBox>
<Text color={inactiveColor} my='auto' fontSize='sm'>
{prop.name}
</Text>
</Flex>
) : (
<HStack spacing={'26px'} ps={'10px'} ms={'0px'}>
<Icon as={FaCircle} w='6px' color='blue.500' />
<Text color={inactiveColor} my='auto' fontSize='sm' fontWeight='normal'>
{prop.name}
</Text>
</HStack>
)}
</Text>
)}
<AccordionIcon color='gray.400' />
</AccordionButton>
<AccordionPanel pe={prop.icon ? null : '0px'} pb='8px'>
<List>
{prop.icon ? (
createLinks(prop.items) // for bullet accordion links
) : (
createAccordionLinks(prop.items)
) // for non-bullet accordion links
}
</List>
</AccordionPanel>
</AccordionItem>
</Accordion>
);
} else {
return (
<NavLink key={key} to={prop.layout + prop.path}>
{prop.icon ? (
<Box>
<HStack spacing='14px' py='15px' px='15px'>
<IconBox bg='blue.500' color='white' h='30px' w='30px' transition={variantChange}>
{prop.icon}
</IconBox>
<Text
color={activeRoute(prop.path.toLowerCase()) ? activeColor : inactiveColor}
fontWeight={activeRoute(prop.name) ? 'bold' : 'normal'}
fontSize='sm'>
{prop.name}
</Text>
</HStack>
</Box>
) : (
<ListItem>
<HStack spacing='22px' py='5px' px='10px'>
<Icon
as={FaCircle}
w={activeRoute(prop.path.toLowerCase()) ? '10px' : '6px'}
color='blue.500'
/>
<Text
color={activeRoute(prop.path.toLowerCase()) ? activeColor : inactiveColor}
fontSize='sm'
fontWeight={activeRoute(prop.path.toLowerCase()) ? 'bold' : 'normal'}>
{prop.name}
</Text>
</HStack>
</ListItem>
)}
</NavLink>
);
}
});
};
const createAccordionLinks = (routes) => {
return routes.map((prop, key) => {
return (
<NavLink key={key} to={prop.layout + prop.path}>
<ListItem pt='5px' ms='26px' key={key}>
<Text
color={activeRoute(prop.path.toLowerCase()) ? activeColor : inactiveColor}
fontWeight={activeRoute(prop.path.toLowerCase()) ? 'bold' : 'normal'}
fontSize='sm'>
{prop.name}
</Text>
</ListItem>
</NavLink>
);
});
};
const { logo, display, routes } = props;
let links = <Box>{createLinks(routes)}</Box>;
// BRAND
// Chakra Color Mode
let hamburgerColor = 'white';
var brand = (
<Box pt={'25px'} mb='12px'>
{logo}
<HSeparator my='26px' />
</Box>
);
// SIDEBAR
const { isOpen, onOpen, onClose } = useDisclosure();
const btnRef = React.useRef();
// Color variables
return (
<Box display={display}>
<Box display={{ sm: 'flex', xl: 'none' }} ms='8px'>
<HamburgerIcon
color={hamburgerColor}
w='18px'
h='18px'
me='16px'
ref={btnRef}
cursor='pointer'
onClick={onOpen}
/>
<Drawer
placement={document.documentElement.dir === 'rtl' ? 'right' : 'left'}
isOpen={isOpen}
onClose={onClose}
finalFocusRef={btnRef}>
<DrawerOverlay />
<DrawerContent
w='250px'
bg={sidebarBackgroundColor}
maxW='250px'
ms={{
sm: '16px'
}}
my={{
sm: '16px'
}}
borderRadius='16px'>
<DrawerCloseButton _focus={{ boxShadow: 'none' }} _hover={{ boxShadow: 'none' }} />
<DrawerBody maxW='250px' px='1rem'>
<Box maxW='100%' h='100vh'>
<Box mb='20px'>{brand}</Box>
<Stack direction='column' mb='40px'>
<Box>{links}</Box>
</Stack>
<SidebarDocs />
</Box>
</DrawerBody>
</DrawerContent>
</Drawer>
</Box>
</Box>
);
}
// PROPS
export default Sidebar;

View File

@@ -0,0 +1,45 @@
import {
Button,
Flex,
Image,
Link,
Stack,
Text,
useColorModeValue,
} from "@chakra-ui/react";
import SidebarHelpImage from "assets/img/SidebarHelpImage.png";
import { SidebarContext } from "contexts/SidebarContext";
import React, { useContext } from "react";
export default function SidebarDocs({ landing }) {
const textColor = useColorModeValue("gray.700", "white");
const { sidebarWidth } = useContext(SidebarContext);
return (
<Flex
justify='center'
direction='column'
align='center'
display={sidebarWidth !== 275 && "none"}
>
<Image src={SidebarHelpImage} w='165px' ms="24px" />
<Flex direction='column' align="center" textAlign='center' mb="12px" me="24px">
<Text fontSize='14px' color={landing ? "white" : textColor} fontWeight='bold'>
Need help?
</Text>
<Text fontSize='12px' color={landing ? "white" : 'gray.500'}>
Please check our docs.
</Text>
</Flex>
<Link href='#' >
<Button variant={landing ? "light" : 'primary'} mb={{ sm: "12px", xl: "16px" }} color={landing && "blue.500"} fontWeight="bold" minW="185px" ms="24px">
DOCUMENTATION
</Button>
</Link>
</Flex>
);
}

View File

@@ -0,0 +1,552 @@
// src/components/StockChart/StockChartAntdModal.js - Antd版本的股票图表组件
import React, { useState, useEffect, useRef } from 'react';
import { Modal, Button, Spin, Typography } from 'antd';
import ReactECharts from 'echarts-for-react';
import * as echarts from 'echarts';
import moment from 'moment';
import { stockService } from '../../services/eventService';
const { Text } = Typography;
const StockChartAntdModal = ({
open = false,
onCancel,
stock,
eventTime,
fixed = false,
width = 800
}) => {
const chartRef = useRef(null);
const chartInstanceRef = useRef(null);
const [activeChartType, setActiveChartType] = useState('timeline');
const [loading, setLoading] = useState(false);
const [chartData, setChartData] = useState(null);
const [preloadedData, setPreloadedData] = useState({});
// 预加载数据
const preloadData = async (type) => {
if (!stock?.stock_code || preloadedData[type]) return;
try {
// 统一的事件时间处理逻辑:盘后事件推到次日开盘
let adjustedEventTime = eventTime;
if (eventTime) {
try {
const eventMoment = moment(eventTime);
if (eventMoment.isValid()) {
// 如果是15:00之后的事件推到下一个交易日的9:30
if (eventMoment.hour() >= 15) {
const nextDay = eventMoment.clone().add(1, 'day');
nextDay.hour(9).minute(30).second(0).millisecond(0);
adjustedEventTime = nextDay.format('YYYY-MM-DD HH:mm');
}
}
} catch (e) {
console.warn('事件时间解析失败:', e);
}
}
const response = await stockService.getKlineData(stock.stock_code, type, adjustedEventTime);
setPreloadedData(prev => ({...prev, [type]: response}));
} catch (err) {
console.error(`预加载${type}数据失败:`, err);
}
};
// 预加载数据的effect
useEffect(() => {
if (open && stock?.stock_code) {
// 预加载两种图表类型的数据
preloadData('timeline');
preloadData('daily');
}
}, [open, stock?.stock_code, eventTime]);
// 加载图表数据
useEffect(() => {
const loadChartData = async () => {
if (!stock?.stock_code) return;
try {
setLoading(true);
// 先尝试使用预加载的数据
let data = preloadedData[activeChartType];
if (!data) {
// 如果预加载数据不存在,则立即请求
let adjustedEventTime = eventTime;
if (eventTime) {
try {
const eventMoment = moment(eventTime);
if (eventMoment.isValid()) {
// 如果是15:00之后的事件推到下一个交易日的9:30
if (eventMoment.hour() >= 15) {
const nextDay = eventMoment.clone().add(1, 'day');
nextDay.hour(9).minute(30).second(0).millisecond(0);
adjustedEventTime = nextDay.format('YYYY-MM-DD HH:mm');
}
}
} catch (e) {
console.warn('事件时间解析失败:', e);
}
}
data = await stockService.getKlineData(stock.stock_code, activeChartType, adjustedEventTime);
}
setChartData(data);
} catch (error) {
console.error('加载图表数据失败:', error);
} finally {
setLoading(false);
}
};
if (stock && stock.stock_code) {
loadChartData();
}
}, [stock?.stock_code, activeChartType, eventTime]);
// 生成图表配置
const getChartOption = () => {
if (!chartData || !chartData.data) {
return {
title: { text: '暂无数据', left: 'center' },
xAxis: { type: 'category', data: [] },
yAxis: { type: 'value' },
series: [{ data: [], type: 'line' }]
};
}
const data = chartData.data;
const tradeDate = chartData.trade_date;
// 处理数据格式
let times = [];
let prices = [];
let opens = [];
let highs = [];
let lows = [];
let closes = [];
let volumes = [];
if (Array.isArray(data)) {
times = data.map(item => item.time || item.date || item.timestamp);
prices = data.map(item => item.close || item.price || item.value);
opens = data.map(item => item.open);
highs = data.map(item => item.high);
lows = data.map(item => item.low);
closes = data.map(item => item.close);
volumes = data.map(item => item.volume);
} else if (data.times && data.prices) {
times = data.times;
prices = data.prices;
opens = data.opens || [];
highs = data.highs || [];
lows = data.lows || [];
closes = data.closes || [];
volumes = data.volumes || [];
}
// 生成K线数据结构
const klineData = times.map((t, i) => [opens[i], closes[i], lows[i], highs[i]]);
// 计算事件标记线位置
let markLineData = [];
if (eventTime && times.length > 0) {
const eventMoment = moment(eventTime);
const eventDate = eventMoment.format('YYYY-MM-DD');
if (activeChartType === 'timeline') {
// 分时图:在相同交易日内定位具体时间
if (eventDate === tradeDate) {
const eventTime = eventMoment.format('HH:mm');
let nearestIdx = 0;
const eventMinutes = eventMoment.hour() * 60 + eventMoment.minute();
for (let i = 0; i < times.length; i++) {
const [h, m] = times[i].split(':').map(Number);
const timeMinutes = h * 60 + m;
const currentDiff = Math.abs(timeMinutes - eventMinutes);
const nearestDiff = Math.abs(
(times[nearestIdx].split(':').map(Number)[0] * 60 + times[nearestIdx].split(':').map(Number)[1]) - eventMinutes
);
if (currentDiff < nearestDiff) {
nearestIdx = i;
}
}
markLineData = [{
name: '事件发生',
xAxis: nearestIdx,
label: {
formatter: '事件发生',
position: 'middle',
color: '#FFD700',
fontSize: 12
},
lineStyle: {
color: '#FFD700',
type: 'solid',
width: 2
}
}];
}
} else if (activeChartType === 'daily') {
// 日K线定位到交易日
let targetIndex = -1;
// 1. 先尝试找到完全匹配的日期
targetIndex = times.findIndex(time => time === eventDate);
// 2. 如果没有完全匹配,找到第一个大于等于事件日期的交易日
if (targetIndex === -1) {
for (let i = 0; i < times.length; i++) {
if (times[i] >= eventDate) {
targetIndex = i;
break;
}
}
}
// 3. 如果事件日期晚于所有交易日,则标记在最后一个交易日
if (targetIndex === -1 && eventDate > times[times.length - 1]) {
targetIndex = times.length - 1;
}
// 4. 如果事件日期早于所有交易日,则标记在第一个交易日
if (targetIndex === -1 && eventDate < times[0]) {
targetIndex = 0;
}
if (targetIndex >= 0) {
let labelText = '事件发生';
let labelPosition = 'middle';
// 根据事件时间和交易日的关系调整标签
if (eventDate === times[targetIndex]) {
if (eventMoment.hour() >= 15) {
labelText = '事件发生\n(盘后)';
} else if (eventMoment.hour() < 9 || (eventMoment.hour() === 9 && eventMoment.minute() < 30)) {
labelText = '事件发生\n(盘前)';
}
} else if (eventDate < times[targetIndex]) {
labelText = '事件发生\n(前一日)';
labelPosition = 'start';
} else {
labelText = '事件发生\n(影响日)';
labelPosition = 'end';
}
markLineData = [{
name: '事件发生',
xAxis: targetIndex,
label: {
formatter: labelText,
position: labelPosition,
color: '#FFD700',
fontSize: 12,
backgroundColor: 'rgba(0,0,0,0.5)',
padding: [4, 8],
borderRadius: 4
},
lineStyle: {
color: '#FFD700',
type: 'solid',
width: 2
}
}];
}
}
}
// 分时图
if (activeChartType === 'timeline') {
const avgPrices = data.map(item => item.avg_price);
// 获取昨收盘价作为基准
const prevClose = chartData.prev_close || (prices.length > 0 ? prices[0] : 0);
// 计算涨跌幅数据
const changePercentData = prices.map(price => ((price - prevClose) / prevClose * 100));
const avgChangePercentData = avgPrices.map(avgPrice => ((avgPrice - prevClose) / prevClose * 100));
const currentPrice = prices[prices.length - 1];
const currentChange = ((currentPrice - prevClose) / prevClose * 100);
const isUp = currentChange >= 0;
const lineColor = isUp ? '#ef5350' : '#26a69a';
return {
title: {
text: `${stock.stock_name || stock.stock_code} - 分时图`,
left: 'center',
textStyle: { fontSize: 16, fontWeight: 'bold' }
},
tooltip: {
trigger: 'axis',
axisPointer: { type: 'cross' },
formatter: function(params) {
const d = params[0]?.dataIndex ?? 0;
const priceChangePercent = ((prices[d] - prevClose) / prevClose * 100);
const avgChangePercent = ((avgPrices[d] - prevClose) / prevClose * 100);
const priceColor = priceChangePercent >= 0 ? '#ef5350' : '#26a69a';
const avgColor = avgChangePercent >= 0 ? '#ef5350' : '#26a69a';
return `时间:${times[d]}<br/>现价:<span style="color: ${priceColor}">¥${prices[d]?.toFixed(2)} (${priceChangePercent >= 0 ? '+' : ''}${priceChangePercent.toFixed(2)}%)</span><br/>均价:<span style="color: ${avgColor}">¥${avgPrices[d]?.toFixed(2)} (${avgChangePercent >= 0 ? '+' : ''}${avgChangePercent.toFixed(2)}%)</span><br/>昨收:¥${prevClose?.toFixed(2)}<br/>成交量:${Math.round(volumes[d]/100)}`;
}
},
grid: [
{ left: '10%', right: '10%', height: '50%', top: '15%' },
{ left: '10%', right: '10%', top: '70%', height: '20%' }
],
xAxis: [
{ type: 'category', data: times, gridIndex: 0, boundaryGap: false },
{ type: 'category', data: times, gridIndex: 1, axisLabel: { show: false } }
],
yAxis: [
{
type: 'value',
gridIndex: 0,
scale: false,
position: 'left',
axisLabel: {
formatter: function(value) {
return (value >= 0 ? '+' : '') + value.toFixed(2) + '%';
}
},
splitLine: {
show: true,
lineStyle: {
color: '#f0f0f0'
}
}
},
{
type: 'value',
gridIndex: 0,
scale: false,
position: 'right',
axisLabel: {
formatter: function(value) {
return (value >= 0 ? '+' : '') + value.toFixed(2) + '%';
}
}
},
{ type: 'value', gridIndex: 1, scale: true, axisLabel: { formatter: v => Math.round(v/100) + '手' } }
],
dataZoom: [
{ type: 'inside', xAxisIndex: [0, 1], start: 0, end: 100 },
{ show: true, xAxisIndex: [0, 1], type: 'slider', bottom: '0%' }
],
series: [
{
name: '分时价',
type: 'line',
xAxisIndex: 0,
yAxisIndex: 0,
data: changePercentData,
smooth: true,
showSymbol: false,
lineStyle: { color: lineColor, width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: isUp ? 'rgba(239, 83, 80, 0.3)' : 'rgba(38, 166, 154, 0.3)' },
{ offset: 1, color: isUp ? 'rgba(239, 83, 80, 0.05)' : 'rgba(38, 166, 154, 0.05)' }
])
},
markLine: {
symbol: 'none',
data: [
// 昨收盘价基准线 (0%)
{
yAxis: 0,
lineStyle: {
color: '#666',
type: 'dashed',
width: 1.5,
opacity: 0.8
},
label: {
show: true,
formatter: '昨收盘价',
position: 'insideEndTop',
color: '#666',
fontSize: 12
}
},
...markLineData
],
animation: false
}
},
{
name: '均价线',
type: 'line',
xAxisIndex: 0,
yAxisIndex: 1,
data: avgChangePercentData,
smooth: true,
showSymbol: false,
lineStyle: { color: '#FFA500', width: 1 }
},
{
name: '成交量',
type: 'bar',
xAxisIndex: 1,
yAxisIndex: 2,
data: volumes,
itemStyle: { color: '#b0c4de', opacity: 0.6 }
}
]
};
}
// 日K线图
if (activeChartType === 'daily') {
return {
title: {
text: `${stock.stock_name || stock.stock_code} - 日K线`,
left: 'center',
textStyle: { fontSize: 16, fontWeight: 'bold' }
},
tooltip: {
trigger: 'axis',
axisPointer: { type: 'cross' },
formatter: function(params) {
const kline = params[0];
const volume = params[1];
if (!kline || !kline.data) return '';
let tooltipHtml = `日期: ${times[kline.dataIndex]}<br/>开盘: ¥${kline.data[0]}<br/>收盘: ¥${kline.data[1]}<br/>最低: ¥${kline.data[2]}<br/>最高: ¥${kline.data[3]}`;
if (volume && volume.data) {
tooltipHtml += `<br/>成交量: ${Math.round(volume.data/100)}`;
}
return tooltipHtml;
}
},
grid: [
{ left: '10%', right: '10%', height: '60%' },
{ left: '10%', right: '10%', top: '75%', height: '20%' }
],
xAxis: [
{ type: 'category', data: times, scale: true, boundaryGap: true, gridIndex: 0 },
{ type: 'category', gridIndex: 1, data: times, axisLabel: { show: false } }
],
yAxis: [
{ scale: true, splitArea: { show: true }, gridIndex: 0 },
{ scale: true, gridIndex: 1, axisLabel: { formatter: (value) => Math.round(value/100) + '手' } }
],
dataZoom: [
{ type: 'inside', xAxisIndex: [0, 1], start: 70, end: 100 },
{ show: true, xAxisIndex: [0, 1], type: 'slider', bottom: '0%', start: 70, end: 100 }
],
series: [
{
name: 'K线',
type: 'candlestick',
yAxisIndex: 0,
data: klineData,
markLine: {
symbol: 'none',
data: markLineData,
animation: false
},
itemStyle: {
color: '#ef5350',
color0: '#26a69a',
borderColor: '#ef5350',
borderColor0: '#26a69a'
}
},
{
name: '成交量',
type: 'bar',
xAxisIndex: 1,
yAxisIndex: 1,
data: volumes.map((volume, index) => ({
value: volume,
itemStyle: {
color: closes[index] >= opens[index] ? '#ef5350' : '#26a69a'
}
}))
}
]
};
}
};
return (
<Modal
open={open}
title={`${stock?.stock_name || stock?.stock_code} (${stock?.stock_code}) - 股票详情`}
footer={null}
onCancel={onCancel}
width={width}
style={{ position: fixed ? 'fixed' : 'absolute', left: fixed ? 50 : 0, top: fixed ? 50 : 80, zIndex: 2000 }}
mask={false}
destroyOnClose={true}
bodyStyle={{ maxHeight: 'calc(90vh - 120px)', overflowY: 'auto', padding: '16px' }}
>
<div style={{ width: '100%' }}>
{/* 图表类型切换按钮 */}
<div style={{ marginBottom: 16, display: 'flex', gap: 8 }}>
<Button
type={activeChartType === 'timeline' ? 'primary' : 'default'}
onClick={() => setActiveChartType('timeline')}
>
分时图
</Button>
<Button
type={activeChartType === 'daily' ? 'primary' : 'default'}
onClick={() => setActiveChartType('daily')}
>
日K线
</Button>
</div>
{/* 图表容器 */}
<div style={{ height: '400px', width: '100%' }}>
{loading ? (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
<Spin size="large" />
</div>
) : (
<ReactECharts
option={getChartOption()}
style={{ height: '100%', width: '100%' }}
notMerge={true}
lazyUpdate={true}
onChartReady={(chart) => {
setTimeout(() => chart.resize(), 50);
}}
/>
)}
</div>
{/* 关联描述 */}
{stock?.relation_desc && (
<div style={{ marginTop: 16, padding: 16, backgroundColor: '#f5f5f5', borderRadius: 6 }}>
<Text strong style={{ display: 'block', marginBottom: 8 }}>关联描述:</Text>
<Text>{stock.relation_desc}AI合成</Text>
</div>
)}
{/* 调试信息 */}
{process.env.NODE_ENV === 'development' && chartData && (
<div style={{ marginTop: 16, padding: 12, backgroundColor: '#f0f0f0', borderRadius: 6, fontSize: '12px' }}>
<Text strong style={{ display: 'block', marginBottom: 4 }}>调试信息:</Text>
<Text>数据条数: {chartData.data ? chartData.data.length : 0}</Text>
<br />
<Text>交易日期: {chartData.trade_date}</Text>
<br />
<Text>图表类型: {activeChartType}</Text>
<br />
<Text>原始事件时间: {eventTime}</Text>
</div>
)}
</div>
</Modal>
);
};
export default StockChartAntdModal;

View File

@@ -0,0 +1,550 @@
// src/components/StockChart/StockChartModal.js - 统一的股票图表组件
import React, { useState, useEffect, useRef } from 'react';
import { Modal, ModalOverlay, ModalContent, ModalHeader, ModalCloseButton, ModalBody, Button, ButtonGroup, VStack, HStack, Text, Badge, Box, Flex, CircularProgress } from '@chakra-ui/react';
import ReactECharts from 'echarts-for-react';
import * as echarts from 'echarts';
import moment from 'moment';
import { stockService } from '../../services/eventService';
const StockChartModal = ({
isOpen,
onClose,
stock,
eventTime,
isChakraUI = true, // 是否使用Chakra UI默认true如果false则使用Antd
size = "6xl"
}) => {
const chartRef = useRef(null);
const chartInstanceRef = useRef(null);
const [chartType, setChartType] = useState('timeline');
const [loading, setLoading] = useState(false);
const [chartData, setChartData] = useState(null);
const [preloadedData, setPreloadedData] = useState({});
// 预加载数据
const preloadData = async (type) => {
if (!stock || preloadedData[type]) return;
try {
let adjustedEventTime = eventTime;
if (eventTime) {
try {
const eventMoment = moment(eventTime);
if (eventMoment.isValid() && eventMoment.hour() >= 15) {
const nextDay = eventMoment.clone().add(1, 'day');
nextDay.hour(9).minute(30).second(0).millisecond(0);
adjustedEventTime = nextDay.format('YYYY-MM-DD HH:mm');
}
} catch (e) {
console.warn('事件时间解析失败:', e);
}
}
const response = await stockService.getKlineData(stock.stock_code, type, adjustedEventTime);
setPreloadedData(prev => ({...prev, [type]: response}));
} catch (err) {
console.error(`预加载${type}数据失败:`, err);
}
};
useEffect(() => {
if (isOpen && stock) {
// 预加载两种图表类型的数据
preloadData('timeline');
preloadData('daily');
// 清理图表实例
return () => {
if (chartInstanceRef.current) {
window.removeEventListener('resize', chartInstanceRef.current.resizeHandler);
chartInstanceRef.current.dispose();
chartInstanceRef.current = null;
}
};
}
}, [isOpen, stock, eventTime]);
useEffect(() => {
if (isOpen && stock) {
loadChartData(chartType);
}
}, [chartType, isOpen, stock]);
const loadChartData = async (type) => {
if (!stock) return;
try {
setLoading(true);
// 先尝试使用预加载的数据
let response = preloadedData[type];
if (!response) {
// 如果预加载数据不存在,则立即请求
let adjustedEventTime = eventTime;
if (eventTime) {
try {
const eventMoment = moment(eventTime);
if (eventMoment.isValid() && eventMoment.hour() >= 15) {
const nextDay = eventMoment.clone().add(1, 'day');
nextDay.hour(9).minute(30).second(0).millisecond(0);
adjustedEventTime = nextDay.format('YYYY-MM-DD HH:mm');
}
} catch (e) {
console.warn('事件时间解析失败:', e);
}
}
response = await stockService.getKlineData(stock.stock_code, type, adjustedEventTime);
}
setChartData(response);
// 初始化图表
if (chartRef.current && !chartInstanceRef.current) {
const chart = echarts.init(chartRef.current);
chart.resizeHandler = () => chart.resize();
window.addEventListener('resize', chart.resizeHandler);
chartInstanceRef.current = chart;
}
if (chartInstanceRef.current) {
const option = generateChartOption(response, type, eventTime);
chartInstanceRef.current.setOption(option, true);
}
} catch (err) {
console.error('加载图表数据失败:', err);
} finally {
setLoading(false);
}
};
const generateChartOption = (data, type, originalEventTime, adjustedEventTime) => {
if (!data || !data.data || data.data.length === 0) {
return { title: { text: '暂无数据', left: 'center', top: 'center', textStyle: { color: '#999', fontSize: 16 } } };
}
const stockData = data.data;
const tradeDate = data.trade_date;
// 分时图
if (type === 'timeline') {
const times = stockData.map(item => item.time);
const prices = stockData.map(item => item.close || item.price);
const avgPrices = stockData.map(item => item.avg_price);
const volumes = stockData.map(item => item.volume);
// 获取昨收盘价作为基准
const prevClose = data.prev_close || (prices.length > 0 ? prices[0] : 0);
// 计算涨跌幅数据
const changePercentData = prices.map(price => ((price - prevClose) / prevClose * 100));
const avgChangePercentData = avgPrices.map(avgPrice => ((avgPrice - prevClose) / prevClose * 100));
const currentPrice = prices[prices.length - 1];
const currentChange = ((currentPrice - prevClose) / prevClose * 100);
const isUp = currentChange >= 0;
const lineColor = isUp ? '#ef5350' : '#26a69a';
// 计算事件标记线位置
let eventMarkLineData = [];
if (originalEventTime && times.length > 0) {
const eventMoment = moment(originalEventTime);
const eventDate = eventMoment.format('YYYY-MM-DD');
const eventTime = eventMoment.format('HH:mm');
if (eventDate === tradeDate) {
// 找到最接近的时间点
let nearestIdx = 0;
const eventMinutes = eventMoment.hour() * 60 + eventMoment.minute();
for (let i = 0; i < times.length; i++) {
const [h, m] = times[i].split(':').map(Number);
const timeMinutes = h * 60 + m;
const currentDiff = Math.abs(timeMinutes - eventMinutes);
const nearestDiff = Math.abs(
(times[nearestIdx].split(':').map(Number)[0] * 60 + times[nearestIdx].split(':').map(Number)[1]) - eventMinutes
);
if (currentDiff < nearestDiff) {
nearestIdx = i;
}
}
eventMarkLineData = [{
name: '事件发生',
xAxis: nearestIdx,
label: {
formatter: '事件发生',
position: 'middle',
color: '#FFD700',
fontSize: 12
},
lineStyle: {
color: '#FFD700',
type: 'solid',
width: 2
}
}];
}
}
return {
title: {
text: `${stock.stock_name || stock.stock_code} - 分时图`,
left: 'center',
textStyle: { fontSize: 16, fontWeight: 'bold' }
},
tooltip: {
trigger: 'axis',
axisPointer: { type: 'cross' },
formatter: function(params) {
if (!params || params.length === 0) return '';
const point = params[0];
const idx = point.dataIndex;
const priceChangePercent = ((prices[idx] - prevClose) / prevClose * 100);
const avgChangePercent = ((avgPrices[idx] - prevClose) / prevClose * 100);
const priceColor = priceChangePercent >= 0 ? '#ef5350' : '#26a69a';
const avgColor = avgChangePercent >= 0 ? '#ef5350' : '#26a69a';
return `时间:${times[idx]}<br/>现价:<span style="color: ${priceColor}">¥${prices[idx]?.toFixed(2)} (${priceChangePercent >= 0 ? '+' : ''}${priceChangePercent.toFixed(2)}%)</span><br/>均价:<span style="color: ${avgColor}">¥${avgPrices[idx]?.toFixed(2)} (${avgChangePercent >= 0 ? '+' : ''}${avgChangePercent.toFixed(2)}%)</span><br/>昨收:¥${prevClose?.toFixed(2)}<br/>成交量:${Math.round(volumes[idx]/100)}`;
}
},
grid: [
{ left: '10%', right: '10%', height: '60%', top: '15%' },
{ left: '10%', right: '10%', top: '80%', height: '15%' }
],
xAxis: [
{ type: 'category', data: times, gridIndex: 0, boundaryGap: false },
{ type: 'category', data: times, gridIndex: 1, axisLabel: { show: false } }
],
yAxis: [
{
type: 'value',
gridIndex: 0,
scale: false,
position: 'left',
axisLabel: {
formatter: function(value) {
return (value >= 0 ? '+' : '') + value.toFixed(2) + '%';
}
},
splitLine: {
show: true,
lineStyle: {
color: '#f0f0f0'
}
}
},
{
type: 'value',
gridIndex: 0,
scale: false,
position: 'right',
axisLabel: {
formatter: function(value) {
return (value >= 0 ? '+' : '') + value.toFixed(2) + '%';
}
}
},
{ type: 'value', gridIndex: 1, scale: true, axisLabel: { formatter: v => Math.round(v/100) + '手' } }
],
dataZoom: [
{ type: 'inside', xAxisIndex: [0, 1], start: 0, end: 100 },
{ show: true, xAxisIndex: [0, 1], type: 'slider', bottom: '0%' }
],
series: [
{
name: '分时价',
type: 'line',
xAxisIndex: 0,
yAxisIndex: 0,
data: changePercentData,
smooth: true,
showSymbol: false,
lineStyle: { color: lineColor, width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: isUp ? 'rgba(239, 83, 80, 0.3)' : 'rgba(38, 166, 154, 0.3)' },
{ offset: 1, color: isUp ? 'rgba(239, 83, 80, 0.05)' : 'rgba(38, 166, 154, 0.05)' }
])
},
markLine: {
symbol: 'none',
data: [
// 昨收盘价基准线 (0%)
{
yAxis: 0,
lineStyle: {
color: '#666',
type: 'dashed',
width: 1.5,
opacity: 0.8
},
label: {
show: true,
formatter: '昨收盘价',
position: 'insideEndTop',
color: '#666',
fontSize: 12
}
},
...eventMarkLineData
],
animation: false
}
},
{
name: '均价线',
type: 'line',
xAxisIndex: 0,
yAxisIndex: 1,
data: avgChangePercentData,
smooth: true,
showSymbol: false,
lineStyle: { color: '#FFA500', width: 1 }
},
{
name: '成交量',
type: 'bar',
xAxisIndex: 1,
yAxisIndex: 2,
data: volumes,
itemStyle: { color: '#b0c4de', opacity: 0.6 }
}
]
};
}
// 日K线
if (type === 'daily') {
const dates = stockData.map(item => item.time || item.date);
const klineData = stockData.map(item => [item.open, item.close, item.low, item.high]);
const volumes = stockData.map(item => item.volume);
// 计算事件标记线位置(重要修复)
let eventMarkLineData = [];
if (originalEventTime && dates.length > 0) {
const eventMoment = moment(originalEventTime);
const eventDate = eventMoment.format('YYYY-MM-DD');
// 找到事件发生日期或最接近的交易日
let targetIndex = -1;
// 1. 先尝试找到完全匹配的日期
targetIndex = dates.findIndex(date => date === eventDate);
// 2. 如果没有完全匹配,找到第一个大于等于事件日期的交易日
if (targetIndex === -1) {
for (let i = 0; i < dates.length; i++) {
if (dates[i] >= eventDate) {
targetIndex = i;
break;
}
}
}
// 3. 如果事件日期晚于所有交易日,则标记在最后一个交易日
if (targetIndex === -1 && eventDate > dates[dates.length - 1]) {
targetIndex = dates.length - 1;
}
// 4. 如果事件日期早于所有交易日,则标记在第一个交易日
if (targetIndex === -1 && eventDate < dates[0]) {
targetIndex = 0;
}
if (targetIndex >= 0) {
let labelText = '事件发生';
let labelPosition = 'middle';
// 根据事件时间和交易日的关系调整标签
if (eventDate === dates[targetIndex]) {
if (eventMoment.hour() >= 15) {
labelText = '事件发生\n(盘后)';
} else if (eventMoment.hour() < 9 || (eventMoment.hour() === 9 && eventMoment.minute() < 30)) {
labelText = '事件发生\n(盘前)';
}
} else if (eventDate < dates[targetIndex]) {
labelText = '事件发生\n(前一日)';
labelPosition = 'start';
} else {
labelText = '事件发生\n(影响日)';
labelPosition = 'end';
}
eventMarkLineData = [{
name: '事件发生',
xAxis: targetIndex,
label: {
formatter: labelText,
position: labelPosition,
color: '#FFD700',
fontSize: 12,
backgroundColor: 'rgba(0,0,0,0.5)',
padding: [4, 8],
borderRadius: 4
},
lineStyle: {
color: '#FFD700',
type: 'solid',
width: 2
}
}];
}
}
return {
title: {
text: `${stock.stock_name || stock.stock_code} - 日K线`,
left: 'center',
textStyle: { fontSize: 16, fontWeight: 'bold' }
},
tooltip: {
trigger: 'axis',
axisPointer: { type: 'cross' },
formatter: function(params) {
if (!params || params.length === 0) return '';
const kline = params[0];
const volume = params[1];
if (!kline || !kline.data) return '';
let tooltipHtml = `日期: ${kline.axisValue}<br/>开盘: ¥${kline.data[0]}<br/>收盘: ¥${kline.data[1]}<br/>最低: ¥${kline.data[2]}<br/>最高: ¥${kline.data[3]}`;
if (volume && volume.data) {
tooltipHtml += `<br/>成交量: ${Math.round(volume.data/100)}`;
}
return tooltipHtml;
}
},
grid: [
{ left: '10%', right: '10%', height: '60%' },
{ left: '10%', right: '10%', top: '75%', height: '20%' }
],
xAxis: [
{ type: 'category', data: dates, scale: true, boundaryGap: true, gridIndex: 0 },
{ type: 'category', data: dates, gridIndex: 1, axisLabel: { show: false } }
],
yAxis: [
{ scale: true, splitArea: { show: true }, gridIndex: 0 },
{ scale: true, gridIndex: 1, axisLabel: { formatter: (value) => Math.round(value/100) + '手' } }
],
dataZoom: [
{ type: 'inside', xAxisIndex: [0, 1], start: 70, end: 100 },
{ show: true, xAxisIndex: [0, 1], type: 'slider', bottom: '0%', start: 70, end: 100 }
],
series: [
{
name: 'K线',
type: 'candlestick',
yAxisIndex: 0,
data: klineData,
markLine: {
symbol: 'none',
data: eventMarkLineData,
animation: false
},
itemStyle: {
color: '#ef5350',
color0: '#26a69a',
borderColor: '#ef5350',
borderColor0: '#26a69a'
}
},
{
name: '成交量',
type: 'bar',
xAxisIndex: 1,
yAxisIndex: 1,
data: volumes.map((volume, index) => ({
value: volume,
itemStyle: {
color: stockData[index].close >= stockData[index].open ? '#ef5350' : '#26a69a'
}
}))
}
]
};
}
return {};
};
if (!stock) return null;
return (
<Modal isOpen={isOpen} onClose={onClose} size={size}>
<ModalOverlay />
<ModalContent maxW="90vw" maxH="90vh" overflow="hidden">
<ModalHeader pb={4}>
<VStack align="flex-start" spacing={2}>
<HStack>
<Text fontSize="lg" fontWeight="bold">
{stock.stock_name || stock.stock_code} ({stock.stock_code}) - 股票详情
</Text>
{chartData && (
<Badge colorScheme="blue">{chartData.trade_date}</Badge>
)}
</HStack>
<ButtonGroup size="sm">
<Button
variant={chartType === 'timeline' ? 'solid' : 'outline'}
onClick={() => setChartType('timeline')}
colorScheme="blue"
>
分时线
</Button>
<Button
variant={chartType === 'daily' ? 'solid' : 'outline'}
onClick={() => setChartType('daily')}
colorScheme="blue"
>
日K线
</Button>
</ButtonGroup>
</VStack>
</ModalHeader>
<ModalCloseButton />
<ModalBody p={0} overflowY="auto" maxH="calc(90vh - 120px)">
<Box h="400px" w="100%" position="relative">
{loading && (
<Flex
position="absolute"
top="0" left="0" right="0" bottom="0"
bg="rgba(255, 255, 255, 0.7)"
zIndex="10"
alignItems="center"
justifyContent="center"
>
<VStack spacing={4}>
<CircularProgress isIndeterminate color="blue.300" />
<Text>加载图表数据...</Text>
</VStack>
</Flex>
)}
<div ref={chartRef} style={{ height: '100%', width: '100%', minHeight: '500px' }} />
</Box>
{stock?.relation_desc && (
<Box p={4} borderTop="1px solid" borderTopColor="gray.200">
<Text fontSize="sm" fontWeight="bold" mb={2}>关联描述:</Text>
<Text fontSize="sm" color="gray.600">{stock.relation_desc}</Text>
</Box>
)}
{process.env.NODE_ENV === 'development' && chartData && (
<Box p={4} bg="gray.50" fontSize="xs" color="gray.600">
<Text fontWeight="bold">调试信息:</Text>
<Text>数据条数: {chartData.data ? chartData.data.length : 0}</Text>
<Text>交易日期: {chartData.trade_date}</Text>
<Text>图表类型: {chartType}</Text>
<Text>原始事件时间: {eventTime}</Text>
</Box>
)}
</ModalBody>
</ModalContent>
</Modal>
);
};
export default StockChartModal;

View File

@@ -0,0 +1,175 @@
import React from 'react';
import {
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalFooter,
ModalBody,
ModalCloseButton,
Button,
VStack,
HStack,
Text,
Badge,
Box,
useColorModeValue,
Icon,
Divider
} from '@chakra-ui/react';
import { FaCrown, FaLock, FaStar, FaRocket } from 'react-icons/fa';
const SubscriptionUpgradeModal = ({
isOpen,
onClose,
requiredLevel = 'pro',
featureName = '功能',
currentLevel = 'free'
}) => {
const bgColor = useColorModeValue('white', 'gray.800');
const borderColor = useColorModeValue('gray.200', 'gray.600');
const textColor = useColorModeValue('gray.600', 'gray.300');
// 订阅级别信息
const subscriptionLevels = {
free: {
name: '免费版',
icon: FaLock,
color: 'gray',
features: ['基础事件浏览', '有限历史事件查看']
},
pro: {
name: 'Pro版',
icon: FaStar,
color: 'blue',
features: ['相关标的分析', '相关概念分析', '完整历史事件']
},
max: {
name: 'Max版',
icon: FaCrown,
color: 'purple',
features: ['传导链分析', '高级分析工具', '实时数据推送', '所有Pro版功能']
}
};
const currentLevelInfo = subscriptionLevels[currentLevel] || subscriptionLevels.free;
const requiredLevelInfo = subscriptionLevels[requiredLevel] || subscriptionLevels.pro;
const handleUpgrade = () => {
// 跳转到订阅页面
window.location.href = 'https://valuefrontier.cn/home/pages/account/subscription';
};
return (
<Modal isOpen={isOpen} onClose={onClose} size="lg" isCentered>
<ModalOverlay />
<ModalContent bg={bgColor}>
<ModalHeader borderBottomWidth="1px" borderColor={borderColor}>
<HStack spacing={3}>
<Icon as={FaLock} color="red.500" boxSize={6} />
<VStack align="start" spacing={0}>
<Text fontSize="lg" fontWeight="bold">
需要{requiredLevelInfo.name}订阅
</Text>
<Text fontSize="sm" color={textColor}>
当前功能需要更高权限
</Text>
</VStack>
</HStack>
</ModalHeader>
<ModalCloseButton />
<ModalBody py={6}>
<VStack spacing={6} align="stretch">
{/* 功能说明 */}
<Box>
<Text fontWeight="semibold" mb={2}>
您正在尝试访问
</Text>
<Box
p={3}
bg={useColorModeValue('blue.50', 'blue.900')}
borderRadius="md"
borderLeft="4px solid"
borderColor="blue.500"
>
<Text fontSize="md" fontWeight="medium">
{featureName}
</Text>
</Box>
</Box>
<Divider />
{/* 当前订阅状态 */}
<Box>
<HStack justify="space-between" mb={3}>
<Text fontWeight="semibold">当前订阅</Text>
<Badge colorScheme={currentLevelInfo.color}>
{currentLevelInfo.name}
</Badge>
</HStack>
<VStack align="start" spacing={1}>
{currentLevelInfo.features.map((feature, index) => (
<HStack key={index} spacing={2}>
<Icon as={currentLevelInfo.icon} color={`${currentLevelInfo.color}.500`} boxSize={3} />
<Text fontSize="sm" color={textColor}>{feature}</Text>
</HStack>
))}
</VStack>
</Box>
{/* 所需订阅状态 */}
<Box>
<HStack justify="space-between" mb={3}>
<Text fontWeight="semibold">所需订阅</Text>
<Badge colorScheme={requiredLevelInfo.color} variant="solid">
{requiredLevelInfo.name}
</Badge>
</HStack>
<VStack align="start" spacing={1}>
{requiredLevelInfo.features.map((feature, index) => (
<HStack key={index} spacing={2}>
<Icon as={requiredLevelInfo.icon} color={`${requiredLevelInfo.color}.500`} boxSize={3} />
<Text fontSize="sm" color={textColor}>{feature}</Text>
</HStack>
))}
</VStack>
</Box>
{/* 升级提示 */}
<Box
p={3}
bg={useColorModeValue('yellow.50', 'yellow.900')}
borderRadius="md"
>
<HStack spacing={2}>
<Icon as={FaRocket} color="yellow.600" />
<Text fontSize="sm" color={useColorModeValue('yellow.800', 'yellow.200')}>
升级到{requiredLevelInfo.name}即可解锁此功能
</Text>
</HStack>
</Box>
</VStack>
</ModalBody>
<ModalFooter borderTopWidth="1px" borderColor={borderColor}>
<HStack spacing={3}>
<Button variant="outline" onClick={onClose}>
稍后再说
</Button>
<Button
colorScheme={requiredLevelInfo.color}
leftIcon={<Icon as={FaCrown} />}
onClick={handleUpgrade}
>
立即升级
</Button>
</HStack>
</ModalFooter>
</ModalContent>
</Modal>
);
};
export default SubscriptionUpgradeModal;

View File

@@ -0,0 +1,288 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import {
Button,
Flex,
Icon,
NumberDecrementStepper,
NumberIncrementStepper,
NumberInput,
NumberInputField,
NumberInputStepper,
Select,
Stack,
Table,
Tbody,
Td,
Text,
Th,
Thead,
Tr,
} from "@chakra-ui/react";
import React, { useMemo } from "react";
import { GrFormNext, GrFormPrevious } from "react-icons/gr";
import {
TiArrowSortedDown,
TiArrowSortedUp,
TiArrowUnsorted,
} from "react-icons/ti";
import { usePagination, useSortBy, useTable } from "react-table";
function BasicTable(props) {
const { columnsData, tableData } = props;
const columns = useMemo(() => columnsData, []);
const data = useMemo(() => tableData, []);
const tableInstance = useTable(
{
columns,
data,
},
useSortBy,
usePagination
);
const {
getTableProps,
getTableBodyProps,
headerGroups,
page,
gotoPage,
pageCount,
prepareRow,
nextPage,
previousPage,
canNextPage,
canPreviousPage,
setPageSize,
state,
} = tableInstance;
const createPages = (count) => {
let arrPageCount = [];
for (let i = 1; i <= count; i++) {
arrPageCount.push(i);
}
return arrPageCount;
};
const { pageIndex, pageSize } = state;
return (
<>
<Flex
direction="column"
w="100%"
overflowX={{ sm: "scroll", lg: "hidden" }}
>
<Stack
direction="row"
spacing="12px"
align="center"
my="24px"
px="22px"
>
<Select
variant="main"
value={pageSize}
onChange={(e) => setPageSize(Number(e.target.value))}
color="gray.500"
size="sm"
borderRadius="12px"
maxW="75px"
cursor="pointer"
>
<option>5</option>
<option>10</option>
<option>15</option>
<option>20</option>
<option>25</option>
</Select>
<Text fontSize="xs" color="gray.400" fontWeight="normal">
entries per page
</Text>
</Stack>
<Table {...getTableProps()} variant="simple" color="gray.500" mb="24px">
<Thead>
{headerGroups.map((headerGroup, index) => (
<Tr {...headerGroup.getHeaderGroupProps()} key={index}>
{headerGroup.headers.map((column, index) => (
<Th key={index}
{...column.getHeaderProps(column.getSortByToggleProps())}
>
<Flex
justify="space-between"
align="center"
fontSize={{ sm: "10px", lg: "12px" }}
color="gray.400"
>
{column.render("Header")}
<Icon
w={{ sm: "10px", md: "14px" }}
h={{ sm: "10px", md: "14px" }}
color={columns.isSorted ? "gray.500" : "gray.400"}
float="right"
as={
column.isSorted
? column.isSortedDesc
? TiArrowSortedDown
: TiArrowSortedUp
: TiArrowUnsorted
}
/>
</Flex>
</Th>
))}
</Tr>
))}
</Thead>
<Tbody {...getTableBodyProps()}>
{page.map((row, index) => {
prepareRow(row);
return (
<Tr {...row.getRowProps()} key={index}>
{row.cells.map((cell, index) => {
return (
<Td
{...cell.getCellProps()}
fontSize={{ sm: "14px" }}
key={index}
>
{cell.render("Cell")}
</Td>
);
})}
</Tr>
);
})}
</Tbody>
</Table>
<Flex
direction={{ sm: "column", md: "row" }}
w="100%"
justify="space-between"
align="center"
px={{ md: "22px" }}
>
<Text
fontSize="sm"
color="gray.500"
fontWeight="normal"
mb={{ sm: "24px", md: "0px" }}
>
Showing {pageSize * pageIndex + 1} to{" "}
{pageSize * (pageIndex + 1) <= tableData.length
? pageSize * (pageIndex + 1)
: tableData.length}{" "}
of {tableData.length} entries
</Text>
<Stack direction="row" alignSelf="flex-end" spacing="4px" ms="auto">
<Button
variant="no-effects"
onClick={() => previousPage()}
transition="all .5s ease"
w="40px"
h="40px"
borderRadius="8px"
bg="#fff"
border="1px solid lightgray"
display={
pageSize === 5 ? "none" : canPreviousPage ? "flex" : "none"
}
_hover={{
opacity: "0.7",
borderColor: "gray.500",
}}
>
<Icon as={GrFormPrevious} w="16px" h="16px" color="gray.400" />
</Button>
{pageSize === 5 ? (
<NumberInput
max={pageCount - 1}
min={1}
w="75px"
mx="6px"
defaultValue="1"
onChange={(e) => gotoPage(e)}
>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper onClick={() => nextPage()} />
<NumberDecrementStepper onClick={() => previousPage()} />
</NumberInputStepper>
</NumberInput>
) : (
createPages(pageCount).map((pageNumber, index) => {
return (
<Button
variant="no-effects"
transition="all .5s ease"
onClick={() => gotoPage(pageNumber - 1)}
w="40px"
h="40px"
borderRadius="8px"
bg={pageNumber === pageIndex + 1 ? "blue.500" : "#fff"}
border={
pageNumber === pageIndex + 1
? "none"
: "1px solid lightgray"
}
_hover={{
opacity: "0.7",
borderColor: "gray.500",
}}
key={index}
>
<Text
fontSize="sm"
color={pageNumber === pageIndex + 1 ? "#fff" : "gray.600"}
>
{pageNumber}
</Text>
</Button>
);
})
)}
<Button
variant="no-effects"
onClick={() => nextPage()}
transition="all .5s ease"
w="40px"
h="40px"
borderRadius="8px"
bg="#fff"
border="1px solid lightgray"
display={pageSize === 5 ? "none" : canNextPage ? "flex" : "none"}
_hover={{
bg: "gray.200",
opacity: "0.7",
borderColor: "gray.500",
}}
>
<Icon as={GrFormNext} w="16px" h="16px" color="gray.400" />
</Button>
</Stack>
</Flex>
</Flex>
</>
);
}
export default BasicTable;

View File

@@ -0,0 +1,93 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import {
Box,
Button,
Flex,
Icon,
Text,
useColorModeValue,
} from "@chakra-ui/react";
import React from "react";
import { FaPencilAlt, FaTrashAlt } from "react-icons/fa";
function BillingRow(props) {
const textColor = useColorModeValue("gray.700", "white");
const bgColor = useColorModeValue("#F8F9FA", "navy.900");
const nameColor = useColorModeValue("gray.500", "white");
const { name, company, email, number } = props;
return (
<Box p="24px" bg={bgColor} mb="22px" borderRadius="12px">
<Flex justify="space-between" w="100%">
<Flex direction="column" maxWidth="70%">
<Text color={nameColor} fontSize="md" fontWeight="bold" mb="10px">
{name}
</Text>
<Text color="gray.400" fontSize="sm">
Company Name:{" "}
<Text as="span" color={nameColor} fontWeight="bold">
{company}
</Text>
</Text>
<Text color="gray.400" fontSize="sm">
Email Address:{" "}
<Text as="span" color={nameColor} fontWeight="bold">
{email}
</Text>
</Text>
<Text color="gray.400" fontSize="sm">
VAT Number:{" "}
<Text as="span" color={nameColor} fontWeight="bold">
{number}
</Text>
</Text>
</Flex>
<Flex
direction={{ sm: "column", md: "row" }}
align="flex-start"
p={{ md: "24px" }}
>
<Button
p="0px"
variant="no-effects"
mb={{ sm: "10px", md: "0px" }}
me={{ md: "12px" }}
>
<Flex color="red.500" cursor="pointer" align="center" p="12px">
<Icon as={FaTrashAlt} me="4px" />
<Text fontSize="sm" fontWeight="semibold">
DELETE
</Text>
</Flex>
</Button>
<Button p="0px" variant="no-effects">
<Flex color={textColor} cursor="pointer" align="center" p="12px">
<Icon as={FaPencilAlt} me="4px" />
<Text fontSize="sm" fontWeight="semibold">
EDIT
</Text>
</Flex>
</Button>
</Flex>
</Flex>
</Box>
);
}
export default BillingRow;

View File

@@ -0,0 +1,89 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import {
Avatar,
AvatarGroup,
Flex,
Icon,
Progress,
Td,
Text,
Tr,
useColorModeValue,
} from "@chakra-ui/react";
import React from "react";
function DashboardTableRow(props) {
const { logo, name, members, budget, progression } = props;
const textColor = useColorModeValue("gray.700", "white");
return (
<Tr>
<Td minWidth={{ sm: "250px" }} ps="0px">
<Flex align="center" py=".8rem" minWidth="100%" flexWrap="nowrap">
<Icon as={logo} h={"24px"} w={"24px"} pe="5px" />
<Text
fontSize="md"
color={textColor}
fontWeight="bold"
minWidth="100%"
>
{name}
</Text>
</Flex>
</Td>
<Td>
<AvatarGroup size="sm">
{members.map((member, index) => {
return (
<Avatar
name="Ryan Florence"
src={member}
_hover={{ zIndex: "3", cursor: "pointer" }}
key={index}
/>
);
})}
</AvatarGroup>
</Td>
<Td>
<Text fontSize="md" color={textColor} fontWeight="bold" pb=".5rem">
{budget}
</Text>
</Td>
<Td>
<Flex direction="column">
<Text
fontSize="md"
color="teal.300"
fontWeight="bold"
pb=".2rem"
>{`${progression}%`}</Text>
<Progress
colorScheme={progression === 100 ? "teal" : "cyan"}
size="xs"
value={progression}
borderRadius="15px"
/>
</Flex>
</Td>
</Tr>
);
}
export default DashboardTableRow;

View File

@@ -0,0 +1,61 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import {
Box,
Button,
Flex,
Icon,
Spacer,
Text,
useColorModeValue,
} from "@chakra-ui/react";
import React from "react";
function InvoicesRow(props) {
const textColor = useColorModeValue("gray.700", "white");
const { date, code, price, format, logo } = props;
return (
<Flex my={{ sm: "1rem", xl: "10px" }} alignItems="center">
<Flex direction="column">
<Text fontSize="md" color={textColor} fontWeight="bold">
{date}
</Text>
<Text fontSize="sm" color="gray.400" fontWeight="semibold" me="16px">
{code}
</Text>
</Flex>
<Spacer />
<Box me="12px">
<Text fontSize="md" color="gray.400" fontWeight="semibold">
{price}
</Text>
</Box>
<Button p="0px" bg="transparent" variant="no-effects">
<Flex alignItems="center" p="12px">
<Icon as={logo} w="20px" h="auto" me="5px" />
<Text fontSize="md" color={textColor} fontWeight="bold">
{format}
</Text>
</Flex>
</Button>
</Flex>
);
}
export default InvoicesRow;

View File

@@ -0,0 +1,312 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import {
Button,
Flex,
Icon,
Input,
NumberDecrementStepper,
NumberIncrementStepper,
NumberInput,
NumberInputField,
NumberInputStepper,
Select,
Stack,
Table,
Tbody,
Td,
Text,
Th,
Thead,
Tr,
} from "@chakra-ui/react";
import React, { useMemo } from "react";
import { GrFormNext, GrFormPrevious } from "react-icons/gr";
import {
TiArrowSortedDown,
TiArrowSortedUp,
TiArrowUnsorted,
} from "react-icons/ti";
import {
useGlobalFilter,
usePagination,
useSortBy,
useTable,
} from "react-table";
function SearchTable1(props) {
const { columnsData, tableData } = props;
const columns = useMemo(() => columnsData, []);
const data = useMemo(() => tableData, []);
const tableInstance = useTable(
{
columns,
data,
},
useGlobalFilter,
useSortBy,
usePagination
);
const {
getTableProps,
getTableBodyProps,
headerGroups,
page,
gotoPage,
pageCount,
prepareRow,
nextPage,
previousPage,
canNextPage,
canPreviousPage,
setPageSize,
setGlobalFilter,
state,
} = tableInstance;
const createPages = (count) => {
let arrPageCount = [];
for (let i = 1; i <= count; i++) {
arrPageCount.push(i);
}
return arrPageCount;
};
const { pageIndex, pageSize, globalFilter } = state;
return (
<>
<Flex
direction="column"
w="100%"
overflowX={{ sm: "scroll", lg: "hidden" }}
>
<Flex justify="space-between" align="center" w="100%" px="22px">
<Stack
direction={{ sm: "column", md: "row" }}
spacing={{ sm: "4px", md: "12px" }}
align="center"
me="12px"
my="24px"
minW={{ sm: "100px", md: "200px" }}
>
<Select
variant="main"
value={pageSize}
onChange={(e) => setPageSize(Number(e.target.value))}
color="gray.500"
size="sm"
borderRadius="12px"
maxW="75px"
cursor="pointer"
>
<option>5</option>
<option>10</option>
<option>15</option>
<option>20</option>
<option>25</option>
</Select>
<Text fontSize="xs" color="gray.400" fontWeight="normal">
entries per page
</Text>
</Stack>
<Input
variant="main"
type="text"
placeholder="Search..."
minW="75px"
maxW="175px"
fontSize="sm"
_focus={{ borderColor: "blue.500" }}
onChange={(e) => setGlobalFilter(e.target.value)}
/>
</Flex>
<Table {...getTableProps()} variant="simple" color="gray.500" mb="24px">
<Thead>
{headerGroups.map((headerGroup, index) => (
<Tr {...headerGroup.getHeaderGroupProps()} key={index}>
{headerGroup.headers.map((column, index) => (
<Th key={index}
{...column.getHeaderProps(column.getSortByToggleProps())}
pe="0px"
>
<Flex
justify="space-between"
align="center"
fontSize={{ sm: "10px", lg: "12px" }}
color="gray.400"
>
{column.render("Header")}
<Icon
w={{ sm: "10px", md: "14px" }}
h={{ sm: "10px", md: "14px" }}
color={columns.isSorted ? "gray.500" : "gray.400"}
float="right"
as={
column.isSorted
? column.isSortedDesc
? TiArrowSortedDown
: TiArrowSortedUp
: TiArrowUnsorted
}
/>
</Flex>
</Th>
))}
</Tr>
))}
</Thead>
<Tbody {...getTableBodyProps()}>
{page.map((row, index) => {
prepareRow(row);
return (
<Tr {...row.getRowProps()} key={index}>
{row.cells.map((cell, index) => {
return (
<Td
{...cell.getCellProps()}
fontSize={{ sm: "14px" }}
key={index}
>
{cell.render("Cell")}
</Td>
);
})}
</Tr>
);
})}
</Tbody>
</Table>
<Flex
direction={{ sm: "column", md: "row" }}
justify="space-between"
align="center"
w="100%"
px={{ md: "22px" }}
>
<Text
fontSize="sm"
color="gray.500"
fontWeight="normal"
mb={{ sm: "24px", md: "0px" }}
>
Showing {pageSize * pageIndex + 1} to{" "}
{pageSize * (pageIndex + 1) <= tableData.length
? pageSize * (pageIndex + 1)
: tableData.length}{" "}
of {tableData.length} entries
</Text>
<Stack direction="row" alignSelf="flex-end" spacing="4px" ms="auto">
<Button
variant="no-effects"
onClick={() => previousPage()}
transition="all .5s ease"
w="40px"
h="40px"
borderRadius="8px"
bg="#fff"
border="1px solid lightgray"
display={
pageSize === 5 ? "none" : canPreviousPage ? "flex" : "none"
}
_hover={{
bg: "gray.200",
opacity: "0.7",
borderColor: "gray.500",
}}
>
<Icon as={GrFormPrevious} w="16px" h="16px" color="gray.400" />
</Button>
{pageSize === 5 ? (
<NumberInput
max={pageCount - 1}
min={1}
w="75px"
mx="6px"
defaultValue="1"
onChange={(e) => gotoPage(e)}
>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper onClick={() => nextPage()} />
<NumberDecrementStepper onClick={() => previousPage()} />
</NumberInputStepper>
</NumberInput>
) : (
createPages(pageCount).map((pageNumber, index) => {
return (
<Button
variant="no-effects"
transition="all .5s ease"
onClick={() => gotoPage(pageNumber - 1)}
w="40px"
h="40px"
borderRadius="8px"
bg={pageNumber === pageIndex + 1 ? "blue.500" : "#fff"}
border={
pageNumber === pageIndex + 1
? "none"
: "1px solid lightgray"
}
_hover={{
opacity: "0.7",
borderColor: "gray.500",
}}
key={index}
>
<Text
fontSize="sm"
color={pageNumber === pageIndex + 1 ? "#fff" : "gray.600"}
>
{pageNumber}
</Text>
</Button>
);
})
)}
<Button
variant="no-effects"
onClick={() => nextPage()}
transition="all .5s ease"
w="40px"
h="40px"
borderRadius="8px"
bg="#fff"
border="1px solid lightgray"
display={pageSize === 5 ? "none" : canNextPage ? "flex" : "none"}
_hover={{
bg: "gray.200",
opacity: "0.7",
borderColor: "gray.500",
}}
>
<Icon as={GrFormNext} w="16px" h="16px" color="gray.400" />
</Button>
</Stack>
</Flex>
</Flex>
</>
);
}
export default SearchTable1;

View File

@@ -0,0 +1,360 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import {
Avatar,
Box,
Button,
Checkbox,
Flex,
Icon,
Input,
NumberDecrementStepper,
NumberIncrementStepper,
NumberInput,
NumberInputField,
NumberInputStepper,
Stack,
Table,
Tbody,
Td,
Text,
Th,
Thead,
Tr,
useColorModeValue,
} from "@chakra-ui/react";
import React, { useMemo } from "react";
import { SearchBar } from "components/Navbars/SearchBar/SearchBar";
import { MdReplay, MdCheck } from "react-icons/md";
import { IoMdClose } from "react-icons/io";
import { FaCheckCircle, FaTimesCircle, FaUndoAlt } from "react-icons/fa";
import { GrFormNext, GrFormPrevious } from "react-icons/gr";
import {
TiArrowSortedDown,
TiArrowSortedUp,
TiArrowUnsorted,
} from "react-icons/ti";
import {
useGlobalFilter,
usePagination,
useSortBy,
useTable,
} from "react-table";
function SearchTable2(props) {
const { columnsData, tableData } = props;
const columns = useMemo(() => columnsData, []);
const data = useMemo(() => tableData, []);
const tableInstance = useTable(
{
columns,
data,
},
useGlobalFilter,
useSortBy,
usePagination
);
const {
getTableProps,
getTableBodyProps,
headerGroups,
page,
gotoPage,
pageCount,
prepareRow,
nextPage,
previousPage,
canNextPage,
canPreviousPage,
setPageSize,
setGlobalFilter,
state,
} = tableInstance;
const createPages = (count) => {
let arrPageCount = [];
for (let i = 1; i <= count; i++) {
arrPageCount.push(i);
}
return arrPageCount;
};
const { pageIndex, pageSize, globalFilter } = state;
return (
<>
<Flex
direction="column"
w="100%"
overflowX={{ sm: "scroll", lg: "hidden" }}
>
<Flex
align={{ sm: "flex-start", lg: "flex-end" }}
justify={{ sm: "flex-start", lg: "flex-end" }}
w="100%"
px="22px"
mb="36px"
>
<SearchBar
border="1px solid "
borderColor={useColorModeValue("gray.200", "gray.600")}
onChange={(e) => setGlobalFilter(e.target.value)}
/>
</Flex>
<Table {...getTableProps()} variant="simple" color="gray.500" mb="24px">
<Thead>
{headerGroups.map((headerGroup, index) => (
<Tr {...headerGroup.getHeaderGroupProps()} key={index}>
{headerGroup.headers.map((column, index) => (
<Th key={index}
{...column.getHeaderProps(column.getSortByToggleProps())}
pe="0px"
>
<Flex
justify="space-between"
align="center"
fontSize={{ sm: "10px", lg: "12px" }}
color="gray.400"
>
{column.render("Header")}
<Icon
w={{ sm: "10px", md: "14px" }}
h={{ sm: "10px", md: "14px" }}
color={columns.isSorted ? "gray.500" : "gray.400"}
float="right"
as={
column.isSorted
? column.isSortedDesc
? TiArrowSortedDown
: TiArrowSortedUp
: TiArrowUnsorted
}
/>
</Flex>
</Th>
))}
</Tr>
))}
</Thead>
<Tbody {...getTableBodyProps()}>
{page.map((row, index) => {
prepareRow(row);
return (
<Tr {...row.getRowProps()} key={index}>
{row.cells.map((cell, index) => {
let data = "";
if (cell.column.Header === "STATUS") {
data = (
<Flex align="center">
<Flex
justify="center"
align="center"
border="1px solid"
borderColor={
cell.value === "Paid"
? "green.400"
: cell.value === "Refunded"
? "gray.400"
: "red.400"
}
borderRadius="50%"
width="24px"
height="24px"
me="6px"
>
<Icon
as={
cell.value === "Paid"
? MdCheck
: cell.value === "Refunded"
? MdReplay
: IoMdClose
}
color={
cell.value === "Paid"
? "green.400"
: cell.value === "Refunded"
? "gray.400"
: "red.400"
}
w="20px"
h="20px"
/>
</Flex>
<Text>{cell.value}</Text>
</Flex>
);
} else if (cell.column.Header === "ID") {
data = (
<Flex align="center">
<Checkbox size="lg" colorScheme="blue" me="8px" />
<Text>{cell.value}</Text>
</Flex>
);
} else if (cell.column.Header === "DATE") {
data = <Text>{cell.value}</Text>;
} else if (cell.column.Header === "CUSTOMER") {
data = (
<Flex align="center">
<Avatar
name={cell.value.split(" ").join()[0]}
w="30px"
h="30px"
me="6px"
/>
<Text>{cell.value}</Text>
</Flex>
);
} else if (cell.column.Header === "PRODUCT") {
data = <Text>{cell.value}</Text>;
} else if (cell.column.Header === "REVENUE") {
data = <Text>{cell.value}</Text>;
}
return (
<Td
{...cell.getCellProps()}
key={index}
fontSize={{ sm: "14px" }}
minW={{ sm: "150px", md: "200px", lg: "auto" }}
>
{data}
</Td>
);
})}
</Tr>
);
})}
</Tbody>
</Table>
<Flex
direction={{ sm: "column", md: "row" }}
justify="space-between"
align="center"
w="100%"
px={{ md: "22px" }}
>
<Text
fontSize="sm"
color="gray.500"
fontWeight="normal"
mb={{ sm: "24px", md: "0px" }}
>
Showing {pageSize * pageIndex + 1} to{" "}
{pageSize * (pageIndex + 1) <= tableData.length
? pageSize * (pageIndex + 1)
: tableData.length}{" "}
of {tableData.length} entries
</Text>
<Stack direction="row" alignSelf="flex-end" spacing="4px" ms="auto">
<Button
variant="no-effects"
onClick={() => previousPage()}
transition="all .5s ease"
w="40px"
h="40px"
borderRadius="8px"
bg="#fff"
border="1px solid lightgray"
display={
pageSize === 5 ? "none" : canPreviousPage ? "flex" : "none"
}
_hover={{
opacity: "0.7",
borderColor: "gray.500",
}}
>
<Icon as={GrFormPrevious} w="16px" h="16px" color="gray.400" />
</Button>
{pageSize === 5 ? (
<NumberInput
max={pageCount - 1}
min={1}
w="75px"
mx="6px"
defaultValue="1"
onChange={(e) => gotoPage(e)}
>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper onClick={() => nextPage()} />
<NumberDecrementStepper onClick={() => previousPage()} />
</NumberInputStepper>
</NumberInput>
) : (
createPages(pageCount).map((pageNumber, index) => {
return (
<Button
variant="no-effects"
transition="all .5s ease"
onClick={() => gotoPage(pageNumber - 1)}
w="40px"
h="40px"
borderRadius="8px"
bg={pageNumber === pageIndex + 1 ? "blue.500" : "#fff"}
border={
pageNumber === pageIndex + 1
? "none"
: "1px solid lightgray"
}
_hover={{
opacity: "0.7",
borderColor: "gray.500",
}}
key={index}
>
<Text
fontSize="sm"
color={pageNumber === pageIndex + 1 ? "#fff" : "gray.600"}
>
{pageNumber}
</Text>
</Button>
);
})
)}
<Button
variant="no-effects"
onClick={() => nextPage()}
transition="all .5s ease"
w="40px"
h="40px"
borderRadius="8px"
bg="#fff"
border="1px solid lightgray"
display={pageSize === 5 ? "none" : canNextPage ? "flex" : "none"}
_hover={{
bg: "gray.200",
opacity: "0.7",
borderColor: "gray.500",
}}
>
<Icon as={GrFormNext} w="16px" h="16px" color="gray.400" />
</Button>
</Stack>
</Flex>
</Flex>
</>
);
}
export default SearchTable2;

View File

@@ -0,0 +1,84 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import {
Button,
Flex,
Icon,
Progress,
Td,
Text,
Tr,
useColorModeValue,
} from "@chakra-ui/react";
import React from "react";
import { FaEllipsisV } from "react-icons/fa";
function DashboardTableRow(props) {
const { logo, name, status, budget, progression } = props;
const textColor = useColorModeValue("gray.700", "white");
return (
<Tr>
<Td minWidth={{ sm: "250px" }} ps="0px">
<Flex alignItems="center" py=".8rem" minWidth="100%" flexWrap="nowrap">
<Icon as={logo} h={"24px"} w={"24px"} me="18px" />
<Text
fontSize="md"
color={textColor}
fontWeight="bold"
minWidth="100%"
>
{name}
</Text>
</Flex>
</Td>
<Td>
<Text fontSize="md" color={textColor} fontWeight="bold" pb=".5rem">
{budget}
</Text>
</Td>
<Td>
<Text fontSize="md" color={textColor} fontWeight="bold" pb=".5rem">
{status}
</Text>
</Td>
<Td>
<Flex direction="column">
<Text
fontSize="md"
color="teal.300"
fontWeight="bold"
pb=".2rem"
>{`${progression}%`}</Text>
<Progress
colorScheme={progression === 100 ? "teal" : "cyan"}
size="xs"
value={progression}
borderRadius="15px"
/>
</Flex>
</Td>
<Td>
<Button p="0px" bg="transparent">
<Icon as={FaEllipsisV} color="gray.400" cursor="pointer" />
</Button>
</Td>
</Tr>
);
}
export default DashboardTableRow;

View File

@@ -0,0 +1,171 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import {
Avatar,
Flex,
Icon,
Td,
Text,
Tr,
useColorModeValue,
} from "@chakra-ui/react";
import React from "react";
import { BsCircleFill } from "react-icons/bs";
function TablesReportsRow(props) {
const {
image,
name,
email,
domain,
review,
employed,
id,
isLast,
paddingY,
} = props;
const borderColor = useColorModeValue("gray.200", "gray.600");
const textColor = useColorModeValue("gray.700", "white");
const secondaryColor = useColorModeValue("gray.400", "white");
const mainColor = useColorModeValue("gray.500", "white");
return (
<Tr border="none">
<Td
borderColor={borderColor}
minW={{ sm: "220px", xl: "180px", "2xl": "220px" }}
ps="0px"
border={isLast ? "none" : null}
px={{ xl: "2px", "2xl": "20px" }}
>
<Flex
align="center"
py={paddingY ? paddingY : ".8rem"}
minWidth="100%"
flexWrap="nowrap"
>
<Avatar
src={image}
borderRadius="12px"
me={{ sm: "18px", xl: "6px", "2xl": "18px" }}
/>
<Text
fontSize={{ sm: "md", xl: "sm", "2xl": "md" }}
color={textColor}
fontWeight="bold"
minWidth="100%"
>
{name}
</Text>
</Flex>
</Td>
<Td
borderColor={borderColor}
minW={{ sm: "150px", lg: "150px" }}
border={isLast ? "none" : null}
px={{ xl: "2px", "2xl": "20px" }}
>
<Flex direction="column">
<Text
fontSize={{ sm: "md", xl: "sm", "2xl": "md" }}
color={mainColor}
fontWeight="bold"
>
{domain}
</Text>
</Flex>
</Td>
<Td
borderColor={borderColor}
minW={{ sm: "150px", lg: "120px" }}
border={isLast ? "none" : null}
px={{ xl: "2px", "2xl": "20px" }}
>
<Flex align="center">
<Icon
as={BsCircleFill}
w="8px"
h="8px"
color={
review === "Positive"
? "teal.300"
: review === "Negative"
? "red.500"
: "gray.700"
}
me="6px"
/>
<Text
color={secondaryColor}
fontSize={{ sm: "md", xl: "sm", "2xl": "md" }}
>
{review}
</Text>
</Flex>
</Td>
<Td
borderColor={borderColor}
minW={{ sm: "200px", lg: "170px" }}
border={isLast ? "none" : null}
px={{ xl: "2px", "2xl": "20px" }}
>
<Text
fontSize={{ sm: "md", xl: "sm", "2xl": "md" }}
color={secondaryColor}
fontWeight="normal"
pb=".5rem"
>
{email}
</Text>
</Td>
<Td
borderColor={borderColor}
minW={{ sm: "150px", lg: "170px" }}
border={isLast ? "none" : null}
px={{ xl: "2px", "2xl": "20px" }}
>
<Text
fontSize={{ sm: "md", xl: "sm", "2xl": "md" }}
color={secondaryColor}
fontWeight="normal"
pb=".5rem"
>
{employed}
</Text>
</Td>
<Td
borderColor={borderColor}
minW={{ sm: "150px", lg: "170px" }}
border={isLast ? "none" : null}
px={{ xl: "2px", "2xl": "20px" }}
>
<Text
fontSize={{ sm: "md", xl: "sm", "2xl": "md" }}
color={secondaryColor}
fontWeight="normal"
pb=".5rem"
>
{id}
</Text>
</Td>
</Tr>
);
}
export default TablesReportsRow;

View File

@@ -0,0 +1,120 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import {
Avatar,
Badge,
Button,
Flex,
Td,
Text,
Tr,
useColorModeValue,
} from "@chakra-ui/react";
import React from "react";
function TablesTableRow(props) {
const {
logo,
name,
email,
subdomain,
domain,
status,
date,
paddingY,
isLast,
} = props;
const textColor = useColorModeValue("gray.500", "white");
const titleColor = useColorModeValue("gray.700", "white");
const bgStatus = useColorModeValue("gray.400", "navy.900");
const borderColor = useColorModeValue("gray.200", "gray.600");
return (
<Tr>
<Td
minWidth={{ sm: "250px" }}
pl="0px"
borderColor={borderColor}
borderBottom={isLast ? "none" : null}
>
<Flex
align="center"
py={paddingY ? paddingY : ".8rem"}
minWidth="100%"
flexWrap="nowrap"
>
<Avatar src={logo} w="50px" borderRadius="12px" me="18px" />
<Flex direction="column">
<Text
fontSize="md"
color={titleColor}
fontWeight="bold"
minWidth="100%"
>
{name}
</Text>
<Text fontSize="sm" color="gray.400" fontWeight="normal">
{email}
</Text>
</Flex>
</Flex>
</Td>
<Td borderColor={borderColor} borderBottom={isLast ? "none" : null}>
<Flex direction="column">
<Text fontSize="md" color={textColor} fontWeight="bold">
{domain}
</Text>
<Text fontSize="sm" color="gray.400" fontWeight="normal">
{subdomain}
</Text>
</Flex>
</Td>
<Td borderColor={borderColor} borderBottom={isLast ? "none" : null}>
<Badge
bg={status === "Online" ? "green.400" : bgStatus}
color={status === "Online" ? "white" : "white"}
fontSize="16px"
p="3px 10px"
borderRadius="8px"
>
{status}
</Badge>
</Td>
<Td borderColor={borderColor} borderBottom={isLast ? "none" : null}>
<Text fontSize="md" color={textColor} fontWeight="bold" pb=".5rem">
{date}
</Text>
</Td>
<Td borderColor={borderColor} borderBottom={isLast ? "none" : null}>
<Button p="0px" bg="transparent" variant="no-effects">
<Text
fontSize="md"
color="gray.400"
fontWeight="bold"
cursor="pointer"
>
Edit
</Text>
</Button>
</Td>
</Tr>
);
}
export default TablesTableRow;

View File

@@ -0,0 +1,132 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import {
Box,
Flex,
Icon,
Stack,
Tag,
Text,
useColorMode,
useColorModeValue,
} from "@chakra-ui/react";
import React from "react";
function TimelineRow(props) {
const {
logo,
title,
titleColor,
date,
color,
index,
tags,
description,
arrLength,
isDark,
} = props;
const textColor = useColorModeValue("gray.700", "white.300");
const { colorMode } = useColorMode();
return (
<Flex alignItems="center" minH="78px" justifyContent="start" mb="5px">
<Flex direction="column" h="100%">
<Icon
as={logo}
color={isDark && colorMode === "dark" ? "white" : color}
h={"30px"}
w={"26px"}
pe="6px"
zIndex="1"
position="relative"
right={document.documentElement.dir === "rtl" ? "-8px" : ""}
left={document.documentElement.dir === "rtl" ? "" : "-8px"}
/>
<Box
w="2px"
bg="gray.200"
minH={
index === arrLength - 1
? "15px"
: description
? { sm: "200px", md: "130px", lg: "150px", "2xl": "130px" }
: "35px"
}
></Box>
</Flex>
<Flex direction="column" justifyContent="flex-start" h="100%">
<Text
fontSize="sm"
color={titleColor !== undefined ? titleColor : textColor}
fontWeight="bold"
>
{title}
</Text>
<Text
fontSize="sm"
color={isDark && colorMode === "dark" ? "white" : "gray.400"}
fontWeight="normal"
mb="14px"
>
{date}
</Text>
{description !== undefined ? (
<Text
fontSize="sm"
color={isDark && colorMode === "dark" ? "white" : "gray.400"}
fontWeight="normal"
mb="6px"
maxW="70%"
>
{description}
</Text>
) : null}
{tags !== undefined ? (
<Stack direction="row" spacing="6px">
{tags.map((tag, index) => {
return (
<Tag
bg={
isDark && colorMode === "dark" && tag.bgTag === "blue.500"
? "white"
: tag.bgTag
}
fontSize="xs"
size="lg"
color={
isDark && colorMode === "dark" && tag.bgTag === "blue.500"
? "blue.500"
: "white"
}
mb="16px"
borderRadius="8px"
alignSelf="flex-start"
key={index}
>
{tag.titleTag}
</Tag>
);
})}
</Stack>
) : null}
</Flex>
</Flex>
);
}
export default TimelineRow;

View File

@@ -0,0 +1,81 @@
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import { Box, Flex, Icon, Text, useColorModeValue } from "@chakra-ui/react";
import React from "react";
function TransactionRow(props) {
const textColor = useColorModeValue("gray.700", "white");
const { name, date, logo, price } = props;
return (
<Flex my="1rem" justifyContent="space-between">
<Flex alignItems="center">
<Box
me="12px"
borderRadius="50%"
color={
price[0] === "+"
? "green.400"
: price[0] === "-"
? "red.400"
: "gray.400"
}
border="1px solid"
display="flex"
alignItems="center"
justifyContent="center"
w="35px"
h="35px"
>
<Icon as={logo} />
</Box>
<Flex direction="column">
<Text
fontSize={{ sm: "md", md: "lg", lg: "md" }}
color={textColor}
fontWeight="bold"
>
{name}
</Text>
<Text
fontSize={{ sm: "xs", md: "sm", lg: "xs" }}
color="gray.400"
fontWeight="semibold"
>
{date}
</Text>
</Flex>
</Flex>
<Box
color={
price[0] === "+"
? "green.400"
: price[0] === "-"
? "red.400"
: { textColor }
}
>
<Text fontSize={{ sm: "md", md: "lg", lg: "md" }} fontWeight="bold">
{price}
</Text>
</Box>
</Flex>
);
}
export default TransactionRow;

View File

@@ -0,0 +1,11 @@
import { brackets } from "./svgs.js";
const Tagline = ({ className, children }) => (
<div className={`tagline flex items-center ${className || ""}`}>
{brackets("left")}
<div className="mx-3 text-n-3">{children}</div>
{brackets("right")}
</div>
);
export default Tagline;

View File

@@ -0,0 +1,49 @@
export const brackets = (position) =>
position === "left" ? (
<svg
width="5"
height="14"
viewBox="0 0 5 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M5 0.822266H1V12.8223H5" stroke="url(#brackets-left)" />
<defs>
<linearGradient
id="brackets-left"
x1="50%"
x2="50%"
y1="0%"
y2="100%"
>
<stop offset="0%" stopColor="#89F9E8" />
<stop offset="100%" stopColor="#FACB7B" />
</linearGradient>
</defs>
</svg>
) : (
<svg
width="5"
height="14"
viewBox="0 0 5 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M-2.98023e-08 0.822266H4V12.8223H-2.98023e-08"
stroke="url(#brackets-right)"
/>
<defs>
<linearGradient
id="brackets-right"
x1="14.635%"
x2="14.635%"
y1="0%"
y2="100%"
>
<stop offset="0%" stopColor="#9099FC" />
<stop offset="100%" stopColor="#D87CEE" />
</linearGradient>
</defs>
</svg>
);

View File

@@ -0,0 +1,49 @@
export const brackets = (position: "left" | "right") =>
position === "left" ? (
<svg
width="5"
height="14"
viewBox="0 0 5 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M5 0.822266H1V12.8223H5" stroke="url(#brackets-left)" />
<defs>
<linearGradient
id="brackets-left"
x1="50%"
x2="50%"
y1="0%"
y2="100%"
>
<stop offset="0%" stopColor="#89F9E8" />
<stop offset="100%" stopColor="#FACB7B" />
</linearGradient>
</defs>
</svg>
) : (
<svg
width="5"
height="14"
viewBox="0 0 5 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M-2.98023e-08 0.822266H4V12.8223H-2.98023e-08"
stroke="url(#brackets-right)"
/>
<defs>
<linearGradient
id="brackets-right"
x1="14.635%"
x2="14.635%"
y1="0%"
y2="100%"
>
<stop offset="0%" stopColor="#9099FC" />
<stop offset="100%" stopColor="#D87CEE" />
</linearGradient>
</defs>
</svg>
);

View File

@@ -0,0 +1,270 @@
import React from "react";
import {
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalBody,
ModalCloseButton,
Text,
Box,
VStack,
Divider,
useColorModeValue
} from "@chakra-ui/react";
const UserAgreementModal = ({ isOpen, onClose }) => {
const modalBg = useColorModeValue("white", "gray.800");
const headingColor = useColorModeValue("gray.800", "white");
const textColor = useColorModeValue("gray.600", "gray.300");
return (
<Modal
isOpen={isOpen}
onClose={onClose}
size="full"
scrollBehavior="inside"
isCentered
>
<ModalOverlay bg="blackAlpha.600" />
<ModalContent
maxW="95vw"
maxH="95vh"
bg={modalBg}
borderRadius="xl"
boxShadow="2xl"
mx={4}
>
<ModalHeader
fontSize="2xl"
fontWeight="bold"
color={headingColor}
borderBottom="1px solid"
borderColor="gray.200"
borderRadius="xl xl 0 0"
py={6}
>
价值前沿用户协议
</ModalHeader>
<ModalCloseButton
size="lg"
_hover={{ bg: "gray.100" }}
/>
<ModalBody py={8} px={8}>
<VStack spacing={6} align="stretch">
<Box bg="orange.50" p={6} borderRadius="lg" border="1px solid" borderColor="orange.100">
<Text fontSize="xl" fontWeight="bold" color="orange.700" mb={6}>
欢迎你使用价值前沿及服务
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8" mb={5}>
为使用价值前沿以下简称"本软件"及服务你应当阅读并遵守价值前沿用户协议以下简称"本协议"请你务必审慎阅读充分理解各条款内容特别是免除或者限制责任的条款以及开通或使用某项服务的单独协议并选择接受或不接受限制免责条款可能以加粗形式提示你注意
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8" mb={5}>
除非你已阅读并接受本协议所有条款否则你无权下载安装或使用本软件及相关服务你的下载安装使用获取价值前沿帐号登录等行为即视为你已阅读并同意上述协议的约束
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8" fontWeight="medium">
如果你未满18周岁请在法定监护人的陪同下阅读本协议及其他上述协议并特别注意未成年人使用条款
</Text>
</Box>
<Divider />
<Box>
<Text fontSize="xl" fontWeight="bold" color={headingColor} mb={6}>
协议的范围
</Text>
<Box pl={4} borderLeft="3px solid" borderColor="blue.300" bg="blue.50" p={4} borderRadius="md" mb={4}>
<Text fontSize="lg" fontWeight="semibold" color="blue.700" mb={2}>
1.1 协议适用主体范围
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8">
本协议是你与北京价值前沿科技有限公司之间关于你下载安装使用复制本软件以及使用价值前沿相关服务所订立的协议
</Text>
</Box>
<Box pl={4} borderLeft="3px solid" borderColor="green.300" bg="green.50" p={4} borderRadius="md" mb={4}>
<Text fontSize="lg" fontWeight="semibold" color="green.700" mb={2}>
1.2 协议关系及冲突条款
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8">
本协议内容同时包括北京价值前沿科技有限公司可能不断发布的关于本服务的相关协议业务规则等内容上述内容一经正式发布即为本协议不可分割的组成部分你同样应当遵守
</Text>
</Box>
<Box pl={4} borderLeft="3px solid" borderColor="purple.300" bg="purple.50" p={4} borderRadius="md" mb={4}>
<Text fontSize="lg" fontWeight="semibold" color="purple.700" mb={2}>
1.3 许可范围
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8">
明确标识免费产品的用户可以进行自用的非商业性无限制数量地下载安装及使用但不得复制分发其他收费类产品或者信息除遵守本协议规定之外还须遵守专门协议的规定
</Text>
</Box>
<Box pl={4} borderLeft="3px solid" borderColor="red.300" bg="red.50" p={4} borderRadius="md">
<Text fontSize="lg" fontWeight="semibold" color="red.700" mb={2}>
1.4 权利限制
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8">
禁止反向工程反向编译和反向汇编用户不得对价值前沿软件类产品进行反向工程反向编译或反向汇编同时不得改动编译程序文件内部的任何资源除法律法规明文规定允许上述活动外用户必须遵守此协议限制
</Text>
</Box>
</Box>
<Divider />
<Box>
<Text fontSize="lg" fontWeight="bold" color={headingColor} mb={4}>
关于本服务
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8" mb={4}>
本服务内容是指北京价值前沿科技有限公司向用户提供的跨平台的社交资讯工具以下简称"价值前沿"支持单人多人参与在发布图片和文字等内容服务的基础上同时为用户提供包括但不限于社交关系拓展便捷工具等功能或内容的软件服务以下简称"本服务"
</Text>
</Box>
<Divider />
<Box>
<Text fontSize="lg" fontWeight="bold" color={headingColor} mb={4}>
免责条款
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8" mb={4}>
北京价值前沿科技有限公司作为面向全球投资人提供信息和服务的商家对以下情况不承担相关责任
</Text>
<VStack align="stretch" spacing={3}>
<Box pl={4} borderLeft="3px solid" borderColor="yellow.400" bg="yellow.50" p={3} borderRadius="md">
<Text fontSize="lg" fontWeight="semibold" color="yellow.700" mb={2}>
1不可抗力
</Text>
<Text fontSize="md" color={textColor} lineHeight="1.6">
如因发生自然灾害战争第三方侵害等不可控因素而发生的信息服务中断价值前沿不承担相应责任
</Text>
</Box>
<Box pl={4} borderLeft="3px solid" borderColor="yellow.400" bg="yellow.50" p={3} borderRadius="md">
<Text fontSize="lg" fontWeight="semibold" color="yellow.700" mb={2}>
2信息网络传播
</Text>
<Text fontSize="md" color={textColor} lineHeight="1.6">
如因信息网络传播中的拥塞断续病毒木马黑客窃取侦听等网络通道上的因素而造成信息缺失丢失延迟被篡改等价值前沿不对此承担相应责任
</Text>
</Box>
<Box pl={4} borderLeft="3px solid" borderColor="yellow.400" bg="yellow.50" p={3} borderRadius="md">
<Text fontSize="lg" fontWeight="semibold" color="yellow.700" mb={2}>
3第三方信息的收集整理
</Text>
<Text fontSize="md" color={textColor} lineHeight="1.6">
价值前沿为了更好地服务投资者便于用户分析研判投资环境尽可能多地收集整理来自第三方的所有信息分门别类地提供给用户参考并明确标识为来自第三方的信息而对内容的真实性合理性完整性合法性等并不承担判断责任也不承担用户因信息而造成的损失责任
</Text>
</Box>
<Box pl={4} borderLeft="3px solid" borderColor="yellow.400" bg="yellow.50" p={3} borderRadius="md">
<Text fontSize="lg" fontWeight="semibold" color="yellow.700" mb={2}>
4证券信息汇总
</Text>
<Text fontSize="md" color={textColor} lineHeight="1.6">
价值前沿仅提供证券信息汇总及证券投资品种历史数据统计功能不针对用户提供任何情况判断投资参考品种操作建议等等不属于荐股软件用户按照自身对于市场环境的分析研判而做出的评论参考用户可以结合自身需求予以借鉴并自行作出判断风险和收益都由用户自行承担
</Text>
</Box>
<Box pl={4} borderLeft="3px solid" borderColor="yellow.400" bg="yellow.50" p={3} borderRadius="md">
<Text fontSize="lg" fontWeight="semibold" color="yellow.700" mb={2}>
5信息储存
</Text>
<Text fontSize="md" color={textColor} lineHeight="1.6">
用户在使用价值前沿系统时会因信息注册产品购买软件使用过程中的某些需求而留存于系统中的账户密码真实身份联系方式用户网络信息等个人信息价值前沿将按照国家相关规定进行必要的保护
</Text>
</Box>
</VStack>
</Box>
<Divider />
<Box>
<Text fontSize="lg" fontWeight="bold" color={headingColor} mb={4}>
用户个人信息保护
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8" mb={4}>
保护用户个人信息是北京价值前沿科技有限公司的一项基本原则北京价值前沿科技有限公司将会采取合理的措施保护用户的个人信息除法律法规规定的情形外未经用户许可北京价值前沿科技有限公司不会向第三方公开透露用户个人信息
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8" mb={4}>
你在注册帐号或使用本服务的过程中需要提供一些必要的信息例如为向你提供帐号注册服务或进行用户身份识别需要你填写手机号码手机通讯录匹配功能需要你授权访问手机通讯录等若国家法律法规或政策有特殊规定的你需要提供真实的身份信息
</Text>
</Box>
<Divider />
<Box>
<Text fontSize="lg" fontWeight="bold" color={headingColor} mb={4}>
用户行为规范
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8" mb={4}>
你理解并同意价值前沿一直致力于为用户提供文明健康规范有序的网络环境你不得利用价值前沿帐号或本软件及服务制作复制发布传播干扰正常运营以及侵犯其他用户或第三方合法权益的内容
</Text>
<Box pl={4} borderLeft="3px solid" borderColor="red.400" bg="red.50" p={4} borderRadius="md">
<Text fontSize="lg" fontWeight="semibold" color="red.700" mb={2}>
禁止内容包括但不限于
</Text>
<VStack align="start" spacing={1} pl={4}>
<Text fontSize="md" color={textColor}> 违反宪法确定的基本原则的内容</Text>
<Text fontSize="md" color={textColor}> 危害国家安全泄露国家秘密的内容</Text>
<Text fontSize="md" color={textColor}> 损害国家荣誉和利益的内容</Text>
<Text fontSize="md" color={textColor}> 散布谣言扰乱社会秩序的内容</Text>
<Text fontSize="md" color={textColor}> 散布淫秽色情赌博暴力恐怖的内容</Text>
<Text fontSize="md" color={textColor}> 侮辱或者诽谤他人侵害他人合法权益的内容</Text>
<Text fontSize="md" color={textColor}> 其他违反法律法规的内容</Text>
</VStack>
</Box>
</Box>
<Divider />
<Box>
<Text fontSize="lg" fontWeight="bold" color={headingColor} mb={4}>
知识产权声明
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8" mb={4}>
北京价值前沿科技有限公司是本软件的知识产权权利人本软件的一切著作权商标权专利权商业秘密等知识产权以及与本软件相关的所有信息内容包括但不限于文字图片音频视频图表界面设计版面框架有关数据或电子文档等均受中华人民共和国法律法规和相应的国际条约保护
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8" mb={4}>
未经北京价值前沿科技有限公司或相关权利人书面同意你不得为任何商业或非商业目的自行或许可任何第三方实施利用转让上述知识产权
</Text>
</Box>
<Divider />
<Box>
<Text fontSize="lg" fontWeight="bold" color={headingColor} mb={4}>
其他条款
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8" mb={4}>
你使用本软件即视为你已阅读并同意受本协议的约束北京价值前沿科技有限公司有权在必要时修改本协议条款你可以在本软件的最新版本中查阅相关协议条款
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8" mb={4}>
本协议签订地为中华人民共和国北京市海淀区本协议的成立生效履行解释及纠纷解决适用中华人民共和国大陆地区法律不包括冲突法
</Text>
<Text fontSize="lg" color={textColor} lineHeight="1.8">
若你和北京价值前沿科技有限公司之间发生任何纠纷或争议首先应友好协商解决协商不成的你同意将纠纷或争议提交本协议签订地有管辖权的人民法院管辖
</Text>
</Box>
</VStack>
</ModalBody>
</ModalContent>
</Modal>
);
};
export default UserAgreementModal;

View File

@@ -0,0 +1,55 @@
import { useState } from "react";
import { Pie } from "@visx/shape";
import { Group } from "@visx/group";
import { Text } from "@visx/text";
import { useColorModeValue } from "@chakra-ui/react";
const VisxPieChart = ({ data, title, width }) => {
const [active, setActive] = useState(null);
const half = width / 2;
const textColor = useColorModeValue("gray.700", "white");
return (
<svg width={width} height={width}>
<Group top={half} left={half}>
<Pie
data={data}
pieValue={(data) => data.percentage}
outerRadius={half}
innerRadius={({ data }) => {
const size = active && active.name == data.name ? 12 : 8;
return half - size;
}}
padAngle={0.01}
>
{(pie) => {
return pie.arcs.map((arc) => {
return (
<g
key={arc.data.name}
onMouseEnter={() => setActive(arc.data)}
onMouseLeave={() => setActive(null)}
>
<path d={pie.path(arc)} fill={arc.data.color}></path>
</g>
);
});
}}
</Pie>
<>
<Text textAnchor="middle" fill={textColor} fontWeight="bold" fontSize={32} dy={20}>
{title}
</Text>
</>
</Group>
</svg>
);
};
export default VisxPieChart;