Compare commits
2 Commits
55098a7b95
...
7c864053bb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c864053bb | ||
|
|
9ce5511ad8 |
@@ -13,7 +13,7 @@ import {
|
|||||||
YAxis,
|
YAxis,
|
||||||
} from "recharts";
|
} from "recharts";
|
||||||
import { DatePicker } from "@/components/ui/date-picker";
|
import { DatePicker } from "@/components/ui/date-picker";
|
||||||
import { useDailyQuotes, useHistoricalMinMax } from "@/lib/queries";
|
import { useDailyQuotes, useHistoricalMinMax, useQuotes } from "@/lib/queries";
|
||||||
|
|
||||||
const priceFormatter = new Intl.NumberFormat("es-AR", {
|
const priceFormatter = new Intl.NumberFormat("es-AR", {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
@@ -47,12 +47,29 @@ export function BeloAnalysisPage() {
|
|||||||
|
|
||||||
const { data: historical, isLoading: historicalLoading } =
|
const { data: historical, isLoading: historicalLoading } =
|
||||||
useHistoricalMinMax("BELO");
|
useHistoricalMinMax("BELO");
|
||||||
|
const { data: quotes } = useQuotes();
|
||||||
const { data: daily, isLoading: dailyLoading } = useDailyQuotes(
|
const { data: daily, isLoading: dailyLoading } = useDailyQuotes(
|
||||||
"BELO",
|
"BELO",
|
||||||
startDateStr,
|
startDateStr,
|
||||||
endDateStr,
|
endDateStr,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const yesterday = subDays(today, 1);
|
||||||
|
const yesterdayStr = formatDate(yesterday);
|
||||||
|
const firstOfMonth = new Date(today.getFullYear(), today.getMonth(), 1);
|
||||||
|
const firstOfMonthStr = formatDate(firstOfMonth);
|
||||||
|
|
||||||
|
const { data: yesterdayQuote } = useDailyQuotes(
|
||||||
|
"BELO",
|
||||||
|
yesterdayStr,
|
||||||
|
yesterdayStr,
|
||||||
|
);
|
||||||
|
const { data: firstDayQuote } = useDailyQuotes(
|
||||||
|
"BELO",
|
||||||
|
firstOfMonthStr,
|
||||||
|
firstOfMonthStr,
|
||||||
|
);
|
||||||
|
|
||||||
const chartData = useMemo(() => {
|
const chartData = useMemo(() => {
|
||||||
if (!daily) return [];
|
if (!daily) return [];
|
||||||
return daily.map((d) => ({
|
return daily.map((d) => ({
|
||||||
@@ -86,6 +103,46 @@ export function BeloAnalysisPage() {
|
|||||||
};
|
};
|
||||||
}, [chartData]);
|
}, [chartData]);
|
||||||
|
|
||||||
|
const beloQuote = quotes?.find((q) => q.type === "BELO");
|
||||||
|
const currentBuy = beloQuote ? Number(beloQuote.buy) : 0;
|
||||||
|
|
||||||
|
const yesterdayBuy = yesterdayQuote?.[0]?.buy ?? null;
|
||||||
|
const prevDayDiff = yesterdayBuy !== null ? currentBuy - yesterdayBuy : null;
|
||||||
|
const prevDayPct =
|
||||||
|
prevDayDiff !== null && yesterdayBuy !== null && yesterdayBuy !== 0
|
||||||
|
? (prevDayDiff / yesterdayBuy) * 100
|
||||||
|
: null;
|
||||||
|
|
||||||
|
const firstMonthBuy = firstDayQuote?.[0]?.buy ?? null;
|
||||||
|
const monthDiff = firstMonthBuy !== null ? currentBuy - firstMonthBuy : null;
|
||||||
|
const monthPct =
|
||||||
|
monthDiff !== null && firstMonthBuy !== null && firstMonthBuy !== 0
|
||||||
|
? (monthDiff / firstMonthBuy) * 100
|
||||||
|
: null;
|
||||||
|
|
||||||
|
function VariationValue({
|
||||||
|
value,
|
||||||
|
pct,
|
||||||
|
}: {
|
||||||
|
value: number | null;
|
||||||
|
pct: number | null;
|
||||||
|
}) {
|
||||||
|
if (value === null || pct === null)
|
||||||
|
return <p className="text-sm text-muted-foreground">Sin datos</p>;
|
||||||
|
const isPositive = value >= 0;
|
||||||
|
const color = isPositive ? "text-emerald-500" : "text-red-500";
|
||||||
|
const sign = isPositive ? "+" : "";
|
||||||
|
return (
|
||||||
|
<p className={`text-lg font-bold tabular-nums ${color}`}>
|
||||||
|
{sign}${priceFormatter.format(Math.abs(value))}{" "}
|
||||||
|
<span className="text-sm font-normal">
|
||||||
|
({sign}
|
||||||
|
{pct.toFixed(2)}%)
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
@@ -101,7 +158,7 @@ export function BeloAnalysisPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid gap-4 md:grid-cols-2">
|
<div className="grid gap-4 md:grid-cols-4">
|
||||||
<div className="rounded-lg border p-4">
|
<div className="rounded-lg border p-4">
|
||||||
<p className="text-sm text-muted-foreground mb-2">
|
<p className="text-sm text-muted-foreground mb-2">
|
||||||
Mínimo histórico (compra)
|
Mínimo histórico (compra)
|
||||||
@@ -140,6 +197,16 @@ export function BeloAnalysisPage() {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="rounded-lg border p-4">
|
||||||
|
<p className="text-sm text-muted-foreground mb-2">Vs. día anterior</p>
|
||||||
|
<VariationValue value={prevDayDiff} pct={prevDayPct} />
|
||||||
|
</div>
|
||||||
|
<div className="rounded-lg border p-4">
|
||||||
|
<p className="text-sm text-muted-foreground mb-2">
|
||||||
|
Vs. primer día del mes
|
||||||
|
</p>
|
||||||
|
<VariationValue value={monthDiff} pct={monthPct} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="rounded-lg border p-4">
|
<div className="rounded-lg border p-4">
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ export function DashboardPage() {
|
|||||||
|
|
||||||
const belo = quotes?.find((q) => q.type === "BELO");
|
const belo = quotes?.find((q) => q.type === "BELO");
|
||||||
const blue = quotes?.find((q) => q.type === "BLUE");
|
const blue = quotes?.find((q) => q.type === "BLUE");
|
||||||
|
const bna = quotes?.find((q) => q.type === "BNA");
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const { data: monthlyExpenses } = useMonthlyPayedTotal(
|
const { data: monthlyExpenses } = useMonthlyPayedTotal(
|
||||||
@@ -156,7 +157,7 @@ export function DashboardPage() {
|
|||||||
Actualizar
|
Actualizar
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-4 md:grid-cols-4">
|
<div className="grid gap-4 md:grid-cols-4 lg:grid-cols-5">
|
||||||
<div className="rounded-lg border p-4">
|
<div className="rounded-lg border p-4">
|
||||||
<p className="text-sm text-muted-foreground">Pagos pendientes</p>
|
<p className="text-sm text-muted-foreground">Pagos pendientes</p>
|
||||||
<p className="text-2xl font-bold">
|
<p className="text-2xl font-bold">
|
||||||
@@ -176,6 +177,7 @@ export function DashboardPage() {
|
|||||||
variant="minimal"
|
variant="minimal"
|
||||||
/>
|
/>
|
||||||
<QuoteCard quote={blue} title="BLUE" variant="minimal" />
|
<QuoteCard quote={blue} title="BLUE" variant="minimal" />
|
||||||
|
<QuoteCard quote={bna} title="Dolar Oficial" variant="minimal" />
|
||||||
</div>
|
</div>
|
||||||
<DashboardExpensesTable />
|
<DashboardExpensesTable />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -141,11 +141,7 @@ export function ExpensesTable({
|
|||||||
if (expense.status === "PAYED") return null;
|
if (expense.status === "PAYED") return null;
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-end gap-1">
|
<div className="flex justify-end gap-1">
|
||||||
<Button
|
<Button variant="ghost" size="xs" onClick={() => onEdit(expense)}>
|
||||||
variant="ghost"
|
|
||||||
size="xs"
|
|
||||||
onClick={() => onEdit(expense)}
|
|
||||||
>
|
|
||||||
<Pencil className="size-3.5" />
|
<Pencil className="size-3.5" />
|
||||||
Editar
|
Editar
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user