tailwind+react组件实现销售后台仪表盘效果代码
代码语言:html
所属分类:布局界面
代码描述:tailwind+react组件实现销售后台仪表盘效果代码
代码标签: tailwind react 组件 销售 后台 仪表盘
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<style>
.half-circle-pie {
display: block;
width: 100%;
max-width: 30rem;
height: auto;
}
.icon {
display: block;
width: 1em;
height: 1em;
}
</style>
</head>
<body class="bg-gray-200 text-black dark:bg-gray-900 dark:text-white transition-colors duration-300">
<div id="root"></div>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/babel.7.18.13.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/react.production.18.2.0.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/react-dom.production.18.2.0.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/tailwindcss.3.4.16.js"></script>
<script type="text/babel">
const { useEffect, useRef, useState,StrictMode} = window.React;
const { createRoot } = window.ReactDOM;
class Formatter {
static LOCALE = "en-US";
static CURRENCY = "USD";
static count(value) {
return new Intl.NumberFormat(this.LOCALE).format(value);
}
static currency(value) {
return new Intl.NumberFormat(this.LOCALE, {
currency: this.CURRENCY,
style: "currency",
notation: "compact",
maximumFractionDigits: 1
}).format(value);
}
static percent(value) {
return new Intl.NumberFormat(this.LOCALE, {
maximumFractionDigits: 1,
style: "percent"
}).format(value);
}
static date(date) {
return new Intl.DateTimeFormat(this.LOCALE, {
dateStyle: "short"
}).format(date);
}
}
class Random {
static random() {
return crypto.getRandomValues(new Uint32Array(1))[0] / 2**32;
}
static float(min, max) {
return (this.random() * (max - min)) + min;
}
static hash() {
return Math.round(this.float(0,1) * 0xffff).toString(16);
}
static int(min, max) {
return Math.floor(this.random() * (max - min)) + min;
}
}
function fakeData() {
const data = {
overview: {
top: Random.int(1,15) / 100,
sales_goals: 0.672,
number_of_sales: 2608,
change: 0.035,
total_sales: 42200,
total_change: -0.045
},
users: [
{
name: "Jack O. Lantern",
avatar: "https://assets.codepen.io/416221/photo-avatar1.jpg"
},
{
name: "Jane Doe",
avatar: "https://assets.codepen.io/416221/photo-avatar2.jpg"
},
{
name: "Joe Schmoe",
avatar: "https://assets.codepen.io/416221/photo-avatar3.jpg"
}
],
performance: {
history: []
},
convert_rate: 0.375,
customer_calls: [
{
name: "Ann Thrax",
vip: true,
source: "TikTok Leads"
}
],
sales_target: {
target: 42200,
streams: [
{
change: -0.2,
revenue: 6800,
source: "Instagram"
},
{
change: -0.45,
revenue: 8200,
source: "Facebook"
},
{
change: 0.7,
revenue: 15400,
source: "TikTok"
},
{
change: -0.5,
revenue: 11800,
source: "Other"
}
]
}
};
const historyPercents = [0.8,0.2,0.5,0.2,0.9,0.3,0.55,0.3,0.15,0.8,0.35,0.3,0.4,0.2,0.85,0.25,0.852];
historyPercents.forEach((percent, i) => {
const date = new Date();
date.setDate(date.getDate() - (historyPercents.length - (i + 1)));
data.performance.history.push({date, percent});
});
return data;
}
createRoot(document.getElementById("root")).render(
<StrictMode>
<IconSprites />
<Dashboard data={fakeData()} />
</StrictMode>
);
function ActionBar({ users }) {
const newestUsers = users.slice(0,3);
return (
<div className="flex flex-col sm:flex-row justify-between gap-x-1 gap-y-3 mb-6">
<div className="flex gap-1 items-center">
{newestUsers.map((user, i) => (
<Avatar key={i} {...user} indentStart={i > 0} />
))}
<Button color="black" icon="plus">Invite</Button>
</div>
<div className="flex gap-1 items-center">
<Button icon="calendar" shape="square" title="Calendar" />
<div className="sm:hidden">
<Button icon="arrow-down" shape="square" title="Download Report" />
</div>
<div className="hidden sm:block">
<Button icon="arrow-down">Download Report</Button>
</div>
<div className="sm:hidden">
<Button color="red" icon="microphone" shape="square" title="AI Assistant" />
</div>
<div className="hidden sm:block">
<Button color="red" icon="microphone">AI Assistant</Button>
</div>
</div>
</div>
);
}
function Avatar({ name, avatar, indentStart }) {
return (
<div className={`bg-gray-400 dark:bg-gray-700 border border-white dark:border-gray-800 rounded-full overflow-hidden w-12 h-12${indentStart ? ' -ms-8' : ''} transition-colors duration-300`}>
<img className="block w-full h-auto" src={avatar} width="40" height="40" alt={name} title={name} />
</div>
);
}
function Button({ children, title, color, icon, shape = "regular", outline, clickEvent }) {
const buttonFills = {
default: "bg-white hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 ",
outline: "hover:bg-gray-100 dark:hover:bg-gray-700 ",
black: "bg-black hover:bg-gray-900 dark:bg-white dark:hover:bg-gray-100 ",
red: "bg-red-600 hover:bg-red-700 "
};
const buttonTexts = {
default: "text-black dark:text-white ",
black: "text-white dark:text-black ",
white: "text-white ",
red: "text-red-600 hover:text-red-700 dark:hover:text-red-500 "
};
const buttonOutlines = {
default: "border-2 border-gray-200 hover:border-gray-300 dark:border-gray-600 dark:hover:border-gray-500 ",
red: "border-2 border-red-600 hover:border-red-700 dark:hover:border-red-500 "
};
const buttonShapes = {
regular: "px-5 py-3 min-w-12 ",
square: "flex-shrink-0 w-12 ",
wide: "py-3 w-full "
};
let buttonFill = buttonFills["default"];
let buttonText = buttonTexts["default"];
let buttonOutline = "";
const buttonShape = buttonShapes[shape];
if (color === "black") {
buttonFill = buttonFills[color];
buttonText = buttonTexts[color];
} else if (color && outline) {
buttonFill = buttonFills["outline"];
buttonText = buttonTexts[color];
buttonOutline = buttonOutlines[color];
} else if (color) {
buttonFill = buttonFills[color];
buttonText = buttonTexts["white"];
} else if (outline) {
buttonOutline = buttonOutlines["default"];
}
return (
<button className={`${buttonFill}${buttonText}${buttonOutline}focus:outline-none focus-visible:ring rounded-full font-light flex justify-center items-center gap-2 ${buttonShape}h-12 transition-colors duration-300`} type="button" title={title} onClick={() => clickEvent?.()}>
{icon ? <Icon icon={icon} /> : ""}
{children}
</button>
);
}
function ConvertRate({ percent }) {
const circumference = 34.56;
const offset = 34.56 * (1 - percent);
const dots = 16;
const dotAngle = +(360 / dots).toFixed(2);
const angles = [];
for (let d = 0; d < dots; ++d) {
angles.push(dotAngle * d);
}
return (
<div className="col-span-6 sm:col-span-2 lg:col-span-2 lg:row-span-2">
<div className="bg-black dark:bg-white aspect-square rounded-full text-white dark:text-black relative m-auto max-h-64 sm:max-h-none transition-colors duration-300">
<svg className="m-auto w-full h-auto rtl:-scale-x-100" viewBox="0 0 16 16" width="160px" height="160px" role="img" aria-label={`Ring chart showing a ${Formatter.percent(percent)} fill over a circle made of 16 dots`}>
<g fill="currentcolor" transform="translate(8,8)".........完整代码请登录后点击上方下载按钮下载查看
网友评论0