Standardize card sizing and spacing

This commit is contained in:
2025-01-02 15:36:06 -05:00
parent a59d0e985f
commit 74fb67db18
5 changed files with 75 additions and 66 deletions

View File

@@ -118,7 +118,7 @@ const SmallLayout = () => {
</div> </div>
{/* Mini Realtime Analytics */} {/* Mini Realtime Analytics */}
<div> <div className="-mt-1">
<div style={{ <div style={{
transform: `scale(${ANALYTICS_SCALE})`, transform: `scale(${ANALYTICS_SCALE})`,
transformOrigin: 'top left', transformOrigin: 'top left',

View File

@@ -78,13 +78,13 @@ const MiniRealtimeAnalytics = () => {
if (loading && !basicData) { if (loading && !basicData) {
return ( return (
<Card className="w-full bg-gradient-to-br from-purple-900 to-purple-800 backdrop-blur-sm h-full"> <Card className="w-full bg-gradient-to-br from-sky-900 to-sky-800 backdrop-blur-sm h-full">
<CardHeader className="p-4 pb-2"> <CardHeader className="p-4 pb-2">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<CardTitle className="text-lg font-bold text-purple-100"> <CardTitle className="text-lg font-bold text-sky-100">
Real-Time Analytics Real-Time Analytics
</CardTitle> </CardTitle>
<Skeleton className="h-4 w-32 bg-purple-700" /> <Skeleton className="h-4 w-32 bg-sky-700" />
</div> </div>
</CardHeader> </CardHeader>
@@ -108,7 +108,7 @@ const MiniRealtimeAnalytics = () => {
</Alert> </Alert>
)} )}
<div className="grid grid-cols-2 gap-2 mt-1 mb-3"> <div className="grid grid-cols-2 gap-2 mt-1 mb-2">
{summaryCard( {summaryCard(
"Last 30 minutes", "Last 30 minutes",
"Active users", "Active users",
@@ -117,7 +117,7 @@ const MiniRealtimeAnalytics = () => {
colorClass: "text-sky-200", colorClass: "text-sky-200",
titleClass: "text-sky-100 font-bold text-md", titleClass: "text-sky-100 font-bold text-md",
descriptionClass: "text-sky-200 text-md font-semibold", descriptionClass: "text-sky-200 text-md font-semibold",
background: "bg-gradient-to-br from-sky-800 to-sky-700", background: "h-[150px] bg-gradient-to-br from-sky-900 to-sky-800",
icon: Users, icon: Users,
iconColor: "text-sky-900", iconColor: "text-sky-900",
iconBackground: "bg-sky-300" iconBackground: "bg-sky-300"
@@ -131,7 +131,7 @@ const MiniRealtimeAnalytics = () => {
colorClass: "text-sky-200", colorClass: "text-sky-200",
titleClass: "text-sky-100 font-bold text-md", titleClass: "text-sky-100 font-bold text-md",
descriptionClass: "text-sky-200 text-md font-semibold", descriptionClass: "text-sky-200 text-md font-semibold",
background: "bg-gradient-to-br from-sky-800 to-sky-700", background: "h-[150px] bg-gradient-to-br from-sky-900 to-sky-800",
icon: Activity, icon: Activity,
iconColor: "text-sky-900", iconColor: "text-sky-900",
iconBackground: "bg-sky-300" iconBackground: "bg-sky-300"
@@ -139,53 +139,55 @@ const MiniRealtimeAnalytics = () => {
)} )}
</div> </div>
<div className="bg-gradient-to-br from-sky-800 to-sky-700 rounded-lg p-2 h-[200px]"> <Card className="bg-gradient-to-br from-sky-900 to-sky-800 backdrop-blur-sm">
<ResponsiveContainer width="100%" height="100%"> <CardContent className="p-4">
<BarChart <div className="h-[200px]">
data={basicData.byMinute} <ResponsiveContainer width="100%" height="100%">
margin={{ top: 5, right: 5, left: -35, bottom: -5 }} <BarChart
> data={basicData.byMinute}
<XAxis margin={{ top: 5, right: 5, left: -35, bottom: -10 }}
dataKey="minute" >
tickFormatter={(value) => value + "m"} <XAxis
className="text-xs" dataKey="minute"
tick={{ fill: "#BAE6FD" }} tickFormatter={(value) => value + "m"}
/> className="text-xs"
<YAxis tick={{ fill: "#BAE6FD" }}
className="text-xs" />
tick={{ fill: "#BAE6FD" }} <YAxis
/> className="text-xs"
<Tooltip tick={{ fill: "#BAE6FD" }}
content={({ active, payload }) => { />
if (active && payload && payload.length) { <Tooltip
const timestamp = new Date( content={({ active, payload }) => {
Date.now() + payload[0].payload.minute * 60000 if (active && payload && payload.length) {
); const timestamp = new Date(payload[0].payload.timestamp);
return ( return (
<Card className="p-2 shadow-lg bg-sky-800 border-none"> <Card className="p-2 shadow-lg bg-sky-800 border-none">
<CardContent className="p-0 space-y-1"> <CardContent className="p-0 space-y-1">
<p className="font-medium text-sm text-sky-100 border-b border-sky-700 pb-1 mb-1"> <p className="font-medium text-sm text-sky-100 border-b border-sky-700 pb-1 mb-1">
{format(timestamp, "h:mm a")} {format(timestamp, "h:mm a")}
</p> </p>
<div className="flex justify-between items-center text-sm"> <div className="flex justify-between items-center text-sm">
<span className="text-sky-200"> <span className="text-sky-200">
Active Users: Active Users:
</span> </span>
<span className="font-medium ml-4 text-sky-100"> <span className="font-medium ml-4 text-sky-100">
{payload[0].value.toLocaleString()} {payload[0].value}
</span> </span>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
); );
} }
return null; return null;
}} }}
/> />
<Bar dataKey="users" fill="#0EA5E9" /> <Bar dataKey="users" fill="#0EA5E9" />
</BarChart> </BarChart>
</ResponsiveContainer> </ResponsiveContainer>
</div> </div>
</CardContent>
</Card>
</div> </div>
); );
}; };

View File

@@ -72,7 +72,7 @@ const MiniStatCard = memo(({
active = true active = true
}) => ( }) => (
<Card <Card
className={`w-full ${background || 'bg-gradient-to-br from-gray-800 to-gray-900 backdrop-blur-md'} ${ className={`w-full ${background || 'bg-gradient-to-br from-gray-900 to-gray-800 backdrop-blur-md'} ${
onClick ? 'cursor-pointer transition-all hover:brightness-110' : '' onClick ? 'cursor-pointer transition-all hover:brightness-110' : ''
} ${!active ? 'opacity-50' : ''}`} } ${!active ? 'opacity-50' : ''}`}
onClick={onClick} onClick={onClick}
@@ -243,7 +243,7 @@ const MiniSalesChart = ({ className = "" }) => {
icon={PiggyBank} icon={PiggyBank}
iconColor="text-emerald-900" iconColor="text-emerald-900"
iconBackground="bg-emerald-300" iconBackground="bg-emerald-300"
background="bg-gradient-to-br from-emerald-900 to-emerald-800" background="h-[150px] bg-gradient-to-br from-emerald-900 to-emerald-800"
onClick={() => toggleMetric('revenue')} onClick={() => toggleMetric('revenue')}
active={visibleMetrics.revenue} active={visibleMetrics.revenue}
/> />
@@ -257,7 +257,7 @@ const MiniSalesChart = ({ className = "" }) => {
icon={Truck} icon={Truck}
iconColor="text-blue-900" iconColor="text-blue-900"
iconBackground="bg-blue-300" iconBackground="bg-blue-300"
background="bg-gradient-to-br from-blue-900 to-blue-800" background="h-[150px] bg-gradient-to-br from-blue-900 to-blue-800"
onClick={() => toggleMetric('orders')} onClick={() => toggleMetric('orders')}
active={visibleMetrics.orders} active={visibleMetrics.orders}
/> />
@@ -305,7 +305,6 @@ const MiniSalesChart = ({ className = "" }) => {
<YAxis <YAxis
yAxisId="orders" yAxisId="orders"
orientation="right" orientation="right"
tickFormatter={(value) => value.toLocaleString()}
className="text-[10px]" className="text-[10px]"
tick={{ fill: "#E9D5FF" }} tick={{ fill: "#E9D5FF" }}
/> />

View File

@@ -410,7 +410,7 @@ const MiniStatCards = ({
onDetailsClick={() => setSelectedMetric("revenue")} onDetailsClick={() => setSelectedMetric("revenue")}
isLoading={loading || !stats} isLoading={loading || !stats}
variant="mini" variant="mini"
background="bg-gradient-to-br from-emerald-900 to-emerald-800" background="h-[150px] bg-gradient-to-br from-emerald-900 to-emerald-800"
/> />
<StatCard <StatCard

View File

@@ -50,8 +50,8 @@ export const METRIC_COLORS = {
export const summaryCard = (label, sublabel, value, options = {}) => { export const summaryCard = (label, sublabel, value, options = {}) => {
const { const {
colorClass = "text-gray-900 dark:text-gray-100", colorClass = "text-gray-900 dark:text-gray-100",
titleClass = "text-sm font-medium text-gray-600 dark:text-gray-300", titleClass = "text-sm font-medium text-gray-500 dark:text-gray-400",
descriptionClass = "text-sm text-muted-foreground", descriptionClass = "text-sm text-gray-600 dark:text-gray-300",
background = "bg-white dark:bg-gray-900/60", background = "bg-white dark:bg-gray-900/60",
icon: Icon, icon: Icon,
iconColor, iconColor,
@@ -59,9 +59,11 @@ export const summaryCard = (label, sublabel, value, options = {}) => {
} = options; } = options;
return ( return (
<Card className={`${background} backdrop-blur-sm`}> <Card className={`w-full ${background} backdrop-blur-sm`}>
<CardHeader className="flex flex-row items-center justify-between space-y-0 px-4 py-2"> <CardHeader className="flex flex-row items-center justify-between space-y-0 px-4 py-2">
<span className={titleClass}>{label}</span> <CardTitle className={titleClass}>
{label}
</CardTitle>
{Icon && ( {Icon && (
<div className="relative p-2"> <div className="relative p-2">
<div className={`absolute inset-0 rounded-full ${iconBackground}`} /> <div className={`absolute inset-0 rounded-full ${iconBackground}`} />
@@ -70,10 +72,16 @@ export const summaryCard = (label, sublabel, value, options = {}) => {
)} )}
</CardHeader> </CardHeader>
<CardContent className="px-4 pt-0 pb-2"> <CardContent className="px-4 pt-0 pb-2">
<div className={`text-2xl font-bold mb-1 ${colorClass}`}> <div className="space-y-2">
{value.toLocaleString()} <div>
<div className={`text-3xl font-extrabold ${colorClass}`}>
{value.toLocaleString()}
</div>
<div className={descriptionClass}>
{sublabel}
</div>
</div>
</div> </div>
<div className={descriptionClass}>{sublabel}</div>
</CardContent> </CardContent>
</Card> </Card>
); );