mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-08 11:37:25 +00:00
added api call to fastapi backend
This commit is contained in:
parent
ac545b2b32
commit
0e2ffe97c3
3 changed files with 101 additions and 26 deletions
62
src/app/api/plan/trigger/route.ts
Normal file
62
src/app/api/plan/trigger/route.ts
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
|
||||
const PresignedUrlBodySchema = z.object({
|
||||
portfolio_id: z.number(),
|
||||
housing_type: z.enum(["Social", "Private"]),
|
||||
goal: z.enum(["Increase EPC", "Reduce energy consumption"]),
|
||||
goal_value: z.string(),
|
||||
trigger_file_path: z.string(),
|
||||
});
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
// For the moment, this api specifically handles uploads of csvs
|
||||
|
||||
const body = await request.json();
|
||||
let validatedBody;
|
||||
|
||||
try {
|
||||
validatedBody = PresignedUrlBodySchema.parse(body);
|
||||
} catch (error) {
|
||||
console.error("Invalid input: ", error);
|
||||
return new NextResponse(JSON.stringify({ msg: "Invalid input" }), {
|
||||
status: 400,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
// We'll trigger the plan build in our fastapi backend and then the user will just have to
|
||||
// wait for the plan to be ready
|
||||
|
||||
const headers = {
|
||||
"x-api-key": process.env.FASTAPI_API_KEY || "",
|
||||
Authorization: `Bearer ${
|
||||
request.cookies.get("next-auth.session-token")?.value
|
||||
}`,
|
||||
};
|
||||
|
||||
const response = await fetch(
|
||||
`${process.env.FASTAPI_API_URL}/v1/plan/trigger`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
body: JSON.stringify(validatedBody),
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("API request failed");
|
||||
}
|
||||
|
||||
const responseData = await response.json();
|
||||
|
||||
return new NextResponse(JSON.stringify(responseData), {
|
||||
status: 200,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return new NextResponse(JSON.stringify({ msg: "Internal server error" }), {
|
||||
status: 500,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -5,14 +5,9 @@ import { z } from "zod";
|
|||
const PresignedUrlBodySchema = z.object({
|
||||
userId: z.number(),
|
||||
portfolioId: z.number(),
|
||||
fileKey: z.string(),
|
||||
});
|
||||
|
||||
function generateS3Key(userId: number, portfolioId: number, filename: string) {
|
||||
const timestamp = new Date().toISOString().replace(/[:.-]/g, "");
|
||||
const key = `${userId}/${portfolioId}/${filename}-${timestamp}.csv`;
|
||||
return key;
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
// For the moment, this api specifically handles uploads of csvs
|
||||
|
||||
|
|
@ -36,12 +31,7 @@ export async function POST(request: NextRequest) {
|
|||
secretAccessKey: process.env.PRESIGN_AWS_SECRET_KEY,
|
||||
});
|
||||
|
||||
const { userId, portfolioId } = validatedBody;
|
||||
const fileKey = generateS3Key(
|
||||
userId,
|
||||
portfolioId,
|
||||
"portfolio_plan_properties"
|
||||
);
|
||||
const { userId, portfolioId, fileKey } = validatedBody;
|
||||
|
||||
// Presigned url is valid for 5 minutes
|
||||
const preSignedUrl = await s3.getSignedUrl("putObject", {
|
||||
|
|
|
|||
|
|
@ -11,14 +11,26 @@ import { useRouter } from "next/navigation";
|
|||
import { useMutation } from "@tanstack/react-query";
|
||||
import { useSession } from "next-auth/react";
|
||||
|
||||
function generateS3Key(userId: number, portfolioId: number, filename: string) {
|
||||
const timestamp = new Date().toISOString().replace(/[:.-]/g, "");
|
||||
const key = `${userId}/${portfolioId}/${filename}-${timestamp}.csv`;
|
||||
return key;
|
||||
}
|
||||
|
||||
async function generatePresignedUrl({
|
||||
userId,
|
||||
portfolioId,
|
||||
fileKey,
|
||||
}: {
|
||||
userId: number;
|
||||
portfolioId: number;
|
||||
fileKey: string;
|
||||
}) {
|
||||
const body = JSON.stringify({ userId: userId, portfolioId: portfolioId });
|
||||
const body = JSON.stringify({
|
||||
userId: userId,
|
||||
portfolioId: portfolioId,
|
||||
fileKey: fileKey,
|
||||
});
|
||||
|
||||
const presignedResponse = await fetch(`/api/upload/csv`, {
|
||||
method: "POST",
|
||||
|
|
@ -75,21 +87,33 @@ export const SubmitPlan = ({
|
|||
const router = useRouter();
|
||||
const session = useSession();
|
||||
|
||||
const userId = session.data?.user.dbId;
|
||||
|
||||
const fileKey = generateS3Key(
|
||||
userId,
|
||||
portfolioId,
|
||||
"portfolio_plan_properties"
|
||||
);
|
||||
|
||||
const { mutate: mutateUploadCsv, isLoading: isUploadLoading } = useMutation(
|
||||
uploadCsvToS3,
|
||||
{
|
||||
onSuccess: (data) => {
|
||||
const body = JSON.stringify({
|
||||
// userId: session.data?.user.dbId,
|
||||
portfolio_id: portfolioId,
|
||||
housing_type: housingType,
|
||||
goal: goal,
|
||||
goal_value: goalValue,
|
||||
trigger_file_path: fileKey,
|
||||
});
|
||||
|
||||
// After the file has been uploaded, we can trigger the job to build the plan
|
||||
// const response = fetch(`/api/plan/build`, {
|
||||
// method: "POST",
|
||||
// body: JSON.stringify({
|
||||
// portfolioId: portfolioId,
|
||||
// housingType: housingType,
|
||||
// goal: goal,
|
||||
// goalValue: goalValue,
|
||||
// }),
|
||||
// });
|
||||
// return response;
|
||||
const response = fetch(`/api/plan/trigger`, {
|
||||
method: "POST",
|
||||
body: body,
|
||||
});
|
||||
return response;
|
||||
},
|
||||
onError: (error) => {
|
||||
// handle error
|
||||
|
|
@ -123,7 +147,6 @@ export const SubmitPlan = ({
|
|||
router.push("/");
|
||||
return null;
|
||||
}
|
||||
const userId = session.data.user.dbId;
|
||||
|
||||
const handlePlanBuild = () => {
|
||||
// The plan build is triggered by clicking submit which will:
|
||||
|
|
@ -131,7 +154,7 @@ export const SubmitPlan = ({
|
|||
// 2) Upload the csv to the pre-signed url
|
||||
// 3) Trigger the job to build the plan
|
||||
// 4) Redirect the user to some loading page - this could be the portfolio page itself and we just trigger a regresh with skeleton cards for the properties
|
||||
mutate({ userId: userId, portfolioId: portfolioId });
|
||||
mutate({ userId: userId, portfolioId: portfolioId, fileKey: fileKey });
|
||||
|
||||
// TODO: Make api call to backend service to trigger the plan build
|
||||
// Probably need to pass in the file key to mutate (define it outside)
|
||||
|
|
@ -523,7 +546,7 @@ export default function UploadCsvModal({
|
|||
</button>
|
||||
<SubmitPlan
|
||||
buttonDisabled={buttonDisabled}
|
||||
goal={goalValue}
|
||||
goal={selectedGoal}
|
||||
housingType={housingType}
|
||||
goalValue={goalValue}
|
||||
portfolioId={portfolioId}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue