-
-
-
-
-
- {/* Measures grid */}
-
- {measuresList.map((measure) => (
- (
-
- {
- const checked = e.target.checked;
- const current = new Set(field.value ?? []);
- if (checked) {
- current.add(measure);
- } else {
- current.delete(measure);
- }
- field.onChange(Array.from(current));
- }}
- className="h-4 w-4"
- />
-
- {measuresDisplayLabels[measure]}
-
-
- )}
- />
- ))}
-
-
- );
-}
diff --git a/src/app/portfolio/[slug]/components/SubmitPlan.tsx b/src/app/portfolio/[slug]/components/SubmitPlan.tsx
deleted file mode 100644
index 06b2339b..00000000
--- a/src/app/portfolio/[slug]/components/SubmitPlan.tsx
+++ /dev/null
@@ -1,195 +0,0 @@
-"use client";
-
-import { useRouter } from "next/navigation";
-import { useMutation } from "@tanstack/react-query";
-import { useSession } from "next-auth/react";
-import { useMemo } from "react";
-
-function generateS3Key(userId: string, portfolioId: string, filename: string) {
- const timestamp = new Date().toISOString().replace(/[:.-]/g, "");
- const key = `${userId}/${portfolioId}/${filename}-${timestamp}.csv`;
- return key;
-}
-
-interface UseCreatePlanProps {
- portfolioId: string;
- housingType: string;
- goal: string;
- goalValue: string;
- file: File;
-}
-
-interface UseCreatePlanReturn {
- handlePlanBuild: () => void;
- isGeneratingUrlLoading: boolean;
- isUploadLoading: boolean;
-}
-
-const useCreatePlan = ({
- portfolioId,
- housingType,
- goal,
- goalValue,
- file,
-}: UseCreatePlanProps): UseCreatePlanReturn => {
- const router = useRouter();
- const session = useSession();
-
- // Since userId is a big int it gets coerced into a string
- const userId = String(session.data?.user.dbId);
-
- // Every time the component is re-rendered, a new file key will be generated. To prevent this,
- // we use useMemo to only generate a new file key when the userId or portfolioId changes.
- const fileKey = useMemo(
- () => generateS3Key(userId, portfolioId, "portfolio_plan_properties"),
- [userId, portfolioId]
- );
-
- const { mutate: mutateUploadCsv, isLoading: isUploadLoading } = useMutation(
- uploadCsvToS3,
- {
- onSuccess: () => {
- const body = JSON.stringify({
- portfolio_id: portfolioId,
- housing_type: housingType,
- goal: goal,
- goal_value: goalValue,
- trigger_file_path: fileKey,
- });
-
- const response = fetch(`/api/plan/trigger`, {
- method: "POST",
- body: body,
- });
-
- return response;
- },
- onError: (error) => {
- console.error(error);
- },
- }
- );
-
- const { mutate, isLoading: isGeneratingUrlLoading } = useMutation(
- generatePresignedUrl,
- {
- onSuccess: (data) => {
- try {
- const response = mutateUploadCsv({
- presignedUrl: data.url,
- file: file,
- });
-
- return response;
- } catch (error) {
- console.error(error);
- }
- },
- onError: (error) => {
- console.error(error);
- },
- }
- );
-
- const handlePlanBuild = () => {
- mutate({ userId: userId, portfolioId: portfolioId, fileKey: fileKey });
- router.push(`/portfolio/${portfolioId}/plan-loading`);
- };
-
- return {
- handlePlanBuild,
- isGeneratingUrlLoading,
- isUploadLoading,
- };
-};
-
-async function generatePresignedUrl({
- userId,
- portfolioId,
- fileKey,
-}: {
- userId: string;
- portfolioId: string;
- fileKey: string;
-}) {
- const body = JSON.stringify({
- userId: userId,
- portfolioId: portfolioId,
- fileKey: fileKey,
- });
-
- const presignedResponse = await fetch(`/api/upload/csv`, {
- method: "POST",
- body: body,
- });
- if (!presignedResponse.ok) {
- throw new Error("Network response was not ok");
- }
- const presignedUrl = await presignedResponse.json();
- return presignedUrl;
-}
-
-async function uploadCsvToS3({
- presignedUrl,
- file,
-}: {
- presignedUrl: string;
- file: File;
-}) {
- try {
- const response = await fetch(presignedUrl, {
- method: "PUT",
- body: file,
- headers: { "Content-Type": "text/csv" },
- });
-
- if (!response.ok) {
- console.error(response);
- throw new Error("Network response was not ok");
- }
- } catch (error) {
- console.error(error);
- throw new Error("Upload failed.");
- }
-
- return { success: true };
-}
-
-export const SubmitPlan = ({
- buttonDisabled,
- goal,
- housingType,
- goalValue,
- file,
- portfolioId,
-}: {
- buttonDisabled: boolean;
- goal: string;
- housingType: string;
- goalValue: string;
- file: File;
- portfolioId: string;
-}) => {
- const { handlePlanBuild, isGeneratingUrlLoading, isUploadLoading } =
- useCreatePlan({ portfolioId, housingType, goal, goalValue, file });
-
- let buttonText;
- if (isUploadLoading) {
- buttonText = "Uploading file...";
- } else if (isGeneratingUrlLoading) {
- buttonText = "Creating plan...";
- } else {
- buttonText = "Create";
- }
-
- return (
-