Skip to content

Commit

Permalink
working dialog box and updating rows in db
Browse files Browse the repository at this point in the history
  • Loading branch information
vim-diesel committed Nov 24, 2024
1 parent 127c720 commit 5d54937
Show file tree
Hide file tree
Showing 7 changed files with 435 additions and 43 deletions.
5 changes: 3 additions & 2 deletions actions/categories/categoriesActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ export async function getCategoriesWithDetails(
return new AppError("DB_ERROR", error.message, error.code).toPlainObject();
}

console.log("categoriesWithDetails", categoriesWithDetails[0].monthly_category_details);

// Map over the data to flatten `monthly_category_details` to a single object
const flattenedData = categoriesWithDetails.map((category) => ({
...category,
Expand Down Expand Up @@ -93,3 +91,6 @@ export async function addCategory(
revalidatePath("/dashboard");
return null;
}

// Update a category in the categories table

71 changes: 62 additions & 9 deletions actions/monthlyCategoryDetails/monthlyCategoryDetailsActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { AppError, PlainAppError } from "@/errors";
import { MonthlyCategoryDetails } from "@/types";
import { createServersideClient } from "@/utils/supabase/server";
import { revalidatePath } from "next/cache";

// Updates the assigned amount for a category in a monthly budget
export async function updateAssigned(
Expand Down Expand Up @@ -33,21 +34,31 @@ export async function updateAssigned(
).toPlainObject();
}

const { error } = await supabase
const { data: updateData, error: updateError } = await supabase
.from("monthly_category_details")
.update({ amount_assigned: amountAssigned })
.eq("monthly_budget_id", monthlyBudgetId)
.eq("category_id", categoryId);
.upsert(
{
user_id: user.id,
monthly_budget_id: monthlyBudgetId,
category_id: categoryId,
amount_assigned: amountAssigned,
},
{ onConflict: "monthly_budget_id,category_id" }, // Specify the conflict target
);

if (error) {
console.error("Error updating assigned amount: ", error);
return new AppError("DB_ERROR", error.message, error.code).toPlainObject();
if (updateError) {
console.error("Error updating assigned amount: ", updateError);
return new AppError(
"DB_ERROR",
updateError.message,
updateError.code,
).toPlainObject();
}

revalidatePath("/dashboard");
return null;
}


export async function getMonthlyCategoryDetails(
budgetId: number,
month: string,
Expand Down Expand Up @@ -79,4 +90,46 @@ export async function getMonthlyCategoryDetails(
}

return details;
}
}

export async function createMonthlyCategoryDetails(
budgetId: number,
categoryId: number,
monthlyBudgetId: number,
): Promise<MonthlyCategoryDetails | PlainAppError> {
const supabase = createServersideClient();
const {
data: { user },
error: authError,
} = await supabase.auth.getUser();

if (authError || !user) {
console.error("Error authenticating user: ", authError?.message);
return new AppError(
"AUTH_ERROR",
"User authentication failed or user not found",
authError?.code,
).toPlainObject();
}

const { data, error } = await supabase
.from("monthly_category_details")
.insert([
{
category_id: categoryId,
monthly_budget_id: monthlyBudgetId,
user_id: user.id,
},
]);

if (error) {
console.error("Error creating monthly category details: ", error);
return new AppError("DB_ERROR", error.message, error.code).toPlainObject();
}

if (!data) {
return new AppError("NOT_FOUND", "No data returned").toPlainObject();
}

return data[0];
}
110 changes: 78 additions & 32 deletions app/dashboard/debug/displayForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ import { Select } from "@/components/select";
import { Input, InputGroup } from "@/components/input";
import { CurrencyDollarIcon } from "@heroicons/react/24/outline";
import { DateType } from "../../../components/input";
import {
Dialog,
DialogActions,
DialogBody,
DialogDescription,
DialogTitle,
} from "@/components/dialog";
import { Field } from "@/components/fieldset";
import { updateAssigned } from "@/actions/monthlyCategoryDetails";
import UpdateBox from "./updateBox";

interface DebugPageProps {
budget: Budget | PlainAppError;
Expand Down Expand Up @@ -142,6 +152,43 @@ export default function DisplayForm({
return;
}

async function handleAssignDollars(
categoryDetailsId: number,
assignedAmount: number,
) {
setLoading(true);
if (!monthlyBudget || isPlainAppError(monthlyBudget)) {
toast.error("Monthly budget is not defined or is an error", {
className: "bg-rose-500",
});
setLoading(false);
return;
}
const amount = Number(assignedAmount);
if (isNaN(amount)) {
toast.warning("Amount must be a number...", {
className: "bg-yellow-200",
});
setLoading(false);
return;
}
const res = await updateAssigned(
monthlyBudget.id,
categoryDetailsId,
amount,
);
if (res?.error) {
const errStr = `Error adding category: ${res.error.message}`;
toast.error(errStr, { className: "bg-rose-500" });
setLoading(false);
return;
} else {
toast.success("Updated!");
setLoading(false);
return;
}
}

return (
<div className="sm:p-4">
<section className="mb-8">
Expand All @@ -153,9 +200,7 @@ export default function DisplayForm({
</DescriptionList>
)}
</section>

<Divider className="my-6" />

<section className="mb-8">
<h2 className="mb-4 text-2xl font-bold">Current Monthly Budget</h2>
{!isPlainAppError(monthlyBudget) && (
Expand All @@ -167,9 +212,14 @@ export default function DisplayForm({
</DescriptionList>
)}
</section>

<Divider className="my-6" />

{/*
*
*
TODO: Fade $0 amounts, make them clickable to pop up a modal to edit
*
*
*/}
<section className="mb-8">
<h2 className="mb-4 text-2xl font-bold">Categories With Details</h2>
<div className="mb-4 w-full">
Expand All @@ -184,32 +234,34 @@ export default function DisplayForm({

{/* Table Rows */}
{Array.isArray(categoryWithDetails) &&
categoryWithDetails.map((c) => (
<div
key={c.id}
className="mb-2 grid grid-cols-[3fr_1fr_1fr_1fr_1fr] gap-4 rounded bg-gray-100 p-4 dark:bg-black"
>
<div>{c.name}</div>
<div>
{c.monthly_category_details &&
c.monthly_category_details.amount_assigned}
</div>
<div>
{c.monthly_category_details &&
c.monthly_category_details.amount_spent}
categoryWithDetails.map((c) => {
if (c.name === "Ready to Assign") {
return null;
}
return (
<div
key={c.id}
className="mb-2 grid grid-cols-[3fr_1fr_1fr_1fr_1fr] gap-4 rounded bg-gray-100 p-4 dark:bg-black"
>
<div>{c.name}</div>
<div>
<UpdateBox c={c} handler={handleAssignDollars} />
</div>
<div>
{c.monthly_category_details &&
c.monthly_category_details.amount_spent}
</div>
<div>{c.target_amount}</div>
<div>
{c.monthly_category_details &&
c.monthly_category_details.carryover_from_previous_month}
</div>
</div>
<div>{c.target_amount}</div>
<div>
{c.monthly_category_details &&
c.monthly_category_details.carryover_from_previous_month}
</div>
</div>
))}
);
})}
</div>
</section>

<Divider className="my-6" />

<section className="mb-8">
<h2 className="mb-4 text-2xl font-bold">Transactions</h2>
<div className="mb-4 w-full">
Expand All @@ -234,9 +286,7 @@ export default function DisplayForm({
))}
</div>
</section>

<Divider className="my-6" />

<section className="mb-8">
<h2 className="mb-3 text-2xl font-bold">Add Category</h2>
<Input
Expand Down Expand Up @@ -267,9 +317,7 @@ export default function DisplayForm({
</Select>
<Button onClick={handleAddCategory}> Add </Button>
</section>

<Divider className="my-6" />

<section className="mb-8">
<h2 className="mb-3 text-2xl font-bold">Add Transaction</h2>
<InputGroup>
Expand Down Expand Up @@ -312,9 +360,7 @@ export default function DisplayForm({
Add
</Button>
</section>

{loading && <div>Loading...</div>}

<Divider className="my-6" />
{/* <section className="mb-8">
{Array.isArray(categoryWithDetails) &&
Expand Down
72 changes: 72 additions & 0 deletions app/dashboard/debug/updateBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Button } from "@/components/button";
import {
Dialog,
DialogActions,
DialogBody,
DialogDescription,
DialogTitle,
} from "@/components/dialog";
import { Field, Label } from "@/components/fieldset";
import { Input } from "@/components/input";
import { CategoryWithDetails } from "@/types";
import { useState } from "react";

export default function UpdateBox({
c,
handler,
}: {
c: CategoryWithDetails;
handler: (categoryId: number, amount: number) => void;
}) {
const [isOpen, setIsOpen] = useState(false);
const [assignedAmount, setAssignedAmount] = useState(
c.monthly_category_details?.amount_assigned,
);

return (
<>
<Button type="button" onClick={() => setIsOpen(true)}>
{c.monthly_category_details &&
c.monthly_category_details.amount_assigned}
</Button>
<Dialog open={isOpen} onClose={setIsOpen}>
<DialogTitle>Assign Dollars</DialogTitle>
<DialogDescription>
Assign your monthly available budget to {c.name}
</DialogDescription>
<DialogBody>
<Field>
<Label>Amount</Label>
<Input
name="amount"
placeholder="$0.00"
autoFocus
value={assignedAmount ?? ""}
onChange={(e) => {
const value = e.target.value;
if (!isNaN(Number(value))) {
setAssignedAmount(Number(value));
}
}}
/>
</Field>
</DialogBody>
<DialogActions>
<Button plain onClick={() => setIsOpen(false)}>
Cancel
</Button>
<Button
onClick={() => {
setIsOpen(false);
if (assignedAmount !== null && assignedAmount >= 0) {
handler(c.id, assignedAmount);
}
}}
>
Set
</Button>
</DialogActions>
</Dialog>
</>
);
}
Loading

0 comments on commit 5d54937

Please sign in to comment.