From d0159383d80b7f6b531b6e404c9a231fb0fb4ac1 Mon Sep 17 00:00:00 2001 From: Youllou Date: Tue, 19 Nov 2024 12:53:44 -0500 Subject: [PATCH 01/15] DashBoard page + link to page in UserMenu.tsx --- src/app/dashboard/page.tsx | 8 ++++++++ src/components/UserMenu.tsx | 9 ++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/app/dashboard/page.tsx diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx new file mode 100644 index 00000000..9467f90f --- /dev/null +++ b/src/app/dashboard/page.tsx @@ -0,0 +1,8 @@ +// default page +import React from 'react'; + +const Dashboard = () => { + return
Dashboard
; +}; + +export default Dashboard; \ No newline at end of file diff --git a/src/components/UserMenu.tsx b/src/components/UserMenu.tsx index 86683d93..7a7bb141 100644 --- a/src/components/UserMenu.tsx +++ b/src/components/UserMenu.tsx @@ -15,6 +15,7 @@ import { useCallback, useEffect, } from "react"; +import { useRouter } from "next/navigation"; import { useTranslation } from "react-i18next"; // import useBreakpoints from "@/utils/useBreakpoints"; @@ -51,6 +52,7 @@ const UserMenu = ({ setAnchorElement, }: UserMenuProps): ReactElement => { const placeholderUser = usePlaceholder(); + const router = useRouter() const { t } = useTranslation("header"); const handleClose = useCallback((): void => { @@ -58,6 +60,11 @@ const UserMenu = ({ setAnchorElement(null); }, [setIsUserMenuOpen, setAnchorElement]); + const handleDashboardClick = (): void => { + router.push("/dashboard"); + handleClose(); + } + const handleLogout = (): void => { document.cookie="token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=Strict"; location.reload() @@ -100,7 +107,7 @@ const UserMenu = ({ {placeholderUser.getUsername()} - + From 26aacd9289ff08cde538f808b35aa9694034fe0a Mon Sep 17 00:00:00 2001 From: Youllou Date: Thu, 21 Nov 2024 13:01:27 -0500 Subject: [PATCH 02/15] User infos on dashboard + start of FertilizerList.tsx --- src/app/dashboard/page.tsx | 56 +++++++++++++++++++++++++++++-- src/components/FertilizerList.tsx | 27 +++++++++++++++ src/types/FertilizerPreview.ts | 7 ++++ 3 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 src/components/FertilizerList.tsx create mode 100644 src/types/FertilizerPreview.ts diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 9467f90f..c0d3f619 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -1,8 +1,60 @@ // default page import React from 'react'; +import FertilizerList from "@/components/FertilizerList"; +import { Grid2 as Grid, InputAdornment, TextField, Typography } from "@mui/material"; +import { Search, LocationOn } from "@mui/icons-material"; + + const Dashboard = () => { - return
Dashboard
; + return + + + + Username + + Mail:User email + Role:User role + :User location + + + + Number of inspections + + + + + + + My inspections + + + + + + ) + } + }} + /> + +
+ + + +
+
+
}; -export default Dashboard; \ No newline at end of file +export default Dashboard; diff --git a/src/components/FertilizerList.tsx b/src/components/FertilizerList.tsx new file mode 100644 index 00000000..c919684c --- /dev/null +++ b/src/components/FertilizerList.tsx @@ -0,0 +1,27 @@ +"use client" +import { useEffect, useState } from "react"; +import { Card, Stack, Typography } from "@mui/material"; +import fertilizerPreview from "@/types/FertilizerPreview"; +import Image from "next/image"; + +const FertilizerList = ()=>{ + + const [fertiList, setFertiList] = useState([] as fertilizerPreview[]) + + useEffect(() => { + setFertiList([...fertiList, {id: 1, finished: false, name: "Fertilizer 1", image: null}]) + }, []); + + return + {fertiList.map((fertilizer, index) => { + return + + {"fertilizer + {fertilizer.name} + + + })} + +} + +export default FertilizerList \ No newline at end of file diff --git a/src/types/FertilizerPreview.ts b/src/types/FertilizerPreview.ts new file mode 100644 index 00000000..b739a83c --- /dev/null +++ b/src/types/FertilizerPreview.ts @@ -0,0 +1,7 @@ +type FertilizerPreview = { + id: number; + finished: boolean; + name: string; + image: File | null; +} +export default FertilizerPreview; \ No newline at end of file From b0074253eecf68c76914f3f3678239c436286a35 Mon Sep 17 00:00:00 2001 From: Youllou Date: Thu, 12 Dec 2024 13:15:14 -0500 Subject: [PATCH 03/15] Modified some style elements, started working on scroll of fertilizer list --- src/app/dashboard/page.tsx | 9 ++++++--- src/components/FertilizerList.tsx | 10 +++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index c0d3f619..2e2a8ab9 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -26,7 +26,7 @@ const Dashboard = () => { - + My inspections @@ -37,10 +37,13 @@ const Dashboard = () => { variant={"filled"} fullWidth slotProps={{ + htmlInput: { + className: "!p-0 after:!transition-none " + }, input: { - className: "after:!transition-none", + className:"p-2", startAdornment:( - + ) diff --git a/src/components/FertilizerList.tsx b/src/components/FertilizerList.tsx index c919684c..9ee3e3cc 100644 --- a/src/components/FertilizerList.tsx +++ b/src/components/FertilizerList.tsx @@ -9,10 +9,14 @@ const FertilizerList = ()=>{ const [fertiList, setFertiList] = useState([] as fertilizerPreview[]) useEffect(() => { - setFertiList([...fertiList, {id: 1, finished: false, name: "Fertilizer 1", image: null}]) - }, []); + setFertiList([...fertiList, + {id: 1, finished: false, name: "Fertilizer 1", image: null}, + {id: 2, finished: true, name: "Fertilizer 2", image: null}, + {id: 3, finished: true, name: "Fertilizer 3", image: null}, + ]) + }, [fertiList]); - return + return {fertiList.map((fertilizer, index) => { return From 3ec24690ed3542636fad88ee681c20aa85fe4026 Mon Sep 17 00:00:00 2001 From: Youllou Date: Tue, 17 Dec 2024 16:27:14 -0500 Subject: [PATCH 04/15] Finished the styling of the InspectionList.tsx and made backend fetching logic - Renamed FertilizerList.tsx to InspectionList.tsx - Popped out InspectionElement.tsx of InspectionList.tsx - Created test files (test are to do) - Renamed FertilizerPreview.ts to InspectionPreview.ts - Modified InspectionPreview.ts to represent the exact data sent by the backend - added a GET to @/app/api/inspections/route.ts - Use this new route in InspectionList.tsx - Added click event on InspectionElement.tsx - Configured the search in @/app/dashboard/page.tsx --- Dockefile | 0 src/app/api/inspections/route.ts | 23 +++++++++ src/app/dashboard/page.tsx | 15 +++--- src/components/FertilizerList.tsx | 31 ----------- .../InspectionList/InspectionElement.tsx | 28 ++++++++++ .../InspectionList/InspectionList.tsx | 51 +++++++++++++++++++ .../__tests__/InspectionElement.test.tsx | 5 ++ .../__tests__/InspectionList.test.tsx | 5 ++ src/types/FertilizerPreview.ts | 7 --- src/types/InspectionPreview.ts | 47 +++++++++++++++++ 10 files changed, 168 insertions(+), 44 deletions(-) delete mode 100644 Dockefile delete mode 100644 src/components/FertilizerList.tsx create mode 100644 src/components/InspectionList/InspectionElement.tsx create mode 100644 src/components/InspectionList/InspectionList.tsx create mode 100644 src/components/InspectionList/__tests__/InspectionElement.test.tsx create mode 100644 src/components/InspectionList/__tests__/InspectionList.test.tsx delete mode 100644 src/types/FertilizerPreview.ts create mode 100644 src/types/InspectionPreview.ts diff --git a/Dockefile b/Dockefile deleted file mode 100644 index e69de29b..00000000 diff --git a/src/app/api/inspections/route.ts b/src/app/api/inspections/route.ts index cf48e129..98a4d377 100644 --- a/src/app/api/inspections/route.ts +++ b/src/app/api/inspections/route.ts @@ -28,3 +28,26 @@ export async function POST(request: Request) { return handleApiError(error); }); } + +export async function GET(request: Request){ + const authHeader = request.headers.get("Authorization"); + if (!authHeader) { + return new Response( + JSON.stringify({ error: "Missing Authorization header" }), + { + status: 401, + }, + ); + } + + return inspectionsApi + .getInspectionsInspectionsGet({ + headers: { Authorization: authHeader }, + }) + .then((inspectionsResponse) => { + return Response.json(inspectionsResponse.data); + }) + .catch((error) => { + return handleApiError(error); + }); +} diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 2e2a8ab9..91d3dea1 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -1,15 +1,16 @@ -// default page -import React from 'react'; -import FertilizerList from "@/components/FertilizerList"; +"use client" +import FertilizerList from "@/components/InspectionList/InspectionList"; import { Grid2 as Grid, InputAdornment, TextField, Typography } from "@mui/material"; import { Search, LocationOn } from "@mui/icons-material"; +import { useState } from "react"; +const Dashboard = () => { + const [search, setSearch] = useState(""); -const Dashboard = () => { return @@ -35,6 +36,8 @@ const Dashboard = () => { setSearch(e.target.value)} fullWidth slotProps={{ htmlInput: { @@ -53,7 +56,7 @@ const Dashboard = () => {
- +
diff --git a/src/components/FertilizerList.tsx b/src/components/FertilizerList.tsx deleted file mode 100644 index 9ee3e3cc..00000000 --- a/src/components/FertilizerList.tsx +++ /dev/null @@ -1,31 +0,0 @@ -"use client" -import { useEffect, useState } from "react"; -import { Card, Stack, Typography } from "@mui/material"; -import fertilizerPreview from "@/types/FertilizerPreview"; -import Image from "next/image"; - -const FertilizerList = ()=>{ - - const [fertiList, setFertiList] = useState([] as fertilizerPreview[]) - - useEffect(() => { - setFertiList([...fertiList, - {id: 1, finished: false, name: "Fertilizer 1", image: null}, - {id: 2, finished: true, name: "Fertilizer 2", image: null}, - {id: 3, finished: true, name: "Fertilizer 3", image: null}, - ]) - }, [fertiList]); - - return - {fertiList.map((fertilizer, index) => { - return - - {"fertilizer - {fertilizer.name} - - - })} - -} - -export default FertilizerList \ No newline at end of file diff --git a/src/components/InspectionList/InspectionElement.tsx b/src/components/InspectionList/InspectionElement.tsx new file mode 100644 index 00000000..a5cd15aa --- /dev/null +++ b/src/components/InspectionList/InspectionElement.tsx @@ -0,0 +1,28 @@ +import { Box, Card, Stack, Typography } from "@mui/material"; +import ErrorIcon from "@mui/icons-material/Error"; +import React from "react"; +import InspectionPreview from "@/types/InspectionPreview"; + +interface InspectionElementProps { + inspection: InspectionPreview; + key: string; + handleClick(): void; +} + +const InspectionElement = ({inspection, key, handleClick}: InspectionElementProps) => { + return + + + {inspection.product_name} + {inspection.updated_at===inspection.upload_date && } + + +} + +export default InspectionElement; \ No newline at end of file diff --git a/src/components/InspectionList/InspectionList.tsx b/src/components/InspectionList/InspectionList.tsx new file mode 100644 index 00000000..7977b135 --- /dev/null +++ b/src/components/InspectionList/InspectionList.tsx @@ -0,0 +1,51 @@ +"use client" +import { Stack } from "@mui/material"; +import InspectionPreview from "@/types/InspectionPreview"; +import InspectionElement from "@/components/InspectionList/InspectionElement"; +import { useEffect, useState } from "react"; +import axios from "axios"; +import Cookies from "js-cookie"; +import { useRouter } from "next/navigation"; + +interface InspectionListProps { + search: string; +} + +const InspectionList = ({search}:InspectionListProps)=>{ + + const [inspectList, setInspectList] = useState([] as InspectionPreview[]) + const [shownList, setShownList] = useState([] as InspectionPreview[]) + + const router = useRouter(); + + const handleInspectionClick = (id: string) => { + router.push(`/label-data-validation/${id}`); + } + + useEffect(() => { + const username = atob(Cookies.get("token") ?? ""); + const password = ""; + const authHeader = "Basic " + btoa(`${username}:${password}`); + axios.get("/api/inspections", + { + headers: { + Authorization: authHeader + }, + }).then((response) => { + setInspectList(response.data); + setShownList(response.data); + }); + }, []); + useEffect(() => { + setShownList(inspectList.filter((inspection) => { + return inspection.product_name!.toLowerCase().includes(search.toLowerCase()); + })); + }, [inspectList, search]); + return + {shownList.map((inspection) => { + return handleInspectionClick(inspection.id)}/> + })} + +} + +export default InspectionList \ No newline at end of file diff --git a/src/components/InspectionList/__tests__/InspectionElement.test.tsx b/src/components/InspectionList/__tests__/InspectionElement.test.tsx new file mode 100644 index 00000000..b9d15db5 --- /dev/null +++ b/src/components/InspectionList/__tests__/InspectionElement.test.tsx @@ -0,0 +1,5 @@ +describe('InspectionElement', () => { + it('TODO', () => { + expect(false).toBe(true) + }) +}) \ No newline at end of file diff --git a/src/components/InspectionList/__tests__/InspectionList.test.tsx b/src/components/InspectionList/__tests__/InspectionList.test.tsx new file mode 100644 index 00000000..b7221486 --- /dev/null +++ b/src/components/InspectionList/__tests__/InspectionList.test.tsx @@ -0,0 +1,5 @@ +describe('InspectionList', () => { + it('TODO', () => { + expect(false).toBe(true) + }) +}) \ No newline at end of file diff --git a/src/types/FertilizerPreview.ts b/src/types/FertilizerPreview.ts deleted file mode 100644 index b739a83c..00000000 --- a/src/types/FertilizerPreview.ts +++ /dev/null @@ -1,7 +0,0 @@ -type FertilizerPreview = { - id: number; - finished: boolean; - name: string; - image: File | null; -} -export default FertilizerPreview; \ No newline at end of file diff --git a/src/types/InspectionPreview.ts b/src/types/InspectionPreview.ts new file mode 100644 index 00000000..53004ff6 --- /dev/null +++ b/src/types/InspectionPreview.ts @@ -0,0 +1,47 @@ +/** + * Response body + * + * [ + * { + * "id": "5cabc8c4-e418-4bf0-84b4-eeb2aa9c30c7", + * "upload_date": "2024-12-12T16:52:56.728348", + * "updated_at": "2024-12-12T16:52:56.728348", + * "sample_id": null, + * "picture_set_id": "ea19b682-dfe0-4216-baa1-6f2410c0e604", + * "label_info_id": "e7ccd300-e0f6-4912-8bbb-d1cb9db6ae7e", + * "product_name": "Granular Zinc 20%", + * "manufacturer_info_id": null, + * "company_info_id": "e0c43744-21f1-4c68-a4c8-e6f498f0b708", + * "company_name": "Cameron Chemicals, Inc." + * }, + * { + * "id": "bf78d5aa-92e9-4be0-9a4a-393dd892a76d", + * "upload_date": "2024-12-17T18:15:28.043513", + * "updated_at": "2024-12-17T18:17:01.313238", + * "sample_id": null, + * "picture_set_id": null, + * "label_info_id": "b9c8a95d-4f99-47aa-b0f3-279788dcf296", + * "product_name": "test2", + * "manufacturer_info_id": "23aa9ed9-543b-49a7-8945-c680a47266f5", + * "company_info_id": "ae386ab9-f702-474b-ab13-b102a464dc70", + * "company_name": "WILLIAM HO" + * } + * ] + * + * Response headers + * + * content-length: 816 content-type: application/json date: Tue,17 Dec 2024 18:24:31 GMT server: uvicorn + */ +type InspectionPreview = { + id: string; + upload_date: string; + updated_at: string; + sample_id: string|null; + picture_set_id: string|null; + label_info_id: string; + product_name: string|null; + manufacturer_info_id: string|null; + company_info_id: string; + company_name: string|null; +} +export default InspectionPreview; \ No newline at end of file From 9074389d63501a30a3e6e81f2d7ab6c4c9b4ea78 Mon Sep 17 00:00:00 2001 From: Youllou Date: Tue, 17 Dec 2024 16:28:46 -0500 Subject: [PATCH 05/15] prettier --- src/app/api/inspections/route.ts | 2 +- src/app/dashboard/page.tsx | 129 +++++++++++------- .../InspectionList/InspectionList.tsx | 62 +++++---- .../__tests__/InspectionElement.test.tsx | 10 +- .../__tests__/InspectionList.test.tsx | 10 +- src/types/InspectionPreview.ts | 14 +- 6 files changed, 135 insertions(+), 92 deletions(-) diff --git a/src/app/api/inspections/route.ts b/src/app/api/inspections/route.ts index 98a4d377..f3a9aa04 100644 --- a/src/app/api/inspections/route.ts +++ b/src/app/api/inspections/route.ts @@ -29,7 +29,7 @@ export async function POST(request: Request) { }); } -export async function GET(request: Request){ +export async function GET(request: Request) { const authHeader = request.headers.get("Authorization"); if (!authHeader) { return new Response( diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 91d3dea1..5d918ebb 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -1,66 +1,97 @@ -"use client" +"use client"; import FertilizerList from "@/components/InspectionList/InspectionList"; -import { Grid2 as Grid, InputAdornment, TextField, Typography } from "@mui/material"; +import { + Grid2 as Grid, + InputAdornment, + TextField, + Typography, +} from "@mui/material"; import { Search, LocationOn } from "@mui/icons-material"; import { useState } from "react"; const Dashboard = () => { - const [search, setSearch] = useState(""); - return + + - - - - Username + + + Username + + + + Mail: + + User email + + Role: + + User role + + + : + + + User location - Mail:User email - Role:User role - :User location - - - - Number of inspections + + + + Number of inspections + + - - - - - My inspections - - - setSearch(e.target.value)} - fullWidth - slotProps={{ - htmlInput: { - className: "!p-0 after:!transition-none " - }, - input: { - className:"p-2", - startAdornment:( - - - - ) - } - }} - /> - -
- - + + + + + My inspections + + + + setSearch(e.target.value)} + fullWidth + slotProps={{ + htmlInput: { + className: "!p-0 after:!transition-none ", + }, + input: { + className: "p-2", + startAdornment: ( + + + + ), + }, + }} + /> + +
+ + +
-
+ ); }; export default Dashboard; diff --git a/src/components/InspectionList/InspectionList.tsx b/src/components/InspectionList/InspectionList.tsx index 7977b135..adf4b333 100644 --- a/src/components/InspectionList/InspectionList.tsx +++ b/src/components/InspectionList/InspectionList.tsx @@ -1,4 +1,4 @@ -"use client" +"use client"; import { Stack } from "@mui/material"; import InspectionPreview from "@/types/InspectionPreview"; import InspectionElement from "@/components/InspectionList/InspectionElement"; @@ -11,41 +11,53 @@ interface InspectionListProps { search: string; } -const InspectionList = ({search}:InspectionListProps)=>{ - - const [inspectList, setInspectList] = useState([] as InspectionPreview[]) - const [shownList, setShownList] = useState([] as InspectionPreview[]) +const InspectionList = ({ search }: InspectionListProps) => { + const [inspectList, setInspectList] = useState([] as InspectionPreview[]); + const [shownList, setShownList] = useState([] as InspectionPreview[]); const router = useRouter(); const handleInspectionClick = (id: string) => { router.push(`/label-data-validation/${id}`); - } + }; useEffect(() => { const username = atob(Cookies.get("token") ?? ""); const password = ""; const authHeader = "Basic " + btoa(`${username}:${password}`); - axios.get("/api/inspections", - { - headers: { - Authorization: authHeader - }, - }).then((response) => { - setInspectList(response.data); - setShownList(response.data); - }); + axios + .get("/api/inspections", { + headers: { + Authorization: authHeader, + }, + }) + .then((response) => { + setInspectList(response.data); + setShownList(response.data); + }); }, []); useEffect(() => { - setShownList(inspectList.filter((inspection) => { - return inspection.product_name!.toLowerCase().includes(search.toLowerCase()); - })); + setShownList( + inspectList.filter((inspection) => { + return inspection + .product_name!.toLowerCase() + .includes(search.toLowerCase()); + }), + ); }, [inspectList, search]); - return - {shownList.map((inspection) => { - return handleInspectionClick(inspection.id)}/> - })} - -} + return ( + + {shownList.map((inspection) => { + return ( + handleInspectionClick(inspection.id)} + /> + ); + })} + + ); +}; -export default InspectionList \ No newline at end of file +export default InspectionList; diff --git a/src/components/InspectionList/__tests__/InspectionElement.test.tsx b/src/components/InspectionList/__tests__/InspectionElement.test.tsx index b9d15db5..d8ab6fd6 100644 --- a/src/components/InspectionList/__tests__/InspectionElement.test.tsx +++ b/src/components/InspectionList/__tests__/InspectionElement.test.tsx @@ -1,5 +1,5 @@ -describe('InspectionElement', () => { - it('TODO', () => { - expect(false).toBe(true) - }) -}) \ No newline at end of file +describe("InspectionElement", () => { + it("TODO", () => { + expect(false).toBe(true); + }); +}); diff --git a/src/components/InspectionList/__tests__/InspectionList.test.tsx b/src/components/InspectionList/__tests__/InspectionList.test.tsx index b7221486..bbd866bd 100644 --- a/src/components/InspectionList/__tests__/InspectionList.test.tsx +++ b/src/components/InspectionList/__tests__/InspectionList.test.tsx @@ -1,5 +1,5 @@ -describe('InspectionList', () => { - it('TODO', () => { - expect(false).toBe(true) - }) -}) \ No newline at end of file +describe("InspectionList", () => { + it("TODO", () => { + expect(false).toBe(true); + }); +}); diff --git a/src/types/InspectionPreview.ts b/src/types/InspectionPreview.ts index 53004ff6..212e54e9 100644 --- a/src/types/InspectionPreview.ts +++ b/src/types/InspectionPreview.ts @@ -36,12 +36,12 @@ type InspectionPreview = { id: string; upload_date: string; updated_at: string; - sample_id: string|null; - picture_set_id: string|null; + sample_id: string | null; + picture_set_id: string | null; label_info_id: string; - product_name: string|null; - manufacturer_info_id: string|null; + product_name: string | null; + manufacturer_info_id: string | null; company_info_id: string; - company_name: string|null; -} -export default InspectionPreview; \ No newline at end of file + company_name: string | null; +}; +export default InspectionPreview; From 8c26b3e1d5030b9bc3d3eca80545f891ffffe076 Mon Sep 17 00:00:00 2001 From: Youllou Date: Tue, 17 Dec 2024 16:30:12 -0500 Subject: [PATCH 06/15] eof in InspectionElement.tsx --- src/components/InspectionList/InspectionElement.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/InspectionList/InspectionElement.tsx b/src/components/InspectionList/InspectionElement.tsx index a5cd15aa..69779ce3 100644 --- a/src/components/InspectionList/InspectionElement.tsx +++ b/src/components/InspectionList/InspectionElement.tsx @@ -25,4 +25,4 @@ const InspectionElement = ({inspection, key, handleClick}: InspectionElementProp
} -export default InspectionElement; \ No newline at end of file +export default InspectionElement; From 74d9f53f4c40f32d3abbc65f6afc88f3ef10de72 Mon Sep 17 00:00:00 2001 From: Youllou Date: Fri, 10 Jan 2025 13:14:59 -0500 Subject: [PATCH 07/15] Tests for InspectionElement.tsx and InspectionList.tsx Moved request to backend logic from InspectionList.tsx to dashboard page Made some css modification for a full zoom and responsiveness compliance Started working on Dashboard.test.tsx (Not sure what to test in there) --- .../dashboard/__tests__/Dashboard.test.tsx | 69 +++++++++++++++++++ src/app/dashboard/page.tsx | 37 ++++++++-- .../InspectionList/InspectionElement.tsx | 8 +-- .../InspectionList/InspectionList.tsx | 27 ++------ .../__tests__/InspectionElement.test.tsx | 52 +++++++++++++- .../__tests__/InspectionList.test.tsx | 62 ++++++++++++++++- 6 files changed, 218 insertions(+), 37 deletions(-) create mode 100644 src/app/dashboard/__tests__/Dashboard.test.tsx diff --git a/src/app/dashboard/__tests__/Dashboard.test.tsx b/src/app/dashboard/__tests__/Dashboard.test.tsx new file mode 100644 index 00000000..635848fa --- /dev/null +++ b/src/app/dashboard/__tests__/Dashboard.test.tsx @@ -0,0 +1,69 @@ +import { render } from "@testing-library/react"; +import Dashboard from "@/app/dashboard/page"; +import { Response } from "whatwg-fetch"; +import axios from "axios"; + +// Mock useRouter: +jest.mock("next/navigation", () => ({ + useRouter() { + return { + prefetch: () => null + }; + } +})); + +const mockInspectList = [ + { + company_info_id: "", + company_name: "test_company", + label_info_id: "", + manufacturer_info_id: "test_manufacturer", + picture_set_id: "", + sample_id: "", + id: "1", + product_name: "Fertilizer 1", + upload_date: new Date().toDateString(), + updated_at: new Date(new Date().getDate()+5).toDateString() + },{ + company_info_id: "", + company_name: "test_company", + label_info_id: "", + manufacturer_info_id: "test_manufacturer", + picture_set_id: "", + sample_id: "", + id: "2", + product_name: "Fertilizer 2", + upload_date: new Date().toDateString(), + updated_at: new Date().toDateString() +} + +] + +axios.get = jest.fn((path: string | URL | Request)=>{ + if(path){ + return Promise.resolve( + new Response(mockInspectList,{ + status:200, + headers: new Headers({"Content-Type":"application/json"}) + }) + ) + }else{ + return Promise.reject( + new Response("",{ + status:400, + headers: new Headers({"Content-Type":"application/json"}) + }) + ) + } +}) + +describe("Dashboard", () => { + + it("renders the dashboard", async () => { + render( + + ); + expect(true).toBe(true); + }); + +}); \ No newline at end of file diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 5d918ebb..ba4b9772 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -7,13 +7,32 @@ import { Typography, } from "@mui/material"; import { Search, LocationOn } from "@mui/icons-material"; -import { useState } from "react"; +import { useEffect, useState } from "react"; +import Cookies from "js-cookie"; +import axios from "axios"; +import theme from "@/app/theme"; const Dashboard = () => { const [search, setSearch] = useState(""); + const [inspectList, setInspectList] = useState([]); + + useEffect(() => { + const username = atob(Cookies.get("token") ?? ""); + const password = ""; + const authHeader = "Basic " + btoa(`${username}:${password}`); + axios + .get("/api/inspections", { + headers: { + Authorization: authHeader, + }, + }) + .then((response) => { + setInspectList(response.data); + }); + }, []); return ( - + { @@ -66,6 +85,10 @@ const Dashboard = () => { setSearch(e.target.value)} fullWidth @@ -76,8 +99,8 @@ const Dashboard = () => { input: { className: "p-2", startAdornment: ( - - + + ), }, @@ -85,8 +108,8 @@ const Dashboard = () => { />
- - + +
diff --git a/src/components/InspectionList/InspectionElement.tsx b/src/components/InspectionList/InspectionElement.tsx index 69779ce3..e07c8510 100644 --- a/src/components/InspectionList/InspectionElement.tsx +++ b/src/components/InspectionList/InspectionElement.tsx @@ -9,18 +9,18 @@ interface InspectionElementProps { handleClick(): void; } -const InspectionElement = ({inspection, key, handleClick}: InspectionElementProps) => { - return +const InspectionElement = ({inspection, handleClick}: InspectionElementProps) => { + return {inspection.product_name} - {inspection.updated_at===inspection.upload_date && } + {inspection.updated_at===inspection.upload_date && } } diff --git a/src/components/InspectionList/InspectionList.tsx b/src/components/InspectionList/InspectionList.tsx index adf4b333..8d9b4da9 100644 --- a/src/components/InspectionList/InspectionList.tsx +++ b/src/components/InspectionList/InspectionList.tsx @@ -3,16 +3,14 @@ import { Stack } from "@mui/material"; import InspectionPreview from "@/types/InspectionPreview"; import InspectionElement from "@/components/InspectionList/InspectionElement"; import { useEffect, useState } from "react"; -import axios from "axios"; -import Cookies from "js-cookie"; import { useRouter } from "next/navigation"; interface InspectionListProps { search: string; + inspectionList: InspectionPreview[]; } -const InspectionList = ({ search }: InspectionListProps) => { - const [inspectList, setInspectList] = useState([] as InspectionPreview[]); +const InspectionList = ({ search, inspectionList }: InspectionListProps) => { const [shownList, setShownList] = useState([] as InspectionPreview[]); const router = useRouter(); @@ -21,32 +19,17 @@ const InspectionList = ({ search }: InspectionListProps) => { router.push(`/label-data-validation/${id}`); }; - useEffect(() => { - const username = atob(Cookies.get("token") ?? ""); - const password = ""; - const authHeader = "Basic " + btoa(`${username}:${password}`); - axios - .get("/api/inspections", { - headers: { - Authorization: authHeader, - }, - }) - .then((response) => { - setInspectList(response.data); - setShownList(response.data); - }); - }, []); useEffect(() => { setShownList( - inspectList.filter((inspection) => { + inspectionList.filter((inspection) => { return inspection .product_name!.toLowerCase() .includes(search.toLowerCase()); }), ); - }, [inspectList, search]); + }, [inspectionList, search]); return ( - + {shownList.map((inspection) => { return ( { - it("TODO", () => { - expect(false).toBe(true); + + const mockFinishedInspection : InspectionPreview = { + company_info_id: "", + company_name: "test_company", + label_info_id: "", + manufacturer_info_id: "test_manufacturer", + picture_set_id: "", + sample_id: "", + id: "1", + product_name: "Fertilizer 1", + upload_date: new Date().toDateString(), + updated_at: new Date(new Date().getDate()+5).toDateString() + } + const mockUnfinishedInspection : InspectionPreview = { + company_info_id: "", + company_name: "test_company", + label_info_id: "", + manufacturer_info_id: "test_manufacturer", + picture_set_id: "", + sample_id: "", + id: "2", + product_name: "Fertilizer 2", + upload_date: new Date().toDateString(), + updated_at: new Date().toDateString() + } + + const handleClick = jest.fn(); + + it("renders an finished InspectionElement and check that all elements are present and that the error icon is not present", () => { + render( {}} />); + expect(screen.getByText("Fertilizer 1")).toBeInTheDocument(); + expect(screen.getByTestId("image")).toBeInTheDocument(); + expect(screen.queryByTestId("error-icon")).not.toBeInTheDocument(); + }); + + it("renders an unfinished InspectionElement and check that all elements are present and that the error icon is present", () => { + render( {}} />); + expect(screen.getByText("Fertilizer 2")).toBeInTheDocument(); + expect(screen.getByTestId("image")).toBeInTheDocument(); + expect(screen.getByTestId("error-icon")).toBeInTheDocument(); + }); + + it("clicks on the InspectionElement and check that the handleClick function has been called", () => { + render(); + screen.getByText("Fertilizer 1").click(); + expect(handleClick).toHaveBeenCalled(); }); }); diff --git a/src/components/InspectionList/__tests__/InspectionList.test.tsx b/src/components/InspectionList/__tests__/InspectionList.test.tsx index bbd866bd..a38860f8 100644 --- a/src/components/InspectionList/__tests__/InspectionList.test.tsx +++ b/src/components/InspectionList/__tests__/InspectionList.test.tsx @@ -1,5 +1,63 @@ +import { render, screen } from "@testing-library/react"; +import InspectionList from "@/components/InspectionList/InspectionList"; + +import i18n from "@/app/i18n"; + +// Mock useRouter: +jest.mock("next/navigation", () => ({ + useRouter() { + return { + prefetch: () => null + }; + } +})); + +const mockFinishedInspection = { + company_info_id: "", + company_name: "test_company", + label_info_id: "", + manufacturer_info_id: "test_manufacturer", + picture_set_id: "", + sample_id: "", + id: "1", + product_name: "Fertilizer 1", + upload_date: new Date().toDateString(), + updated_at: new Date(new Date().getDate()+5).toDateString() +} +const mockUnfinishedInspection = { + company_info_id: "", + company_name: "test_company", + label_info_id: "", + manufacturer_info_id: "test_manufacturer", + picture_set_id: "", + sample_id: "", + id: "2", + product_name: "Fertilizer 2", + upload_date: new Date().toDateString(), + updated_at: new Date().toDateString() +} + describe("InspectionList", () => { - it("TODO", () => { - expect(false).toBe(true); + + + + beforeEach(() => { + i18n.init(); }); + + it("renders an InspectionList component and check that the inspection elements are present", async () => { + render( + + ); + expect(screen.getByText("Fertilizer 1")).toBeInTheDocument(); + expect(screen.getByText("Fertilizer 2")).toBeInTheDocument(); + }) + + it("renders an InspectionList component with a search and check that only the searched inspection elements are present", async () => { + render( + + ); + expect(screen.getByText("Fertilizer 1")).toBeInTheDocument(); + expect(screen.queryByText("Fertilizer 2")).not.toBeInTheDocument(); + }) }); From e2dcd64de36e9d0fa75f630ed7bd9f41970520f8 Mon Sep 17 00:00:00 2001 From: Youllou Date: Fri, 10 Jan 2025 13:24:47 -0500 Subject: [PATCH 08/15] Added mocked router to Header.test.tsx and UserMenu.test.tsx --- src/components/__tests__/Header.test.tsx | 14 ++++++++++++++ src/components/__tests__/UserMenu.test.tsx | 15 +++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/components/__tests__/Header.test.tsx b/src/components/__tests__/Header.test.tsx index 126c53e1..0b91b57c 100644 --- a/src/components/__tests__/Header.test.tsx +++ b/src/components/__tests__/Header.test.tsx @@ -4,6 +4,20 @@ import "@testing-library/jest-dom"; import { fireEvent, render, screen } from "@testing-library/react"; import Header from "../Header"; +const mockedRouterPush = jest.fn(); +jest.mock("next/navigation", () => ({ + useRouter() { + return { + route: "/", + pathname: "", + query: "", + asPath: "", + push: mockedRouterPush, + }; + }, +})); + + describe("Header Component", () => { const mockSetSideNavOpen = jest.fn(); diff --git a/src/components/__tests__/UserMenu.test.tsx b/src/components/__tests__/UserMenu.test.tsx index 5e76eaec..2ec60c55 100644 --- a/src/components/__tests__/UserMenu.test.tsx +++ b/src/components/__tests__/UserMenu.test.tsx @@ -9,6 +9,21 @@ jest.mock("../../classe/User", () => ({ usePlaceholder: jest.fn(), })); +const mockedRouterPush = jest.fn(); +jest.mock("next/navigation", () => ({ + useRouter() { + return { + route: "/", + pathname: "", + query: "", + asPath: "", + push: mockedRouterPush, + }; + }, +})); + + + const dummyUser = { getUsername: jest.fn().mockReturnValue("placeholderUser"), }; From 8309c82c1ffaa39c66df08fe6df62c617542db2d Mon Sep 17 00:00:00 2001 From: Youllou Date: Fri, 10 Jan 2025 13:26:52 -0500 Subject: [PATCH 09/15] Prettier and lint --- .../dashboard/__tests__/Dashboard.test.tsx | 70 +++++++++---------- src/app/dashboard/page.tsx | 15 ++-- .../InspectionList/InspectionElement.tsx | 44 ++++++++---- .../__tests__/InspectionElement.test.tsx | 37 +++++++--- .../__tests__/InspectionList.test.tsx | 29 ++++---- src/components/__tests__/Header.test.tsx | 1 - src/components/__tests__/UserMenu.test.tsx | 2 - 7 files changed, 115 insertions(+), 83 deletions(-) diff --git a/src/app/dashboard/__tests__/Dashboard.test.tsx b/src/app/dashboard/__tests__/Dashboard.test.tsx index 635848fa..209ce79d 100644 --- a/src/app/dashboard/__tests__/Dashboard.test.tsx +++ b/src/app/dashboard/__tests__/Dashboard.test.tsx @@ -7,9 +7,9 @@ import axios from "axios"; jest.mock("next/navigation", () => ({ useRouter() { return { - prefetch: () => null + prefetch: () => null, }; - } + }, })); const mockInspectList = [ @@ -23,47 +23,43 @@ const mockInspectList = [ id: "1", product_name: "Fertilizer 1", upload_date: new Date().toDateString(), - updated_at: new Date(new Date().getDate()+5).toDateString() - },{ - company_info_id: "", - company_name: "test_company", - label_info_id: "", - manufacturer_info_id: "test_manufacturer", - picture_set_id: "", - sample_id: "", - id: "2", - product_name: "Fertilizer 2", - upload_date: new Date().toDateString(), - updated_at: new Date().toDateString() -} - -] + updated_at: new Date(new Date().getDate() + 5).toDateString(), + }, + { + company_info_id: "", + company_name: "test_company", + label_info_id: "", + manufacturer_info_id: "test_manufacturer", + picture_set_id: "", + sample_id: "", + id: "2", + product_name: "Fertilizer 2", + upload_date: new Date().toDateString(), + updated_at: new Date().toDateString(), + }, +]; -axios.get = jest.fn((path: string | URL | Request)=>{ - if(path){ +axios.get = jest.fn((path: string | URL | Request) => { + if (path) { return Promise.resolve( - new Response(mockInspectList,{ - status:200, - headers: new Headers({"Content-Type":"application/json"}) - }) - ) - }else{ + new Response(mockInspectList, { + status: 200, + headers: new Headers({ "Content-Type": "application/json" }), + }), + ); + } else { return Promise.reject( - new Response("",{ - status:400, - headers: new Headers({"Content-Type":"application/json"}) - }) - ) + new Response("", { + status: 400, + headers: new Headers({ "Content-Type": "application/json" }), + }), + ); } -}) +}); describe("Dashboard", () => { - it("renders the dashboard", async () => { - render( - - ); + render(); expect(true).toBe(true); }); - -}); \ No newline at end of file +}); diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index ba4b9772..1712377a 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -32,7 +32,7 @@ const Dashboard = () => { }, []); return ( - + { @@ -99,8 +101,8 @@ const Dashboard = () => { input: { className: "p-2", startAdornment: ( - - + + ), }, @@ -108,7 +110,10 @@ const Dashboard = () => { />
- + diff --git a/src/components/InspectionList/InspectionElement.tsx b/src/components/InspectionList/InspectionElement.tsx index e07c8510..e018990f 100644 --- a/src/components/InspectionList/InspectionElement.tsx +++ b/src/components/InspectionList/InspectionElement.tsx @@ -9,20 +9,34 @@ interface InspectionElementProps { handleClick(): void; } -const InspectionElement = ({inspection, handleClick}: InspectionElementProps) => { - return - - - {inspection.product_name} - {inspection.updated_at===inspection.upload_date && } - - -} +const InspectionElement = ({ + inspection, + handleClick, +}: InspectionElementProps) => { + return ( + + + + + {inspection.product_name} + + {inspection.updated_at === inspection.upload_date && ( + + )} + + + ); +}; export default InspectionElement; diff --git a/src/components/InspectionList/__tests__/InspectionElement.test.tsx b/src/components/InspectionList/__tests__/InspectionElement.test.tsx index 376330c2..c19b6fbb 100644 --- a/src/components/InspectionList/__tests__/InspectionElement.test.tsx +++ b/src/components/InspectionList/__tests__/InspectionElement.test.tsx @@ -3,8 +3,7 @@ import { render, screen } from "@testing-library/react"; import InspectionElement from "@/components/InspectionList/InspectionElement"; describe("InspectionElement", () => { - - const mockFinishedInspection : InspectionPreview = { + const mockFinishedInspection: InspectionPreview = { company_info_id: "", company_name: "test_company", label_info_id: "", @@ -14,9 +13,9 @@ describe("InspectionElement", () => { id: "1", product_name: "Fertilizer 1", upload_date: new Date().toDateString(), - updated_at: new Date(new Date().getDate()+5).toDateString() - } - const mockUnfinishedInspection : InspectionPreview = { + updated_at: new Date(new Date().getDate() + 5).toDateString(), + }; + const mockUnfinishedInspection: InspectionPreview = { company_info_id: "", company_name: "test_company", label_info_id: "", @@ -26,27 +25,45 @@ describe("InspectionElement", () => { id: "2", product_name: "Fertilizer 2", upload_date: new Date().toDateString(), - updated_at: new Date().toDateString() - } + updated_at: new Date().toDateString(), + }; const handleClick = jest.fn(); it("renders an finished InspectionElement and check that all elements are present and that the error icon is not present", () => { - render( {}} />); + render( + {}} + />, + ); expect(screen.getByText("Fertilizer 1")).toBeInTheDocument(); expect(screen.getByTestId("image")).toBeInTheDocument(); expect(screen.queryByTestId("error-icon")).not.toBeInTheDocument(); }); it("renders an unfinished InspectionElement and check that all elements are present and that the error icon is present", () => { - render( {}} />); + render( + {}} + />, + ); expect(screen.getByText("Fertilizer 2")).toBeInTheDocument(); expect(screen.getByTestId("image")).toBeInTheDocument(); expect(screen.getByTestId("error-icon")).toBeInTheDocument(); }); it("clicks on the InspectionElement and check that the handleClick function has been called", () => { - render(); + render( + , + ); screen.getByText("Fertilizer 1").click(); expect(handleClick).toHaveBeenCalled(); }); diff --git a/src/components/InspectionList/__tests__/InspectionList.test.tsx b/src/components/InspectionList/__tests__/InspectionList.test.tsx index a38860f8..07bf110e 100644 --- a/src/components/InspectionList/__tests__/InspectionList.test.tsx +++ b/src/components/InspectionList/__tests__/InspectionList.test.tsx @@ -7,9 +7,9 @@ import i18n from "@/app/i18n"; jest.mock("next/navigation", () => ({ useRouter() { return { - prefetch: () => null + prefetch: () => null, }; - } + }, })); const mockFinishedInspection = { @@ -22,8 +22,8 @@ const mockFinishedInspection = { id: "1", product_name: "Fertilizer 1", upload_date: new Date().toDateString(), - updated_at: new Date(new Date().getDate()+5).toDateString() -} + updated_at: new Date(new Date().getDate() + 5).toDateString(), +}; const mockUnfinishedInspection = { company_info_id: "", company_name: "test_company", @@ -34,30 +34,33 @@ const mockUnfinishedInspection = { id: "2", product_name: "Fertilizer 2", upload_date: new Date().toDateString(), - updated_at: new Date().toDateString() -} + updated_at: new Date().toDateString(), +}; describe("InspectionList", () => { - - - beforeEach(() => { i18n.init(); }); it("renders an InspectionList component and check that the inspection elements are present", async () => { render( - + , ); expect(screen.getByText("Fertilizer 1")).toBeInTheDocument(); expect(screen.getByText("Fertilizer 2")).toBeInTheDocument(); - }) + }); it("renders an InspectionList component with a search and check that only the searched inspection elements are present", async () => { render( - + , ); expect(screen.getByText("Fertilizer 1")).toBeInTheDocument(); expect(screen.queryByText("Fertilizer 2")).not.toBeInTheDocument(); - }) + }); }); diff --git a/src/components/__tests__/Header.test.tsx b/src/components/__tests__/Header.test.tsx index 0b91b57c..59534d40 100644 --- a/src/components/__tests__/Header.test.tsx +++ b/src/components/__tests__/Header.test.tsx @@ -17,7 +17,6 @@ jest.mock("next/navigation", () => ({ }, })); - describe("Header Component", () => { const mockSetSideNavOpen = jest.fn(); diff --git a/src/components/__tests__/UserMenu.test.tsx b/src/components/__tests__/UserMenu.test.tsx index 2ec60c55..8b8f9e0b 100644 --- a/src/components/__tests__/UserMenu.test.tsx +++ b/src/components/__tests__/UserMenu.test.tsx @@ -22,8 +22,6 @@ jest.mock("next/navigation", () => ({ }, })); - - const dummyUser = { getUsername: jest.fn().mockReturnValue("placeholderUser"), }; From d338e9b6933692926ca9e7678d8471c29b9b7071 Mon Sep 17 00:00:00 2001 From: Youllou Date: Fri, 10 Jan 2025 13:30:26 -0500 Subject: [PATCH 10/15] Added some basic tests to Dashboard.test.tsx --- src/app/dashboard/__tests__/Dashboard.test.tsx | 4 ++-- src/app/dashboard/page.tsx | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/dashboard/__tests__/Dashboard.test.tsx b/src/app/dashboard/__tests__/Dashboard.test.tsx index 209ce79d..e2a6dddc 100644 --- a/src/app/dashboard/__tests__/Dashboard.test.tsx +++ b/src/app/dashboard/__tests__/Dashboard.test.tsx @@ -1,4 +1,4 @@ -import { render } from "@testing-library/react"; +import { screen, render } from "@testing-library/react"; import Dashboard from "@/app/dashboard/page"; import { Response } from "whatwg-fetch"; import axios from "axios"; @@ -60,6 +60,6 @@ axios.get = jest.fn((path: string | URL | Request) => { describe("Dashboard", () => { it("renders the dashboard", async () => { render(); - expect(true).toBe(true); + expect(screen.getByTestId("user-info")).toBeInTheDocument(); }); }); diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 1712377a..5e47d602 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -35,6 +35,7 @@ const Dashboard = () => { From a6dd99ab04ab923bea235e5b7df481a599eb6d94 Mon Sep 17 00:00:00 2001 From: Youllou Date: Fri, 10 Jan 2025 14:59:13 -0500 Subject: [PATCH 11/15] Added translations --- public/locales/en/dashboard.json | 12 ++++++++++++ public/locales/fr/dashboard.json | 12 ++++++++++++ src/app/dashboard/page.tsx | 14 ++++++++------ 3 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 public/locales/en/dashboard.json create mode 100644 public/locales/fr/dashboard.json diff --git a/public/locales/en/dashboard.json b/public/locales/en/dashboard.json new file mode 100644 index 00000000..10ed43ae --- /dev/null +++ b/public/locales/en/dashboard.json @@ -0,0 +1,12 @@ +{ + "user-info": { + "username": "Username", + "mail": "Email", + "role": "Role", + "inspectionNumber": "Number of inspections" + }, + "list": { + "my-inspections": "My inspections", + "search": "Search" + } +} \ No newline at end of file diff --git a/public/locales/fr/dashboard.json b/public/locales/fr/dashboard.json new file mode 100644 index 00000000..0c3b4d07 --- /dev/null +++ b/public/locales/fr/dashboard.json @@ -0,0 +1,12 @@ +{ + "user-info": { + "username": "Nom d'utilisateur", + "mail": "Email", + "role": "Rôle", + "inspectionNumber": "Nombre d'inspections" + }, + "list": { + "my-inspections": "Mes inspections", + "search": "Rechercher" + } +} \ No newline at end of file diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 5e47d602..5054df2e 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -11,8 +11,10 @@ import { useEffect, useState } from "react"; import Cookies from "js-cookie"; import axios from "axios"; import theme from "@/app/theme"; +import { useTranslation } from "react-i18next"; const Dashboard = () => { + const { t } = useTranslation("dashboard"); const [search, setSearch] = useState(""); const [inspectList, setInspectList] = useState([]); @@ -41,15 +43,15 @@ const Dashboard = () => { > - Username + {t("user-info.username")} - Mail: + {t("user-info.mail")}: User email - Role: + {t("user-info.role")}: User role @@ -67,7 +69,7 @@ const Dashboard = () => { > - Number of inspections + {t("user-info.inspectionNumber")} @@ -81,12 +83,12 @@ const Dashboard = () => { - My inspections + {t("list.my-inspections")} Date: Fri, 10 Jan 2025 15:04:38 -0500 Subject: [PATCH 12/15] Added tooltips for error icon on unverified inspection --- public/locales/en/dashboard.json | 3 +++ public/locales/fr/dashboard.json | 3 +++ src/components/InspectionList/InspectionElement.tsx | 10 ++++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/public/locales/en/dashboard.json b/public/locales/en/dashboard.json index 10ed43ae..c1fb7d21 100644 --- a/public/locales/en/dashboard.json +++ b/public/locales/en/dashboard.json @@ -8,5 +8,8 @@ "list": { "my-inspections": "My inspections", "search": "Search" + }, + "inspection": { + "unverified": "Inspection unverified" } } \ No newline at end of file diff --git a/public/locales/fr/dashboard.json b/public/locales/fr/dashboard.json index 0c3b4d07..f75348b8 100644 --- a/public/locales/fr/dashboard.json +++ b/public/locales/fr/dashboard.json @@ -8,5 +8,8 @@ "list": { "my-inspections": "Mes inspections", "search": "Rechercher" + }, + "inspection": { + "unverified": "Inspection non vérifié" } } \ No newline at end of file diff --git a/src/components/InspectionList/InspectionElement.tsx b/src/components/InspectionList/InspectionElement.tsx index e018990f..9af54e37 100644 --- a/src/components/InspectionList/InspectionElement.tsx +++ b/src/components/InspectionList/InspectionElement.tsx @@ -1,7 +1,8 @@ -import { Box, Card, Stack, Typography } from "@mui/material"; +import { Box, Card, Stack, Tooltip, Typography } from "@mui/material"; import ErrorIcon from "@mui/icons-material/Error"; import React from "react"; import InspectionPreview from "@/types/InspectionPreview"; +import { useTranslation } from "react-i18next"; interface InspectionElementProps { inspection: InspectionPreview; @@ -13,6 +14,9 @@ const InspectionElement = ({ inspection, handleClick, }: InspectionElementProps) => { + + const { t } = useTranslation("dashboard"); + return ( {inspection.updated_at === inspection.upload_date && ( - + + + )}
From 2b2c59c461bf295e107a0af67fdebac4c8b58af6 Mon Sep 17 00:00:00 2001 From: Youllou Date: Fri, 10 Jan 2025 15:05:26 -0500 Subject: [PATCH 13/15] Added inspections number --- src/app/dashboard/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 5054df2e..72157e2b 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -69,7 +69,7 @@ const Dashboard = () => { > - {t("user-info.inspectionNumber")} + {t("user-info.inspectionNumber")}: {inspectList.length}
From 41757f5afcfbd12e0581eaa4e489cb20c76f7525 Mon Sep 17 00:00:00 2001 From: Youllou Date: Fri, 10 Jan 2025 15:08:31 -0500 Subject: [PATCH 14/15] eof in locales --- public/locales/en/dashboard.json | 2 +- public/locales/fr/dashboard.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/locales/en/dashboard.json b/public/locales/en/dashboard.json index c1fb7d21..a9462277 100644 --- a/public/locales/en/dashboard.json +++ b/public/locales/en/dashboard.json @@ -12,4 +12,4 @@ "inspection": { "unverified": "Inspection unverified" } -} \ No newline at end of file +} diff --git a/public/locales/fr/dashboard.json b/public/locales/fr/dashboard.json index f75348b8..ece63b99 100644 --- a/public/locales/fr/dashboard.json +++ b/public/locales/fr/dashboard.json @@ -12,4 +12,4 @@ "inspection": { "unverified": "Inspection non vérifié" } -} \ No newline at end of file +} From d494a5f70f960e900e28d0949ad56ed9f4b71e22 Mon Sep 17 00:00:00 2001 From: Youllou Date: Fri, 10 Jan 2025 15:10:56 -0500 Subject: [PATCH 15/15] Added wait in InspectionList.test.tsx to wait for updates --- src/components/InspectionList/__tests__/InspectionList.test.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/InspectionList/__tests__/InspectionList.test.tsx b/src/components/InspectionList/__tests__/InspectionList.test.tsx index 07bf110e..5506c75c 100644 --- a/src/components/InspectionList/__tests__/InspectionList.test.tsx +++ b/src/components/InspectionList/__tests__/InspectionList.test.tsx @@ -49,6 +49,7 @@ describe("InspectionList", () => { inspectionList={[mockFinishedInspection, mockUnfinishedInspection]} />, ); + await new Promise((r) => setTimeout(r, 1000)); expect(screen.getByText("Fertilizer 1")).toBeInTheDocument(); expect(screen.getByText("Fertilizer 2")).toBeInTheDocument(); }); @@ -60,6 +61,7 @@ describe("InspectionList", () => { inspectionList={[mockFinishedInspection, mockUnfinishedInspection]} />, ); + await new Promise((r) => setTimeout(r, 1000)); expect(screen.getByText("Fertilizer 1")).toBeInTheDocument(); expect(screen.queryByText("Fertilizer 2")).not.toBeInTheDocument(); });