Initial commit
This commit is contained in:
40
src/components/Arrows/index.tsx
Normal file
40
src/components/Arrows/index.tsx
Normal 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;
|
||||
40
src/components/Button/index.tsx
Normal file
40
src/components/Button/index.tsx
Normal 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;
|
||||
58
src/components/Button/svgs.tsx
Normal file
58
src/components/Button/svgs.tsx
Normal 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>
|
||||
</>
|
||||
);
|
||||
52
src/components/Calendars/EventCalendar.js
Normal file
52
src/components/Calendars/EventCalendar.js
Normal 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;
|
||||
29
src/components/Card/Card.js
Normal file
29
src/components/Card/Card.js
Normal 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;
|
||||
29
src/components/Card/CardBody.js
Normal file
29
src/components/Card/CardBody.js
Normal 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;
|
||||
29
src/components/Card/CardHeader.js
Normal file
29
src/components/Card/CardHeader.js
Normal 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;
|
||||
50
src/components/Charts/BarChart.js
Normal file
50
src/components/Charts/BarChart.js
Normal 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;
|
||||
50
src/components/Charts/BubbleChart.js
Normal file
50
src/components/Charts/BubbleChart.js
Normal 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;
|
||||
51
src/components/Charts/DonutChart.js
Normal file
51
src/components/Charts/DonutChart.js
Normal 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;
|
||||
50
src/components/Charts/LineBarChart.js
Normal file
50
src/components/Charts/LineBarChart.js
Normal 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;
|
||||
51
src/components/Charts/LineChart.js
Normal file
51
src/components/Charts/LineChart.js
Normal 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;
|
||||
51
src/components/Charts/PieChart.js
Normal file
51
src/components/Charts/PieChart.js
Normal 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;
|
||||
51
src/components/Charts/PolarChart.js
Normal file
51
src/components/Charts/PolarChart.js
Normal 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;
|
||||
51
src/components/Charts/RadarChart.js
Normal file
51
src/components/Charts/RadarChart.js
Normal 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;
|
||||
202
src/components/Configurator/Configurator.js
Normal file
202
src/components/Configurator/Configurator.js
Normal 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,
|
||||
};
|
||||
139
src/components/Editor/Editor.js
Normal file
139
src/components/Editor/Editor.js
Normal 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',
|
||||
];
|
||||
80
src/components/ErrorBoundary.js
Normal file
80
src/components/ErrorBoundary.js
Normal 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
|
||||
63
src/components/FixedPlugin/FixedPlugin.js
Normal file
63
src/components/FixedPlugin/FixedPlugin.js
Normal 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,
|
||||
};
|
||||
127
src/components/Footer/Footer.js
Normal file
127
src/components/Footer/Footer.js
Normal 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" }}>
|
||||
© {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>
|
||||
);
|
||||
}
|
||||
52
src/components/Footer/index.js
Normal file
52
src/components/Footer/index.js
Normal 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;
|
||||
20
src/components/Generating/index.tsx
Normal file
20
src/components/Generating/index.tsx
Normal 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;
|
||||
125
src/components/Header/index.js
Normal file
125
src/components/Header/index.js
Normal 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;
|
||||
32
src/components/Heading/index.js
Normal file
32
src/components/Heading/index.js
Normal 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;
|
||||
34
src/components/Icons/IconBox.js
Normal file
34
src/components/Icons/IconBox.js
Normal 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>
|
||||
);
|
||||
}
|
||||
736
src/components/Icons/Icons.js
Normal file
736
src/components/Icons/Icons.js
Normal 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>
|
||||
),
|
||||
});
|
||||
17
src/components/Image/index.tsx
Normal file
17
src/components/Image/index.tsx
Normal 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;
|
||||
73
src/components/Join/index.tsx
Normal file
73
src/components/Join/index.tsx
Normal 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;
|
||||
12
src/components/Layout/MainPanel.js
Normal file
12
src/components/Layout/MainPanel.js
Normal 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;
|
||||
12
src/components/Layout/PanelContainer.js
Normal file
12
src/components/Layout/PanelContainer.js
Normal 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;
|
||||
29
src/components/Layout/PanelContent.js
Normal file
29
src/components/Layout/PanelContent.js
Normal 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;
|
||||
12
src/components/Layout/index.js
Normal file
12
src/components/Layout/index.js
Normal 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;
|
||||
16
src/components/Logo/index.js
Normal file
16
src/components/Logo/index.js
Normal 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;
|
||||
53
src/components/Logos/index.tsx
Normal file
53
src/components/Logos/index.tsx
Normal 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;
|
||||
3
src/components/Map/Map.css
Normal file
3
src/components/Map/Map.css
Normal file
@@ -0,0 +1,3 @@
|
||||
.leaflet-container {
|
||||
height: 300px;
|
||||
}
|
||||
28
src/components/Map/Map.js
Normal file
28
src/components/Map/Map.js
Normal 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='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
/>
|
||||
</MapContainer>
|
||||
)
|
||||
}
|
||||
|
||||
export default Map;
|
||||
52
src/components/Menu/ItemContent.js
Normal file
52
src/components/Menu/ItemContent.js
Normal 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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
222
src/components/Navbars/AdminNavbar.js
Normal file
222
src/components/Navbars/AdminNavbar.js
Normal 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,
|
||||
};
|
||||
253
src/components/Navbars/AdminNavbarLinks.js
Normal file
253
src/components/Navbars/AdminNavbarLinks.js
Normal 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,
|
||||
};
|
||||
675
src/components/Navbars/AuthNavbar.js
Normal file
675
src/components/Navbars/AuthNavbar.js
Normal 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,
|
||||
};
|
||||
1041
src/components/Navbars/HomeNavbar.js
Normal file
1041
src/components/Navbars/HomeNavbar.js
Normal file
File diff suppressed because it is too large
Load Diff
45
src/components/Navbars/SearchBar/SearchBar.js
Normal file
45
src/components/Navbars/SearchBar/SearchBar.js
Normal 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>
|
||||
);
|
||||
}
|
||||
71
src/components/Navbars/Settings/SettingsBar.js
Normal file
71
src/components/Navbars/Settings/SettingsBar.js
Normal 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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
49
src/components/Notification/index.tsx
Normal file
49
src/components/Notification/index.tsx
Normal 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;
|
||||
91
src/components/PinInput/PinInput.js
Normal file
91
src/components/PinInput/PinInput.js
Normal 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_@./#&+-]*$/}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
138
src/components/PricingList/index.tsx
Normal file
138
src/components/PricingList/index.tsx
Normal 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;
|
||||
272
src/components/PrivacyPolicyModal.js
Normal file
272
src/components/PrivacyPolicyModal.js
Normal 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 35273—2020),个人信息是指以电子或者其他方式记录的能够单独或者与其他信息结合识别特定自然人身份或者反映特定自然人活动情况的各种信息。本隐私政策中涉及的个人信息包括:基本信息(包括性别、地址、地区、个人电话号码、电子邮箱);个人身份信息(包括身份证、护照、相关身份证明等);网络身份标识信息(包括系统账号、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">
|
||||
【QQ】QQ互联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;
|
||||
41
src/components/ProtectedRoute.js
Normal file
41
src/components/ProtectedRoute.js
Normal 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;
|
||||
30
src/components/RTLProvider/RTLProvider.js
Normal file
30
src/components/RTLProvider/RTLProvider.js
Normal 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} />;
|
||||
}
|
||||
108
src/components/Scrollbar/Scrollbar.js
Normal file
108
src/components/Scrollbar/Scrollbar.js
Normal 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} />;
|
||||
};
|
||||
57
src/components/Section/index.tsx
Normal file
57
src/components/Section/index.tsx
Normal 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;
|
||||
42
src/components/Separator/Separator.js
Normal file
42
src/components/Separator/Separator.js
Normal 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>
|
||||
);
|
||||
}
|
||||
195
src/components/Services/index.tsx
Normal file
195
src/components/Services/index.tsx
Normal 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 world’s 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;
|
||||
719
src/components/Sidebar/Sidebar.js
Normal file
719
src/components/Sidebar/Sidebar.js
Normal 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;
|
||||
45
src/components/Sidebar/SidebarDocs.js
Normal file
45
src/components/Sidebar/SidebarDocs.js
Normal 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>
|
||||
);
|
||||
}
|
||||
552
src/components/StockChart/StockChartAntdModal.js
Normal file
552
src/components/StockChart/StockChartAntdModal.js
Normal 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;
|
||||
550
src/components/StockChart/StockChartModal.js
Normal file
550
src/components/StockChart/StockChartModal.js
Normal 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;
|
||||
175
src/components/SubscriptionUpgradeModal.js
Normal file
175
src/components/SubscriptionUpgradeModal.js
Normal 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;
|
||||
288
src/components/Tables/BasicTable.js
Normal file
288
src/components/Tables/BasicTable.js
Normal 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;
|
||||
93
src/components/Tables/BillingRow.js
Normal file
93
src/components/Tables/BillingRow.js
Normal 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;
|
||||
89
src/components/Tables/DashboardTableRow.js
Normal file
89
src/components/Tables/DashboardTableRow.js
Normal 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;
|
||||
61
src/components/Tables/InvoicesRow.js
Normal file
61
src/components/Tables/InvoicesRow.js
Normal 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;
|
||||
312
src/components/Tables/SearchTable1.js
Normal file
312
src/components/Tables/SearchTable1.js
Normal 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;
|
||||
360
src/components/Tables/SearchTable2.js
Normal file
360
src/components/Tables/SearchTable2.js
Normal 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;
|
||||
84
src/components/Tables/TablesProjectRow.js
Normal file
84
src/components/Tables/TablesProjectRow.js
Normal 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;
|
||||
171
src/components/Tables/TablesReportsRow.js
Normal file
171
src/components/Tables/TablesReportsRow.js
Normal 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;
|
||||
120
src/components/Tables/TablesTableRow.js
Normal file
120
src/components/Tables/TablesTableRow.js
Normal 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;
|
||||
132
src/components/Tables/TimelineRow.js
Normal file
132
src/components/Tables/TimelineRow.js
Normal 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;
|
||||
81
src/components/Tables/TransactionRow.js
Normal file
81
src/components/Tables/TransactionRow.js
Normal 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;
|
||||
11
src/components/Tagline/index.js
Normal file
11
src/components/Tagline/index.js
Normal 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;
|
||||
49
src/components/Tagline/svgs.js
Normal file
49
src/components/Tagline/svgs.js
Normal 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>
|
||||
);
|
||||
49
src/components/Tagline/svgs.tsx
Normal file
49
src/components/Tagline/svgs.tsx
Normal 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>
|
||||
);
|
||||
270
src/components/UserAgreementModal.js
Normal file
270
src/components/UserAgreementModal.js
Normal 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;
|
||||
55
src/components/VisxPieChart/VisxPieChart.js
Normal file
55
src/components/VisxPieChart/VisxPieChart.js
Normal 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;
|
||||
Reference in New Issue
Block a user