Skip to content

Commit

Permalink
issue #202: handle confirm button click
Browse files Browse the repository at this point in the history
  • Loading branch information
k-allagbe committed Jan 17, 2025
1 parent a30b53c commit 4f5052e
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 71 deletions.
17 changes: 8 additions & 9 deletions docs/label-data-confirmation/flowchart.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,20 @@ flowchart TD

```mermaid
flowchart TD
Start([Confirm Button Clicked]) --> CheckLabelDataConfirmed{"labelData.confirmed?"}
CheckLabelDataConfirmed -->|No| End([End])
CheckLabelDataConfirmed -->|Yes| CheckInspectionID{"labelData.inspection_id?"}
Start([Confirm Button Clicked]) --> CheckConfirmationCheckbox{"Confirmation Checkbox Checked?"}
CheckConfirmationCheckbox -->|No| End([End])
CheckConfirmationCheckbox -->|Yes| CopyLabelData["Copy Label Data and Set confirmed = true"] --> CheckInspectionID{"labelData.inspection_id?"}
CheckInspectionID -->|No| TransformToLabelDataInput["Transform Label Data into LabelDataInput"]
TransformToLabelDataInput --> StartLoadingAnimationNoID["Start Loading Animation"]
StartLoadingAnimationNoID --> PostRequest["POST api/inspections with LabelDataInput"]
CheckInspectionID -->|No| StartLoadingAnimationNoID["Start Loading Animation"]
StartLoadingAnimationNoID --> PostRequest["POST api/inspections with LabelData"]
PostRequest --> PostRequestSuccess{"Request Success?"}
PostRequestSuccess -->|No| StopLoadingFailure["Stop Loading Animation"] --> DisplayFailureAlert["Display Failure Alert"] --> End
PostRequestSuccess -->|Yes| TransformLabelData["Transform Label Data into InspectionUpdate"] --> StartLoadingAnimationWithID["Start Loading Animation"] --> PutRequest["PUT api/inspections/inspection_id with InspectionUpdate"]
PostRequestSuccess -->|Yes| StoreLabelDataAfterPost["Store Label Data"] --> StartLoadingAnimationWithID["Start Loading Animation"] --> PutRequest["PUT api/inspections/inspection_id with LabelData"]
CheckInspectionID -->|Yes| TransformLabelData
CheckInspectionID -->|Yes| StartLoadingAnimationWithID
PutRequest --> PutRequestSuccess{"Request Success?"}
PutRequestSuccess -->|No| StopLoadingFailure
PutRequestSuccess -->|Yes| StopLoadingSuccess["Stop Loading Animation"] --> DisplaySuccessAlert["Display Success Alert"] --> HomePage[Home] --> End
PutRequestSuccess -->|Yes| StopLoadingSuccess["Stop Loading Animation"] --> DisplaySuccessAlert["Display Success Alert"] --> StoreLabelData["Store Label Data"] --> HomePage[Home] --> End
```

## Click on Edit button
Expand Down
2 changes: 2 additions & 0 deletions src/app/api/extract-label-data/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { mapLabelDataOutputToLabelData } from "@/utils/server/modelTransformatio

