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