mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 11:01:45 +00:00
refactor(dashboard): reorganizar módulos em subdiretórios e nova arquitetura de widgets
Arquivos de queries, helpers e controllers dispersos na raiz de dashboard/ foram movidos para subdiretórios temáticos (bills/, invoices/, notes/, notifications/, overview/, payments/, goals-progress/, categories/). ~25 widgets monolíticos obsoletos removidos em favor de nova arquitetura baseada em widget-registry com components/widgets/. Novos componentes: category-breakdown-chart/list, goals-progress-item, percentage-change-indicator. Imports atualizados em fetch-dashboard-data e transaction-filters limpos. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import type {
|
||||
Budget,
|
||||
BudgetCategory,
|
||||
} from "@/features/budgets/components/types";
|
||||
import type {
|
||||
GoalProgressCategory,
|
||||
GoalProgressItem,
|
||||
GoalProgressStatus,
|
||||
} from "@/features/dashboard/goals-progress/goals-progress-queries";
|
||||
import { formatPercentage } from "@/shared/utils/percentage";
|
||||
|
||||
export const clampGoalProgress = (value: number, min: number, max: number) =>
|
||||
Math.min(max, Math.max(min, value));
|
||||
|
||||
export const formatGoalProgressPercentage = (value: number, withSign = false) =>
|
||||
formatPercentage(value, {
|
||||
maximumFractionDigits: 1,
|
||||
signDisplay: withSign ? "always" : "auto",
|
||||
});
|
||||
|
||||
export const getGoalProgressStatusColorClass = (status: GoalProgressStatus) =>
|
||||
status === "exceeded" ? "text-destructive" : "";
|
||||
|
||||
export const mapGoalProgressCategoriesToBudgetCategories = (
|
||||
categories: GoalProgressCategory[],
|
||||
): BudgetCategory[] =>
|
||||
categories.map((category) => ({
|
||||
id: category.id,
|
||||
name: category.name,
|
||||
icon: category.icon,
|
||||
}));
|
||||
|
||||
export const mapGoalProgressItemToBudget = (
|
||||
item: GoalProgressItem,
|
||||
): Budget => ({
|
||||
id: item.id,
|
||||
amount: item.budgetAmount,
|
||||
spent: item.spentAmount,
|
||||
period: item.period,
|
||||
createdAt: item.createdAt,
|
||||
category: item.categoryId
|
||||
? {
|
||||
id: item.categoryId,
|
||||
name: item.categoryName,
|
||||
icon: item.categoryIcon,
|
||||
}
|
||||
: null,
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
export type GoalProgressStatus = "on-track" | "critical" | "exceeded";
|
||||
|
||||
export type GoalProgressItem = {
|
||||
id: string;
|
||||
categoryId: string | null;
|
||||
categoryName: string;
|
||||
categoryIcon: string | null;
|
||||
period: string;
|
||||
createdAt: string;
|
||||
budgetAmount: number;
|
||||
spentAmount: number;
|
||||
usedPercentage: number;
|
||||
status: GoalProgressStatus;
|
||||
};
|
||||
|
||||
export type GoalProgressCategory = {
|
||||
id: string;
|
||||
name: string;
|
||||
icon: string | null;
|
||||
};
|
||||
|
||||
export type GoalsProgressData = {
|
||||
items: GoalProgressItem[];
|
||||
categories: GoalProgressCategory[];
|
||||
totalBudgets: number;
|
||||
exceededCount: number;
|
||||
criticalCount: number;
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
"use client";
|
||||
|
||||
import { useMemo, useState } from "react";
|
||||
import type {
|
||||
Budget,
|
||||
BudgetCategory,
|
||||
} from "@/features/budgets/components/types";
|
||||
import {
|
||||
mapGoalProgressCategoriesToBudgetCategories,
|
||||
mapGoalProgressItemToBudget,
|
||||
} from "@/features/dashboard/goals-progress/goals-progress-helpers";
|
||||
import type {
|
||||
GoalProgressItem,
|
||||
GoalsProgressData,
|
||||
} from "@/features/dashboard/goals-progress/goals-progress-queries";
|
||||
|
||||
type GoalsProgressWidgetController = {
|
||||
selectedBudget: Budget | null;
|
||||
editOpen: boolean;
|
||||
categories: BudgetCategory[];
|
||||
defaultPeriod: string;
|
||||
handleEdit: (item: GoalProgressItem) => void;
|
||||
handleEditOpenChange: (open: boolean) => void;
|
||||
};
|
||||
|
||||
export function useGoalsProgressWidgetController(
|
||||
data: GoalsProgressData,
|
||||
): GoalsProgressWidgetController {
|
||||
const [editOpen, setEditOpen] = useState(false);
|
||||
const [selectedBudget, setSelectedBudget] = useState<Budget | null>(null);
|
||||
|
||||
const categories = useMemo<BudgetCategory[]>(
|
||||
() => mapGoalProgressCategoriesToBudgetCategories(data.categories),
|
||||
[data.categories],
|
||||
);
|
||||
|
||||
const defaultPeriod = data.items[0]?.period ?? "";
|
||||
|
||||
const handleEdit = (item: GoalProgressItem) => {
|
||||
setSelectedBudget(mapGoalProgressItemToBudget(item));
|
||||
setEditOpen(true);
|
||||
};
|
||||
|
||||
const handleEditOpenChange = (open: boolean) => {
|
||||
setEditOpen(open);
|
||||
if (!open) {
|
||||
setSelectedBudget(null);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
selectedBudget,
|
||||
editOpen,
|
||||
categories,
|
||||
defaultPeriod,
|
||||
handleEdit,
|
||||
handleEditOpenChange,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user