feat: add SavingsWidget + GitActivityWidget
All checks were successful
Build & Deploy Dashboard / deploy (push) Successful in 1m6s
All checks were successful
Build & Deploy Dashboard / deploy (push) Successful in 1m6s
This commit is contained in:
54
src/app/api/savings/route.ts
Normal file
54
src/app/api/savings/route.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
export const dynamic = "force-dynamic";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
const PULSE_REFRESH_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE4MDIwMjY5NDgsImlhdCI6MTc3MDQ5MDk0OCwidHlwZSI6InJlZnJlc2giLCJ1c2VyX2lkIjoxfQ.zPJJB7o9vtnfIBFl7rNygEEXd9h-5YZeAxRIvWcRlXY";
|
||||
const PULSE_API = "https://api.digital-home.site";
|
||||
|
||||
async function getAccessToken(): Promise<string> {
|
||||
const res = await fetch(`${PULSE_API}/auth/refresh`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ refresh_token: PULSE_REFRESH_TOKEN }),
|
||||
signal: AbortSignal.timeout(5000),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!data.access_token) throw new Error("Failed to get token");
|
||||
return data.access_token;
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const token = await getAccessToken();
|
||||
|
||||
const res = await fetch(`${PULSE_API}/finance/transactions?limit=200&type=expense`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
signal: AbortSignal.timeout(8000),
|
||||
});
|
||||
const txs = await res.json();
|
||||
|
||||
// Группируем накопления по цели
|
||||
const groups: Record<string, number> = {};
|
||||
for (const t of txs) {
|
||||
if (t.category_emoji === "💎") {
|
||||
// Нормализуем название
|
||||
const desc = t.description as string;
|
||||
let key = "Другое";
|
||||
if (desc.toLowerCase().includes("квартир")) key = "🏠 Квартира";
|
||||
else if (desc.toLowerCase().includes("отпуск") || desc.toLowerCase().includes("путешеств")) key = "✈️ Отпуск";
|
||||
else if (desc.toLowerCase().includes("машин") || desc.toLowerCase().includes("авто")) key = "🚗 Машина";
|
||||
else key = desc;
|
||||
groups[key] = (groups[key] || 0) + (t.amount as number);
|
||||
}
|
||||
}
|
||||
|
||||
const goals = Object.entries(groups)
|
||||
.map(([name, amount]) => ({ name, amount }))
|
||||
.sort((a, b) => b.amount - a.amount);
|
||||
|
||||
const total = goals.reduce((s, g) => s + g.amount, 0);
|
||||
|
||||
return NextResponse.json({ goals, total });
|
||||
} catch (e) {
|
||||
return NextResponse.json({ error: String(e), goals: [], total: 0 }, { status: 500 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user