export async function POST(request: Request) {
const formData = await request.formData();
console.debug("request body (formdata):", formData);
const files = formData.getAll("files") as File[];

const authHeader = request.headers.get("Authorization");
Expand All @@ -16,6 +17,7 @@ export async function POST(request: Request) {
.analyzeDocumentAnalyzePost(files)
.then((analyzeResponse) => {
const labelData = mapLabelDataOutputToLabelData(analyzeResponse.data);
console.debug("response:", labelData);
return Response.json(labelData);
})
.catch((error) => {
Expand Down
3 changes: 3 additions & 0 deletions src/app/api/inspections/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export async function GET(
})
.then((inspectionResponse) => {
const labelData = mapInspectionToLabelData(inspectionResponse.data);
console.debug("response:", labelData);
return Response.json(labelData);
})
.catch((error) => {
Expand All @@ -51,13 +52,15 @@ export async function PUT(
return INVALID_ID_RESPONSE;
}
const body = await request.json();
console.debug("request body:", body);
const inspectionUpdate = mapLabelDataToInspectionUpdate(body);
return inspectionsApi
.putInspectionInspectionsIdPut(id, inspectionUpdate, {
headers: { Authorization: authHeader },
})
.then((inspectionResponse) => {
const labelData = mapInspectionToLabelData(inspectionResponse.data);
console.debug("response:", labelData);
return Response.json(labelData);
})
.catch((error) => {
Expand Down
2 changes: 2 additions & 0 deletions src/app/api/inspections/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {

export async function POST(request: Request) {
const formData = await request.formData();
console.debug("request body (formdata):", formData);
const files = formData.getAll("files") as File[];
const labelDataString = formData.get("labelData") as string;
const labelData = JSON.parse(labelDataString);
Expand All @@ -24,6 +25,7 @@ export async function POST(request: Request) {
})
.then((inspectionsResponse) => {
const labelData = mapInspectionToLabelData(inspectionsResponse.data);
console.debug("response:", labelData);
return Response.json(labelData);
})
.catch((error) => {
Expand Down
119 changes: 106 additions & 13 deletions src/app/label-data-confirmation/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"use client";
import ImageViewer from "@/components/ImageViewer";
import useAlertStore from "@/stores/alertStore";
import useUploadedFilesStore from "@/stores/fileStore";
import useLabelDataStore from "@/stores/labelDataStore";
import { Quantity } from "@/types/types";
import { LabelData, Quantity } from "@/types/types";
import { processAxiosError } from "@/utils/client/apiErrors";
import {
Box,
Button,
Expand All @@ -20,9 +22,10 @@ import {
TableRow,
Typography,
} from "@mui/material";
import axios from "axios";
import Cookies from "js-cookie";
import { useRouter } from "next/navigation";
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import React, { useEffect, useState } from "react";

interface QuantityChipsProps extends React.ComponentProps<typeof Box> {
quantities: Quantity[] | undefined;
Expand All @@ -48,24 +51,112 @@ QuantityChips.displayName = "QuantityChips";

const LabelDataConfirmationPage = () => {
const labelData = useLabelDataStore((state) => state.labelData);
const updateConfirmed = useLabelDataStore((state) => state.updateConfirmed);
const setLabelData = useLabelDataStore((state) => state.setLabelData);
const { uploadedFiles } = useUploadedFilesStore();
const imageFiles = uploadedFiles.map((file) => file.getFile());
const { t } = useTranslation("labelDataValidator");
const router = useRouter();
const [loading, setLoading] = useState(false);
const showAlert = useAlertStore((state) => state.showAlert);
const [confirmed, setConfirmed] = useState(false);

useEffect(() => {
console.log(labelData);
}, [labelData]);
const getAuthHeader = () => {
return "Basic " + btoa(`${atob(Cookies.get("token") ?? "")}:`);
};

const updateLabelData = (labelData: LabelData, signal: AbortSignal) => {
if (!labelData.confirmed) {
showAlert("Internal error: Label data not confirmed.", "error");
return;
}
setLoading(true);
axios
.put(`/api/inspections/${labelData.inspectionId}`, labelData, {
headers: { Authorization: getAuthHeader() },
signal,
})
.then((response) => {
showAlert("Label data saved successfully.", "success");
const updatedLabelData: LabelData = response.data;
setLabelData(updatedLabelData);
router.push("/");
})
.catch((error) => {
showAlert(
`Label data saving failed: ${processAxiosError(error)}`,
"error",
);
})
.finally(() => {
setLoading(false);
});
};

const saveLabelData = (labelData: LabelData, signal: AbortSignal) => {
const formData = new FormData();
uploadedFiles.forEach((fileUploaded) => {
const file = fileUploaded.getFile();
formData.append("files", file);
});
formData.append("labelData", JSON.stringify(labelData));
setLoading(true);
axios
.post("/api/inspections", formData, {
headers: { Authorization: getAuthHeader() },
signal,
})
.then((response) => {
const initiallySavedLabelData: LabelData = {
...response.data,
confirmed: confirmed,
};
if (!initiallySavedLabelData.inspectionId) {
throw new Error("ID missing in initial label data saving response.");
}
setLabelData(initiallySavedLabelData);
updateLabelData(initiallySavedLabelData, signal);
})
.catch((error) => {
showAlert(
`Label data initial saving failed: ${processAxiosError(error)}`,
"error",
);
})
.finally(() => {
setLoading(false);
});
};

const handleEditClick = () => {
if (labelData?.inspection_id) {
router.push(`/label-data-validation/${labelData.inspection_id}`);
if (labelData?.inspectionId) {
router.push(`/label-data-validation/${labelData.inspectionId}`);
} else {
router.push("/label-data-validation");
}
};

const handleConfirmClick = () => {
if (!labelData) {
showAlert("Internal error: Label data not found.", "error");
return;
}
if (!confirmed) {
showAlert("Internal error: Label data not confirmed.", "error");
return;
}

const controller = new AbortController();
const signal = controller.signal;
if (labelData?.inspectionId) {
const updatedLabelData = { ...labelData, confirmed: confirmed };
return updateLabelData(updatedLabelData, signal);
}
return saveLabelData(labelData, signal);
};

useEffect(() => {
console.debug("labelData", labelData);
}, [labelData]);

return (
<Container
className="flex flex-col max-w-[1920px] bg-gray-100 text-black"
Expand Down Expand Up @@ -96,7 +187,6 @@ const LabelDataConfirmationPage = () => {
</Box>

<Box
// className="flex flex-col p-4 text-center gap-4 content-end bg-white border overflow-y-auto"
className="flex flex-col gap-4 flex-1 border overflow-y-auto sm:px-8 py-4"
data-testid="form-container"
>
Expand Down Expand Up @@ -450,8 +540,8 @@ const LabelDataConfirmationPage = () => {
<FormControlLabel
control={
<Checkbox
checked={labelData?.confirmed}
onChange={(event) => updateConfirmed(event.target.checked)}
checked={confirmed}
onChange={(event) => setConfirmed(event.target.checked)}
/>
}
label={
Expand All @@ -467,13 +557,16 @@ const LabelDataConfirmationPage = () => {
variant="contained"
color="success"
className="px-4 py-2 font-bold hover:bg-green-700"
disabled={!confirmed || loading}
onClick={handleConfirmClick}
data-testid="confirm-button"
>
Confirm
</Button>
<Button
variant="contained"
className="px-4 py-2 bg-gray-300 text-black font-bold hover:bg-gray-400"
disabled={loading}
onClick={handleEditClick}
data-testid="edit-button"
>
Expand Down
2 changes: 1 addition & 1 deletion src/app/label-data-validation/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function LabelDataValidationPage() {
})
.then((response) => {
const labelData: LabelData = response.data;
router.push(`/label-data-validation/${labelData.inspection_id}`);
router.push(`/label-data-validation/${labelData.inspectionId}`);
return null;
})
.catch((error) => {
Expand Down
13 changes: 1 addition & 12 deletions src/stores/labelDataStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,12 @@ interface LabelDataState {
labelData: LabelData | null;
setLabelData: (newData: LabelData) => void;
resetLabelData: () => void;
updateConfirmed: (isConfirmed: boolean) => void;
}

const useLabelDataStore = create<LabelDataState>((set) => ({
labelData: VERIFIED_LABEL_DATA,
labelData: null,
setLabelData: (newData) => set({ labelData: newData }),
resetLabelData: () => set({ labelData: null }),
updateConfirmed: (isConfirmed) =>
set((state) => {
if (!state.labelData) return state;
return {
labelData: {
...state.labelData,
confirmed: isConfirmed,
},
};
}),
}));

export default useLabelDataStore;
2 changes: 1 addition & 1 deletion src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export type LabelData = {
ingredients: BilingualField[];
confirmed: boolean;
comment?: string;
inspection_id?: string;
inspectionId?: string;
};

export const DEFAULT_LABEL_DATA: LabelData = {
Expand Down
Loading

0 comments on commit 4f5052e

Please sign in to comment.