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