diff --git a/app/(authenticated)/dashboard/_components/summar-card.tsx b/app/(authenticated)/dashboard/_components/summar-card.tsx
new file mode 100644
index 0000000..61b8632
--- /dev/null
+++ b/app/(authenticated)/dashboard/_components/summar-card.tsx
@@ -0,0 +1,44 @@
+import AddTransactionButton from "@/app/_components/add-transaction-button";
+import { Card, CardContent, CardHeader } from "@/app/_components/ui/card";
+import { cn } from "@/app/_lib/utils";
+
+interface SummaryCardProps {
+ title: string;
+ amount: string;
+ icon: React.ReactNode;
+ size?: "sm" | "lg";
+}
+
+const SummaryCard = ({
+ title,
+ amount,
+ icon,
+ size = "sm",
+}: SummaryCardProps) => {
+ return (
+
+
+ {icon}
+
+ {title}
+
+
+
+
+ {Intl.NumberFormat("pt-BR", {
+ style: "currency",
+ currency: "BRL",
+ }).format(Number(amount))}
+
+ {size === "lg" && }
+
+
+ );
+};
+
+export default SummaryCard;
diff --git a/app/(authenticated)/dashboard/_components/summary-cards.tsx b/app/(authenticated)/dashboard/_components/summary-cards.tsx
new file mode 100644
index 0000000..e33a32b
--- /dev/null
+++ b/app/(authenticated)/dashboard/_components/summary-cards.tsx
@@ -0,0 +1,87 @@
+import {
+ PiggyBankIcon,
+ TrendingDownIcon,
+ TrendingUpIcon,
+ WalletIcon,
+} from "lucide-react";
+import SummaryCard from "./summar-card";
+import { db } from "@/app/_lib/prisma";
+
+interface SummaryCardsProps {
+ month: string;
+}
+
+const SummaryCards = async ({ month }: SummaryCardsProps) => {
+ const where = {
+ date: {
+ gte: new Date(`2024-${month}-01`),
+ lt: new Date(`2024-${month}-31`),
+ },
+ };
+
+ const deposits = await db.transactions.aggregate({
+ where: {
+ type: "DEPOSIT",
+ ...where,
+ },
+ _sum: {
+ amount: true,
+ },
+ });
+ const depositsTotal = deposits._sum.amount ?? 0;
+
+ const investments = await db.transactions.aggregate({
+ where: {
+ type: "INVESTMENT",
+ ...where,
+ },
+ _sum: {
+ amount: true,
+ },
+ });
+ const investmentsTotal = investments._sum.amount ?? 0;
+
+ const expenses = await db.transactions.aggregate({
+ where: {
+ type: "EXPENSE",
+ ...where,
+ },
+ _sum: {
+ amount: true,
+ },
+ });
+ const expensesTotal = expenses._sum.amount ?? 0;
+
+ const balance =
+ Number(depositsTotal) - Number(investmentsTotal) - Number(expensesTotal);
+
+ return (
+
+
}
+ size="lg"
+ />
+
+ }
+ />
+ }
+ />
+ }
+ />
+
+
+ );
+};
+
+export default SummaryCards;
diff --git a/app/(authenticated)/dashboard/_components/time-select.tsx b/app/(authenticated)/dashboard/_components/time-select.tsx
new file mode 100644
index 0000000..fd509e1
--- /dev/null
+++ b/app/(authenticated)/dashboard/_components/time-select.tsx
@@ -0,0 +1,57 @@
+"use client";
+
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/app/_components/ui/select";
+import { useRouter, useSearchParams } from "next/navigation";
+
+interface TimeSelectProps {
+ defaultValue?: string;
+}
+
+const MONTH_OPTIONS = [
+ { value: "1", label: "Janeiro" },
+ { value: "2", label: "Fevereiro" },
+ { value: "3", label: "Março" },
+ { value: "4", label: "Abril" },
+ { value: "5", label: "Maio" },
+ { value: "6", label: "Junho" },
+ { value: "7", label: "Julho" },
+ { value: "8", label: "Agosto" },
+ { value: "9", label: "Setembro" },
+ { value: "10", label: "Outubro" },
+ { value: "11", label: "Novembro" },
+ { value: "12", label: "Dezembro" },
+];
+
+const TimeSelect = ({ defaultValue = "1" }: TimeSelectProps) => {
+ const router = useRouter();
+ const searchParams = useSearchParams();
+
+ const handleMonthChange = (month: string) => {
+ const params = new URLSearchParams(searchParams);
+ params.set("month", month);
+ router.push(`/dashboard?${params.toString()}`);
+ };
+
+ return (
+
+ );
+};
+
+export default TimeSelect;
diff --git a/app/(authenticated)/dashboard/page.tsx b/app/(authenticated)/dashboard/page.tsx
new file mode 100644
index 0000000..25d871a
--- /dev/null
+++ b/app/(authenticated)/dashboard/page.tsx
@@ -0,0 +1,38 @@
+import { auth } from "@clerk/nextjs/server";
+import { redirect } from "next/navigation";
+import SummaryCards from "./_components/summary-cards";
+import TimeSelect from "./_components/time-select";
+
+interface HomeProps {
+ searchParams: {
+ month?: string;
+ };
+}
+
+const Home = async ({ searchParams: { month = "1" } }: HomeProps) => {
+ const { userId } = await auth();
+
+ if (!userId) {
+ redirect("/login");
+ }
+
+ // Validação do mês
+ const monthNumber = Number(month);
+ const isValidMonth = monthNumber >= 1 && monthNumber <= 12;
+
+ if (!isValidMonth) {
+ redirect("/dashboard?month=1");
+ }
+
+ return (
+
+ );
+};
+
+export default Home;
diff --git a/app/(authenticated)/page.tsx b/app/(authenticated)/page.tsx
deleted file mode 100644
index 499de4a..0000000
--- a/app/(authenticated)/page.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import { auth } from "@clerk/nextjs/server";
-import { redirect } from "next/navigation";
-
-const Home = async () => {
- const { userId } = await auth();
-
- if (!userId) {
- redirect("/login");
- }
-
- return (
-
-
Home
-
- );
-};
-
-export default Home;
diff --git a/app/_components/Header.tsx b/app/_components/Header.tsx
index 39672a1..f88dc92 100644
--- a/app/_components/Header.tsx
+++ b/app/_components/Header.tsx
@@ -11,7 +11,7 @@ const Header = ({ isEnabled = true }: { isEnabled?: boolean }) => {
const navigation = [
{
label: "Dashboard",
- href: "/",
+ href: "/dashboard",
},
{
label: "Transações",
@@ -28,7 +28,7 @@ const Header = ({ isEnabled = true }: { isEnabled?: boolean }) => {
return (
-
+
@@ -39,8 +39,8 @@ const Header = ({ isEnabled = true }: { isEnabled?: boolean }) => {
href={item.href}
className={`text-sm transition-colors ${
pathname === item.href
- ? "text-foreground"
- : "text-muted-foreground hover:text-foreground"
+ ? "font-medium text-primary"
+ : "text-muted-foreground hover:text-primary"
}`}
>
{item.label}
diff --git a/app/_components/ui/card.tsx b/app/_components/ui/card.tsx
new file mode 100644
index 0000000..a6c236e
--- /dev/null
+++ b/app/_components/ui/card.tsx
@@ -0,0 +1,86 @@
+import * as React from "react";
+
+import { cn } from "@/app/_lib/utils";
+
+const Card = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+Card.displayName = "Card";
+
+const CardHeader = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardHeader.displayName = "CardHeader";
+
+const CardTitle = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardTitle.displayName = "CardTitle";
+
+const CardDescription = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardDescription.displayName = "CardDescription";
+
+const CardContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardContent.displayName = "CardContent";
+
+const CardFooter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardFooter.displayName = "CardFooter";
+
+export {
+ Card,
+ CardHeader,
+ CardFooter,
+ CardTitle,
+ CardDescription,
+ CardContent,
+};
diff --git a/app/global-error.tsx b/app/global-error.tsx
index c3e77ec..4b0d157 100644
--- a/app/global-error.tsx
+++ b/app/global-error.tsx
@@ -90,7 +90,7 @@ export default function GlobalError({
Tentar novamente