mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 11:01:45 +00:00
style(ui): padronizar tipografia — font-medium para font-semibold
Padronização de peso tipográfico em títulos, rótulos de seção, nomes de entidades e valores monetários em toda a interface. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,10 @@ import {
|
||||
ACCOUNT_AUTO_INVOICE_NOTE_PREFIX,
|
||||
INITIAL_BALANCE_NOTE,
|
||||
} from "@/shared/lib/accounts/constants";
|
||||
import type { CategoryType } from "@/shared/lib/categories/constants";
|
||||
import {
|
||||
type CategoryType,
|
||||
INVOICE_PAYMENT_CATEGORY_NAME,
|
||||
} from "@/shared/lib/categories/constants";
|
||||
import { db } from "@/shared/lib/db";
|
||||
import { getAdminPayerId } from "@/shared/lib/payers/get-admin-id";
|
||||
import { calculatePercentageChange } from "@/shared/utils/math";
|
||||
@@ -45,6 +48,7 @@ export async function fetchCategoryDetails(
|
||||
const previousPeriod = getPreviousPeriod(period);
|
||||
const transactionType = category.type === "receita" ? "Receita" : "Despesa";
|
||||
const adminPayerId = await getAdminPayerId(userId);
|
||||
const isInvoiceCategory = category.name === INVOICE_PAYMENT_CATEGORY_NAME;
|
||||
|
||||
const sanitizedNote = or(
|
||||
isNull(transactions.note),
|
||||
@@ -59,7 +63,7 @@ export async function fetchCategoryDetails(
|
||||
eq(transactions.transactionType, transactionType),
|
||||
eq(transactions.period, period),
|
||||
eq(transactions.payerId, adminPayerId),
|
||||
sanitizedNote,
|
||||
...(isInvoiceCategory ? [] : [sanitizedNote]),
|
||||
),
|
||||
with: {
|
||||
payer: true,
|
||||
@@ -108,7 +112,7 @@ export async function fetchCategoryDetails(
|
||||
eq(transactions.categoryId, categoryId),
|
||||
eq(transactions.transactionType, transactionType),
|
||||
eq(transactions.payerId, adminPayerId),
|
||||
sanitizedNote,
|
||||
...(isInvoiceCategory ? [] : [sanitizedNote]),
|
||||
eq(transactions.period, previousPeriod),
|
||||
or(
|
||||
isNull(transactions.note),
|
||||
|
||||
@@ -46,7 +46,7 @@ export function BillListItem({ bill, onPay }: BillListItemProps) {
|
||||
<span
|
||||
className={cn(
|
||||
"cursor-help rounded-full py-0.5",
|
||||
bill.isSettled && "text-success",
|
||||
bill.isSettled && "text-success font-semibold",
|
||||
)}
|
||||
>
|
||||
{statusLabel}
|
||||
@@ -60,7 +60,7 @@ export function BillListItem({ bill, onPay }: BillListItemProps) {
|
||||
<span
|
||||
className={cn(
|
||||
"rounded-full py-0.5",
|
||||
bill.isSettled && "text-success",
|
||||
bill.isSettled && "text-success font-semibold",
|
||||
)}
|
||||
>
|
||||
{statusLabel}
|
||||
@@ -72,7 +72,7 @@ export function BillListItem({ bill, onPay }: BillListItemProps) {
|
||||
</div>
|
||||
|
||||
<div className="flex shrink-0 flex-col items-end">
|
||||
<MoneyValues amount={bill.amount} />
|
||||
<MoneyValues className="font-medium" amount={bill.amount} />
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
|
||||
@@ -97,7 +97,7 @@ export function BillPaymentDialog({
|
||||
<p className="mb-1 text-xs font-medium text-muted-foreground uppercase tracking-wide">
|
||||
Boleto
|
||||
</p>
|
||||
<p className="text-base font-medium text-foreground">
|
||||
<p className="text-base font-semibold text-foreground">
|
||||
{bill.name}
|
||||
</p>
|
||||
</div>
|
||||
@@ -113,7 +113,7 @@ export function BillPaymentDialog({
|
||||
</div>
|
||||
<MoneyValues
|
||||
amount={bill.amount}
|
||||
className="text-lg font-medium"
|
||||
className="text-lg font-semibold"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -281,12 +281,12 @@ export function CategoryBreakdownWidgetView({
|
||||
|
||||
<div className="flex shrink-0 flex-col items-end gap-0.5">
|
||||
<MoneyValues
|
||||
className="text-foreground"
|
||||
className="text-foreground font-medium"
|
||||
amount={category.currentAmount}
|
||||
/>
|
||||
{category.percentageChange !== null ? (
|
||||
<span
|
||||
className={`flex items-center gap-0.5 text-xs ${changeClassName}`}
|
||||
className={`flex items-center gap-0.5 text-xs font-medium ${changeClassName}`}
|
||||
>
|
||||
{hasIncrease ? (
|
||||
<RiArrowUpSFill className="size-3" />
|
||||
|
||||
@@ -197,7 +197,9 @@ export function CategoryHistoryWidget({ data }: CategoryHistoryWidgetProps) {
|
||||
style={{ backgroundColor: color }}
|
||||
/>
|
||||
)}
|
||||
<span className="text-foreground">{category.name}</span>
|
||||
<span className="text-sm font-medium text-foreground">
|
||||
{category.name}
|
||||
</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
@@ -398,7 +400,7 @@ export function CategoryHistoryWidget({ data }: CategoryHistoryWidgetProps) {
|
||||
{config?.label}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-xs font-medium tabular-nums">
|
||||
<span className="text-xs font-medium">
|
||||
{formatCurrency(value)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -116,13 +116,14 @@ const getPercentChange = (current: number, previous: number): string => {
|
||||
}
|
||||
|
||||
const change = ((current - previous) / Math.abs(previous)) * 100;
|
||||
return Number.isFinite(change) && Math.abs(change) < 1000000
|
||||
? formatPercentage(change, {
|
||||
maximumFractionDigits: 1,
|
||||
minimumFractionDigits: 1,
|
||||
signDisplay: "always",
|
||||
})
|
||||
: "—";
|
||||
if (!Number.isFinite(change)) return "—";
|
||||
if (change > 999) return "+999%";
|
||||
if (change < -999) return "-999%";
|
||||
return formatPercentage(change, {
|
||||
maximumFractionDigits: 2,
|
||||
minimumFractionDigits: 2,
|
||||
signDisplay: "always",
|
||||
});
|
||||
};
|
||||
|
||||
const getTrendBadgeClass = (trend: Trend, invertTrend: boolean): string => {
|
||||
@@ -159,7 +160,7 @@ export function DashboardMetricsCards({ metrics }: DashboardMetricsCardsProps) {
|
||||
<CardHeader>
|
||||
<div className="flex items-start justify-between">
|
||||
<div>
|
||||
<CardTitle className="flex items-center gap-1.5 tracking-tight">
|
||||
<CardTitle className="flex items-center gap-1.5 ">
|
||||
<Icon className={cn("size-4", iconClass)} aria-hidden />
|
||||
{label}
|
||||
<MetricsCardInfoButton
|
||||
@@ -179,12 +180,12 @@ export function DashboardMetricsCards({ metrics }: DashboardMetricsCardsProps) {
|
||||
<CardContent className="flex flex-col gap-3">
|
||||
<div className="flex flex-wrap items-center justify-between gap-2 mt-1">
|
||||
<MoneyValues
|
||||
className="text-2xl leading-none"
|
||||
className="text-2xl leading-none font-medium"
|
||||
amount={metric.current}
|
||||
/>
|
||||
<div
|
||||
className={cn(
|
||||
"inline-flex items-center gap-1 text-xs ",
|
||||
"inline-flex items-center gap-1 text-xs font-medium",
|
||||
trendBadgeClass,
|
||||
)}
|
||||
>
|
||||
@@ -195,7 +196,7 @@ export function DashboardMetricsCards({ metrics }: DashboardMetricsCardsProps) {
|
||||
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<MoneyValues
|
||||
className="inline text-xs text-muted-foreground"
|
||||
className="inline text-xs font-medium text-muted-foreground"
|
||||
amount={metric.previous}
|
||||
/>
|
||||
<span className="ml-1">no mês anterior</span>
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
import { formatCurrentDate, getGreeting } from "./welcome-widget";
|
||||
|
||||
export function DashboardWelcome({ name }: { name?: string | null }) {
|
||||
type DashboardWelcomeProps = {
|
||||
name?: string | null;
|
||||
};
|
||||
|
||||
export function DashboardWelcome({ name }: DashboardWelcomeProps) {
|
||||
const displayName = name && name.trim().length > 0 ? name : "Administrador";
|
||||
const formattedDate = formatCurrentDate();
|
||||
const greeting = getGreeting();
|
||||
|
||||
return (
|
||||
<section className="py-4">
|
||||
<div className="tracking-tight">
|
||||
<h1 className="text-xl font-medium">
|
||||
<div>
|
||||
<h1 className="text-xl tracking-tight">
|
||||
{greeting}, {displayName}
|
||||
</h1>
|
||||
<h2 className="text-sm mt-1 text-muted-foreground">{formattedDate}</h2>
|
||||
<h2 className="mt-1 text-sm text-muted-foreground">{formattedDate}</h2>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -44,8 +44,9 @@ export function GoalProgressItem({
|
||||
{item.categoryName}
|
||||
</p>
|
||||
<p className="mt-0.5 text-xs text-muted-foreground">
|
||||
<MoneyValues amount={item.spentAmount} /> de{" "}
|
||||
<MoneyValues amount={item.budgetAmount} />
|
||||
<MoneyValues className="font-medium" amount={item.spentAmount} />{" "}
|
||||
de{" "}
|
||||
<MoneyValues className="font-medium" amount={item.budgetAmount} />
|
||||
<span className={`ml-1.5 font-medium ${deltaColor}`}>
|
||||
{formatGoalProgressPercentage(percentageDelta, true)}
|
||||
</span>
|
||||
|
||||
@@ -132,12 +132,12 @@ export function InstallmentAnalysisPage({
|
||||
{/* Card de resumo principal */}
|
||||
<Card className="border-none bg-primary/15">
|
||||
<CardContent className="flex flex-col items-start justify-center gap-2 py-2">
|
||||
<p className="text-sm font-medium text-muted-foreground">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Se você pagar tudo que está selecionado:
|
||||
</p>
|
||||
<MoneyValues
|
||||
amount={grandTotal}
|
||||
className="text-3xl font-medium text-primary"
|
||||
className="text-3xl font-semibold text-primary"
|
||||
/>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{selectedCount} {selectedCount === 1 ? "parcela" : "parcelas"}{" "}
|
||||
@@ -167,7 +167,7 @@ export function InstallmentAnalysisPage({
|
||||
|
||||
{/* Seção de Lançamentos Parcelados */}
|
||||
{data.installmentGroups.length > 0 && (
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
||||
{data.installmentGroups.map((group) => (
|
||||
<InstallmentGroupCard
|
||||
key={group.seriesId}
|
||||
|
||||
@@ -59,7 +59,10 @@ export function InstallmentExpenseListItem({
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
<MoneyValues amount={expense.amount} className="shrink-0" />
|
||||
<MoneyValues
|
||||
amount={expense.amount}
|
||||
className="shrink-0 font-medium"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-muted-foreground">
|
||||
@@ -67,7 +70,7 @@ export function InstallmentExpenseListItem({
|
||||
{" · Restante "}
|
||||
<MoneyValues
|
||||
amount={remainingAmount}
|
||||
className="inline-block font-medium"
|
||||
className="inline-block font-semibold"
|
||||
/>{" "}
|
||||
({remainingInstallments})
|
||||
</p>
|
||||
|
||||
@@ -116,7 +116,10 @@ export function InvoiceListItem({ invoice, onPay }: InvoiceListItemProps) {
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-sm font-medium text-foreground">
|
||||
<MoneyValues amount={share.amount} />
|
||||
<MoneyValues
|
||||
className="font-medium"
|
||||
amount={share.amount}
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
@@ -144,7 +147,7 @@ export function InvoiceListItem({ invoice, onPay }: InvoiceListItemProps) {
|
||||
paymentTooltipLabel ? (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span className="cursor-help text-success">
|
||||
<span className="cursor-help text-success font-semibold">
|
||||
{paymentInfo.label}
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
@@ -153,7 +156,9 @@ export function InvoiceListItem({ invoice, onPay }: InvoiceListItemProps) {
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<span className="text-success">{paymentInfo.label}</span>
|
||||
<span className="text-success font-semibold">
|
||||
{paymentInfo.label}
|
||||
</span>
|
||||
)
|
||||
) : null}
|
||||
</div>
|
||||
@@ -161,7 +166,10 @@ export function InvoiceListItem({ invoice, onPay }: InvoiceListItemProps) {
|
||||
</div>
|
||||
|
||||
<div className="flex shrink-0 flex-col items-end">
|
||||
<MoneyValues amount={Math.abs(invoice.totalAmount)} />
|
||||
<MoneyValues
|
||||
className="font-medium"
|
||||
amount={Math.abs(invoice.totalAmount)}
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
|
||||
@@ -113,7 +113,7 @@ export function InvoicePaymentDialog({
|
||||
<p className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
|
||||
Cartão
|
||||
</p>
|
||||
<p className="truncate text-base font-medium text-foreground">
|
||||
<p className="truncate text-base font-semibold text-foreground">
|
||||
{invoice.cardName}
|
||||
</p>
|
||||
</div>
|
||||
@@ -130,7 +130,7 @@ export function InvoicePaymentDialog({
|
||||
</div>
|
||||
<MoneyValues
|
||||
amount={Math.abs(invoice.totalAmount)}
|
||||
className="text-lg font-medium"
|
||||
className="text-lg font-semibold"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ export function MyAccountsWidget({
|
||||
<div className="flex items-start justify-between gap-3 py-1">
|
||||
<div className="space-y-1">
|
||||
<p className="text-sm text-muted-foreground">Saldo Total</p>
|
||||
<MoneyValues className="text-2xl" amount={totalBalance} />
|
||||
<MoneyValues className="text-2xl font-medium" amount={totalBalance} />
|
||||
</div>
|
||||
|
||||
{excludedAccountsCount > 0 ? (
|
||||
@@ -137,7 +137,7 @@ export function MyAccountsWidget({
|
||||
</div>
|
||||
) : (
|
||||
<ul className="flex flex-col">
|
||||
{displayedAccounts.map((account) => {
|
||||
{displayedAccounts.map((account, index) => {
|
||||
const logoSrc = resolveLogoSrc(account.logo);
|
||||
|
||||
return (
|
||||
@@ -154,6 +154,7 @@ export function MyAccountsWidget({
|
||||
fill
|
||||
sizes="38px"
|
||||
className="object-contain rounded-full"
|
||||
priority={index === 0}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -199,7 +200,10 @@ export function MyAccountsWidget({
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-end gap-0.5 text-right">
|
||||
<MoneyValues amount={account.balance} />
|
||||
<MoneyValues
|
||||
className="font-medium"
|
||||
amount={account.balance}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -83,10 +83,13 @@ export function PayersWidget({ payers }: PayersWidgetProps) {
|
||||
</div>
|
||||
|
||||
<div className="flex shrink-0 flex-col items-end">
|
||||
<MoneyValues amount={payer.totalExpenses} />
|
||||
<MoneyValues
|
||||
className="font-medium"
|
||||
amount={payer.totalExpenses}
|
||||
/>
|
||||
{percentageChange !== null && (
|
||||
<span
|
||||
className={`flex items-center gap-0.5 text-xs ${
|
||||
className={`flex items-center gap-0.5 text-xs font-medium ${
|
||||
percentageChange > 0
|
||||
? "text-destructive"
|
||||
: percentageChange < 0
|
||||
|
||||
@@ -8,11 +8,15 @@ import { PaymentOverviewWidgetView } from "./payment-overview/payment-overview-w
|
||||
type PaymentOverviewWidgetProps = {
|
||||
paymentConditionsData: PaymentConditionsData;
|
||||
paymentMethodsData: PaymentMethodsData;
|
||||
period: string;
|
||||
adminPayerSlug: string | null;
|
||||
};
|
||||
|
||||
export function PaymentOverviewWidget({
|
||||
paymentConditionsData,
|
||||
paymentMethodsData,
|
||||
period,
|
||||
adminPayerSlug,
|
||||
}: PaymentOverviewWidgetProps) {
|
||||
const { activeTab, handleTabChange } = usePaymentOverviewWidgetController();
|
||||
|
||||
@@ -22,6 +26,8 @@ export function PaymentOverviewWidget({
|
||||
paymentConditionsData={paymentConditionsData}
|
||||
paymentMethodsData={paymentMethodsData}
|
||||
onTabChange={handleTabChange}
|
||||
period={period}
|
||||
adminPayerSlug={adminPayerSlug}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { RiExternalLinkLine } from "@remixicon/react";
|
||||
import Link from "next/link";
|
||||
import type { ReactNode } from "react";
|
||||
import {
|
||||
formatPaymentBreakdownPercentage,
|
||||
@@ -17,6 +19,7 @@ export type PaymentBreakdownListItemData = {
|
||||
amount: number;
|
||||
transactions: number;
|
||||
percentage: number;
|
||||
href?: string;
|
||||
};
|
||||
|
||||
type PaymentBreakdownListItemProps = {
|
||||
@@ -40,8 +43,21 @@ export function PaymentBreakdownListItem({
|
||||
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-sm font-medium text-foreground">{item.title}</p>
|
||||
<MoneyValues amount={item.amount} />
|
||||
{item.href ? (
|
||||
<Link
|
||||
href={item.href}
|
||||
className="inline-flex items-center gap-1 text-sm font-medium text-foreground underline-offset-2 hover:text-primary hover:underline"
|
||||
>
|
||||
<span className="truncate">{item.title}</span>
|
||||
<RiExternalLinkLine
|
||||
className="size-3 shrink-0 text-muted-foreground"
|
||||
aria-hidden
|
||||
/>
|
||||
</Link>
|
||||
) : (
|
||||
<p className="text-sm font-medium text-foreground">{item.title}</p>
|
||||
)}
|
||||
<MoneyValues className="font-medium" amount={item.amount} />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between text-xs text-muted-foreground">
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { RiCheckLine, RiSlideshowLine } from "@remixicon/react";
|
||||
import type { PaymentConditionsData } from "@/features/dashboard/payments/payment-conditions-queries";
|
||||
import { getConditionIcon } from "@/shared/utils/icons";
|
||||
import { formatPeriodForUrl } from "@/shared/utils/period";
|
||||
import { slugify } from "@/shared/utils/string";
|
||||
import {
|
||||
PaymentBreakdownList,
|
||||
type PaymentBreakdownListItemData,
|
||||
@@ -8,6 +10,8 @@ import {
|
||||
|
||||
type PaymentConditionsWidgetProps = {
|
||||
data: PaymentConditionsData;
|
||||
period: string;
|
||||
adminPayerSlug: string | null;
|
||||
};
|
||||
|
||||
const resolveConditionIcon = (condition: string) =>
|
||||
@@ -15,16 +19,27 @@ const resolveConditionIcon = (condition: string) =>
|
||||
|
||||
export function PaymentConditionsWidget({
|
||||
data,
|
||||
period,
|
||||
adminPayerSlug,
|
||||
}: PaymentConditionsWidgetProps) {
|
||||
const items: PaymentBreakdownListItemData[] = data.conditions.map(
|
||||
(condition) => ({
|
||||
id: condition.condition,
|
||||
title: condition.condition,
|
||||
icon: resolveConditionIcon(condition.condition),
|
||||
amount: condition.amount,
|
||||
transactions: condition.transactions,
|
||||
percentage: condition.percentage,
|
||||
}),
|
||||
(condition) => {
|
||||
const params = new URLSearchParams({
|
||||
type: slugify("Despesa"),
|
||||
condition: slugify(condition.condition),
|
||||
periodo: formatPeriodForUrl(period),
|
||||
});
|
||||
if (adminPayerSlug) params.set("payer", adminPayerSlug);
|
||||
return {
|
||||
id: condition.condition,
|
||||
title: condition.condition,
|
||||
icon: resolveConditionIcon(condition.condition),
|
||||
amount: condition.amount,
|
||||
transactions: condition.transactions,
|
||||
percentage: condition.percentage,
|
||||
href: `/transactions?${params.toString()}`,
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { RiBankCard2Line, RiMoneyDollarCircleLine } from "@remixicon/react";
|
||||
import type { PaymentMethodsData } from "@/features/dashboard/payments/payment-methods-queries";
|
||||
import { getPaymentMethodIcon } from "@/shared/utils/icons";
|
||||
import { formatPeriodForUrl } from "@/shared/utils/period";
|
||||
import { slugify } from "@/shared/utils/string";
|
||||
import {
|
||||
PaymentBreakdownList,
|
||||
type PaymentBreakdownListItemData,
|
||||
@@ -8,6 +10,8 @@ import {
|
||||
|
||||
type PaymentMethodsWidgetProps = {
|
||||
data: PaymentMethodsData;
|
||||
period: string;
|
||||
adminPayerSlug: string | null;
|
||||
};
|
||||
|
||||
const resolvePaymentMethodIcon = (paymentMethod: string) =>
|
||||
@@ -15,15 +19,28 @@ const resolvePaymentMethodIcon = (paymentMethod: string) =>
|
||||
<RiBankCard2Line className="size-5" aria-hidden />
|
||||
);
|
||||
|
||||
export function PaymentMethodsWidget({ data }: PaymentMethodsWidgetProps) {
|
||||
const items: PaymentBreakdownListItemData[] = data.methods.map((method) => ({
|
||||
id: method.paymentMethod,
|
||||
title: method.paymentMethod,
|
||||
icon: resolvePaymentMethodIcon(method.paymentMethod),
|
||||
amount: method.amount,
|
||||
transactions: method.transactions,
|
||||
percentage: method.percentage,
|
||||
}));
|
||||
export function PaymentMethodsWidget({
|
||||
data,
|
||||
period,
|
||||
adminPayerSlug,
|
||||
}: PaymentMethodsWidgetProps) {
|
||||
const items: PaymentBreakdownListItemData[] = data.methods.map((method) => {
|
||||
const params = new URLSearchParams({
|
||||
type: slugify("Despesa"),
|
||||
payment: slugify(method.paymentMethod),
|
||||
periodo: formatPeriodForUrl(period),
|
||||
});
|
||||
if (adminPayerSlug) params.set("payer", adminPayerSlug);
|
||||
return {
|
||||
id: method.paymentMethod,
|
||||
title: method.paymentMethod,
|
||||
icon: resolvePaymentMethodIcon(method.paymentMethod),
|
||||
amount: method.amount,
|
||||
transactions: method.transactions,
|
||||
percentage: method.percentage,
|
||||
href: `/transactions?${params.toString()}`,
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<PaymentBreakdownList
|
||||
|
||||
@@ -16,6 +16,8 @@ type PaymentOverviewWidgetViewProps = {
|
||||
paymentConditionsData: PaymentConditionsData;
|
||||
paymentMethodsData: PaymentMethodsData;
|
||||
onTabChange: (value: string) => void;
|
||||
period: string;
|
||||
adminPayerSlug: string | null;
|
||||
};
|
||||
|
||||
export function PaymentOverviewWidgetView({
|
||||
@@ -23,6 +25,8 @@ export function PaymentOverviewWidgetView({
|
||||
paymentConditionsData,
|
||||
paymentMethodsData,
|
||||
onTabChange,
|
||||
period,
|
||||
adminPayerSlug,
|
||||
}: PaymentOverviewWidgetViewProps) {
|
||||
return (
|
||||
<Tabs value={activeTab} onValueChange={onTabChange} className="w-full">
|
||||
@@ -38,11 +42,19 @@ export function PaymentOverviewWidgetView({
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="conditions" className="mt-2">
|
||||
<PaymentConditionsWidget data={paymentConditionsData} />
|
||||
<PaymentConditionsWidget
|
||||
data={paymentConditionsData}
|
||||
period={period}
|
||||
adminPayerSlug={adminPayerSlug}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="methods" className="mt-2">
|
||||
<PaymentMethodsWidget data={paymentMethodsData} />
|
||||
<PaymentMethodsWidget
|
||||
data={paymentMethodsData}
|
||||
period={period}
|
||||
adminPayerSlug={adminPayerSlug}
|
||||
/>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
);
|
||||
|
||||
@@ -24,10 +24,7 @@ export function PaymentStatusCategorySection({
|
||||
<div className="mt-4 space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm font-medium text-foreground">{title}</span>
|
||||
<MoneyValues
|
||||
amount={total}
|
||||
className="text-sm font-medium tabular-nums"
|
||||
/>
|
||||
<MoneyValues amount={total} className="font-medium" />
|
||||
</div>
|
||||
|
||||
<Progress value={confirmedPercentage} className="h-2" />
|
||||
@@ -35,13 +32,13 @@ export function PaymentStatusCategorySection({
|
||||
<div className="flex flex-col gap-1 text-sm sm:flex-row sm:items-center sm:justify-between sm:gap-4">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<StatusDot color="bg-primary" />
|
||||
<MoneyValues amount={confirmed} className="tabular-nums" />
|
||||
<MoneyValues amount={confirmed} className="font-medium" />
|
||||
<span className="text-xs text-muted-foreground">confirmados</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-1.5">
|
||||
<StatusDot color="bg-warning/40" />
|
||||
<MoneyValues amount={pending} className="tabular-nums" />
|
||||
<MoneyValues amount={pending} className="font-medium" />
|
||||
<span className="text-xs text-muted-foreground">pendentes</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -178,7 +178,10 @@ export function PurchasesByCategoryWidget({
|
||||
</div>
|
||||
|
||||
<div className="shrink-0 text-foreground">
|
||||
<MoneyValues amount={transaction.amount} />
|
||||
<MoneyValues
|
||||
className="font-medium"
|
||||
amount={transaction.amount}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -45,7 +45,7 @@ export function RecurringExpensesWidget({
|
||||
{expense.name}
|
||||
</p>
|
||||
|
||||
<MoneyValues amount={expense.amount} />
|
||||
<MoneyValues className="font-medium" amount={expense.amount} />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between text-xs text-muted-foreground">
|
||||
|
||||
@@ -48,7 +48,10 @@ export function TopEstablishmentsWidget({
|
||||
</div>
|
||||
|
||||
<div className="shrink-0 text-foreground">
|
||||
<MoneyValues amount={establishment.amount} />
|
||||
<MoneyValues
|
||||
className="font-medium"
|
||||
amount={establishment.amount}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -113,7 +113,10 @@ export function TopExpensesWidget({
|
||||
</div>
|
||||
|
||||
<div className="shrink-0 text-foreground">
|
||||
<MoneyValues amount={expense.amount} />
|
||||
<MoneyValues
|
||||
className="font-medium"
|
||||
amount={expense.amount}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user