import {
RiArrowDownSFill,
RiArrowUpSFill,
RiExternalLinkLine,
RiPieChartLine,
RiWallet3Line,
} from "@remixicon/react";
import Link from "next/link";
import MoneyValues from "@/components/money-values";
import type { IncomeByCategoryData } from "@/lib/dashboard/categories/income-by-category";
import { getIconComponent } from "@/lib/utils/icons";
import { formatPeriodForUrl } from "@/lib/utils/period";
import { WidgetEmptyState } from "../widget-empty-state";
type IncomeByCategoryWidgetProps = {
data: IncomeByCategoryData;
period: string;
};
const buildInitials = (value: string) => {
const parts = value.trim().split(/\s+/).filter(Boolean);
if (parts.length === 0) {
return "CT";
}
if (parts.length === 1) {
const firstPart = parts[0];
return firstPart ? firstPart.slice(0, 2).toUpperCase() : "CT";
}
const firstChar = parts[0]?.[0] ?? "";
const secondChar = parts[1]?.[0] ?? "";
return `${firstChar}${secondChar}`.toUpperCase() || "CT";
};
const formatPercentage = (value: number) => {
return `${Math.abs(value).toFixed(1)}%`;
};
export function IncomeByCategoryWidget({
data,
period,
}: IncomeByCategoryWidgetProps) {
const periodParam = formatPeriodForUrl(period);
if (data.categories.length === 0) {
return (
}
title="Nenhuma receita encontrada"
description="Quando houver receitas registradas, elas aparecerão aqui."
/>
);
}
return (
{data.categories.map((category) => {
const IconComponent = category.categoryIcon
? getIconComponent(category.categoryIcon)
: null;
const initials = buildInitials(category.categoryName);
const hasIncrease =
category.percentageChange !== null && category.percentageChange > 0;
const hasDecrease =
category.percentageChange !== null && category.percentageChange < 0;
const hasBudget = category.budgetAmount !== null;
const budgetExceeded =
hasBudget &&
category.budgetUsedPercentage !== null &&
category.budgetUsedPercentage > 100;
const formatCurrency = (value: number) =>
new Intl.NumberFormat("pt-BR", {
style: "currency",
currency: "BRL",
}).format(value);
const exceededAmount =
budgetExceeded && category.budgetAmount
? category.currentAmount - category.budgetAmount
: 0;
return (
{IconComponent ? (
) : (
{initials}
)}
{category.categoryName}
{formatPercentage(category.percentageOfTotal)} da receita
total
{category.percentageChange !== null && (
{hasIncrease && }
{hasDecrease && }
{formatPercentage(category.percentageChange)}
)}
{hasBudget &&
category.budgetUsedPercentage !== null &&
category.budgetAmount !== null && (
{budgetExceeded ? (
<>
{formatPercentage(category.budgetUsedPercentage)} do
limite {formatCurrency(category.budgetAmount)} - excedeu
em {formatCurrency(exceededAmount)}
>
) : (
<>
{formatPercentage(category.budgetUsedPercentage)} do
limite {formatCurrency(category.budgetAmount)}
>
)}
)}
);
})}
);
}