Skip to content

Commit

Permalink
issue #433: save validation progress in cookies
Browse files Browse the repository at this point in the history
  • Loading branch information
k-allagbe committed Feb 19, 2025
1 parent eff4c6e commit b588cb3
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 21 deletions.
20 changes: 12 additions & 8 deletions docs/label-data-validation/flowchart.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ flowchart TD
```mermaid
flowchart TD
Start([Start]) --> LabelDataValidationID["/label-data-validation/id"]
%% Parallel branches
LabelDataValidationID --> ImagesUploaded{Images Uploaded?}
ImagesUploaded -->|No| GetInspections[GET /inspections/id]
ImagesUploaded -->|Yes| DisplayUploadedImages["Display Uploaded Images"]
DisplayUploadedImages --> GetInspections
GetInspections --> FetchSuccess{Success?}
FetchSuccess -->|No| HomePage["/home"]
FetchSuccess -->|Yes| DisplayData["Display Data"]
DisplayData --> End([End])
HomePage --> End
LabelDataValidationID --> FetchInspections[GET /inspections/id]
%% Image handling branch
ImagesUploaded -->|No| End([End])
ImagesUploaded -->|Yes| DisplayUploadedImages["Display Uploaded Images"] --> End
%% Inspection handling branch
FetchInspections --> FetchSuccess{Success?}
FetchSuccess -->|No| ErrorPage["Display Error Page"] --> End
FetchSuccess -->|Yes| UpdateValidationProgress["Update Validation Progress from Cookies"] --> DisplayData["Display Data"] --> End
```
2 changes: 1 addition & 1 deletion src/app/label-data-confirmation/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import useUploadedFilesStore from "@/stores/fileStore";
import useLabelDataStore from "@/stores/labelDataStore";
import { LabelData } from "@/types/types";
import { processAxiosError } from "@/utils/client/apiErrors";
import { getAuthHeader } from "@/utils/client/auth";
import { getAuthHeader } from "@/utils/client/cookies";
import { isAllVerified } from "@/utils/client/fieldValidation";
import { updateLabelData } from "@/utils/client/modelTransformation";
import {
Expand Down
9 changes: 5 additions & 4 deletions src/app/label-data-validation/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import LabelDataValidator from "@/components/LabelDataValidator";
import useAlertStore from "@/stores/alertStore";
import useUploadedFilesStore from "@/stores/fileStore";
import { DEFAULT_LABEL_DATA, LabelData } from "@/types/types";
import { getAuthHeader } from "@/utils/client/auth";
import { getAuthHeader, getLabelDataFromCookies } from "@/utils/client/cookies";
import { Box, CircularProgress } from "@mui/material";
import axios, { AxiosResponse } from "axios";
import Error from "next/error";
import { useParams, useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";

export default function Page() {
export default function LabelDataValidationPageWithId() {
const { id } = useParams();
const inspectionId = Array.isArray(id) ? id[0] : id;
const uploadedFiles = useUploadedFilesStore((state) => state.uploadedFiles);
Expand All @@ -24,7 +24,7 @@ export default function Page() {

useEffect(() => {
if (!inspectionId) return;

const controller = new AbortController();
const signal = controller.signal;

Expand All @@ -39,7 +39,8 @@ export default function Page() {
showAlert(t("alert.alreadyCompleted"), "warning");
return router.push("/");
}
setLabelData(labelData);
const c_labelData = getLabelDataFromCookies(inspectionId);
setLabelData(c_labelData ? c_labelData : labelData);
})
.catch((error) => {
if (axios.isCancel(error)) {
Expand Down
2 changes: 1 addition & 1 deletion src/app/label-inspections/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import useAlertStore from "@/stores/alertStore";
import useUploadedFilesStore from "@/stores/fileStore";
import { LabelData } from "@/types/types";
import { processAxiosError } from "@/utils/client/apiErrors";
import { getAuthHeader } from "@/utils/client/auth";
import { getAuthHeader } from "@/utils/client/cookies";
import {
Box,
Button,
Expand Down
12 changes: 10 additions & 2 deletions src/components/LabelDataValidator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import {
} from "@/components/stepper";
import useLabelDataStore from "@/stores/labelDataStore";
import { FormComponentProps, LabelData } from "@/types/types";
import {
getLabelDataFromCookies,
setLabelDataInCookies,
} from "@/utils/client/cookies";
import {
checkFieldArray,
checkFieldRecord,
Expand Down Expand Up @@ -47,7 +51,7 @@ interface LabelDataValidatorProps {
* @param {LabelDataValidatorProps} props - The properties passed to the component.
* @returns {JSX.Element} The rendered LabelDataValidator component.
*/
const LabelDataValidator=({
const LabelDataValidator = ({
loading = false,
fileUploads,
labelData,
Expand Down Expand Up @@ -203,6 +207,10 @@ const LabelDataValidator=({
);
}, [labelData.ingredients, setIngredientsStepStatus]);

useEffect(() => {
setLabelDataInCookies(labelData);
}, [labelData]);

return (
<Container
className="flex max-w-[1920px] flex-col bg-gray-100 text-black"
Expand Down Expand Up @@ -244,6 +252,6 @@ const LabelDataValidator=({
/>
</Container>
);
}
};

export default LabelDataValidator;
91 changes: 91 additions & 0 deletions src/utils/client/__tests__/cookies.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import Cookies from "js-cookie";
import { VERIFIED_LABEL_DATA, VERIFIED_LABEL_DATA_WITH_ID } from "../constants";
import {
getAuthHeader,
getLabelDataFromCookies,
setLabelDataInCookies,
} from "../cookies";

jest.mock("js-cookie");

describe("getAuthHeader", () => {
it("should return the correct Authorization header", () => {
(Cookies.get as jest.Mock).mockReturnValue(btoa("testUser:password"));
const authHeader = getAuthHeader();
expect(authHeader).toBe("Basic dGVzdFVzZXI6cGFzc3dvcmQ6");
});

it("should return empty Authorization header if token is missing", () => {
(Cookies.get as jest.Mock).mockReturnValue(undefined);
const authHeader = getAuthHeader();
expect(authHeader).toBe("Basic Og==");
});
});

describe("setLabelDataInCookies", () => {
beforeEach(() => {
jest.clearAllMocks();
});

it("should set label data with an inspectionId", () => {
setLabelDataInCookies(VERIFIED_LABEL_DATA_WITH_ID);
expect(Cookies.set).toHaveBeenCalledWith(
"labelData_1234",
JSON.stringify(VERIFIED_LABEL_DATA_WITH_ID),
{ expires: 1 },
);
});

it("should set label data with default name if no inspectionId", () => {
setLabelDataInCookies(VERIFIED_LABEL_DATA);
expect(Cookies.set).toHaveBeenCalledWith(
"labelData_no_id",
JSON.stringify(VERIFIED_LABEL_DATA),
{ expires: 1 },
);
});
});

describe("getLabelDataFromCookies", () => {
beforeEach(() => {
jest.clearAllMocks();
});

it("should retrieve label data if cookie exists", () => {
(Cookies.get as jest.Mock).mockReturnValue(
JSON.stringify(VERIFIED_LABEL_DATA_WITH_ID),
);
const result = getLabelDataFromCookies("1234");
expect(result).toEqual(VERIFIED_LABEL_DATA_WITH_ID);
});

it("should return null if cookie does not exist", () => {
(Cookies.get as jest.Mock).mockReturnValue(undefined);
const result = getLabelDataFromCookies("1234");
expect(result).toBeNull();
});

it("should retrieve label data with default name if no inspectionId", () => {
(Cookies.get as jest.Mock).mockReturnValue(
JSON.stringify(VERIFIED_LABEL_DATA),
);
const result = getLabelDataFromCookies(null);
expect(result).toEqual(VERIFIED_LABEL_DATA);
});

it("should retrieve label data with default name if inspectionId is an empty string", () => {
(Cookies.get as jest.Mock).mockReturnValue(
JSON.stringify(VERIFIED_LABEL_DATA),
);
const result = getLabelDataFromCookies("");
expect(result).toEqual(VERIFIED_LABEL_DATA);
});

it("should retrieve label data with default name if inspectionId is undefined", () => {
(Cookies.get as jest.Mock).mockReturnValue(
JSON.stringify(VERIFIED_LABEL_DATA),
);
const result = getLabelDataFromCookies(undefined);
expect(result).toEqual(VERIFIED_LABEL_DATA);
});
});
5 changes: 0 additions & 5 deletions src/utils/client/auth.ts

This file was deleted.

31 changes: 31 additions & 0 deletions src/utils/client/cookies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { LabelData } from "@/types/types";
import Cookies from "js-cookie";

const COOKIE_PREFIX = "labelData_";

const getCookieName = (inspectionId?: string | null) =>
COOKIE_PREFIX + (inspectionId || "no_id");

export const getAuthHeader = () => {
return "Basic " + btoa(`${atob(Cookies.get("token") ?? "")}:`);
};

export const setLabelDataInCookies = (labelData: LabelData) => {
const cookieName = getCookieName(labelData.inspectionId);

console.debug(`[Cookies] Setting label data for:`, cookieName);

Cookies.set(cookieName, JSON.stringify(labelData), { expires: 1 });
};

export const getLabelDataFromCookies = (
inspectionId: string | null | undefined,
): LabelData | null => {
const cookieName = getCookieName(inspectionId);

const data = Cookies.get(cookieName);
if (!data) return null;

console.debug(`[Cookies] Retrieved label data for:`, cookieName);
return JSON.parse(data);
};

0 comments on commit b588cb3

Please sign in to comment.