Fusion UI LogoFusion UI Logo
Fusion UI LogoFusion UI Logo
/
Getting Started
Concepts
Components
Example Apps
Getting Started
Concepts
Components
Example Apps
Fusion UI LogoFusion UI Logo
Getting Started
Concepts
Components
Example Apps
Overview
Example Apps
Analytics Dashboard
Customer Management
Account Settings
Support Inbox
Subscription Checkout

Analytics Dashboard

Key figures, charts and the latest orders of a shop at a glance.

Preview

/preview/analytics-dashboard

File: app.tsx

"use client";
import React, {useMemo, useState} from "react";
import {
AccountMenu,
BarChart,
Button,
ColumnConfig,
CommandMenuTrigger,
Container,
DataTable,
FlowLayout,
IconDashboard,
IconDownload,
IconFileList,
IconShoppingBag,
IconTeam,
KPICard,
LineChart,
MainNavResponsive,
MainNavView,
PageHeaderView,
PieChart,
RatioCard,
SideMenuItem,
SideMenuSection,
SideMenuView,
StackLayout,
Status,
StatusStyle,
Tabs,
Tile,
TileContent,
TileHeader,
useSimpleTable,
} from "@brynlabs/fusion-ui";
import {categories, channels, kpis, Order, orders, Period, periods, revenue} from "./data";
import {tableText} from "../shared/table-text";
const statusStyles: Record<Order["status"], StatusStyle> = {
Paid: "info",
Shipped: "success",
Pending: "warn",
Refunded: "neutral",
};
const currency = (value: number) =>
value.toLocaleString("en", {style: "currency", currency: "EUR"});
const LatestOrders = () => {
const options = useMemo(() => {
const columns: ColumnConfig<Order>[] = [
{key: "id", label: "Order", render: order => order.id, initialWidth: 100},
{key: "customer", label: "Customer", render: order => order.customer},
{key: "date", label: "Date", render: order => order.date, initialWidth: 120},
{
key: "total",
label: "Total",
render: order => currency(order.total),
sortFunction: (a, b) => a.total - b.total,
initialWidth: 120,
},
{
key: "status",
label: "Status",
render: order => <Status status={order.status} statusStyle={statusStyles[order.status]} />,
filter: {type: "multiSelect", getValue: order => order.status},
initialWidth: 130,
},
];
return {
columns,
initialColumns: columns.map(column => column.key),
searchIndexRow: (order: Order) => [order.id, order.customer],
};
}, []);
const table = useSimpleTable<Order>(orders, options);
return (
<div style={{height: "460px"}}>
<DataTable<Order> {...table} hasCheckboxes={false} modalText={tableText} />
</div>
);
};
export const AnalyticsDashboardApp = () => {
const [period, setPeriod] = useState<Period>("Week");
const figures = kpis[period];
return (
<MainNavView
logo={<span className={"heading-4-font"}>Shopboard</span>}
menuItems={[
{title: "Analytics", href: "/preview/analytics-dashboard"},
{title: "Products", href: "#products"},
{title: "Customers", href: "#customers"},
]}
pinnedActions={
<MainNavResponsive full={<CommandMenuTrigger />} compact={<CommandMenuTrigger compact />} />
}
accountMenu={<AccountMenu name={"Jane Doe"} email={"jane@shopboard.example"} />}>
<SideMenuView
menuItems={
<SideMenuSection sectionTitle={"Analytics"}>
<SideMenuItem
menuItem={{
title: "Overview",
href: "/preview/analytics-dashboard",
icon: <IconDashboard />,
}}
/>
<SideMenuItem
menuItem={{title: "Orders", href: "#orders", icon: <IconShoppingBag />}}
/>
<SideMenuItem menuItem={{title: "Audience", href: "#audience", icon: <IconTeam />}} />
<SideMenuItem menuItem={{title: "Reports", href: "#reports", icon: <IconFileList />}} />
</SideMenuSection>
}>
<PageHeaderView
pageHeaderTitle={"Overview"}
subtitle={"All sales channels"}
buttons={
<Button size={"small"} color={"neutral"} primaryIcon={<IconDownload />}>
Export
</Button>
}
tabs={
<Tabs
tabs={periods.map(label => ({label}))}
activeIndex={periods.indexOf(period)}
onChange={index => setPeriod(periods[index] ?? "Week")}
/>
}>
<Container direction={"both"}>
<StackLayout>
<FlowLayout>
<KPICard
elevated
data={{
type: "number",
name: "Revenue (€)",
value: figures.revenue,
previousValue: figures.previousRevenue,
previousValueType: "percent",
}}
/>
<KPICard
elevated
data={{
type: "number",
name: "Orders",
value: figures.orders,
previousValue: figures.previousOrders,
previousValueType: "percent",
}}
/>
<KPICard
elevated
data={{
type: "number",
name: "Average order (€)",
value: Math.round(figures.revenue / figures.orders),
previousValue: Math.round(figures.previousRevenue / figures.previousOrders),
previousValueType: "number",
}}
/>
</FlowLayout>
<Tile>
<TileHeader>Revenue by channel</TileHeader>
<TileContent>
<LineChart data={revenue[period]} />
</TileContent>
</Tile>
<FlowLayout>
<Tile>
<TileHeader>Top categories</TileHeader>
<TileContent>
<BarChart data={categories} />
</TileContent>
</Tile>
<Tile>
<TileHeader>Traffic sources</TileHeader>
<TileContent>
<PieChart data={channels} chartTitle={"Visits"} total={"12.4k"} />
</TileContent>
</Tile>
</FlowLayout>
<Tile>
<TileContent>
<RatioCard
data={{
name: "Deliveries",
title: "Mostly on time",
showKPIs: true,
colors: "spectrum",
marker: {label: "Goal", percent: 90},
data: [
{value: 368, name: "On time"},
{value: 31, name: "Late"},
{value: 13, name: "Lost"},
],
}}
/>
</TileContent>
</Tile>
<Tile>
<TileHeader>Latest orders</TileHeader>
<TileContent>
<LatestOrders />
</TileContent>
</Tile>
</StackLayout>
</Container>
</PageHeaderView>
</SideMenuView>
</MainNavView>
);
};

What it shows

  • MainNavView, SideMenuView and PageHeaderView stacked as an application shell
  • KPI and ratio cards in a responsive flow layout
  • Line, bar and pie charts in tiles with tabs to switch the period
  • A data table with status chips for the latest orders

Components used

Read more about each component and when to use it.

Main NavSide MenuPage HeaderTabsKPI CardRatio CardLine ChartBar ChartPie ChartTileData TableStatusFlow Layout
On this page
  • Preview
  • What it shows
  • Components used