mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-10 11:21:45 +00:00
style: padroniza widgets e listas do dashboard
This commit is contained in:
@@ -3,15 +3,14 @@ import {
|
||||
RiArrowDownSFill,
|
||||
RiArrowUpLine,
|
||||
RiArrowUpSFill,
|
||||
RiCashLine,
|
||||
RiIncreaseDecreaseLine,
|
||||
RiCalendarCheckLine,
|
||||
RiScalesLine,
|
||||
RiSubtractLine,
|
||||
} from "@remixicon/react";
|
||||
import type { DashboardCardMetrics } from "@/features/dashboard/dashboard-metrics-queries";
|
||||
import MoneyValues from "@/shared/components/money-values";
|
||||
import {
|
||||
Card,
|
||||
CardAction,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
@@ -32,20 +31,33 @@ const CARDS = [
|
||||
key: "receitas",
|
||||
icon: RiArrowUpLine,
|
||||
invertTrend: false,
|
||||
cardClass: "",
|
||||
iconClass: "text-success",
|
||||
},
|
||||
{
|
||||
label: "Despesas",
|
||||
key: "despesas",
|
||||
icon: RiArrowDownLine,
|
||||
invertTrend: true,
|
||||
cardClass: "",
|
||||
iconClass: "text-destructive",
|
||||
},
|
||||
{
|
||||
label: "Balanço",
|
||||
key: "balanco",
|
||||
icon: RiIncreaseDecreaseLine,
|
||||
icon: RiScalesLine,
|
||||
invertTrend: false,
|
||||
cardClass: "",
|
||||
iconClass: "text-amber-500",
|
||||
},
|
||||
{
|
||||
label: "Previsto",
|
||||
key: "previsto",
|
||||
icon: RiCalendarCheckLine,
|
||||
invertTrend: false,
|
||||
cardClass: "border border-dashed",
|
||||
iconClass: "",
|
||||
},
|
||||
{ label: "Previsto", key: "previsto", icon: RiCashLine, invertTrend: false },
|
||||
] as const;
|
||||
|
||||
const TREND_ICONS = {
|
||||
@@ -62,7 +74,7 @@ const getTrend = (current: number, previous: number): Trend => {
|
||||
};
|
||||
|
||||
const getPercentChange = (current: number, previous: number): string => {
|
||||
const EPSILON = 0.01; // Considera valores menores que 1 centavo como zero
|
||||
const EPSILON = 0.01;
|
||||
|
||||
if (Math.abs(previous) < EPSILON) {
|
||||
if (Math.abs(current) < EPSILON) return "0%";
|
||||
@@ -80,48 +92,49 @@ const getPercentChange = (current: number, previous: number): string => {
|
||||
};
|
||||
|
||||
const getTrendColor = (trend: Trend, invertTrend: boolean): string => {
|
||||
if (trend === "flat") return "";
|
||||
if (trend === "flat") return "text-muted-foreground";
|
||||
const isPositive = invertTrend ? trend === "down" : trend === "up";
|
||||
return isPositive
|
||||
? "text-success border-success"
|
||||
: "text-destructive border-destructive";
|
||||
return isPositive ? "text-success" : "text-destructive";
|
||||
};
|
||||
|
||||
export function DashboardMetricsCards({ metrics }: DashboardMetricsCardsProps) {
|
||||
return (
|
||||
<div className="*:data-[slot=card]:from-primary/5 *:data-[slot=card]:to-card dark:*:data-[slot=card]:bg-card grid grid-cols-1 gap-3 @xl/main:grid-cols-2 @5xl/main:grid-cols-4">
|
||||
{CARDS.map(({ label, key, icon: Icon, invertTrend }) => {
|
||||
const metric = metrics[key];
|
||||
const trend = getTrend(metric.current, metric.previous);
|
||||
const TrendIcon = TREND_ICONS[trend];
|
||||
const trendColor = getTrendColor(trend, invertTrend);
|
||||
<div className="grid grid-cols-1 gap-3 @xl/main:grid-cols-2 @5xl/main:grid-cols-4">
|
||||
{CARDS.map(
|
||||
({ label, key, icon: Icon, invertTrend, cardClass, iconClass }) => {
|
||||
const metric = metrics[key];
|
||||
const trend = getTrend(metric.current, metric.previous);
|
||||
const TrendIcon = TREND_ICONS[trend];
|
||||
const trendColor = getTrendColor(trend, invertTrend);
|
||||
|
||||
return (
|
||||
<Card key={label} className="@container/card gap-2">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-1 tracking-tighter lowercase">
|
||||
<Icon className="size-4" />
|
||||
{label}
|
||||
</CardTitle>
|
||||
<MoneyValues className="text-2xl" amount={metric.current} />
|
||||
<CardAction>
|
||||
<div className={`flex items-center text-xs ${trendColor}`}>
|
||||
<TrendIcon size={16} />
|
||||
{getPercentChange(metric.current, metric.previous)}
|
||||
return (
|
||||
<Card
|
||||
key={label}
|
||||
className={`@container/card flex flex-col justify-between min-h-34 ${cardClass}`}
|
||||
>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-1 tracking-tight lowercase">
|
||||
<Icon className={`size-4 ${iconClass}`} />
|
||||
{label}
|
||||
</CardTitle>
|
||||
<div className="flex items-baseline gap-2 mt-auto pt-2">
|
||||
<MoneyValues className="text-2xl" amount={metric.current} />
|
||||
<div className={`flex items-center text-xs ${trendColor}`}>
|
||||
<TrendIcon size={14} />
|
||||
{getPercentChange(metric.current, metric.previous)}
|
||||
</div>
|
||||
</div>
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardFooter className="flex-col items-start gap-2 text-sm">
|
||||
<div className="line-clamp-1 flex gap-2 text-xs">
|
||||
mês anterior
|
||||
</div>
|
||||
<div className="text-foreground">
|
||||
<MoneyValues amount={metric.previous} />
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</CardHeader>
|
||||
<CardFooter className="text-sm">
|
||||
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
||||
<span>vs. mês anterior</span>
|
||||
<MoneyValues amount={metric.previous} />
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user