refactor(core): move app para src e padroniza estrutura
5
.vscode/settings.json
vendored
@@ -28,5 +28,8 @@
|
||||
"eslint.enable": false,
|
||||
"prettier.enable": false,
|
||||
"typescript.preferences.organizeImportsCollation": "ordinal",
|
||||
"editor.fontSize": 15
|
||||
"editor.fontSize": 15,
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "vscode.json-language-features"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<img src="./public/imagens/logo_small.png" alt="OpenMonetis Logo" height="80" />
|
||||
<img src="./public/images/logo_small.png" alt="OpenMonetis Logo" height="80" />
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
@@ -21,7 +21,7 @@
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
<img src="./public/imagens/dashboard-preview-light.webp" alt="Dashboard Preview" width="800" />
|
||||
<img src="./public/images/dashboard-preview-light.webp" alt="Dashboard Preview" width="800" />
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { CategoryHistoryWidget } from "@/components/dashboard/category-history-widget";
|
||||
import { getUser } from "@/lib/auth/server";
|
||||
import { fetchCategoryHistory } from "@/lib/dashboard/categories/category-history";
|
||||
import { getCurrentPeriod } from "@/lib/utils/period";
|
||||
|
||||
export default async function HistoricoCategoriasPage() {
|
||||
const user = await getUser();
|
||||
const currentPeriod = getCurrentPeriod();
|
||||
|
||||
const data = await fetchCategoryHistory(user.id, currentPeriod);
|
||||
|
||||
return (
|
||||
<main>
|
||||
<CategoryHistoryWidget data={data} />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import { and, desc, eq, isNull, ne, or, type SQL } from "drizzle-orm";
|
||||
import {
|
||||
cartoes,
|
||||
categorias,
|
||||
contas,
|
||||
lancamentos,
|
||||
pagadores,
|
||||
} from "@/db/schema";
|
||||
import { INITIAL_BALANCE_NOTE } from "@/lib/contas/constants";
|
||||
import { db } from "@/lib/db";
|
||||
|
||||
export async function fetchLancamentos(filters: SQL[]) {
|
||||
const lancamentoRows = await db
|
||||
.select({
|
||||
lancamento: lancamentos,
|
||||
pagador: pagadores,
|
||||
conta: contas,
|
||||
cartao: cartoes,
|
||||
categoria: categorias,
|
||||
})
|
||||
.from(lancamentos)
|
||||
.leftJoin(pagadores, eq(lancamentos.pagadorId, pagadores.id))
|
||||
.leftJoin(contas, eq(lancamentos.contaId, contas.id))
|
||||
.leftJoin(cartoes, eq(lancamentos.cartaoId, cartoes.id))
|
||||
.leftJoin(categorias, eq(lancamentos.categoriaId, categorias.id))
|
||||
.where(
|
||||
and(
|
||||
...filters,
|
||||
// Excluir saldos iniciais de contas que têm excludeInitialBalanceFromIncome = true
|
||||
or(
|
||||
ne(lancamentos.note, INITIAL_BALANCE_NOTE),
|
||||
isNull(contas.excludeInitialBalanceFromIncome),
|
||||
eq(contas.excludeInitialBalanceFromIncome, false),
|
||||
),
|
||||
),
|
||||
)
|
||||
.orderBy(desc(lancamentos.purchaseDate), desc(lancamentos.createdAt));
|
||||
|
||||
// Transformar resultado para o formato esperado
|
||||
return lancamentoRows.map((row) => ({
|
||||
...row.lancamento,
|
||||
pagador: row.pagador,
|
||||
conta: row.conta,
|
||||
cartao: row.cartao,
|
||||
categoria: row.categoria,
|
||||
}));
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { InstallmentAnalysisPage } from "@/components/dashboard/installment-analysis/installment-analysis-page";
|
||||
import { getUser } from "@/lib/auth/server";
|
||||
import { fetchInstallmentAnalysis } from "@/lib/dashboard/expenses/installment-analysis";
|
||||
|
||||
export default async function Page() {
|
||||
const user = await getUser();
|
||||
const data = await fetchInstallmentAnalysis(user.id);
|
||||
|
||||
return (
|
||||
<main className="flex flex-col gap-4 pb-8">
|
||||
<InstallmentAnalysisPage data={data} />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.4.4/schema.json",
|
||||
"$schema": "https://biomejs.dev/schemas/2.4.6/schema.json",
|
||||
"vcs": {
|
||||
"enabled": true,
|
||||
"clientKind": "git",
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { LogoPickerTrigger, LogoPickerDialog } from "./logo-picker";
|
||||
@@ -1 +0,0 @@
|
||||
export { useIsMobile, useMobile } from "@/lib/hooks/use-mobile";
|
||||
15
drizzle/0019_parched_mephistopheles.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
CREATE TABLE "recurring_series" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"user_id" text NOT NULL,
|
||||
"status" text DEFAULT 'active' NOT NULL,
|
||||
"day_of_month" smallint NOT NULL,
|
||||
"last_generated_period" text NOT NULL,
|
||||
"template_data" jsonb NOT NULL,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "lancamentos" ADD COLUMN "recurring_series_id" uuid;--> statement-breakpoint
|
||||
ALTER TABLE "recurring_series" ADD CONSTRAINT "recurring_series_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX "recurring_series_user_id_status_idx" ON "recurring_series" USING btree ("user_id","status");--> statement-breakpoint
|
||||
ALTER TABLE "lancamentos" ADD CONSTRAINT "lancamentos_recurring_series_id_recurring_series_id_fk" FOREIGN KEY ("recurring_series_id") REFERENCES "public"."recurring_series"("id") ON DELETE set null ON UPDATE no action;
|
||||
2398
drizzle/meta/0019_snapshot.json
Normal file
@@ -1,139 +1,146 @@
|
||||
{
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "7",
|
||||
"when": 1762993507299,
|
||||
"tag": "0000_flashy_manta",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"version": "7",
|
||||
"when": 1765199006435,
|
||||
"tag": "0001_young_mister_fear",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"version": "7",
|
||||
"when": 1765200545692,
|
||||
"tag": "0002_slimy_flatman",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"version": "7",
|
||||
"when": 1767102605526,
|
||||
"tag": "0003_green_korg",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"version": "7",
|
||||
"when": 1767104066872,
|
||||
"tag": "0004_acoustic_mach_iv",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"version": "7",
|
||||
"when": 1767106121811,
|
||||
"tag": "0005_adorable_bruce_banner",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"version": "7",
|
||||
"when": 1767107487318,
|
||||
"tag": "0006_youthful_mister_fear",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"version": "7",
|
||||
"when": 1767118780033,
|
||||
"tag": "0007_sturdy_kate_bishop",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"version": "7",
|
||||
"when": 1767125796314,
|
||||
"tag": "0008_fat_stick",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"version": "7",
|
||||
"when": 1768925100873,
|
||||
"tag": "0009_add_dashboard_widgets",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"version": "7",
|
||||
"when": 1769369834242,
|
||||
"tag": "0010_lame_psynapse",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"version": "7",
|
||||
"when": 1769447087678,
|
||||
"tag": "0011_remove_unused_inbox_columns",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"version": "7",
|
||||
"when": 1769533200000,
|
||||
"tag": "0012_rename_tables_to_portuguese",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"version": "7",
|
||||
"when": 1769523352777,
|
||||
"tag": "0013_fancy_rick_jones",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"version": "7",
|
||||
"when": 1769619226903,
|
||||
"tag": "0014_yielding_jack_flag",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"version": "7",
|
||||
"when": 1770332054481,
|
||||
"tag": "0015_concerned_kat_farrell",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"version": "7",
|
||||
"when": 1771166328908,
|
||||
"tag": "0016_complete_randall",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"version": "7",
|
||||
"when": 1772400510326,
|
||||
"tag": "0017_previous_warstar",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"version": "7",
|
||||
"when": 1773020417482,
|
||||
"tag": "0018_rainy_epoch",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "7",
|
||||
"when": 1762993507299,
|
||||
"tag": "0000_flashy_manta",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"version": "7",
|
||||
"when": 1765199006435,
|
||||
"tag": "0001_young_mister_fear",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"version": "7",
|
||||
"when": 1765200545692,
|
||||
"tag": "0002_slimy_flatman",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"version": "7",
|
||||
"when": 1767102605526,
|
||||
"tag": "0003_green_korg",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"version": "7",
|
||||
"when": 1767104066872,
|
||||
"tag": "0004_acoustic_mach_iv",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"version": "7",
|
||||
"when": 1767106121811,
|
||||
"tag": "0005_adorable_bruce_banner",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"version": "7",
|
||||
"when": 1767107487318,
|
||||
"tag": "0006_youthful_mister_fear",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"version": "7",
|
||||
"when": 1767118780033,
|
||||
"tag": "0007_sturdy_kate_bishop",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"version": "7",
|
||||
"when": 1767125796314,
|
||||
"tag": "0008_fat_stick",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"version": "7",
|
||||
"when": 1768925100873,
|
||||
"tag": "0009_add_dashboard_widgets",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"version": "7",
|
||||
"when": 1769369834242,
|
||||
"tag": "0010_lame_psynapse",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"version": "7",
|
||||
"when": 1769447087678,
|
||||
"tag": "0011_remove_unused_inbox_columns",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"version": "7",
|
||||
"when": 1769533200000,
|
||||
"tag": "0012_rename_tables_to_portuguese",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"version": "7",
|
||||
"when": 1769523352777,
|
||||
"tag": "0013_fancy_rick_jones",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"version": "7",
|
||||
"when": 1769619226903,
|
||||
"tag": "0014_yielding_jack_flag",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"version": "7",
|
||||
"when": 1770332054481,
|
||||
"tag": "0015_concerned_kat_farrell",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"version": "7",
|
||||
"when": 1771166328908,
|
||||
"tag": "0016_complete_randall",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"version": "7",
|
||||
"when": 1772400510326,
|
||||
"tag": "0017_previous_warstar",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"version": "7",
|
||||
"when": 1773020417482,
|
||||
"tag": "0018_rainy_epoch",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"version": "7",
|
||||
"when": 1773265586360,
|
||||
"tag": "0019_parched_mephistopheles",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from "./actions";
|
||||
export * from "./calendario";
|
||||
export * from "./relatorios";
|
||||
@@ -19,6 +19,85 @@ const nextConfig: NextConfig = {
|
||||
devIndicators: {
|
||||
position: "bottom-right",
|
||||
},
|
||||
async redirects() {
|
||||
return [
|
||||
{ source: "/ajustes", destination: "/settings", permanent: true },
|
||||
{ source: "/anotacoes", destination: "/notes", permanent: true },
|
||||
{ source: "/calendario", destination: "/calendar", permanent: true },
|
||||
{ source: "/cartoes", destination: "/cards", permanent: true },
|
||||
{
|
||||
source: "/accounts/:accountId/extrato",
|
||||
destination: "/accounts/:accountId/statement",
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: "/cartoes/:cartaoId/fatura",
|
||||
destination: "/cards/:cartaoId/invoice",
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: "/cards/:cardId/fatura",
|
||||
destination: "/cards/:cardId/invoice",
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: "/categorias/historico",
|
||||
destination: "/categories/history",
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: "/categorias/:categoryId",
|
||||
destination: "/categories/:categoryId",
|
||||
permanent: true,
|
||||
},
|
||||
{ source: "/categorias", destination: "/categories", permanent: true },
|
||||
{ source: "/contas", destination: "/accounts", permanent: true },
|
||||
{
|
||||
source: "/contas/:contaId/extrato",
|
||||
destination: "/accounts/:contaId/statement",
|
||||
permanent: true,
|
||||
},
|
||||
{ source: "/lancamentos", destination: "/transactions", permanent: true },
|
||||
{ source: "/orcamentos", destination: "/budgets", permanent: true },
|
||||
{ source: "/pagadores", destination: "/payers", permanent: true },
|
||||
{
|
||||
source: "/pagadores/:pagadorId",
|
||||
destination: "/payers/:pagadorId",
|
||||
permanent: true,
|
||||
},
|
||||
{ source: "/pre-lancamentos", destination: "/inbox", permanent: true },
|
||||
{
|
||||
source: "/relatorios",
|
||||
destination: "/reports/category-trends",
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: "/relatorios/analise-parcelas",
|
||||
destination: "/reports/installment-analysis",
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: "/relatorios/estabelecimentos",
|
||||
destination: "/reports/establishments",
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: "/relatorios/tendencias",
|
||||
destination: "/reports/category-trends",
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: "/relatorios/uso-cartoes",
|
||||
destination: "/reports/card-usage",
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: "/changelog",
|
||||
destination: "/settings/changelog",
|
||||
permanent: true,
|
||||
},
|
||||
];
|
||||
},
|
||||
// Headers for Safari compatibility
|
||||
async headers() {
|
||||
return [
|
||||
|
||||
20
package.json
@@ -27,14 +27,14 @@
|
||||
"docker:rebuild": "docker compose up --build --force-recreate"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "^3.0.58",
|
||||
"@ai-sdk/google": "^3.0.43",
|
||||
"@ai-sdk/openai": "^3.0.41",
|
||||
"@ai-sdk/anthropic": "^3.0.60",
|
||||
"@ai-sdk/google": "^3.0.47",
|
||||
"@ai-sdk/openai": "^3.0.45",
|
||||
"@better-auth/passkey": "^1.5.4",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@openrouter/ai-sdk-provider": "^2.2.3",
|
||||
"@openrouter/ai-sdk-provider": "^2.2.5",
|
||||
"@radix-ui/react-alert-dialog": "1.1.15",
|
||||
"@radix-ui/react-avatar": "1.1.11",
|
||||
"@radix-ui/react-checkbox": "1.3.3",
|
||||
@@ -58,8 +58,8 @@
|
||||
"@tanstack/react-table": "8.21.3",
|
||||
"@vercel/analytics": "^1.6.1",
|
||||
"@vercel/speed-insights": "^1.3.1",
|
||||
"ai": "^6.0.116",
|
||||
"better-auth": "1.4.19",
|
||||
"ai": "^6.0.124",
|
||||
"better-auth": "1.5.4",
|
||||
"class-variance-authority": "0.7.1",
|
||||
"clsx": "2.1.1",
|
||||
"cmdk": "^1.1.1",
|
||||
@@ -69,12 +69,12 @@
|
||||
"jspdf-autotable": "^5.0.7",
|
||||
"next": "16.1.6",
|
||||
"next-themes": "0.4.6",
|
||||
"pg": "8.19.0",
|
||||
"pg": "8.20.0",
|
||||
"radix-ui": "^1.4.3",
|
||||
"react": "19.2.4",
|
||||
"react-day-picker": "^9.14.0",
|
||||
"react-dom": "19.2.4",
|
||||
"recharts": "3.7.0",
|
||||
"recharts": "3.8.0",
|
||||
"resend": "^6.9.3",
|
||||
"sonner": "2.0.7",
|
||||
"tailwind-merge": "3.5.0",
|
||||
@@ -83,9 +83,9 @@
|
||||
"zod": "4.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.4.4",
|
||||
"@biomejs/biome": "2.4.6",
|
||||
"@tailwindcss/postcss": "4.2.1",
|
||||
"@types/node": "25.3.2",
|
||||
"@types/node": "25.4.0",
|
||||
"@types/pg": "^8.18.0",
|
||||
"@types/react": "19.2.14",
|
||||
"@types/react-dom": "19.2.3",
|
||||
|
||||
1133
pnpm-lock.yaml
generated
2
proxy.ts
@@ -1,5 +1,5 @@
|
||||
import { type NextRequest, NextResponse } from "next/server";
|
||||
import { auth } from "@/lib/auth/config";
|
||||
import { auth } from "@/shared/lib/auth/config";
|
||||
|
||||
// Rotas protegidas que requerem autenticação
|
||||
const PROTECTED_ROUTES = [
|
||||
|
||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 163 KiB |
|
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 178 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 162 KiB |
|
Before Width: | Height: | Size: 169 KiB After Width: | Height: | Size: 169 KiB |
|
Before Width: | Height: | Size: 262 KiB After Width: | Height: | Size: 262 KiB |
|
Before Width: | Height: | Size: 272 KiB After Width: | Height: | Size: 272 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
@@ -1,4 +1,4 @@
|
||||
import { LoginForm } from "@/components/auth/login-form";
|
||||
import { LoginForm } from "@/features/auth/components/login-form";
|
||||
|
||||
export default function LoginPage() {
|
||||
return (
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SignupForm } from "@/components/auth/signup-form";
|
||||
import { SignupForm } from "@/features/auth/components/signup-form";
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
@@ -2,8 +2,8 @@ import {
|
||||
AccountStatementCardSkeleton,
|
||||
FilterSkeleton,
|
||||
TransactionsTableSkeleton,
|
||||
} from "@/components/shared/skeletons";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
} from "@/shared/components/skeletons";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
/**
|
||||
* Loading state para a página de extrato de conta
|
||||
@@ -1,37 +1,39 @@
|
||||
import { RiPencilLine } from "@remixicon/react";
|
||||
import { notFound } from "next/navigation";
|
||||
import { fetchUserPreferences } from "@/app/(dashboard)/ajustes/data";
|
||||
import { getRecentEstablishmentsAction } from "@/app/(dashboard)/lancamentos/actions";
|
||||
import { AccountDialog } from "@/components/contas/account-dialog";
|
||||
import { AccountStatementCard } from "@/components/contas/account-statement-card";
|
||||
import type { Account } from "@/components/contas/types";
|
||||
import { LancamentosPage as LancamentosSection } from "@/components/lancamentos/page/lancamentos-page";
|
||||
import MonthNavigation from "@/components/month-picker/month-navigation";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
import { AccountDialog } from "@/features/accounts/components/account-dialog";
|
||||
import { AccountStatementCard } from "@/features/accounts/components/account-statement-card";
|
||||
import type { Account } from "@/features/accounts/components/types";
|
||||
import {
|
||||
fetchAccountData,
|
||||
fetchAccountLancamentos,
|
||||
fetchAccountSummary,
|
||||
} from "@/features/accounts/statement-queries";
|
||||
import { fetchUserPreferences } from "@/features/settings/queries";
|
||||
import { LancamentosPage as LancamentosSection } from "@/features/transactions/components/page/transactions-page";
|
||||
import {
|
||||
buildLancamentoWhere,
|
||||
buildOptionSets,
|
||||
buildSluggedFilters,
|
||||
buildSlugMaps,
|
||||
extractLancamentoSearchFilters,
|
||||
fetchLancamentoFilterSources,
|
||||
getSingleParam,
|
||||
mapLancamentosData,
|
||||
type ResolvedSearchParams,
|
||||
} from "@/lib/lancamentos/page-helpers";
|
||||
import { loadLogoOptions } from "@/lib/logo/options";
|
||||
import { parsePeriodParam } from "@/lib/utils/period";
|
||||
} from "@/features/transactions/page-helpers";
|
||||
import {
|
||||
fetchAccountData,
|
||||
fetchAccountLancamentos,
|
||||
fetchAccountSummary,
|
||||
} from "./data";
|
||||
fetchLancamentoFilterSources,
|
||||
fetchRecentEstablishments,
|
||||
} from "@/features/transactions/queries";
|
||||
import MonthNavigation from "@/shared/components/month-picker/month-navigation";
|
||||
import { Button } from "@/shared/components/ui/button";
|
||||
import { getUserId } from "@/shared/lib/auth/server";
|
||||
import { loadLogoOptions } from "@/shared/lib/logo/options";
|
||||
import { parsePeriodParam } from "@/shared/utils/period";
|
||||
|
||||
type PageSearchParams = Promise<ResolvedSearchParams>;
|
||||
|
||||
type PageProps = {
|
||||
params: Promise<{ contaId: string }>;
|
||||
params: Promise<{ accountId: string }>;
|
||||
searchParams?: PageSearchParams;
|
||||
};
|
||||
|
||||
@@ -39,7 +41,7 @@ const capitalize = (value: string) =>
|
||||
value.length > 0 ? value[0]?.toUpperCase().concat(value.slice(1)) : value;
|
||||
|
||||
export default async function Page({ params, searchParams }: PageProps) {
|
||||
const { contaId } = await params;
|
||||
const { accountId: contaId } = await params;
|
||||
const userId = await getUserId();
|
||||
const resolvedSearchParams = searchParams ? await searchParams : undefined;
|
||||
|
||||
@@ -68,7 +70,7 @@ export default async function Page({ params, searchParams }: PageProps) {
|
||||
fetchLancamentoFilterSources(userId),
|
||||
loadLogoOptions(),
|
||||
fetchAccountSummary(userId, contaId, selectedPeriod),
|
||||
getRecentEstablishmentsAction(),
|
||||
fetchRecentEstablishments(userId),
|
||||
fetchUserPreferences(userId),
|
||||
]);
|
||||
const sluggedFilters = buildSluggedFilters(filterSources);
|
||||
@@ -1,5 +1,5 @@
|
||||
import { RiBankLine } from "@remixicon/react";
|
||||
import PageDescription from "@/components/shared/page-description";
|
||||
import PageDescription from "@/shared/components/page-description";
|
||||
|
||||
export const metadata = {
|
||||
title: "Contas | OpenMonetis",
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
export default function ContasLoading() {
|
||||
return (
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AccountsPage } from "@/components/contas/accounts-page";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
import { fetchAllAccountsForUser } from "./data";
|
||||
import { AccountsPage } from "@/features/accounts/components/accounts-page";
|
||||
import { fetchAllAccountsForUser } from "@/features/accounts/queries";
|
||||
import { getUserId } from "@/shared/lib/auth/server";
|
||||
|
||||
export default async function Page() {
|
||||
const userId = await getUserId();
|
||||
@@ -1,5 +1,5 @@
|
||||
import { RiBarChart2Line } from "@remixicon/react";
|
||||
import PageDescription from "@/components/shared/page-description";
|
||||
import PageDescription from "@/shared/components/page-description";
|
||||
|
||||
export const metadata = {
|
||||
title: "Orçamentos | OpenMonetis",
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
/**
|
||||
* Loading state para a página de orçamentos
|
||||
@@ -1,8 +1,8 @@
|
||||
import MonthNavigation from "@/components/month-picker/month-navigation";
|
||||
import { BudgetsPage } from "@/components/orcamentos/budgets-page";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
import { parsePeriodParam } from "@/lib/utils/period";
|
||||
import { fetchBudgetsForUser } from "./data";
|
||||
import { BudgetsPage } from "@/features/budgets/components/budgets-page";
|
||||
import { fetchBudgetsForUser } from "@/features/budgets/queries";
|
||||
import MonthNavigation from "@/shared/components/month-picker/month-navigation";
|
||||
import { getUserId } from "@/shared/lib/auth/server";
|
||||
import { parsePeriodParam } from "@/shared/utils/period";
|
||||
|
||||
type PageSearchParams = Promise<Record<string, string | string[] | undefined>>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { RiCalendarEventLine } from "@remixicon/react";
|
||||
import PageDescription from "@/components/shared/page-description";
|
||||
import PageDescription from "@/shared/components/page-description";
|
||||
|
||||
export const metadata = {
|
||||
title: "Calendário | OpenMonetis",
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
/**
|
||||
* Loading state para a página de calendário
|
||||
@@ -1,13 +1,13 @@
|
||||
import { MonthlyCalendar } from "@/components/calendario/monthly-calendar";
|
||||
import MonthNavigation from "@/components/month-picker/month-navigation";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
import { MonthlyCalendar } from "@/features/calendar/components/monthly-calendar";
|
||||
import { fetchCalendarData } from "@/features/calendar/queries";
|
||||
import {
|
||||
getSingleParam,
|
||||
type ResolvedSearchParams,
|
||||
} from "@/lib/lancamentos/page-helpers";
|
||||
import type { CalendarPeriod } from "@/lib/types/calendario";
|
||||
import { parsePeriodParam } from "@/lib/utils/period";
|
||||
import { fetchCalendarData } from "./data";
|
||||
} from "@/features/transactions/page-helpers";
|
||||
import MonthNavigation from "@/shared/components/month-picker/month-navigation";
|
||||
import { getUserId } from "@/shared/lib/auth/server";
|
||||
import type { CalendarPeriod } from "@/shared/lib/types/calendar";
|
||||
import { parsePeriodParam } from "@/shared/utils/period";
|
||||
|
||||
type PageSearchParams = Promise<ResolvedSearchParams>;
|
||||
|
||||
@@ -2,8 +2,8 @@ import {
|
||||
FilterSkeleton,
|
||||
InvoiceSummaryCardSkeleton,
|
||||
TransactionsTableSkeleton,
|
||||
} from "@/components/shared/skeletons";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
} from "@/shared/components/skeletons";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
/**
|
||||
* Loading state para a página de fatura de cartão
|
||||
@@ -1,39 +1,45 @@
|
||||
import { RiPencilLine } from "@remixicon/react";
|
||||
import { notFound } from "next/navigation";
|
||||
import { fetchUserPreferences } from "@/app/(dashboard)/ajustes/data";
|
||||
import { getRecentEstablishmentsAction } from "@/app/(dashboard)/lancamentos/actions";
|
||||
import { CardDialog } from "@/components/cartoes/card-dialog";
|
||||
import type { Card } from "@/components/cartoes/types";
|
||||
import { InvoiceSummaryCard } from "@/components/faturas/invoice-summary-card";
|
||||
import { LancamentosPage as LancamentosSection } from "@/components/lancamentos/page/lancamentos-page";
|
||||
import MonthNavigation from "@/components/month-picker/month-navigation";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import type { Conta } from "@/db/schema";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
import { CardDialog } from "@/features/cards/components/card-dialog";
|
||||
import type { Card } from "@/features/cards/components/types";
|
||||
import { InvoiceSummaryCard } from "@/features/invoices/components/invoice-summary-card";
|
||||
import {
|
||||
fetchCardData,
|
||||
fetchCardLancamentos,
|
||||
fetchInvoiceData,
|
||||
} from "@/features/invoices/queries";
|
||||
import { fetchUserPreferences } from "@/features/settings/queries";
|
||||
import { LancamentosPage as LancamentosSection } from "@/features/transactions/components/page/transactions-page";
|
||||
import {
|
||||
buildLancamentoWhere,
|
||||
buildOptionSets,
|
||||
buildSluggedFilters,
|
||||
buildSlugMaps,
|
||||
extractLancamentoSearchFilters,
|
||||
fetchLancamentoFilterSources,
|
||||
getSingleParam,
|
||||
mapLancamentosData,
|
||||
type ResolvedSearchParams,
|
||||
} from "@/lib/lancamentos/page-helpers";
|
||||
import { loadLogoOptions } from "@/lib/logo/options";
|
||||
import { parsePeriodParam } from "@/lib/utils/period";
|
||||
import { fetchCardData, fetchCardLancamentos, fetchInvoiceData } from "./data";
|
||||
} from "@/features/transactions/page-helpers";
|
||||
import {
|
||||
fetchLancamentoFilterSources,
|
||||
fetchRecentEstablishments,
|
||||
} from "@/features/transactions/queries";
|
||||
import MonthNavigation from "@/shared/components/month-picker/month-navigation";
|
||||
import { Button } from "@/shared/components/ui/button";
|
||||
import { getUserId } from "@/shared/lib/auth/server";
|
||||
import { loadLogoOptions } from "@/shared/lib/logo/options";
|
||||
import { parsePeriodParam } from "@/shared/utils/period";
|
||||
|
||||
type PageSearchParams = Promise<ResolvedSearchParams>;
|
||||
|
||||
type PageProps = {
|
||||
params: Promise<{ cartaoId: string }>;
|
||||
params: Promise<{ cardId: string }>;
|
||||
searchParams?: PageSearchParams;
|
||||
};
|
||||
|
||||
export default async function Page({ params, searchParams }: PageProps) {
|
||||
const { cartaoId } = await params;
|
||||
const { cardId: cartaoId } = await params;
|
||||
const userId = await getUserId();
|
||||
const resolvedSearchParams = searchParams ? await searchParams : undefined;
|
||||
|
||||
@@ -62,7 +68,7 @@ export default async function Page({ params, searchParams }: PageProps) {
|
||||
fetchLancamentoFilterSources(userId),
|
||||
loadLogoOptions(),
|
||||
fetchInvoiceData(userId, cartaoId, selectedPeriod),
|
||||
getRecentEstablishmentsAction(),
|
||||
fetchRecentEstablishments(userId),
|
||||
fetchUserPreferences(userId),
|
||||
]);
|
||||
const sluggedFilters = buildSluggedFilters(filterSources);
|
||||
@@ -99,6 +105,7 @@ export default async function Page({ params, searchParams }: PageProps) {
|
||||
const accountOptions = filterSources.contaRows.map((conta: Conta) => ({
|
||||
id: conta.id,
|
||||
name: conta.name ?? "Conta",
|
||||
logo: conta.logo ?? null,
|
||||
}));
|
||||
|
||||
const contaName =
|
||||
@@ -1,5 +1,5 @@
|
||||
import { RiBankCard2Line } from "@remixicon/react";
|
||||
import PageDescription from "@/components/shared/page-description";
|
||||
import PageDescription from "@/shared/components/page-description";
|
||||
|
||||
export const metadata = {
|
||||
title: "Cartões | OpenMonetis",
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
export default function CartoesLoading() {
|
||||
return (
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CardsPage } from "@/components/cartoes/cards-page";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
import { fetchAllCardsForUser } from "./data";
|
||||
import { CardsPage } from "@/features/cards/components/cards-page";
|
||||
import { fetchAllCardsForUser } from "@/features/cards/queries";
|
||||
import { getUserId } from "@/shared/lib/auth/server";
|
||||
|
||||
export default async function Page() {
|
||||
const userId = await getUserId();
|
||||
@@ -1,17 +1,19 @@
|
||||
import { notFound } from "next/navigation";
|
||||
import { fetchUserPreferences } from "@/app/(dashboard)/ajustes/data";
|
||||
import { getRecentEstablishmentsAction } from "@/app/(dashboard)/lancamentos/actions";
|
||||
import { CategoryDetailHeader } from "@/components/categorias/category-detail-header";
|
||||
import { LancamentosPage } from "@/components/lancamentos/page/lancamentos-page";
|
||||
import MonthNavigation from "@/components/month-picker/month-navigation";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
import { fetchCategoryDetails } from "@/lib/dashboard/categories/category-details";
|
||||
import { CategoryDetailHeader } from "@/features/categories/components/category-detail-header";
|
||||
import { fetchCategoryDetails } from "@/features/dashboard/categories/category-details-queries";
|
||||
import { fetchUserPreferences } from "@/features/settings/queries";
|
||||
import { LancamentosPage } from "@/features/transactions/components/page/transactions-page";
|
||||
import {
|
||||
buildOptionSets,
|
||||
buildSluggedFilters,
|
||||
} from "@/features/transactions/page-helpers";
|
||||
import {
|
||||
fetchLancamentoFilterSources,
|
||||
} from "@/lib/lancamentos/page-helpers";
|
||||
import { displayPeriod, parsePeriodParam } from "@/lib/utils/period";
|
||||
fetchRecentEstablishments,
|
||||
} from "@/features/transactions/queries";
|
||||
import MonthNavigation from "@/shared/components/month-picker/month-navigation";
|
||||
import { getUserId } from "@/shared/lib/auth/server";
|
||||
import { displayPeriod, parsePeriodParam } from "@/shared/utils/period";
|
||||
|
||||
type PageSearchParams = Promise<Record<string, string | string[] | undefined>>;
|
||||
|
||||
@@ -41,7 +43,7 @@ export default async function Page({ params, searchParams }: PageProps) {
|
||||
await Promise.all([
|
||||
fetchCategoryDetails(userId, categoryId, selectedPeriod),
|
||||
fetchLancamentoFilterSources(userId),
|
||||
getRecentEstablishmentsAction(),
|
||||
fetchRecentEstablishments(userId),
|
||||
fetchUserPreferences(userId),
|
||||
]);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Card, CardContent } from "@/shared/components/ui/card";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
export default function Loading() {
|
||||
return (
|
||||
17
src/app/(dashboard)/categories/history/page.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import { fetchCategoryHistory } from "@/features/dashboard/categories/category-history-queries";
|
||||
import { CategoryHistoryWidget } from "@/features/dashboard/components/category-history-widget";
|
||||
import { getUser } from "@/shared/lib/auth/server";
|
||||
import { getCurrentPeriod } from "@/shared/utils/period";
|
||||
|
||||
export default async function HistoricoCategoriasPage() {
|
||||
const user = await getUser();
|
||||
const currentPeriod = getCurrentPeriod();
|
||||
|
||||
const data = await fetchCategoryHistory(user.id, currentPeriod);
|
||||
|
||||
return (
|
||||
<main>
|
||||
<CategoryHistoryWidget data={data} />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { RiPriceTag3Line } from "@remixicon/react";
|
||||
import PageDescription from "@/components/shared/page-description";
|
||||
import PageDescription from "@/shared/components/page-description";
|
||||
|
||||
export const metadata = {
|
||||
title: "Categorias | OpenMonetis",
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Card, CardContent } from "@/shared/components/ui/card";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
export default function CategoriasLoading() {
|
||||
return (
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CategoriesPage } from "@/components/categorias/categories-page";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
import { fetchCategoriesForUser } from "./data";
|
||||
import { CategoriesPage } from "@/features/categories/components/categories-page";
|
||||
import { fetchCategoriesForUser } from "@/features/categories/queries";
|
||||
import { getUserId } from "@/shared/lib/auth/server";
|
||||
|
||||
export default async function Page() {
|
||||
const userId = await getUserId();
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DashboardGridSkeleton } from "@/components/shared/skeletons";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { DashboardGridSkeleton } from "@/shared/components/skeletons";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
export default function DashboardLoading() {
|
||||
return (
|
||||
@@ -1,17 +1,21 @@
|
||||
import { DashboardGridEditable } from "@/components/dashboard/dashboard-grid-editable";
|
||||
import { DashboardMetricsCards } from "@/components/dashboard/dashboard-metrics-cards";
|
||||
import { DashboardWelcome } from "@/components/dashboard/dashboard-welcome";
|
||||
import MonthNavigation from "@/components/month-picker/month-navigation";
|
||||
import { getUser } from "@/lib/auth/server";
|
||||
import { fetchDashboardData } from "@/lib/dashboard/fetch-dashboard-data";
|
||||
import { DashboardGridEditable } from "@/features/dashboard/components/dashboard-grid-editable";
|
||||
import { DashboardMetricsCards } from "@/features/dashboard/components/dashboard-metrics-cards";
|
||||
import { DashboardWelcome } from "@/features/dashboard/components/dashboard-welcome";
|
||||
import { fetchDashboardData } from "@/features/dashboard/fetch-dashboard-data";
|
||||
import { fetchUserDashboardPreferences } from "@/features/dashboard/preferences-queries";
|
||||
import { triggerRecurringGeneration } from "@/features/recurring/trigger-recurring-generation";
|
||||
import {
|
||||
buildOptionSets,
|
||||
buildSluggedFilters,
|
||||
getSingleParam,
|
||||
} from "@/features/transactions/page-helpers";
|
||||
import {
|
||||
fetchLancamentoFilterSources,
|
||||
} from "@/lib/lancamentos/page-helpers";
|
||||
import { parsePeriodParam } from "@/lib/utils/period";
|
||||
import { getRecentEstablishmentsAction } from "../lancamentos/actions";
|
||||
import { fetchUserDashboardPreferences } from "./data";
|
||||
fetchRecentEstablishments,
|
||||
} from "@/features/transactions/queries";
|
||||
import MonthNavigation from "@/shared/components/month-picker/month-navigation";
|
||||
import { getUser } from "@/shared/lib/auth/server";
|
||||
import { parsePeriodParam } from "@/shared/utils/period";
|
||||
|
||||
type PageSearchParams = Promise<Record<string, string | string[] | undefined>>;
|
||||
|
||||
@@ -19,17 +23,9 @@ type PageProps = {
|
||||
searchParams?: PageSearchParams;
|
||||
};
|
||||
|
||||
const getSingleParam = (
|
||||
params: Record<string, string | string[] | undefined> | undefined,
|
||||
key: string,
|
||||
) => {
|
||||
const value = params?.[key];
|
||||
if (!value) return null;
|
||||
return Array.isArray(value) ? (value[0] ?? null) : value;
|
||||
};
|
||||
|
||||
export default async function Page({ searchParams }: PageProps) {
|
||||
const user = await getUser();
|
||||
await triggerRecurringGeneration(user.id);
|
||||
const resolvedSearchParams = searchParams ? await searchParams : undefined;
|
||||
const periodoParam = getSingleParam(resolvedSearchParams, "periodo");
|
||||
const { period: selectedPeriod } = parsePeriodParam(periodoParam);
|
||||
@@ -39,7 +35,7 @@ export default async function Page({ searchParams }: PageProps) {
|
||||
fetchDashboardData(user.id, selectedPeriod),
|
||||
fetchUserDashboardPreferences(user.id),
|
||||
fetchLancamentoFilterSources(user.id),
|
||||
getRecentEstablishmentsAction(),
|
||||
fetchRecentEstablishments(user.id),
|
||||
]);
|
||||
const { dashboardWidgets } = preferences;
|
||||
const sluggedFilters = buildSluggedFilters(filterSources);
|
||||
@@ -1,5 +1,5 @@
|
||||
import { RiAtLine } from "@remixicon/react";
|
||||
import PageDescription from "@/components/shared/page-description";
|
||||
import PageDescription from "@/shared/components/page-description";
|
||||
|
||||
export const metadata = {
|
||||
title: "Pré-Lançamentos | OpenMonetis",
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Card } from "@/shared/components/ui/card";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
export default function Loading() {
|
||||
return (
|
||||
@@ -1,6 +1,10 @@
|
||||
import { InboxPage } from "@/components/pre-lancamentos/inbox-page";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
import { fetchAppLogoMap, fetchInboxDialogData, fetchInboxItems } from "./data";
|
||||
import { InboxPage } from "@/features/inbox/components/inbox-page";
|
||||
import {
|
||||
fetchAppLogoMap,
|
||||
fetchInboxDialogData,
|
||||
fetchInboxItems,
|
||||
} from "@/features/inbox/queries";
|
||||
import { getUserId } from "@/shared/lib/auth/server";
|
||||
|
||||
export default async function Page() {
|
||||
const userId = await getUserId();
|
||||
@@ -1,5 +1,5 @@
|
||||
import { RiSparklingLine } from "@remixicon/react";
|
||||
import PageDescription from "@/components/shared/page-description";
|
||||
import PageDescription from "@/shared/components/page-description";
|
||||
|
||||
export const metadata = {
|
||||
title: "Insights | OpenMonetis",
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
/**
|
||||
* Loading state para a página de insights com IA
|
||||
@@ -1,6 +1,6 @@
|
||||
import { InsightsPage } from "@/components/insights/insights-page";
|
||||
import MonthNavigation from "@/components/month-picker/month-navigation";
|
||||
import { parsePeriodParam } from "@/lib/utils/period";
|
||||
import { InsightsPage } from "@/features/insights/components/insights-page";
|
||||
import MonthNavigation from "@/shared/components/month-picker/month-navigation";
|
||||
import { parsePeriodParam } from "@/shared/utils/period";
|
||||
|
||||
type PageSearchParams = Promise<Record<string, string | string[] | undefined>>;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { AppNavbar } from "@/components/navigation/navbar/app-navbar";
|
||||
import { FontProvider } from "@/components/providers/font-provider";
|
||||
import { PrivacyProvider } from "@/components/providers/privacy-provider";
|
||||
import { getUserSession } from "@/lib/auth/server";
|
||||
import { fetchDashboardNotifications } from "@/lib/dashboard/notifications";
|
||||
import { fetchPagadoresWithAccess } from "@/lib/pagadores/access";
|
||||
import { PAGADOR_ROLE_ADMIN } from "@/lib/pagadores/constants";
|
||||
import { fetchUserFontPreferences } from "@/lib/preferences/fonts";
|
||||
import { parsePeriodParam } from "@/lib/utils/period";
|
||||
import { fetchPendingInboxCount } from "./pre-lancamentos/data";
|
||||
import { fetchDashboardNotifications } from "@/features/dashboard/notifications-queries";
|
||||
import { fetchPendingInboxCount } from "@/features/inbox/queries";
|
||||
import { AppNavbar } from "@/shared/components/navigation/navbar/app-navbar";
|
||||
import { FontProvider } from "@/shared/components/providers/font-provider";
|
||||
import { PrivacyProvider } from "@/shared/components/providers/privacy-provider";
|
||||
import { getUserSession } from "@/shared/lib/auth/server";
|
||||
import { fetchPagadoresWithAccess } from "@/shared/lib/payers/access";
|
||||
import { PAGADOR_ROLE_ADMIN } from "@/shared/lib/payers/constants";
|
||||
import { fetchUserFontPreferences } from "@/shared/lib/preferences/fonts";
|
||||
import { parsePeriodParam } from "@/shared/utils/period";
|
||||
|
||||
export default async function DashboardLayout({
|
||||
children,
|
||||
@@ -36,16 +36,13 @@ export default async function DashboardLayout({
|
||||
const { period: currentPeriod } = parsePeriodParam(
|
||||
singlePeriodoParam ?? null,
|
||||
);
|
||||
const notificationsSnapshot = await fetchDashboardNotifications(
|
||||
session.user.id,
|
||||
currentPeriod,
|
||||
);
|
||||
|
||||
// Buscar contagem de pré-lançamentos pendentes e preferências de fonte
|
||||
const [preLancamentosCount, fontPrefs] = await Promise.all([
|
||||
fetchPendingInboxCount(session.user.id),
|
||||
fetchUserFontPreferences(session.user.id),
|
||||
]);
|
||||
// Buscar notificações, contagem de pré-lançamentos e preferências de fonte em paralelo
|
||||
const [notificationsSnapshot, preLancamentosCount, fontPrefs] =
|
||||
await Promise.all([
|
||||
fetchDashboardNotifications(session.user.id, currentPeriod),
|
||||
fetchPendingInboxCount(session.user.id),
|
||||
fetchUserFontPreferences(session.user.id),
|
||||
]);
|
||||
|
||||
return (
|
||||
<FontProvider
|
||||
@@ -1,5 +1,5 @@
|
||||
import { RiTodoLine } from "@remixicon/react";
|
||||
import PageDescription from "@/components/shared/page-description";
|
||||
import PageDescription from "@/shared/components/page-description";
|
||||
|
||||
export const metadata = {
|
||||
title: "Anotações | OpenMonetis",
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
/**
|
||||
* Loading state para a página de anotações
|
||||
@@ -1,6 +1,6 @@
|
||||
import { NotesPage } from "@/components/anotacoes/notes-page";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
import { fetchAllNotesForUser } from "./data";
|
||||
import { NotesPage } from "@/features/notes/components/notes-page";
|
||||
import { fetchAllNotesForUser } from "@/features/notes/queries";
|
||||
import { getUserId } from "@/shared/lib/auth/server";
|
||||
|
||||
export default async function Page() {
|
||||
const userId = await getUserId();
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
/**
|
||||
* Loading state para a página de detalhes do pagador.
|
||||
@@ -4,46 +4,52 @@ import {
|
||||
RiWallet3Line,
|
||||
} from "@remixicon/react";
|
||||
import { notFound } from "next/navigation";
|
||||
import { fetchUserPreferences } from "@/app/(dashboard)/ajustes/data";
|
||||
import { getRecentEstablishmentsAction } from "@/app/(dashboard)/lancamentos/actions";
|
||||
import { ExpandableWidgetCard } from "@/components/shared/expandable-widget-card";
|
||||
import { LancamentosPage as LancamentosSection } from "@/components/lancamentos/page/lancamentos-page";
|
||||
import type {
|
||||
ContaCartaoFilterOption,
|
||||
LancamentoFilterOption,
|
||||
LancamentoItem,
|
||||
SelectOption,
|
||||
} from "@/components/lancamentos/types";
|
||||
import MonthNavigation from "@/components/month-picker/month-navigation";
|
||||
import { PagadorCardUsageCard } from "@/components/pagadores/details/pagador-card-usage-card";
|
||||
import { PagadorHeaderCard } from "@/components/pagadores/details/pagador-header-card";
|
||||
import { PagadorHistoryCard } from "@/components/pagadores/details/pagador-history-card";
|
||||
import { PagadorInfoCard } from "@/components/pagadores/details/pagador-info-card";
|
||||
import { PagadorLeaveShareCard } from "@/components/pagadores/details/pagador-leave-share-card";
|
||||
import { PagadorMonthlySummaryCard } from "@/components/pagadores/details/pagador-monthly-summary-card";
|
||||
import { PagadorCardUsageCard } from "@/features/payers/components/details/payer-card-usage-card";
|
||||
import { PagadorHeaderCard } from "@/features/payers/components/details/payer-header-card";
|
||||
import { PagadorHistoryCard } from "@/features/payers/components/details/payer-history-card";
|
||||
import { PagadorInfoCard } from "@/features/payers/components/details/payer-info-card";
|
||||
import { PagadorLeaveShareCard } from "@/features/payers/components/details/payer-leave-share-card";
|
||||
import { PagadorMonthlySummaryCard } from "@/features/payers/components/details/payer-monthly-summary-card";
|
||||
import {
|
||||
PagadorBoletoCard,
|
||||
PagadorPaymentStatusCard,
|
||||
} from "@/components/pagadores/details/pagador-payment-method-cards";
|
||||
import { PagadorSharingCard } from "@/components/pagadores/details/pagador-sharing-card";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import type { pagadores } from "@/db/schema";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
} from "@/features/payers/components/details/payer-payment-method-cards";
|
||||
import { PagadorSharingCard } from "@/features/payers/components/details/payer-sharing-card";
|
||||
import {
|
||||
fetchCurrentUserShare,
|
||||
fetchPagadorLancamentos,
|
||||
fetchPagadorShares,
|
||||
} from "@/features/payers/detail-queries";
|
||||
import { buildReadOnlyOptionSets } from "@/features/payers/lib/build-readonly-option-sets";
|
||||
import { fetchUserPreferences } from "@/features/settings/queries";
|
||||
import { LancamentosPage as LancamentosSection } from "@/features/transactions/components/page/transactions-page";
|
||||
import {
|
||||
buildLancamentoWhere,
|
||||
buildOptionSets,
|
||||
buildSluggedFilters,
|
||||
buildSlugMaps,
|
||||
extractLancamentoSearchFilters,
|
||||
fetchLancamentoFilterSources,
|
||||
getSingleParam,
|
||||
type LancamentoSearchFilters,
|
||||
mapLancamentosData,
|
||||
type ResolvedSearchParams,
|
||||
type SluggedFilters,
|
||||
type SlugMaps,
|
||||
} from "@/lib/lancamentos/page-helpers";
|
||||
import { getPagadorAccess } from "@/lib/pagadores/access";
|
||||
} from "@/features/transactions/page-helpers";
|
||||
import {
|
||||
fetchLancamentoFilterSources,
|
||||
fetchRecentEstablishments,
|
||||
} from "@/features/transactions/queries";
|
||||
import { ExpandableWidgetCard } from "@/shared/components/expandable-widget-card";
|
||||
import MonthNavigation from "@/shared/components/month-picker/month-navigation";
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "@/shared/components/ui/tabs";
|
||||
import { getUserId } from "@/shared/lib/auth/server";
|
||||
import { getPagadorAccess } from "@/shared/lib/payers/access";
|
||||
import {
|
||||
fetchPagadorBoletoItems,
|
||||
fetchPagadorBoletoStats,
|
||||
@@ -52,18 +58,13 @@ import {
|
||||
fetchPagadorMonthlyBreakdown,
|
||||
fetchPagadorPaymentStatus,
|
||||
type PagadorCardUsageItem,
|
||||
} from "@/lib/pagadores/details";
|
||||
import { parsePeriodParam } from "@/lib/utils/period";
|
||||
import {
|
||||
fetchCurrentUserShare,
|
||||
fetchPagadorLancamentos,
|
||||
fetchPagadorShares,
|
||||
} from "./data";
|
||||
} from "@/shared/lib/payers/details";
|
||||
import { parsePeriodParam } from "@/shared/utils/period";
|
||||
|
||||
type PageSearchParams = Promise<ResolvedSearchParams>;
|
||||
|
||||
type PageProps = {
|
||||
params: Promise<{ pagadorId: string }>;
|
||||
params: Promise<{ payerId: string }>;
|
||||
searchParams?: PageSearchParams;
|
||||
};
|
||||
|
||||
@@ -90,7 +91,7 @@ const createEmptySlugMaps = (): SlugMaps => ({
|
||||
type OptionSet = ReturnType<typeof buildOptionSets>;
|
||||
|
||||
export default async function Page({ params, searchParams }: PageProps) {
|
||||
const { pagadorId } = await params;
|
||||
const { payerId: pagadorId } = await params;
|
||||
const userId = await getUserId();
|
||||
const resolvedSearchParams = searchParams ? await searchParams : undefined;
|
||||
|
||||
@@ -206,7 +207,7 @@ export default async function Page({ params, searchParams }: PageProps) {
|
||||
}),
|
||||
sharesPromise,
|
||||
currentUserSharePromise,
|
||||
getRecentEstablishmentsAction(),
|
||||
fetchRecentEstablishments(userId),
|
||||
fetchUserPreferences(userId),
|
||||
]);
|
||||
|
||||
@@ -403,90 +404,3 @@ export default async function Page({ params, searchParams }: PageProps) {
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
const normalizeOptionLabel = (
|
||||
value: string | null | undefined,
|
||||
fallback: string,
|
||||
) => (value?.trim().length ? value.trim() : fallback);
|
||||
|
||||
function buildReadOnlyOptionSets(
|
||||
items: LancamentoItem[],
|
||||
pagador: typeof pagadores.$inferSelect,
|
||||
): OptionSet {
|
||||
const pagadorLabel = normalizeOptionLabel(pagador.name, "Pagador");
|
||||
const pagadorOptions: SelectOption[] = [
|
||||
{
|
||||
value: pagador.id,
|
||||
label: pagadorLabel,
|
||||
slug: pagador.id,
|
||||
},
|
||||
];
|
||||
|
||||
const contaOptionsMap = new Map<string, SelectOption>();
|
||||
const cartaoOptionsMap = new Map<string, SelectOption>();
|
||||
const categoriaOptionsMap = new Map<string, SelectOption>();
|
||||
|
||||
items.forEach((item) => {
|
||||
if (item.contaId && !contaOptionsMap.has(item.contaId)) {
|
||||
contaOptionsMap.set(item.contaId, {
|
||||
value: item.contaId,
|
||||
label: normalizeOptionLabel(item.contaName, "Conta sem nome"),
|
||||
slug: item.contaId,
|
||||
});
|
||||
}
|
||||
if (item.cartaoId && !cartaoOptionsMap.has(item.cartaoId)) {
|
||||
cartaoOptionsMap.set(item.cartaoId, {
|
||||
value: item.cartaoId,
|
||||
label: normalizeOptionLabel(item.cartaoName, "Cartão sem nome"),
|
||||
slug: item.cartaoId,
|
||||
});
|
||||
}
|
||||
if (item.categoriaId && !categoriaOptionsMap.has(item.categoriaId)) {
|
||||
categoriaOptionsMap.set(item.categoriaId, {
|
||||
value: item.categoriaId,
|
||||
label: normalizeOptionLabel(item.categoriaName, "Categoria"),
|
||||
slug: item.categoriaId,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const contaOptions = Array.from(contaOptionsMap.values());
|
||||
const cartaoOptions = Array.from(cartaoOptionsMap.values());
|
||||
const categoriaOptions = Array.from(categoriaOptionsMap.values());
|
||||
|
||||
const pagadorFilterOptions: LancamentoFilterOption[] = [
|
||||
{ slug: pagador.id, label: pagadorLabel },
|
||||
];
|
||||
|
||||
const categoriaFilterOptions: LancamentoFilterOption[] = categoriaOptions.map(
|
||||
(option) => ({
|
||||
slug: option.value,
|
||||
label: option.label,
|
||||
}),
|
||||
);
|
||||
|
||||
const contaCartaoFilterOptions: ContaCartaoFilterOption[] = [
|
||||
...contaOptions.map((option) => ({
|
||||
slug: option.value,
|
||||
label: option.label,
|
||||
kind: "conta" as const,
|
||||
})),
|
||||
...cartaoOptions.map((option) => ({
|
||||
slug: option.value,
|
||||
label: option.label,
|
||||
kind: "cartao" as const,
|
||||
})),
|
||||
];
|
||||
|
||||
return {
|
||||
pagadorOptions,
|
||||
splitPagadorOptions: [],
|
||||
defaultPagadorId: pagador.id,
|
||||
contaOptions,
|
||||
cartaoOptions,
|
||||
categoriaOptions,
|
||||
pagadorFilterOptions,
|
||||
categoriaFilterOptions,
|
||||
contaCartaoFilterOptions,
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { RiGroupLine } from "@remixicon/react";
|
||||
import PageDescription from "@/components/shared/page-description";
|
||||
import PageDescription from "@/shared/components/page-description";
|
||||
|
||||
export const metadata = {
|
||||
title: "Pagadores | OpenMonetis",
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
/**
|
||||
* Loading state para a página de pagadores
|
||||
@@ -1,6 +1,6 @@
|
||||
import { PagadoresPage } from "@/components/pagadores/pagadores-page";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
import { fetchPagadoresForUser } from "./data";
|
||||
import { PagadoresPage } from "@/features/payers/components/payers-page";
|
||||
import { fetchPagadoresForUser } from "@/features/payers/queries";
|
||||
import { getUserId } from "@/shared/lib/auth/server";
|
||||
|
||||
export default async function Page() {
|
||||
const userId = await getUserId();
|
||||
@@ -1,5 +1,5 @@
|
||||
import { RiBankCard2Line } from "@remixicon/react";
|
||||
import PageDescription from "@/components/shared/page-description";
|
||||
import PageDescription from "@/shared/components/page-description";
|
||||
|
||||
export const metadata = {
|
||||
title: "Uso de Cartões | OpenMonetis",
|
||||