Skip to content

Commit

Permalink
Created a BudgetProgress functionality in dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
Priyanshu9898 committed Dec 30, 2024
1 parent ae4fec1 commit 338b3a4
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 1 deletion.
2 changes: 1 addition & 1 deletion actions/Budget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export async function getCurrentBudget(accountId: string) {
}
}

export async function updateBudget(amount: string) {
export async function updateBudget(amount: number) {
try {
const { userId } = await auth();
if (!userId) throw new Error("Unauthorized");
Expand Down
155 changes: 155 additions & 0 deletions app/(main)/dashboard/_components/BudgetProgress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
"use client";

import { useState, useEffect } from "react";
import { Pencil, Check, X } from "lucide-react";
import { toast } from "sonner";

import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Progress } from "@/components/ui/progress";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { updateBudget } from "@/actions/Budget";

interface Budget {
amount: number;
}

interface BudgetProgressProps {
initialBudget?: Budget | null;
currentExpenses: number;
}

export function BudgetProgress({
initialBudget,
currentExpenses,
}: BudgetProgressProps) {
const [isEditing, setIsEditing] = useState(false);
const [newBudget, setNewBudget] = useState(
initialBudget?.amount?.toString() ?? ""
);
const [isLoading, setIsLoading] = useState(false);

const percentUsed = initialBudget
? (currentExpenses / initialBudget.amount) * 100
: 0;

const handleUpdateBudget = async () => {
const amount = parseFloat(newBudget);

if (isNaN(amount) || amount <= 0) {
toast.error("Please enter a valid amount");
return;
}

setIsLoading(true);

try {
const updatedBudget = await updateBudget(amount);
if (updatedBudget?.success) {
setIsEditing(false);
toast.success("Budget updated successfully");
} else {
toast.error("Failed to update budget");
}
} catch (error) {
console.error(error);
toast.error("Failed to update budget");
} finally {
setIsLoading(false);
}
};

const handleCancel = () => {
setNewBudget(initialBudget?.amount?.toString() || "");
setIsEditing(false);
};

useEffect(() => {
setNewBudget(initialBudget?.amount?.toString() || "");
}, [initialBudget]);

// Dynamically determine the progress bar color
const progressBarColor =
percentUsed >= 90
? "bg-red-500"
: percentUsed >= 75
? "bg-yellow-500"
: "bg-green-500";

return (
<Card className="mb-8">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<div className="flex-1">
<CardTitle className="text-sm font-medium">
Monthly Budget (Default Account)
</CardTitle>
<div className="flex items-center gap-2 mt-1">
{isEditing ? (
<div className="flex items-center gap-2">
<Input
type="number"
value={newBudget}
onChange={(e) => setNewBudget(e.target.value)}
className="w-32"
placeholder="Enter amount"
autoFocus
disabled={isLoading}
/>
<Button
variant="ghost"
size="icon"
onClick={handleUpdateBudget}
disabled={isLoading}
>
<Check className="h-4 w-4 text-green-500" />
</Button>
<Button
variant="ghost"
size="icon"
onClick={handleCancel}
disabled={isLoading}
>
<X className="h-4 w-4 text-red-500" />
</Button>
</div>
) : (
<>
<CardDescription>
{initialBudget
? `$${currentExpenses.toFixed(
2
)} of $${initialBudget.amount.toFixed(2)} spent`
: "No budget set"}
</CardDescription>
<Button
variant="ghost"
size="icon"
onClick={() => setIsEditing(true)}
className="h-6 w-6"
>
<Pencil className="h-3 w-3" />
</Button>
</>
)}
</div>
</div>
</CardHeader>
<CardContent>
{initialBudget && (
<div className="space-y-2">
<Progress value={percentUsed} className={progressBarColor} />
<p className="text-xs text-muted-foreground text-right">
{percentUsed.toFixed(1)}% used
</p>
</div>
)}
</CardContent>
</Card>
);
}
18 changes: 18 additions & 0 deletions app/(main)/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
export const dynamic = "force-dynamic";

import { getCurrentBudget } from "@/actions/Budget";
import { fetchAllUserAccounts } from "@/actions/Dashboard";
import AccountCard from "@/components/AccountCard";
import CreateAccountDrawer from "@/components/CreateAccountDrawer";
import React from "react";
import { BudgetProgress } from "./_components/BudgetProgress";

const Dashboard = async () => {
const userAccounts = (await fetchAllUserAccounts()) || [];

const defaultAccount = userAccounts?.find((account) => account.isDefault);

let budgetData = null;

if (defaultAccount) {
console.log(defaultAccount.id);
budgetData = await getCurrentBudget(defaultAccount.id);
}

console.log(budgetData);

return (
<div>
{/* */}

<BudgetProgress
initialBudget={budgetData?.budget}
currentExpenses={budgetData?.currentExpenses || 0}
/>

{/* */}

{/* Create Account and All Account section */}
Expand Down

0 comments on commit 338b3a4

Please sign in to comment.