adding the basline for the setting api

This commit is contained in:
Khalim Conn-Kowlessar 2024-10-24 17:00:03 +01:00
parent 5f2cc6b1b9
commit 74ac3783b9
3 changed files with 146 additions and 29 deletions

View file

@ -0,0 +1,31 @@
import { db } from "@/app/db/db";
import { NextRequest, NextResponse } from "next/server";
import { portfolio } from "@/app/db/schema/portfolio";
import { and, eq, inArray } from "drizzle-orm";
export async function PUT(request: NextRequest) {
const body = await request.json();
console.log("HI WE MADE IT!!");
console.log(body);
const portfolioId = body.portfolioId;
const userId = body.userId;
delete body.userId;
delete body.portfolioId;
console.log(body);
// Update the database
await db.update(portfolio).set(body).where(eq(portfolio.id, portfolioId));
// Returning a successful response
return new NextResponse(JSON.stringify({}), {
status: 200,
});
}
export async function DELETE(request: NextRequest) {
const body = await request.json();
console.log("WE BE DELETIN'");
}

View file

@ -1,6 +1,7 @@
"use client";
import { useState } from "react";
import { useMutation } from "@tanstack/react-query";
import { PortfolioSettingsType } from "../../utils";
import { Button } from "@/app/shadcn_components/ui/button";
import { Input } from "@/app/shadcn_components/ui/input";
@ -23,6 +24,7 @@ import {
} from "@/app/shadcn_components/ui/dialog";
import { PortfolioStatus as PortfolioStatusOptions } from "@/app/db/schema/portfolio";
import { PortfolioGoal as PortfolioGoalOptions } from "@/app/db/schema/portfolio";
import { useSession } from "next-auth/react";
// dropdown selection component for both goal and status
@ -57,6 +59,74 @@ export function SettingsDropdown({
);
}
type updateSettingsArgs = {
userId: bigint;
portfolioId: string;
name: string | null;
budget: number | string | undefined | null;
goal: (typeof PortfolioGoalOptions)[number] | null;
status: (typeof PortfolioStatusOptions)[number] | null;
};
type bodyType = {
userId: string;
portfolioId: string;
name?: string;
budget?: number | string;
goal?: string;
status?: string;
};
const updateSettings = async ({
userId,
portfolioId,
name,
budget,
goal,
status,
}: updateSettingsArgs) => {
// We convert the the bigint to a string since big ints are not serialisable and we don't want to loose precision
// We will create a js object with the starting values
// We will then update the values that are not null
const body: bodyType = {
userId: userId.toString(),
portfolioId: portfolioId,
};
if (name) {
body.name = name;
}
if (budget) {
body.budget = budget;
}
if (goal) {
body.goal = goal;
}
if (status) {
body.status = status;
}
const requestBody = JSON.stringify(body);
const response = await fetch(`/api/portfolio/${portfolioId}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: requestBody,
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
};
export default function PortfolioSettings({
portfolioId,
portfolioSettingsData,
@ -64,12 +134,21 @@ export default function PortfolioSettings({
portfolioId: string;
portfolioSettingsData: PortfolioSettingsType;
}) {
// Running in the client
// This is a client component so we can access the session directly
const session = useSession();
const router = useRouter();
// Set up state for portfolioName, portfolioBudget, portfolioGoal and portfolioStatus
const { mutate, isLoading } = useMutation(updateSettings, {
onSuccess: () => {
router.refresh();
},
onError: (error) => {
// handle error
console.log(error);
},
});
// Syntax const [variable, function whos only job is to update the value of variable] = useState(initial value)
const [portfolioName, setPortfolioName] = useState(
portfolioSettingsData.name
);
@ -92,6 +171,14 @@ export default function PortfolioSettings({
const [deleteConfirmationByName, setDeleteConfirmationByName] = useState("");
if (!session.data) {
// The user is not logged in, redirect them to sign in
router.push("/");
return null;
}
const userId = session.data.user.dbId;
function handleOpenDeleteModal() {
setDeleteConfirmationByName("");
setIsDeleteModalOpen(true);
@ -120,10 +207,15 @@ export default function PortfolioSettings({
// The onClick function called to update the NAME in the DB
function handleRenameDb() {
// apiRanameFunction(portfolioSettingsData.name)
// Update portfolioName
router.refresh();
function handleRename() {
mutate({
userId,
portfolioId,
name: portfolioName,
budget: null,
goal: null,
status: null,
});
}
// BUDGET CHANGING FUNCTIONS
@ -136,10 +228,15 @@ export default function PortfolioSettings({
// The onClick function called to update the BUDGET in the DB
function handleBudgetUpdateDb() {
// apiBudgetChangeFunction(portfolioSettingsData.budget)
// Update portfolioBudget
router.refresh();
function handleBudgetUpdate() {
mutate({
userId,
portfolioId,
name: null,
budget: portfolioBudget,
goal: null,
status: null,
});
}
// CHANGING GOAL AND STATUS FUNCTIONALITY
@ -162,6 +259,11 @@ export default function PortfolioSettings({
// HTML to render the page
// TODO: 1) Set up the useMutate hook
// 2) Set up the api functions
// 3) add the call to mutate() so that when we submit the form, the data is updated in the DB
// 4) Create the API
return (
<>
<div className="p-4 mt-5 flex justify-center max-w-8xl w-8xl pt-5 bg-gray-50 rounded-lg text-brandblue">
@ -174,7 +276,7 @@ export default function PortfolioSettings({
<Input value={portfolioName} onChange={handlePortfolioNameChange} />
</div>
<div className="flex items-center">
<Button className="w-full" onClick={handleRenameDb}>
<Button className="w-full" onClick={handleRename}>
Rename
</Button>
</div>
@ -192,7 +294,7 @@ export default function PortfolioSettings({
/>
</div>
<div className="flex items-center">
<Button className="w-full" onClick={handleBudgetUpdateDb}>
<Button className="w-full" onClick={handleBudgetUpdate}>
Update
</Button>
</div>

View file

@ -7,24 +7,8 @@ export default async function PortfolioSettingsPage({
params: { slug: string };
}) {
const portfolioId = params.slug;
// fetch data securely on the server
// Stef's page!!!!
// 1) Rename
// 2) Update budget, status, goal
// 3) Delete - much harder
// fetch data in the server - name, budget, goal,
// pass it to a client component to render and take user input
const portfolioSettingsData = await getPortfolioSettings(portfolioId);
// Get goal options and status options by importing something like this:
// import {
// PortfolioStatus,
// PortfolioGoal,
// } from "./../../db/schema/portfolio";
// and then pass them to the portfoliosettings component
return (
<>
<div className="flex justify-center max-w-8xl w-8xl">