mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-08 11:37:25 +00:00
debugging file upload ui
This commit is contained in:
parent
bc9ddbd7e2
commit
bcaaaab391
3 changed files with 66 additions and 33 deletions
|
|
@ -19,6 +19,7 @@ const PresignedUrlBodySchema = z.object({
|
|||
already_installed_file_path: z.string().optional(),
|
||||
// optional scenario_id to link the plan to an existing scenario
|
||||
scenario_id: z.string().optional().nullable(),
|
||||
file_type: z.enum(["csv", "xlsx"]).optional(), // Specify the file type
|
||||
});
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
|
|
@ -54,8 +55,6 @@ export async function POST(request: NextRequest) {
|
|||
console.log("Triggering plan with body: ", validatedBody);
|
||||
|
||||
const url = `${process.env.FASTAPI_API_URL}/v1/plan/trigger`;
|
||||
console.log("Triggering plan with url: ", url);
|
||||
console.log("Triggering plan with headers: ", headers);
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: "POST",
|
||||
|
|
|
|||
|
|
@ -10,41 +10,70 @@ export async function POST(req: NextRequest) {
|
|||
return NextResponse.json({ error: "No file provided" }, { status: 400 });
|
||||
}
|
||||
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
const workbook = XLSX.read(arrayBuffer, { type: "array" });
|
||||
const filename = file.name.toLowerCase();
|
||||
const mimeType = file.type;
|
||||
|
||||
const sheetNames = workbook.SheetNames;
|
||||
let fileType: "csv" | "xlsx" | "unknown" = "unknown";
|
||||
|
||||
if (
|
||||
filename.endsWith(".csv") ||
|
||||
mimeType === "text/csv" ||
|
||||
mimeType === "application/vnd.ms-excel"
|
||||
) {
|
||||
fileType = "csv";
|
||||
} else if (
|
||||
filename.endsWith(".xlsx") ||
|
||||
filename.endsWith(".xls") ||
|
||||
mimeType ===
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
) {
|
||||
fileType = "xlsx";
|
||||
}
|
||||
|
||||
if (fileType === "unknown") {
|
||||
return NextResponse.json(
|
||||
{ error: "Unsupported file type", file_type: fileType },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
let isStandardised = false;
|
||||
let sheetNames: string[] = [];
|
||||
|
||||
for (const sheetName of sheetNames) {
|
||||
if (sheetName !== "Standardised Asset List") continue;
|
||||
// Handle CSV
|
||||
if (fileType === "csv") {
|
||||
const text = await file.text();
|
||||
const lines = text.split("\n").map((line) => line.split(","));
|
||||
const headers = lines[0].map((h) => h.trim());
|
||||
isStandardised = headers.includes("domna_property_id");
|
||||
}
|
||||
|
||||
const worksheet = workbook.Sheets[sheetName];
|
||||
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }) as (
|
||||
| string
|
||||
| number
|
||||
| null
|
||||
)[][];
|
||||
// Handle Excel
|
||||
if (fileType === "xlsx") {
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
|
||||
const headers = jsonData.find(
|
||||
(row): row is string[] =>
|
||||
Array.isArray(row) &&
|
||||
row.length > 0 &&
|
||||
row.every((cell) => typeof cell === "string" || cell === null)
|
||||
);
|
||||
// Only load specific sheet to reduce memory usage
|
||||
const workbook = XLSX.read(arrayBuffer, {
|
||||
type: "array",
|
||||
sheets: ["Standardised Asset List"],
|
||||
});
|
||||
|
||||
if (headers?.includes("domna_property_id")) {
|
||||
isStandardised = true;
|
||||
break;
|
||||
sheetNames = workbook.SheetNames;
|
||||
|
||||
const worksheet = workbook.Sheets["Standardised Asset List"];
|
||||
if (worksheet) {
|
||||
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
|
||||
const headers = jsonData[0] as string[];
|
||||
isStandardised = headers?.includes("domna_property_id");
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
message: isStandardised
|
||||
? "Standardised Asset List format detected. Please select which tab to use."
|
||||
? "Standardised Asset List format detected."
|
||||
: "Valid file. No standardised format detected.",
|
||||
sheetNames: isStandardised ? sheetNames : undefined,
|
||||
isStandardised,
|
||||
file_type: fileType,
|
||||
...(fileType === "xlsx" && isStandardised ? { sheetNames } : {}),
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,9 +51,13 @@ const goalValueOptions = [
|
|||
{ label: "A", value: "A", disabled: false },
|
||||
];
|
||||
|
||||
function generateS3Key(userId: string, portfolioId: string) {
|
||||
function generateS3Key(
|
||||
userId: string,
|
||||
portfolioId: string,
|
||||
fileType: "csv" | "xlsx"
|
||||
) {
|
||||
const timestamp = new Date().toISOString().replace(/[:.-]/g, "");
|
||||
return `${userId}/${portfolioId}/${timestamp}/asset_list.csv`;
|
||||
return `${userId}/${portfolioId}/${timestamp}/asset_list.${fileType}`;
|
||||
}
|
||||
|
||||
async function uploadCsvToS3({
|
||||
|
|
@ -103,6 +107,7 @@ export function useUploadCsvPlan({
|
|||
ashpCop,
|
||||
measures,
|
||||
onSuccessRedirect,
|
||||
fileType,
|
||||
}: {
|
||||
file: File;
|
||||
portfolioId: string;
|
||||
|
|
@ -115,13 +120,14 @@ export function useUploadCsvPlan({
|
|||
selectedSheet: string;
|
||||
measures: (typeof measuresList)[number][];
|
||||
onSuccessRedirect: (path: string) => void;
|
||||
fileType: "csv" | "xlsx";
|
||||
}) {
|
||||
const session = useSession();
|
||||
const userId = String(session.data?.user.dbId);
|
||||
|
||||
const fileKey = useMemo(
|
||||
() => generateS3Key(userId, portfolioId),
|
||||
[userId, portfolioId]
|
||||
() => generateS3Key(userId, portfolioId, fileType),
|
||||
[userId, portfolioId, fileType]
|
||||
);
|
||||
|
||||
const { mutateAsync: uploadFileToS3, isLoading: isUploadLoading } =
|
||||
|
|
@ -154,6 +160,7 @@ export function useUploadCsvPlan({
|
|||
event_type: "remote_assessment",
|
||||
sheet_name: selectedSheet,
|
||||
ashp_cop: ashpCop,
|
||||
file_type: fileType, // Pass the file type for backend processing
|
||||
};
|
||||
|
||||
const triggerRes = await fetch("/api/plan/trigger", {
|
||||
|
|
@ -211,6 +218,7 @@ export default function UploadCsvModal({
|
|||
const [csvFile, setCsvFile] = useState<File | null>(null);
|
||||
const [selectedScenario, setSelectedScenario] = useState<string | null>(null);
|
||||
const [showMeasures, setShowMeasures] = useState(false);
|
||||
const [fileType, setFileType] = useState<"csv" | "xlsx">("csv");
|
||||
|
||||
const scenarioOptions = useMemo(
|
||||
() =>
|
||||
|
|
@ -242,6 +250,7 @@ export default function UploadCsvModal({
|
|||
setSheetNames([]);
|
||||
setSelectedSheet("");
|
||||
}
|
||||
setFileType(data.file_type); // capture file type
|
||||
},
|
||||
onError: () => {
|
||||
setSheetNames([]);
|
||||
|
|
@ -282,6 +291,7 @@ export default function UploadCsvModal({
|
|||
ashpCop: form.watch("ashpCop"),
|
||||
scenarioName: form.watch("scenario"),
|
||||
measures: form.watch("measures"),
|
||||
fileType: fileType,
|
||||
portfolioId,
|
||||
selectedSheet,
|
||||
onSuccessRedirect: (path) => router.push(path),
|
||||
|
|
@ -496,11 +506,6 @@ export default function UploadCsvModal({
|
|||
/>
|
||||
</div>
|
||||
|
||||
<pre>
|
||||
{JSON.stringify(form.formState.errors, null, 2)}
|
||||
</pre>
|
||||
<pre>{JSON.stringify(form.watch(), null, 2)}</pre>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{/* Heat Pump COP */}
|
||||
<FormField
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue